{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "drawer-base",
  "type": "registry:ui",
  "title": "Drawer (Base UI)",
  "description": "A panel that slides in from the edge of the screen.",
  "dependencies": [
    "@base-ui/react"
  ],
  "files": [
    {
      "path": "src/registry/components/ui/drawer-base.tsx",
      "content": "\"use client\";\n\nimport { cn } from \"@/lib/utils\";\nimport { Drawer as DrawerPrimitive } from \"@base-ui/react/drawer\";\nimport { ComponentProps, createContext, use } from \"react\";\n\nfunction resolveClassName<S>(\n  className: string | ((state: S) => string | undefined) | undefined,\n  state: S,\n): string | undefined {\n  return typeof className === \"function\" ? className(state) : className;\n}\n\nconst DrawerContext =\n  createContext<DrawerPrimitive.Root.Props[\"swipeDirection\"]>(\"down\");\n\nfunction DrawerProvider({ ...props }: DrawerPrimitive.Provider.Props) {\n  return <DrawerPrimitive.Provider {...props} />;\n}\n\nfunction Drawer({\n  swipeDirection = \"down\",\n  ...props\n}: DrawerPrimitive.Root.Props) {\n  return (\n    <DrawerContext value={swipeDirection}>\n      <DrawerPrimitive.Root\n        data-slot=\"drawer\"\n        swipeDirection={swipeDirection}\n        {...props}\n      />\n    </DrawerContext>\n  );\n}\n\nfunction DrawerTrigger({ ...props }: DrawerPrimitive.Trigger.Props) {\n  return <DrawerPrimitive.Trigger {...props} data-slot=\"drawer-trigger\" />;\n}\n\nfunction DrawerPortal({ className, ...props }: DrawerPrimitive.Portal.Props) {\n  return (\n    <DrawerPrimitive.Portal\n      data-slot=\"drawer-portal\"\n      className={(state) => cn(\"z-50\", resolveClassName(className, state))}\n      {...props}\n    />\n  );\n}\n\nfunction DrawerClose({ ...props }: DrawerPrimitive.Close.Props) {\n  return <DrawerPrimitive.Close data-slot=\"drawer-close\" {...props} />;\n}\n\nfunction DrawerContent({ className, ...props }: DrawerPrimitive.Content.Props) {\n  return (\n    <DrawerPrimitive.Content\n      data-slot=\"drawer-content\"\n      className={(state) =>\n        cn(\n          \"transition-opacity duration-300 ease-[cubic-bezier(0.45,1.005,0,1.005)] group-data-nested-drawer-open/popup:opacity-0 group-data-nested-drawer-swiping/popup:opacity-100\",\n          resolveClassName(className, state),\n        )\n      }\n      {...props}\n    />\n  );\n}\n\nexport const drawerPopupClassName = ({\n  swipeDirection,\n}: DrawerPrimitive.Popup.State) => {\n  return cn(\n    \"group/popup relative\",\n    \"[--bleed:3rem] outline-1 outline-foreground/5 bg-background text-foreground dark:outline-border overflow-y-auto overscroll-contain touch-auto data-swiping:select-none\",\n    \"data-ending-style:duration-[calc(var(--drawer-swipe-strength)*400ms)]\",\n    // Nested drawer stacking variables (no-ops when not nested)\n    \"[--peek:1rem] [--stack-progress:clamp(0,var(--drawer-swipe-progress),1)] [--stack-step:0.05] [--stack-peek-offset:max(0px,calc((var(--nested-drawers)-var(--stack-progress))*var(--peek)))] [--scale-base:calc(max(0,1-(var(--nested-drawers)*var(--stack-step))))] [--scale:clamp(0,calc(var(--scale-base)+(var(--stack-step)*var(--stack-progress))),1)] [--shrink:calc(1-var(--scale))] [--height:max(0px,calc(var(--drawer-frontmost-height,var(--drawer-height))-var(--bleed)))]\",\n    // Nested drawer overlay (::after pseudo-element)\n    \"after:absolute after:inset-0 after:rounded-[inherit] after:bg-transparent after:pointer-events-none after:content-[''] after:transition-[background-color] after:duration-450 after:ease-[cubic-bezier(0.32,0.72,0,1)]\",\n    // Nested drawer states\n    \"data-nested-drawer-swiping:duration-0 data-nested-drawer-open:overflow-hidden data-nested-drawer-open:after:bg-black/5\",\n    {\n      // Shared horizontal (left & right)\n      \"supports-[-webkit-touch-callout:none]:[--bleed:0px] h-full w-[calc(22rem+var(--bleed))] max-w-[calc(100vw-3rem+var(--bleed))] p-6 supports-[-webkit-touch-callout:none]:w-[20rem] supports-[-webkit-touch-callout:none]:max-w-[calc(100vw-20px)] supports-[-webkit-touch-callout:none]:rounded-[10px]\":\n        swipeDirection === \"left\" || swipeDirection === \"right\",\n      // Right-only (with stacking transform + transition for box-shadow)\n      \"rounded-l-2xl -mr-(--bleed) pr-[calc(1.5rem+var(--bleed))] supports-[-webkit-touch-callout:none]:mr-0 supports-[-webkit-touch-callout:none]:pr-6 shadow-[-2px_0_10px_rgb(0_0_0/0.1)] data-ending-style:shadow-[-2px_0_10px_rgb(0_0_0/0)] origin-[calc(100%-var(--bleed))_50%] transform-[translateX(calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-x)-var(--stack-peek-offset)-(var(--shrink)*100%)))_scale(var(--scale))] data-swiping:duration-0 [transition:transform_450ms_cubic-bezier(0.32,0.72,0,1),box-shadow_450ms_cubic-bezier(0.32,0.72,0,1)]\":\n        swipeDirection === \"right\",\n      // Left-only (with stacking transform + transition for box-shadow)\n      \"rounded-r-2xl -ml-(--bleed) pl-[calc(1.5rem+var(--bleed))] supports-[-webkit-touch-callout:none]:ml-0 supports-[-webkit-touch-callout:none]:pl-6 shadow-[2px_0_10px_rgb(0_0_0/0.1)] data-ending-style:shadow-[2px_0_10px_rgb(0_0_0/0)] origin-[var(--bleed)_50%] transform-[translateX(calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-x)+var(--stack-peek-offset)+(var(--shrink)*100%)))_scale(var(--scale))] data-swiping:duration-0 [transition:transform_450ms_cubic-bezier(0.32,0.72,0,1),box-shadow_450ms_cubic-bezier(0.32,0.72,0,1)]\":\n        swipeDirection === \"left\",\n      // Right enter/exit\n      \"data-ending-style:transform-[translateX(calc(100%-var(--bleed)+var(--viewport-padding)))] data-starting-style:transform-[translateX(calc(100%-var(--bleed)+var(--viewport-padding)))]\":\n        swipeDirection === \"right\",\n      // Left enter/exit\n      \"data-ending-style:transform-[translateX(calc(-100%+var(--bleed)-var(--viewport-padding)))] data-starting-style:transform-[translateX(calc(-100%+var(--bleed)-var(--viewport-padding)))]\":\n        swipeDirection === \"left\",\n      // Shared vertical (up & down)\n      \"w-full max-h-[calc(80vh+var(--bleed))] px-6\":\n        swipeDirection === \"up\" || swipeDirection === \"down\",\n      // Down-only (with stacking transform + transitions for height & box-shadow)\n      \"rounded-t-2xl -mb-(--bleed) pt-4 pb-[calc(1.5rem+env(safe-area-inset-bottom,0px)+var(--bleed))] h-(--drawer-height,auto) shadow-[0_2px_10px_rgb(0_0_0/0.1)] data-ending-style:shadow-[0_2px_10px_rgb(0_0_0/0)] origin-[50%_calc(100%-var(--bleed))] transform-[translateY(calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y)-var(--stack-peek-offset)-(var(--shrink)*var(--height))))_scale(var(--scale))] data-swiping:duration-0 data-nested-drawer-open:h-[calc(var(--height)+var(--bleed))] [transition:transform_450ms_cubic-bezier(0.32,0.72,0,1),height_450ms_cubic-bezier(0.32,0.72,0,1),box-shadow_450ms_cubic-bezier(0.32,0.72,0,1)]\":\n        swipeDirection === \"down\",\n      // Up-only (with stacking transform + transitions for height & box-shadow)\n      \"rounded-b-2xl -mt-(--bleed) pb-6 pt-[calc(1.5rem+env(safe-area-inset-top,0px)+var(--bleed))] h-(--drawer-height,auto) shadow-[0_-2px_10px_rgb(0_0_0/0.1)] data-ending-style:shadow-[0_-2px_10px_rgb(0_0_0/0)] origin-[50%_var(--bleed)] transform-[translateY(calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y)+var(--stack-peek-offset)+(var(--shrink)*var(--height))))_scale(var(--scale))] data-swiping:duration-0 data-nested-drawer-open:h-[calc(var(--height)+var(--bleed))] [transition:transform_450ms_cubic-bezier(0.32,0.72,0,1),height_450ms_cubic-bezier(0.32,0.72,0,1),box-shadow_450ms_cubic-bezier(0.32,0.72,0,1)]\":\n        swipeDirection === \"up\",\n      // Down enter/exit\n      \"data-ending-style:transform-[translateY(calc(100%-var(--bleed)))] data-starting-style:transform-[translateY(calc(100%-var(--bleed)))]\":\n        swipeDirection === \"down\",\n      // Up enter/exit\n      \"data-ending-style:transform-[translateY(calc(-100%+var(--bleed)))] data-starting-style:transform-[translateY(calc(-100%+var(--bleed)))]\":\n        swipeDirection === \"up\",\n    },\n  );\n};\n\nfunction DrawerPopup({\n  className,\n  children,\n  container,\n  ...props\n}: DrawerPrimitive.Popup.Props & {\n  container?: DrawerPrimitive.Portal.Props[\"container\"];\n}) {\n  const dir = use(DrawerContext);\n\n  return (\n    <DrawerPortal container={container}>\n      <DrawerBackdrop />\n      <DrawerViewport>\n        <DrawerPrimitive.Popup\n          data-slot=\"drawer-popup\"\n          className={(state) =>\n            cn(drawerPopupClassName(state), resolveClassName(className, state))\n          }\n          {...props}\n        >\n          {dir === \"down\" && <DrawerHandle />}\n          {children}\n        </DrawerPrimitive.Popup>\n      </DrawerViewport>\n    </DrawerPortal>\n  );\n}\n\nfunction DrawerHandle({ className, ...props }: ComponentProps<\"div\">) {\n  return (\n    <div\n      className={cn(\n        \"shrink-0 w-12 h-1 mx-auto mb-5 rounded-full bg-muted transition-opacity duration-200 group-data-nested-drawer-open/popup:opacity-0 group-data-nested-drawer-swiping/popup:opacity-100\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction DrawerViewport({\n  className,\n  ...props\n}: DrawerPrimitive.Viewport.Props) {\n  const dir = use(DrawerContext);\n  return (\n    <DrawerPrimitive.Viewport\n      data-slot=\"drawer-viewport\"\n      className={(state) =>\n        cn(\n          \"fixed flex inset-0\",\n          {\n            \"[--viewport-padding:0px] supports-[-webkit-touch-callout:none]:[--viewport-padding:0.625rem] items-stretch p-(--viewport-padding)\":\n              dir === \"left\" || dir === \"right\",\n            \"justify-end\": dir === \"right\",\n            \"justify-start\": dir === \"left\",\n            \"items-end justify-center\": dir === \"down\",\n            \"items-start justify-center\": dir === \"up\",\n          },\n          resolveClassName(className, state),\n        )\n      }\n      {...props}\n    />\n  );\n}\n\nfunction DrawerTitle({ className, ...props }: DrawerPrimitive.Title.Props) {\n  const dir = use(DrawerContext);\n\n  return (\n    <DrawerPrimitive.Title\n      data-slot=\"drawer-title\"\n      className={(state) =>\n        cn(\n          \"text-foreground text-base font-medium\",\n          {\n            \"text-center\": dir === \"down\" || dir === \"up\",\n          },\n          resolveClassName(className, state),\n        )\n      }\n      {...props}\n    />\n  );\n}\n\nfunction DrawerDescription({\n  className,\n  ...props\n}: DrawerPrimitive.Description.Props) {\n  const dir = use(DrawerContext);\n\n  return (\n    <DrawerPrimitive.Description\n      data-slot=\"drawer-description\"\n      className={(state) =>\n        cn(\n          \"mt-1.5 text-muted-foreground text-sm\",\n          {\n            \"text-center\": dir === \"down\" || dir === \"up\",\n          },\n          resolveClassName(className, state),\n        )\n      }\n      {...props}\n    />\n  );\n}\n\nfunction DrawerBackdrop({\n  className,\n  ...props\n}: DrawerPrimitive.Backdrop.Props) {\n  return (\n    <DrawerPrimitive.Backdrop\n      data-slot=\"drawer-backdrop\"\n      className={(state) =>\n        cn(\n          \"[--backdrop-opacity:0.2] [--bleed:3rem] dark:[--backdrop-opacity:0.7] fixed inset-0 min-h-dvh bg-black opacity-[calc(var(--backdrop-opacity)*(1-var(--drawer-swipe-progress)))] transition-opacity duration-450 ease-[cubic-bezier(0.32,0.72,0,1)] data-swiping:duration-0 data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:duration-[calc(var(--drawer-swipe-strength)*400ms)] supports-[-webkit-touch-callout:none]:absolute supports-backdrop-filter:backdrop-blur-3xl\",\n          resolveClassName(className, state),\n        )\n      }\n      {...props}\n    />\n  );\n}\n\nfunction DrawerIndentBackground({\n  className,\n  ...props\n}: DrawerPrimitive.IndentBackground.Props) {\n  return (\n    <DrawerPrimitive.IndentBackground\n      data-slot=\"drawer-indent-background\"\n      className={(state) =>\n        cn(\n          \"isolate absolute inset-0 bg-foreground/70\",\n          resolveClassName(className, state),\n        )\n      }\n      {...props}\n    />\n  );\n}\n\nfunction DrawerIndent({ className, ...props }: DrawerPrimitive.Indent.Props) {\n  return (\n    <DrawerPrimitive.Indent\n      className={(state) =>\n        cn(\n          \"bg-background [--indent-progress:var(--drawer-swipe-progress)] [--indent-radius:calc(1rem*(1-var(--indent-progress)))] [--indent-transition:calc(1-clamp(0,calc(var(--drawer-swipe-progress)*100000),1))] relative border p-4 [transition:transform_0.4s_cubic-bezier(0.32,0.72,0,1),border-radius_0.25s_cubic-bezier(0.32,0.72,0,1)] origin-[center_top] will-change-transform transform-[scale(1)_translateY(0)] duration-[calc(400ms*var(--indent-transition)),calc(250ms*var(--indent-transition))] data-active:transform-[scale(calc(0.98+(0.02*var(--indent-progress))))_translateY(calc(0.5rem*(1-var(--indent-progress))))] data-active:rounded-tl-(--indent-radius) data-active:rounded-tr-(--indent-radius)\",\n          resolveClassName(className, state),\n        )\n      }\n      {...props}\n    />\n  );\n}\n\nexport {\n  DrawerProvider,\n  Drawer,\n  DrawerBackdrop,\n  DrawerClose,\n  DrawerContent,\n  DrawerDescription,\n  DrawerPopup,\n  DrawerPortal,\n  DrawerTitle,\n  DrawerTrigger,\n  DrawerViewport,\n  DrawerIndentBackground,\n  DrawerIndent,\n  DrawerHandle,\n};\n",
      "type": "registry:ui",
      "target": "components/ui/drawer.tsx"
    }
  ]
}