{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "drawer",
  "type": "registry:ui",
  "dependencies": [
    "@base-ui/react",
    "clsx",
    "tailwind-merge"
  ],
  "registryDependencies": [
    "https://usva.build/r/card.json",
    "https://usva.build/r/overlay-core.json"
  ],
  "files": [
    {
      "path": "drawer.tsx",
      "target": "components/ui/drawer.tsx",
      "type": "registry:ui",
      "content": "\"use client\";\nimport { Dialog as Base } from \"@base-ui/react/dialog\";\nimport * as React from \"react\";\nimport { cn } from \"@/lib/utils\";\nimport {\n  type CardHighlight,\n  type CardSurface,\n  SURFACE_ELEVATED,\n  SURFACE_SKIN,\n} from \"./card\";\nimport { useScopedTheme } from \"./use-scoped-theme\";\n\nexport type DrawerSide = \"top\" | \"right\" | \"bottom\" | \"left\";\nexport type DrawerSize = \"sm\" | \"md\" | \"lg\";\n\nexport type DrawerProps = Base.Root.Props;\n\nfunction DrawerRoot(props: DrawerProps) {\n  return <Base.Root {...props} />;\n}\nDrawerRoot.displayName = \"Drawer\";\n\nexport const DrawerTrigger = Base.Trigger;\n\n/** Edge anchoring, plus the border and radius on the inner edge only. */\nconst sideAnchor: Record<DrawerSide, string> = {\n  right: \"inset-y-0 right-0 h-full border-l rounded-l-2xl\",\n  left: \"inset-y-0 left-0 h-full border-r rounded-r-2xl\",\n  top: \"inset-x-0 top-0 w-full border-b rounded-b-2xl\",\n  bottom: \"inset-x-0 bottom-0 w-full border-t rounded-t-2xl\",\n};\n\n/** Inline size on the vertical edges, block size on the horizontal ones. */\nconst sideSize: Record<DrawerSide, Record<DrawerSize, string>> = {\n  right: {\n    sm: \"w-full max-w-xs\",\n    md: \"w-full max-w-md\",\n    lg: \"w-full max-w-2xl\",\n  },\n  left: {\n    sm: \"w-full max-w-xs\",\n    md: \"w-full max-w-md\",\n    lg: \"w-full max-w-2xl\",\n  },\n  top: { sm: \"max-h-[30vh]\", md: \"max-h-[50vh]\", lg: \"max-h-[80vh]\" },\n  bottom: { sm: \"max-h-[30vh]\", md: \"max-h-[50vh]\", lg: \"max-h-[80vh]\" },\n};\n\nconst sideEnter: Record<DrawerSide, string> = {\n  right:\n    \"data-[starting-style]:translate-x-full data-[ending-style]:translate-x-full\",\n  left: \"data-[starting-style]:-translate-x-full data-[ending-style]:-translate-x-full\",\n  top: \"data-[starting-style]:-translate-y-full data-[ending-style]:-translate-y-full\",\n  bottom:\n    \"data-[starting-style]:translate-y-full data-[ending-style]:translate-y-full\",\n};\n\nexport type DrawerContentProps = React.ComponentPropsWithoutRef<\n  typeof Base.Popup\n> & {\n  side?: DrawerSide;\n  size?: DrawerSize;\n  backdropClassName?: string;\n  /** How the panel sits above the scrim. Defaults to elevated. */\n  surface?: CardSurface;\n  /** Accent treatment, shared with Card: a wash, an inner edge, or a glow ring. */\n  highlight?: CardHighlight;\n};\n\n/**\n * Base UI owns focus trap, scroll lock, Esc, and portalling. This adds only the\n * edge anchoring and the slide, both CSS. kajo's slide-up sheet is side=\"bottom\".\n */\nexport const DrawerContent = React.forwardRef<\n  HTMLDivElement,\n  DrawerContentProps\n>(\n  (\n    {\n      className,\n      backdropClassName,\n      side = \"right\",\n      size = \"md\",\n      surface = \"elevated\",\n      highlight = \"none\",\n      children,\n      ...props\n    },\n    ref,\n  ) => {\n    const [probe, scopedTheme] = useScopedTheme();\n\n    return (\n      <>\n        <span ref={probe} hidden />\n        <Base.Portal>\n          <Base.Backdrop\n            data-theme={scopedTheme}\n            className={cn(\n              \"fixed inset-0 z-overlay transition-opacity duration-base motion-reduce:transition-none\",\n              \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0\",\n              surface === \"glass\"\n                ? \"bg-scrim/40 backdrop-blur-[3px]\"\n                : \"bg-scrim backdrop-blur-sm\",\n              backdropClassName,\n            )}\n          />\n          <Base.Popup\n            ref={ref}\n            data-theme={scopedTheme}\n            data-side={side}\n            data-surface={surface}\n            data-highlight={highlight !== \"none\" ? highlight : undefined}\n            className={cn(\n              \"fixed z-overlay flex flex-col overflow-y-auto\",\n              \"isolate border-border p-6 text-ink\",\n              sideAnchor[side],\n              sideSize[side][size],\n              SURFACE_SKIN[surface],\n              highlight === \"ring\"\n                ? \"glow-ring\"\n                : SURFACE_ELEVATED[surface] && \"shadow-overlay\",\n              highlight === \"wash\" && \"wash-accent\",\n              highlight === \"edge\" &&\n                \"after:absolute after:inset-x-6 after:top-0 after:h-px after:hairline-accent\",\n              \"transition-enter duration-[350ms] ease-spring\",\n              \"motion-reduce:transition-none motion-reduce:transform-none\",\n              \"data-[starting-style]:opacity-0 data-[ending-style]:opacity-0\",\n              \"data-[ending-style]:duration-base data-[ending-style]:ease-soft\",\n              sideEnter[side],\n              className,\n            )}\n            {...props}\n          >\n            {children}\n          </Base.Popup>\n        </Base.Portal>\n      </>\n    );\n  },\n);\nDrawerContent.displayName = \"DrawerContent\";\n\nexport const DrawerTitle = React.forwardRef<\n  HTMLHeadingElement,\n  React.ComponentPropsWithoutRef<typeof Base.Title>\n>(({ className, ...props }, ref) => (\n  <Base.Title\n    ref={ref}\n    className={cn(\n      \"text-balance text-lg font-semibold tracking-[-0.01em] text-ink\",\n      className,\n    )}\n    {...props}\n  />\n));\nDrawerTitle.displayName = \"DrawerTitle\";\n\nexport const DrawerDescription = React.forwardRef<\n  HTMLParagraphElement,\n  React.ComponentPropsWithoutRef<typeof Base.Description>\n>(({ className, ...props }, ref) => (\n  <Base.Description\n    ref={ref}\n    className={cn(\"mt-1 text-pretty text-sm text-muted\", className)}\n    {...props}\n  />\n));\nDrawerDescription.displayName = \"DrawerDescription\";\n\nexport const DrawerClose = React.forwardRef<\n  HTMLButtonElement,\n  React.ComponentPropsWithoutRef<typeof Base.Close>\n>(({ className, ...props }, ref) => (\n  <Base.Close\n    ref={ref}\n    className={cn(\n      \"inline-flex min-h-11 min-w-11 items-center justify-center rounded-md text-muted outline-none\",\n      \"transition-control duration-fast ease-soft\",\n      \"hover:bg-surface-2 hover:text-ink active:scale-[0.96] focus-visible:ring-focus\",\n      \"motion-reduce:transition-none motion-reduce:transform-none\",\n      className,\n    )}\n    {...props}\n  />\n));\nDrawerClose.displayName = \"DrawerClose\";\n\nexport const Drawer = Object.assign(DrawerRoot, {\n  Trigger: DrawerTrigger,\n  Content: DrawerContent,\n  Title: DrawerTitle,\n  Description: DrawerDescription,\n  Close: DrawerClose,\n});\n"
    }
  ]
}