{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "r-popover",
  "type": "registry:ui",
  "registryDependencies": [],
  "dependencies": ["@radix-ui/react-popover", "motion"],
  "devDependencies": [],
  "files": [
    {
      "path": "r-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-none outline-none\"\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 FLUID_EASE = [0.16, 1, 0.3, 1] as const;\nconst POPOVER_EXIT_EASE = [0.4, 0, 0.6, 1] as const;\n\nconst POPOVER_SPRING = {\n  type: \"spring\" as const,\n  stiffness: 340,\n  damping: 30,\n  mass: 0.72,\n};\n\nfunction getSideMotionOffset(side: Side) {\n  switch (side) {\n    case \"top\":\n      return { x: 0, y: 4 };\n    case \"right\":\n      return { x: -4, y: 0 };\n    case \"left\":\n      return { x: 4, y: 0 };\n    default:\n      return { x: 0, y: -4 };\n  }\n}\n\nfunction getPopoverMotion(side: Side) {\n  const offset = getSideMotionOffset(side);\n\n  return {\n    animate: { opacity: 1, scale: 1, x: 0, y: 0 },\n    closed: { opacity: 0, scale: 0.988, ...offset },\n    initial: { opacity: 0, scale: 0.988, ...offset },\n    openTransition: {\n      opacity: { duration: 0.26, ease: FLUID_EASE },\n      scale: POPOVER_SPRING,\n      x: POPOVER_SPRING,\n      y: POPOVER_SPRING,\n    },\n    closedTransition: {\n      opacity: { duration: 0.16, ease: POPOVER_EXIT_EASE },\n      scale: { duration: 0.16, ease: POPOVER_EXIT_EASE },\n      x: { duration: 0.16, ease: POPOVER_EXIT_EASE },\n      y: { duration: 0.16, ease: POPOVER_EXIT_EASE },\n    },\n  };\n}\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.HTMLAttributes<HTMLDivElement> & {\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  const popoverMotion = getPopoverMotion(resolvedSide);\n  const panelVariants = {\n    closed: {\n      ...popoverMotion.closed,\n      transition: popoverMotion.closedTransition,\n    },\n    open: {\n      ...popoverMotion.animate,\n      transition: popoverMotion.openTransition,\n    },\n  };\n\n  return (\n    <div ref={ref} style={style} {...props}>\n      <motion.div\n        animate=\"open\"\n        className={cn(popoverThemeClassName, popoverPanelClassName, className)}\n        exit=\"closed\"\n        initial=\"closed\"\n        layout=\"size\"\n        style={{\n          transformOrigin: \"var(--radix-popover-content-transform-origin)\",\n        }}\n        variants={panelVariants}\n      >\n        {children}\n      </motion.div>\n    </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        side={side}\n        sideOffset={sideOffset}\n        {...props}\n      >\n        <PopoverContentPanel className={className} ref={ref}>\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 (Radix UI)",
  "description": "Popover with the same Iconiq API layered over Radix UI popover primitives, preserving side-aware panel motion, optional anchor support, and size-aware content transitions."
}
