{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "docx-sources-block",
  "title": "DOCX Sources",
  "description": "Values extracted from a Word document linked back to where they came from — hover to highlight the text and scroll to it.",
  "registryDependencies": [
    "@retab/docx-viewer",
    "@retab/docx-source",
    "@retab/document-source",
    "@retab/segmented-document",
    "@retab/source-segmented-document",
    "@retab/source-field-list",
    "@retab/source-field-link",
    "@retab/source-indicator"
  ],
  "files": [
    {
      "path": "registry/new-york-v4/blocks/docx-sources-block.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { Source } from \"@/lib/document-source\";\nimport {\n  sourceToDocxHighlight,\n  useDocxSourceTarget,\n} from \"@/components/ui/docx-source\";\nimport { DocxViewer, type DocxViewerHandle } from \"@/components/ui/docx-viewer\";\nimport {\n  FileViewer,\n  FileViewerContent,\n  FileViewerHeader,\n  FileViewerTitle,\n  FileViewerProvider,\n  FileViewerSidebar,\n  FileViewerSidebarContent,\n  FileViewerInset,\n  FileViewerControls,\n  FileViewerViewport,\n} from \"@/components/ui/file-viewer\";\nimport { SegmentedDocumentProvider } from \"@/components/ui/segmented-document-provider\";\nimport { useSegmentedSourceFieldLink } from \"@/components/ui/source-field-link\";\nimport {\n  SourceFieldList,\n  type SourceField,\n} from \"@/components/ui/source-field-list\";\nimport { createSourcesSegmentedDocumentModel } from \"@/components/ui/source-segmented-document-model\";\nimport docxSample from \"@/components/viewers/sample-data/docx-sources.json\";\n\nconst DOCX_URL = \"/samples/quarterly-business-review.docx\";\nconst DOCX_SOURCE = {\n  kind: \"url\" as const,\n  url: DOCX_URL,\n  fileName: \"quarterly-business-review.docx\",\n};\n\ntype DocxField = SourceField & { source: Source };\n\n/** A short locator hint per anchor kind, matching the other source blocks. */\nfunction hintFor(source: Source): string | undefined {\n  const a = source.anchor;\n  if (a.kind === \"docx_text_span\") return `¶ ${a.paragraph + 1}`;\n  if (a.kind === \"docx_table_cell\")\n    return `Table ${a.table + 1} · R${a.row + 1}C${a.column + 1}`;\n  return undefined;\n}\n\nconst FIELDS = (docxSample as DocxField[]).map((field) => ({\n  ...field,\n  hint: hintFor(field.source),\n}));\nconst FIELD_BY_KEY = new Map(FIELDS.map((field) => [field.key, field]));\nconst SEGMENTED_DOCUMENT = createSourcesSegmentedDocumentModel(\n  FIELDS.map((field) => ({\n    id: field.key,\n    label: field.label,\n    source: field.source,\n  })),\n);\n\n/**\n * DOCX sources block — values extracted from a Word document, linked to where\n * they came from. Hovering a field highlights its text in the document and\n * scrolls to it. Segmented source interaction owns preview/selection while the\n * DOCX source adapter owns rendered-document target navigation.\n */\nexport function DocxSourcesBlock() {\n  const viewerRef = React.useRef<DocxViewerHandle>(null);\n\n  return (\n    <SegmentedDocumentProvider model={SEGMENTED_DOCUMENT}>\n      <DocxSourcesContent viewerRef={viewerRef} />\n    </SegmentedDocumentProvider>\n  );\n}\n\nfunction DocxSourcesContent({\n  viewerRef,\n}: {\n  viewerRef: React.RefObject<DocxViewerHandle | null>;\n}) {\n  const target = useDocxSourceTarget(viewerRef);\n  const segmentedLink = useSegmentedSourceFieldLink({\n    initialSourcePath: FIELDS[0]?.key,\n  });\n  const link = useTargetedSourceFieldLink({\n    fieldByKey: FIELD_BY_KEY,\n    link: segmentedLink,\n    target,\n  });\n  const activeSource = link.activeSourcePath\n    ? FIELD_BY_KEY.get(link.activeSourcePath)?.source\n    : undefined;\n  const highlight = sourceToDocxHighlight(activeSource);\n\n  return (\n    <FileViewerProvider source={DOCX_SOURCE} defaultSidebarOpen>\n      <FileViewer\n        className=\"bg-background h-full min-h-[680px]\"\n       \n      >\n        <FileViewerHeader>\n            <FileViewerTitle />\n            <FileViewerControls />\n        </FileViewerHeader>\n        <FileViewerContent>\n          <FileViewerInset>\n            <FileViewerViewport>\n              <DocxViewer\n                ref={viewerRef}\n                source={DOCX_SOURCE}\n                bare\n                className=\"h-full\"\n                controls={false}\n                highlight={highlight}\n              />\n            </FileViewerViewport>\n          </FileViewerInset>\n          <FileViewerSidebar\n            aria-label=\"Source fields\"\n            side=\"right\"\n            collapsible=\"none\"\n            width=\"360px\"\n            className=\"border-l\"\n          >\n            <FileViewerSidebarContent>\n              <SourceFieldList fields={FIELDS} link={link} />\n            </FileViewerSidebarContent>\n          </FileViewerSidebar>\n        </FileViewerContent>\n      </FileViewer>\n    </FileViewerProvider>\n  );\n}\n\nfunction useTargetedSourceFieldLink({\n  fieldByKey,\n  link,\n  target,\n}: {\n  fieldByKey: ReadonlyMap<string, DocxField>;\n  link: ReturnType<typeof useSegmentedSourceFieldLink>;\n  target: ReturnType<typeof useDocxSourceTarget>;\n}) {\n  const scrollToField = React.useCallback(\n    (path: string, behavior: ScrollBehavior) => {\n      const source = fieldByKey.get(path)?.source;\n      if (source) target.scrollTo?.(source, { behavior });\n    },\n    [fieldByKey, target],\n  );\n  const onSourceHover = React.useCallback(\n    (path: string | null) => {\n      link.onSourceHover(path);\n      if (path) scrollToField(path, \"auto\");\n    },\n    [link, scrollToField],\n  );\n  const selectSourcePath = React.useCallback(\n    (path: string) => {\n      link.selectSourcePath?.(path);\n      scrollToField(path, \"smooth\");\n    },\n    [link, scrollToField],\n  );\n\n  return React.useMemo(\n    () => ({\n      ...link,\n      onSourceHover,\n      selectSourcePath,\n    }),\n    [link, onSourceHover, selectSourcePath],\n  );\n}\n",
      "type": "registry:component",
      "target": "@components/blocks/docx-sources-block.tsx"
    },
    {
      "path": "components/viewers/sample-data/docx-sources.json",
      "content": "[\n  {\n    \"key\": \"title\",\n    \"label\": \"Report title\",\n    \"value\": \"Quarterly Business Review\",\n    \"source\": {\n      \"content\": \"Quarterly Business Review\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 0 }\n    }\n  },\n  {\n    \"key\": \"fiscalYear\",\n    \"label\": \"Fiscal year\",\n    \"value\": \"FY2026\",\n    \"source\": {\n      \"content\": \"Fiscal Year 2026 — Consolidated Report\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 1 }\n    }\n  },\n  {\n    \"key\": \"totalPages\",\n    \"label\": \"Total pages\",\n    \"value\": \"25\",\n    \"source\": {\n      \"content\": \"Total pages: 25\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 3 }\n    }\n  },\n  {\n    \"key\": \"execSummarySection\",\n    \"label\": \"Executive summary section\",\n    \"value\": \"Executive Summary\",\n    \"source\": {\n      \"content\": \"1. Executive Summary\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 5 }\n    }\n  },\n  {\n    \"key\": \"marketOverviewSection\",\n    \"label\": \"Market overview section\",\n    \"value\": \"Market Overview\",\n    \"source\": {\n      \"content\": \"2. Market Overview\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 12 }\n    }\n  },\n  {\n    \"key\": \"revenueSection\",\n    \"label\": \"Revenue section\",\n    \"value\": \"Revenue Analysis\",\n    \"source\": {\n      \"content\": \"3. Revenue Analysis\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 19 }\n    }\n  },\n  {\n    \"key\": \"costStructureSection\",\n    \"label\": \"Cost structure section\",\n    \"value\": \"Cost Structure\",\n    \"source\": {\n      \"content\": \"4. Cost Structure\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 26 }\n    }\n  },\n  {\n    \"key\": \"operatingMarginsSection\",\n    \"label\": \"Operating margins section\",\n    \"value\": \"Operating Margins\",\n    \"source\": {\n      \"content\": \"5. Operating Margins\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 33 }\n    }\n  },\n  {\n    \"key\": \"segmentPerformanceSection\",\n    \"label\": \"Segment performance section\",\n    \"value\": \"Segment Performance\",\n    \"source\": {\n      \"content\": \"6. Segment Performance\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 40 }\n    }\n  },\n  {\n    \"key\": \"cashFlowSection\",\n    \"label\": \"Cash flow section\",\n    \"value\": \"Cash Flow\",\n    \"source\": {\n      \"content\": \"11. Cash Flow\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 75 }\n    }\n  },\n  {\n    \"key\": \"balanceSheetSection\",\n    \"label\": \"Balance sheet section\",\n    \"value\": \"Balance Sheet Review\",\n    \"source\": {\n      \"content\": \"12. Balance Sheet Review\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 82 }\n    }\n  },\n  {\n    \"key\": \"riskSection\",\n    \"label\": \"Risk section\",\n    \"value\": \"Risk Factors\",\n    \"source\": {\n      \"content\": \"14. Risk Factors\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 96 }\n    }\n  },\n  {\n    \"key\": \"governanceSection\",\n    \"label\": \"Governance section\",\n    \"value\": \"Governance\",\n    \"source\": {\n      \"content\": \"19. Governance\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 131 }\n    }\n  },\n  {\n    \"key\": \"outlookSection\",\n    \"label\": \"Outlook section\",\n    \"value\": \"Outlook & Guidance\",\n    \"source\": {\n      \"content\": \"20. Outlook & Guidance\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 138 }\n    }\n  },\n  {\n    \"key\": \"methodologyAppendix\",\n    \"label\": \"Methodology appendix\",\n    \"value\": \"Appendix A: Methodology\",\n    \"source\": {\n      \"content\": \"23. Appendix A: Methodology\",\n      \"anchor\": { \"kind\": \"docx_text_span\", \"paragraph\": 159 }\n    }\n  }\n]\n",
      "type": "registry:file",
      "target": "@components/viewers/sample-data/docx-sources.json"
    }
  ],
  "categories": [
    "primitives"
  ],
  "type": "registry:block"
}