{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "citation",
  "title": "Citation",
  "description": "An exhibit sticker in the text that opens the exact passage it cites, with a stamp saying whether the source checks out.",
  "dependencies": [
    "@base-ui/react",
    "cn"
  ],
  "registryDependencies": [
    "https://bevel-ui.vercel.app/r/bevel.json",
    "https://bevel-ui.vercel.app/r/stamp.json"
  ],
  "files": [
    {
      "path": "registry/bevel/ui/citation.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Popover as PopoverPrimitive } from \"@base-ui/react/popover\"\nimport { cn } from \"cn\"\nimport { Stamp } from \"@/components/ui/stamp\"\n\n/** A cited source. Wraps a trigger (the exhibit sticker) and the passage it opens. */\nfunction Citation(props: PopoverPrimitive.Root.Props) {\n  return <PopoverPrimitive.Root data-slot=\"citation\" {...props} />\n}\n\ntype CitationTriggerProps = PopoverPrimitive.Trigger.Props & {\n  /** Sticker colour: yellow (the default), blue, or white. */\n  tone?: \"yellow\" | \"blue\" | \"white\"\n  /** The printed prefix on the sticker. */\n  abbreviation?: string\n  /** The prefix in full, read by screen readers instead of the abbreviation. */\n  label?: string\n}\n\n/**\n * The exhibit sticker, inline in text: \"Ex. 4\". Read as \"Exhibit 4\". Opens\n * the source on click, Enter or Space.\n */\nfunction CitationTrigger({\n  className,\n  tone = \"yellow\",\n  abbreviation = \"Ex.\",\n  label = \"Exhibit\",\n  children,\n  ...props\n}: CitationTriggerProps) {\n  return (\n    <PopoverPrimitive.Trigger\n      data-slot=\"citation-trigger\"\n      data-tone={tone}\n      className={cn(\n        \"mx-0.5 inline-flex -translate-y-px rotate-(--citation-tilt) items-baseline gap-0.5 rounded-(--bevel-radius-xs) bg-(--citation-sticker) px-1 py-px align-baseline text-(length:--citation-size) leading-none font-bold text-(--bevel-sticker-foreground) shadow-(--bevel-depth-sheet) outline-none select-none\",\n        \"cursor-pointer transition-[translate,rotate] duration-(--bevel-duration-small) ease-(--bevel-ease-out) motion-reduce:transition-none\",\n        \"hover:-translate-y-0.5 data-popup-open:rotate-0 data-popup-open:-translate-y-0.5\",\n        \"focus-visible:ring-2 focus-visible:ring-(--bevel-pen-blue)/60 focus-visible:ring-offset-1\",\n        \"forced-colors:border forced-colors:border-[ButtonText]\",\n        className\n      )}\n      {...props}\n    >\n      <span aria-hidden className=\"text-(length:--citation-abbreviation-size) tracking-(--bevel-tracking-print) uppercase\">\n        {abbreviation}\n      </span>\n      <span className=\"sr-only\">{label} </span>\n      <span className=\"tabular-nums\">{children}</span>\n    </PopoverPrimitive.Trigger>\n  )\n}\n\n/** The paper slip the sticker opens. Grows from the sticker. */\nfunction CitationContent({\n  className,\n  children,\n  side = \"bottom\",\n  align = \"start\",\n  sideOffset = 8,\n  ...props\n}: PopoverPrimitive.Popup.Props &\n  Pick<PopoverPrimitive.Positioner.Props, \"side\" | \"align\" | \"sideOffset\">) {\n  return (\n    <PopoverPrimitive.Portal>\n      <PopoverPrimitive.Positioner side={side} align={align} sideOffset={sideOffset} className=\"z-50\">\n        <PopoverPrimitive.Popup\n          data-slot=\"citation-content\"\n          className={cn(\n            \"bevel-paper flex w-80 max-w-[calc(100vw-2rem)] origin-(--transform-origin) flex-col gap-2 rounded-(--bevel-radius-xs) p-4 text-sm outline-none\",\n            \"transition-[scale,opacity] duration-(--bevel-duration-small) ease-(--bevel-ease-out) motion-reduce:transition-none\",\n            \"data-starting-style:scale-(--citation-pop-scale) data-starting-style:opacity-0 data-ending-style:scale-(--citation-pop-scale) data-ending-style:opacity-0\",\n            className\n          )}\n          {...props}\n        >\n          {children}\n        </PopoverPrimitive.Popup>\n      </PopoverPrimitive.Positioner>\n    </PopoverPrimitive.Portal>\n  )\n}\n\n/** The source's name. Titles the slip for screen readers. */\nfunction CitationSource({ className, ...props }: PopoverPrimitive.Title.Props) {\n  return (\n    <PopoverPrimitive.Title\n      data-slot=\"citation-source\"\n      className={cn(\"font-semibold text-(--bevel-paper-foreground)\", className)}\n      {...props}\n    />\n  )\n}\n\n/** Where in the source: page, paragraph, clause. */\nfunction CitationLocation({ className, ...props }: React.ComponentProps<\"p\">) {\n  return (\n    <p\n      data-slot=\"citation-location\"\n      className={cn(\"font-mono text-(length:--bevel-fine) text-(--bevel-paper-muted)\", className)}\n      {...props}\n    />\n  )\n}\n\n/** The quoted passage, highlighted as if marked up by hand. */\nfunction CitationQuote({ className, children, ...props }: React.ComponentProps<\"blockquote\">) {\n  return (\n    <blockquote\n      data-slot=\"citation-quote\"\n      className={cn(\n        \"border-l-2 border-(--bevel-paper-rule) pl-3 leading-relaxed text-(--bevel-paper-foreground)\",\n        className\n      )}\n      {...props}\n    >\n      <mark className=\"box-decoration-clone bg-(--citation-highlight) px-0.5 text-inherit\">\n        {children}\n      </mark>\n    </blockquote>\n  )\n}\n\nconst statusStamp = {\n  verified: { tone: \"green\", text: \"Verified\" },\n  caution: { tone: \"amber\", text: \"Caution\" },\n  unverified: { tone: \"red\", text: \"Unverified\" },\n} as const\n\ntype CitationStatusProps = Omit<React.ComponentProps<typeof Stamp>, \"tone\" | \"children\"> & {\n  /** Whether the source checks out. Always shown in words, never colour alone. */\n  status: keyof typeof statusStamp\n  /** Replace the stamped word. */\n  children?: React.ReactNode\n}\n\nfunction CitationStatus({ status, className, children, ...props }: CitationStatusProps) {\n  const stamp = statusStamp[status]\n  return (\n    <Stamp\n      data-citation-status={status}\n      tone={stamp.tone}\n      className={cn(\"self-start\", className)}\n      {...props}\n    >\n      {children ?? stamp.text}\n    </Stamp>\n  )\n}\n\n/** Close the slip, or link onward to the full document. */\nfunction CitationFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n  return (\n    <div\n      data-slot=\"citation-footer\"\n      className={cn(\"mt-1 flex items-center justify-between gap-3\", className)}\n      {...props}\n    />\n  )\n}\n\nexport {\n  Citation,\n  CitationTrigger,\n  CitationContent,\n  CitationSource,\n  CitationLocation,\n  CitationQuote,\n  CitationStatus,\n  CitationFooter,\n}\nexport type { CitationTriggerProps, CitationStatusProps }\n",
      "type": "registry:ui"
    }
  ],
  "css": {
    ":root": {
      "--citation-tilt": "-2deg",
      "--citation-size": "0.75em",
      "--citation-abbreviation-size": "0.8em",
      "--citation-highlight": "oklch(0.93 0.13 100 / 0.75)",
      "--citation-sticker-blue": "oklch(0.86 0.06 240)",
      "--citation-sticker-white": "oklch(0.97 0.004 90)",
      "--citation-pop-scale": "0.96"
    },
    "[data-slot=\"citation-trigger\"]": {
      "--citation-sticker": "var(--bevel-sticker)"
    },
    "[data-slot=\"citation-trigger\"][data-tone=\"blue\"]": {
      "--citation-sticker": "var(--citation-sticker-blue)"
    },
    "[data-slot=\"citation-trigger\"][data-tone=\"white\"]": {
      "--citation-sticker": "var(--citation-sticker-white)"
    }
  },
  "categories": [
    "documents"
  ],
  "type": "registry:ui"
}