{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "xlsx-source",
  "title": "Excel source adapter",
  "description": "Bridges the document-source model to the XLSX viewer: xlsxAnchorToTarget and sourceToXlsxCell for spreadsheet_cell anchors.",
  "registryDependencies": [
    "@retab/xlsx-viewer",
    "@retab/document-source"
  ],
  "files": [
    {
      "path": "registry/new-york-v4/ui/xlsx-source.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\n\nimport type { Source, SourceAnchor } from \"@/lib/document-source\";\nimport type { XlsxViewerHandle } from \"@/components/ui/xlsx-viewer\";\n\nexport interface SourceTarget {\n  scrollTo?: (source: Source, options: { behavior: ScrollBehavior }) => void;\n}\n\n/** Spreadsheet column letter → 0-based index (\"A\" → 0, \"B\" → 1, \"AA\" → 26). */\nexport function spreadsheetColumnToIndex(letter: string): number | null {\n  if (!/^[A-Za-z]+$/.test(letter)) return null;\n  let n = 0;\n  for (const ch of letter.toUpperCase()) {\n    n = n * 26 + (ch.charCodeAt(0) - 64);\n    if (!Number.isSafeInteger(n)) return null;\n  }\n  return n - 1;\n}\n\n/**\n * A `spreadsheet_cell` anchor to the viewer's public compatibility coordinates.\n * Internals convert this shape to `{ sheetIndex, rowIndex, columnIndex }`.\n */\nexport function xlsxAnchorToTarget(\n  anchor: SourceAnchor,\n): { sheet: number; row: number; col: number } | undefined {\n  if (anchor.kind === \"spreadsheet_cell\") {\n    const col = spreadsheetColumnToIndex(anchor.column);\n    if (\n      col == null ||\n      !Number.isSafeInteger(anchor.sheet_index) ||\n      anchor.sheet_index < 0 ||\n      !Number.isSafeInteger(anchor.row) ||\n      anchor.row < 1\n    ) {\n      return undefined;\n    }\n    return {\n      sheet: anchor.sheet_index,\n      row: anchor.row - 1,\n      col,\n    };\n  }\n  return undefined;\n}\n\n/** A stable source target over an `XlsxViewer` ref. */\nexport function useXlsxSourceTarget(\n  viewerRef: React.RefObject<XlsxViewerHandle | null>,\n): SourceTarget {\n  return React.useMemo<SourceTarget>(\n    () => ({\n      scrollTo: (source: Source, options) => {\n        const target = xlsxAnchorToTarget(source.anchor);\n        if (target) {\n          viewerRef.current?.scrollToCell(\n            target.sheet,\n            target.row,\n            target.col,\n            options,\n          );\n        }\n      },\n    }),\n    [viewerRef],\n  );\n}\n\n/**\n * The public compatibility `activeCell` prop for `XlsxViewer` derived from a\n * source.\n */\nexport function sourceToXlsxCell(\n  source: Source | undefined,\n): { sheet: number; row: number; col: number } | null {\n  return source ? xlsxAnchorToTarget(source.anchor) || null : null;\n}\n",
      "type": "registry:ui",
      "target": "@ui/xlsx-source.tsx"
    }
  ],
  "type": "registry:ui"
}