{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "hover-card",
  "title": "Hover Card",
  "description": "A popover that previews a link while the pointer rests on it.",
  "dependencies": [
    "@base-ui/react",
    "@stylexjs/stylex"
  ],
  "registryDependencies": [
    "https://constella.aayush.cv/r/base.json"
  ],
  "files": [
    {
      "path": "src/components/primitives/hover-card.tsx",
      "content": "\"use client\";\n\nimport { PreviewCard as PreviewCardPrimitive } from \"@base-ui/react/preview-card\";\nimport * as stylex from \"@stylexjs/stylex\";\n\nimport type { Sx } from \"@/lib/constella/styles\";\nimport { typeStyles } from \"@/lib/constella/styles\";\nimport {\n  colors,\n  durations,\n  easings,\n  layers,\n  media,\n  motion,\n  offsets,\n  radii,\n  shadows,\n  sizes,\n  space,\n} from \"@/lib/constella/tokens.stylex\";\n\ntype Styled<T> = Omit<T, \"className\" | \"style\"> & {\n  sx?: Sx;\n};\n\ntype HoverCardContentProps = Styled<PreviewCardPrimitive.Popup.Props> &\n  Pick<\n    PreviewCardPrimitive.Positioner.Props,\n    \"align\" | \"alignOffset\" | \"side\" | \"sideOffset\"\n  >;\n\nconst offstage = \":is([data-starting-style], [data-ending-style])\";\nconst closing = \":is([data-ending-style]):not([data-instant])\";\nconst instant = \":is([data-instant])\";\n\nconst styles = stylex.create({\n  // Moving between triggers that share one card, it glides to the new one.\n  positioner: {\n    transitionDuration: {\n      default: durations.move,\n      [instant]: \"0s\",\n      [media.reducedMotion]: \"0s\",\n    },\n    transitionProperty: \"top, left, right, bottom\",\n    transitionTimingFunction: easings.out,\n    zIndex: layers.popover,\n  },\n  // A popover's surface and motion.\n  popup: {\n    backgroundColor: colors.raised,\n    borderStartStartRadius: radii.lg,\n    borderStartEndRadius: radii.lg,\n    borderEndStartRadius: radii.lg,\n    borderEndEndRadius: radii.lg,\n    boxShadow: shadows.lg,\n    color: colors.textPrimary,\n    // Base UI measures each trigger's content, so the card can grow to the next one's height.\n    height: \"var(--popup-height, auto)\",\n    maxWidth: \"var(--available-width)\",\n    opacity: { default: 1, [offstage]: 0 },\n    paddingBlockEnd: space.popup,\n    paddingBlockStart: space.popup,\n    paddingInlineEnd: space.popup,\n    paddingInlineStart: space.popup,\n    transform: { default: \"none\", [offstage]: `scale(${motion.popoverScale})` },\n    transformOrigin: \"var(--transform-origin)\",\n    transitionDuration: {\n      default: `${durations.popover}, ${durations.popover}, ${durations.move}`,\n      [closing]: durations.popoverExit,\n      [instant]: \"0s\",\n    },\n    transitionProperty: {\n      default: \"opacity, transform, height\",\n      [media.reducedMotion]: \"opacity\",\n    },\n    transitionTimingFunction: easings.out,\n    width: sizes.popover,\n  },\n  viewport: {\n    height: \"100%\",\n    overflow: \"clip\",\n    position: \"relative\",\n  },\n});\n\n/** One card several triggers share: pass it to `HoverCard` and each `HoverCardTrigger` as `handle`. */\nconst createHoverCardHandle = PreviewCardPrimitive.createHandle;\n\n/** Its children can be a function of the open trigger's `payload`. */\nfunction HoverCard<Payload>(props: PreviewCardPrimitive.Root.Props<Payload>) {\n  return <PreviewCardPrimitive.Root {...props} />;\n}\n\n// Base UI takes bare milliseconds; the tokens carry `ms`.\nconst openDelay = Number(durations.hoverCardDelay.slice(0, -\"ms\".length));\nconst closeAfter = Number(durations.hoverCardCloseDelay.slice(0, -\"ms\".length));\n\nfunction HoverCardTrigger<Payload>({\n  closeDelay = closeAfter,\n  delay = openDelay,\n  sx,\n  ...props\n}: Styled<PreviewCardPrimitive.Trigger.Props<Payload>>) {\n  return (\n    <PreviewCardPrimitive.Trigger\n      closeDelay={closeDelay}\n      data-slot=\"hover-card-trigger\"\n      delay={delay}\n      {...props}\n      {...stylex.props(sx)}\n    />\n  );\n}\n\n/** Renders the portal, the positioner and the popup. Placement props go to the positioner. */\nfunction HoverCardContent({\n  align = \"center\",\n  alignOffset = 0,\n  children,\n  side = \"bottom\",\n  sideOffset = Number(offsets.popover),\n  sx,\n  ...props\n}: HoverCardContentProps) {\n  return (\n    <PreviewCardPrimitive.Portal>\n      <PreviewCardPrimitive.Positioner\n        align={align}\n        alignOffset={alignOffset}\n        side={side}\n        sideOffset={sideOffset}\n        {...stylex.props(styles.positioner)}\n      >\n        <PreviewCardPrimitive.Popup\n          data-slot=\"hover-card-content\"\n          {...props}\n          {...stylex.props([typeStyles.textSm, styles.popup], sx)}\n        >\n          <PreviewCardPrimitive.Viewport\n            data-slot=\"hover-card-viewport\"\n            {...stylex.props(styles.viewport)}\n          >\n            {children}\n          </PreviewCardPrimitive.Viewport>\n        </PreviewCardPrimitive.Popup>\n      </PreviewCardPrimitive.Positioner>\n    </PreviewCardPrimitive.Portal>\n  );\n}\n\nexport { createHoverCardHandle, HoverCard, HoverCardContent, HoverCardTrigger };\nexport type { HoverCardContentProps };\n",
      "type": "registry:component"
    }
  ],
  "docs": "Usage: https://constella.aayush.cv/docs/components/hover-card/index.md",
  "type": "registry:ui"
}