{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "inline-citations",
  "title": "Inline Citations",
  "description": "Numbered markers inside generated text, each linking to its entry in a source list.",
  "dependencies": [
    "lucide-react@^1.31.0"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/default/inline-citations/inline-citations.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ArrowUpRight } from \"lucide-react\"\nimport { cn } from \"@/lib/utils\"\n\nexport type CitationSource = {\n  id: string\n  title: string\n  url?: string\n  snippet?: string\n}\n\nexport type InlineCitationsProps = React.HTMLAttributes<HTMLDivElement> & {\n  sources: CitationSource[]\n  sourceListLabel?: React.ReactNode\n  showSourceList?: boolean\n}\n\nexport type CitationProps = Omit<\n  React.AnchorHTMLAttributes<HTMLAnchorElement>,\n  \"href\" | \"children\"\n> & {\n  id: string\n}\n\ntype CitationsContext = {\n  order: Map<string, number>\n  sources: Map<string, CitationSource>\n  scope: string\n}\n\nconst CitationsContext = React.createContext<CitationsContext | null>(null)\n\nexport function InlineCitations({\n  sources,\n  sourceListLabel = \"Sources\",\n  showSourceList = true,\n  children,\n  className,\n  ...rootProps\n}: InlineCitationsProps) {\n  const scope = React.useId().replace(/:/g, \"\")\n\n  const context = React.useMemo<CitationsContext>(\n    () => ({\n      order: new Map(sources.map((source, index) => [source.id, index + 1])),\n      sources: new Map(sources.map((source) => [source.id, source])),\n      scope,\n    }),\n    [sources, scope]\n  )\n\n  return (\n    <CitationsContext.Provider value={context}>\n      <div data-slot=\"inline-citations\" className={className} {...rootProps}>\n        <div data-slot=\"inline-citations-body\">{children}</div>\n\n        {showSourceList && sources.length > 0 ? (\n          <div data-slot=\"inline-citations-sources\" className=\"mt-5\">\n            <p className=\"text-muted-foreground text-xs font-bold tracking-[0.08em] uppercase\">\n              {sourceListLabel}\n            </p>\n\n            <ol className=\"mt-2 grid gap-1.5\">\n              {sources.map((source, index) => (\n                <li\n                  key={source.id}\n                  id={`${scope}-source-${source.id}`}\n                  data-slot=\"inline-citations-source\"\n                  className=\"flex gap-2.5 text-sm\"\n                >\n                  <span className=\"text-muted-foreground font-[family-name:var(--font-mono),monospace] text-xs tabular-nums\">\n                    {index + 1}\n                  </span>\n\n                  <span className=\"min-w-0\">\n                    {source.url ? (\n                      <a\n                        href={source.url}\n                        target=\"_blank\"\n                        rel=\"noreferrer noopener\"\n                        className=\"hover:text-primary inline-flex items-center gap-1 font-semibold underline underline-offset-4\"\n                      >\n                        {source.title}\n                        <ArrowUpRight aria-hidden=\"true\" size={13} />\n                        <span className=\"sr-only\">(opens in a new tab)</span>\n                      </a>\n                    ) : (\n                      <span className=\"font-semibold\">{source.title}</span>\n                    )}\n\n                    {source.snippet ? (\n                      <span className=\"text-muted-foreground mt-0.5 block text-xs leading-relaxed\">\n                        {source.snippet}\n                      </span>\n                    ) : null}\n                  </span>\n                </li>\n              ))}\n            </ol>\n          </div>\n        ) : null}\n      </div>\n    </CitationsContext.Provider>\n  )\n}\n\nexport function Citation({ id, className, ...anchorProps }: CitationProps) {\n  const context = React.useContext(CitationsContext)\n\n  if (!context) {\n    throw new Error(\"Citation must be rendered inside InlineCitations.\")\n  }\n\n  const number = context.order.get(id)\n  const source = context.sources.get(id)\n\n  if (number === undefined || source === undefined) return null\n\n  return (\n    <a\n      data-slot=\"citation\"\n      href={`#${context.scope}-source-${id}`}\n      className={cn(\n        \"bg-muted text-muted-foreground hover:bg-foreground hover:text-background focus-visible:ring-ring ml-0.5 inline-flex min-w-[1.25rem] translate-y-[-0.15em] items-center justify-center rounded-full px-1 align-baseline font-[family-name:var(--font-mono),monospace] text-[0.65em] leading-[1.5] font-semibold no-underline transition-colors duration-150 focus-visible:ring-2 focus-visible:outline-none motion-reduce:transition-none\",\n        className\n      )}\n      {...anchorProps}\n    >\n      <span aria-hidden=\"true\">{number}</span>\n      <span className=\"sr-only\">\n        Source {number}: {source.title}\n      </span>\n    </a>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "ai",
    "citations",
    "sources",
    "agent"
  ],
  "type": "registry:ui"
}