{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "sheet",
  "title": "Sheet",
  "description": "A dialog that slides in from an edge, for side panels on narrow screens.",
  "dependencies": [
    "@base-ui/react",
    "@stylexjs/stylex"
  ],
  "registryDependencies": [
    "https://constella.aayush.cv/r/base.json",
    "https://constella.aayush.cv/r/dialog.json"
  ],
  "files": [
    {
      "path": "src/components/primitives/sheet.tsx",
      "content": "\"use client\";\n\nimport { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\";\nimport * as stylex from \"@stylexjs/stylex\";\nimport type { ComponentProps } from \"react\";\n\nimport {\n  DialogBackdrop,\n  DialogCloseButton,\n  DialogDescription,\n  DialogPortal,\n  DialogTitle,\n} from \"@/components/primitives/dialog\";\nimport type { Sx } from \"@/lib/constella/styles\";\nimport { typeStyles } from \"@/lib/constella/styles\";\nimport {\n  colors,\n  durations,\n  easings,\n  layers,\n  media,\n  shadows,\n  sizes,\n  space,\n  strokes,\n} from \"@/lib/constella/tokens.stylex\";\n\nconst sheetSides = [\"top\", \"right\", \"bottom\", \"left\"] as const;\n\ntype SheetSide = (typeof sheetSides)[number];\n\ntype Styled<T> = Omit<T, \"className\" | \"style\"> & {\n  sx?: Sx;\n};\n\ntype SheetContentProps = Styled<SheetPrimitive.Popup.Props> & {\n  showCloseButton?: boolean;\n  side?: SheetSide;\n};\n\nconst offstage = \":is([data-starting-style], [data-ending-style])\";\nconst withClose = \":is(:has(> [data-slot='dialog-close-button']) > *)\";\n\nconst styles = stylex.create({\n  // Slides the whole way in from its edge and back out the same way.\n  popup: {\n    backgroundColor: colors.raised,\n    boxShadow: shadows.xl,\n    color: colors.textPrimary,\n    display: \"flex\",\n    flexDirection: \"column\",\n    opacity: {\n      default: 1,\n      [media.reducedMotion]: { default: 1, [offstage]: 0 },\n    },\n    overflowY: {\n      default: \"auto\",\n      \":has(> [data-slot='sheet-body'])\": \"hidden\",\n    },\n    position: \"fixed\",\n    transitionDuration: {\n      default: durations.layout,\n      \":is([data-ending-style])\": durations.dialog,\n    },\n    transitionProperty: {\n      default: \"transform\",\n      [media.reducedMotion]: \"opacity\",\n    },\n    transitionTimingFunction: easings.layout,\n    zIndex: layers.dialog,\n  },\n  // Sides are physical, like the slide that brings them in.\n  right: {\n    height: \"100%\",\n    insetBlockEnd: 0,\n    insetBlockStart: 0,\n    right: 0,\n    transform: {\n      default: \"none\",\n      [offstage]: {\n        default: \"translateX(100%)\",\n        [media.reducedMotion]: \"none\",\n      },\n    },\n    width: `min(75%, ${sizes.dialog})`,\n  },\n  left: {\n    height: \"100%\",\n    insetBlockEnd: 0,\n    insetBlockStart: 0,\n    left: 0,\n    transform: {\n      default: \"none\",\n      [offstage]: {\n        default: \"translateX(-100%)\",\n        [media.reducedMotion]: \"none\",\n      },\n    },\n    width: `min(75%, ${sizes.dialog})`,\n  },\n  top: {\n    insetBlockStart: 0,\n    insetInlineEnd: 0,\n    insetInlineStart: 0,\n    transform: {\n      default: \"none\",\n      [offstage]: {\n        default: \"translateY(-100%)\",\n        [media.reducedMotion]: \"none\",\n      },\n    },\n  },\n  bottom: {\n    insetBlockEnd: 0,\n    insetInlineEnd: 0,\n    insetInlineStart: 0,\n    transform: {\n      default: \"none\",\n      [offstage]: {\n        default: \"translateY(100%)\",\n        [media.reducedMotion]: \"none\",\n      },\n    },\n  },\n  header: {\n    display: \"flex\",\n    flexDirection: \"column\",\n    flexShrink: 0,\n    gap: space.xxs,\n    paddingBlockEnd: space.md,\n    paddingBlockStart: space.md,\n    paddingInlineEnd: {\n      default: space.md,\n      [withClose]: `calc(${sizes.controlSm} + ${space.xs})`,\n    },\n    paddingInlineStart: space.md,\n  },\n  body: {\n    flexGrow: 1,\n    minHeight: 0,\n    overflowY: \"auto\",\n    paddingInlineEnd: space.md,\n    paddingInlineStart: space.md,\n  },\n  // The dialog's footer bar, pinned to the bottom.\n  footer: {\n    backgroundColor: colors.fillSubtle,\n    borderBlockStartColor: colors.borderSubtle,\n    borderBlockStartStyle: \"solid\",\n    borderBlockStartWidth: strokes.border,\n    display: \"flex\",\n    flexDirection: \"column\",\n    flexShrink: 0,\n    gap: space.xs,\n    marginBlockStart: \"auto\",\n    paddingBlockEnd: space.md,\n    paddingBlockStart: space.md,\n    paddingInlineEnd: space.md,\n    paddingInlineStart: space.md,\n  },\n});\n\nfunction Sheet(props: SheetPrimitive.Root.Props) {\n  return <SheetPrimitive.Root {...props} />;\n}\n\nfunction SheetTrigger({ sx, ...props }: Styled<SheetPrimitive.Trigger.Props>) {\n  return (\n    <SheetPrimitive.Trigger\n      data-slot=\"sheet-trigger\"\n      {...props}\n      {...stylex.props(sx)}\n    />\n  );\n}\n\nfunction SheetClose({ sx, ...props }: Styled<SheetPrimitive.Close.Props>) {\n  return (\n    <SheetPrimitive.Close\n      data-slot=\"sheet-close\"\n      {...props}\n      {...stylex.props(sx)}\n    />\n  );\n}\n\n/** Renders the portal, backdrop and popup at the `side` edge, with a close button unless `showCloseButton={false}`. */\nfunction SheetContent({\n  children,\n  showCloseButton = true,\n  side = \"right\",\n  sx,\n  ...props\n}: SheetContentProps) {\n  return (\n    <DialogPortal>\n      <DialogBackdrop />\n      <SheetPrimitive.Popup\n        data-side={side}\n        data-slot=\"sheet-content\"\n        {...props}\n        {...stylex.props([typeStyles.textSm, styles.popup], styles[side], sx)}\n      >\n        {children}\n        {showCloseButton && <DialogCloseButton />}\n      </SheetPrimitive.Popup>\n    </DialogPortal>\n  );\n}\n\nfunction SheetHeader({ sx, ...props }: Styled<ComponentProps<\"div\">>) {\n  return (\n    <div\n      data-slot=\"sheet-header\"\n      {...props}\n      {...stylex.props(styles.header, sx)}\n    />\n  );\n}\n\nfunction SheetBody({ sx, ...props }: Styled<ComponentProps<\"div\">>) {\n  return (\n    <div data-slot=\"sheet-body\" {...props} {...stylex.props(styles.body, sx)} />\n  );\n}\n\nfunction SheetFooter({ sx, ...props }: Styled<ComponentProps<\"div\">>) {\n  return (\n    <div\n      data-slot=\"sheet-footer\"\n      {...props}\n      {...stylex.props(styles.footer, sx)}\n    />\n  );\n}\n\nfunction SheetTitle(props: ComponentProps<typeof DialogTitle>) {\n  return <DialogTitle data-slot=\"sheet-title\" {...props} />;\n}\n\nfunction SheetDescription(props: ComponentProps<typeof DialogDescription>) {\n  return <DialogDescription data-slot=\"sheet-description\" {...props} />;\n}\n\nexport {\n  Sheet,\n  SheetBody,\n  SheetClose,\n  SheetContent,\n  SheetDescription,\n  SheetFooter,\n  SheetHeader,\n  sheetSides,\n  SheetTitle,\n  SheetTrigger,\n};\nexport type { SheetContentProps, SheetSide };\n",
      "type": "registry:component"
    }
  ],
  "docs": "Usage: https://constella.aayush.cv/docs/components/sheet/index.md",
  "type": "registry:ui"
}