@lembryo/voxsheet 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/hooks/useChunks.ts","../src/hooks/useEditBuffer.ts","../src/core/format.ts","../src/core/range.ts","../src/core/clipboard.ts","../src/icons.tsx","../src/labels.ts","../src/platform.ts","../src/VoxSheet.tsx"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from \"react\"\nimport type { CellValue, Column, FetchRowsFn, FilterSpec, SortSpec } from \"../types\"\n\nconst CHUNK = 200\nconst FETCH_DEBOUNCE_MS = 80\n\nexport type VisibleRow = { values: CellValue[]; id: number; ordinal: number }\n\nexport type ChunkStatus = \"idle\" | \"loading\" | \"error\"\n\ntype Params = {\n fetchRows: FetchRowsFn\n totalRows: number\n columns: Column[]\n sort: SortSpec[]\n filters: FilterSpec[]\n search: string | undefined\n queryKey: unknown\n frozenRows: number\n startRow: number\n endRow: number\n onError?: (error: unknown, ctx: { phase: \"fetch\" | \"commit\" }) => void\n}\n\n/**\n * ビューポート範囲をチャンク単位で取得・キャッシュするフック。\n * - sort/filters/search/columns/queryKey の変化でキャッシュを無効化して再取得する。\n * - 取得は debounce し、各取得は AbortSignal で中断可能。\n */\nexport const useChunks = (params: Params) => {\n const {\n fetchRows,\n totalRows,\n columns,\n sort,\n filters,\n search,\n queryKey,\n frozenRows,\n startRow,\n endRow,\n onError,\n } = params\n\n const cacheRef = useRef<Map<number, VisibleRow[]>>(new Map())\n const pendingRef = useRef<Set<number>>(new Set())\n const controllersRef = useRef<Set<AbortController>>(new Set())\n const [rows, setRows] = useState<Map<number, VisibleRow>>(new Map())\n const [total, setTotal] = useState(totalRows)\n const [status, setStatus] = useState<ChunkStatus>(\"idle\")\n\n // 無効化キー(controlled なドメイン状態に依存)\n const invalidationKey = JSON.stringify({\n columns: columns.map((c) => c.name),\n sort,\n filters,\n search: search ?? null,\n })\n\n const reset = useCallback(() => {\n for (const controller of controllersRef.current) controller.abort()\n controllersRef.current.clear()\n cacheRef.current.clear()\n pendingRef.current.clear()\n setRows(new Map())\n }, [])\n\n // 無効化(controlled 状態 / queryKey の変化)\n useEffect(() => {\n reset()\n }, [invalidationKey, queryKey, reset])\n\n const rebuildVisible = useCallback(() => {\n const next = new Map<number, VisibleRow>()\n for (const [offset, chunk] of cacheRef.current) {\n chunk.forEach((row, i) => next.set(offset + i, row))\n }\n setRows(next)\n }, [])\n\n const loadChunks = useCallback(async () => {\n const effectiveTotal = total > 0 ? total : totalRows\n const offsets: number[] = []\n if (frozenRows > 0) offsets.push(0)\n const from = Math.floor(startRow / CHUNK) * CHUNK\n const to = Math.ceil(endRow / CHUNK) * CHUNK\n for (let o = from; o < to; o += CHUNK) {\n if (o >= 0) offsets.push(o)\n }\n\n const targets = offsets.filter(\n (o) => o < effectiveTotal && !cacheRef.current.has(o) && !pendingRef.current.has(o),\n )\n if (targets.length === 0) return\n\n setStatus(\"loading\")\n const jobs = targets.map(async (offset) => {\n pendingRef.current.add(offset)\n const controller = new AbortController()\n controllersRef.current.add(controller)\n // 常に 1 チャンク分を要求する。総数が未確定(初回や stale)でも\n // チャンク満杯を取りに行き、サーバ側が末尾でクランプして返す。\n // ここで effectiveTotal でクランプすると、総数が小さく見える初回に\n // limit が極端に小さくなり(例: 1)、そのチャンクが過小取得のまま\n // キャッシュされて二度と取り直されない不具合になる。\n const limit = CHUNK\n try {\n const result = await fetchRows(\n { offset, limit, sort, filters, search },\n controller.signal,\n )\n const chunk: VisibleRow[] = result.data.map((values, i) => ({\n values,\n id: result.ids[i] ?? offset + i + 1,\n ordinal: result.ordinals[i] ?? offset + i + 1,\n }))\n cacheRef.current.set(offset, chunk)\n if (typeof result.total === \"number\") setTotal(result.total)\n } catch (error) {\n if (!controller.signal.aborted) {\n onError?.(error, { phase: \"fetch\" })\n setStatus(\"error\")\n }\n } finally {\n pendingRef.current.delete(offset)\n controllersRef.current.delete(controller)\n }\n })\n\n await Promise.all(jobs)\n rebuildVisible()\n setStatus((prev) => (prev === \"error\" ? prev : \"idle\"))\n }, [\n fetchRows,\n sort,\n filters,\n search,\n startRow,\n endRow,\n frozenRows,\n total,\n totalRows,\n onError,\n rebuildVisible,\n ])\n\n // 範囲変化に対する debounce 付きフェッチ\n useEffect(() => {\n const timer = setTimeout(() => {\n void loadChunks()\n }, FETCH_DEBOUNCE_MS)\n return () => clearTimeout(timer)\n }, [loadChunks])\n\n // totalRows prop の変化を反映(フィルタ解除等)\n useEffect(() => {\n setTotal(totalRows)\n }, [totalRows])\n\n const invalidate = useCallback(() => {\n reset()\n void loadChunks()\n }, [reset, loadChunks])\n\n return { rows, total: total > 0 ? total : totalRows, status, invalidate }\n}\n","import { useCallback, useMemo, useRef, useState } from \"react\"\nimport type { CellEdit, CellValue } from \"../types\"\n\nconst MAX_UNDO = 200\n\nconst keyOf = (row: number, col: number): string => `${row}:${col}`\n\ntype Params = {\n onCellChange?: (edit: CellEdit) => void\n onDirtyChange?: (hasChanges: boolean) => void\n}\n\n/**\n * ローカル編集レイヤー。未コミットの編集を保持し、Undo/Redo と dirty 追跡を行う。\n * 永続化はしない(ホストが getLocalEdits を取り出してコミットする)。\n */\nexport const useEditBuffer = ({ onCellChange, onDirtyChange }: Params) => {\n const editsRef = useRef<Map<string, CellValue>>(new Map())\n const originalRef = useRef<Map<string, CellValue>>(new Map())\n const undoRef = useRef<CellEdit[][]>([])\n const redoRef = useRef<CellEdit[][]>([])\n // 編集の変化で再描画させるためのバージョン\n const [version, setVersion] = useState(0)\n\n const notifyDirty = useCallback(() => {\n onDirtyChange?.(editsRef.current.size > 0)\n }, [onDirtyChange])\n\n // 1 セルへ値を適用する(元値に戻れば dirty 解除)。\n const applyValue = useCallback(\n (\n row: number,\n col: number,\n value: CellValue,\n getBase: (r: number, c: number) => CellValue,\n ) => {\n const key = keyOf(row, col)\n if (!originalRef.current.has(key)) {\n originalRef.current.set(key, getBase(row, col))\n }\n const original = originalRef.current.get(key) ?? null\n if (value === original) {\n editsRef.current.delete(key)\n originalRef.current.delete(key)\n } else {\n editsRef.current.set(key, value)\n }\n onCellChange?.({ row, col, oldValue: original, newValue: value })\n },\n [onCellChange],\n )\n\n /** 1 操作(複数セル)を適用し、Undo スタックに 1 アクションとして積む。 */\n const applyEdits = useCallback(\n (edits: CellEdit[], getBase: (r: number, c: number) => CellValue) => {\n if (edits.length === 0) return\n for (const edit of edits) applyValue(edit.row, edit.col, edit.newValue, getBase)\n undoRef.current.push(edits)\n if (undoRef.current.length > MAX_UNDO) undoRef.current.shift()\n redoRef.current = []\n setVersion((v) => v + 1)\n notifyDirty()\n },\n [applyValue, notifyDirty],\n )\n\n const noBase = useCallback((): CellValue => null, [])\n\n const undo = useCallback(() => {\n const action = undoRef.current.pop()\n if (!action) return\n for (let i = action.length - 1; i >= 0; i--) {\n const edit = action[i]!\n applyValue(edit.row, edit.col, edit.oldValue, noBase)\n }\n redoRef.current.push(action)\n setVersion((v) => v + 1)\n notifyDirty()\n }, [applyValue, noBase, notifyDirty])\n\n const redo = useCallback(() => {\n const action = redoRef.current.pop()\n if (!action) return\n for (const edit of action) applyValue(edit.row, edit.col, edit.newValue, noBase)\n undoRef.current.push(action)\n setVersion((v) => v + 1)\n notifyDirty()\n }, [applyValue, noBase, notifyDirty])\n\n const getEditedValue = useCallback((row: number, col: number): CellValue | undefined => {\n const key = keyOf(row, col)\n return editsRef.current.has(key) ? editsRef.current.get(key) : undefined\n }, [])\n\n const isDirty = useCallback(\n (row: number, col: number): boolean => editsRef.current.has(keyOf(row, col)),\n [],\n )\n\n const getLocalEdits = useCallback((): CellEdit[] => {\n const result: CellEdit[] = []\n for (const [key, newValue] of editsRef.current) {\n const [rs, cs] = key.split(\":\")\n result.push({\n row: Number(rs),\n col: Number(cs),\n oldValue: originalRef.current.get(key) ?? null,\n newValue,\n })\n }\n return result\n }, [])\n\n const clear = useCallback(() => {\n editsRef.current.clear()\n originalRef.current.clear()\n undoRef.current = []\n redoRef.current = []\n setVersion((v) => v + 1)\n onDirtyChange?.(false)\n }, [onDirtyChange])\n\n const canUndo = useCallback(() => undoRef.current.length > 0, [])\n const canRedo = useCallback(() => redoRef.current.length > 0, [])\n\n // 返り値の identity を安定させる。毎レンダーで新オブジェクトを返すと、これに依存する\n // getRawValue や選択統計の effect が毎レンダー再実行され、無限ループ\n //(Maximum update depth exceeded)の原因になる。\n return useMemo(\n () => ({\n version,\n applyEdits,\n undo,\n redo,\n getEditedValue,\n isDirty,\n getLocalEdits,\n clear,\n canUndo,\n canRedo,\n }),\n [\n version,\n applyEdits,\n undo,\n redo,\n getEditedValue,\n isDirty,\n getLocalEdits,\n clear,\n canUndo,\n canRedo,\n ],\n )\n}\n","import type { CellValue, Column, ColumnAlign, ColumnType } from '../types';\n\n/** 型から既定の水平アラインを導出する。 */\nexport const defaultAlign = (type: ColumnType | undefined): ColumnAlign => {\n if (type === \"number\") return \"right\"\n if (type === \"date\") return \"right\"\n if (type === \"boolean\") return \"center\"\n return \"left\"\n}\n\n/** epoch ミリ秒(number)または ISO 文字列を Date に変換する(失敗時 null)。 */\nconst toDate = (value: CellValue): Date | null => {\n if (value === null || value === \"\") return null\n const d = typeof value === \"number\" ? new Date(value) : new Date(String(value))\n return Number.isNaN(d.getTime()) ? null : d\n}\n\n/**\n * セル値を表示文字列に整形する。column.format > 型別既定 の順で解決する。\n */\nexport const formatCellValue = (value: CellValue, column: Column, row: number): string => {\n const format = column.format\n if (typeof format === \"function\") return format(value, { column, row })\n if (value === null) return \"\"\n\n if (format && format.kind === \"number\" && typeof value === \"number\") {\n return new Intl.NumberFormat(undefined, format.options).format(value)\n }\n if (format && format.kind === \"date\") {\n const d = toDate(value)\n if (d) return new Intl.DateTimeFormat(undefined, format.options).format(d)\n }\n\n switch (column.type) {\n case \"boolean\":\n return value ? \"✓\" : \"\"\n case \"date\": {\n const d = toDate(value)\n // 既定は YYYY-MM-DD(ISO のまま表示できる場合はそれを優先)\n if (typeof value === \"string\") return value\n return d ? d.toISOString().slice(0, 10) : \"\"\n }\n case \"number\":\n return typeof value === \"number\" ? String(value) : String(value)\n default:\n return String(value)\n }\n}\n\n/**\n * 編集の生入力文字列を列の型に応じた CellValue へパースする。\n * パースできない場合は raw(文字列)を返し、検証はホスト/列 validate に委ねる。\n */\nexport const parseInputValue = (raw: string, type: ColumnType | undefined): CellValue => {\n if (raw === \"\") return type === \"string\" || type === undefined ? \"\" : null\n switch (type) {\n case \"number\": {\n const n = Number(raw.replace(/,/g, \"\"))\n return Number.isNaN(n) ? raw : n\n }\n case \"boolean\": {\n const lower = raw.trim().toLowerCase()\n if ([\"true\", \"1\", \"yes\", \"y\", \"✓\"].includes(lower)) return true\n if ([\"false\", \"0\", \"no\", \"n\", \"\"].includes(lower)) return false\n return raw\n }\n case \"date\":\n // 日付は ISO 文字列のまま保持する(解釈は表示側)。\n return raw\n default:\n return raw\n }\n}\n\n/** 数値として解釈できる場合に number を返す(統計用)。 */\nexport const numericValue = (value: CellValue): number | null => {\n if (typeof value === \"number\") return value\n if (typeof value === \"string\" && value.trim() !== \"\") {\n const n = Number(value.replace(/,/g, \"\"))\n return Number.isNaN(n) ? null : n\n }\n return null\n}\n","import type { Selection } from \"../types\"\n\n/** 正規化済みの矩形(r1<=r2, c1<=c2)。 */\nexport type Rect = { r1: number; r2: number; c1: number; c2: number }\n\nexport const normalizeRect = (sel: Selection): Rect => ({\n r1: Math.min(sel.start.row, sel.end.row),\n r2: Math.max(sel.start.row, sel.end.row),\n c1: Math.min(sel.start.col, sel.end.col),\n c2: Math.max(sel.start.col, sel.end.col),\n})\n\nexport const normalizeRects = (selections: Selection[]): Rect[] => selections.map(normalizeRect)\n\nexport const rectContains = (rect: Rect, row: number, col: number): boolean =>\n row >= rect.r1 && row <= rect.r2 && col >= rect.c1 && col <= rect.c2\n\nexport const cellInRects = (rects: Rect[], row: number, col: number): boolean =>\n rects.some((rect) => rectContains(rect, row, col))\n\n/** 矩形が「行全体(全列を含む)」かどうか。 */\nexport const isFullRowRect = (rect: Rect, columnCount: number): boolean =>\n rect.c1 === 0 && rect.c2 === columnCount - 1\n\n/** 矩形が「列全体(全行を含む)」かどうか。 */\nexport const isFullColRect = (rect: Rect, totalRows: number): boolean =>\n rect.r1 === 0 && rect.r2 === totalRows - 1\n\n/** レンジ群に含まれる行の和集合(昇順)。 */\nexport const rowsInRects = (rects: Rect[]): number[] => {\n const set = new Set<number>()\n for (const rect of rects) {\n for (let r = rect.r1; r <= rect.r2; r++) set.add(r)\n }\n return Array.from(set).sort((a, b) => a - b)\n}\n\n/** レンジ群の総セル数(未取得行も含む論理的なセル数)。 */\nexport const totalCellCount = (rects: Rect[]): number =>\n rects.reduce((sum, rect) => sum + (rect.r2 - rect.r1 + 1) * (rect.c2 - rect.c1 + 1), 0)\n","import type { Rect } from \"./range\"\n\n/** TSV の 1 セルをエスケープする(タブ/改行/引用符を含む場合はダブルクオートで囲む)。 */\nconst escapeCell = (text: string): string => {\n if (/[\\t\\n\\r\"]/.test(text)) {\n return `\"${text.replace(/\"/g, '\"\"')}\"`\n }\n return text\n}\n\n/**\n * 選択レンジ群から TSV(Excel 互換タブ区切り)テキストを生成する。\n * - 複数レンジで行範囲が一致 → 列方向に連結\n * - 列範囲が一致 → 行方向に連結\n * - それ以外 → アクティブレンジ(末尾)のみ\n */\nexport const buildTsv = (rects: Rect[], getValue: (row: number, col: number) => string): string => {\n if (rects.length === 0) return \"\"\n\n const rectToLines = (rect: Rect): string[] => {\n const lines: string[] = []\n for (let r = rect.r1; r <= rect.r2; r++) {\n const cells: string[] = []\n for (let c = rect.c1; c <= rect.c2; c++) cells.push(escapeCell(getValue(r, c)))\n lines.push(cells.join(\"\\t\"))\n }\n return lines\n }\n\n if (rects.length > 1) {\n const first = rects[0]!\n const sameRows = rects.every((rect) => rect.r1 === first.r1 && rect.r2 === first.r2)\n if (sameRows) {\n const sorted = [...rects].sort((a, b) => a.c1 - b.c1)\n const lines: string[] = []\n for (let r = first.r1; r <= first.r2; r++) {\n const cells: string[] = []\n for (const rect of sorted) {\n for (let c = rect.c1; c <= rect.c2; c++) cells.push(escapeCell(getValue(r, c)))\n }\n lines.push(cells.join(\"\\t\"))\n }\n return lines.join(\"\\n\")\n }\n const sameCols = rects.every((rect) => rect.c1 === first.c1 && rect.c2 === first.c2)\n if (sameCols) {\n const sorted = [...rects].sort((a, b) => a.r1 - b.r1)\n return sorted.flatMap(rectToLines).join(\"\\n\")\n }\n }\n\n return rectToLines(rects[rects.length - 1]!).join(\"\\n\")\n}\n\n/**\n * TSV/Excel 形式のクリップボードテキストを 2 次元配列にパースする。\n * ダブルクオートで囲まれたセル内のタブ・改行・\"\" を正しく扱う。\n */\nexport const parseTsv = (text: string): string[][] => {\n const rows: string[][] = []\n let row: string[] = []\n let cell = \"\"\n let inQuotes = false\n let i = 0\n\n const pushCell = () => {\n row.push(cell)\n cell = \"\"\n }\n const pushRow = () => {\n pushCell()\n rows.push(row)\n row = []\n }\n\n while (i < text.length) {\n const ch = text[i]!\n if (inQuotes) {\n if (ch === '\"') {\n if (text[i + 1] === '\"') {\n cell += '\"'\n i += 2\n continue\n }\n inQuotes = false\n i++\n continue\n }\n cell += ch\n i++\n continue\n }\n if (ch === '\"') {\n inQuotes = true\n i++\n continue\n }\n if (ch === \"\\t\") {\n pushCell()\n i++\n continue\n }\n if (ch === \"\\n\" || ch === \"\\r\") {\n // \\r\\n はまとめて 1 改行として扱う\n if (ch === \"\\r\" && text[i + 1] === \"\\n\") i++\n pushRow()\n i++\n continue\n }\n cell += ch\n i++\n }\n // 末尾セル/行の確定(末尾が空でない場合のみ行を作る)\n if (cell !== \"\" || row.length > 0) pushRow()\n return rows\n}\n","import type { IconName, IconProps, IconRenderer, Icons } from \"./types\"\n\n/**\n * 既定アイコン(最小インライン SVG)。FontAwesome 等の外部依存を持たない。\n * `icons` prop で個別に差し替えられる。\n */\n\nconst svgProps = (props: IconProps) => ({\n width: props.size ?? 14,\n height: props.size ?? 14,\n viewBox: \"0 0 16 16\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.6,\n strokeLinecap: \"round\" as const,\n strokeLinejoin: \"round\" as const,\n className: props.className,\n \"aria-hidden\": true,\n})\n\nconst SortAscending: IconRenderer = (props) => (\n <svg {...svgProps(props)}>\n <path d=\"M8 12V4M8 4l-3 3M8 4l3 3\" />\n </svg>\n)\n\nconst SortDescending: IconRenderer = (props) => (\n <svg {...svgProps(props)}>\n <path d=\"M8 4v8M8 12l-3-3M8 12l3-3\" />\n </svg>\n)\n\nconst SortUnsorted: IconRenderer = (props) => (\n <svg {...svgProps(props)} opacity={0.45}>\n <path d=\"M5 6l3-3 3 3M5 10l3 3 3-3\" />\n </svg>\n)\n\nconst Filter: IconRenderer = (props) => (\n <svg {...svgProps(props)}>\n <path d=\"M2.5 3.5h11l-4.2 5v4l-2.6 1.3v-5.3z\" />\n </svg>\n)\n\nconst FilterActive: IconRenderer = (props) => (\n <svg {...svgProps(props)} fill=\"currentColor\" stroke=\"none\">\n <path d=\"M2.5 3.5h11l-4.2 5v4l-2.6 1.3v-5.3z\" />\n </svg>\n)\n\nexport const DEFAULT_ICONS: Record<IconName, IconRenderer> = {\n sortAscending: SortAscending,\n sortDescending: SortDescending,\n sortUnsorted: SortUnsorted,\n filter: Filter,\n filterActive: FilterActive,\n}\n\nexport const resolveIcons = (overrides?: Icons): Record<IconName, IconRenderer> =>\n overrides ? { ...DEFAULT_ICONS, ...overrides } : DEFAULT_ICONS\n","import type { VoxLabels } from \"./types\"\n\n/** 内蔵 UI の既定文言(英語)。`labels` prop で部分上書きできる。 */\nexport const DEFAULT_LABELS: VoxLabels = {\n loading: \"Loading…\",\n empty: \"No rows\",\n contextCut: \"Cut\",\n contextCopy: \"Copy\",\n contextPaste: \"Paste\",\n contextInsertRowAbove: \"Insert row above\",\n contextInsertRowBelow: \"Insert row below\",\n contextDeleteRows: \"Delete rows\",\n contextUndo: \"Undo\",\n contextRedo: \"Redo\",\n confirmLargeCopyTitle: \"Copy a large selection\",\n confirmLargeCopyMessage: \"The selection is large and copying may take a while. Continue?\",\n confirmOk: \"OK\",\n confirmCancel: \"Cancel\",\n}\n\nexport const resolveLabels = (overrides?: Partial<VoxLabels>): VoxLabels =>\n overrides ? { ...DEFAULT_LABELS, ...overrides } : DEFAULT_LABELS\n","import type { ConfirmOptions, PlatformAdapter, ToastKind } from \"./types\"\n\n/**\n * 解決済みプラットフォーム。各メソッドは常に存在する(未指定は web 既定にフォールバック)。\n */\nexport type ResolvedPlatform = {\n readText: () => Promise<string>\n writeText: (text: string) => Promise<void>\n notify: (\n kind: ToastKind,\n message: string,\n opts?: { id?: string; durationMs?: number },\n ) => string\n confirm: (opts: ConfirmOptions) => Promise<boolean>\n saveFile: (opts: {\n suggestedName: string\n mimeType?: string\n data: string | Blob\n }) => Promise<void>\n}\n\nconst hasDom = (): boolean => typeof document !== \"undefined\"\n\n// --- 既定クリップボード(navigator.clipboard) ---\n\nconst defaultReadText = async (): Promise<string> => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n return navigator.clipboard.readText()\n }\n return \"\"\n}\n\nconst defaultWriteText = async (text: string): Promise<void> => {\n if (typeof navigator !== \"undefined\" && navigator.clipboard) {\n await navigator.clipboard.writeText(text)\n }\n}\n\n// --- 既定トースト(vox- スタイルの最小内蔵 DOM 実装) ---\n\nlet toastSeq = 0\n\nconst ensureToastContainer = (): HTMLElement | null => {\n if (!hasDom()) return null\n let el = document.querySelector<HTMLElement>(\".vox-toast-container\")\n if (!el) {\n el = document.createElement(\"div\")\n el.className = \"vox-toast-container\"\n document.body.appendChild(el)\n }\n return el\n}\n\nconst defaultNotify = (\n kind: ToastKind,\n message: string,\n opts?: { id?: string; durationMs?: number },\n): string => {\n const container = ensureToastContainer()\n const id = opts?.id ?? `vox-toast-${++toastSeq}`\n if (!container) return id\n\n let toast = document.getElementById(id)\n if (!toast) {\n toast = document.createElement(\"div\")\n toast.id = id\n container.appendChild(toast)\n }\n toast.className = `vox-toast vox-toast--${kind}`\n toast.textContent = message\n\n const duration = opts?.durationMs ?? (kind === \"loading\" ? 0 : 3000)\n if (duration > 0) {\n window.setTimeout(() => toast?.remove(), duration)\n }\n return id\n}\n\n// --- 既定確認ダイアログ(vox- スタイルの最小内蔵モーダル) ---\n\nconst defaultConfirm = (opts: ConfirmOptions): Promise<boolean> => {\n if (!hasDom()) return Promise.resolve(false)\n return new Promise<boolean>((resolve) => {\n const backdrop = document.createElement(\"div\")\n backdrop.className = \"vox-modal-backdrop\"\n\n const modal = document.createElement(\"div\")\n modal.className = \"vox-modal\"\n modal.setAttribute(\"role\", \"dialog\")\n modal.setAttribute(\"aria-modal\", \"true\")\n\n const close = (result: boolean) => {\n backdrop.remove()\n resolve(result)\n }\n\n if (opts.title) {\n const title = document.createElement(\"div\")\n title.className = \"vox-modal-title\"\n title.textContent = opts.title\n modal.appendChild(title)\n }\n const body = document.createElement(\"div\")\n body.className = \"vox-modal-body\"\n body.textContent = opts.message\n modal.appendChild(body)\n\n const footer = document.createElement(\"div\")\n footer.className = \"vox-modal-footer\"\n const cancel = document.createElement(\"button\")\n cancel.className = \"vox-btn\"\n cancel.textContent = opts.cancelLabel ?? \"Cancel\"\n cancel.onclick = () => close(false)\n const ok = document.createElement(\"button\")\n ok.className = \"vox-btn vox-btn--primary\"\n ok.textContent = opts.confirmLabel ?? \"OK\"\n ok.onclick = () => close(true)\n footer.append(cancel, ok)\n modal.appendChild(footer)\n\n backdrop.appendChild(modal)\n backdrop.onclick = (e) => {\n if (e.target === backdrop) close(false)\n }\n document.body.appendChild(backdrop)\n ok.focus()\n })\n}\n\n// --- 既定ファイル保存(ブラウザダウンロード) ---\n\nconst defaultSaveFile = async (opts: {\n suggestedName: string\n mimeType?: string\n data: string | Blob\n}): Promise<void> => {\n if (!hasDom()) return\n const blob =\n typeof opts.data === \"string\"\n ? new Blob([opts.data], { type: opts.mimeType ?? \"text/plain\" })\n : opts.data\n const url = URL.createObjectURL(blob)\n const a = document.createElement(\"a\")\n a.href = url\n a.download = opts.suggestedName\n document.body.appendChild(a)\n a.click()\n a.remove()\n URL.revokeObjectURL(url)\n}\n\n/** props の platform を web 既定とマージして解決する。 */\nexport const resolvePlatform = (platform?: PlatformAdapter): ResolvedPlatform => ({\n readText: platform?.clipboard?.readText ?? defaultReadText,\n writeText: platform?.clipboard?.writeText ?? defaultWriteText,\n notify: platform?.notify ?? defaultNotify,\n confirm: platform?.confirm ?? defaultConfirm,\n saveFile: platform?.saveFile ?? defaultSaveFile,\n})\n","import type { CSSProperties, ReactElement } from \"react\"\nimport {\n forwardRef,\n useCallback,\n useEffect,\n useImperativeHandle,\n useMemo,\n useRef,\n useState,\n} from \"react\"\nimport type {\n CellEdit,\n CellValue,\n Selection,\n SortSpec,\n VoxSheetHandle,\n VoxSheetProps,\n} from \"./types\"\nimport { useChunks } from \"./hooks/useChunks\"\nimport { useEditBuffer } from \"./hooks/useEditBuffer\"\nimport { defaultAlign, formatCellValue, numericValue, parseInputValue } from \"./core/format\"\nimport { cellInRects, normalizeRects, totalCellCount } from \"./core/range\"\nimport { buildTsv, parseTsv } from \"./core/clipboard\"\nimport { resolveIcons } from \"./icons\"\nimport { resolveLabels } from \"./labels\"\nimport { resolvePlatform } from \"./platform\"\nimport \"./styles.css\"\n\nconst DENSITY: Record<\n NonNullable<VoxSheetProps[\"density\"]>,\n { rowHeight: number; fontSize: number }\n> = {\n compact: { rowHeight: 22, fontSize: 12 },\n normal: { rowHeight: 28, fontSize: 13 },\n comfortable: { rowHeight: 34, fontSize: 15 },\n}\n\nconst ROW_HEADER_WIDTH = 52\nconst OVERSCAN = 8\nconst MIN_COL_WIDTH = 40\nconst MAX_AUTOFIT_WIDTH = 600\n/** これを超えるセル数のコピー/集計は重いので抑止する(簡易ガード)。 */\nconst HEAVY_CELL_LIMIT = 100_000\n\ntype Cell = { row: number; col: number }\n\nconst cellToInput = (value: CellValue): string => (value === null ? \"\" : String(value))\n\n/**\n * VoxSheet — DOM ベースの仮想スクロール対応スプレッドシート。\n * 連番列・選択・編集・オートフィル・ソート/フィルタのヘッダ UI を備える。\n */\nconst VoxSheetInner = (props: VoxSheetProps, ref: React.Ref<VoxSheetHandle>): ReactElement => {\n const {\n columns,\n totalRows,\n fetchRows,\n queryKey,\n density = \"normal\",\n defaultColumnWidth = 120,\n frozenRows = 0,\n theme = \"system\",\n className,\n style,\n readOnly = false,\n sort = [],\n filters = [],\n search,\n searchHighlights,\n currentSearchHit,\n renderLoading,\n renderEmpty,\n labels: labelOverrides,\n icons: iconOverrides,\n platform: platformOverride,\n onSortChange,\n onFilterButtonClick,\n onColumnResize,\n onColumnRename,\n onAddColumn,\n onCellChange,\n onDirtyChange,\n onAppendRow,\n onInsertRow,\n onDeleteRows,\n onAutoFill,\n onSelectionChange,\n onSelectionStats,\n onCellKeyDown,\n onError,\n } = props\n\n const labels = useMemo(() => resolveLabels(labelOverrides), [labelOverrides])\n const icons = useMemo(() => resolveIcons(iconOverrides), [iconOverrides])\n const platform = useMemo(() => resolvePlatform(platformOverride), [platformOverride])\n\n const rowHeight = props.rowHeight ?? DENSITY[density].rowHeight\n const fontSize = DENSITY[density].fontSize\n\n const rootRef = useRef<HTMLDivElement>(null)\n const bodyRef = useRef<HTMLDivElement>(null)\n const headerRef = useRef<HTMLDivElement>(null)\n const frozenRef = useRef<HTMLDivElement>(null)\n const [scrollTop, setScrollTop] = useState(0)\n const [viewportHeight, setViewportHeight] = useState(600)\n const [scrollbarWidth, setScrollbarWidth] = useState(0)\n\n // --- 列幅(列名キーで記憶し、リネーム後も引き継ぐ) ---\n const [colWidths, setColWidths] = useState<number[]>([])\n const widthMemoryRef = useRef<Map<string, number>>(new Map())\n const prevNamesRef = useRef<string[] | null>(null)\n useEffect(() => {\n const memory = widthMemoryRef.current\n const prev = prevNamesRef.current\n if (prev && prev.length === columns.length) {\n prev.forEach((oldName, i) => {\n const newName = columns[i]?.name\n if (newName && newName !== oldName && memory.has(oldName)) {\n memory.set(newName, memory.get(oldName)!)\n memory.delete(oldName)\n }\n })\n }\n prevNamesRef.current = columns.map((c) => c.name)\n setColWidths(columns.map((c) => memory.get(c.name) ?? c.width ?? defaultColumnWidth))\n }, [columns, defaultColumnWidth])\n\n const getColWidth = useCallback(\n (i: number): number => colWidths[i] ?? columns[i]?.width ?? defaultColumnWidth,\n [colWidths, columns, defaultColumnWidth],\n )\n // 行ヘッダ込みでの列 c の左端 px。選択枠オーバーレイの位置計算に使う。\n const colLeft = useCallback(\n (c: number): number => {\n let x = ROW_HEADER_WIDTH\n for (let i = 0; i < c; i++) x += getColWidth(i)\n return x\n },\n [getColWidth],\n )\n const applyColWidth = useCallback(\n (col: number, width: number) => {\n const w = Math.max(MIN_COL_WIDTH, Math.round(width))\n setColWidths((prev) => {\n const next = [...prev]\n next[col] = w\n return next\n })\n const name = columns[col]?.name\n if (name) widthMemoryRef.current.set(name, w)\n onColumnResize?.(col, w)\n },\n [columns, onColumnResize],\n )\n\n // --- ビューポート高さ+縦スクロールバー幅の追従 ---\n // 計測は mount 時と ResizeObserver(リサイズ時)のみに限定する。\n // 毎レンダーで計測すると、高 DPI 環境で offsetWidth/clientWidth が 1px 揺れて\n // setState → 再レンダー → 再計測… の無限ループ(Maximum update depth)になりうる。\n // スクロールバー幅はヘッダ右端の padding に反映し、横スクロール時の列ズレを補正する。\n useEffect(() => {\n const el = bodyRef.current\n if (!el) return\n const measure = () => {\n setViewportHeight(el.clientHeight)\n setScrollbarWidth(el.offsetWidth - el.clientWidth)\n }\n measure()\n const observer = new ResizeObserver(() => measure())\n observer.observe(el)\n return () => observer.disconnect()\n }, [])\n\n // --- 可視範囲 ---\n // frozenRows(先頭行の固定表示)は現状未対応。prop は受け付けるが描画には反映しない\n // (チャンク取得側へはヒントとして渡す)。固定バンドの描画は今後の実装。\n const bodyOffset = 0\n // ビューポートから必要な行範囲(+オーバースキャンの余裕)を算出する。\n // 総数が未確定でもまず取得できるよう、ここでは totalRows でクランプしない。\n // 実際の描画範囲は取得後に判明する total でクランプする(下の visibleEnd)。\n const desiredStart = Math.max(0, Math.floor(scrollTop / rowHeight) - OVERSCAN)\n const desiredEnd = Math.ceil((scrollTop + viewportHeight) / rowHeight) + OVERSCAN\n\n // --- データ取得(チャンク) ---\n const { rows, total, status, invalidate } = useChunks({\n fetchRows,\n totalRows,\n columns,\n sort,\n filters,\n search,\n queryKey,\n frozenRows,\n startRow: desiredStart,\n endRow: desiredEnd,\n onError,\n })\n\n // 描画範囲は「ビューポートの要求」と「判明している総数」の小さい方。\n // total はレスポンスの FetchResult.total で自己更新されるため、ホストが\n // totalRows を更新しなくても初回取得後に正しい行数まで広がる。\n const visibleStart = Math.min(desiredStart, Math.max(0, total - 1))\n const visibleEnd = Math.min(total, desiredEnd)\n\n // --- ローカル編集レイヤー ---\n const editBuffer = useEditBuffer({ onCellChange, onDirtyChange })\n\n const getBaseValue = useCallback(\n (r: number, c: number): CellValue => rows.get(r)?.values[c] ?? null,\n [rows],\n )\n const getRawValue = useCallback(\n (r: number, c: number): CellValue => {\n const edited = editBuffer.getEditedValue(r, c)\n return edited !== undefined ? edited : getBaseValue(r, c)\n },\n [editBuffer, getBaseValue],\n )\n const getCellText = useCallback(\n (r: number, c: number): string => {\n const col = columns[c]\n if (!col) return \"\"\n return formatCellValue(getRawValue(r, c), col, r)\n },\n [columns, getRawValue],\n )\n const applyEdits = useCallback(\n (edits: CellEdit[]) => editBuffer.applyEdits(edits, getBaseValue),\n [editBuffer, getBaseValue],\n )\n\n // --- 選択 ---\n const [selections, setSelections] = useState<Selection[]>([])\n const [activeCell, setActiveCell] = useState<Cell | null>(null)\n const selRects = useMemo(() => normalizeRects(selections), [selections])\n const selMin = selRects.length > 0 ? selRects[selRects.length - 1]! : null\n const activeRange = selections.length > 0 ? selections[selections.length - 1]! : null\n\n const setSelection = useCallback((sel: Selection | null) => {\n setSelections(sel ? [sel] : [])\n }, [])\n const updateActiveSelection = useCallback((sel: Selection) => {\n setSelections((prev) => (prev.length > 0 ? [...prev.slice(0, -1), sel] : [sel]))\n }, [])\n const addSelection = useCallback((sel: Selection) => {\n setSelections((prev) => [...prev, sel])\n }, [])\n\n const isDraggingRef = useRef(false)\n const isRowDraggingRef = useRef(false)\n const isColDraggingRef = useRef(false)\n const rowAnchorRef = useRef<number | null>(null)\n const colAnchorRef = useRef<number | null>(null)\n\n // --- 編集状態 ---\n const [editingCell, setEditingCell] = useState<Cell | null>(null)\n const [editValue, setEditValue] = useState(\"\")\n const editInputRef = useRef<HTMLInputElement>(null)\n const composingRef = useRef(false)\n\n // --- ヘッダ名編集 ---\n const [editingHeader, setEditingHeader] = useState<number | null>(null)\n const [headerEditValue, setHeaderEditValue] = useState(\"\")\n const headerInputRef = useRef<HTMLInputElement>(null)\n\n // --- オートフィル ---\n const [fillDragging, setFillDragging] = useState(false)\n const [fillTarget, setFillTarget] = useState<number | null>(null)\n\n // --- リサイズ ---\n const [resizingCol, setResizingCol] = useState<number | null>(null)\n const resizeStartXRef = useRef(0)\n const resizeStartWRef = useRef(0)\n\n // --- コンテキストメニュー ---\n const [ctxMenu, setCtxMenu] = useState<{ x: number; y: number } | null>(null)\n\n // --- 編集可否 ---\n const columnEditable = useCallback(\n (c: number, r: number): boolean => {\n if (readOnly) return false\n const e = columns[c]?.editable\n if (e === undefined) return true\n return typeof e === \"function\" ? e({ row: r }) : e\n },\n [columns, readOnly],\n )\n\n // --- 検索ハイライト ---\n const searchHitSet = useMemo(() => {\n const s = new Set<string>()\n searchHighlights?.forEach((h) => s.add(`${h.row}:${h.col}`))\n return s\n }, [searchHighlights])\n\n // currentSearchHit が変わったらスクロール\n useEffect(() => {\n const el = bodyRef.current\n if (!currentSearchHit || !el) return\n const targetTop = Math.max(0, (currentSearchHit.row - bodyOffset) * rowHeight)\n const viewH = el.clientHeight\n const st = el.scrollTop\n if (targetTop < st || targetTop > st + viewH - rowHeight) {\n el.scrollTop = Math.max(0, targetTop - viewH / 3)\n }\n }, [currentSearchHit, rowHeight, bodyOffset])\n\n // --- 選択の通知 ---\n useEffect(() => {\n onSelectionChange?.(selections)\n }, [selections, onSelectionChange])\n\n // --- 選択統計 ---\n useEffect(() => {\n if (!onSelectionStats) return\n if (selRects.length === 0) {\n onSelectionStats(null)\n return\n }\n const count = totalCellCount(selRects)\n if (count > HEAVY_CELL_LIMIT) {\n onSelectionStats({ count, numericCount: 0, sum: null, average: null })\n return\n }\n let numericCount = 0\n let sum = 0\n for (const rect of selRects) {\n for (let r = rect.r1; r <= rect.r2; r++) {\n for (let c = rect.c1; c <= rect.c2; c++) {\n const n = numericValue(getRawValue(r, c))\n if (n !== null) {\n sum += n\n numericCount++\n }\n }\n }\n }\n onSelectionStats({\n count,\n numericCount,\n sum: numericCount > 0 ? sum : null,\n average: numericCount > 0 ? sum / numericCount : null,\n })\n }, [selRects, rows, editBuffer.version, onSelectionStats, getRawValue])\n\n // --- スクロール(横方向はヘッダ/固定行へ同期) ---\n const handleScroll = useCallback(() => {\n const body = bodyRef.current\n if (!body) return\n if (headerRef.current) headerRef.current.scrollLeft = body.scrollLeft\n if (frozenRef.current) frozenRef.current.scrollLeft = body.scrollLeft\n setScrollTop(body.scrollTop)\n }, [])\n\n // --- 編集 ---\n const startEdit = useCallback(\n (r: number, c: number, initial?: string) => {\n if (!columnEditable(c, r)) return\n setCtxMenu(null)\n setEditingCell({ row: r, col: c })\n setEditValue(initial ?? cellToInput(getRawValue(r, c)))\n },\n [columnEditable, getRawValue],\n )\n const cancelEdit = useCallback(() => setEditingCell(null), [])\n const commitEdit = useCallback(() => {\n if (!editingCell) return\n const { row, col } = editingCell\n const column = columns[col]\n setEditingCell(null)\n if (!column) return\n const oldValue = getRawValue(row, col)\n const newValue = parseInputValue(editValue, column.type)\n if (column.validate) {\n const result = column.validate(newValue, { row })\n if (result === false || typeof result === \"string\") {\n platform.notify(\"error\", typeof result === \"string\" ? result : \"Invalid value\")\n return\n }\n }\n if (newValue !== oldValue) {\n applyEdits([{ row, col, oldValue, newValue }])\n }\n }, [editingCell, columns, editValue, getRawValue, applyEdits, platform])\n\n useEffect(() => {\n if (editingCell && editInputRef.current) {\n editInputRef.current.focus()\n editInputRef.current.select()\n }\n }, [editingCell])\n\n // --- セル操作 ---\n const handleCellMouseDown = useCallback(\n (r: number, c: number, e: React.MouseEvent) => {\n if (editingCell && editingCell.row === r && editingCell.col === c) return\n if (editingCell) commitEdit()\n setCtxMenu(null)\n if (e.shiftKey && activeCell) {\n updateActiveSelection({ start: activeCell, end: { row: r, col: c } })\n } else if (e.ctrlKey || e.metaKey) {\n setActiveCell({ row: r, col: c })\n addSelection({ start: { row: r, col: c }, end: { row: r, col: c } })\n } else {\n setActiveCell({ row: r, col: c })\n setSelection({ start: { row: r, col: c }, end: { row: r, col: c } })\n }\n isDraggingRef.current = true\n },\n [activeCell, editingCell, commitEdit, setSelection, updateActiveSelection, addSelection],\n )\n\n const handleCellMouseEnter = useCallback(\n (r: number, c: number) => {\n if (isDraggingRef.current && activeCell) {\n updateActiveSelection({ start: activeCell, end: { row: r, col: c } })\n }\n if (isRowDraggingRef.current && rowAnchorRef.current !== null) {\n updateActiveSelection({\n start: { row: rowAnchorRef.current, col: 0 },\n end: { row: r, col: columns.length - 1 },\n })\n }\n if (fillDragging) setFillTarget(r)\n },\n [activeCell, fillDragging, columns.length, updateActiveSelection],\n )\n\n // --- オートフィル適用 ---\n const applyFill = useCallback(() => {\n if (!activeRange || fillTarget === null) return\n const sr = Math.min(activeRange.start.row, activeRange.end.row)\n const er = Math.max(activeRange.start.row, activeRange.end.row)\n const sc = Math.min(activeRange.start.col, activeRange.end.col)\n const ec = Math.max(activeRange.start.col, activeRange.end.col)\n const te = Math.max(er, fillTarget)\n if (te <= er) return\n const edits: CellEdit[] = []\n for (let r = er + 1; r <= te; r++) {\n const srcR = sr + ((r - sr) % (er - sr + 1))\n for (let c = sc; c <= ec; c++) {\n if (!columnEditable(c, r)) continue\n edits.push({\n row: r,\n col: c,\n oldValue: getRawValue(r, c),\n newValue: getRawValue(srcR, c),\n })\n }\n }\n applyEdits(edits)\n setSelection({ start: { row: sr, col: sc }, end: { row: te, col: ec } })\n onAutoFill?.({\n sourceRange: { start: { row: sr, col: sc }, end: { row: er, col: ec } },\n direction: \"down\",\n toEnd: false,\n })\n }, [activeRange, fillTarget, columnEditable, getRawValue, applyEdits, setSelection, onAutoFill])\n\n useEffect(() => {\n const up = () => {\n isDraggingRef.current = false\n isRowDraggingRef.current = false\n isColDraggingRef.current = false\n if (fillDragging && fillTarget !== null) applyFill()\n setFillDragging(false)\n setFillTarget(null)\n }\n window.addEventListener(\"mouseup\", up)\n return () => window.removeEventListener(\"mouseup\", up)\n }, [fillDragging, fillTarget, applyFill])\n\n const handleFillHandleMouseDown = useCallback((e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setFillDragging(true)\n }, [])\n\n // --- 行ヘッダ(行全体の選択) ---\n const fullRow = useCallback(\n (a: number, b: number): Selection => ({\n start: { row: a, col: 0 },\n end: { row: b, col: columns.length - 1 },\n }),\n [columns.length],\n )\n const handleRowHeaderMouseDown = useCallback(\n (r: number, e: React.MouseEvent) => {\n if (editingCell) commitEdit()\n setCtxMenu(null)\n if (e.shiftKey && rowAnchorRef.current !== null) {\n updateActiveSelection(fullRow(rowAnchorRef.current, r))\n } else if (e.ctrlKey || e.metaKey) {\n rowAnchorRef.current = r\n setActiveCell({ row: r, col: 0 })\n addSelection(fullRow(r, r))\n } else {\n rowAnchorRef.current = r\n setActiveCell({ row: r, col: 0 })\n setSelection(fullRow(r, r))\n }\n isRowDraggingRef.current = true\n },\n [editingCell, commitEdit, fullRow, setSelection, updateActiveSelection, addSelection],\n )\n\n // --- 列ヘッダ(列全体の選択) ---\n const fullCol = useCallback(\n (a: number, b: number): Selection => ({\n start: { row: 0, col: a },\n end: { row: total - 1, col: b },\n }),\n [total],\n )\n const handleColHeaderMouseDown = useCallback(\n (c: number, e: React.MouseEvent) => {\n if (editingHeader !== null) return\n if (editingCell) commitEdit()\n setCtxMenu(null)\n if (e.shiftKey && colAnchorRef.current !== null) {\n updateActiveSelection(fullCol(colAnchorRef.current, c))\n } else if (e.ctrlKey || e.metaKey) {\n colAnchorRef.current = c\n setActiveCell({ row: 0, col: c })\n addSelection(fullCol(c, c))\n } else {\n colAnchorRef.current = c\n setActiveCell({ row: 0, col: c })\n setSelection(fullCol(c, c))\n }\n isColDraggingRef.current = true\n },\n [\n editingHeader,\n editingCell,\n commitEdit,\n fullCol,\n setSelection,\n updateActiveSelection,\n addSelection,\n ],\n )\n const handleColHeaderMouseEnter = useCallback(\n (c: number) => {\n if (isColDraggingRef.current && colAnchorRef.current !== null) {\n updateActiveSelection(fullCol(colAnchorRef.current, c))\n }\n },\n [fullCol, updateActiveSelection],\n )\n\n const handleSelectAll = useCallback(() => {\n if (editingCell) commitEdit()\n setActiveCell({ row: 0, col: 0 })\n setSelection({\n start: { row: 0, col: 0 },\n end: { row: total - 1, col: columns.length - 1 },\n })\n }, [editingCell, commitEdit, total, columns.length, setSelection])\n\n // --- ヘッダ名編集 ---\n const startHeaderEdit = useCallback(\n (c: number) => {\n if (!onColumnRename) return\n setEditingCell(null)\n setSelection(null)\n setActiveCell(null)\n setEditingHeader(c)\n setHeaderEditValue(columns[c]?.name ?? \"\")\n },\n [onColumnRename, columns, setSelection],\n )\n const commitHeaderEdit = useCallback(() => {\n if (editingHeader === null) return\n const name = headerEditValue.trim()\n if (name && name !== columns[editingHeader]?.name) onColumnRename?.(editingHeader, name)\n setEditingHeader(null)\n }, [editingHeader, headerEditValue, columns, onColumnRename])\n useEffect(() => {\n if (editingHeader !== null && headerInputRef.current) {\n headerInputRef.current.focus()\n headerInputRef.current.select()\n }\n }, [editingHeader])\n\n // --- ソート(none→asc→desc→なし のトグル) ---\n const handleSortClick = useCallback(\n (c: number) => {\n const name = columns[c]?.name\n if (!name || !onSortChange) return\n const current = sort.find((s) => s.column === name)\n let next: SortSpec[]\n if (!current) next = [...sort, { column: name, direction: \"asc\" }]\n else if (current.direction === \"asc\")\n next = sort.map((s) => (s.column === name ? { ...s, direction: \"desc\" } : s))\n else next = sort.filter((s) => s.column !== name)\n onSortChange(next)\n },\n [columns, onSortChange, sort],\n )\n\n const handleFilterClick = useCallback(\n (c: number, e: React.MouseEvent) => {\n e.stopPropagation()\n if (!onFilterButtonClick) return\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect()\n onFilterButtonClick(c, rect)\n },\n [onFilterButtonClick],\n )\n\n // --- リサイズ ---\n const handleResizeStart = useCallback(\n (c: number, e: React.MouseEvent) => {\n e.preventDefault()\n e.stopPropagation()\n setResizingCol(c)\n resizeStartXRef.current = e.clientX\n resizeStartWRef.current = getColWidth(c)\n },\n [getColWidth],\n )\n useEffect(() => {\n if (resizingCol === null) return\n const move = (e: MouseEvent) => {\n applyColWidth(\n resizingCol,\n resizeStartWRef.current + (e.clientX - resizeStartXRef.current),\n )\n }\n const up = () => setResizingCol(null)\n window.addEventListener(\"mousemove\", move)\n window.addEventListener(\"mouseup\", up)\n return () => {\n window.removeEventListener(\"mousemove\", move)\n window.removeEventListener(\"mouseup\", up)\n }\n }, [resizingCol, applyColWidth])\n\n const measureCanvasRef = useRef<HTMLCanvasElement | null>(null)\n const autoFitColumn = useCallback(\n (c: number) => {\n if (!measureCanvasRef.current)\n measureCanvasRef.current = document.createElement(\"canvas\")\n const ctx = measureCanvasRef.current.getContext(\"2d\")\n if (!ctx) return\n const sample = bodyRef.current?.querySelector(\".vox-cell\")\n if (sample) {\n const cs = getComputedStyle(sample)\n ctx.font = `${cs.fontWeight} ${cs.fontSize} ${cs.fontFamily}`\n } else {\n ctx.font = `${fontSize}px sans-serif`\n }\n let max = ctx.measureText(columns[c]?.name ?? \"\").width + 48\n rows.forEach((_, r) => {\n const text = getCellText(r, c)\n if (text) max = Math.max(max, ctx.measureText(text).width)\n })\n applyColWidth(c, Math.min(MAX_AUTOFIT_WIDTH, max + 16))\n },\n [columns, rows, getCellText, applyColWidth, fontSize],\n )\n\n // --- クリップボード ---\n const handleCopy = useCallback(async () => {\n if (selRects.length === 0) return\n if (totalCellCount(selRects) > HEAVY_CELL_LIMIT) {\n platform.notify(\"error\", \"Selection is too large to copy\")\n return\n }\n try {\n await platform.writeText(buildTsv(selRects, getCellText))\n } catch (err) {\n onError?.(err, { phase: \"commit\" })\n }\n }, [selRects, platform, getCellText, onError])\n\n const handleCut = useCallback(async () => {\n if (readOnly) return\n await handleCopy()\n if (selRects.length === 0 || totalCellCount(selRects) > HEAVY_CELL_LIMIT) return\n const edits: CellEdit[] = []\n const seen = new Set<string>()\n for (const rect of selRects) {\n for (let r = rect.r1; r <= rect.r2; r++) {\n for (let c = rect.c1; c <= rect.c2; c++) {\n const key = `${r}:${c}`\n if (seen.has(key) || !columnEditable(c, r)) continue\n seen.add(key)\n edits.push({ row: r, col: c, oldValue: getRawValue(r, c), newValue: null })\n }\n }\n }\n applyEdits(edits)\n }, [readOnly, handleCopy, selRects, columnEditable, getRawValue, applyEdits])\n\n const handlePaste = useCallback(async () => {\n if (readOnly || !activeCell) return\n try {\n const text = await platform.readText()\n const grid = parseTsv(text)\n const edits: CellEdit[] = []\n for (let ri = 0; ri < grid.length; ri++) {\n const line = grid[ri]!\n for (let ci = 0; ci < line.length; ci++) {\n const tr = activeCell.row + ri\n const tc = activeCell.col + ci\n if (tr >= total || tc >= columns.length || !columnEditable(tc, tr)) continue\n edits.push({\n row: tr,\n col: tc,\n oldValue: getRawValue(tr, tc),\n newValue: parseInputValue(line[ci] ?? \"\", columns[tc]?.type),\n })\n }\n }\n applyEdits(edits)\n } catch (err) {\n onError?.(err, { phase: \"commit\" })\n }\n }, [\n readOnly,\n activeCell,\n platform,\n total,\n columns,\n columnEditable,\n getRawValue,\n applyEdits,\n onError,\n ])\n\n // --- キーボード ---\n const moveActive = useCallback(\n (nr: number, nc: number, extend: boolean) => {\n const row = Math.max(0, Math.min(total - 1, nr))\n const col = Math.max(0, Math.min(columns.length - 1, nc))\n setActiveCell({ row, col })\n if (extend && activeRange) {\n updateActiveSelection({ start: activeRange.start, end: { row, col } })\n } else {\n setSelection({ start: { row, col }, end: { row, col } })\n }\n // 可視範囲外なら追従スクロール\n const el = bodyRef.current\n if (el) {\n const top = (row - bodyOffset) * rowHeight\n if (top < el.scrollTop) el.scrollTop = top\n else if (top + rowHeight > el.scrollTop + el.clientHeight)\n el.scrollTop = top + rowHeight - el.clientHeight\n }\n },\n [\n total,\n columns.length,\n activeRange,\n updateActiveSelection,\n setSelection,\n bodyOffset,\n rowHeight,\n ],\n )\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (editingHeader !== null) return\n if (activeCell && onCellKeyDown) {\n const column = columns[activeCell.col]\n if (column) {\n onCellKeyDown(e, {\n row: activeCell.row,\n col: activeCell.col,\n value: getRawValue(activeCell.row, activeCell.col),\n column,\n })\n if (e.defaultPrevented) return\n }\n }\n\n const mod = e.ctrlKey || e.metaKey\n if (mod && !editingCell) {\n if (e.key === \"a\") {\n e.preventDefault()\n handleSelectAll()\n return\n }\n if (e.key === \"c\") {\n e.preventDefault()\n void handleCopy()\n return\n }\n if (!readOnly && e.key === \"x\") {\n e.preventDefault()\n void handleCut()\n return\n }\n if (!readOnly && e.key === \"v\") {\n e.preventDefault()\n void handlePaste()\n return\n }\n if (!readOnly && e.key === \"z\") {\n e.preventDefault()\n editBuffer.undo()\n return\n }\n if (!readOnly && e.key === \"y\") {\n e.preventDefault()\n editBuffer.redo()\n return\n }\n }\n\n if (editingCell) {\n if (e.key === \"Enter\" && !composingRef.current) {\n e.preventDefault()\n commitEdit()\n moveActive(editingCell.row + 1, editingCell.col, false)\n } else if (e.key === \"Escape\") {\n e.preventDefault()\n cancelEdit()\n } else if (e.key === \"Tab\") {\n e.preventDefault()\n commitEdit()\n moveActive(editingCell.row, editingCell.col + (e.shiftKey ? -1 : 1), false)\n }\n return\n }\n\n if (!activeCell) return\n if (readOnly && !e.key.startsWith(\"Arrow\") && e.key !== \"Tab\") return\n const { row: r, col: c } = activeCell\n const extend = e.shiftKey && e.key.startsWith(\"Arrow\")\n if (e.key === \"ArrowDown\") {\n e.preventDefault()\n moveActive(r + 1, c, extend)\n } else if (e.key === \"ArrowUp\") {\n e.preventDefault()\n moveActive(r - 1, c, extend)\n } else if (e.key === \"ArrowRight\") {\n e.preventDefault()\n moveActive(r, c + 1, extend)\n } else if (e.key === \"ArrowLeft\") {\n e.preventDefault()\n moveActive(r, c - 1, extend)\n } else if (e.key === \"Tab\") {\n e.preventDefault()\n moveActive(r, c + (e.shiftKey ? -1 : 1), false)\n } else if (e.key === \"Enter\") {\n e.preventDefault()\n if (r >= total - 1) onAppendRow?.(total)\n else moveActive(r + 1, c, false)\n } else if (e.key === \"Home\") {\n e.preventDefault()\n moveActive(r, mod ? 0 : 0, extend)\n if (mod) moveActive(0, 0, extend)\n } else if (e.key === \"End\") {\n e.preventDefault()\n if (mod) moveActive(total - 1, columns.length - 1, extend)\n else moveActive(r, columns.length - 1, extend)\n } else if (e.key === \"PageDown\") {\n e.preventDefault()\n moveActive(r + Math.floor(viewportHeight / rowHeight), c, extend)\n } else if (e.key === \"PageUp\") {\n e.preventDefault()\n moveActive(r - Math.floor(viewportHeight / rowHeight), c, extend)\n } else if (!readOnly && (e.key === \"Delete\" || e.key === \"Backspace\")) {\n e.preventDefault()\n startEdit(r, c, \"\")\n } else if (!readOnly && e.key === \"F2\") {\n e.preventDefault()\n startEdit(r, c)\n } else if (!readOnly && e.key.length === 1 && !mod && !e.altKey) {\n startEdit(r, c, e.key)\n }\n },\n [\n editingHeader,\n activeCell,\n onCellKeyDown,\n columns,\n getRawValue,\n editingCell,\n readOnly,\n handleSelectAll,\n handleCopy,\n handleCut,\n handlePaste,\n editBuffer,\n commitEdit,\n cancelEdit,\n moveActive,\n total,\n onAppendRow,\n viewportHeight,\n rowHeight,\n startEdit,\n ],\n )\n\n // --- コンテキストメニュー ---\n const handleContextMenu = useCallback(\n (e: React.MouseEvent) => {\n if (readOnly) {\n e.preventDefault()\n return\n }\n e.preventDefault()\n setCtxMenu({ x: e.clientX, y: e.clientY })\n },\n [readOnly],\n )\n const deleteSelectedRows = useCallback(() => {\n if (selRects.length === 0) return\n const set = new Set<number>()\n for (const rect of selRects) for (let r = rect.r1; r <= rect.r2; r++) set.add(r)\n onDeleteRows?.(Array.from(set).sort((a, b) => a - b))\n }, [selRects, onDeleteRows])\n\n // --- 命令的ハンドル ---\n useImperativeHandle(\n ref,\n (): VoxSheetHandle => ({\n scrollToRow: (row) => {\n if (bodyRef.current)\n bodyRef.current.scrollTop = Math.max(0, (row - bodyOffset) * rowHeight)\n },\n scrollToCell: (row, col) => {\n if (bodyRef.current)\n bodyRef.current.scrollTop = Math.max(0, (row - bodyOffset) * rowHeight)\n let left = 0\n for (let i = 0; i < col; i++) left += getColWidth(i)\n if (bodyRef.current) bodyRef.current.scrollLeft = left\n },\n focusCell: (row, col) => {\n setActiveCell({ row, col })\n setSelection({ start: { row, col }, end: { row, col } })\n rootRef.current?.focus()\n },\n getSelection: () => selections,\n setSelection: (sel) => setSelections(sel),\n startEdit: (row, col) => startEdit(row, col),\n getLocalEdits: () => editBuffer.getLocalEdits(),\n clearLocalEdits: () => editBuffer.clear(),\n undo: () => editBuffer.undo(),\n redo: () => editBuffer.redo(),\n invalidate: () => invalidate(),\n }),\n [\n bodyOffset,\n rowHeight,\n getColWidth,\n selections,\n setSelection,\n startEdit,\n editBuffer,\n invalidate,\n ],\n )\n\n // --- レンダリング ---\n const headerWidth = ROW_HEADER_WIDTH + columns.reduce((sum, _, i) => sum + getColWidth(i), 0)\n const totalHeight = Math.max(0, total - bodyOffset) * rowHeight\n const fillRow = selMin ? selMin.r2 : null\n const fillCol = selMin ? selMin.c2 : null\n\n const renderHeaderActions = (c: number): ReactElement | null => {\n if (readOnly || (!onSortChange && !onFilterButtonClick)) return null\n const name = columns[c]?.name ?? \"\"\n const sortIndex = sort.findIndex((s) => s.column === name)\n const sortSpec = sortIndex >= 0 ? sort[sortIndex] : undefined\n const hasFilter = filters.some((f) => f.column === name)\n const SortIcon = sortSpec\n ? sortSpec.direction === \"asc\"\n ? icons.sortAscending\n : icons.sortDescending\n : icons.sortUnsorted\n const FilterIcon = hasFilter ? icons.filterActive : icons.filter\n return (\n <span className=\"vox-header-actions\" onMouseDown={(e) => e.stopPropagation()}>\n {onFilterButtonClick && (\n <button\n type=\"button\"\n className=\"vox-header-btn\"\n title=\"Filter\"\n aria-label={`Filter ${name}`}\n onClick={(e) => handleFilterClick(c, e)}\n >\n <FilterIcon size={13} />\n </button>\n )}\n {onSortChange && (\n <button\n type=\"button\"\n className=\"vox-header-btn\"\n title=\"Sort\"\n aria-label={`Sort ${name}`}\n onClick={(e) => {\n e.stopPropagation()\n handleSortClick(c)\n }}\n >\n <SortIcon size={13} />\n {sortSpec && sort.length > 1 && <sup>{sortIndex + 1}</sup>}\n </button>\n )}\n </span>\n )\n }\n\n const renderRow = (rowIdx: number, top: number): ReactElement => {\n const entry = rows.get(rowIdx)\n const rowSelected = selRects.some(\n (rect) =>\n rowIdx >= rect.r1 &&\n rowIdx <= rect.r2 &&\n rect.c1 === 0 &&\n rect.c2 === columns.length - 1,\n )\n const ordinal = entry ? Math.floor(entry.ordinal) : rowIdx + 1\n return (\n <div\n key={rowIdx}\n className=\"vox-row\"\n style={{ top, height: rowHeight }}\n aria-rowindex={rowIdx + 1}\n >\n <div\n className={`vox-row-header${rowSelected ? \" vox-row-header--selected\" : \"\"}`}\n style={{ width: ROW_HEADER_WIDTH, height: rowHeight }}\n onMouseDown={(e) => handleRowHeaderMouseDown(rowIdx, e)}\n onMouseEnter={() =>\n isRowDraggingRef.current &&\n rowAnchorRef.current !== null &&\n updateActiveSelection(fullRow(rowAnchorRef.current, rowIdx))\n }\n >\n {ordinal.toLocaleString()}\n </div>\n {columns.map((col, c) => {\n const selected = cellInRects(selRects, rowIdx, c)\n const isActive = activeCell?.row === rowIdx && activeCell?.col === c\n const isEditing = editingCell?.row === rowIdx && editingCell?.col === c\n const dirty = editBuffer.isDirty(rowIdx, c)\n const hit = searchHitSet.has(`${rowIdx}:${c}`)\n const isCurrent =\n currentSearchHit?.row === rowIdx && currentSearchHit?.col === c\n const showFill =\n !fillDragging &&\n rowIdx === fillRow &&\n c === fillCol &&\n selMin !== null &&\n !readOnly\n const isFillPreview =\n fillDragging &&\n fillTarget !== null &&\n selMin !== null &&\n rowIdx > selMin.r2 &&\n rowIdx <= fillTarget &&\n c >= selMin.c1 &&\n c <= selMin.c2\n const align = col.align ?? defaultAlign(col.type)\n const cls =\n \"vox-cell\" +\n (selected ? \" vox-cell--selected\" : \"\") +\n (isActive ? \" vox-cell--active\" : \"\") +\n (dirty ? \" vox-cell--dirty\" : \"\") +\n (isFillPreview ? \" vox-cell--selected\" : \"\") +\n (hit ? \" vox-cell--search-hit\" : \"\") +\n (isCurrent ? \" vox-cell--search-current\" : \"\")\n return (\n <div\n key={c}\n className={cls}\n role=\"gridcell\"\n aria-selected={selected}\n aria-colindex={c + 1}\n style={{\n width: getColWidth(c),\n height: rowHeight,\n justifyContent: alignToJustify(align),\n }}\n onMouseDown={(e) => handleCellMouseDown(rowIdx, c, e)}\n onMouseEnter={() => handleCellMouseEnter(rowIdx, c)}\n onDoubleClick={() => startEdit(rowIdx, c)}\n onContextMenu={handleContextMenu}\n >\n {isEditing ? (\n <input\n ref={editInputRef}\n className=\"vox-cell-input\"\n value={editValue}\n onChange={(e) => setEditValue(e.target.value)}\n onBlur={commitEdit}\n onCompositionStart={() => (composingRef.current = true)}\n onCompositionEnd={() => (composingRef.current = false)}\n />\n ) : (\n getCellText(rowIdx, c)\n )}\n {showFill && (\n <div\n className=\"vox-fill-handle\"\n onMouseDown={handleFillHandleMouseDown}\n />\n )}\n </div>\n )\n })}\n </div>\n )\n }\n\n const bodyRows: ReactElement[] = []\n for (let r = visibleStart; r < visibleEnd; r++) {\n bodyRows.push(renderRow(r, (r - bodyOffset) * rowHeight))\n }\n\n const rootStyle: CSSProperties = {\n [\"--vox-row-height\" as string]: `${rowHeight}px`,\n [\"--vox-font-size\" as string]: `${fontSize}px`,\n [\"--vox-row-header-width\" as string]: `${ROW_HEADER_WIDTH}px`,\n ...style,\n }\n\n const isEmpty = total === 0 && status !== \"loading\"\n\n return (\n <div\n ref={rootRef}\n className={`vox-sheet${className ? ` ${className}` : \"\"}`}\n data-vox-theme={theme === \"system\" ? undefined : theme}\n role=\"grid\"\n aria-rowcount={total}\n aria-colcount={columns.length}\n aria-readonly={readOnly}\n tabIndex={0}\n style={rootStyle}\n onKeyDown={handleKeyDown}\n onContextMenu={readOnly ? (e) => e.preventDefault() : undefined}\n >\n <div className=\"vox-header-wrap\" style={{ paddingRight: scrollbarWidth }}>\n <div\n className=\"vox-corner\"\n style={{ width: ROW_HEADER_WIDTH }}\n onClick={handleSelectAll}\n />\n <div className=\"vox-header\" ref={headerRef} role=\"row\">\n {columns.map((col, c) => {\n const colSelected = selRects.some(\n (rect) =>\n c >= rect.c1 &&\n c <= rect.c2 &&\n rect.r1 === 0 &&\n rect.r2 === total - 1,\n )\n const sortName = col.name\n const sortSpec = sort.find((s) => s.column === sortName)\n return (\n <div\n key={c}\n className=\"vox-header-cell\"\n role=\"columnheader\"\n aria-colindex={c + 1}\n aria-sort={\n sortSpec\n ? sortSpec.direction === \"asc\"\n ? \"ascending\"\n : \"descending\"\n : \"none\"\n }\n style={{\n width: getColWidth(c),\n background: colSelected\n ? \"var(--vox-color-selection-bg)\"\n : undefined,\n }}\n onMouseDown={(e) => handleColHeaderMouseDown(c, e)}\n onMouseEnter={() => handleColHeaderMouseEnter(c)}\n >\n {editingHeader === c ? (\n <input\n ref={headerInputRef}\n className=\"vox-cell-input\"\n value={headerEditValue}\n onChange={(e) => setHeaderEditValue(e.target.value)}\n onBlur={commitHeaderEdit}\n onMouseDown={(e) => e.stopPropagation()}\n onKeyDown={(e) => {\n if (e.key === \"Enter\") {\n e.preventDefault()\n commitHeaderEdit()\n } else if (e.key === \"Escape\") {\n e.preventDefault()\n setEditingHeader(null)\n }\n }}\n />\n ) : (\n <span\n className=\"vox-header-label\"\n onDoubleClick={\n onColumnRename\n ? (e) => {\n e.stopPropagation()\n startHeaderEdit(c)\n }\n : undefined\n }\n >\n {col.name}\n </span>\n )}\n {renderHeaderActions(c)}\n <div\n className=\"vox-resize-handle\"\n onMouseDown={(e) => handleResizeStart(c, e)}\n onDoubleClick={(e) => {\n e.preventDefault()\n e.stopPropagation()\n autoFitColumn(c)\n }}\n />\n </div>\n )\n })}\n {onAddColumn && (\n <button\n type=\"button\"\n className=\"vox-add-column\"\n title=\"Add column\"\n onClick={() => onAddColumn(columns.length)}\n >\n +\n </button>\n )}\n </div>\n </div>\n\n <div className=\"vox-body\" ref={bodyRef} onScroll={handleScroll}>\n <div\n className=\"vox-scroll-spacer\"\n style={{ height: totalHeight, width: headerWidth }}\n >\n {bodyRows}\n {selRects.map((rect, i) => (\n <div\n key={`sel-${i}`}\n className=\"vox-selection-outline\"\n style={{\n left: colLeft(rect.c1),\n top: (rect.r1 - bodyOffset) * rowHeight,\n width: colLeft(rect.c2) + getColWidth(rect.c2) - colLeft(rect.c1),\n height: (rect.r2 - rect.r1 + 1) * rowHeight,\n }}\n />\n ))}\n </div>\n </div>\n\n {status === \"loading\" && total === 0 && (\n <div className=\"vox-overlay\">\n {renderLoading ? renderLoading() : labels.loading}\n </div>\n )}\n {isEmpty && (\n <div className=\"vox-overlay\">{renderEmpty ? renderEmpty() : labels.empty}</div>\n )}\n\n {ctxMenu && (\n <ContextMenu\n x={ctxMenu.x}\n y={ctxMenu.y}\n onClose={() => setCtxMenu(null)}\n items={[\n {\n label: labels.contextCut,\n action: () => void handleCut(),\n disabled: !selMin,\n },\n {\n label: labels.contextCopy,\n action: () => void handleCopy(),\n disabled: !selMin,\n },\n {\n label: labels.contextPaste,\n action: () => void handlePaste(),\n disabled: !activeCell,\n },\n ...(onInsertRow\n ? ([\n \"sep\" as const,\n {\n label: labels.contextInsertRowAbove,\n action: () =>\n activeCell && onInsertRow(activeCell.row, \"above\"),\n disabled: !activeCell,\n },\n {\n label: labels.contextInsertRowBelow,\n action: () =>\n activeCell && onInsertRow(activeCell.row, \"below\"),\n disabled: !activeCell,\n },\n ] as const)\n : []),\n ...(onDeleteRows\n ? ([\n \"sep\" as const,\n {\n label: labels.contextDeleteRows,\n action: deleteSelectedRows,\n disabled: selRects.length === 0,\n },\n ] as const)\n : []),\n \"sep\" as const,\n {\n label: labels.contextUndo,\n action: () => editBuffer.undo(),\n disabled: !editBuffer.canUndo(),\n },\n {\n label: labels.contextRedo,\n action: () => editBuffer.redo(),\n disabled: !editBuffer.canRedo(),\n },\n ]}\n />\n )}\n </div>\n )\n}\n\nconst alignToJustify = (align: \"left\" | \"right\" | \"center\"): string =>\n align === \"right\" ? \"flex-end\" : align === \"center\" ? \"center\" : \"flex-start\"\n\ntype CtxItem = { label: string; action: () => void; disabled?: boolean }\n\nconst ContextMenu = ({\n x,\n y,\n items,\n onClose,\n}: {\n x: number\n y: number\n items: (CtxItem | \"sep\")[]\n onClose: () => void\n}): ReactElement => {\n const ref = useRef<HTMLDivElement>(null)\n useEffect(() => {\n const close = (e: MouseEvent) => {\n if (ref.current && !ref.current.contains(e.target as Node)) onClose()\n }\n document.addEventListener(\"mousedown\", close)\n return () => document.removeEventListener(\"mousedown\", close)\n }, [onClose])\n return (\n <div ref={ref} className=\"vox-context-menu\" style={{ left: x, top: y }} role=\"menu\">\n {items.map((item, i) =>\n item === \"sep\" ? (\n <div key={i} className=\"vox-context-separator\" />\n ) : (\n <button\n key={i}\n type=\"button\"\n className=\"vox-context-item\"\n role=\"menuitem\"\n disabled={item.disabled}\n onClick={() => {\n item.action()\n onClose()\n }}\n >\n {item.label}\n </button>\n ),\n )}\n </div>\n )\n}\n\nexport const VoxSheet = forwardRef<VoxSheetHandle, VoxSheetProps>(VoxSheetInner)\n"],"names":["CHUNK","FETCH_DEBOUNCE_MS","useChunks","params","fetchRows","totalRows","columns","sort","filters","search","queryKey","frozenRows","startRow","endRow","onError","cacheRef","useRef","pendingRef","controllersRef","rows","setRows","useState","total","setTotal","status","setStatus","invalidationKey","c","reset","useCallback","controller","useEffect","rebuildVisible","next","offset","chunk","row","i","loadChunks","effectiveTotal","offsets","from","to","o","targets","jobs","limit","result","values","error","prev","timer","invalidate","MAX_UNDO","keyOf","col","useEditBuffer","onCellChange","onDirtyChange","editsRef","originalRef","undoRef","redoRef","version","setVersion","notifyDirty","applyValue","value","getBase","key","original","applyEdits","edits","edit","v","noBase","undo","action","redo","getEditedValue","isDirty","getLocalEdits","newValue","rs","cs","clear","canUndo","canRedo","useMemo","defaultAlign","type","toDate","formatCellValue","column","format","d","parseInputValue","raw","n","lower","numericValue","normalizeRect","sel","normalizeRects","selections","rectContains","rect","cellInRects","rects","totalCellCount","sum","escapeCell","text","buildTsv","getValue","rectToLines","lines","r","cells","first","sorted","a","b","parseTsv","cell","inQuotes","pushCell","pushRow","ch","svgProps","props","SortAscending","jsx","SortDescending","SortUnsorted","Filter","FilterActive","DEFAULT_ICONS","resolveIcons","overrides","DEFAULT_LABELS","resolveLabels","hasDom","defaultReadText","defaultWriteText","toastSeq","ensureToastContainer","el","defaultNotify","kind","message","opts","container","id","toast","duration","defaultConfirm","resolve","backdrop","modal","close","title","body","footer","cancel","ok","e","defaultSaveFile","blob","url","resolvePlatform","platform","DENSITY","ROW_HEADER_WIDTH","OVERSCAN","MIN_COL_WIDTH","MAX_AUTOFIT_WIDTH","HEAVY_CELL_LIMIT","cellToInput","VoxSheetInner","ref","density","defaultColumnWidth","theme","className","style","readOnly","searchHighlights","currentSearchHit","renderLoading","renderEmpty","labelOverrides","iconOverrides","platformOverride","onSortChange","onFilterButtonClick","onColumnResize","onColumnRename","onAddColumn","onAppendRow","onInsertRow","onDeleteRows","onAutoFill","onSelectionChange","onSelectionStats","onCellKeyDown","labels","icons","rowHeight","fontSize","rootRef","bodyRef","headerRef","frozenRef","scrollTop","setScrollTop","viewportHeight","setViewportHeight","scrollbarWidth","setScrollbarWidth","colWidths","setColWidths","widthMemoryRef","prevNamesRef","memory","oldName","newName","getColWidth","colLeft","x","applyColWidth","width","w","name","measure","observer","bodyOffset","desiredStart","desiredEnd","visibleStart","visibleEnd","editBuffer","getBaseValue","getRawValue","edited","getCellText","setSelections","activeCell","setActiveCell","selRects","selMin","activeRange","setSelection","updateActiveSelection","addSelection","isDraggingRef","isRowDraggingRef","isColDraggingRef","rowAnchorRef","colAnchorRef","editingCell","setEditingCell","editValue","setEditValue","editInputRef","composingRef","editingHeader","setEditingHeader","headerEditValue","setHeaderEditValue","headerInputRef","fillDragging","setFillDragging","fillTarget","setFillTarget","resizingCol","setResizingCol","resizeStartXRef","resizeStartWRef","ctxMenu","setCtxMenu","columnEditable","searchHitSet","s","h","targetTop","viewH","st","count","numericCount","handleScroll","startEdit","initial","cancelEdit","commitEdit","oldValue","handleCellMouseDown","handleCellMouseEnter","applyFill","sr","er","sc","ec","te","srcR","up","handleFillHandleMouseDown","fullRow","handleRowHeaderMouseDown","fullCol","handleColHeaderMouseDown","handleColHeaderMouseEnter","handleSelectAll","startHeaderEdit","commitHeaderEdit","handleSortClick","current","handleFilterClick","handleResizeStart","move","measureCanvasRef","autoFitColumn","ctx","sample","max","_","handleCopy","err","handleCut","seen","handlePaste","grid","ri","line","ci","tr","tc","moveActive","nr","nc","extend","top","handleKeyDown","mod","handleContextMenu","deleteSelectedRows","set","useImperativeHandle","left","headerWidth","totalHeight","fillRow","fillCol","renderHeaderActions","sortIndex","sortSpec","hasFilter","f","SortIcon","FilterIcon","jsxs","renderRow","rowIdx","entry","rowSelected","ordinal","selected","isActive","isEditing","dirty","hit","isCurrent","showFill","isFillPreview","align","cls","alignToJustify","bodyRows","rootStyle","isEmpty","colSelected","sortName","ContextMenu","y","items","onClose","item","VoxSheet","forwardRef"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { VoxLabels } from "./types";
2
+ /** 内蔵 UI の既定文言(英語)。`labels` prop で部分上書きできる。 */
3
+ export declare const DEFAULT_LABELS: VoxLabels;
4
+ export declare const resolveLabels: (overrides?: Partial<VoxLabels>) => VoxLabels;
5
+ //# sourceMappingURL=labels.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"labels.d.ts","sourceRoot":"","sources":["../src/labels.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAExC,+CAA+C;AAC/C,eAAO,MAAM,cAAc,EAAE,SAe5B,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,YAAY,OAAO,CAAC,SAAS,CAAC,KAAG,SACK,CAAA"}
@@ -0,0 +1,21 @@
1
+ import type { ConfirmOptions, PlatformAdapter, ToastKind } from "./types";
2
+ /**
3
+ * 解決済みプラットフォーム。各メソッドは常に存在する(未指定は web 既定にフォールバック)。
4
+ */
5
+ export type ResolvedPlatform = {
6
+ readText: () => Promise<string>;
7
+ writeText: (text: string) => Promise<void>;
8
+ notify: (kind: ToastKind, message: string, opts?: {
9
+ id?: string;
10
+ durationMs?: number;
11
+ }) => string;
12
+ confirm: (opts: ConfirmOptions) => Promise<boolean>;
13
+ saveFile: (opts: {
14
+ suggestedName: string;
15
+ mimeType?: string;
16
+ data: string | Blob;
17
+ }) => Promise<void>;
18
+ };
19
+ /** props の platform を web 既定とマージして解決する。 */
20
+ export declare const resolvePlatform: (platform?: PlatformAdapter) => ResolvedPlatform;
21
+ //# sourceMappingURL=platform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AAEzE;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC3B,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAC/B,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C,MAAM,EAAE,CACJ,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,IAAI,CAAC,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,KAC1C,MAAM,CAAA;IACX,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;IACnD,QAAQ,EAAE,CAAC,IAAI,EAAE;QACb,aAAa,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;KACtB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtB,CAAA;AAoID,2CAA2C;AAC3C,eAAO,MAAM,eAAe,GAAI,WAAW,eAAe,KAAG,gBAM3D,CAAA"}
@@ -0,0 +1,244 @@
1
+ import type { CSSProperties, KeyboardEvent as ReactKeyboardEvent, ReactElement, ReactNode } from "react";
2
+ /**
3
+ * セル値。JSON シリアライズ可能な型に限定する。
4
+ * - 日付は ISO 8601 文字列(推奨)または epoch ミリ秒で運び、列 type='date' で解釈する。
5
+ * - null は SQL NULL を表現し、空文字 "" と区別する。
6
+ */
7
+ export type CellValue = string | number | boolean | null;
8
+ export type ColumnType = "string" | "number" | "date" | "boolean";
9
+ export type ColumnAlign = "left" | "right" | "center";
10
+ /** 列の表示整形。関数 > kind 別既定 の順で解決する。 */
11
+ export type ColumnFormat = {
12
+ kind: "number";
13
+ options: Intl.NumberFormatOptions;
14
+ } | {
15
+ kind: "date";
16
+ options: Intl.DateTimeFormatOptions;
17
+ } | ((value: CellValue, ctx: {
18
+ column: Column;
19
+ row: number;
20
+ }) => string);
21
+ /** 列メタデータ。型は列が宣言し、描画・編集・比較・オートフィルを駆動する。 */
22
+ export type Column = {
23
+ /** 識別子兼表示名(sort/filter の column 参照に使用) */
24
+ name: string;
25
+ /** 既定 "string" */
26
+ type?: ColumnType;
27
+ /** 既定は type から導出(number/date=right, boolean=center) */
28
+ align?: ColumnAlign;
29
+ /** 既定は defaultColumnWidth。ユーザリサイズは列名キーで記憶する */
30
+ width?: number;
31
+ format?: ColumnFormat;
32
+ /** 既定は親 readOnly に従う */
33
+ editable?: boolean | ((ctx: {
34
+ row: number;
35
+ }) => boolean);
36
+ /** false / 文字列で却下 */
37
+ validate?: (value: CellValue, ctx: {
38
+ row: number;
39
+ }) => boolean | string;
40
+ };
41
+ export type SortDirection = "asc" | "desc";
42
+ /** 配列順 = 多列ソートの優先順位 */
43
+ export type SortSpec = {
44
+ column: string;
45
+ direction: SortDirection;
46
+ };
47
+ export type FilterOperator = "=" | "!=" | ">" | ">=" | "<" | "<=" | "contains" | "startsWith" | "endsWith" | "isNull" | "notNull";
48
+ export type FilterSpec = {
49
+ column: string;
50
+ operator: FilterOperator;
51
+ value?: CellValue;
52
+ };
53
+ /** fetchRows に渡すクエリ。offset/limit はグリッド所有、sort/filters/search は controlled。 */
54
+ export type Query = {
55
+ offset: number;
56
+ limit: number;
57
+ sort: SortSpec[];
58
+ filters: FilterSpec[];
59
+ search?: string;
60
+ };
61
+ /**
62
+ * チャンク取得の戻り値。
63
+ * data[i][j] = i 行目 j 列目、ids[i] が行 ID、ordinals[i] が表示順序。
64
+ * total はフィルタ適用後の総件数(毎回返すのが望ましい)。
65
+ */
66
+ export type FetchResult = {
67
+ data: CellValue[][];
68
+ ids: number[];
69
+ ordinals: number[];
70
+ total?: number;
71
+ };
72
+ /** 行データを範囲指定で取得する関数。signal で陳腐化した取得を中断できる。 */
73
+ export type FetchRowsFn = (query: Query, signal: AbortSignal) => Promise<FetchResult>;
74
+ export type CellAddress = {
75
+ row: number;
76
+ col: number;
77
+ };
78
+ /** 矩形選択。配列で複数レンジ(Excel 風)。 */
79
+ export type Selection = {
80
+ start: CellAddress;
81
+ end: CellAddress;
82
+ };
83
+ export type SelectionStats = {
84
+ count: number;
85
+ numericCount: number;
86
+ sum: number | null;
87
+ average: number | null;
88
+ };
89
+ export type CellEdit = {
90
+ row: number;
91
+ col: number;
92
+ oldValue: CellValue;
93
+ newValue: CellValue;
94
+ };
95
+ /** 1 操作(ペースト/オートフィル/カット)= Undo の単位。 */
96
+ export type EditAction = {
97
+ edits: CellEdit[];
98
+ };
99
+ /** onCellKeyDown に渡す文脈。 */
100
+ export type CellContext = {
101
+ row: number;
102
+ col: number;
103
+ value: CellValue;
104
+ column: Column;
105
+ };
106
+ export type IconName = "sortAscending" | "sortDescending" | "sortUnsorted" | "filter" | "filterActive";
107
+ export type IconProps = {
108
+ size?: number;
109
+ className?: string;
110
+ };
111
+ export type IconRenderer = (props: IconProps) => ReactElement;
112
+ export type Icons = Partial<Record<IconName, IconRenderer>>;
113
+ export type VoxLabels = {
114
+ loading: string;
115
+ empty: string;
116
+ contextCut: string;
117
+ contextCopy: string;
118
+ contextPaste: string;
119
+ contextInsertRowAbove: string;
120
+ contextInsertRowBelow: string;
121
+ contextDeleteRows: string;
122
+ contextUndo: string;
123
+ contextRedo: string;
124
+ confirmLargeCopyTitle: string;
125
+ confirmLargeCopyMessage: string;
126
+ confirmOk: string;
127
+ confirmCancel: string;
128
+ };
129
+ export type ToastKind = "loading" | "success" | "error" | "info";
130
+ export type ConfirmOptions = {
131
+ title?: string;
132
+ message: string;
133
+ confirmLabel?: string;
134
+ cancelLabel?: string;
135
+ };
136
+ export type PlatformAdapter = {
137
+ clipboard?: {
138
+ readText?: () => Promise<string>;
139
+ writeText?: (text: string) => Promise<void>;
140
+ };
141
+ notify?: (kind: ToastKind, message: string, opts?: {
142
+ id?: string;
143
+ durationMs?: number;
144
+ }) => string;
145
+ confirm?: (opts: ConfirmOptions) => Promise<boolean>;
146
+ saveFile?: (opts: {
147
+ suggestedName: string;
148
+ mimeType?: string;
149
+ data: string | Blob;
150
+ }) => Promise<void>;
151
+ };
152
+ /** 命令的ハンドル(ref 経由)。 */
153
+ export type VoxSheetHandle = {
154
+ scrollToRow: (row: number) => void;
155
+ scrollToCell: (row: number, col: number) => void;
156
+ focusCell: (row: number, col: number) => void;
157
+ getSelection: () => Selection[];
158
+ setSelection: (sel: Selection[]) => void;
159
+ startEdit: (row: number, col: number) => void;
160
+ /** 未コミット編集の取り出し */
161
+ getLocalEdits: () => CellEdit[];
162
+ /** コミット後にローカル編集と Undo/Redo をクリア */
163
+ clearLocalEdits: () => void;
164
+ undo: () => void;
165
+ redo: () => void;
166
+ /** キャッシュ破棄+再取得(queryKey を使わない明示リフレッシュ) */
167
+ invalidate: () => void;
168
+ };
169
+ export type VoxSheetProps = {
170
+ /** 列定義(controlled)。表示/非表示は配列から除外で表現する。 */
171
+ columns: Column[];
172
+ /** 総行数。FetchResult.total で同期する。 */
173
+ totalRows: number;
174
+ /** 行取得 (query, signal) => Promise<FetchResult> */
175
+ fetchRows: FetchRowsFn;
176
+ /** ホスト独自クエリ入力の無効化キー */
177
+ queryKey?: unknown;
178
+ /** 行の高さ(px)。既定 28。density より優先。 */
179
+ rowHeight?: number;
180
+ /** フォントと行高をセットで切替。既定 "normal"。 */
181
+ density?: "compact" | "normal" | "comfortable";
182
+ /** 列幅既定(px)。既定 120。 */
183
+ defaultColumnWidth?: number;
184
+ /** 先頭から固定する行数。既定 0。 */
185
+ frozenRows?: number;
186
+ /** data-vox-theme を設定。既定 "system"。 */
187
+ theme?: "light" | "dark" | "system";
188
+ className?: string;
189
+ style?: CSSProperties;
190
+ /** 編集 UI 無効(コピー・選択・ナビは可)。 */
191
+ readOnly?: boolean;
192
+ /** 多列ソート(controlled)。 */
193
+ sort?: SortSpec[];
194
+ /** フィルタ(controlled・条件 UI はホスト所有)。 */
195
+ filters?: FilterSpec[];
196
+ /** 検索キーワード。 */
197
+ search?: string;
198
+ /** ハイライト対象セル。 */
199
+ searchHighlights?: CellAddress[];
200
+ /** 現在ヒット。変化でスクロールする。 */
201
+ currentSearchHit?: CellAddress | null;
202
+ renderLoading?: () => ReactNode;
203
+ renderEmpty?: () => ReactNode;
204
+ labels?: Partial<VoxLabels>;
205
+ icons?: Icons;
206
+ platform?: PlatformAdapter;
207
+ /** none→asc→desc をグリッドがトグルし通知。未指定でソートボタン非表示。 */
208
+ onSortChange?: (sort: SortSpec[]) => void;
209
+ /** フィルタ操作要求(ホストがポップオーバー表示)。未指定でフィルタボタン非表示。 */
210
+ onFilterButtonClick?: (col: number, anchor: DOMRect) => void;
211
+ /** 列幅変更(ドラッグ/ダブルクリック自動フィット)。 */
212
+ onColumnResize?: (col: number, width: number) => void;
213
+ /** ヘッダ名編集。未指定でリネーム無効。 */
214
+ onColumnRename?: (col: number, newName: string) => void;
215
+ /** 列追加要求。未指定で追加ボタン非表示。 */
216
+ onAddColumn?: (atCol: number) => void;
217
+ /** ローカル編集の都度。 */
218
+ onCellChange?: (edit: CellEdit) => void;
219
+ /** 未コミット変更の有無。 */
220
+ onDirtyChange?: (hasChanges: boolean) => void;
221
+ /** 行追加(最下行 Enter/末尾)。 */
222
+ onAppendRow?: (atRow: number) => void;
223
+ /** 行挿入要求。 */
224
+ onInsertRow?: (atRow: number, pos: "above" | "below") => void;
225
+ /** 行削除要求。 */
226
+ onDeleteRows?: (rows: number[]) => void;
227
+ /** フィルハンドルのドラッグ/ダブルクリック。 */
228
+ onAutoFill?: (p: {
229
+ sourceRange: Selection;
230
+ direction: "down" | "up" | "left" | "right";
231
+ toEnd: boolean;
232
+ }) => void;
233
+ /** 選択変更。 */
234
+ onSelectionChange?: (selection: Selection[]) => void;
235
+ /** 選択集計(合計/平均/件数)。 */
236
+ onSelectionStats?: (stats: SelectionStats | null) => void;
237
+ /** 既定キー処理前にフック(preventDefault で抑止)。 */
238
+ onCellKeyDown?: (e: ReactKeyboardEvent, ctx: CellContext) => void;
239
+ /** 取得/コミット失敗。 */
240
+ onError?: (err: unknown, ctx: {
241
+ phase: "fetch" | "commit";
242
+ }) => void;
243
+ };
244
+ //# sourceMappingURL=types.d.ts.map