{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "base-preview-card",
  "type": "registry:ui",
  "title": "Base Preview Card",
  "description": "A popup that appears when a link is hovered, showing a preview for sighted users.",
  "dependencies": [
    "motion",
    "@base-ui-components/react"
  ],
  "files": [
    {
      "path": "registry/base/preview-card/index.tsx",
      "content": "'use client';\n\nimport * as React from 'react';\nimport { PreviewCard as PreviewCardPrimitives } from '@base-ui-components/react/preview-card';\nimport {\n  AnimatePresence,\n  motion,\n  type HTMLMotionProps,\n  type Transition,\n} from 'motion/react';\n\nimport { cn } from '@/lib/utils';\n\ntype PreviewCardContextType = {\n  isOpen: boolean;\n};\n\nconst PreviewCardContext = React.createContext<\n  PreviewCardContextType | undefined\n>(undefined);\n\nconst usePreviewCard = (): PreviewCardContextType => {\n  const context = React.useContext(PreviewCardContext);\n  if (!context) {\n    throw new Error('usePreviewCard must be used within a PreviewCard');\n  }\n  return context;\n};\n\ntype Side = React.ComponentPropsWithoutRef<\n  typeof PreviewCardPrimitives.Positioner\n>['side'];\n\ntype Align = React.ComponentPropsWithoutRef<\n  typeof PreviewCardPrimitives.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 PreviewCardProps = React.ComponentProps<typeof PreviewCardPrimitives.Root>;\n\nfunction PreviewCard(props: PreviewCardProps) {\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<NonNullable<PreviewCardProps['onOpenChange']>>[2],\n    ) => {\n      setIsOpen(open);\n      props.onOpenChange?.(open, event, reason);\n    },\n    [props],\n  );\n\n  return (\n    <PreviewCardContext.Provider value={{ isOpen }}>\n      <PreviewCardPrimitives.Root\n        data-slot=\"preview-card\"\n        {...props}\n        onOpenChange={handleOpenChange}\n      />\n    </PreviewCardContext.Provider>\n  );\n}\n\ntype PreviewCardTriggerProps = React.ComponentProps<\n  typeof PreviewCardPrimitives.Trigger\n>;\n\nfunction PreviewCardTrigger(props: PreviewCardTriggerProps) {\n  return (\n    <PreviewCardPrimitives.Trigger\n      data-slot=\"preview-card-trigger\"\n      {...props}\n    />\n  );\n}\n\ntype PreviewCardContentProps = React.ComponentProps<\n  typeof PreviewCardPrimitives.Positioner\n> & {\n  transition?: Transition;\n  popupProps?: typeof PreviewCardPrimitives.Popup;\n  motionProps?: HTMLMotionProps<'div'>;\n  positionerClassName?: string;\n};\n\nfunction PreviewCardContent({\n  className,\n  popupProps,\n  motionProps,\n  positionerClassName,\n  side = 'bottom',\n  sideOffset = 10,\n  transition = { type: 'spring', stiffness: 300, damping: 25 },\n  children,\n  ...props\n}: PreviewCardContentProps) {\n  const { isOpen } = usePreviewCard();\n  const initialPosition = getInitialPosition(side);\n\n  return (\n    <AnimatePresence>\n      {isOpen && (\n        <PreviewCardPrimitives.Portal\n          keepMounted\n          data-slot=\"preview-card-portal\"\n        >\n          <PreviewCardPrimitives.Positioner\n            data-slot=\"preview-card-positioner\"\n            side={side}\n            sideOffset={sideOffset}\n            className={cn('z-50', positionerClassName)}\n            {...props}\n          >\n            <PreviewCardPrimitives.Popup\n              data-slot=\"preview-card-popup\"\n              {...popupProps}\n              className={cn(\n                'w-64 rounded-lg border bg-popover p-4 text-popover-foreground shadow-md outline-none',\n                className,\n              )}\n              render={\n                <motion.div\n                  key=\"preview-card-content\"\n                  initial={{ opacity: 0, scale: 0.5, ...initialPosition }}\n                  animate={{ opacity: 1, scale: 1, x: 0, y: 0 }}\n                  exit={{ opacity: 0, scale: 0.5, ...initialPosition }}\n                  transition={transition}\n                  {...motionProps}\n                />\n              }\n            >\n              {children}\n            </PreviewCardPrimitives.Popup>\n          </PreviewCardPrimitives.Positioner>\n        </PreviewCardPrimitives.Portal>\n      )}\n    </AnimatePresence>\n  );\n}\n\nexport {\n  PreviewCard,\n  PreviewCardTrigger,\n  PreviewCardContent,\n  usePreviewCard,\n  type PreviewCardProps,\n  type PreviewCardTriggerProps,\n  type PreviewCardContentProps,\n  type Side,\n  type Align,\n};\n",
      "type": "registry:ui",
      "target": "components/animate-ui/base/preview-card.tsx"
    }
  ]
}