{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "popover",
  "title": "Popover",
  "description": "A popover component.",
  "registryDependencies": [
    "@cubby-ui/elevated"
  ],
  "files": [
    {
      "path": "registry/default/popover/popover.tsx",
      "content": "import * as React from \"react\";\r\nimport { Popover as BasePopover } from \"@base-ui/react/popover\";\r\n\r\nimport { cn } from \"@/lib/utils\";\r\nimport {\r\n  solidSurface,\r\n  type SurfaceLevel,\r\n} from \"@/registry/default/lib/elevated\";\r\n\r\nfunction Popover<Payload = unknown>({\r\n  ...props\r\n}: BasePopover.Root.Props<Payload>) {\r\n  return <BasePopover.Root data-slot=\"popover\" {...props} />;\r\n}\r\n\r\nfunction PopoverPortal({ ...props }: BasePopover.Portal.Props) {\r\n  return <BasePopover.Portal data-slot=\"popover-portal\" {...props} />;\r\n}\r\n\r\nfunction PopoverTrigger({ ...props }: BasePopover.Trigger.Props) {\r\n  return <BasePopover.Trigger data-slot=\"popover-trigger\" {...props} />;\r\n}\r\n\r\nfunction PopoverClose({ ...props }: BasePopover.Close.Props) {\r\n  return <BasePopover.Close data-slot=\"popover-close\" {...props} />;\r\n}\r\n\r\nfunction PopoverArrow({ ...props }: BasePopover.Arrow.Props) {\r\n  return <BasePopover.Arrow data-slot=\"popover-arrow\" {...props} />;\r\n}\r\n\r\nfunction PopoverPositioner({ ...props }: BasePopover.Positioner.Props) {\r\n  return <BasePopover.Positioner data-slot=\"popover-positioner\" {...props} />;\r\n}\r\n\r\nfunction PopoverViewport({ className, ...props }: BasePopover.Viewport.Props) {\r\n  return (\r\n    <BasePopover.Viewport\r\n      data-slot=\"popover-viewport\"\r\n      // Same height and overflow policy as the viewport inside PopoverContent,\r\n      // which see for why both the percentage and the cap are needed. Padding\r\n      // is left to the caller; hand-composed popups own their own spacing.\r\n      className={cn(\r\n        \"relative h-full max-h-(--available-height) w-full overflow-clip\",\r\n        \"not-data-transitioning:overflow-y-auto\",\r\n        className,\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction PopoverPopup({\r\n  className,\r\n  level = 3,\r\n  shadowLevel = 3,\r\n  ...props\r\n}: BasePopover.Popup.Props & {\r\n  level?: SurfaceLevel;\r\n  shadowLevel?: SurfaceLevel;\r\n}) {\r\n  return (\r\n    <BasePopover.Popup\r\n      data-slot=\"popover-popup\"\r\n      data-level={level}\r\n      className={cn(\r\n        \"text-popover-foreground relative max-h-(--available-height) max-w-(--available-width) origin-(--transform-origin) rounded-xl outline-none\",\r\n        solidSurface(level, shadowLevel),\r\n        className,\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction PopoverBackdrop({ className, ...props }: BasePopover.Backdrop.Props) {\r\n  return (\r\n    <BasePopover.Backdrop\r\n      data-slot=\"popover-backdrop\"\r\n      className={cn(\r\n        \"ease-out-expo fixed inset-0 z-30 min-h-dvh bg-black/40 transition-all duration-150 supports-[-webkit-touch-callout:none]:absolute\",\r\n        \"backdrop-blur-sm data-ending-style:opacity-0 data-starting-style:opacity-0 motion-reduce:transition-none\",\r\n        className,\r\n      )}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction PopoverTitle({ className, ...props }: BasePopover.Title.Props) {\r\n  return (\r\n    <BasePopover.Title\r\n      data-slot=\"popover-title\"\r\n      className={cn(\"text-sm font-semibold\", className)}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction PopoverDescription({\r\n  className,\r\n  ...props\r\n}: BasePopover.Description.Props) {\r\n  return (\r\n    <BasePopover.Description\r\n      data-slot=\"popover-description\"\r\n      className={cn(\"text-muted-foreground text-sm\", className)}\r\n      {...props}\r\n    />\r\n  );\r\n}\r\n\r\nfunction PopoverContent({\r\n  children,\r\n  className,\r\n  side = \"bottom\",\r\n  align = \"center\",\r\n  sideOffset = 8,\r\n  alignOffset = 0,\r\n  collisionBoundary,\r\n  collisionPadding = 10,\r\n  sticky = false,\r\n  positionMethod = \"absolute\",\r\n  arrow = false,\r\n  arrowPadding,\r\n  container,\r\n  level = 3,\r\n  shadowLevel = 3,\r\n  ...props\r\n}: BasePopover.Popup.Props & {\r\n  side?: BasePopover.Positioner.Props[\"side\"];\r\n  align?: BasePopover.Positioner.Props[\"align\"];\r\n  sideOffset?: BasePopover.Positioner.Props[\"sideOffset\"];\r\n  alignOffset?: BasePopover.Positioner.Props[\"alignOffset\"];\r\n  collisionBoundary?: BasePopover.Positioner.Props[\"collisionBoundary\"];\r\n  collisionPadding?: BasePopover.Positioner.Props[\"collisionPadding\"];\r\n  sticky?: BasePopover.Positioner.Props[\"sticky\"];\r\n  positionMethod?: BasePopover.Positioner.Props[\"positionMethod\"];\r\n  arrow?: boolean;\r\n  arrowPadding?: number;\r\n  container?: HTMLElement | undefined;\r\n  /** Surface elevation level for the popup bg (1-8). Bump when nesting inside a Dialog or other elevated container. Defaults to 3. */\r\n  level?: SurfaceLevel;\r\n  /** Shadow weight (1-8). Pinned to 3 by default so the popover reads the same regardless of nesting depth. */\r\n  shadowLevel?: SurfaceLevel;\r\n}) {\r\n  return (\r\n    <PopoverPortal container={container}>\r\n      <BasePopover.Positioner\r\n        data-slot=\"popover-positioner\"\r\n        side={side}\r\n        align={align}\r\n        sideOffset={sideOffset}\r\n        alignOffset={alignOffset}\r\n        collisionBoundary={collisionBoundary}\r\n        collisionPadding={collisionPadding}\r\n        sticky={sticky}\r\n        positionMethod={positionMethod}\r\n        arrowPadding={arrowPadding}\r\n        className=\"z-50 h-(--positioner-height) max-h-(--available-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom,transform] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)] data-instant:transition-none motion-reduce:transition-none\"\r\n      >\r\n        <BasePopover.Popup\r\n          data-slot=\"popover-content\"\r\n          data-level={level}\r\n          className={cn(\r\n            // Base styles\r\n            \"text-popover-foreground relative outline-none\",\r\n            \"h-(--popup-height,auto) w-(--popup-width,auto)\",\r\n            \"max-h-(--available-height) max-w-(--available-width)\",\r\n            \"origin-(--transform-origin) overflow-hidden rounded-xl\",\r\n            // Surface elevation — bg tracks `level`, shadow weight tracks `shadowLevel`\r\n            solidSurface(level, shadowLevel),\r\n            // Size/opacity transitions\r\n            \"transition-[width,height,scale,opacity] duration-[150ms,150ms,100ms,100ms] ease-[cubic-bezier(0.22,1,0.36,1),cubic-bezier(0.22,1,0.36,1),var(--ease-out-expo),var(--ease-out-expo)]\",\r\n            \"data-starting-style:scale-95 data-starting-style:opacity-0\",\r\n            \"data-ending-style:scale-95 data-ending-style:opacity-0\",\r\n            // Only the \"already open, something changed\" instant. Base UI waits on\r\n            // this transition before unmounting, so suppressing a close means no\r\n            // exit at all, and 'click' is inferred from `event.detail === 0`,\r\n            // which every right-click matches.\r\n            \"data-[instant=trigger-change]:transition-none\",\r\n            \"motion-reduce:transition-none\",\r\n            className,\r\n          )}\r\n          {...props}\r\n        >\r\n          {arrow && (\r\n            <PopoverArrow className=\"transition-[left,right,top,bottom] duration-200 ease-[cubic-bezier(0.22,1,0.36,1)] data-instant:transition-none data-[side=bottom]:top-[-8px] data-[side=left]:right-[-13px] data-[side=left]:rotate-90 data-[side=right]:left-[-13px] data-[side=right]:-rotate-90 data-[side=top]:bottom-[-8px] data-[side=top]:rotate-180 motion-reduce:transition-none\">\r\n              <svg width=\"20\" height=\"10\" viewBox=\"0 0 20 10\" fill=\"none\">\r\n                <path\r\n                  d=\"M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V9H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z\"\r\n                  className=\"fill-(--popup-surface,var(--popover))\"\r\n                />\r\n                <path\r\n                  d=\"M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z\"\r\n                  className=\"fill-border/70\"\r\n                />\r\n              </svg>\r\n            </PopoverArrow>\r\n          )}\r\n          <BasePopover.Viewport\r\n            data-slot=\"popover-viewport\"\r\n            className={cn(\r\n              // `h-full` and the cap do different jobs; both are load-bearing. At\r\n              // rest --popup-height is `auto`, so the percentage is indefinite and\r\n              // only the cap bounds the viewport, which is what engages the\r\n              // overflow-y below. Mid-swap it is a definite px that transitions,\r\n              // and the percentage tracks it. Without that the viewport snaps to\r\n              // the incoming content's height on frame one, because Base UI takes\r\n              // the outgoing content out of flow with position:absolute, and\r\n              // overflow-clip cuts its extra rows instead of letting them fade.\r\n              // No `max-w`: `w-full` resolves against the popup's already-capped\r\n              // content box, so the width bound is inherited for free.\r\n              \"relative h-full max-h-(--available-height) w-full overflow-clip px-3 py-3 [--viewport-padding:0.75rem]\",\r\n              \"not-data-transitioning:overflow-y-auto\",\r\n              // Content width calculation (edge-to-edge minus padding)\r\n              \"**:data-current:w-[calc(var(--popup-width)-2*var(--viewport-padding))]\",\r\n              \"**:data-previous:w-[calc(var(--popup-width)-2*var(--viewport-padding))]\",\r\n              // Non-directional crossfade, mirroring TransitionPanel's `fade`\r\n              // mode: the two halves dissolve in place rather than sliding past\r\n              // each other, so nothing implies travel and the popup's own\r\n              // width/height morph carries the movement on its own.\r\n              \"**:data-current:scale-100 **:data-current:opacity-100\",\r\n              \"**:data-previous:scale-100 **:data-previous:opacity-100\",\r\n              \"**:data-current:transition-[scale,opacity] **:data-current:duration-150 **:data-current:ease-[cubic-bezier(0.22,1,0.36,1)]\",\r\n              \"**:data-previous:transition-[scale,opacity] **:data-previous:duration-150 **:data-previous:ease-[cubic-bezier(0.22,1,0.36,1)]\",\r\n              // Both directions recede to 0.96, so the swap reads the same\r\n              // whichever trigger you came from.\r\n              \"**:data-current:data-starting-style:scale-[0.96] **:data-current:data-starting-style:opacity-0\",\r\n              \"**:data-previous:data-ending-style:scale-[0.96] **:data-previous:data-ending-style:opacity-0\",\r\n              // Value-matched to the popup's guard above so one policy governs the\r\n              // subtree. Targets the content: the viewport has no transitions of\r\n              // its own and transition-property does not inherit.\r\n              \"[[data-instant=trigger-change]_&_[data-current]]:transition-none [[data-instant=trigger-change]_&_[data-previous]]:transition-none\",\r\n              \"motion-reduce:**:data-current:transition-none motion-reduce:**:data-previous:transition-none\",\r\n            )}\r\n          >\r\n            {children}\r\n          </BasePopover.Viewport>\r\n        </BasePopover.Popup>\r\n      </BasePopover.Positioner>\r\n    </PopoverPortal>\r\n  );\r\n}\r\n\r\nconst createPopoverHandle = BasePopover.createHandle;\r\n\r\nexport {\r\n  Popover,\r\n  PopoverTrigger,\r\n  PopoverTitle,\r\n  PopoverDescription,\r\n  PopoverContent,\r\n  PopoverClose,\r\n  PopoverArrow,\r\n  PopoverPositioner,\r\n  PopoverPortal,\r\n  PopoverPopup,\r\n  PopoverBackdrop,\r\n  PopoverViewport,\r\n  createPopoverHandle,\r\n};\r\n",
      "type": "registry:ui",
      "target": "components/ui/cubby-ui/popover.tsx"
    }
  ],
  "type": "registry:ui"
}