{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "popover",
  "type": "registry:ui",
  "registryDependencies": [],
  "dependencies": ["@radix-ui/react-popover", "motion"],
  "devDependencies": [],
  "files": [
    {
      "path": "popover.tsx",
      "content": "\"use client\";\n\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\";\nimport { AnimatePresence, motion } from \"motion/react\";\nimport * as React from \"react\";\n\nimport { cn } from \"@/lib/utils\";\n\nconst controlCornerClassName =\n  \"rounded-lg supports-[corner-shape:squircle]:corner-squircle supports-[corner-shape:squircle]:rounded-[11px]\";\n\nconst surfaceCornerClassName =\n  \"rounded-lg supports-[corner-shape:squircle]:corner-squircle supports-[corner-shape:squircle]:rounded-[12px]\";\n\nconst popoverThemeClassName =\n  \"[--po-surface:#ffffff] [--po-foreground:#111111] [--po-border:#e3e7ec] [--po-ring:rgba(17,17,17,0.16)] dark:[--po-surface:#111111] dark:[--po-foreground:#f6f3ec] dark:[--po-border:#2b2a25] dark:[--po-ring:rgba(246,243,236,0.18)]\";\n\nconst popoverPanelClassName = cn(\n  surfaceCornerClassName,\n  \"z-50 w-72 transform-gpu border border-[color:var(--po-border)] bg-[color:var(--po-surface)] p-4 text-[color:var(--po-foreground)] shadow-lg outline-none will-change-[transform,opacity,filter]\"\n);\n\nconst popoverTriggerClassName = cn(\n  controlCornerClassName,\n  \"inline-flex min-h-11 min-w-11 touch-manipulation items-center justify-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:color-mix(in_oklch,var(--po-ring),transparent_50%)] focus-visible:ring-offset-2 focus-visible:ring-offset-[color:var(--po-surface)]\"\n);\n\ntype Side = \"top\" | \"right\" | \"bottom\" | \"left\";\n\ntype PopoverContextValue = {\n  open: boolean;\n};\n\nconst PopoverContext = React.createContext<PopoverContextValue | null>(null);\n\nconst initialOffset: Record<Side, { x: number; y: number }> = {\n  top: { x: 0, y: 10 },\n  right: { x: -10, y: 0 },\n  bottom: { x: 0, y: -10 },\n  left: { x: 10, y: 0 },\n};\n\nconst PANEL_SPRING = {\n  type: \"spring\",\n  stiffness: 240,\n  damping: 22,\n  mass: 0.78,\n} as const;\n\nconst usePopover = () => {\n  const context = React.useContext(PopoverContext);\n\n  if (!context) {\n    throw new Error(\"Popover components must be used inside Popover\");\n  }\n\n  return context;\n};\n\ntype PopoverProps = React.ComponentPropsWithoutRef<\n  typeof PopoverPrimitive.Root\n>;\n\nconst Popover = ({\n  children,\n  defaultOpen = false,\n  onOpenChange,\n  open: openProp,\n  ...props\n}: PopoverProps) => {\n  const isControlled = openProp !== undefined;\n  const [uncontrolledOpen, setUncontrolledOpen] = React.useState(defaultOpen);\n  const open = isControlled ? openProp : uncontrolledOpen;\n\n  const handleOpenChange = React.useCallback(\n    (nextOpen: boolean) => {\n      if (!isControlled) {\n        setUncontrolledOpen(nextOpen);\n      }\n\n      onOpenChange?.(nextOpen);\n    },\n    [isControlled, onOpenChange]\n  );\n\n  return (\n    <PopoverContext.Provider value={{ open }}>\n      <PopoverPrimitive.Root\n        {...props}\n        onOpenChange={handleOpenChange}\n        open={open}\n      >\n        {children}\n      </PopoverPrimitive.Root>\n    </PopoverContext.Provider>\n  );\n};\nPopover.displayName = \"Popover\";\n\ntype PopoverTriggerProps = React.ComponentPropsWithoutRef<\n  typeof PopoverPrimitive.Trigger\n>;\n\nconst PopoverTrigger = React.forwardRef<\n  React.ElementRef<typeof PopoverPrimitive.Trigger>,\n  PopoverTriggerProps\n>(({ asChild, className, ...props }, ref) => {\n  return (\n    <PopoverPrimitive.Trigger\n      asChild={asChild}\n      className={cn(\n        !asChild && popoverThemeClassName,\n        !asChild && popoverTriggerClassName,\n        className\n      )}\n      ref={ref}\n      {...props}\n    />\n  );\n});\nPopoverTrigger.displayName = \"PopoverTrigger\";\n\nconst PopoverAnchor = PopoverPrimitive.Anchor;\n\ntype PopoverContentProps = React.ComponentPropsWithoutRef<\n  typeof PopoverPrimitive.Content\n> & {\n  open?: boolean;\n};\n\ntype PopoverContentPanelProps = React.ComponentPropsWithoutRef<\n  typeof motion.div\n> & {\n  \"data-side\"?: Side;\n};\n\nconst PopoverContentPanel = React.forwardRef<\n  HTMLDivElement,\n  PopoverContentPanelProps\n>(({ children, className, style, \"data-side\": dataSide, ...props }, ref) => {\n  const resolvedSide = dataSide ?? \"bottom\";\n\n  return (\n    <motion.div\n      animate={{ opacity: 1, scale: 1, x: 0, y: 0, filter: \"blur(0px)\" }}\n      className={cn(popoverThemeClassName, popoverPanelClassName, className)}\n      exit={{\n        opacity: 0,\n        scale: 0.985,\n        filter: \"blur(4px)\",\n        ...initialOffset[resolvedSide],\n        transition: { duration: 0.2, ease: \"easeOut\" },\n      }}\n      initial={{\n        opacity: 0,\n        scale: 0.955,\n        filter: \"blur(8px)\",\n        ...initialOffset[resolvedSide],\n      }}\n      layout=\"size\"\n      ref={ref}\n      style={{\n        transformOrigin: \"var(--radix-popover-content-transform-origin)\",\n        ...style,\n      }}\n      transition={PANEL_SPRING}\n      {...props}\n    >\n      {children}\n    </motion.div>\n  );\n});\nPopoverContentPanel.displayName = \"PopoverContentPanel\";\n\n/**\n * Internal content body — uses Radix's placement data for direction-aware\n * motion and lets Motion smoothly animate size changes while content updates.\n */\nconst PopoverContentBody = React.forwardRef<\n  React.ElementRef<typeof PopoverPrimitive.Content>,\n  PopoverContentProps\n>(\n  (\n    {\n      align = \"center\",\n      avoidCollisions = true,\n      children,\n      className,\n      collisionPadding = 12,\n      side = \"bottom\",\n      sideOffset = 8,\n      ...props\n    },\n    ref\n  ) => {\n    return (\n      <PopoverPrimitive.Content\n        align={align}\n        asChild\n        avoidCollisions={avoidCollisions}\n        collisionPadding={collisionPadding}\n        ref={ref}\n        side={side}\n        sideOffset={sideOffset}\n        {...props}\n      >\n        <PopoverContentPanel className={className}>\n          {children}\n        </PopoverContentPanel>\n      </PopoverPrimitive.Content>\n    );\n  }\n);\nPopoverContentBody.displayName = \"PopoverContentBody\";\n\n/**\n * Wrap PopoverContent with AnimatePresence so exit animations play.\n * Presence follows the nearest Popover root state.\n * `open` is accepted for backwards compatibility but is no longer required.\n */\nconst PopoverContent = React.forwardRef<\n  React.ElementRef<typeof PopoverPrimitive.Content>,\n  PopoverContentProps\n>(({ open: _open, ...props }, ref) => {\n  const { open: contextOpen } = usePopover();\n\n  return (\n    <AnimatePresence>\n      {contextOpen ? (\n        <PopoverPrimitive.Portal forceMount>\n          <PopoverContentBody ref={ref} {...props} />\n        </PopoverPrimitive.Portal>\n      ) : null}\n    </AnimatePresence>\n  );\n});\nPopoverContent.displayName = \"PopoverContent\";\n\nexport { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };\n",
      "type": "registry:ui"
    }
  ],
  "title": "Popover",
  "description": "Popover built on Radix with portal-based positioning, optional anchor support, side-aware motion, and smooth size changes while content updates."
}
