@pixerate/editor 0.23.0 → 0.24.0
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.
- package/README.md +96 -1
- package/THIRD_PARTY_NOTICES.md +51 -0
- package/dist/agent/index.cjs +9 -8
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +4 -3
- package/dist/agent/index.d.ts +4 -3
- package/dist/agent/index.js +3 -2
- package/dist/agent/index.js.map +1 -1
- package/dist/canvas/index.cjs +1210 -17
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +318 -1
- package/dist/canvas/index.d.ts +318 -1
- package/dist/canvas/index.js +1199 -6
- package/dist/canvas/index.js.map +1 -1
- package/dist/{chunk-QBJ22YZR.js → chunk-3CN2WD3X.js} +1354 -206
- package/dist/chunk-3CN2WD3X.js.map +1 -0
- package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
- package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
- package/dist/chunk-5S3Z4PPF.js.map +1 -0
- package/dist/chunk-664LQYFJ.js +115 -0
- package/dist/chunk-664LQYFJ.js.map +1 -0
- package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
- package/dist/chunk-D27YFC46.cjs.map +1 -0
- package/dist/chunk-D6FH2YAX.cjs +131 -0
- package/dist/chunk-D6FH2YAX.cjs.map +1 -0
- package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
- package/dist/chunk-FD4LPFAE.cjs.map +1 -0
- package/dist/chunk-FODNLX5N.js +749 -0
- package/dist/chunk-FODNLX5N.js.map +1 -0
- package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
- package/dist/chunk-FPENXAEJ.js.map +1 -0
- package/dist/chunk-HLIMTC6N.js +1 -0
- package/dist/chunk-HLIMTC6N.js.map +1 -0
- package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
- package/dist/chunk-ITBSKI26.js.map +1 -0
- package/dist/{chunk-XDMXXC4Z.cjs → chunk-MA2F5KHF.cjs} +350 -227
- package/dist/chunk-MA2F5KHF.cjs.map +1 -0
- package/dist/{chunk-RIKBJLS2.cjs → chunk-MCSJFWAO.cjs} +1356 -208
- package/dist/chunk-MCSJFWAO.cjs.map +1 -0
- package/dist/chunk-MKA3AHLV.cjs +256 -0
- package/dist/chunk-MKA3AHLV.cjs.map +1 -0
- package/dist/chunk-OLZJXL4R.cjs +749 -0
- package/dist/chunk-OLZJXL4R.cjs.map +1 -0
- package/dist/chunk-OXSV64JX.js +689 -0
- package/dist/chunk-OXSV64JX.js.map +1 -0
- package/dist/chunk-P3RQ5UJE.cjs +689 -0
- package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
- package/dist/chunk-P6ODPZ4W.js +256 -0
- package/dist/chunk-P6ODPZ4W.js.map +1 -0
- package/dist/chunk-PGNZKFQS.js +685 -0
- package/dist/chunk-PGNZKFQS.js.map +1 -0
- package/dist/chunk-PL4JB3BF.cjs +1 -0
- package/dist/chunk-PL4JB3BF.cjs.map +1 -0
- package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
- package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
- package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
- package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
- package/dist/chunk-TNNJXF46.cjs +115 -0
- package/dist/chunk-TNNJXF46.cjs.map +1 -0
- package/dist/chunk-U5HZSFCS.js +131 -0
- package/dist/chunk-U5HZSFCS.js.map +1 -0
- package/dist/{chunk-K3R5NG2D.js → chunk-U5KWZU4X.js} +251 -128
- package/dist/chunk-U5KWZU4X.js.map +1 -0
- package/dist/chunk-XNORY7M6.cjs +685 -0
- package/dist/chunk-XNORY7M6.cjs.map +1 -0
- package/dist/commands/index.d.cts +5 -353
- package/dist/commands/index.d.ts +5 -353
- package/dist/comment-store-BEMgVlAA.d.cts +135 -0
- package/dist/comment-store-BEMgVlAA.d.ts +135 -0
- package/dist/compare/index.cjs +15 -0
- package/dist/compare/index.cjs.map +1 -0
- package/dist/compare/index.d.cts +58 -0
- package/dist/compare/index.d.ts +58 -0
- package/dist/compare/index.js +15 -0
- package/dist/compare/index.js.map +1 -0
- package/dist/{controller-pePCJLT1.d.cts → controller-BhLLAoi8.d.cts} +45 -4
- package/dist/{controller-pePCJLT1.d.ts → controller-BhLLAoi8.d.ts} +45 -4
- package/dist/documents-BQjzJNe2.d.ts +76 -0
- package/dist/documents-KRTPhvst.d.cts +76 -0
- package/dist/extensions/index.cjs +53 -5
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +7 -3
- package/dist/extensions/index.d.ts +7 -3
- package/dist/extensions/index.js +52 -4
- package/dist/generation/index.cjs +1373 -0
- package/dist/generation/index.cjs.map +1 -0
- package/dist/generation/index.d.cts +554 -0
- package/dist/generation/index.d.ts +554 -0
- package/dist/generation/index.js +1373 -0
- package/dist/generation/index.js.map +1 -0
- package/dist/grammar/index.cjs +48 -3
- package/dist/grammar/index.cjs.map +1 -1
- package/dist/grammar/index.d.cts +322 -100
- package/dist/grammar/index.d.ts +322 -100
- package/dist/grammar/index.js +54 -9
- package/dist/image-editor/index.cjs +1831 -30
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +590 -3
- package/dist/image-editor/index.d.ts +590 -3
- package/dist/image-editor/index.js +1807 -6
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
- package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
- package/dist/index.cjs +162 -25
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -8
- package/dist/index.d.ts +14 -8
- package/dist/index.js +174 -37
- package/dist/index.js.map +1 -1
- package/dist/migrate-iTlm3a8h.d.cts +112 -0
- package/dist/migrate-iTlm3a8h.d.ts +112 -0
- package/dist/persistence/index.cjs +676 -0
- package/dist/persistence/index.cjs.map +1 -0
- package/dist/persistence/index.d.cts +347 -0
- package/dist/persistence/index.d.ts +347 -0
- package/dist/persistence/index.js +676 -0
- package/dist/persistence/index.js.map +1 -0
- package/dist/{registry-D5-R90p0.d.cts → registry-BDe-vlv3.d.ts} +2 -40
- package/dist/registry-D32LpIc4.d.cts +354 -0
- package/dist/{registry-D5-R90p0.d.ts → registry-DnzpgY27.d.cts} +2 -40
- package/dist/registry-evKTP4ls.d.ts +354 -0
- package/dist/schema-DYDGdYL9.d.cts +41 -0
- package/dist/schema-DYDGdYL9.d.ts +41 -0
- package/dist/serializers/index.cjs +4 -3
- package/dist/serializers/index.cjs.map +1 -1
- package/dist/serializers/index.d.cts +2 -1
- package/dist/serializers/index.d.ts +2 -1
- package/dist/serializers/index.js +3 -2
- package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
- package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
- package/dist/spreadsheet/index.cjs +37 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +188 -17
- package/dist/spreadsheet/index.d.ts +188 -17
- package/dist/spreadsheet/index.js +43 -9
- package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
- package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
- package/dist/{track-changes-BSF58RK0.d.ts → track-changes-BK5sVf4_.d.cts} +18 -136
- package/dist/{track-changes-BSF58RK0.d.cts → track-changes-CDjCrwKe.d.ts} +18 -136
- package/package.json +16 -1
- package/dist/chunk-4SUNJZWB.cjs.map +0 -1
- package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
- package/dist/chunk-AXV2ZW34.cjs +0 -118
- package/dist/chunk-AXV2ZW34.cjs.map +0 -1
- package/dist/chunk-B2ZRLN4S.js +0 -118
- package/dist/chunk-B2ZRLN4S.js.map +0 -1
- package/dist/chunk-GVSMRPHB.cjs.map +0 -1
- package/dist/chunk-K3R5NG2D.js.map +0 -1
- package/dist/chunk-MJZBNWG7.js.map +0 -1
- package/dist/chunk-OYXSKQFR.js.map +0 -1
- package/dist/chunk-QBJ22YZR.js.map +0 -1
- package/dist/chunk-QGHGJ56O.js.map +0 -1
- package/dist/chunk-RIKBJLS2.cjs.map +0 -1
- package/dist/chunk-XDMXXC4Z.cjs.map +0 -1
- /package/dist/{chunk-JJDLPEWL.js.map → chunk-3LV6RRPH.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/spreadsheet/formula/dependency-graph.ts","../src/spreadsheet/formula/references.ts","../src/spreadsheet/formula/caret.ts","../src/spreadsheet/numfmt/presets.ts","../src/spreadsheet/formula/format.ts","../src/spreadsheet/datasource/index.ts","../src/spreadsheet/table.ts","../src/spreadsheet/clipboard.ts","../src/spreadsheet/view.ts","../src/spreadsheet/controller.ts","../src/spreadsheet/menu.ts","../src/spreadsheet/actions.ts","../src/spreadsheet/import.ts"],"sourcesContent":["import { ASTNode, parseFormula, WHOLE_COLUMN_END_ROW } from './parser';\nimport { colNameToIndex, indexToColName } from './evaluator';\n\nexport interface CellDep {\n col: string;\n row: number;\n}\n\n/**\n * Dependency key for \"every cell in column `col`\", used by whole-column ranges\n * (`A:A`) instead of expanding a million cell keys.\n */\nexport const columnDependencyKey = (col: string): string => `${col.toUpperCase()}:`;\n\nexport function extractCellDependencies(node: ASTNode): CellDep[] {\n const deps: CellDep[] = [];\n\n const visit = (curr: ASTNode) => {\n if (curr.type === 'CellRef') {\n deps.push({ col: curr.col, row: curr.row });\n } else if (curr.type === 'SpillRef') {\n // A1# is computed by A1: depending on the anchor orders it correctly.\n deps.push({ col: curr.col, row: curr.row });\n } else if (curr.type === 'Range' && curr.endRow >= WHOLE_COLUMN_END_ROW) {\n // Whole-column range: depend on the columns, not on every cell.\n const startC = colNameToIndex(curr.startCol);\n const endC = colNameToIndex(curr.endCol);\n for (let c = Math.min(startC, endC); c <= Math.max(startC, endC); c++) {\n deps.push({ col: indexToColName(c), row: 0 });\n }\n } else if (curr.type === 'Range') {\n const startC = colNameToIndex(curr.startCol);\n const endC = colNameToIndex(curr.endCol);\n const minC = Math.min(startC, endC);\n const maxC = Math.max(startC, endC);\n const minR = Math.min(curr.startRow, curr.endRow);\n const maxR = Math.max(curr.startRow, curr.endRow);\n\n for (let c = minC; c <= maxC; c++) {\n for (let r = minR; r <= maxR; r++) {\n deps.push({ col: indexToColName(c), row: r });\n }\n }\n } else if (curr.type === 'BinaryOp') {\n visit(curr.left);\n visit(curr.right);\n } else if (curr.type === 'UnaryOp') {\n visit(curr.argument);\n } else if (curr.type === 'FunctionCall') {\n curr.args.forEach(visit);\n }\n };\n\n visit(node);\n return deps;\n}\n\nexport class DependencyGraph {\n // Map of cellKey (e.g. \"B2\") -> Set of cellKeys that this cell depends ON\n private dependencies = new Map<string, Set<string>>();\n // Map of cellKey (e.g. \"A1\") -> Set of cellKeys that depend ON this cell (dependents)\n private dependents = new Map<string, Set<string>>();\n // Dynamic-array edges, set by the controller after evaluating an anchor:\n // spilled cells depend on their anchor, and a blocked (#SPILL!) anchor\n // depends on the cells blocking it. Kept apart from formula dependencies,\n // so re-entering a formula doesn't drop them.\n private spillDependencies = new Map<string, Set<string>>();\n private spillDependents = new Map<string, Set<string>>();\n // anchor -> the edges it registered (so they can be replaced).\n private spillEdges = new Map<string, Array<[from: string, to: string]>>();\n\n public setCellFormula(cellKey: string, formulaStr: string | null): void {\n const key = cellKey.toUpperCase();\n\n // Clear existing dependencies\n const oldDeps = this.dependencies.get(key) || new Set();\n for (const dep of oldDeps) {\n this.dependents.get(dep)?.delete(key);\n }\n this.dependencies.delete(key);\n\n if (!formulaStr || !formulaStr.startsWith('=')) {\n return;\n }\n\n try {\n const ast = parseFormula(formulaStr);\n const deps = extractCellDependencies(ast);\n const newDeps = new Set<string>();\n\n for (const d of deps) {\n const depKey = d.row === 0 ? columnDependencyKey(d.col) : `${d.col}${d.row}`.toUpperCase();\n newDeps.add(depKey);\n\n if (!this.dependents.has(depKey)) {\n this.dependents.set(depKey, new Set());\n }\n this.dependents.get(depKey)!.add(key);\n }\n\n this.dependencies.set(key, newDeps);\n } catch {\n // Syntax errors in formula have no valid dependencies\n }\n }\n\n /** Removes every registered formula and dependency. */\n public clear(): void {\n this.dependencies.clear();\n this.dependents.clear();\n this.spillDependencies.clear();\n this.spillDependents.clear();\n this.spillEdges.clear();\n }\n\n /**\n * Records the dynamic-array edges of the anchor `anchorKey`, replacing its\n * previous ones: every key in `spilledKeys` (cells holding its spilled\n * values) depends on the anchor, and the anchor depends on every key in\n * `blockingKeys` (cells that stop it spilling). Pass empty lists to remove\n * the anchor's edges.\n */\n public setSpillEdges(anchorKey: string, spilledKeys: Iterable<string>, blockingKeys: Iterable<string> = []): void {\n const anchor = anchorKey.toUpperCase();\n for (const [from, to] of this.spillEdges.get(anchor) ?? []) {\n this.spillDependencies.get(from)?.delete(to);\n this.spillDependents.get(to)?.delete(from);\n }\n const edges: Array<[string, string]> = [];\n for (const key of spilledKeys) edges.push([key.toUpperCase(), anchor]);\n for (const key of blockingKeys) edges.push([anchor, key.toUpperCase()]);\n for (const [from, to] of edges) {\n if (!this.spillDependencies.has(from)) this.spillDependencies.set(from, new Set());\n this.spillDependencies.get(from)!.add(to);\n if (!this.spillDependents.has(to)) this.spillDependents.set(to, new Set());\n this.spillDependents.get(to)!.add(from);\n }\n if (edges.length > 0) this.spillEdges.set(anchor, edges);\n else this.spillEdges.delete(anchor);\n }\n\n /** The spilled cells registered for `anchorKey` by `setSpillEdges`. */\n public getSpilledKeys(anchorKey: string): string[] {\n const anchor = anchorKey.toUpperCase();\n return (this.spillEdges.get(anchor) ?? []).filter(([, to]) => to === anchor).map(([from]) => from);\n }\n\n /** Formula dependencies plus dynamic-array (spill) dependencies of a cell. */\n public getDependencies(cellKey: string): string[] {\n const key = cellKey.toUpperCase();\n return unionOf(this.dependencies.get(key), this.spillDependencies.get(key));\n }\n\n /** Cells depending on `cellKey`, through formulas or spills. */\n public getDependents(cellKey: string): string[] {\n const key = cellKey.toUpperCase();\n return unionOf(this.dependents.get(key), this.spillDependents.get(key));\n }\n\n /**\n * Detects if there is a cycle containing cellKey.\n */\n public hasCycle(cellKey: string): boolean {\n const key = cellKey.toUpperCase();\n const visited = new Set<string>();\n const recStack = new Set<string>();\n\n const dfs = (node: string): boolean => {\n visited.add(node);\n recStack.add(node);\n\n const deps = this.getDependencies(node);\n for (const neighbor of deps) {\n if (!visited.has(neighbor)) {\n if (dfs(neighbor)) return true;\n } else if (recStack.has(neighbor)) {\n return true;\n }\n }\n\n recStack.delete(node);\n return false;\n };\n\n return dfs(key);\n }\n\n /**\n * Returns cells affected by updating cellKey in topological order.\n */\n public getEvaluationOrder(startCellKey: string): { order: string[]; hasCycle: boolean } {\n const start = startCellKey.toUpperCase();\n const visited = new Set<string>();\n const recStack = new Set<string>();\n const order: string[] = [];\n let cycleDetected = false;\n\n // Collect all downstream affected cells (reachability via dependents)\n const affected = new Set<string>();\n const collectAffected = (node: string) => {\n affected.add(node);\n const directDependents = this.dependents.get(node) || new Set();\n for (const dep of directDependents) {\n if (!affected.has(dep)) {\n collectAffected(dep);\n }\n }\n };\n collectAffected(start);\n\n // Topological sort among affected cells\n const visit = (node: string) => {\n if (recStack.has(node)) {\n cycleDetected = true;\n return;\n }\n if (visited.has(node)) return;\n\n recStack.add(node);\n visited.add(node);\n\n // Visit nodes that this node depends on, IF they are in the affected set\n const deps = this.dependencies.get(node) || new Set();\n for (const neighbor of deps) {\n if (affected.has(neighbor)) {\n visit(neighbor);\n }\n }\n\n recStack.delete(node);\n order.push(node);\n };\n\n for (const node of affected) {\n if (!visited.has(node)) {\n visit(node);\n }\n }\n\n return { order, hasCycle: cycleDetected };\n }\n\n /**\n * Plans a recalculation over `cellKeys` (and, with `includeDependents`, every\n * cell that transitively depends on them). Returns the keys in evaluation\n * order (dependencies first) and the set of keys that are part of a cycle,\n * which must be marked `#CYCLE!` instead of evaluated. Every member of a\n * cycle is reported, not just the cell that closed it.\n */\n public getEvaluationPlan(\n cellKeys: Iterable<string>,\n options: { includeDependents?: boolean } = {},\n ): { order: string[]; cyclic: Set<string> } {\n const nodes = new Set<string>();\n const queue: string[] = [];\n for (const key of cellKeys) {\n const upper = key.toUpperCase();\n if (!nodes.has(upper)) {\n nodes.add(upper);\n queue.push(upper);\n }\n }\n if (options.includeDependents) {\n while (queue.length > 0) {\n const node = queue.pop()!;\n const direct = [\n ...(this.dependents.get(node) ?? []),\n ...(this.spillDependents.get(node) ?? []),\n ...(this.dependents.get(columnDependencyKey(node.replace(/\\d+$/, ''))) ?? []),\n ];\n for (const dep of direct) {\n if (!nodes.has(dep)) {\n nodes.add(dep);\n queue.push(dep);\n }\n }\n }\n }\n\n // Edges point from a cell to the cells it depends on, restricted to `nodes`.\n // Whole-column dependencies expand to the planned cells in that column.\n const neighbors = (node: string): string[] => {\n const result: string[] = [];\n for (const dep of this.getDependencies(node)) {\n if (dep.endsWith(':')) {\n const col = dep.slice(0, -1);\n for (const candidate of nodes) {\n if (candidate.replace(/\\d+$/, '') === col) result.push(candidate);\n }\n } else if (nodes.has(dep)) {\n result.push(dep);\n }\n }\n return result;\n };\n\n // Iterative Tarjan: SCCs are emitted dependencies-first.\n const order: string[] = [];\n const cyclic = new Set<string>();\n const index = new Map<string, number>();\n const low = new Map<string, number>();\n const stack: string[] = [];\n const onStack = new Set<string>();\n let counter = 0;\n\n for (const root of nodes) {\n if (index.has(root)) continue;\n const work: Array<{ node: string; edges: string[]; next: number }> = [];\n const enter = (node: string) => {\n index.set(node, counter);\n low.set(node, counter);\n counter++;\n stack.push(node);\n onStack.add(node);\n work.push({ node, edges: neighbors(node), next: 0 });\n };\n enter(root);\n\n while (work.length > 0) {\n const frame = work[work.length - 1];\n if (frame.next < frame.edges.length) {\n const target = frame.edges[frame.next++];\n if (!index.has(target)) {\n enter(target);\n } else if (onStack.has(target)) {\n low.set(frame.node, Math.min(low.get(frame.node)!, index.get(target)!));\n }\n continue;\n }\n\n work.pop();\n if (work.length > 0) {\n const parent = work[work.length - 1].node;\n low.set(parent, Math.min(low.get(parent)!, low.get(frame.node)!));\n }\n\n if (low.get(frame.node) === index.get(frame.node)) {\n const component: string[] = [];\n let member: string;\n do {\n member = stack.pop()!;\n onStack.delete(member);\n component.push(member);\n } while (member !== frame.node);\n\n const isCycle = component.length > 1 || frame.edges.includes(frame.node);\n for (const key of component) {\n order.push(key);\n if (isCycle) cyclic.add(key);\n }\n }\n }\n }\n\n return { order, cyclic };\n }\n}\n\nfunction unionOf(a: Set<string> | undefined, b: Set<string> | undefined): string[] {\n if (!b || b.size === 0) return Array.from(a ?? []);\n if (!a || a.size === 0) return Array.from(b);\n return Array.from(new Set([...a, ...b]));\n}\n","import { tokenizeFormula } from './lexer';\nimport { colNameToIndex, indexToColName } from './evaluator';\n\n/**\n * A row or column insertion/deletion. `index` is the 0-based position of the\n * inserted or deleted row/column.\n */\nexport interface StructuralChange {\n axis: 'row' | 'col';\n index: number;\n type: 'insert' | 'delete';\n}\n\nconst CELL_PART = /^(\\$?)([A-Za-z]+)(\\$?)(\\d+)$/;\nconst COLUMN_PART = /^(\\$?)([A-Za-z]+)$/;\nconst REF_CHAR = /[A-Za-z0-9_$.:]/;\n\ninterface RefPart {\n colAbs: string;\n col: number; // 0-based column index\n rowAbs: string;\n row: number | null; // 0-based row index; null for whole-column parts (A:A)\n}\n\nfunction parsePart(text: string): RefPart | null {\n const cell = CELL_PART.exec(text);\n if (cell) {\n return {\n colAbs: cell[1],\n col: colNameToIndex(cell[2]),\n rowAbs: cell[3],\n row: parseInt(cell[4], 10) - 1,\n };\n }\n const column = COLUMN_PART.exec(text);\n if (column) {\n return { colAbs: column[1], col: colNameToIndex(column[2]), rowAbs: '', row: null };\n }\n return null;\n}\n\nfunction formatPart(part: RefPart): string {\n const col = `${part.colAbs}${indexToColName(part.col)}`;\n return part.row === null ? col : `${col}${part.rowAbs}${part.row + 1}`;\n}\n\n/** Shifts one coordinate; returns null when it points at a deleted row/column. */\nfunction shiftCoordinate(value: number, change: StructuralChange): number | null {\n if (change.type === 'insert') {\n return value >= change.index ? value + 1 : value;\n }\n if (value === change.index) return null;\n return value > change.index ? value - 1 : value;\n}\n\n/** Shifts a range's [lo, hi] bounds; returns null when the whole span is deleted. */\nfunction shiftSpan(lo: number, hi: number, change: StructuralChange): [number, number] | null {\n if (change.type === 'insert') {\n return [lo >= change.index ? lo + 1 : lo, hi >= change.index ? hi + 1 : hi];\n }\n if (lo === change.index && hi === change.index) return null;\n // Deleting inside or at the edge of a range shrinks it, like spreadsheets do.\n return [lo > change.index ? lo - 1 : lo, hi >= change.index ? hi - 1 : hi];\n}\n\nfunction rewriteReference(text: string, change: StructuralChange): string {\n const [startText, endText] = text.split(':');\n const start = parsePart(startText);\n if (!start) return text;\n\n const key = change.axis === 'row' ? 'row' : 'col';\n\n if (endText === undefined) {\n if (start[key] === null) return text;\n const shifted = shiftCoordinate(start[key] as number, change);\n if (shifted === null) return '#REF!';\n return formatPart({ ...start, [key]: shifted });\n }\n\n const end = parsePart(endText);\n if (!end) return text;\n if (start[key] === null || end[key] === null) return text; // e.g. rows of A:A\n\n const startValue = start[key] as number;\n const endValue = end[key] as number;\n const span = shiftSpan(Math.min(startValue, endValue), Math.max(startValue, endValue), change);\n if (span === null) return '#REF!';\n const [lo, hi] = span;\n const newStart = { ...start, [key]: startValue <= endValue ? lo : hi };\n const newEnd = { ...end, [key]: startValue <= endValue ? hi : lo };\n return `${formatPart(newStart)}:${formatPart(newEnd)}`;\n}\n\n/**\n * Rewrites the cell and range references in `formula` after a row or column\n * is inserted or deleted, the way spreadsheet apps do: references after the\n * change shift, ranges grow or shrink, and references to a deleted row/column\n * become `#REF!`. Absolute (`$`) markers are kept. String literals, property\n * references and function names are left untouched.\n */\nexport function shiftFormulaReferences(formula: string, change: StructuralChange): string {\n return mapFormulaReferences(formula, (text) => rewriteReference(text, change));\n}\n\n/**\n * Calls `rewrite` with the source text of every cell or range reference in\n * `formula` (e.g. `\"$A1\"`, `\"B2:C10\"`, `\"A:A\"`) and splices in its result.\n * For a spill reference (`A1#`) it receives the anchor (`\"A1\"`) and the `#`\n * is kept, unless the rewrite returns `#REF!`. String literals, property references and function names (e.g. `LOG10(`)\n * are skipped. Formulas that fail to tokenize are returned unchanged.\n */\nexport function mapFormulaReferences(formula: string, rewrite: (reference: string) => string): string {\n if (!formula.startsWith('=')) return formula;\n\n let tokens;\n try {\n tokens = tokenizeFormula(formula);\n } catch {\n return formula;\n }\n\n let result = '';\n let cursor = 0;\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (token.type !== 'CELL_REF' && token.type !== 'RANGE' && token.type !== 'SPILL_REF') continue;\n // Function names that look like cell references (e.g. LOG10) are calls.\n if (tokens[i + 1]?.type === 'LPAREN') continue;\n\n let end = token.position;\n while (end < formula.length && REF_CHAR.test(formula[end])) end++;\n const original = formula.slice(token.position, end);\n\n if (token.type === 'SPILL_REF') {\n // A1#: the anchor is rewritten like a cell reference; `#` stays.\n const rewritten = rewrite(original);\n result += formula.slice(cursor, token.position) + (rewritten === '#REF!' ? rewritten : `${rewritten}#`);\n cursor = end + 1;\n continue;\n }\n\n result += formula.slice(cursor, token.position) + rewrite(original);\n cursor = end;\n }\n return result + formula.slice(cursor);\n}\n\n/**\n * Moves a formula by (`rowOffset`, `colOffset`), as copy/paste and autofill\n * do: relative row/column parts shift, `$`-absolute parts stay. A reference\n * pushed above row 1 or left of column A becomes `#REF!`.\n */\nexport function offsetFormulaReferences(formula: string, rowOffset: number, colOffset: number): string {\n if (rowOffset === 0 && colOffset === 0) return formula;\n return mapFormulaReferences(formula, (text) => {\n const parts = text.split(':').map(parsePart);\n if (parts.some((p) => p === null)) return text;\n const moved: RefPart[] = [];\n for (const part of parts as RefPart[]) {\n const col = part.colAbs ? part.col : part.col + colOffset;\n const row = part.row === null || part.rowAbs ? part.row : part.row + rowOffset;\n if (col < 0 || (row !== null && row < 0)) return '#REF!';\n moved.push({ ...part, col, row });\n }\n return moved.map(formatPart).join(':');\n });\n}\n\n/** A 0-based cell position. */\nexport interface CellPosition {\n row: number;\n col: number;\n}\n\n// Ranges larger than this are never remapped cell by cell.\nconst MAX_REMAP_RANGE_CELLS = 100_000;\n\n/**\n * Rewrites references when cells *move* (sort, transpose): references follow\n * the cell they point at, whether relative or absolute. `moveCell` returns a\n * cell's new position, or null when it did not move. A range is remapped only\n * when its cells moved together as a rectangle of the same size (e.g. a\n * one-row range inside a sorted row, or a range inside a transposed block);\n * otherwise it is kept, since it still covers the same rows and columns.\n */\nexport function remapFormulaReferences(\n formula: string,\n moveCell: (position: CellPosition) => CellPosition | null,\n): string {\n return mapFormulaReferences(formula, (text) => {\n const parts = text.split(':').map(parsePart);\n if (parts.some((p) => p === null)) return text;\n const [start, end] = parts as RefPart[];\n if (start.row === null || (end && end.row === null)) return text; // whole columns\n\n if (!end) {\n const target = moveCell({ row: start.row, col: start.col });\n return target ? formatPart({ ...start, row: target.row, col: target.col }) : text;\n }\n\n const lo = { row: Math.min(start.row, end.row!), col: Math.min(start.col, end.col) };\n const hi = { row: Math.max(start.row, end.row!), col: Math.max(start.col, end.col) };\n const area = (hi.row - lo.row + 1) * (hi.col - lo.col + 1);\n if (area > MAX_REMAP_RANGE_CELLS) return text;\n\n let minR = Infinity;\n let maxR = -Infinity;\n let minC = Infinity;\n let maxC = -Infinity;\n let movedAny = false;\n const targets = new Set<string>();\n for (let r = lo.row; r <= hi.row; r++) {\n for (let c = lo.col; c <= hi.col; c++) {\n const moved = moveCell({ row: r, col: c });\n if (moved) movedAny = true;\n const t = moved ?? { row: r, col: c };\n targets.add(`${t.row}:${t.col}`);\n minR = Math.min(minR, t.row);\n maxR = Math.max(maxR, t.row);\n minC = Math.min(minC, t.col);\n maxC = Math.max(maxC, t.col);\n }\n }\n // The cells must still form a filled rectangle of the same area.\n if (!movedAny || targets.size !== area || (maxR - minR + 1) * (maxC - minC + 1) !== area) {\n return text;\n }\n return `${formatPart({ ...start, row: minR, col: minC })}:${formatPart({ ...end, row: maxR, col: maxC })}`;\n });\n}\n","import {\n getFormulaArgumentSpecIndex,\n getFormulaFunction,\n getFormulaSignature,\n getFormulaSignatureParts,\n searchFormulaFunctions,\n type FormulaArgumentSpec,\n type FormulaFunctionDefinition,\n type FormulaSignaturePart,\n} from './registry';\n\n/**\n * Caret analysis for formula autocomplete. The input is scanned tolerantly\n * (unterminated strings and unbalanced parentheses are expected while typing),\n * so this never throws.\n */\nexport interface FormulaCaretContext {\n /** The function-name prefix being typed right before the caret, if any. */\n prefix: { text: string; start: number; end: number } | null;\n /** The innermost function call containing the caret, if any. */\n call: {\n name: string;\n /** 0-based index of the argument the caret is in. */\n argIndex: number;\n /** Offset of the call's opening parenthesis. */\n openParen: number;\n } | null;\n}\n\nconst EMPTY: FormulaCaretContext = { prefix: null, call: null };\n\n/** Determines what is being typed at `caret` in `input` (a formula starting with `=`). */\nexport function getFormulaCaretContext(input: string, caret: number = input.length): FormulaCaretContext {\n const leading = input.length - input.trimStart().length;\n if (input[leading] !== '=') return EMPTY;\n const end = Math.max(0, Math.min(caret, input.length));\n if (end <= leading) return EMPTY;\n\n const stack: Array<{ name: string | null; argIndex: number; openParen: number }> = [];\n let quote: string | null = null;\n let inProperty = false;\n\n for (let i = leading + 1; i < end; i++) {\n const char = input[i];\n if (quote) {\n if (char === '\\\\') i++;\n else if (char === quote) quote = null;\n continue;\n }\n if (inProperty) {\n if (char === ']') inProperty = false;\n continue;\n }\n if (char === '\"' || char === \"'\") {\n quote = char;\n } else if (char === '[') {\n inProperty = true;\n } else if (char === '(') {\n const name = /([A-Za-z_][A-Za-z0-9_.]*)\\s*$/.exec(input.slice(leading + 1, i));\n const isFunction = name && !/^\\$?[A-Za-z]+\\$?\\d+$/.test(name[1]) && !/[:$]$/.test(input.slice(0, i - name[0].length));\n stack.push({ name: isFunction ? name![1].toUpperCase() : null, argIndex: 0, openParen: i });\n } else if (char === ')') {\n stack.pop();\n } else if (char === ',' && stack.length > 0) {\n stack[stack.length - 1].argIndex++;\n }\n }\n\n if (quote || inProperty) {\n // Inside a string or [property]: no name completion, but keep the call hint.\n return { prefix: null, call: innermostCall(stack) };\n }\n\n let prefix: FormulaCaretContext['prefix'] = null;\n const before = input.slice(leading + 1, end);\n const word = /[A-Za-z_][A-Za-z0-9_.]*$/.exec(before);\n if (word) {\n const start = leading + 1 + word.index;\n const preceding = input[start - 1] ?? '';\n // Not a range end (A1:B), an absolute ref ($A) or part of a number (1E5).\n if (!/[:$0-9.]/.test(preceding)) {\n prefix = { text: word[0], start, end };\n }\n }\n\n return { prefix, call: innermostCall(stack) };\n}\n\nfunction innermostCall(stack: Array<{ name: string | null; argIndex: number; openParen: number }>) {\n for (let i = stack.length - 1; i >= 0; i--) {\n const frame = stack[i];\n if (frame.name) return { name: frame.name, argIndex: frame.argIndex, openParen: frame.openParen };\n }\n return null;\n}\n\n/** A function suggestion for autocomplete. */\nexport interface FormulaFunctionSuggestion {\n name: string;\n signature: string;\n description: string;\n category: FormulaFunctionDefinition['category'];\n}\n\nexport interface FormulaActiveCall {\n name: string;\n signature: string;\n description: string;\n /** Signature split into parts, with the active argument marked. */\n parts: FormulaSignaturePart[];\n /** 0-based argument index at the caret. */\n argIndex: number;\n /** Spec of the active argument, if the function takes an argument there. */\n argument: FormulaArgumentSpec | null;\n}\n\nexport interface FormulaHints {\n context: FormulaCaretContext;\n /** Functions matching the name prefix at the caret (empty when not typing a name). */\n suggestions: FormulaFunctionSuggestion[];\n /** The known function whose arguments the caret is in. */\n activeCall: FormulaActiveCall | null;\n}\n\nconst toSuggestion = (def: FormulaFunctionDefinition): FormulaFunctionSuggestion => ({\n name: def.name,\n signature: getFormulaSignature(def),\n description: def.description,\n category: def.category,\n});\n\n/** Everything formula autocomplete UIs need for `input` with the caret at `caret`. */\nexport function getFormulaHints(\n input: string,\n caret: number = input.length,\n options: { limit?: number } = {},\n): FormulaHints {\n const context = getFormulaCaretContext(input, caret);\n let suggestions: FormulaFunctionSuggestion[] = [];\n if (context.prefix) {\n const query = context.prefix.text.toUpperCase();\n // Suggest names that start with what was typed; hide an exact, complete match.\n suggestions = searchFormulaFunctions(query, { limit: undefined })\n .filter((def) => def.name.startsWith(query))\n .slice(0, options.limit ?? 8)\n .map(toSuggestion);\n const followedByParen = input.slice(context.prefix.end).trimStart().startsWith('(');\n if (followedByParen || (suggestions.length === 1 && suggestions[0].name === query)) suggestions = [];\n }\n\n let activeCall: FormulaActiveCall | null = null;\n if (context.call) {\n const def = getFormulaFunction(context.call.name);\n if (def) {\n const specIndex = getFormulaArgumentSpecIndex(def, context.call.argIndex);\n activeCall = {\n name: def.name,\n signature: getFormulaSignature(def),\n description: def.description,\n parts: getFormulaSignatureParts(def, context.call.argIndex),\n argIndex: context.call.argIndex,\n argument: specIndex >= 0 ? def.args[specIndex] : null,\n };\n }\n }\n\n return { context, suggestions, activeCall };\n}\n\n/**\n * Replaces the name prefix at the caret with `NAME(`, returning the new input\n * and caret position (just inside the parenthesis).\n */\nexport function applyFormulaSuggestion(\n input: string,\n caret: number,\n name: string,\n): { value: string; caret: number } {\n const context = getFormulaCaretContext(input, caret);\n const start = context.prefix?.start ?? caret;\n const end = context.prefix?.end ?? caret;\n // Skip an existing \"(\" so accepting inside \"SU|(\" doesn't double it.\n const hasParen = input[end] === '(';\n const insert = hasParen ? name.toUpperCase() : `${name.toUpperCase()}(`;\n const value = input.slice(0, start) + insert + input.slice(end);\n return { value, caret: start + insert.length + (hasParen ? 1 : 0) };\n}\n","/**\n * Common number formats offered by the \"Format cells\" menu, and the mapping\n * between format codes and the coarser `CellFormat` kinds.\n */\nimport type { CellFormat } from '../types';\nimport { NumberFormat } from './index';\n\nexport interface NumberFormatPreset {\n id: 'general' | 'number' | 'currency' | 'percent' | 'date' | 'time';\n label: string;\n code: string;\n}\n\n/** Presets of the \"Format cells\" menu (en-US). */\nexport const NUMBER_FORMAT_PRESETS: readonly NumberFormatPreset[] = [\n { id: 'general', label: 'General', code: 'General' },\n { id: 'number', label: 'Number (0.00)', code: '0.00' },\n { id: 'currency', label: 'Currency ($1,234.50)', code: '\"$\"#,##0.00' },\n { id: 'percent', label: 'Percent (12.5%)', code: '0.0%' },\n { id: 'date', label: 'Date (3/14/2026)', code: 'm/d/yyyy' },\n { id: 'time', label: 'Time (1:30 PM)', code: 'h:mm AM/PM' },\n];\n\n/**\n * Format code for a `CellFormat` kind, used to display numbers in cells that\n * have a kind but no format code: `currency` → `\"$\"#,##0.00`, `percentage` →\n * `0%`, `date` → `m/d/yyyy`. Other kinds (`number`, `text` — the default of\n * new columns —, `badge`, `status`, `assignee`) display as General (undefined).\n */\nexport function numberFormatForCellFormat(format: CellFormat | undefined): string | undefined {\n switch (format) {\n case 'currency':\n return '\"$\"#,##0.00';\n case 'percentage':\n return '0%';\n case 'date':\n return 'm/d/yyyy';\n default:\n return undefined;\n }\n}\n\n/**\n * `CellFormat` kind matching a format code (`\"$\"#,##0.00` → `currency`,\n * `0%` → `percentage`, `m/d/yyyy` → `date`, `0.00` → `number`, `@` → `text`);\n * undefined for General, times and custom codes.\n */\nexport function cellFormatForNumberFormat(code: string): CellFormat | undefined {\n switch (NumberFormat.parseCached(code).kind()) {\n case 'number':\n case 'fraction':\n case 'scientific':\n case 'special':\n return 'number';\n case 'currency':\n case 'accounting':\n return 'currency';\n case 'percentage':\n return 'percentage';\n case 'date':\n return 'date';\n case 'text':\n return 'text';\n default:\n return undefined;\n }\n}\n\n/** True for an empty or `General` code. */\nexport const isGeneralNumberFormat = (code: string | undefined): boolean =>\n code === undefined || NumberFormat.parseCached(code).isGeneral();\n","import type { CellData } from '../types';\nimport { formatTextFunction, NumberFormat, type FormattedNumberValue } from '../numfmt';\nimport { isGeneralNumberFormat, numberFormatForCellFormat } from '../numfmt/presets';\nimport { isBlank, toText } from './values';\n\ntype DisplayCell = Pick<CellData, 'value' | 'error' | 'numberFormat' | 'format'>;\n\n/**\n * How a cell is shown: its error, or its value formatted with its number\n * format code (`numberFormat`: set explicitly, inherited from the column, or\n * chosen for typed input, e.g. `\"$\"#,##0.00` for `$1,200.50`). Numbers in a\n * cell with a `currency` / `percentage` / `date` `CellFormat` but no code use\n * that kind's code. Without a code (General), numbers use up to 15\n * significant digits and booleans show as TRUE/FALSE.\n *\n * `numeric` is true for numbers (and dates shown through a date format):\n * grids right-align those. `color` comes from a `[Red]` / `[ColorN]` tag.\n */\nexport function formatCellForDisplay(cell: DisplayCell | null | undefined): FormattedNumberValue {\n if (!cell) return { text: '', numeric: false };\n if (cell.error) return { text: cell.error, numeric: false };\n const { value } = cell;\n const code = cell.numberFormat ?? (typeof value === 'number' ? numberFormatForCellFormat(cell.format) : undefined);\n if (code !== undefined && !isGeneralNumberFormat(code) && !isBlank(value) && typeof value !== 'boolean') {\n return NumberFormat.parseCached(code).format(value);\n }\n return { text: toText(value), numeric: typeof value === 'number' };\n}\n\n/** The text a cell shows (see `formatCellForDisplay`). Used by grids, CSV export and the clipboard. */\nexport function formatCellDisplay(cell: DisplayCell | null | undefined): string {\n return formatCellForDisplay(cell).text;\n}\n\n/**\n * Formats a value with a number format code, as `TEXT()` does (see\n * `formatTextFunction`). Null when the value can't be shown with that code\n * (a date out of range, a code over 255 characters, an error value).\n */\nexport function formatValueWithCode(value: unknown, format: string): string | null {\n const result = formatTextFunction(value, format);\n return 'text' in result ? result.text : null;\n}\n","import { SpreadsheetDataSource, SpreadsheetRow, SpreadsheetColumn } from '../types';\n\nexport class DataSourceBinder {\n private dataSources = new Map<string, SpreadsheetDataSource>();\n\n public register(dataSource: SpreadsheetDataSource): void {\n this.dataSources.set(dataSource.id, dataSource);\n }\n\n public unregister(dataSourceId: string): void {\n this.dataSources.delete(dataSourceId);\n }\n\n public getDataSource(id: string): SpreadsheetDataSource | undefined {\n return this.dataSources.get(id);\n }\n\n /**\n * Generates or reconciles spreadsheet rows from a primary data source.\n */\n public syncRows(\n currentRows: SpreadsheetRow[],\n dataSourceId: string\n ): SpreadsheetRow[] {\n const ds = this.dataSources.get(dataSourceId);\n if (!ds) return currentRows;\n\n const records = ds.getRecords();\n const existingRecordRowMap = new Map<string, SpreadsheetRow>();\n const freeformRows: SpreadsheetRow[] = [];\n\n for (const row of currentRows) {\n if (row.type === 'record' && row.recordId) {\n existingRecordRowMap.set(row.recordId, row);\n } else {\n freeformRows.push(row);\n }\n }\n\n const nextRows: SpreadsheetRow[] = [];\n let rowIndex = 0;\n\n for (const record of records) {\n const existing = existingRecordRowMap.get(record.id);\n nextRows.push({\n ...(existing?.hidden ? { hidden: true } : {}),\n id: existing?.id || `row_${record.id}`,\n index: rowIndex++,\n height: existing?.height || 32,\n recordId: record.id,\n type: 'record'\n });\n existingRecordRowMap.delete(record.id);\n }\n\n // Append preserved freeform rows\n for (const freeform of freeformRows) {\n nextRows.push({\n ...freeform,\n index: rowIndex++\n });\n }\n\n return nextRows;\n }\n\n /**\n * Resolves a record's bound field value.\n */\n public resolveBoundValue(\n dataSourceId: string,\n recordId: string,\n field: string\n ): any {\n const ds = this.dataSources.get(dataSourceId);\n if (!ds) return undefined;\n\n const records = ds.getRecords();\n const record = records.find((r) => r.id === recordId);\n return record ? record[field] : undefined;\n }\n\n /**\n * Dispatches an update to the underlying data source.\n */\n public async commitBoundValue(\n dataSourceId: string,\n recordId: string,\n field: string,\n value: any\n ): Promise<void> {\n const ds = this.dataSources.get(dataSourceId);\n if (!ds) return;\n await ds.updateRecord(recordId, field, value);\n }\n}\n","/**\n * Pure helpers behind the controller's table operations: value comparison\n * for sorting, filter matching, group aggregates, autofill series and range\n * arithmetic. Framework packages use these through `SpreadsheetController`.\n */\nimport type { CellRange, FilterRule, GroupAggregate, SortDirection } from './types';\nimport type { CellPosition } from './formula';\nimport { compareValues, isFormulaError, numericValue, parseIsoDate, sortCompareValues } from './formula/values';\nimport { parseCellInput } from './formula/parse-input';\n\n// --- Ranges ---\n\n/** Returns `range` with start <= end on both axes. */\nexport function normalizeRange(range: CellRange): CellRange {\n return {\n startRow: Math.min(range.startRow, range.endRow),\n startCol: Math.min(range.startCol, range.endCol),\n endRow: Math.max(range.startRow, range.endRow),\n endCol: Math.max(range.startCol, range.endCol),\n };\n}\n\nexport function rangeContains(range: CellRange, row: number, col: number): boolean {\n const r = normalizeRange(range);\n return row >= r.startRow && row <= r.endRow && col >= r.startCol && col <= r.endCol;\n}\n\nexport function rangesIntersect(a: CellRange, b: CellRange): boolean {\n const x = normalizeRange(a);\n const y = normalizeRange(b);\n return x.startRow <= y.endRow && y.startRow <= x.endRow && x.startCol <= y.endCol && y.startCol <= x.endCol;\n}\n\n/** True when `inner` lies entirely inside `outer`. */\nexport function rangeContainsRange(outer: CellRange, inner: CellRange): boolean {\n const o = normalizeRange(outer);\n const i = normalizeRange(inner);\n return i.startRow >= o.startRow && i.endRow <= o.endRow && i.startCol >= o.startCol && i.endCol <= o.endCol;\n}\n\nexport function isSingleCellRange(range: CellRange): boolean {\n const r = normalizeRange(range);\n return r.startRow === r.endRow && r.startCol === r.endCol;\n}\n\n// --- Values ---\n\nconst NUMBER_PATTERN = /^[-+]?(\\d+\\.?\\d*|\\.\\d+)(e[-+]?\\d+)?$/i;\nconst ISO_DATE_PATTERN = /^(\\d{4})-(\\d{2})-(\\d{2})$/;\n\nexport function isBlankValue(value: unknown): boolean {\n return value === null || value === undefined || (typeof value === 'string' && value.trim() === '');\n}\n\n/** The numeric value of a number or numeric string, or null. */\nexport function toNumber(value: unknown): number | null {\n if (typeof value === 'number') return Number.isFinite(value) ? value : null;\n if (typeof value === 'string') {\n const trimmed = value.trim();\n if (NUMBER_PATTERN.test(trimmed)) return parseFloat(trimmed);\n }\n return null;\n}\n\nconst collator =\n typeof Intl !== 'undefined' ? new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' }) : null;\n\nfunction compareText(a: string, b: string): number {\n return collator ? collator.compare(a, b) : a < b ? -1 : a > b ? 1 : 0;\n}\n\n/**\n * Sort order for cell values, as in Excel: numbers (ascending), then text,\n * booleans and errors; `desc` reverses that order. Numbers compare at 15\n * significant digits and ISO dates chronologically. Text uses a natural,\n * case-insensitive order (\"Item 2\" before \"Item 10\"). Blanks always sort\n * last, whatever the direction.\n */\nexport function compareCellValues(a: unknown, b: unknown, direction: SortDirection = 'asc'): number {\n const aBlank = isBlankValue(a);\n const bBlank = isBlankValue(b);\n if (aBlank || bBlank) return aBlank === bBlank ? 0 : aBlank ? 1 : -1;\n\n let result: number;\n if (isPlainText(a) && isPlainText(b) && !(parseIsoDate(a) && parseIsoDate(b))) {\n result = compareText(a, b);\n } else {\n result = sortCompareValues(a, b);\n }\n if (result === 0) return 0;\n return direction === 'desc' ? -Math.sign(result) : Math.sign(result);\n}\n\nconst isPlainText = (value: unknown): value is string => typeof value === 'string' && !isFormulaError(value);\n\n// --- Filters ---\n\ntype FilterKind = 'number' | 'text' | 'boolean';\n\n/**\n * A cell value for filtering: numeric text (e.g. from a data source) counts\n * as a number, like criteria in COUNTIF. ISO dates order with numbers\n * (as serial dates).\n */\nfunction filterValue(value: unknown): { value: unknown; kind: FilterKind } | null {\n if (isBlankValue(value) || isFormulaError(value)) return null;\n if (typeof value === 'number') return Number.isFinite(value) ? { value, kind: 'number' } : null;\n if (typeof value === 'boolean') return { value, kind: 'boolean' };\n const num = numericValue(value);\n if (num !== null) return { value: num, kind: 'number' };\n const text = String(value);\n return { value: text, kind: parseIsoDate(text) ? 'number' : 'text' };\n}\n\n/** A filter operand, read with the typed-input rules (\"1,000\", \"10%\", \"3/4/2026\", \"TRUE\"). */\nfunction filterOperand(operand: unknown): { value: unknown; kind: FilterKind } | null {\n if (typeof operand !== 'string') return filterValue(operand);\n if (operand.trim() === '') return null;\n const parsed = parseCellInput(operand.trim());\n if (parsed.type === 'number' || parsed.type === 'date' || parsed.type === 'boolean') return filterValue(parsed.value);\n return { value: operand, kind: 'text' };\n}\n\nfunction compareForFilter(value: unknown, operand: unknown): number | null {\n const a = filterValue(value);\n const b = filterOperand(operand);\n // Numbers (and dates), text and booleans never compare with each other.\n if (!a || !b || a.kind !== b.kind) return null;\n return compareValues(a.value, b.value);\n}\n\nfunction looselyEquals(value: unknown, operand: unknown): boolean {\n const c = compareForFilter(value, operand);\n if (c !== null) return c === 0;\n return String(value ?? '').trim().toLowerCase() === String(operand ?? '').trim().toLowerCase();\n}\n\n/** Whether a cell value passes one filter rule. */\nexport function matchesFilterRule(value: unknown, rule: FilterRule): boolean {\n const text = String(value ?? '').toLowerCase();\n switch (rule.operator) {\n case 'equals':\n return looselyEquals(value, rule.value);\n case 'notEquals':\n return !looselyEquals(value, rule.value);\n case 'contains':\n return text.includes(String(rule.value ?? '').toLowerCase());\n case 'notContains':\n return !text.includes(String(rule.value ?? '').toLowerCase());\n case 'greaterThan': {\n const c = compareForFilter(value, rule.value);\n return c !== null && c > 0;\n }\n case 'greaterThanOrEqual': {\n const c = compareForFilter(value, rule.value);\n return c !== null && c >= 0;\n }\n case 'lessThan': {\n const c = compareForFilter(value, rule.value);\n return c !== null && c < 0;\n }\n case 'lessThanOrEqual': {\n const c = compareForFilter(value, rule.value);\n return c !== null && c <= 0;\n }\n case 'between': {\n const lo = compareForFilter(value, rule.value);\n const hi = compareForFilter(value, rule.value2);\n return lo !== null && hi !== null && lo >= 0 && hi <= 0;\n }\n case 'isBlank':\n return isBlankValue(value);\n case 'isNotBlank':\n return !isBlankValue(value);\n case 'oneOf':\n return (rule.values ?? []).some((candidate) => String(candidate) === String(value ?? ''));\n default:\n return true;\n }\n}\n\n// --- Group summaries ---\n\n/**\n * Aggregates values the way category summaries do: `count` counts non-blank\n * values; the other aggregates use numeric values only and return null when\n * there are none.\n */\nexport function aggregateValues(values: unknown[], aggregate: GroupAggregate): number | null {\n if (aggregate === 'count') return values.filter((v) => !isBlankValue(v)).length;\n const numbers: number[] = [];\n for (const v of values) {\n const n = toNumber(v);\n if (n !== null) numbers.push(n);\n }\n if (numbers.length === 0) return aggregate === 'sum' ? 0 : null;\n switch (aggregate) {\n case 'sum':\n return roundFloat(numbers.reduce((s, n) => s + n, 0));\n case 'average':\n return roundFloat(numbers.reduce((s, n) => s + n, 0) / numbers.length);\n case 'min':\n return numbers.reduce((m, n) => (n < m ? n : m), numbers[0]);\n case 'max':\n return numbers.reduce((m, n) => (n > m ? n : m), numbers[0]);\n default:\n return null;\n }\n}\n\n/** Removes binary floating point noise (0.1 + 0.2 -> 0.3). */\nexport function roundFloat(value: number): number {\n return Number.isInteger(value) ? value : parseFloat(value.toPrecision(12));\n}\n\n// --- Autofill ---\n\ntype FillValue =\n | { kind: 'blank' }\n | { kind: 'number'; value: number }\n | { kind: 'date'; time: number; year: number; month: number; day: number }\n | { kind: 'textNumber'; prefix: string; value: number; width: number; suffix: string }\n | { kind: 'text'; text: string };\n\nconst DAY_MS = 86_400_000;\nconst TRAILING_NUMBER = /^(.*?)(\\d+)(\\D*)$/;\n\nfunction classifyFillValue(raw: string): FillValue {\n if (raw.trim() === '') return { kind: 'blank' };\n const num = toNumber(raw);\n if (num !== null) return { kind: 'number', value: num };\n // Typed dates (\"3/4/2026\", \"Mar 4, 2026\") continue as ISO dates.\n const typed = parseCellInput(raw);\n const date = ISO_DATE_PATTERN.exec(typed.type === 'date' ? String(typed.value) : raw.trim());\n if (date) {\n const [year, month, day] = [Number(date[1]), Number(date[2]), Number(date[3])];\n const time = Date.UTC(year, month - 1, day);\n const check = new Date(time);\n if (check.getUTCMonth() === month - 1 && check.getUTCDate() === day) {\n return { kind: 'date', time, year, month, day };\n }\n }\n const textNumber = TRAILING_NUMBER.exec(raw);\n if (textNumber && textNumber[1] !== '') {\n return {\n kind: 'textNumber',\n prefix: textNumber[1],\n value: parseInt(textNumber[2], 10),\n width: textNumber[2].length,\n suffix: textNumber[3],\n };\n }\n return { kind: 'text', text: raw };\n}\n\nconst pad = (n: number, width: number) => String(Math.abs(n)).padStart(width, '0');\n\nfunction formatDate(time: number): string {\n const d = new Date(time);\n return `${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1, 2)}-${pad(d.getUTCDate(), 2)}`;\n}\n\n/** Constant difference between consecutive values, or null. */\nfunction constantStep(values: number[]): number | null {\n const step = values[1] - values[0];\n for (let i = 2; i < values.length; i++) {\n if (Math.abs(values[i] - values[i - 1] - step) > 1e-9) return null;\n }\n return step;\n}\n\n/** Least-squares line through (i, values[i]), evaluated at `x`. */\nfunction linearTrend(values: number[], x: number): number {\n const n = values.length;\n const meanX = (n - 1) / 2;\n const meanY = values.reduce((s, v) => s + v, 0) / n;\n let num = 0;\n let den = 0;\n values.forEach((v, i) => {\n num += (i - meanX) * (v - meanY);\n den += (i - meanX) ** 2;\n });\n const slope = den === 0 ? 0 : num / den;\n return meanY + slope * (x - meanX);\n}\n\n/**\n * Extends `source` (raw values in fill order: for an upward or leftward fill,\n * nearest-first) by `count` values, the way a fill handle does:\n *\n * - numbers: one value repeats; two or more continue their linear trend\n * - dates (ISO `YYYY-MM-DD`, or typed like `3/4/2026`): one date counts up\n * by a day; two or more continue their day or month step (as ISO dates)\n * - text ending in a number (\"Item 1\"): the number counts up (or continues\n * the step of several values with the same prefix/suffix)\n * - anything else (or a mix) repeats the source cyclically\n *\n * Formulas are not handled here; the controller shifts their references.\n */\nexport function fillSeries(source: string[], count: number): string[] {\n if (count <= 0) return [];\n if (source.length === 0) return Array(count).fill('');\n const repeat = () => Array.from({ length: count }, (_, i) => source[i % source.length]);\n\n const parsed = source.map(classifyFillValue);\n const kind = parsed[0].kind;\n if (!parsed.every((p) => p.kind === kind)) return repeat();\n const n = source.length;\n\n if (kind === 'number') {\n if (n === 1) return repeat();\n const values = parsed.map((p) => (p as { value: number }).value);\n return Array.from({ length: count }, (_, i) => String(roundFloat(linearTrend(values, n + i))));\n }\n\n if (kind === 'date') {\n const dates = parsed as Array<Extract<FillValue, { kind: 'date' }>>;\n if (n === 1) {\n return Array.from({ length: count }, (_, i) => formatDate(dates[0].time + (i + 1) * DAY_MS));\n }\n // Same day of month, constant month step: step by months (Jan 31 -> Feb 28 clamps).\n const monthIndex = dates.map((d) => d.year * 12 + (d.month - 1));\n const monthStep = constantStep(monthIndex);\n if (monthStep !== null && monthStep !== 0 && dates.every((d) => d.day === dates[0].day)) {\n const last = monthIndex[n - 1];\n return Array.from({ length: count }, (_, i) => {\n const m = last + monthStep * (i + 1);\n const year = Math.floor(m / 12);\n const month = m - year * 12;\n const daysInMonth = new Date(Date.UTC(year, month + 1, 0)).getUTCDate();\n return formatDate(Date.UTC(year, month, Math.min(dates[0].day, daysInMonth)));\n });\n }\n const dayStep = constantStep(dates.map((d) => Math.round(d.time / DAY_MS)));\n if (dayStep === null) return repeat();\n const lastTime = dates[n - 1].time;\n return Array.from({ length: count }, (_, i) => formatDate(lastTime + dayStep * (i + 1) * DAY_MS));\n }\n\n if (kind === 'textNumber') {\n const items = parsed as Array<Extract<FillValue, { kind: 'textNumber' }>>;\n const { prefix, suffix } = items[0];\n if (!items.every((t) => t.prefix === prefix && t.suffix === suffix)) return repeat();\n const step = n === 1 ? 1 : constantStep(items.map((t) => t.value));\n if (step === null) return repeat();\n const last = items[n - 1];\n return Array.from({ length: count }, (_, i) => {\n const value = last.value + step * (i + 1);\n const digits = value < 0 ? `-${pad(value, last.width)}` : pad(value, last.width);\n return `${prefix}${digits}${suffix}`;\n });\n }\n\n return repeat();\n}\n\nexport type FillDirection = 'down' | 'up' | 'right' | 'left';\n\n/**\n * Works out where a fill handle drag ends. Dragging further vertically than\n * horizontally fills down/up the source's columns; otherwise right/left\n * across its rows. Returns the full target range (source included), or null\n * while the pointer is still inside the source.\n */\nexport function computeFillTarget(source: CellRange, pointer: CellPosition): CellRange | null {\n const s = normalizeRange(source);\n const rowOverflow = pointer.row > s.endRow ? pointer.row - s.endRow : pointer.row < s.startRow ? s.startRow - pointer.row : 0;\n const colOverflow = pointer.col > s.endCol ? pointer.col - s.endCol : pointer.col < s.startCol ? s.startCol - pointer.col : 0;\n if (rowOverflow === 0 && colOverflow === 0) return null;\n if (rowOverflow >= colOverflow) {\n return pointer.row > s.endRow ? { ...s, endRow: pointer.row } : { ...s, startRow: pointer.row };\n }\n return pointer.col > s.endCol ? { ...s, endCol: pointer.col } : { ...s, startCol: pointer.col };\n}\n\n/**\n * The direction of a fill from `source` into `target` (the extended range),\n * or null when `target` does not extend `source` along exactly one edge.\n */\nexport function getFillDirection(source: CellRange, target: CellRange): FillDirection | null {\n const s = normalizeRange(source);\n const t = normalizeRange(target);\n const sameCols = s.startCol === t.startCol && s.endCol === t.endCol;\n const sameRows = s.startRow === t.startRow && s.endRow === t.endRow;\n if (sameCols && t.startRow === s.startRow && t.endRow > s.endRow) return 'down';\n if (sameCols && t.endRow === s.endRow && t.startRow < s.startRow) return 'up';\n if (sameRows && t.startCol === s.startCol && t.endCol > s.endCol) return 'right';\n if (sameRows && t.endCol === s.endCol && t.startCol < s.startCol) return 'left';\n return null;\n}\n","/**\n * Spreadsheet clipboard formats. Copying writes three representations:\n *\n * - `text/plain`: TSV of the displayed values (pastes into any app)\n * - `text/html`: an HTML `<table>` (pastes into docs, mail, other sheets)\n * - `application/x.pixerate.spreadsheet+json`: raw inputs and formulas, so a\n * paste into a pixerate spreadsheet is lossless; formulas are re-based to\n * the paste position like a spreadsheet copy/paste\n *\n * Pasting prefers the custom format, then an HTML table, then TSV. All\n * functions here are pure and DOM-free.\n */\nimport { offsetFormulaReferences, type CellPosition } from './formula';\nimport { parseTsv, serializeTsv } from './csv';\n\nexport const SPREADSHEET_CLIPBOARD_MIME = 'application/x.pixerate.spreadsheet+json';\n\nexport interface SpreadsheetClipboardCell {\n raw: string; // input as typed (formula text for formulas)\n value: unknown; // displayed value\n /** Display text for `text/plain` and `text/html` (e.g. `10%` for 0.1); defaults to the value as text. Not stored in the JSON payload. */\n text?: string;\n}\n\nexport interface SpreadsheetClipboardPayload {\n type: 'pixerate-spreadsheet';\n version: 1;\n /** Position of the copied block's top-left cell, used to re-base formulas. */\n origin: CellPosition;\n cells: SpreadsheetClipboardCell[][];\n}\n\n/** MIME type -> data, as written to `DataTransfer.setData`. */\nexport type SpreadsheetClipboardData = Record<string, string>;\n\n/** Anything clipboard data can be read from: a `DataTransfer` or a plain record. */\nexport type SpreadsheetClipboardSource =\n | { getData(format: string): string }\n | Record<string, string | undefined>;\n\nexport interface ParsedSpreadsheetClipboard {\n format: 'internal' | 'html' | 'text';\n /** Raw inputs to write, row by row. */\n rows: string[][];\n /** For internal pastes: where the block was copied from. */\n origin?: CellPosition;\n}\n\nconst displayText = (value: unknown): string => (value === null || value === undefined ? '' : String(value));\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"');\n}\n\n/** Serializes displayed values as an HTML table. Line breaks become `<br>`. */\nexport function serializeHtmlTable(values: ReadonlyArray<ReadonlyArray<unknown>>): string {\n const body = values\n .map(\n (row) =>\n `<tr>${row.map((v) => `<td>${escapeHtml(displayText(v)).replace(/\\r?\\n/g, '<br>')}</td>`).join('')}</tr>`,\n )\n .join('');\n return `<table><tbody>${body}</tbody></table>`;\n}\n\nconst NAMED_ENTITIES: Record<string, string> = {\n amp: '&',\n lt: '<',\n gt: '>',\n quot: '\"',\n apos: \"'\",\n nbsp: ' ',\n};\n\nfunction decodeEntities(text: string): string {\n return text.replace(/&(#x[0-9a-f]+|#\\d+|[a-z]+);/gi, (match, entity: string) => {\n if (entity[0] === '#') {\n const code = entity[1] === 'x' || entity[1] === 'X' ? parseInt(entity.slice(2), 16) : parseInt(entity.slice(1), 10);\n return Number.isFinite(code) ? String.fromCodePoint(code) : match;\n }\n return NAMED_ENTITIES[entity.toLowerCase()] ?? match;\n });\n}\n\n// Private-use placeholder for line breaks while HTML whitespace is collapsed.\nconst LINE_BREAK = '';\n\nfunction cellHtmlToText(html: string): string {\n const text = html\n .replace(/<!--[\\s\\S]*?-->/g, '')\n .replace(/<(style|script)[\\s\\S]*?<\\/\\1\\s*>/gi, '')\n .replace(/<br\\s*\\/?>/gi, LINE_BREAK)\n .replace(/<\\/(p|div)\\s*>/gi, LINE_BREAK)\n .replace(/<[^>]*>/g, '')\n .replace(/\\s+/g, ' ');\n return decodeEntities(text)\n .replace(/ /g, ' ')\n .split(LINE_BREAK)\n .map((line) => line.trim())\n .join('\\n')\n .replace(/^\\n+|\\n+$/g, '');\n}\n\n/**\n * Extracts cell texts from the first `<table>` in `html` (as written by\n * spreadsheet apps and browsers). `colspan`/`rowspan` cells are expanded with\n * blank cells so positions line up. Returns null when there is no table.\n */\nexport function parseHtmlTable(html: string): string[][] | null {\n const tableMatch = /<table[\\s>][\\s\\S]*?<\\/table\\s*>/i.exec(html);\n if (!tableMatch) return null;\n const table = tableMatch[0];\n\n const rows: string[][] = [];\n // Cells still occupied by a rowspan from an earlier row: row -> cols.\n const occupied = new Map<number, Set<number>>();\n const rowPattern = /<tr[\\s>]([\\s\\S]*?)<\\/tr\\s*>/gi;\n const cellPattern = /<(td|th)(\\s[^>]*)?>([\\s\\S]*?)<\\/\\1\\s*>/gi;\n let rowMatch: RegExpExecArray | null;\n let rowIndex = 0;\n while ((rowMatch = rowPattern.exec(table))) {\n const row: string[] = [];\n const taken = occupied.get(rowIndex) ?? new Set<number>();\n let col = 0;\n let cellMatch: RegExpExecArray | null;\n cellPattern.lastIndex = 0;\n while ((cellMatch = cellPattern.exec(rowMatch[1]))) {\n while (taken.has(col)) row[col++] = '';\n const attrs = cellMatch[2] ?? '';\n const colspan = Math.max(1, parseInt(/colspan\\s*=\\s*[\"']?(\\d+)/i.exec(attrs)?.[1] ?? '1', 10));\n const rowspan = Math.max(1, parseInt(/rowspan\\s*=\\s*[\"']?(\\d+)/i.exec(attrs)?.[1] ?? '1', 10));\n row[col] = cellHtmlToText(cellMatch[3]);\n for (let c = col; c < col + colspan; c++) {\n if (c > col) row[c] = '';\n for (let r = rowIndex + 1; r < rowIndex + rowspan; r++) {\n if (!occupied.has(r)) occupied.set(r, new Set());\n occupied.get(r)!.add(c);\n }\n }\n col += colspan;\n }\n while (taken.has(col)) row[col++] = '';\n rows.push(Array.from(row, (v) => v ?? ''));\n rowIndex++;\n }\n return rows.length > 0 ? rows : null;\n}\n\n/** Builds the three clipboard representations of a copied block. */\nexport function createSpreadsheetClipboardData(\n cells: SpreadsheetClipboardCell[][],\n origin: CellPosition,\n): SpreadsheetClipboardData {\n const texts = cells.map((row) => row.map((cell) => cell.text ?? displayText(cell.value)));\n const payload: SpreadsheetClipboardPayload = {\n type: 'pixerate-spreadsheet',\n version: 1,\n origin,\n cells: cells.map((row) => row.map(({ raw, value }) => ({ raw, value }))),\n };\n return {\n 'text/plain': serializeTsv(texts),\n 'text/html': serializeHtmlTable(texts),\n [SPREADSHEET_CLIPBOARD_MIME]: JSON.stringify(payload),\n };\n}\n\nfunction readFormat(source: SpreadsheetClipboardSource, format: string): string {\n try {\n if (typeof (source as { getData?: unknown }).getData === 'function') {\n return (source as { getData(format: string): string }).getData(format) ?? '';\n }\n return (source as Record<string, string | undefined>)[format] ?? '';\n } catch {\n return '';\n }\n}\n\nfunction parsePayload(json: string): SpreadsheetClipboardPayload | null {\n try {\n const payload = JSON.parse(json);\n if (\n payload?.type !== 'pixerate-spreadsheet' ||\n !Array.isArray(payload.cells) ||\n !payload.cells.every((row: unknown) => Array.isArray(row)) ||\n typeof payload.origin?.row !== 'number' ||\n typeof payload.origin?.col !== 'number'\n ) {\n return null;\n }\n return payload as SpreadsheetClipboardPayload;\n } catch {\n return null;\n }\n}\n\n/**\n * Reads clipboard data, preferring the lossless internal format, then an\n * HTML table, then TSV text. Returns null when there is nothing to paste.\n */\nexport function readSpreadsheetClipboard(source: SpreadsheetClipboardSource): ParsedSpreadsheetClipboard | null {\n const payload = parsePayload(readFormat(source, SPREADSHEET_CLIPBOARD_MIME));\n if (payload) {\n return {\n format: 'internal',\n origin: payload.origin,\n rows: payload.cells.map((row) => row.map((cell) => (typeof cell?.raw === 'string' ? cell.raw : displayText(cell?.value)))),\n };\n }\n\n const html = readFormat(source, 'text/html');\n if (html) {\n const rows = parseHtmlTable(html);\n if (rows) return { format: 'html', rows };\n }\n\n const text = readFormat(source, 'text/plain');\n if (text) {\n const rows = parseTsv(text);\n if (rows.length > 0) return { format: 'text', rows };\n }\n return null;\n}\n\n/**\n * Moves formulas copied from `origin` so they keep their relative references\n * when pasted at `target`. Non-formula inputs are returned unchanged.\n */\nexport function rebaseClipboardRows(rows: string[][], origin: CellPosition, target: CellPosition): string[][] {\n const rowOffset = target.row - origin.row;\n const colOffset = target.col - origin.col;\n return rows.map((row) =>\n row.map((raw) => (raw.startsWith('=') ? offsetFormulaReferences(raw, rowOffset, colOffset) : raw)),\n );\n}\n","/**\n * The render model of a spreadsheet: which rows and columns are shown, in\n * which order, with group header rows, frozen (sticky) offsets and merged\n * cell spans. Filters, hidden rows/columns and collapsed groups only affect\n * this view; the document keeps every row.\n */\nimport type {\n CellRange,\n SpreadsheetColumn,\n SpreadsheetDocument,\n SpreadsheetRow,\n} from './types';\nimport type { CellPosition } from './formula';\nimport { aggregateValues, compareCellValues, isBlankValue, matchesFilterRule, normalizeRange } from './table';\n\nexport const DEFAULT_ROW_HEIGHT = 32;\nexport const DEFAULT_COLUMN_WIDTH = 130;\n\nexport type SpreadsheetRowSection = 'header' | 'body' | 'footer';\n\nexport interface SpreadsheetRowGroup {\n key: string; // grouping value as text ('' for blanks)\n label: string;\n rowIndices: number[]; // member rows that pass the filters, in document order\n collapsed: boolean;\n summaries: Record<string, number | null>; // colId -> aggregate\n}\n\nexport type SpreadsheetViewRow =\n | {\n kind: 'row';\n row: SpreadsheetRow;\n index: number; // document row index\n section: SpreadsheetRowSection;\n frozen: boolean;\n stickyTop: number; // offset from the first frozen row (frozen rows only)\n groupKey?: string;\n }\n | { kind: 'group'; group: SpreadsheetRowGroup };\n\nexport interface SpreadsheetViewColumn {\n column: SpreadsheetColumn;\n index: number; // document column index\n header: boolean; // inside the header columns\n frozen: boolean;\n stickyLeft: number; // offset from the first frozen column (frozen columns only)\n}\n\nexport interface SpreadsheetCellSpan {\n rowSpan: number;\n colSpan: number;\n /** The cell whose content is shown (a merge's top-left cell). */\n source: CellPosition;\n merge?: CellRange;\n}\n\nexport interface SpreadsheetViewModel {\n rows: SpreadsheetViewRow[];\n columns: SpreadsheetViewColumn[];\n groups: SpreadsheetRowGroup[];\n /** Visible document row indices in display order (for keyboard navigation). */\n rowOrder: number[];\n /** Visible document column indices in display order. */\n columnOrder: number[];\n filteredOutCount: number;\n hiddenRowCount: number;\n hiddenColumnCount: number;\n /**\n * Span of the cell rendered at (row, col): `{ rowSpan: 1, colSpan: 1 }` for\n * an ordinary cell, the visible extent for a merge's first visible cell, and\n * null for cells covered by a merge (render nothing).\n */\n getCellSpan(row: number, col: number): SpreadsheetCellSpan | null;\n}\n\nexport type CellValueReader = (rowIndex: number, colIndex: number) => unknown;\n\nconst clampCount = (value: number | undefined, max: number) => Math.max(0, Math.min(Math.floor(value ?? 0), max));\n\n/** Header and footer row counts, clamped so they never overlap. */\nexport function getTableSections(doc: SpreadsheetDocument): { headerRows: number; footerRows: number } {\n const total = doc.rows.length;\n const headerRows = clampCount(doc.table?.headerRowCount, total);\n const footerRows = clampCount(doc.table?.footerRowCount, total - headerRows);\n return { headerRows, footerRows };\n}\n\nexport function getRowSection(doc: SpreadsheetDocument, rowIndex: number): SpreadsheetRowSection {\n const { headerRows, footerRows } = getTableSections(doc);\n if (rowIndex < headerRows) return 'header';\n if (rowIndex >= doc.rows.length - footerRows) return 'footer';\n return 'body';\n}\n\n/** Whether a body row passes the active filters. Header/footer rows always do. */\nexport function rowPassesFilters(doc: SpreadsheetDocument, rowIndex: number, getValue: CellValueReader): boolean {\n const filter = doc.table?.filter;\n if (!filter?.enabled || filter.rules.length === 0) return true;\n if (getRowSection(doc, rowIndex) !== 'body') return true;\n return filter.rules.every((rule) => {\n const colIndex = doc.columns.findIndex((c) => c.id === rule.colId);\n if (colIndex === -1) return true; // rules on deleted columns are ignored\n return matchesFilterRule(getValue(rowIndex, colIndex), rule);\n });\n}\n\n/** Category groups of the (unhidden, unfiltered) body rows. */\nexport function computeRowGroups(doc: SpreadsheetDocument, getValue: CellValueReader): SpreadsheetRowGroup[] {\n const grouping = doc.table?.grouping;\n if (!grouping) return [];\n const groupCol = doc.columns.findIndex((c) => c.id === grouping.colId);\n if (groupCol === -1) return [];\n\n const { headerRows, footerRows } = getTableSections(doc);\n const byKey = new Map<string, number[]>();\n for (let r = headerRows; r < doc.rows.length - footerRows; r++) {\n if (doc.rows[r].hidden || !rowPassesFilters(doc, r, getValue)) continue;\n const value = getValue(r, groupCol);\n const key = isBlankValue(value) ? '' : String(value).trim();\n if (!byKey.has(key)) byKey.set(key, []);\n byKey.get(key)!.push(r);\n }\n\n const collapsed = new Set(grouping.collapsed);\n return Array.from(byKey.keys())\n .sort((a, b) => compareCellValues(a, b))\n .map((key) => {\n const rowIndices = byKey.get(key)!;\n const summaries: Record<string, number | null> = {};\n for (const summary of grouping.summaries) {\n const colIndex = doc.columns.findIndex((c) => c.id === summary.colId);\n if (colIndex === -1) continue;\n summaries[summary.colId] = aggregateValues(\n rowIndices.map((r) => getValue(r, colIndex)),\n summary.aggregate,\n );\n }\n return { key, label: key === '' ? '(blank)' : key, rowIndices, collapsed: collapsed.has(key), summaries };\n });\n}\n\nexport function buildSpreadsheetView(doc: SpreadsheetDocument, getValue: CellValueReader): SpreadsheetViewModel {\n const { headerRows, footerRows } = getTableSections(doc);\n const frozenRows = clampCount(doc.table?.frozenRowCount, doc.rows.length);\n const frozenCols = clampCount(doc.table?.frozenColumnCount, doc.columns.length);\n const headerCols = clampCount(doc.table?.headerColumnCount, doc.columns.length);\n\n // Columns\n const columns: SpreadsheetViewColumn[] = [];\n let left = 0;\n let hiddenColumnCount = 0;\n doc.columns.forEach((column, index) => {\n if (column.hidden) {\n hiddenColumnCount++;\n return;\n }\n const frozen = index < frozenCols;\n columns.push({ column, index, header: index < headerCols, frozen, stickyLeft: frozen ? left : 0 });\n if (frozen) left += column.width || DEFAULT_COLUMN_WIDTH;\n });\n\n // Rows\n const rows: SpreadsheetViewRow[] = [];\n let hiddenRowCount = 0;\n let filteredOutCount = 0;\n const pushRow = (index: number, section: SpreadsheetRowSection, groupKey?: string) => {\n const row = doc.rows[index];\n rows.push({ kind: 'row', row, index, section, frozen: false, stickyTop: 0, groupKey });\n };\n\n for (let r = 0; r < headerRows; r++) {\n if (doc.rows[r].hidden) hiddenRowCount++;\n else pushRow(r, 'header');\n }\n\n const bodyEnd = doc.rows.length - footerRows;\n const groups = computeRowGroups(doc, getValue);\n for (let r = headerRows; r < bodyEnd; r++) {\n if (doc.rows[r].hidden) hiddenRowCount++;\n else if (!rowPassesFilters(doc, r, getValue)) filteredOutCount++;\n }\n const grouping = doc.table?.grouping;\n if (grouping && doc.columns.some((c) => c.id === grouping.colId)) {\n for (const group of groups) {\n rows.push({ kind: 'group', group });\n if (!group.collapsed) group.rowIndices.forEach((r) => pushRow(r, 'body', group.key));\n }\n } else {\n for (let r = headerRows; r < bodyEnd; r++) {\n if (!doc.rows[r].hidden && rowPassesFilters(doc, r, getValue)) pushRow(r, 'body');\n }\n }\n\n for (let r = bodyEnd; r < doc.rows.length; r++) {\n if (doc.rows[r].hidden) hiddenRowCount++;\n else pushRow(r, 'footer');\n }\n\n // Frozen rows: the leading run of displayed rows inside the frozen count.\n let top = 0;\n for (const viewRow of rows) {\n if (viewRow.kind !== 'row' || viewRow.index >= frozenRows) break;\n viewRow.frozen = true;\n viewRow.stickyTop = top;\n top += viewRow.row.height || DEFAULT_ROW_HEIGHT;\n }\n\n const rowOrder = rows.flatMap((r) => (r.kind === 'row' ? [r.index] : []));\n const columnOrder = columns.map((c) => c.index);\n\n // Merged cells: span the visible, display-contiguous part of each merge.\n const rowPos = new Map(rowOrder.map((index, pos) => [index, pos]));\n const colPos = new Map(columnOrder.map((index, pos) => [index, pos]));\n const spans = new Map<string, SpreadsheetCellSpan | null>();\n const contiguousRun = (indices: number[], positions: Map<number, number>) => {\n const visible = indices\n .filter((i) => positions.has(i))\n .sort((a, b) => positions.get(a)! - positions.get(b)!);\n if (visible.length === 0) return null;\n let run = 1;\n while (run < visible.length && positions.get(visible[run])! === positions.get(visible[0])! + run) run++;\n return { first: visible[0], run };\n };\n for (const raw of doc.table?.merges ?? []) {\n const merge = normalizeRange(raw);\n const rowIdx: number[] = [];\n const colIdx: number[] = [];\n for (let r = merge.startRow; r <= merge.endRow; r++) rowIdx.push(r);\n for (let c = merge.startCol; c <= merge.endCol; c++) colIdx.push(c);\n const rowRun = contiguousRun(rowIdx, rowPos);\n const colRun = contiguousRun(colIdx, colPos);\n for (const r of rowIdx) for (const c of colIdx) spans.set(`${r}:${c}`, null);\n if (rowRun && colRun) {\n spans.set(`${rowRun.first}:${colRun.first}`, {\n rowSpan: rowRun.run,\n colSpan: colRun.run,\n source: { row: merge.startRow, col: merge.startCol },\n merge,\n });\n }\n }\n\n return {\n rows,\n columns,\n groups,\n rowOrder,\n columnOrder,\n filteredOutCount,\n hiddenRowCount,\n hiddenColumnCount,\n getCellSpan(row, col) {\n const span = spans.get(`${row}:${col}`);\n if (span === undefined) return { rowSpan: 1, colSpan: 1, source: { row, col } };\n return span;\n },\n };\n}\n","import {\n SpreadsheetDocument,\n SpreadsheetColumn,\n SpreadsheetRow,\n CellCoordinate,\n CellRange,\n CellData,\n SpreadsheetDataSource,\n SpreadsheetTableSettings,\n SortKey,\n FilterRule,\n SpreadsheetFilterState,\n GroupAggregate,\n GroupSummary,\n SpreadsheetSpill\n} from './types';\nimport {\n FormulaEvaluator,\n colNameToIndex,\n indexToColName,\n DependencyGraph,\n shiftFormulaReferences,\n remapFormulaReferences,\n offsetFormulaReferences,\n WHOLE_COLUMN_END_ROW,\n describeFormulaError,\n isFormulaError,\n type FormulaRange,\n type StructuralChange,\n type CellPosition\n} from './formula';\nimport { parseCellInput } from './formula/parse-input';\nimport { formatCellDisplay } from './formula/format';\nimport { cellFormatForNumberFormat, isGeneralNumberFormat } from './numfmt/presets';\nimport { DataSourceBinder } from './datasource';\nimport {\n compareCellValues,\n fillSeries,\n getFillDirection,\n isSingleCellRange,\n normalizeRange,\n rangeContains,\n rangeContainsRange,\n rangesIntersect\n} from './table';\nimport { parseCsv, serializeCsv } from './csv';\nimport {\n createSpreadsheetClipboardData,\n readSpreadsheetClipboard,\n rebaseClipboardRows,\n type SpreadsheetClipboardData,\n type SpreadsheetClipboardSource\n} from './clipboard';\nimport {\n buildSpreadsheetView,\n computeRowGroups,\n getTableSections,\n type SpreadsheetRowGroup,\n type SpreadsheetViewModel\n} from './view';\n\nexport interface CsvExportOptions {\n range?: CellRange | null;\n delimiter?: string;\n lineEnding?: string;\n bom?: boolean;\n /** Export formulas as typed (`=SUM(A1:A3)`) instead of their values. */\n formulas?: boolean;\n}\n\nexport interface CsvImportOptions {\n startRow?: number;\n startCol?: number;\n delimiter?: string;\n}\n\nexport type NewFilterRule = Omit<FilterRule, 'id'> & { id?: string };\n\nexport interface SpreadsheetControllerOptions {\n document?: Partial<SpreadsheetDocument>;\n dataSources?: SpreadsheetDataSource[];\n primaryDataSourceId?: string;\n onDocumentChange?: (doc: SpreadsheetDocument) => void;\n onSelectionChange?: (activeCell: CellCoordinate | null, range: CellRange | null) => void;\n onCellCommit?: (rowId: string, colId: string, raw: string, value: any) => void;\n /**\n * Approximate memory budget for undo/redo snapshots, in bytes (UTF-16 size of\n * the serialized documents). The oldest undo steps beyond it are dropped, but\n * the most recent one is always kept. Defaults to 64 MiB; 0 = unlimited.\n */\n maxHistoryBytes?: number;\n}\n\n/** Module-wide sequence that makes generated row, column and filter ids unique. */\nlet nextIdSequence = 0;\n\n/** A placed dynamic array: derived state, rebuilt by every recalculation. */\ninterface SpillRecord {\n anchor: string;\n row: number;\n col: number;\n rows: number;\n cols: number;\n /** Column-major values, anchor (top-left) first. */\n values: any[];\n /** The spilled cells (anchor excluded). */\n cells: Array<{ key: string; rowId: string; colId: string }>;\n}\n\n// Default undo/redo snapshot budget (see SpreadsheetControllerOptions.maxHistoryBytes).\nconst DEFAULT_MAX_HISTORY_BYTES = 64 * 1024 * 1024;\n\n// Recalculation passes after spill ranges change (see recalculateKeys).\nconst MAX_SPILL_PASSES = 25;\n\nconst spillCellId = (rowId: string, colId: string) => `${rowId}\\u0000${colId}`;\n\nexport class SpreadsheetController {\n public document: SpreadsheetDocument;\n public activeCell: CellCoordinate | null = null;\n public selectedRange: CellRange | null = null;\n public editingCell: CellCoordinate | null = null;\n public draftValue = '';\n\n public readonly binder = new DataSourceBinder();\n public readonly depGraph = new DependencyGraph();\n public readonly evaluator: FormulaEvaluator;\n\n private primaryDataSourceId?: string;\n private onDocumentChange?: (doc: SpreadsheetDocument) => void;\n private onSelectionChange?: (activeCell: CellCoordinate | null, range: CellRange | null) => void;\n private onCellCommit?: (rowId: string, colId: string, raw: string, value: any) => void;\n\n // History stack for undo/redo\n private undoStack: string[] = [];\n private redoStack: string[] = [];\n private isApplyingHistory = false;\n private readonly maxHistoryBytes: number;\n // Set while importing TSV: history and recalculation are done once at the end.\n private batching = false;\n private pendingCommits: Array<[string, string, string]> = [];\n // Row being evaluated, so [property] references resolve per row.\n private evaluatingRowIndex: number | null = null;\n // Cell being evaluated, for implicit intersection (`=@A:A`).\n private evaluatingCell: { col: string; row: number } | null = null;\n\n // Dynamic arrays. Spilled values are derived state: they live here, not in\n // the document, and every recalculation rebuilds them.\n private spills = new Map<string, SpillRecord>(); // anchor key -> spill\n private spilledBy = new Map<string, string>(); // spilled cell key -> anchor key\n private spillCells = new Map<string, CellData>(); // spillCellId -> displayed cell\n // Cells whose spill ownership changed during the current pass.\n private spillChanges: Set<string> | null = null;\n\n constructor(options: SpreadsheetControllerOptions = {}) {\n const defaultCols: SpreadsheetColumn[] = [\n { id: 'col_a', key: 'A', title: 'A', width: 120, type: 'freeform' },\n { id: 'col_b', key: 'B', title: 'B', width: 120, type: 'freeform' },\n { id: 'col_c', key: 'C', title: 'C', width: 120, type: 'freeform' },\n { id: 'col_d', key: 'D', title: 'D', width: 120, type: 'freeform' }\n ];\n\n const defaultRows: SpreadsheetRow[] = options.primaryDataSourceId ? [] : Array.from({ length: 10 }, (_, i) => ({\n id: `row_${i + 1}`,\n index: i,\n height: 32,\n type: 'freeform'\n }));\n\n this.document = {\n id: options.document?.id || `sheet_${Date.now()}`,\n name: options.document?.name || 'Sheet 1',\n columns: options.document?.columns || defaultCols,\n rows: options.document?.rows || defaultRows,\n cells: options.document?.cells || {},\n createdAt: options.document?.createdAt || Date.now(),\n updatedAt: options.document?.updatedAt || Date.now(),\n ...(options.document?.table ? { table: options.document.table } : {})\n };\n\n this.primaryDataSourceId = options.primaryDataSourceId;\n this.maxHistoryBytes = Math.max(0, options.maxHistoryBytes ?? DEFAULT_MAX_HISTORY_BYTES);\n this.onDocumentChange = options.onDocumentChange;\n this.onSelectionChange = options.onSelectionChange;\n this.onCellCommit = options.onCellCommit;\n\n if (options.dataSources) {\n options.dataSources.forEach((ds) => this.binder.register(ds));\n }\n\n this.evaluator = new FormulaEvaluator({\n resolveCell: (colStr, rowNum) => this.resolveCellByCoord(colStr, rowNum),\n resolveRange: (sCol, sRow, eCol, eRow) => this.resolveRangeByCoords(sCol, sRow, eCol, eRow),\n resolveProperty: (prop) => this.resolveCurrentRowProperty(prop),\n resolveSpill: (colStr, rowNum) => this.resolveSpillByCoord(colStr, rowNum),\n getFormulaCell: () => this.evaluatingCell\n });\n\n this.syncWithDataSource();\n this.rederiveTypedValues();\n this.recalculateAll();\n }\n\n public loadDocument(document: SpreadsheetDocument): void {\n this.document = JSON.parse(JSON.stringify(document));\n this.activeCell = null;\n this.selectedRange = null;\n this.editingCell = null;\n this.draftValue = '';\n this.undoStack = [];\n this.redoStack = [];\n this.syncWithDataSource();\n this.rederiveTypedValues();\n this.recalculateAll();\n this.notifyChange();\n }\n\n /**\n * Re-parses the value of every stored typed (non-formula) cell from its\n * `raw` input, so documents saved before typed input was parsed (whose\n * values are text such as `\"120\"`) compare and sort as numbers. Cells of\n * bound columns in record rows keep their value: it belongs to the data\n * source.\n */\n private rederiveTypedValues(): void {\n for (const row of this.document.rows) {\n const cells = this.document.cells[row.id];\n if (!cells) continue;\n for (const col of this.document.columns) {\n const cell = cells[col.id];\n if (!cell || typeof cell.raw !== 'string' || cell.raw.startsWith('=')) continue;\n if (col.type === 'bound' && col.binding && row.recordId) continue;\n const typed = this.typedCell(cell.raw, cell.format, col, cell);\n cell.value = typed.value;\n if (typed.numberFormat) cell.numberFormat = typed.numberFormat;\n else delete cell.numberFormat;\n if (typed.format) cell.format = typed.format;\n }\n }\n }\n\n /**\n * Value of typed (non-formula) input: a number, boolean, ISO date, error\n * or text (see `parseCellInput`), its automatic number format, and the\n * `CellFormat` to use: the automatic one (currency, percentage, date,\n * number) when `format` is unset or `text` (the default of new columns).\n */\n private typedCell(\n raw: string,\n format: CellData['format'],\n col?: SpreadsheetColumn,\n existing?: CellData\n ): Pick<CellData, 'value' | 'numberFormat' | 'explicitNumberFormat' | 'format'> {\n const parsed = parseCellInput(raw);\n const fixed = this.fixedNumberFormat(col, existing);\n const numberFormat = fixed ?? parsed.numberFormat;\n return {\n value: parsed.value,\n ...(numberFormat ? { numberFormat } : {}),\n ...(existing?.explicitNumberFormat ? { explicitNumberFormat: true } : {}),\n format: fixed === undefined && parsed.cellFormat && (!format || format === 'text') ? parsed.cellFormat : format\n };\n }\n\n /**\n * The number format a cell keeps whatever is typed into it: its explicit\n * one, else its column's. Undefined lets typed input choose one.\n */\n private fixedNumberFormat(col: SpreadsheetColumn | undefined, existing: CellData | undefined): string | undefined {\n if (existing?.explicitNumberFormat && existing.numberFormat !== undefined) return existing.numberFormat;\n return col?.numberFormat && !isGeneralNumberFormat(col.numberFormat) ? col.numberFormat : undefined;\n }\n\n /** `numberFormat` / `explicitNumberFormat` fields for a formula, bound or spilled cell. */\n private fixedNumberFormatFields(col: SpreadsheetColumn | undefined, existing: CellData | undefined): Partial<CellData> {\n const numberFormat = this.fixedNumberFormat(col, existing);\n if (numberFormat === undefined) return {};\n return existing?.explicitNumberFormat ? { numberFormat, explicitNumberFormat: true } : { numberFormat };\n }\n\n /**\n * Typed input for a bound field, coerced by the field's declared type:\n * number, boolean and date fields get a number, boolean or ISO date when\n * the input parses as one; string and enum fields (and unknown fields)\n * keep the text exactly as typed.\n */\n private boundInputValue(dataSourceId: string, field: string, raw: string): unknown {\n if (raw.startsWith('=')) return raw;\n const type = this.binder.getDataSource(dataSourceId)?.getFields().find((f) => f.key === field)?.type;\n if (type !== 'number' && type !== 'boolean' && type !== 'date') return raw;\n const parsed = parseCellInput(raw);\n if (type === 'number' && parsed.type === 'number') return parsed.value;\n if (type === 'boolean' && parsed.type === 'boolean') return parsed.value;\n if (type === 'date' && parsed.type === 'date') return parsed.value;\n return raw;\n }\n\n public registerDataSource(ds: SpreadsheetDataSource): void {\n this.binder.register(ds);\n this.syncWithDataSource();\n this.recalculateAll();\n }\n\n public setPrimaryDataSource(dataSourceId: string | undefined): void {\n this.primaryDataSourceId = dataSourceId;\n this.syncWithDataSource();\n this.recalculateAll();\n }\n\n public syncWithDataSource(): void {\n if (!this.primaryDataSourceId) return;\n this.document.rows = this.binder.syncRows(this.document.rows, this.primaryDataSourceId);\n this.recomputeRowIndices();\n }\n\n private recomputeRowIndices(): void {\n this.document.rows.forEach((r, idx) => {\n r.index = idx;\n });\n this.document.columns.forEach((c, idx) => {\n c.key = indexToColName(idx);\n });\n }\n\n public getColumn(colIdOrKey: string): SpreadsheetColumn | undefined {\n return this.document.columns.find(\n (c) => c.id === colIdOrKey || c.key.toUpperCase() === colIdOrKey.toUpperCase()\n );\n }\n\n public getRow(rowIdOrIndex: string | number): SpreadsheetRow | undefined {\n if (typeof rowIdOrIndex === 'number') {\n return this.document.rows[rowIdOrIndex];\n }\n return this.document.rows.find((r) => r.id === rowIdOrIndex);\n }\n\n public getCell(rowId: string, colId: string): CellData {\n const existing = this.document.cells[rowId]?.[colId];\n if (existing && existing.raw !== '') return existing;\n if (this.spillCells.size > 0) {\n const spilled = this.spillCells.get(spillCellId(rowId, colId));\n if (spilled) return spilled;\n }\n if (existing && !existing.explicitNumberFormat) return existing;\n\n const col = this.document.columns.find((c) => c.id === colId);\n const row = this.document.rows.find((r) => r.id === rowId);\n const derived = this.getDerivedCell(row, col);\n if (!existing) return derived;\n // A blank cell holding only an explicit number format, over a bound\n // record value or a column formula: show that value with the format.\n if (derived.raw === '') return existing;\n return { ...derived, numberFormat: existing.numberFormat, explicitNumberFormat: true };\n }\n\n /** Value of a cell with no stored data: bound record value, column formula, or blank. */\n private getDerivedCell(row: SpreadsheetRow | undefined, col: SpreadsheetColumn | undefined): CellData {\n // Check if column is bound to record\n if (col && row && col.type === 'bound' && col.binding && row.recordId) {\n const boundVal = this.binder.resolveBoundValue(\n col.binding.dataSource,\n row.recordId,\n col.binding.field\n );\n return {\n raw: boundVal !== undefined ? String(boundVal) : '',\n value: boundVal ?? '',\n format: col.format,\n ...this.fixedNumberFormatFields(col, undefined)\n };\n }\n\n // Check if column has a column-level formula\n if (col && col.type === 'formula' && col.formula) {\n return {\n raw: col.formula,\n value: '',\n format: col.format,\n ...this.fixedNumberFormatFields(col, undefined)\n };\n }\n\n return { raw: '', value: '', format: col?.format, ...this.fixedNumberFormatFields(col, undefined) };\n }\n\n public setCellValue(rowId: string, colId: string, raw: string): void {\n this.recordSnapshot();\n\n if (!this.document.cells[rowId]) {\n this.document.cells[rowId] = {};\n }\n\n const col = this.document.columns.find((c) => c.id === colId);\n const row = this.document.rows.find((r) => r.id === rowId);\n\n const isFormula = raw.startsWith('=');\n const existing = this.document.cells[rowId][colId];\n let cell: CellData;\n // If this is a bound column and row is bound to record, dispatch back to data source\n if (col?.type === 'bound' && col.binding && row?.recordId) {\n const value = this.boundInputValue(col.binding.dataSource, col.binding.field, raw);\n this.binder.commitBoundValue(col.binding.dataSource, row.recordId, col.binding.field, value);\n cell = { raw, value, format: col.format, ...this.fixedNumberFormatFields(col, existing) };\n } else if (isFormula) {\n cell = { raw, value: raw, format: col?.format, ...this.fixedNumberFormatFields(col, existing) };\n } else {\n cell = { raw, ...this.typedCell(raw, col?.format, col, existing) };\n }\n\n const cellKey = this.getCellKey(rowId, colId);\n this.depGraph.setCellFormula(cellKey, isFormula ? raw : null);\n\n this.document.cells[rowId][colId] = cell;\n\n this.document.updatedAt = Date.now();\n if (this.batching) {\n this.pendingCommits.push([rowId, colId, raw]);\n return;\n }\n this.recalculateCell(rowId, colId);\n this.notifyChange();\n\n const evaluatedVal = this.document.cells[rowId][colId]?.value;\n this.onCellCommit?.(rowId, colId, raw, evaluatedVal);\n }\n\n private getCellKey(rowId: string, colId: string): string {\n const row = this.document.rows.find((r) => r.id === rowId);\n const col = this.document.columns.find((c) => c.id === colId);\n if (!row || !col) return `${colId}_${rowId}`;\n return `${col.key}${row.index + 1}`.toUpperCase();\n }\n\n /**\n * Recalculates a cell and everything that depends on it, in dependency\n * order. Every cell in a reference cycle is marked `#CYCLE!`.\n */\n public recalculateCell(rowId: string, colId: string): void {\n const cellKey = this.getCellKey(rowId, colId);\n // Typing into a spilled cell blocks its array: the anchor recalculates (#SPILL!).\n const anchor = this.spilledBy.get(cellKey);\n this.recalculateKeys(anchor ? [cellKey, anchor] : [cellKey], true);\n }\n\n /**\n * Recalculates `keys` (and, with `includeDependents`, their dependents) in\n * dependency order. Spill ranges are only known after evaluating their\n * anchors, so when a pass changes which cells hold spilled values (and so\n * the dependency graph), the dependents of those cells are recalculated in\n * another pass, until nothing changes.\n */\n private recalculateKeys(keys: Iterable<string>, includeDependents: boolean): void {\n let pending = Array.from(keys);\n let withDependents = includeDependents;\n for (let pass = 0; pass < MAX_SPILL_PASSES && pending.length > 0; pass++) {\n const changed = new Set<string>();\n this.spillChanges = changed;\n try {\n this.runEvaluationPlan(this.depGraph.getEvaluationPlan(pending, { includeDependents: withDependents }));\n } finally {\n this.spillChanges = null;\n }\n pending = Array.from(changed);\n withDependents = true;\n }\n }\n\n /**\n * Rebuilds the dependency graph from scratch and recalculates every formula\n * in dependency order.\n */\n public recalculateAll(): void {\n this.depGraph.clear();\n this.spills.clear();\n this.spilledBy.clear();\n this.spillCells.clear();\n const formulaKeys: string[] = [];\n for (const row of this.document.rows) {\n for (const col of this.document.columns) {\n // Avoid getCell's id lookups: this loop visits every cell.\n const cell = this.document.cells[row.id]?.[col.id] ?? this.getDerivedCell(row, col);\n if (cell.raw.startsWith('=')) {\n const cellKey = `${col.key}${row.index + 1}`.toUpperCase();\n this.depGraph.setCellFormula(cellKey, cell.raw);\n formulaKeys.push(cellKey);\n }\n }\n }\n this.recalculateKeys(formulaKeys, false);\n }\n\n private runEvaluationPlan(plan: { order: string[]; cyclic: Set<string> }): void {\n for (const key of plan.order) {\n if (plan.cyclic.has(key)) {\n this.markCycle(key);\n } else {\n this.evalSingleCellByKey(key);\n }\n }\n }\n\n private locateCellKey(cellKey: string): { row: SpreadsheetRow; col: SpreadsheetColumn } | null {\n const match = cellKey.match(/^([A-Za-z]+)(\\d+)$/);\n if (!match) return null;\n const col = this.document.columns.find((c) => c.key.toUpperCase() === match[1].toUpperCase());\n const row = this.document.rows[parseInt(match[2], 10) - 1];\n return col && row ? { row, col } : null;\n }\n\n private markCycle(cellKey: string): void {\n const located = this.locateCellKey(cellKey);\n if (!located) return;\n const { row, col } = located;\n const cell = this.getCell(row.id, col.id);\n if (!cell.raw.startsWith('=')) return;\n if (!this.document.cells[row.id]) this.document.cells[row.id] = {};\n // A direct self reference (A1 = A1+1, or SUM(A:A) in column A) gets its own message.\n const deps = this.depGraph.getDependencies(cellKey);\n const selfReference = deps.includes(cellKey) || deps.includes(`${col.key.toUpperCase()}:`);\n const spilledKeys = this.depGraph.getSpilledKeys(cellKey);\n const ownSpill = deps.find((dep) => spilledKeys.includes(dep));\n const errorMessage = selfReference\n ? \"This formula can't reference its own cell.\"\n : ownSpill\n ? `This formula refers to ${ownSpill}, which holds its own spilled results (a circular reference).`\n : 'This formula is part of a circular reference: it depends on its own result through other cells.';\n // Keep the spill edges, so the cycle stays detected on the next pass.\n this.clearSpill(cellKey.toUpperCase(), true);\n this.document.cells[row.id][col.id] = { ...cell, value: '#CYCLE!', error: '#CYCLE!', errorMessage };\n }\n\n private evalSingleCellByKey(cellKey: string): void {\n const match = cellKey.match(/^([A-Za-z]+)(\\d+)$/);\n if (!match) return;\n const colName = match[1].toUpperCase();\n const rowNum = parseInt(match[2], 10);\n\n const col = this.document.columns.find((c) => c.key.toUpperCase() === colName);\n const row = this.document.rows[rowNum - 1];\n if (!col || !row) return;\n\n const cell = this.getCell(row.id, col.id);\n if (!cell.raw.startsWith('=')) {\n if (cell.error === '#CYCLE!') {\n cell.error = undefined;\n cell.errorMessage = undefined;\n }\n // No longer a formula: drop any array it spilled.\n this.clearSpill(`${colName}${rowNum}`);\n return;\n }\n\n try {\n this.evaluatingRowIndex = rowNum - 1;\n this.evaluatingCell = { col: colName, row: rowNum };\n const result = this.evaluator.evaluateWithDiagnostics(cell.raw);\n if (!this.document.cells[row.id]) {\n this.document.cells[row.id] = {};\n }\n let { value, error, message } = result;\n if (result.array) {\n const blocked = this.placeSpill(`${colName}${rowNum}`, rowNum - 1, this.document.columns.indexOf(col), result.array);\n if (blocked) {\n value = '#SPILL!';\n error = '#SPILL!';\n message = blocked;\n }\n } else {\n this.clearSpill(`${colName}${rowNum}`);\n }\n this.document.cells[row.id][col.id] = {\n ...cell,\n value,\n // `#ERROR!` (malformed formula, wrong argument count) keeps its\n // message in `error`, as before; other errors store their code.\n error: error === '#ERROR!' ? message : error,\n errorMessage: message\n };\n } finally {\n this.evaluatingRowIndex = null;\n this.evaluatingCell = null;\n }\n }\n\n // --- Dynamic arrays (spilling) ---\n\n /**\n * Spills `array` from the anchor at (row, col) into the cells below and to\n * the right. Returns why it can't (the anchor then shows `#SPILL!`), or\n * null once placed. The grid never grows to fit an array, as in Excel.\n */\n private placeSpill(anchor: string, row: number, col: number, array: FormulaRange): string | null {\n const { rows, cols } = array;\n const area: CellRange = { startRow: row, startCol: col, endRow: row + rows - 1, endCol: col + cols - 1 };\n const label = `${indexToColName(area.startCol)}${area.startRow + 1}:${indexToColName(area.endCol)}${area.endRow + 1}`;\n let reason: string | null = null;\n const blockers: string[] = [];\n\n if (area.endRow >= this.document.rows.length || area.endCol >= this.document.columns.length) {\n reason = `The ${rows}×${cols} result needs ${label}, which extends past the edge of the sheet.`;\n } else if (this.getMerges().some((m) => rangesIntersect(m, area))) {\n reason = `The result can't spill into merged cells (it needs ${label}).`;\n } else {\n for (let c = area.startCol; c <= area.endCol; c++) {\n const column = this.document.columns[c];\n for (let r = area.startRow; r <= area.endRow; r++) {\n if (r === row && c === col) continue;\n const rowObj = this.document.rows[r];\n const key = `${column.key}${r + 1}`.toUpperCase();\n const stored = this.document.cells[rowObj.id]?.[column.id];\n const raw = stored ? stored.raw : this.getDerivedCell(rowObj, column).raw;\n const owner = this.spilledBy.get(key);\n if (raw !== '') {\n blockers.push(key);\n reason ??= `The result needs ${label}, but ${key} isn't empty.`;\n } else if (owner && owner !== anchor) {\n blockers.push(key);\n reason ??= `The result needs ${label}, but ${key} already holds values spilled from ${owner}.`;\n }\n }\n }\n }\n\n if (reason) {\n this.clearSpill(anchor);\n // Clearing a blocking cell recalculates this anchor.\n this.depGraph.setSpillEdges(anchor, [], blockers);\n return reason;\n }\n\n const previous = this.spills.get(anchor);\n const cells: SpillRecord['cells'] = [];\n for (let c = 0; c < cols; c++) {\n const column = this.document.columns[col + c];\n for (let r = 0; r < rows; r++) {\n if (r === 0 && c === 0) continue;\n const rowObj = this.document.rows[row + r];\n const key = `${column.key}${row + r + 1}`.toUpperCase();\n const value = array.values[c * rows + r] ?? '';\n const display: CellData = {\n raw: '',\n value,\n format: column.format,\n spillAnchor: anchor,\n ...this.fixedNumberFormatFields(column, this.document.cells[rowObj.id]?.[column.id])\n };\n if (isFormulaError(value)) {\n display.error = value;\n display.errorMessage = describeFormulaError(value);\n }\n this.spillCells.set(spillCellId(rowObj.id, column.id), display);\n if (this.spilledBy.get(key) !== anchor) {\n this.spilledBy.set(key, anchor);\n this.spillChanges?.add(key);\n }\n cells.push({ key, rowId: rowObj.id, colId: column.id });\n }\n }\n if (previous) {\n const kept = new Set(cells.map((cell) => cell.key));\n for (const old of previous.cells) {\n if (kept.has(old.key)) continue;\n this.forgetSpilledCell(anchor, old);\n }\n }\n this.spills.set(anchor, { anchor, row, col, rows, cols, values: array.values, cells });\n this.depGraph.setSpillEdges(anchor, cells.map((cell) => cell.key));\n return null;\n }\n\n /** Removes the array spilled from `anchor`. With `keepEdges`, its dependency edges stay. */\n private clearSpill(anchor: string, keepEdges = false): void {\n const record = this.spills.get(anchor);\n if (record) {\n for (const cell of record.cells) this.forgetSpilledCell(anchor, cell);\n this.spills.delete(anchor);\n }\n if (!keepEdges) this.depGraph.setSpillEdges(anchor, []);\n }\n\n private forgetSpilledCell(anchor: string, cell: SpillRecord['cells'][number]): void {\n if (this.spilledBy.get(cell.key) !== anchor) return;\n this.spilledBy.delete(cell.key);\n this.spillCells.delete(spillCellId(cell.rowId, cell.colId));\n this.spillChanges?.add(cell.key);\n }\n\n private resolveSpillByCoord(colStr: string, rowNum: number): FormulaRange | string {\n const record = this.spills.get(`${colStr}${rowNum}`.toUpperCase());\n if (record) return { rows: record.rows, cols: record.cols, values: record.values };\n const value = this.resolveCellByCoord(colStr, rowNum);\n return isFormulaError(value) ? value : '#REF!';\n }\n\n private toSpill(record: SpillRecord): SpreadsheetSpill {\n const row = this.document.rows[record.row];\n const col = this.document.columns[record.col];\n return {\n key: record.anchor,\n anchor: { row: record.row, col: record.col },\n range: {\n startRow: record.row,\n startCol: record.col,\n endRow: record.row + record.rows - 1,\n endCol: record.col + record.cols - 1\n },\n formula: row && col ? this.getCell(row.id, col.id).raw : ''\n };\n }\n\n /**\n * The dynamic array covering (row, col), whether it is the anchor (the cell\n * holding the formula) or a spilled cell; null when there is none.\n */\n public getSpillAt(row: number, col: number): SpreadsheetSpill | null {\n if (this.spills.size === 0) return null;\n const key = `${indexToColName(col)}${row + 1}`;\n const record = this.spills.get(key) ?? this.spills.get(this.spilledBy.get(key) ?? '');\n return record ? this.toSpill(record) : null;\n }\n\n /** Every dynamic array currently spilled. */\n public getSpills(): SpreadsheetSpill[] {\n return Array.from(this.spills.values(), (record) => this.toSpill(record));\n }\n\n /** Whether `range` overlaps a spilled array (its anchor or spilled cells). */\n private intersectsSpill(range: CellRange): boolean {\n for (const record of this.spills.values()) {\n const area: CellRange = {\n startRow: record.row,\n startCol: record.col,\n endRow: record.row + record.rows - 1,\n endCol: record.col + record.cols - 1\n };\n if (rangesIntersect(area, range)) return true;\n }\n return false;\n }\n\n private resolveCellByCoord(colStr: string, rowNum: number): any {\n const col = this.document.columns.find((c) => c.key.toUpperCase() === colStr.toUpperCase());\n const row = this.document.rows[rowNum - 1];\n if (!col || !row) return 0;\n\n // Blank cells resolve to '' (0 in arithmetic, \"\" in text), as in spreadsheets.\n return this.getCell(row.id, col.id).value ?? '';\n }\n\n private resolveRangeByCoords(sCol: string, sRow: number, eCol: string, eRow: number): any[] {\n const startC = colNameToIndex(sCol);\n const endC = colNameToIndex(eCol);\n const minC = Math.min(startC, endC);\n const maxC = Math.max(startC, endC);\n const minR = Math.min(sRow, eRow);\n // Whole-column ranges (A:A) stop at the last row.\n const maxR = Math.min(Math.max(sRow, eRow), WHOLE_COLUMN_END_ROW, this.document.rows.length);\n\n const results: any[] = [];\n for (let c = minC; c <= maxC; c++) {\n const colName = indexToColName(c);\n const col = this.document.columns.find((colDef) => colDef.key.toUpperCase() === colName);\n if (!col) continue;\n\n for (let r = minR; r <= maxR; r++) {\n const row = this.document.rows[r - 1];\n if (!row) continue;\n results.push(this.getCell(row.id, col.id).value ?? '');\n }\n }\n return results;\n }\n\n private resolveCurrentRowProperty(prop: string): any {\n // Resolve against the row being evaluated, not the selected cell's row.\n const rowIndex = this.evaluatingRowIndex ?? this.activeCell?.row;\n if (rowIndex === undefined || rowIndex === null) return 0;\n const row = this.document.rows[rowIndex];\n if (!row || !row.recordId || !this.primaryDataSourceId) return 0;\n return this.binder.resolveBoundValue(this.primaryDataSourceId, row.recordId, prop) ?? 0;\n }\n\n // --- Selection and Navigation ---\n\n public selectCell(row: number, col: number, extendSelection = false): void {\n const clampedRow = Math.max(0, Math.min(row, this.document.rows.length - 1));\n const clampedCol = Math.max(0, Math.min(col, this.document.columns.length - 1));\n\n // A merged cell is selected as a whole, through its top-left cell.\n const merge = extendSelection ? null : this.getMergeAt(clampedRow, clampedCol);\n const activeRow = merge ? merge.startRow : clampedRow;\n const activeCol = merge ? merge.startCol : clampedCol;\n const rowObj = this.document.rows[activeRow];\n const colObj = this.document.columns[activeCol];\n\n this.activeCell = {\n row: activeRow,\n col: activeCol,\n rowId: rowObj?.id,\n colId: colObj?.id\n };\n\n if (extendSelection && this.selectedRange) {\n this.selectedRange = this.expandRangeToMerges({\n startRow: this.selectedRange.startRow,\n startCol: this.selectedRange.startCol,\n endRow: clampedRow,\n endCol: clampedCol\n });\n } else if (merge) {\n this.selectedRange = { ...merge };\n } else {\n this.selectedRange = {\n startRow: clampedRow,\n startCol: clampedCol,\n endRow: clampedRow,\n endCol: clampedCol\n };\n }\n\n this.onSelectionChange?.(this.activeCell, this.selectedRange);\n }\n\n public selectRange(range: CellRange): void {\n this.selectedRange = range;\n this.onSelectionChange?.(this.activeCell, this.selectedRange);\n }\n\n public startEditing(row?: number, col?: number, initialValue?: string): void {\n this.selectCell(row ?? this.activeCell?.row ?? 0, col ?? this.activeCell?.col ?? 0);\n // selectCell moves into a merge's top-left cell, which holds its content.\n const targetRow = this.activeCell?.row ?? 0;\n const targetCol = this.activeCell?.col ?? 0;\n\n const rowObj = this.document.rows[targetRow];\n const colObj = this.document.columns[targetCol];\n if (!rowObj || !colObj) return;\n\n this.editingCell = {\n row: targetRow,\n col: targetCol,\n rowId: rowObj.id,\n colId: colObj.id\n };\n\n const cell = this.getCell(rowObj.id, colObj.id);\n this.draftValue = initialValue !== undefined ? initialValue : cell.raw;\n }\n\n public commitEditing(valueToCommit?: string): void {\n if (!this.editingCell) return;\n const val = valueToCommit !== undefined ? valueToCommit : this.draftValue;\n if (this.editingCell.rowId && this.editingCell.colId) {\n this.setCellValue(this.editingCell.rowId, this.editingCell.colId, val);\n }\n this.editingCell = null;\n this.draftValue = '';\n }\n\n public cancelEditing(): void {\n this.editingCell = null;\n this.draftValue = '';\n }\n\n public moveCursor(\n direction: 'up' | 'down' | 'left' | 'right',\n extendSelection = false\n ): void {\n if (!this.activeCell) {\n this.selectCell(0, 0);\n return;\n }\n\n // Move in display order: skip hidden, filtered and collapsed rows, hidden\n // columns, and step over merged cells as a whole.\n const { rowOrder, columnOrder } = this.getViewModel();\n let nextRow = this.activeCell.row;\n let nextCol = this.activeCell.col;\n const merge = extendSelection ? null : this.getMergeAt(nextRow, nextCol);\n\n switch (direction) {\n case 'up':\n nextRow = stepInOrder(rowOrder, merge ? merge.startRow : nextRow, -1);\n break;\n case 'down':\n nextRow = stepInOrder(rowOrder, merge ? merge.endRow : nextRow, 1);\n break;\n case 'left':\n nextCol = stepInOrder(columnOrder, merge ? merge.startCol : nextCol, -1);\n break;\n case 'right':\n nextCol = stepInOrder(columnOrder, merge ? merge.endCol : nextCol, 1);\n break;\n }\n\n this.selectCell(nextRow, nextCol, extendSelection);\n }\n\n // --- Grid Structure Mutations ---\n\n public insertColumn(index: number, config?: Partial<SpreadsheetColumn>): void {\n this.recordSnapshot();\n const newId = config?.id || this.generateId('col');\n const newCol: SpreadsheetColumn = {\n id: newId,\n key: indexToColName(index),\n title: config?.title || indexToColName(index),\n width: config?.width || 130,\n type: config?.type || 'freeform',\n binding: config?.binding,\n formula: config?.formula,\n format: config?.format || 'text',\n ...(config?.numberFormat ? { numberFormat: config.numberFormat } : {}),\n readOnly: config?.readOnly\n };\n\n this.shiftReferences({ axis: 'col', index, type: 'insert' });\n this.adjustTableForStructuralChange({ axis: 'col', index, type: 'insert' });\n this.document.columns.splice(index, 0, newCol);\n this.recomputeRowIndices();\n this.recalculateAll();\n this.notifyChange();\n }\n\n public deleteColumn(colId: string): void {\n this.recordSnapshot();\n const colIndex = this.document.columns.findIndex((c) => c.id === colId);\n if (colIndex === -1) return;\n this.shiftReferences({ axis: 'col', index: colIndex, type: 'delete' });\n this.adjustTableForStructuralChange({ axis: 'col', index: colIndex, type: 'delete' });\n this.document.columns = this.document.columns.filter((c) => c.id !== colId);\n for (const rowId of Object.keys(this.document.cells)) {\n delete this.document.cells[rowId][colId];\n }\n this.recomputeRowIndices();\n this.recalculateAll();\n this.notifyChange();\n }\n\n public insertRow(index: number, config?: Partial<SpreadsheetRow>): void {\n this.recordSnapshot();\n const newId = config?.id || this.generateId('row');\n const newRow: SpreadsheetRow = {\n id: newId,\n index,\n height: config?.height || 32,\n recordId: config?.recordId,\n type: config?.type || 'freeform'\n };\n\n this.shiftReferences({ axis: 'row', index, type: 'insert' });\n this.adjustTableForStructuralChange({ axis: 'row', index, type: 'insert' });\n this.document.rows.splice(index, 0, newRow);\n this.recomputeRowIndices();\n this.recalculateAll();\n this.notifyChange();\n }\n\n public deleteRow(rowId: string): void {\n this.recordSnapshot();\n const rowIndex = this.document.rows.findIndex((r) => r.id === rowId);\n if (rowIndex === -1) return;\n this.shiftReferences({ axis: 'row', index: rowIndex, type: 'delete' });\n this.adjustTableForStructuralChange({ axis: 'row', index: rowIndex, type: 'delete' });\n this.document.rows = this.document.rows.filter((r) => r.id !== rowId);\n delete this.document.cells[rowId];\n this.recomputeRowIndices();\n this.recalculateAll();\n this.notifyChange();\n }\n\n private generateId(prefix: 'row' | 'col'): string {\n // The counter keeps ids unique when many rows are created in the same\n // millisecond (e.g. growing the grid on import); duplicate row ids would\n // share cell storage.\n return `${prefix}_${Date.now()}_${(nextIdSequence++).toString(36)}_${Math.random().toString(36).slice(2, 6)}`;\n }\n\n /**\n * Rewrites references in every cell formula (and, for column changes, every\n * column formula) so they keep pointing at the same cells.\n */\n private shiftReferences(change: StructuralChange): void {\n for (const rowCells of Object.values(this.document.cells)) {\n for (const cell of Object.values(rowCells)) {\n if (cell.raw?.startsWith('=')) {\n cell.raw = shiftFormulaReferences(cell.raw, change);\n }\n }\n }\n if (change.axis === 'col') {\n for (const col of this.document.columns) {\n if (col.formula?.startsWith('=')) {\n col.formula = shiftFormulaReferences(col.formula, change);\n }\n }\n }\n }\n\n public setColumnWidth(colId: string, width: number): void {\n const col = this.document.columns.find((c) => c.id === colId);\n if (col) {\n col.width = Math.max(30, width);\n this.notifyChange();\n }\n }\n\n public autoFitColumnWidth(colId: string, customWidth?: number): void {\n if (customWidth !== undefined) {\n this.setColumnWidth(colId, customWidth);\n return;\n }\n const col = this.document.columns.find((c) => c.id === colId);\n if (!col) return;\n\n let maxLen = (col.title || '').length + (col.key ? col.key.length + 3 : 0);\n for (const row of this.document.rows) {\n const cell = this.getCell(row.id, col.id);\n const valStr = formatCellDisplay(cell);\n if (valStr.length > maxLen) {\n maxLen = valStr.length;\n }\n }\n const estimatedWidth = Math.min(600, Math.max(50, Math.ceil(maxLen * 8.5 + 32)));\n this.setColumnWidth(colId, estimatedWidth);\n }\n\n // --- Clipboard TSV/CSV ---\n\n /**\n * Exports cell values as TSV: the whole sheet, or only `range` (e.g. the\n * current selection) when given.\n */\n public exportToTsv(range?: CellRange | null): string {\n const rows = range\n ? this.document.rows.slice(\n Math.min(range.startRow, range.endRow),\n Math.max(range.startRow, range.endRow) + 1,\n )\n : this.document.rows;\n const columns = range\n ? this.document.columns.slice(\n Math.min(range.startCol, range.endCol),\n Math.max(range.startCol, range.endCol) + 1,\n )\n : this.document.columns;\n return rows\n .map((row) =>\n columns\n .map((col) => {\n return formatCellDisplay(this.getCell(row.id, col.id)).replace(/\\t/g, ' ');\n })\n .join('\\t')\n )\n .join('\\n');\n }\n\n /**\n * Pastes tab-separated values starting at (startRow, startCol), adding rows\n * and columns as needed. The whole paste is a single undo step.\n */\n public importFromTsv(tsvData: string, startRow = 0, startCol = 0): void {\n // Only drop the final line break: leading tabs are empty cells.\n const normalized = tsvData.replace(/\\r\\n?/g, '\\n').replace(/\\n$/, '');\n if (normalized === '') return;\n this.writeMatrix(normalized.split('\\n').map((line) => line.split('\\t')), startRow, startCol);\n }\n\n /** Adds rows/columns at the end until (rowIndex, colIndex) exists. */\n private growGrid(rowIndex: number, colIndex: number): void {\n // Growing the grid is not an insertion: no references shift.\n while (rowIndex >= this.document.rows.length) {\n const index = this.document.rows.length;\n this.document.rows.push({ id: this.generateId('row'), index, height: 32, type: 'freeform' });\n }\n while (colIndex >= this.document.columns.length) {\n const key = indexToColName(this.document.columns.length);\n this.document.columns.push({\n id: this.generateId('col'),\n key,\n title: key,\n width: 130,\n type: 'freeform',\n format: 'text'\n });\n }\n }\n\n /**\n * Writes raw inputs starting at (startRow, startCol), growing the grid as\n * needed, as a single undo step with one recalculation.\n */\n private writeMatrix(matrix: string[][], startRow: number, startCol: number): void {\n if (matrix.length === 0) return;\n this.runBatch(() => {\n matrix.forEach((line, rIdx) => {\n line.forEach((val, cIdx) => {\n this.growGrid(startRow + rIdx, startCol + cIdx);\n const row = this.document.rows[startRow + rIdx];\n this.setCellValue(row.id, this.document.columns[startCol + cIdx].id, val);\n });\n });\n });\n }\n\n /**\n * Runs `fn` as one undo step: cell writes inside it are batched and\n * recalculated once, then listeners are notified.\n */\n private runBatch(fn: () => void): void {\n this.recordSnapshot();\n this.batching = true;\n this.pendingCommits = [];\n try {\n fn();\n } finally {\n this.batching = false;\n }\n\n this.recomputeRowIndices();\n this.recalculateAll();\n this.document.updatedAt = Date.now();\n this.notifyChange();\n const commits = this.pendingCommits;\n this.pendingCommits = [];\n for (const [rowId, colId, raw] of commits) {\n this.onCellCommit?.(rowId, colId, raw, this.document.cells[rowId]?.[colId]?.value);\n }\n }\n\n // --- CSV ---\n\n /**\n * Exports the sheet (or `range`) as RFC 4180 CSV. Values are exported as\n * displayed unless `formulas` is set.\n */\n public exportToCsv(options: CsvExportOptions = {}): string {\n const matrix = this.readMatrix(options.range ?? null).map((row) =>\n row.map((cell) => (options.formulas ? cell.raw : formatCellDisplay(cell)))\n );\n return serializeCsv(matrix, {\n delimiter: options.delimiter,\n lineEnding: options.lineEnding,\n bom: options.bom\n });\n }\n\n /**\n * Imports CSV text at (startRow, startCol) (default A1), growing the grid\n * as needed. The whole import is a single undo step.\n */\n public importFromCsv(csv: string, options: CsvImportOptions = {}): void {\n const matrix = parseCsv(csv, { delimiter: options.delimiter });\n this.writeMatrix(matrix, options.startRow ?? 0, options.startCol ?? 0);\n }\n\n /**\n * Writes already-parsed rows of raw inputs (e.g. from an import adapter)\n * starting at (startRow, startCol), as a single undo step.\n */\n public importRows(rows: string[][], options: Omit<CsvImportOptions, 'delimiter'> = {}): void {\n this.writeMatrix(rows, options.startRow ?? 0, options.startCol ?? 0);\n }\n\n /** The cells of `range` (or the whole sheet), row by row. */\n private readMatrix(range: CellRange | null): CellData[][] {\n const r = range ? normalizeRange(range) : null;\n const rows = r ? this.document.rows.slice(r.startRow, r.endRow + 1) : this.document.rows;\n const columns = r ? this.document.columns.slice(r.startCol, r.endCol + 1) : this.document.columns;\n return rows.map((row) => columns.map((col) => this.getCell(row.id, col.id)));\n }\n\n // --- Spreadsheet clipboard ---\n\n /**\n * Builds clipboard data for `range` (default: the selection) as TSV,\n * an HTML table and the lossless internal JSON format. Write every entry\n * with `clipboardData.setData(type, data)` in a `copy` event.\n */\n public copyToClipboardData(range: CellRange | null = this.selectedRange): SpreadsheetClipboardData {\n const r = range\n ? normalizeRange(range)\n : { startRow: 0, startCol: 0, endRow: this.document.rows.length - 1, endCol: this.document.columns.length - 1 };\n const cells = this.readMatrix(r).map((row) =>\n row.map((cell) => {\n const value = cell.error || cell.value;\n const text = formatCellDisplay(cell);\n // A spilled value is pasted as a constant unless its anchor (whose\n // formula re-spills) is copied too.\n if (cell.spillAnchor && !this.spillAnchorInRange(cell.spillAnchor, r)) {\n return { raw: text, value, text };\n }\n return { raw: cell.raw, value, text };\n })\n );\n return createSpreadsheetClipboardData(cells, { row: r.startRow, col: r.startCol });\n }\n\n /**\n * Pastes clipboard data at `target` (default: the selection's top-left).\n * Prefers the internal format (formulas re-based to the target), then an\n * HTML table, then TSV. Returns false when there was nothing to paste.\n */\n public pasteClipboardData(source: SpreadsheetClipboardSource, target?: CellPosition): boolean {\n const parsed = readSpreadsheetClipboard(source);\n if (!parsed) return false;\n const at = target ?? this.getSelectionTopLeft();\n const rows = parsed.origin ? rebaseClipboardRows(parsed.rows, parsed.origin, at) : parsed.rows;\n this.writeMatrix(rows, at.row, at.col);\n const r = normalizeRange({\n startRow: at.row,\n startCol: at.col,\n endRow: at.row + rows.length - 1,\n endCol: at.col + rows.reduce((max, row) => Math.max(max, row.length), 1) - 1\n });\n this.selectRange(r);\n return true;\n }\n\n private spillAnchorInRange(anchor: string, range: CellRange): boolean {\n const record = this.spills.get(anchor);\n return !!record && rangeContains(range, record.row, record.col);\n }\n\n private getSelectionTopLeft(): CellPosition {\n if (this.selectedRange) {\n const r = normalizeRange(this.selectedRange);\n return { row: r.startRow, col: r.startCol };\n }\n return { row: this.activeCell?.row ?? 0, col: this.activeCell?.col ?? 0 };\n }\n\n // --- Table operations: shared helpers ---\n\n /** The table settings object, created on first use. */\n private get table(): SpreadsheetTableSettings {\n if (!this.document.table) this.document.table = {};\n return this.document.table;\n }\n\n /** Records an undo step, applies `fn`, then notifies listeners. */\n private applyTableChange(fn: () => void, options: { recalculate?: boolean } = {}): void {\n this.recordSnapshot();\n fn();\n if (options.recalculate) {\n this.recomputeRowIndices();\n this.recalculateAll();\n }\n this.document.updatedAt = Date.now();\n this.notifyChange();\n }\n\n /** First and last (inclusive) body row: rows between header and footer rows. */\n private getBodyRowBounds(): { start: number; end: number } {\n const { headerRows, footerRows } = getTableSections(this.document);\n return { start: headerRows, end: this.document.rows.length - footerRows - 1 };\n }\n\n private getCellValueAt = (rowIndex: number, colIndex: number): unknown => {\n const row = this.document.rows[rowIndex];\n const col = this.document.columns[colIndex];\n if (!row || !col) return '';\n return this.getCell(row.id, col.id).value;\n };\n\n /** Rewrites every formula so references follow cells that moved. */\n private remapAllFormulas(moveCell: (position: CellPosition) => CellPosition | null): void {\n for (const rowCells of Object.values(this.document.cells)) {\n for (const cell of Object.values(rowCells)) {\n if (cell.raw?.startsWith('=')) {\n cell.raw = remapFormulaReferences(cell.raw, moveCell);\n }\n }\n }\n }\n\n /**\n * Keeps merges in place when rows/columns are inserted or deleted:\n * merges after the change shift, merges across it grow or shrink, and\n * merges reduced to a single cell are dropped.\n */\n private adjustTableForStructuralChange(change: StructuralChange): void {\n const merges = this.document.table?.merges;\n if (!merges?.length) return;\n const startKey = change.axis === 'row' ? 'startRow' : 'startCol';\n const endKey = change.axis === 'row' ? 'endRow' : 'endCol';\n const next: CellRange[] = [];\n for (const merge of merges) {\n const m = { ...merge };\n if (change.type === 'insert') {\n if (m[startKey] >= change.index) m[startKey]++;\n if (m[endKey] >= change.index) m[endKey]++;\n } else {\n if (m[startKey] === change.index && m[endKey] === change.index) continue;\n if (m[startKey] > change.index) m[startKey]--;\n if (m[endKey] >= change.index) m[endKey]--;\n }\n if (!isSingleCellRange(m)) next.push(m);\n }\n this.document.table!.merges = next;\n }\n\n // --- Sort ---\n\n /**\n * Sorts rows by one or more columns (stable; numbers before text, blanks\n * last). Without a range (or with a range spanning every column) whole rows\n * move; with a range only the cells inside it move. Header and footer rows\n * never move. References follow the moved cells. Returns false when the\n * sort is rejected (no valid keys, a key outside the range, or merged\n * cells in the sorted area).\n */\n public sortRows(keys: SortKey[], options: { range?: CellRange | null } = {}): boolean {\n const colCount = this.document.columns.length;\n const body = this.getBodyRowBounds();\n const range = options.range ? normalizeRange(options.range) : null;\n const startRow = Math.max(range?.startRow ?? body.start, body.start);\n const endRow = Math.min(range?.endRow ?? body.end, body.end);\n const startCol = range ? Math.max(0, range.startCol) : 0;\n const endCol = range ? Math.min(colCount - 1, range.endCol) : colCount - 1;\n if (endRow - startRow < 1 || startCol > endCol) return false;\n\n const keyCols = keys.map((key) => ({\n index: this.document.columns.findIndex((c) => c.id === key.colId),\n direction: key.direction ?? 'asc'\n }));\n if (keyCols.length === 0 || keyCols.some((k) => k.index < startCol || k.index > endCol)) return false;\n\n const area: CellRange = { startRow, startCol, endRow, endCol };\n if ((this.document.table?.merges ?? []).some((m) => rangesIntersect(m, area))) return false;\n // Part of a dynamic array can't move (Excel: \"You can't change part of an array\").\n if (this.intersectsSpill(area)) return false;\n\n const sourceRows: number[] = [];\n for (let r = startRow; r <= endRow; r++) sourceRows.push(r);\n const sorted = sourceRows\n .map((r) => ({ r, values: keyCols.map((k) => this.getCellValueAt(r, k.index)) }))\n .sort((a, b) => {\n for (let i = 0; i < keyCols.length; i++) {\n const result = compareCellValues(a.values[i], b.values[i], keyCols[i].direction);\n if (result !== 0) return result;\n }\n return a.r - b.r; // stable\n })\n .map((entry) => entry.r);\n if (sorted.every((r, i) => r === sourceRows[i])) return true; // already sorted\n\n // newIndexOf[oldRow] = newRow\n const newIndexOf = new Map<number, number>();\n sorted.forEach((oldRow, i) => newIndexOf.set(oldRow, startRow + i));\n const wholeRows = startCol === 0 && endCol === colCount - 1;\n\n this.applyTableChange(() => {\n this.remapAllFormulas(({ row, col }) => {\n const target = newIndexOf.get(row);\n if (target === undefined || col < startCol || col > endCol) return null;\n return { row: target, col };\n });\n\n if (wholeRows) {\n const moved = sorted.map((r) => this.document.rows[r]);\n this.document.rows.splice(startRow, moved.length, ...moved);\n } else {\n const colIds = this.document.columns.slice(startCol, endCol + 1).map((c) => c.id);\n const snapshot = sorted.map((oldRow) => {\n const rowId = this.document.rows[oldRow].id;\n return colIds.map((colId) => this.document.cells[rowId]?.[colId]);\n });\n snapshot.forEach((cells, i) => {\n const rowId = this.document.rows[startRow + i].id;\n if (!this.document.cells[rowId]) this.document.cells[rowId] = {};\n colIds.forEach((colId, c) => {\n if (cells[c]) this.document.cells[rowId][colId] = cells[c]!;\n else delete this.document.cells[rowId][colId];\n });\n });\n }\n }, { recalculate: true });\n return true;\n }\n\n // --- Filters ---\n\n public getFilterState(): SpreadsheetFilterState {\n return this.document.table?.filter ?? { enabled: false, rules: [] };\n }\n\n /** Replaces all filter rules (and turns filters on when there are any). */\n public setFilterRules(rules: NewFilterRule[]): void {\n this.applyTableChange(() => {\n this.table.filter = {\n enabled: rules.length > 0,\n rules: rules.map((rule) => ({ ...rule, id: rule.id ?? this.generateFilterId() }))\n };\n });\n }\n\n /** Adds a filter rule (AND-combined with the others) and turns filters on. Returns its id. */\n public addFilterRule(rule: NewFilterRule): string {\n const id = rule.id ?? this.generateFilterId();\n this.applyTableChange(() => {\n const current = this.getFilterState();\n this.table.filter = { enabled: true, rules: [...current.rules, { ...rule, id }] };\n });\n return id;\n }\n\n public updateFilterRule(ruleId: string, changes: Partial<Omit<FilterRule, 'id'>>): void {\n const current = this.getFilterState();\n if (!current.rules.some((r) => r.id === ruleId)) return;\n this.applyTableChange(() => {\n this.table.filter = {\n ...current,\n rules: current.rules.map((r) => (r.id === ruleId ? { ...r, ...changes } : r))\n };\n });\n }\n\n public removeFilterRule(ruleId: string): void {\n const current = this.getFilterState();\n if (!current.rules.some((r) => r.id === ruleId)) return;\n this.applyTableChange(() => {\n this.table.filter = { ...current, rules: current.rules.filter((r) => r.id !== ruleId) };\n });\n }\n\n public clearFilters(): void {\n if (this.getFilterState().rules.length === 0) return;\n this.applyTableChange(() => {\n this.table.filter = { enabled: false, rules: [] };\n });\n }\n\n /** Turns filtering on or off, keeping the rules. */\n public setFiltersEnabled(enabled: boolean): void {\n const current = this.getFilterState();\n if (current.enabled === enabled) return;\n this.applyTableChange(() => {\n this.table.filter = { ...current, enabled };\n });\n }\n\n public toggleFilters(): void {\n this.setFiltersEnabled(!this.getFilterState().enabled);\n }\n\n private generateFilterId(): string {\n return `filter_${Date.now()}_${(nextIdSequence++).toString(36)}_${Math.random().toString(36).slice(2, 6)}`;\n }\n\n // --- Header, footer and frozen rows/columns ---\n\n public setHeaderRowCount(count: number): void {\n this.setTableCount('headerRowCount', count, this.document.rows.length);\n }\n\n public setFooterRowCount(count: number): void {\n this.setTableCount('footerRowCount', count, this.document.rows.length);\n }\n\n public setHeaderColumnCount(count: number): void {\n this.setTableCount('headerColumnCount', count, this.document.columns.length);\n }\n\n /** Keeps the first `count` rows visible while scrolling. 0 unfreezes. */\n public setFrozenRowCount(count: number): void {\n this.setTableCount('frozenRowCount', count, this.document.rows.length);\n }\n\n /** Keeps the first `count` columns visible while scrolling. 0 unfreezes. */\n public setFrozenColumnCount(count: number): void {\n this.setTableCount('frozenColumnCount', count, this.document.columns.length);\n }\n\n private setTableCount(\n key: 'headerRowCount' | 'footerRowCount' | 'headerColumnCount' | 'frozenRowCount' | 'frozenColumnCount',\n count: number,\n max: number\n ): void {\n const value = Math.max(0, Math.min(Math.floor(count), max));\n if ((this.document.table?.[key] ?? 0) === value) return;\n this.applyTableChange(() => {\n this.table[key] = value;\n });\n }\n\n // --- Number formats ---\n //\n // Cells are replaced, never mutated in place: framework bindings compare\n // cell objects by identity to decide what to re-render.\n\n /**\n * Sets an explicit number format code (e.g. `0.00`, `\"$\"#,##0.00`,\n * `m/d/yyyy`, `[Red]0;[Blue]-0`) on every cell in `range`, including blank\n * cells, so values typed later keep it. `null` removes explicit formats: the\n * cells go back to their column's format or the one chosen for typed input.\n * Undoable as one step. Returns false when there is no range.\n */\n public setCellNumberFormat(range: CellRange | null, code: string | null): boolean {\n if (!range) return false;\n const r = normalizeRange(range);\n this.recordSnapshot();\n const kind = code === null ? undefined : cellFormatForNumberFormat(code);\n for (let ri = r.startRow; ri <= r.endRow; ri++) {\n const row = this.document.rows[ri];\n if (!row) continue;\n for (let ci = r.startCol; ci <= r.endCol; ci++) {\n const col = this.document.columns[ci];\n if (!col) continue;\n const cells = (this.document.cells[row.id] ??= {});\n const existing = cells[col.id];\n if (code === null) {\n if (!existing?.explicitNumberFormat) continue;\n if (existing.raw === '' && existing.value === '' && !existing.error) {\n delete cells[col.id];\n } else {\n const { explicitNumberFormat: _explicit, ...rest } = existing;\n cells[col.id] = this.withNumberFormat(rest, this.implicitNumberFormat(rest, col, row));\n }\n } else {\n cells[col.id] = {\n ...(existing ?? { raw: '', value: '' }),\n format: kind ?? existing?.format ?? col.format,\n numberFormat: code,\n explicitNumberFormat: true\n };\n }\n this.refreshSpilledNumberFormat(row, col);\n }\n }\n this.document.updatedAt = Date.now();\n this.notifyChange();\n return true;\n }\n\n /**\n * Sets the number format code of a column (`null` or `General` clears it).\n * Its cells without an explicit format of their own use it, including\n * values typed later; when cleared they go back to the format chosen for\n * typed input. Undoable.\n */\n public setColumnNumberFormat(colId: string, code: string | null): void {\n const col = this.getColumn(colId);\n if (!col) return;\n this.recordSnapshot();\n if (code === null || isGeneralNumberFormat(code)) delete col.numberFormat;\n else col.numberFormat = code;\n for (const row of this.document.rows) {\n const cells = this.document.cells[row.id];\n const cell = cells?.[col.id];\n if (cells && cell && !cell.explicitNumberFormat) {\n cells[col.id] = this.withNumberFormat(cell, this.implicitNumberFormat(cell, col, row));\n }\n this.refreshSpilledNumberFormat(row, col);\n }\n this.document.updatedAt = Date.now();\n this.notifyChange();\n }\n\n /** The column's format, or the one typed input chose (typed cells only). */\n private implicitNumberFormat(cell: CellData, col: SpreadsheetColumn, row: SpreadsheetRow): string | undefined {\n const typed = cell.raw !== '' && !cell.raw.startsWith('=') && !(col.type === 'bound' && col.binding && row.recordId);\n return this.fixedNumberFormat(col, undefined) ?? (typed ? parseCellInput(cell.raw).numberFormat : undefined);\n }\n\n /** A copy of `cell` with `numberFormat` set, or removed when undefined. */\n private withNumberFormat(cell: CellData, numberFormat: string | undefined): CellData {\n const { numberFormat: _old, ...rest } = cell;\n return numberFormat === undefined ? rest : { ...rest, numberFormat };\n }\n\n /** Re-applies the stored cell's (or the column's) format to a spilled value shown there. */\n private refreshSpilledNumberFormat(row: SpreadsheetRow, col: SpreadsheetColumn): void {\n const id = spillCellId(row.id, col.id);\n const spilled = this.spillCells.get(id);\n if (!spilled) return;\n const { numberFormat: _old, explicitNumberFormat: _explicit, ...rest } = spilled;\n this.spillCells.set(id, { ...rest, ...this.fixedNumberFormatFields(col, this.document.cells[row.id]?.[col.id]) });\n }\n\n // --- Hide / unhide ---\n\n public hideRows(indices: number[]): void {\n this.setHidden('row', indices, true);\n }\n\n public unhideRows(indices: number[]): void {\n this.setHidden('row', indices, false);\n }\n\n public hideColumns(indices: number[]): void {\n this.setHidden('col', indices, true);\n }\n\n public unhideColumns(indices: number[]): void {\n this.setHidden('col', indices, false);\n }\n\n /** Unhides every hidden row and column (filters are unaffected). */\n public unhideAll(): void {\n const rows = this.document.rows.flatMap((r, i) => (r.hidden ? [i] : []));\n const cols = this.document.columns.flatMap((c, i) => (c.hidden ? [i] : []));\n if (rows.length === 0 && cols.length === 0) return;\n this.applyTableChange(() => {\n rows.forEach((i) => delete this.document.rows[i].hidden);\n cols.forEach((i) => delete this.document.columns[i].hidden);\n });\n }\n\n private setHidden(axis: 'row' | 'col', indices: number[], hidden: boolean): void {\n const items: Array<SpreadsheetRow | SpreadsheetColumn> = axis === 'row' ? this.document.rows : this.document.columns;\n const targets = indices.filter((i) => items[i] && !!items[i].hidden !== hidden);\n if (targets.length === 0) return;\n this.applyTableChange(() => {\n for (const i of targets) {\n if (hidden) items[i].hidden = true;\n else delete items[i].hidden;\n }\n });\n }\n\n // --- Merged cells ---\n\n public getMerges(): CellRange[] {\n return this.document.table?.merges ?? [];\n }\n\n /** The merge containing (row, col), or null. */\n public getMergeAt(row: number, col: number): CellRange | null {\n return this.getMerges().find((m) => rangeContains(m, row, col)) ?? null;\n }\n\n /** Grows `range` until no merge crosses its edge. Keeps the drag direction. */\n public expandRangeToMerges(range: CellRange): CellRange {\n let r = normalizeRange(range);\n let changed = true;\n while (changed) {\n changed = false;\n for (const m of this.getMerges()) {\n if (rangesIntersect(m, r) && !rangeContainsRange(r, m)) {\n r = {\n startRow: Math.min(r.startRow, m.startRow),\n startCol: Math.min(r.startCol, m.startCol),\n endRow: Math.max(r.endRow, m.endRow),\n endCol: Math.max(r.endCol, m.endCol)\n };\n changed = true;\n }\n }\n }\n const rowsReversed = range.startRow > range.endRow;\n const colsReversed = range.startCol > range.endCol;\n return {\n startRow: rowsReversed ? r.endRow : r.startRow,\n endRow: rowsReversed ? r.startRow : r.endRow,\n startCol: colsReversed ? r.endCol : r.startCol,\n endCol: colsReversed ? r.startCol : r.endCol\n };\n }\n\n /**\n * Merges `range` (default: the selection) into one cell anchored on its\n * top-left cell; the other cells are cleared. Merges fully inside the range\n * are absorbed. Returns false for single cells and for ranges that\n * partially overlap an existing merge.\n */\n public mergeCells(range: CellRange | null = this.selectedRange): boolean {\n if (!range) return false;\n const r = normalizeRange(range);\n if (\n isSingleCellRange(r) ||\n r.startRow < 0 ||\n r.startCol < 0 ||\n r.endRow >= this.document.rows.length ||\n r.endCol >= this.document.columns.length\n ) {\n return false;\n }\n const merges = this.getMerges();\n if (merges.some((m) => rangesIntersect(m, r) && !rangeContainsRange(r, m))) return false;\n if (this.intersectsSpill(r)) return false;\n\n this.applyTableChange(() => {\n for (let row = r.startRow; row <= r.endRow; row++) {\n const rowId = this.document.rows[row].id;\n for (let col = r.startCol; col <= r.endCol; col++) {\n if (row === r.startRow && col === r.startCol) continue;\n delete this.document.cells[rowId]?.[this.document.columns[col].id];\n }\n }\n this.table.merges = [...merges.filter((m) => !rangeContainsRange(r, m)), r];\n }, { recalculate: true });\n this.selectCell(r.startRow, r.startCol);\n return true;\n }\n\n /** Removes every merge intersecting `range` (default: the selection). */\n public unmergeCells(range: CellRange | null = this.selectedRange): boolean {\n if (!range) return false;\n const merges = this.getMerges();\n const remaining = merges.filter((m) => !rangesIntersect(m, range));\n if (remaining.length === merges.length) return false;\n // Recalculate: the merge may have blocked a dynamic array (#SPILL!).\n this.applyTableChange(() => {\n this.table.merges = remaining;\n }, { recalculate: true });\n return true;\n }\n\n // --- Autofill ---\n\n /**\n * Fills `target` from `source` like dragging the fill handle. `target` is\n * the extended range (source included) and must extend `source` down, up,\n * right or left. Numbers and dates continue their series, text ending in a\n * number counts up, other text repeats, and formulas are copied with\n * their relative references shifted (`$` parts stay). Returns false when\n * the ranges don't line up.\n */\n public autofill(source: CellRange, target: CellRange): boolean {\n const s = normalizeRange(source);\n const t = normalizeRange(target);\n const direction = getFillDirection(s, t);\n if (!direction || t.startRow < 0 || t.startCol < 0) return false;\n if (s.endRow >= this.document.rows.length || s.endCol >= this.document.columns.length) return false;\n\n const vertical = direction === 'down' || direction === 'up';\n const forward = direction === 'down' || direction === 'right';\n // Source positions along the fill axis, nearest to the fill area last.\n const sourceSteps: number[] = [];\n const [sLo, sHi] = vertical ? [s.startRow, s.endRow] : [s.startCol, s.endCol];\n for (let i = sLo; i <= sHi; i++) sourceSteps.push(i);\n if (!forward) sourceSteps.reverse();\n const fillSteps: number[] = [];\n if (forward) for (let i = sHi + 1; i <= (vertical ? t.endRow : t.endCol); i++) fillSteps.push(i);\n else for (let i = sLo - 1; i >= (vertical ? t.startRow : t.startCol); i--) fillSteps.push(i);\n\n const [lLo, lHi] = vertical ? [s.startCol, s.endCol] : [s.startRow, s.endRow];\n this.runBatch(() => {\n this.growGrid(vertical ? Math.max(t.endRow, 0) : s.endRow, vertical ? s.endCol : Math.max(t.endCol, 0));\n for (let line = lLo; line <= lHi; line++) {\n const at = (step: number) => (vertical ? { row: step, col: line } : { row: line, col: step });\n const raws = sourceSteps.map((step) => {\n const p = at(step);\n return this.getCell(this.document.rows[p.row].id, this.document.columns[p.col].id).raw;\n });\n const hasFormula = raws.some((raw) => raw.startsWith('='));\n const series = hasFormula ? null : fillSeries(raws, fillSteps.length);\n fillSteps.forEach((step, i) => {\n const p = at(step);\n let raw: string;\n if (series) {\n raw = series[i];\n } else {\n const from = sourceSteps[i % sourceSteps.length];\n raw = raws[i % raws.length];\n if (raw.startsWith('=')) {\n const delta = step - from;\n raw = vertical ? offsetFormulaReferences(raw, delta, 0) : offsetFormulaReferences(raw, 0, delta);\n }\n }\n this.setCellValue(this.document.rows[p.row].id, this.document.columns[p.col].id, raw);\n });\n }\n });\n this.selectRange(t);\n return true;\n }\n\n // --- Categories (row groups) ---\n\n /**\n * Groups body rows by the value in `colId`, with optional per-group\n * summaries (e.g. `[{ colId, aggregate: 'sum' }]`).\n */\n public groupRowsBy(colId: string, summaries: GroupSummary[] = []): void {\n if (!this.getColumn(colId)) return;\n this.applyTableChange(() => {\n this.table.grouping = { colId, summaries, collapsed: [] };\n });\n }\n\n public ungroupRows(): void {\n if (!this.document.table?.grouping) return;\n this.applyTableChange(() => {\n delete this.table.grouping;\n });\n }\n\n /** Sets (or with `null`, removes) the group summary for a column. */\n public setGroupSummary(colId: string, aggregate: GroupAggregate | null): void {\n const grouping = this.document.table?.grouping;\n if (!grouping) return;\n this.applyTableChange(() => {\n const others = grouping.summaries.filter((s) => s.colId !== colId);\n this.table.grouping = {\n ...grouping,\n summaries: aggregate ? [...others, { colId, aggregate }] : others\n };\n });\n }\n\n public setGroupCollapsed(key: string, collapsed: boolean): void {\n const grouping = this.document.table?.grouping;\n if (!grouping || grouping.collapsed.includes(key) === collapsed) return;\n this.applyTableChange(() => {\n this.table.grouping = {\n ...grouping,\n collapsed: collapsed ? [...grouping.collapsed, key] : grouping.collapsed.filter((k) => k !== key)\n };\n });\n }\n\n public toggleGroupCollapsed(key: string): void {\n const grouping = this.document.table?.grouping;\n if (!grouping) return;\n this.setGroupCollapsed(key, !grouping.collapsed.includes(key));\n }\n\n /** The current row groups with their summaries (empty when not grouped). */\n public getGroups(): SpreadsheetRowGroup[] {\n return computeRowGroups(this.document, this.getCellValueAt);\n }\n\n // --- Transpose ---\n\n /**\n * Transposes `range` (default: the selection) in place around its top-left\n * cell: rows become columns. Cells left uncovered are cleared, the grid\n * grows if needed, and references follow the moved cells. Returns false\n * for single cells or when merged cells are involved.\n */\n public transposeRange(range: CellRange | null = this.selectedRange): boolean {\n if (!range) return false;\n const s = normalizeRange(range);\n if (isSingleCellRange(s)) return false;\n const height = s.endRow - s.startRow + 1;\n const width = s.endCol - s.startCol + 1;\n const t: CellRange = { startRow: s.startRow, startCol: s.startCol, endRow: s.startRow + width - 1, endCol: s.startCol + height - 1 };\n if (this.getMerges().some((m) => rangesIntersect(m, s) || rangesIntersect(m, t))) return false;\n if (this.intersectsSpill(s) || this.intersectsSpill(t)) return false;\n\n this.applyTableChange(() => {\n this.growGrid(t.endRow, t.endCol);\n this.remapAllFormulas(({ row, col }) => {\n if (!rangeContains(s, row, col)) return null;\n return { row: s.startRow + (col - s.startCol), col: s.startCol + (row - s.startRow) };\n });\n\n const rowId = (r: number) => this.document.rows[r].id;\n const colId = (c: number) => this.document.columns[c].id;\n const moved: Array<{ row: number; col: number; cell: CellData | undefined }> = [];\n for (let r = s.startRow; r <= s.endRow; r++) {\n for (let c = s.startCol; c <= s.endCol; c++) {\n moved.push({\n row: s.startRow + (c - s.startCol),\n col: s.startCol + (r - s.startRow),\n cell: this.document.cells[rowId(r)]?.[colId(c)]\n });\n delete this.document.cells[rowId(r)]?.[colId(c)];\n }\n }\n for (const { row, col, cell } of moved) {\n if (!cell) continue;\n if (!this.document.cells[rowId(row)]) this.document.cells[rowId(row)] = {};\n this.document.cells[rowId(row)][colId(col)] = cell;\n }\n }, { recalculate: true });\n this.selectRange(t);\n return true;\n }\n\n // --- View model ---\n\n /**\n * What to render: visible rows (with group headers) and columns in display\n * order, frozen offsets and merged-cell spans. Filters, hidden rows/columns\n * and collapsed groups only affect this view, never the document.\n */\n public getViewModel(): SpreadsheetViewModel {\n return buildSpreadsheetView(this.document, this.getCellValueAt);\n }\n\n // --- Undo/Redo Snapshots ---\n\n private recordSnapshot(): void {\n if (this.isApplyingHistory || this.batching) return;\n this.undoStack.push(JSON.stringify(this.document));\n if (this.undoStack.length > 50) this.undoStack.shift();\n this.redoStack = [];\n this.trimHistory();\n }\n\n /** Drops the oldest snapshots beyond `maxHistoryBytes`, always keeping the newest. */\n private trimHistory(): void {\n if (this.maxHistoryBytes <= 0 || this.undoStack.length <= 1) return;\n let total = 0;\n for (const s of this.undoStack) total += s.length * 2;\n for (const s of this.redoStack) total += s.length * 2;\n while (total > this.maxHistoryBytes && this.undoStack.length > 1) {\n total -= this.undoStack.shift()!.length * 2;\n }\n }\n\n /** Approximate bytes held by the undo/redo snapshots (UTF-16 size). */\n public getHistoryByteSize(): number {\n let total = 0;\n for (const s of this.undoStack) total += s.length * 2;\n for (const s of this.redoStack) total += s.length * 2;\n return total;\n }\n\n /** Number of undo / redo snapshots currently held. */\n public getHistoryDepth(): { undo: number; redo: number } {\n return { undo: this.undoStack.length, redo: this.redoStack.length };\n }\n\n public undo(): void {\n if (this.undoStack.length === 0) return;\n this.isApplyingHistory = true;\n try {\n this.redoStack.push(JSON.stringify(this.document));\n this.document = JSON.parse(this.undoStack.pop()!);\n this.recalculateAll();\n this.notifyChange();\n } finally {\n this.isApplyingHistory = false;\n }\n }\n\n public redo(): void {\n if (this.redoStack.length === 0) return;\n this.isApplyingHistory = true;\n try {\n this.undoStack.push(JSON.stringify(this.document));\n this.document = JSON.parse(this.redoStack.pop()!);\n this.recalculateAll();\n this.notifyChange();\n } finally {\n this.isApplyingHistory = false;\n }\n }\n\n private notifyChange(): void {\n this.onDocumentChange?.(this.document);\n }\n}\n\n/**\n * The index after (`delta` = 1) or before (-1) `from` in a display order,\n * staying put at the edges. When `from` is not displayed (hidden), moves to\n * the nearest displayed index in that direction.\n */\nfunction stepInOrder(order: number[], from: number, delta: 1 | -1): number {\n if (order.length === 0) return from;\n const pos = order.indexOf(from);\n if (pos === -1) {\n const candidates = order.filter((i) => (delta > 0 ? i > from : i < from));\n if (candidates.length === 0) return from;\n return candidates.reduce((best, i) => (delta > 0 ? Math.min(best, i) : Math.max(best, i)));\n }\n return order[Math.max(0, Math.min(order.length - 1, pos + delta))];\n}\n","/**\n * The spreadsheet's table context menu, defined once so the React and Svelte\n * editors show the same actions. Frameworks render the items and call\n * `run()`; the controller's change listeners refresh their state.\n */\nimport type { SpreadsheetController } from './controller';\nimport type { CellRange } from './types';\nimport type { CellPosition } from './formula';\nimport { formatCellDisplay, indexToColName } from './formula';\nimport { isSingleCellRange, normalizeRange, rangeContains, rangesIntersect } from './table';\nimport { NUMBER_FORMAT_PRESETS, isGeneralNumberFormat } from './numfmt/presets';\n\nexport interface SpreadsheetMenuItem {\n id: string;\n label: string;\n disabled?: boolean;\n /** Draw a divider before this item. */\n separatorBefore?: boolean;\n /** The item is the current choice of its group (e.g. the cell's number format). */\n checked?: boolean;\n /**\n * Ask for text before running (e.g. a custom number format code): the\n * editor prompts with `label` and `defaultValue`, then calls `run(text)`;\n * cancelling skips `run`.\n */\n input?: { label: string; defaultValue?: string };\n run: (input?: string) => void;\n}\n\n/**\n * Runs a menu item the way the editors do: an item with `input` first asks\n * for text with `ask` (default `window.prompt`) and is skipped when that is\n * cancelled. Returns whether `run` was called.\n */\nexport function runSpreadsheetMenuItem(\n item: SpreadsheetMenuItem,\n ask?: (label: string, defaultValue: string) => string | null | undefined\n): boolean {\n if (!item.input) {\n item.run();\n return true;\n }\n const prompt =\n ask ?? ((label: string, value: string) => (typeof window !== 'undefined' && window.prompt ? window.prompt(label, value) : null));\n const text = prompt(item.input.label, item.input.defaultValue ?? '');\n if (text === null || text === undefined) return false;\n item.run(text);\n return true;\n}\n\n/**\n * Where to place a `position: fixed` menu opened at `point` so it stays inside\n * the viewport: it flips to the left of / above the pointer when it would\n * overflow the right / bottom edge, or, when the flipped menu would not fit\n * either, slides back just enough to fit. It is kept at least `margin` px from\n * every edge (a menu taller than the viewport is pinned to the top and should\n * scroll, e.g. with `max-height: calc(100vh - 2 * margin)`).\n */\nexport function clampMenuPosition(\n point: { x: number; y: number },\n size: { width: number; height: number },\n viewport: { width: number; height: number },\n margin = 4\n): { x: number; y: number } {\n const place = (start: number, length: number, limit: number) => {\n if (start + length <= limit - margin) return Math.max(margin, start);\n const flipped = start - length;\n // Flip when that fits; otherwise slide it back just enough to fit.\n return Math.max(margin, flipped >= margin ? flipped : limit - margin - length);\n };\n return {\n x: place(point.x, size.width, viewport.width),\n y: place(point.y, size.height, viewport.height)\n };\n}\n\nconst quote = (value: unknown) => {\n const text = String(value ?? '');\n return text.length > 24 ? `\"${text.slice(0, 23)}…\"` : `\"${text}\"`;\n};\n\n/**\n * Menu items for a right-click on `cell`. When the cell is inside the\n * selection, range actions (hide, merge, transpose) apply to the selection;\n * otherwise to the clicked cell.\n */\nexport function getSpreadsheetMenuItems(controller: SpreadsheetController, cell: CellPosition): SpreadsheetMenuItem[] {\n const doc = controller.document;\n const column = doc.columns[cell.col];\n const row = doc.rows[cell.row];\n if (!column || !row) return [];\n\n const selection: CellRange =\n controller.selectedRange && rangeContains(controller.selectedRange, cell.row, cell.col)\n ? normalizeRange(controller.selectedRange)\n : { startRow: cell.row, startCol: cell.col, endRow: cell.row, endCol: cell.col };\n const colName = indexToColName(cell.col);\n const cellData = controller.getCell(row.id, column.id);\n const value = cellData.value;\n const table = doc.table ?? {};\n const filter = controller.getFilterState();\n const grouping = table.grouping;\n const rows = Array.from({ length: selection.endRow - selection.startRow + 1 }, (_, i) => selection.startRow + i);\n const cols = Array.from({ length: selection.endCol - selection.startCol + 1 }, (_, i) => selection.startCol + i);\n const anyHidden = doc.rows.some((r) => r.hidden) || doc.columns.some((c) => c.hidden);\n const hasMerge = controller.getMerges().some((m) => rangesIntersect(m, selection));\n const sortRange = isSingleCellRange(selection) ? null : selection;\n\n const items: SpreadsheetMenuItem[] = [\n {\n id: 'sort-asc',\n label: `Sort ascending by column ${colName}`,\n run: () => controller.sortRows([{ colId: column.id, direction: 'asc' }], { range: sortRange }),\n },\n {\n id: 'sort-desc',\n label: `Sort descending by column ${colName}`,\n run: () => controller.sortRows([{ colId: column.id, direction: 'desc' }], { range: sortRange }),\n },\n {\n id: 'filter-equals',\n label: `Show only rows where ${colName} = ${quote(formatCellDisplay(cellData))}`,\n separatorBefore: true,\n run: () => controller.addFilterRule({ colId: column.id, operator: 'equals', value: String(value ?? '') }),\n },\n {\n id: 'filter-toggle',\n label: filter.enabled ? 'Turn filters off' : 'Turn filters on',\n disabled: filter.rules.length === 0,\n run: () => controller.toggleFilters(),\n },\n {\n id: 'filter-clear',\n label: 'Clear filters',\n disabled: filter.rules.length === 0,\n run: () => controller.clearFilters(),\n },\n {\n id: 'freeze-rows',\n label: `Freeze rows 1–${cell.row + 1}`,\n separatorBefore: true,\n run: () => controller.setFrozenRowCount(cell.row + 1),\n },\n {\n id: 'freeze-columns',\n label: `Freeze columns A–${colName}`,\n run: () => controller.setFrozenColumnCount(cell.col + 1),\n },\n {\n id: 'unfreeze',\n label: 'Unfreeze rows and columns',\n disabled: !table.frozenRowCount && !table.frozenColumnCount,\n run: () => {\n controller.setFrozenRowCount(0);\n controller.setFrozenColumnCount(0);\n },\n },\n {\n id: 'header-rows',\n label: `Use rows 1–${cell.row + 1} as header rows`,\n run: () => controller.setHeaderRowCount(cell.row + 1),\n },\n {\n id: 'footer-rows',\n label: `Use rows ${cell.row + 1}–${doc.rows.length} as footer rows`,\n run: () => controller.setFooterRowCount(doc.rows.length - cell.row),\n },\n {\n id: 'hide-rows',\n label: rows.length > 1 ? `Hide ${rows.length} rows` : `Hide row ${cell.row + 1}`,\n separatorBefore: true,\n run: () => controller.hideRows(rows),\n },\n {\n id: 'hide-columns',\n label: cols.length > 1 ? `Hide ${cols.length} columns` : `Hide column ${colName}`,\n run: () => controller.hideColumns(cols),\n },\n {\n id: 'unhide-all',\n label: 'Unhide all rows and columns',\n disabled: !anyHidden,\n run: () => controller.unhideAll(),\n },\n {\n id: 'merge',\n label: 'Merge cells',\n separatorBefore: true,\n disabled: isSingleCellRange(selection),\n run: () => {\n controller.mergeCells(selection);\n },\n },\n {\n id: 'unmerge',\n label: 'Unmerge cells',\n disabled: !hasMerge,\n run: () => {\n controller.unmergeCells(selection);\n },\n },\n {\n id: 'transpose',\n label: 'Transpose',\n disabled: isSingleCellRange(selection),\n run: () => {\n controller.transposeRange(selection);\n },\n },\n ];\n\n // Format cells: number format presets and a custom code, for the selection.\n const currentFormat = cellData.numberFormat;\n const presetMatch = NUMBER_FORMAT_PRESETS.find((p) =>\n p.id === 'general' ? isGeneralNumberFormat(currentFormat) : p.code === currentFormat\n );\n NUMBER_FORMAT_PRESETS.forEach((preset, i) => {\n items.push({\n id: `number-format-${preset.id}`,\n label: `Format cells: ${preset.label}`,\n separatorBefore: i === 0,\n checked: presetMatch === preset,\n run: () => {\n controller.setCellNumberFormat(selection, preset.code);\n },\n });\n });\n items.push({\n id: 'number-format-custom',\n label: 'Format cells: Custom…',\n checked: !presetMatch,\n input: { label: 'Number format code, e.g. #,##0.00;[Red](#,##0.00)', defaultValue: currentFormat ?? 'General' },\n run: (code) => {\n if (code === undefined) return;\n controller.setCellNumberFormat(selection, code.trim() === '' ? null : code);\n },\n });\n\n if (grouping) {\n items.push(\n {\n id: 'ungroup',\n label: 'Remove categories',\n separatorBefore: true,\n run: () => controller.ungroupRows(),\n },\n ...(['sum', 'count', 'average'] as const).map((aggregate) => ({\n id: `summary-${aggregate}`,\n label: `Summarize column ${colName}: ${aggregate.toUpperCase()}`,\n run: () => controller.setGroupSummary(column.id, aggregate),\n })),\n );\n } else {\n items.push({\n id: 'group-by',\n label: `Categorize by column ${colName}`,\n separatorBefore: true,\n run: () => controller.groupRowsBy(column.id),\n });\n }\n\n return items;\n}\n","import type { SpreadsheetController } from './controller';\n\n/**\n * Controller methods the React and Svelte spreadsheet bindings expose as-is,\n * so both frameworks offer the same table operations. They need no extra\n * state syncing: the controller reports changes through `onDocumentChange`\n * and `onSelectionChange`.\n */\nexport const SPREADSHEET_TABLE_ACTIONS = [\n 'sortRows',\n 'getFilterState',\n 'setFilterRules',\n 'addFilterRule',\n 'updateFilterRule',\n 'removeFilterRule',\n 'clearFilters',\n 'setFiltersEnabled',\n 'toggleFilters',\n 'setHeaderRowCount',\n 'setFooterRowCount',\n 'setHeaderColumnCount',\n 'setFrozenRowCount',\n 'setFrozenColumnCount',\n 'hideRows',\n 'unhideRows',\n 'hideColumns',\n 'unhideColumns',\n 'unhideAll',\n 'getMerges',\n 'getMergeAt',\n 'mergeCells',\n 'unmergeCells',\n 'autofill',\n 'groupRowsBy',\n 'ungroupRows',\n 'setGroupSummary',\n 'setGroupCollapsed',\n 'toggleGroupCollapsed',\n 'getGroups',\n 'transposeRange',\n 'setCellNumberFormat',\n 'setColumnNumberFormat',\n 'exportToCsv',\n 'importFromCsv',\n 'copyToClipboardData',\n 'pasteClipboardData'\n] as const;\n\nexport type SpreadsheetTableActionName = (typeof SPREADSHEET_TABLE_ACTIONS)[number];\nexport type SpreadsheetTableActions = Pick<SpreadsheetController, SpreadsheetTableActionName>;\n\n/** The table operations of `controller`, bound so they can be passed around. */\nexport function bindSpreadsheetTableActions(controller: SpreadsheetController): SpreadsheetTableActions {\n const actions = {} as Record<string, unknown>;\n for (const name of SPREADSHEET_TABLE_ACTIONS) {\n actions[name] = (controller[name] as (...args: unknown[]) => unknown).bind(controller);\n }\n return actions as SpreadsheetTableActions;\n}\n","/**\n * `spreadsheet` import adapters for the import registry: CSV and TSV files\n * parsed with the RFC 4180 parser in `csv.ts`.\n *\n * They are not registered by default (the default registry only knows\n * `document` adapters). Registries are passed in explicitly so this entry\n * point does not pull in the document adapters (markdown, TipTap):\n *\n * registerSpreadsheetImportAdapters(defaultImportRegistry);\n * await importFileIntoSpreadsheet(controller, file, { registry: defaultImportRegistry });\n */\nimport type {\n ImportAdapter,\n ImportAdapterRegistry,\n ImportInput,\n ImportOutcome,\n} from '../import/registry';\nimport type { SpreadsheetController } from './controller';\nimport { parseCsv } from './csv';\n\n/** Result of every `spreadsheet` adapter. */\nexport interface SpreadsheetImport {\n /** Parsed records, one array of raw cell inputs per row. */\n rows: string[][];\n /** Field separator the file was parsed with. */\n delimiter: string;\n}\n\nexport type SpreadsheetImportAdapter = ImportAdapter<SpreadsheetImport>;\n\nfunction delimitedAdapter(\n id: string,\n label: string,\n delimiter: string,\n mimeTypes: string[],\n extensions: string[],\n): SpreadsheetImportAdapter {\n return {\n id,\n label,\n mimeTypes,\n extensions,\n target: 'spreadsheet',\n async import(_input, context) {\n return { rows: parseCsv(await context.readText(), { delimiter }), delimiter };\n },\n };\n}\n\nexport const csvImportAdapter = delimitedAdapter(\n 'csv',\n 'CSV',\n ',',\n ['text/csv', 'application/csv', 'text/comma-separated-values'],\n ['.csv'],\n);\n\nexport const tsvImportAdapter = delimitedAdapter(\n 'tsv',\n 'Tab-separated values',\n '\\t',\n ['text/tab-separated-values'],\n ['.tsv', '.tab'],\n);\n\nexport const SPREADSHEET_IMPORT_ADAPTERS: readonly SpreadsheetImportAdapter[] = [\n csvImportAdapter,\n tsvImportAdapter,\n];\n\n/** Registers the CSV and TSV adapters; returns a function that unregisters them. */\nexport function registerSpreadsheetImportAdapters(registry: ImportAdapterRegistry): () => void {\n const unregisters = SPREADSHEET_IMPORT_ADAPTERS.map((adapter) =>\n registry.register(adapter, { replace: true }),\n );\n return () => unregisters.forEach((unregister) => unregister());\n}\n\nexport interface ImportFileIntoSpreadsheetOptions {\n /** Registry to resolve the adapter from (e.g. `defaultImportRegistry`). */\n registry: ImportAdapterRegistry;\n /** Force an adapter instead of matching by file name / MIME type. */\n adapterId?: string;\n fileName?: string;\n mimeType?: string;\n /** Top-left cell to write to (0-based). Default A1. */\n startRow?: number;\n startCol?: number;\n}\n\n/**\n * Imports a CSV/TSV file (or any registered `spreadsheet` adapter that\n * returns `SpreadsheetImport`) into the controller as one undoable change.\n */\nexport async function importFileIntoSpreadsheet(\n controller: SpreadsheetController,\n input: ImportInput,\n options: ImportFileIntoSpreadsheetOptions,\n): Promise<ImportOutcome<SpreadsheetImport>> {\n const { registry, startRow, startCol, ...rest } = options;\n const outcome = await registry.importFile<SpreadsheetImport>(input, { ...rest, target: 'spreadsheet' });\n controller.importRows(outcome.result.rows, { startRow, startCol });\n return outcome;\n}\n"],"mappings":"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","names":["quote"]}
|