{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "source-field-list",
  "title": "Source field list",
  "description": "A field list that drives source-field interaction: hover previews the field location in the viewer, click selects it.",
  "registryDependencies": [
    "@retab/interactive-item-list",
    "@retab/source-field-link",
    "@retab/source-evidence",
    "@retab/utils",
    "@retab/source-indicator"
  ],
  "files": [
    {
      "path": "registry/new-york-v4/ui/source-field-list.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { Source } from \"@/lib/document-source\";\nimport { cn } from \"@/lib/utils\";\nimport type { SourceFieldLink } from \"@/components/ui/source-field-link\";\n\nimport { InteractiveItemList } from \"./interactive-item-list\";\nimport { SourceIndicator } from \"./source-indicator\";\nimport {\n  sourceFieldToEvidenceItem,\n  type SourceEvidenceField,\n  type SourceEvidenceItem,\n} from \"./source-evidence\";\n\nexport interface SourceField extends Omit<SourceEvidenceField, \"source\"> {\n  /** Join key used by the source field link for hover, selection, and navigation. */\n  key: string;\n  label: string;\n  value: React.ReactNode;\n  /** Optional small hint under the value (e.g. \"Page 2\", \"Line 14\", \"Sheet 1 · B7\"). */\n  hint?: string;\n  source?: Source | null;\n}\n\n/**\n * A simple field list that drives source-field interaction: hovering previews\n * the field location in the viewer, clicking selects it.\n */\nexport function SourceFieldList({\n  fields,\n  link,\n  title = \"Extracted fields\",\n  className,\n}: {\n  fields: SourceField[];\n  link: SourceFieldLink;\n  title?: string;\n  className?: string;\n}) {\n  const titleId = React.useId();\n  const evidenceItems = React.useMemo(\n    () => fields.map(sourceFieldToEvidenceItem),\n    [fields],\n  );\n\n  return (\n    <div\n      aria-labelledby={titleId}\n      data-slot=\"source-field-list\"\n      className={cn(\"flex min-h-0 flex-1 flex-col\", className)}\n    >\n      <div className=\"flex h-10 flex-shrink-0 items-center border-b px-4\">\n        <h2 id={titleId} className=\"sr-only\">\n          {title}\n        </h2>\n        <SourceIndicator\n          path={link.activeSourcePath}\n          className=\"min-h-0 flex-1 px-0 py-0\"\n        />\n      </div>\n      <InteractiveItemList\n        aria-label={title}\n        activeItemId={link.activeSourcePath}\n        emptyLabel=\"No fields.\"\n        items={evidenceItems}\n        onActivateItem={(item) => link.selectSourcePath?.(item.id)}\n        onClearPreview={() => link.onSourceHover(null)}\n        onPreviewItem={(item) => link.onSourceHover(item.id)}\n        renderItem={(item, state) => (\n          <SourceFieldRow\n            item={item}\n            isActive={state.isActive}\n            isDisabled={state.isDisabled}\n          />\n        )}\n      />\n    </div>\n  );\n}\n\nfunction SourceFieldRow({\n  isActive,\n  isDisabled,\n  item,\n}: {\n  isActive: boolean;\n  isDisabled: boolean;\n  item: SourceEvidenceItem;\n}) {\n  const { hint, label, value } = item.payload;\n\n  return (\n    <span\n      className={cn(\n        \"flex flex-col gap-0.5 rounded-md border px-3 py-2 text-left transition-colors\",\n        isActive\n          ? \"border-primary/40 bg-primary/5\"\n          : \"hover:bg-muted/60 border-transparent\",\n        isDisabled && \"hover:bg-transparent\",\n      )}\n    >\n      <span className=\"text-muted-foreground text-xs\">{label}</span>\n      <span className=\"text-sm tabular-nums\">{value}</span>\n      {hint ? (\n        <span className=\"text-muted-foreground/70 text-[11px]\">{hint}</span>\n      ) : null}\n      {item.anchor.status === \"invalid\" ? (\n        <span className=\"text-destructive text-[11px]\">\n          {item.anchor.reason}\n        </span>\n      ) : null}\n    </span>\n  );\n}\n",
      "type": "registry:ui",
      "target": "@ui/source-field-list.tsx"
    }
  ],
  "type": "registry:ui"
}