{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "popover",
  "title": "Popover",
  "description": "Rich content in a floating panel, opened from a button, with a header and room for a form.",
  "dependencies": [
    "@base-ui/react",
    "@stylexjs/stylex"
  ],
  "registryDependencies": [
    "https://constella.aayush.cv/r/base.json"
  ],
  "files": [
    {
      "path": "src/components/primitives/popover.tsx",
      "content": "\"use client\";\n\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\";\nimport * as stylex from \"@stylexjs/stylex\";\nimport type { ComponentProps } from \"react\";\n\nimport type { Sx } from \"@/lib/constella/styles\";\nimport { typeStyles } from \"@/lib/constella/styles\";\nimport {\n  colors,\n  durations,\n  easings,\n  fontWeights,\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 PopoverContentProps = Styled<PopoverPrimitive.Popup.Props> &\n  Pick<\n    PopoverPrimitive.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  positioner: {\n    zIndex: layers.popover,\n  },\n  // Select's surface and motion (below), so every popup opens the same way.\n  surface: {\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    display: \"flex\",\n    flexDirection: \"column\",\n    gap: space.popup,\n    maxWidth: \"var(--available-width)\",\n    paddingBlock: space.popup,\n    paddingInline: space.popup,\n    width: sizes.popover,\n  },\n  motion: {\n    opacity: { default: 1, [offstage]: 0 },\n    transform: { default: \"none\", [offstage]: `scale(${motion.popoverScale})` },\n    transformOrigin: \"var(--transform-origin)\",\n    transitionDuration: {\n      default: durations.popover,\n      [closing]: durations.popoverExit,\n      [instant]: \"0s\",\n    },\n    transitionProperty: {\n      default: \"opacity, transform\",\n      [media.reducedMotion]: \"opacity\",\n    },\n    transitionTimingFunction: easings.out,\n  },\n  header: {\n    display: \"flex\",\n    flexDirection: \"column\",\n    gap: space.xxxs,\n  },\n  title: {\n    fontWeight: fontWeights.medium,\n    marginBlock: 0,\n    marginInline: 0,\n    textWrap: \"balance\",\n  },\n  description: {\n    color: colors.textSecondary,\n    marginBlock: 0,\n    marginInline: 0,\n    textWrap: \"pretty\",\n  },\n});\n\nfunction Popover(props: PopoverPrimitive.Root.Props) {\n  return <PopoverPrimitive.Root data-slot=\"popover\" {...props} />;\n}\n\nfunction PopoverTrigger({\n  sx,\n  ...props\n}: Styled<PopoverPrimitive.Trigger.Props>) {\n  return (\n    <PopoverPrimitive.Trigger\n      data-slot=\"popover-trigger\"\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 PopoverContent({\n  align = \"center\",\n  alignOffset = 0,\n  side = \"bottom\",\n  sideOffset = Number(offsets.popover),\n  sx,\n  ...props\n}: PopoverContentProps) {\n  return (\n    <PopoverPrimitive.Portal>\n      <PopoverPrimitive.Positioner\n        align={align}\n        alignOffset={alignOffset}\n        side={side}\n        sideOffset={sideOffset}\n        {...stylex.props(styles.positioner)}\n      >\n        <PopoverPrimitive.Popup\n          data-slot=\"popover-content\"\n          {...props}\n          {...stylex.props(\n            [typeStyles.textSm, styles.surface],\n            styles.motion,\n            sx\n          )}\n        />\n      </PopoverPrimitive.Positioner>\n    </PopoverPrimitive.Portal>\n  );\n}\n\nfunction PopoverHeader({ sx, ...props }: Styled<ComponentProps<\"div\">>) {\n  return (\n    <div\n      data-slot=\"popover-header\"\n      {...props}\n      {...stylex.props(styles.header, sx)}\n    />\n  );\n}\n\nfunction PopoverTitle({ sx, ...props }: Styled<PopoverPrimitive.Title.Props>) {\n  return (\n    <PopoverPrimitive.Title\n      data-slot=\"popover-title\"\n      {...props}\n      {...stylex.props([typeStyles.textSm, styles.title], sx)}\n    />\n  );\n}\n\nfunction PopoverDescription({\n  sx,\n  ...props\n}: Styled<PopoverPrimitive.Description.Props>) {\n  return (\n    <PopoverPrimitive.Description\n      data-slot=\"popover-description\"\n      {...props}\n      {...stylex.props([typeStyles.textSm, styles.description], sx)}\n    />\n  );\n}\n\n/** The positioner's layer, the popup's surface and its motion, for a part that draws its own popup. */\nconst popoverStyles = {\n  motion: styles.motion,\n  positioner: styles.positioner,\n  surface: [typeStyles.textSm, styles.surface],\n};\n\nexport {\n  Popover,\n  PopoverContent,\n  PopoverDescription,\n  PopoverHeader,\n  popoverStyles,\n  PopoverTitle,\n  PopoverTrigger,\n};\nexport type { PopoverContentProps };\n",
      "type": "registry:component"
    }
  ],
  "docs": "Usage: https://constella.aayush.cv/docs/components/popover/index.md",
  "type": "registry:ui"
}