{ "$schema": "https://ui.shadcn.com/schema/registry-item.json", "name": "base-popover", "type": "registry:ui", "title": "Base Popover", "description": "An accessible popup anchored to a button.", "dependencies": [ "motion", "@base-ui-components/react" ], "files": [ { "path": "registry/base/popover/index.tsx", "content": "'use client';\n\nimport * as React from 'react';\nimport { Popover as PopoverPrimitive } from '@base-ui-components/react/popover';\nimport {\n AnimatePresence,\n HTMLMotionProps,\n motion,\n type Transition,\n} from 'motion/react';\n\nimport { cn } from '@/lib/utils';\n\ntype Side = React.ComponentPropsWithoutRef<\n typeof PopoverPrimitive.Positioner\n>['side'];\n\ntype Align = React.ComponentPropsWithoutRef<\n typeof PopoverPrimitive.Positioner\n>['align'];\n\nconst getInitialPosition = (side: Side) => {\n switch (side) {\n case 'top':\n return { y: 15 };\n case 'bottom':\n return { y: -15 };\n case 'left':\n case 'inline-start':\n return { x: 15 };\n case 'right':\n case 'inline-end':\n return { x: -15 };\n }\n};\n\ntype PopoverContextType = {\n isOpen: boolean;\n side?: Side;\n setSide?: (side: Side) => void;\n};\n\nconst PopoverContext = React.createContext(\n undefined,\n);\n\nconst usePopover = (): PopoverContextType => {\n const context = React.useContext(PopoverContext);\n if (!context) {\n throw new Error('usePopover must be used within a Popover');\n }\n return context;\n};\n\ntype PopoverProps = React.ComponentProps;\n\nfunction Popover(props: PopoverProps) {\n const [isOpen, setIsOpen] = React.useState(\n props?.open ?? props?.defaultOpen ?? false,\n );\n\n React.useEffect(() => {\n if (props?.open !== undefined) setIsOpen(props.open);\n }, [props?.open]);\n\n const handleOpenChange = React.useCallback(\n (\n open: boolean,\n event: Event | undefined,\n reason: Parameters>[2],\n ) => {\n setIsOpen(open);\n props.onOpenChange?.(open, event, reason);\n },\n [props],\n );\n\n return (\n \n \n \n );\n}\n\ntype PopoverTriggerProps = React.ComponentProps<\n typeof PopoverPrimitive.Trigger\n>;\n\nfunction PopoverTrigger(props: PopoverTriggerProps) {\n return ;\n}\n\ntype PopoverContentProps = Omit<\n React.ComponentProps,\n 'render'\n> & {\n transition?: Transition;\n popupProps?: typeof PopoverPrimitive.Popup;\n motionProps?: HTMLMotionProps<'div'>;\n positionerClassName?: string;\n};\n\nfunction PopoverContent({\n children,\n align = 'center',\n side = 'bottom',\n sideOffset = 4,\n className,\n positionerClassName,\n popupProps,\n motionProps,\n transition = { type: 'spring', stiffness: 300, damping: 25 },\n ...props\n}: PopoverContentProps) {\n const { isOpen } = usePopover();\n const initialPosition = getInitialPosition(side);\n\n return (\n \n {isOpen && (\n \n \n \n }\n >\n {children}\n \n \n \n )}\n \n );\n}\n\nexport {\n Popover,\n PopoverTrigger,\n PopoverContent,\n usePopover,\n type PopoverContextType,\n type PopoverProps,\n type PopoverTriggerProps,\n type PopoverContentProps,\n type Side,\n type Align,\n};\n", "type": "registry:ui", "target": "components/animate-ui/base/popover.tsx" } ] }