{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "popover",
  "title": "Popover",
  "type": "registry:ui",
  "files": [
    {
      "path": "packages/registry-react/components/popover/popover.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport * as PopoverPrimitive from '@radix-ui/react-popover'\nimport { cn } from '@/lib/utils'\n\nexport type PopoverCloseBehavior = 'auto' | 'click-outside' | 'esc' | 'manual' | 'none'\n\ninterface PopoverContextValue {\n  closeBehavior: PopoverCloseBehavior\n}\n\nconst PopoverContext = React.createContext<PopoverContextValue>({ closeBehavior: 'auto' })\n\nexport interface PopoverProps extends React.ComponentProps<typeof PopoverPrimitive.Root> {\n  /** Persist open state in localStorage. `true` uses an auto-generated key,\n   *  a string uses that key verbatim, `false` (default) disables. */\n  persist?: string | boolean\n  /** Controls how the popover may be dismissed. */\n  closeBehavior?: PopoverCloseBehavior\n}\n\nfunction Popover({\n  persist = false,\n  closeBehavior = 'auto',\n  open,\n  defaultOpen,\n  onOpenChange,\n  children,\n  ...props\n}: PopoverProps) {\n  const autoId = React.useId()\n  const storageKey = React.useMemo(() => {\n    if (persist === false) return null\n    if (persist === true) return `uipkge-popover-${autoId}`\n    return persist\n  }, [persist, autoId])\n\n  const isControlled = open !== undefined\n  const [localOpen, setLocalOpen] = React.useState<boolean>(defaultOpen ?? false)\n\n  // Hydrate from localStorage on mount.\n  React.useEffect(() => {\n    if (!storageKey || typeof localStorage === 'undefined') return\n    if (localStorage.getItem(storageKey) === '1') {\n      setLocalOpen(true)\n      if (!isControlled) onOpenChange?.(true)\n    }\n    // eslint-disable-next-line react-hooks/exhaustive-deps\n  }, [storageKey])\n\n  // Persist current open state.\n  const effectiveOpen = isControlled ? open : localOpen\n  React.useEffect(() => {\n    if (!storageKey || typeof localStorage === 'undefined') return\n    if (effectiveOpen) localStorage.setItem(storageKey, '1')\n    else localStorage.removeItem(storageKey)\n  }, [storageKey, effectiveOpen])\n\n  function handleOpenChange(value: boolean) {\n    setLocalOpen(value)\n    onOpenChange?.(value)\n  }\n\n  return (\n    <PopoverContext.Provider value={{ closeBehavior }}>\n      <PopoverPrimitive.Root\n        data-uipkge=\"\"\n        data-slot=\"popover\"\n        open={open}\n        defaultOpen={defaultOpen}\n        onOpenChange={handleOpenChange}\n        {...props}\n      >\n        {children}\n      </PopoverPrimitive.Root>\n    </PopoverContext.Provider>\n  )\n}\n\nconst PopoverTrigger = React.forwardRef<\n  React.ElementRef<typeof PopoverPrimitive.Trigger>,\n  React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Trigger>\n>((props, ref) => (\n  <PopoverPrimitive.Trigger ref={ref} data-uipkge=\"\" data-slot=\"popover-trigger\" {...props} />\n))\nPopoverTrigger.displayName = PopoverPrimitive.Trigger.displayName\n\nconst PopoverAnchor = React.forwardRef<\n  React.ElementRef<typeof PopoverPrimitive.Anchor>,\n  React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Anchor>\n>((props, ref) => (\n  <PopoverPrimitive.Anchor ref={ref} data-uipkge=\"\" data-slot=\"popover-anchor\" {...props} />\n))\nPopoverAnchor.displayName = PopoverPrimitive.Anchor.displayName\n\nconst PopoverContent = React.forwardRef<\n  React.ElementRef<typeof PopoverPrimitive.Content>,\n  React.ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>\n>(({ className, align = 'center', sideOffset = 4, ...props }, ref) => {\n  const { closeBehavior } = React.useContext(PopoverContext)\n\n  function handlePointerDownOutside(e: Event) {\n    if (closeBehavior === 'esc' || closeBehavior === 'manual' || closeBehavior === 'none') {\n      e.preventDefault()\n    }\n  }\n\n  function handleEscapeKeyDown(e: KeyboardEvent) {\n    if (closeBehavior === 'click-outside' || closeBehavior === 'manual' || closeBehavior === 'none') {\n      e.preventDefault()\n    }\n  }\n\n  return (\n    <PopoverPrimitive.Portal>\n      <PopoverPrimitive.Content\n        ref={ref}\n        data-uipkge=\"\"\n        data-slot=\"popover-content\"\n        align={align}\n        sideOffset={sideOffset}\n        onPointerDownOutside={handlePointerDownOutside}\n        onEscapeKeyDown={handleEscapeKeyDown}\n        className={cn(\n          'bg-popover text-popover-foreground motion-safe:data-[state=open]:animate-in motion-safe:data-[state=closed]:animate-out motion-safe:data-[state=closed]:fade-out-0 motion-safe:data-[state=open]:fade-in-0 motion-safe:data-[state=closed]:zoom-out-95 motion-safe:data-[state=open]:zoom-in-95 motion-safe:data-[side=bottom]:slide-in-from-top-2 motion-safe:data-[side=left]:slide-in-from-right-2 motion-safe:data-[side=right]:slide-in-from-left-2 motion-safe:data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden',\n          className,\n        )}\n        {...props}\n      />\n    </PopoverPrimitive.Portal>\n  )\n})\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverAnchor, PopoverContent }\n",
      "type": "registry:ui",
      "target": "~/components/ui/popover/popover.tsx"
    },
    {
      "path": "packages/registry-react/components/popover/index.ts",
      "content": "export {\n  Popover,\n  PopoverTrigger,\n  PopoverAnchor,\n  PopoverContent,\n  type PopoverProps,\n  type PopoverCloseBehavior,\n} from './popover'\n",
      "type": "registry:ui",
      "target": "~/components/ui/popover/index.ts"
    }
  ],
  "dependencies": [
    "@radix-ui/react-popover"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "description": "Click-triggered floating panel anchored to a trigger element. Supports optional localStorage persistence and configurable dismissal (click-outside, escape, manual). Built on @radix-ui/react-popover with collision detection.",
  "categories": [
    "overlay"
  ]
}