@ricsam/formula-engine 0.0.17 → 0.0.19
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/dist/cjs/core/api/api-builder.cjs +67 -0
- package/dist/cjs/core/api/api-builder.cjs.map +10 -0
- package/dist/cjs/core/api/api-helpers.cjs +191 -0
- package/dist/cjs/core/api/api-helpers.cjs.map +10 -0
- package/dist/cjs/core/api/api.cjs +65 -0
- package/dist/cjs/core/api/api.cjs.map +10 -0
- package/dist/cjs/core/api/cell-orm.cjs +80 -0
- package/dist/cjs/core/api/cell-orm.cjs.map +10 -0
- package/dist/cjs/core/api/table-orm.cjs +171 -0
- package/dist/cjs/core/api/table-orm.cjs.map +10 -0
- package/dist/cjs/core/autofill-utils.cjs +3 -5
- package/dist/cjs/core/autofill-utils.cjs.map +3 -3
- package/dist/cjs/core/commands/command-executor.cjs +140 -0
- package/dist/cjs/core/commands/command-executor.cjs.map +10 -0
- package/dist/cjs/core/commands/content-commands.cjs +574 -0
- package/dist/cjs/core/commands/content-commands.cjs.map +10 -0
- package/dist/cjs/core/commands/metadata-commands.cjs +150 -0
- package/dist/cjs/core/commands/metadata-commands.cjs.map +10 -0
- package/dist/cjs/core/commands/named-expression-commands.cjs +238 -0
- package/dist/cjs/core/commands/named-expression-commands.cjs.map +10 -0
- package/dist/cjs/core/commands/structure-commands.cjs +495 -0
- package/dist/cjs/core/commands/structure-commands.cjs.map +10 -0
- package/dist/cjs/core/commands/style-commands.cjs +219 -0
- package/dist/cjs/core/commands/style-commands.cjs.map +10 -0
- package/dist/cjs/core/commands/table-commands.cjs +226 -0
- package/dist/cjs/core/commands/table-commands.cjs.map +10 -0
- package/dist/cjs/core/commands/types.cjs +72 -0
- package/dist/cjs/core/commands/types.cjs.map +10 -0
- package/dist/cjs/core/engine.cjs +170 -297
- package/dist/cjs/core/engine.cjs.map +3 -3
- package/dist/cjs/core/managers/api-schema-manager.cjs +304 -0
- package/dist/cjs/core/managers/api-schema-manager.cjs.map +10 -0
- package/dist/cjs/core/managers/copy-manager.cjs +1 -2
- package/dist/cjs/core/managers/copy-manager.cjs.map +3 -3
- package/dist/cjs/core/types.cjs.map +2 -2
- package/dist/cjs/lib.cjs +13 -2
- package/dist/cjs/lib.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/mjs/core/api/api-builder.mjs +37 -0
- package/dist/mjs/core/api/api-builder.mjs.map +10 -0
- package/dist/mjs/core/api/api-helpers.mjs +161 -0
- package/dist/mjs/core/api/api-helpers.mjs.map +10 -0
- package/dist/mjs/core/api/api.mjs +35 -0
- package/dist/mjs/core/api/api.mjs.map +10 -0
- package/dist/mjs/core/api/cell-orm.mjs +49 -0
- package/dist/mjs/core/api/cell-orm.mjs.map +10 -0
- package/dist/mjs/core/api/table-orm.mjs +148 -0
- package/dist/mjs/core/api/table-orm.mjs.map +10 -0
- package/dist/mjs/core/autofill-utils.mjs +3 -5
- package/dist/mjs/core/autofill-utils.mjs.map +3 -3
- package/dist/mjs/core/commands/command-executor.mjs +109 -0
- package/dist/mjs/core/commands/command-executor.mjs.map +10 -0
- package/dist/mjs/core/commands/content-commands.mjs +544 -0
- package/dist/mjs/core/commands/content-commands.mjs.map +10 -0
- package/dist/mjs/core/commands/metadata-commands.mjs +120 -0
- package/dist/mjs/core/commands/metadata-commands.mjs.map +10 -0
- package/dist/mjs/core/commands/named-expression-commands.mjs +208 -0
- package/dist/mjs/core/commands/named-expression-commands.mjs.map +10 -0
- package/dist/mjs/core/commands/structure-commands.mjs +465 -0
- package/dist/mjs/core/commands/structure-commands.mjs.map +10 -0
- package/dist/mjs/core/commands/style-commands.mjs +189 -0
- package/dist/mjs/core/commands/style-commands.mjs.map +10 -0
- package/dist/mjs/core/commands/table-commands.mjs +196 -0
- package/dist/mjs/core/commands/table-commands.mjs.map +10 -0
- package/dist/mjs/core/commands/types.mjs +42 -0
- package/dist/mjs/core/commands/types.mjs.map +10 -0
- package/dist/mjs/core/engine.mjs +213 -297
- package/dist/mjs/core/engine.mjs.map +3 -3
- package/dist/mjs/core/managers/api-schema-manager.mjs +274 -0
- package/dist/mjs/core/managers/api-schema-manager.mjs.map +10 -0
- package/dist/mjs/core/managers/copy-manager.mjs +1 -2
- package/dist/mjs/core/managers/copy-manager.mjs.map +3 -3
- package/dist/mjs/core/types.mjs.map +2 -2
- package/dist/mjs/lib.mjs +13 -2
- package/dist/mjs/lib.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/types/core/api/api-builder.d.ts +16 -0
- package/dist/types/core/api/api-helpers.d.ts +37 -0
- package/dist/types/core/api/api.d.ts +83 -0
- package/dist/types/core/api/api.type-test.d.ts +1 -0
- package/dist/types/core/api/cell-orm.d.ts +29 -0
- package/dist/types/core/api/table-orm.d.ts +46 -0
- package/dist/types/core/autofill-utils.d.ts +2 -9
- package/dist/types/core/commands/command-executor.d.ts +83 -0
- package/dist/types/core/commands/content-commands.d.ts +142 -0
- package/dist/types/core/commands/metadata-commands.d.ts +55 -0
- package/dist/types/core/commands/named-expression-commands.d.ts +115 -0
- package/dist/types/core/commands/structure-commands.d.ts +132 -0
- package/dist/types/core/commands/style-commands.d.ts +76 -0
- package/dist/types/core/commands/table-commands.d.ts +104 -0
- package/dist/types/core/commands/types.d.ts +114 -0
- package/dist/types/core/engine.d.ts +130 -26
- package/dist/types/core/managers/api-schema-manager.d.ts +121 -0
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/lib.d.ts +8 -0
- package/package.json +1 -1
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/core/managers/copy-manager.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * CopyManager - Manages cell copy/paste operations\n */\n\nimport type {\n CellAddress,\n CopyCellsOptions,\n ConditionalStyle,\n DirectCellStyle,\n LocalCellAddress,\n RangeAddress,\n SerializedCellValue,\n SpreadsheetRange,\n} from \"../types.mjs\";\nimport type { WorkbookManager } from \"./workbook-manager.mjs\";\nimport type { EvaluationManager } from \"./evaluation-manager.mjs\";\nimport type { StyleManager } from \"./style-manager.mjs\";\nimport { parseFormula } from \"../../parser/parser.mjs\";\nimport { astToString } from \"../../parser/formatter.mjs\";\nimport { transformAST } from \"../ast-traverser.mjs\";\nimport type { ReferenceNode, RangeNode } from \"../../parser/ast.mjs\";\nimport { getCellReference, isCellInRange } from \"../utils.mjs\";\nimport { intersectRanges } from \"../utils/range-utils.mjs\";\nimport {\n updateReferencesForMovedCells,\n type MovedCellsInfo,\n} from \"../cell-mover.mjs\";\n\n/**\n * Snapshot of a cell's content, metadata, and styles\n */\ninterface CellSnapshot {\n address: CellAddress;\n content: SerializedCellValue | undefined;\n metadata: unknown | undefined;\n matchingCellStyles?: DirectCellStyle[];\n matchingConditionalStyles?: ConditionalStyle[];\n}\n\nexport class CopyManager {\n constructor(\n private workbookManager: WorkbookManager,\n private evaluationManager: EvaluationManager,\n private styleManager: StyleManager\n ) {}\n\n /**\n * Normalize the include option to an array of parts to copy\n */\n private normalizeInclude(\n include: CopyCellsOptions[\"include\"]\n ): (\"content\" | \"style\" | \"metadata\")[] {\n if (!include || include === \"all\") {\n return [\"content\", \"style\", \"metadata\"];\n }\n return include;\n }\n\n /**\n * Check if a specific part should be included in the copy operation\n */\n private shouldInclude(\n options: CopyCellsOptions,\n part: \"content\" | \"style\" | \"metadata\"\n ): boolean {\n const normalized = this.normalizeInclude(options.include);\n return normalized.includes(part);\n }\n\n /**\n * Paste cells from source to target\n * Delegates to cutCells for move operations or copyOnlyCells for copy operations\n */\n pasteCells(\n source: CellAddress[],\n target: CellAddress,\n options: CopyCellsOptions\n ): void {\n if (source.length === 0) {\n return;\n }\n\n if (options.cut === true) {\n return this.cutCells(source, target, options);\n } else {\n return this.copyOnlyCells(source, target, options);\n }\n }\n\n /**\n * Cut cells: Proper snapshot flow for move operations\n * 1. Snapshot source cells (with styles)\n * 2. Remove source cells and punch holes in style areas\n * 3. Update references in OTHER cells (not in moved set)\n * 4. Update formulas in snapshot and apply to target\n */\n private cutCells(\n source: CellAddress[],\n target: CellAddress,\n options: CopyCellsOptions\n ): void {\n const topLeft = this.findTopLeft(source);\n const rowOffset = target.rowIndex - topLeft.rowIndex;\n const colOffset = target.colIndex - topLeft.colIndex;\n\n // 1. Snapshot source cells (with styles)\n const snapshot = this.snapshotCellsWithStyles(source);\n\n // 2. Remove source cells (content) and punch holes in styles\n this.clearSourceCells(source);\n\n // Punch holes in style areas for each cut cell\n if (this.shouldInclude(options, \"style\")) {\n for (const cell of source) {\n const cellRange: RangeAddress = {\n workbookName: cell.workbookName,\n sheetName: cell.sheetName,\n range: {\n start: { col: cell.colIndex, row: cell.rowIndex },\n end: {\n col: { type: \"number\", value: cell.colIndex },\n row: { type: \"number\", value: cell.rowIndex },\n },\n },\n };\n this.styleManager.clearCellStylesInRange(cellRange);\n }\n }\n\n // 3. Update references in OTHER cells (not in moved set)\n const movedCellsSet = new Set(\n source.map(\n (c) => `${c.workbookName}:${c.sheetName}:${c.colIndex}:${c.rowIndex}`\n )\n );\n\n const movedCellsInfo: MovedCellsInfo = {\n cellsSet: movedCellsSet,\n workbookName: topLeft.workbookName,\n sheetName: topLeft.sheetName,\n rowOffset,\n colOffset,\n };\n\n this.workbookManager.updateFormulasExcluding(movedCellsSet, (formula) =>\n updateReferencesForMovedCells(formula, movedCellsInfo)\n );\n\n // 4. Update formulas in snapshot and apply to target\n for (let i = 0; i < snapshot.length; i++) {\n const snap = snapshot[i]!;\n const sourceCell = source[i]!;\n const targetCell: CellAddress = {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n colIndex: sourceCell.colIndex + colOffset,\n rowIndex: sourceCell.rowIndex + rowOffset,\n };\n\n // Apply content (with formula adjustment)\n if (this.shouldInclude(options, \"content\") && snap.content) {\n let targetContent = snap.content;\n\n if (typeof snap.content === \"string\" && snap.content.startsWith(\"=\")) {\n // Adjust formula references relative to new position\n targetContent = this.adjustFormulaReferences(\n snap.content,\n {\n colIndex: snap.address.colIndex,\n rowIndex: snap.address.rowIndex,\n },\n {\n colIndex: targetCell.colIndex,\n rowIndex: targetCell.rowIndex,\n }\n );\n }\n\n console.log(\"targetContent\", targetContent);\n\n // Use setCellContent to ensure proper cache invalidation and dependency tracking\n this.workbookManager.setCellContent(targetCell, targetContent);\n }\n\n // Apply metadata\n if (this.shouldInclude(options, \"metadata\")) {\n if (snap.metadata) {\n this.workbookManager.setCellMetadata(targetCell, {\n ...snap.metadata,\n });\n } else {\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n\n // Apply styles from snapshot to new location\n if (this.shouldInclude(options, \"style\")) {\n this.applyStylesFromSnapshot(snap, targetCell);\n }\n }\n }\n\n /**\n * Copy cells: Standard copy operation (not cut/move)\n * Snapshot → Copy with adjustment → Copy formatting\n */\n private copyOnlyCells(\n source: CellAddress[],\n target: CellAddress,\n options: CopyCellsOptions\n ): void {\n const topLeft = this.findTopLeft(source);\n const rowOffset = target.rowIndex - topLeft.rowIndex;\n const colOffset = target.colIndex - topLeft.colIndex;\n\n // SNAPSHOT source cells (handles overlapping ranges)\n const snapshot = this.snapshotCells(source);\n\n // Copy cell contents if requested (from snapshot, not live cells)\n if (this.shouldInclude(options, \"content\")) {\n for (let i = 0; i < source.length; i++) {\n const sourceCell = source[i]!;\n const cellSnapshot = snapshot[i]!;\n const targetCell: CellAddress = {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n colIndex: sourceCell.colIndex + colOffset,\n rowIndex: sourceCell.rowIndex + rowOffset,\n };\n\n this.copyCellContentFromSnapshot(\n cellSnapshot,\n targetCell,\n topLeft,\n options\n );\n }\n }\n\n // Copy formatting if requested\n if (this.shouldInclude(options, \"style\")) {\n this.copyFormatting(source, topLeft, target, rowOffset, colOffset);\n }\n }\n\n /**\n * Find the top-left cell (minimum row/col indices)\n */\n private findTopLeft(cells: CellAddress[]): CellAddress {\n let minRow = Infinity;\n let minCol = Infinity;\n let topLeftCell = cells[0]!;\n\n for (const cell of cells) {\n if (\n cell.rowIndex < minRow ||\n (cell.rowIndex === minRow && cell.colIndex < minCol)\n ) {\n minRow = cell.rowIndex;\n minCol = cell.colIndex;\n topLeftCell = cell;\n }\n }\n\n return topLeftCell;\n }\n\n /**\n * Create a snapshot of cells' content and metadata\n * This prevents issues with overlapping ranges where source and target overlap\n * Used for copy operations (not cut)\n */\n private snapshotCells(cells: CellAddress[]): CellSnapshot[] {\n return cells.map((cell) => {\n const sheet = this.workbookManager.getSheet({\n workbookName: cell.workbookName,\n sheetName: cell.sheetName,\n });\n\n const key = `${String.fromCharCode(65 + cell.colIndex)}${\n cell.rowIndex + 1\n }`;\n const content = sheet?.content.get(key);\n const metadata = this.workbookManager.getCellMetadata(cell);\n\n return {\n address: cell,\n content,\n metadata,\n };\n });\n }\n\n /**\n * Create a snapshot of cells with content, metadata, AND styles\n * Used for cut operations to preserve all cell information\n */\n private snapshotCellsWithStyles(cells: CellAddress[]): CellSnapshot[] {\n const allCellStyles = this.styleManager.getAllCellStyles();\n const allConditionalStyles = this.styleManager.getAllConditionalStyles();\n\n return cells.map((cell) => {\n const sheet = this.workbookManager.getSheet({\n workbookName: cell.workbookName,\n sheetName: cell.sheetName,\n });\n\n const key = getCellReference(cell);\n const content = sheet?.content.get(key);\n const metadata = this.workbookManager.getCellMetadata(cell);\n\n // Find all styles that apply to this cell\n const matchingCellStyles = allCellStyles.filter((style) =>\n style.areas.some(\n (area) =>\n area.workbookName === cell.workbookName &&\n area.sheetName === cell.sheetName &&\n isCellInRange(cell, area.range)\n )\n );\n\n const matchingConditionalStyles = allConditionalStyles.filter((style) =>\n style.areas.some(\n (area) =>\n area.workbookName === cell.workbookName &&\n area.sheetName === cell.sheetName &&\n isCellInRange(cell, area.range)\n )\n );\n\n return {\n address: cell,\n content,\n metadata,\n matchingCellStyles,\n matchingConditionalStyles,\n };\n });\n }\n\n /**\n * Apply styles from a snapshot to a target cell\n * Creates new style areas at the target location\n */\n private applyStylesFromSnapshot(\n snapshot: CellSnapshot,\n targetCell: CellAddress\n ): void {\n // Apply cell styles\n if (snapshot.matchingCellStyles) {\n for (const style of snapshot.matchingCellStyles) {\n const newStyle: DirectCellStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: { col: targetCell.colIndex, row: targetCell.rowIndex },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n style: style.style,\n };\n this.styleManager.addCellStyle(newStyle);\n }\n }\n\n // Apply conditional styles\n if (snapshot.matchingConditionalStyles) {\n for (const style of snapshot.matchingConditionalStyles) {\n const newStyle: ConditionalStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: { col: targetCell.colIndex, row: targetCell.rowIndex },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n condition: style.condition,\n };\n this.styleManager.addConditionalStyle(newStyle);\n }\n }\n }\n\n /**\n * Copy content from a cell snapshot to a target cell\n */\n private copyCellContentFromSnapshot(\n snapshot: CellSnapshot,\n targetCell: CellAddress,\n sourceTopLeft: CellAddress,\n options: CopyCellsOptions\n ): void {\n if (!snapshot.content) {\n // Source cell was empty\n return;\n }\n\n let targetContent: SerializedCellValue;\n const copyType = options.type ?? \"formula\";\n\n if (copyType === \"value\") {\n // Copy evaluated value\n const evalResult = this.evaluationManager.getCellEvaluationResult(\n snapshot.address\n );\n\n if (!evalResult || evalResult.type !== \"value\") {\n // If evaluation failed or is not a value, copy as-is\n targetContent = snapshot.content;\n } else {\n // Convert to literal value\n const result = evalResult.result;\n if (result.type === \"number\") {\n targetContent = result.value;\n } else if (result.type === \"string\") {\n targetContent = result.value;\n } else if (result.type === \"boolean\") {\n targetContent = result.value;\n } else {\n // Error or other type, copy as-is\n targetContent = snapshot.content;\n }\n }\n } else {\n // Copy formula\n if (\n typeof snapshot.content === \"string\" &&\n snapshot.content.startsWith(\"=\")\n ) {\n // Adjust formula references\n targetContent = this.adjustFormulaReferences(\n snapshot.content,\n {\n colIndex: snapshot.address.colIndex,\n rowIndex: snapshot.address.rowIndex,\n },\n {\n colIndex: targetCell.colIndex,\n rowIndex: targetCell.rowIndex,\n }\n );\n } else {\n // Not a formula, copy as-is\n targetContent = snapshot.content;\n }\n }\n\n // Set target cell content\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.set(targetKey, targetContent);\n }\n\n // Copy metadata if requested\n if (this.shouldInclude(options, \"metadata\")) {\n if (snapshot.metadata) {\n this.workbookManager.setCellMetadata(targetCell, {\n ...snapshot.metadata,\n });\n } else {\n // Clear target metadata if source has none\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n }\n\n /**\n * Update all formula references when cells are cut (moved)\n */\n /**\n * Copy content from one cell to another\n */\n private copyCellContent(\n sourceCell: CellAddress,\n targetCell: CellAddress,\n sourceTopLeft: CellAddress,\n options: CopyCellsOptions\n ): void {\n const sheet = this.workbookManager.getSheet({\n workbookName: sourceCell.workbookName,\n sheetName: sourceCell.sheetName,\n });\n\n if (!sheet) {\n return;\n }\n\n const key = `${String.fromCharCode(65 + sourceCell.colIndex)}${\n sourceCell.rowIndex + 1\n }`;\n const cellContent = sheet.content.get(key);\n\n if (!cellContent) {\n // Source cell is empty\n return;\n }\n\n let targetContent: SerializedCellValue;\n const copyType = options.type ?? \"formula\";\n\n if (copyType === \"value\") {\n // Copy evaluated value\n const evalResult =\n this.evaluationManager.getCellEvaluationResult(sourceCell);\n\n if (!evalResult || evalResult.type !== \"value\") {\n // If evaluation failed or is not a value, copy as-is\n targetContent = cellContent;\n } else {\n // Convert to literal value\n const result = evalResult.result;\n if (result.type === \"number\") {\n targetContent = result.value;\n } else if (result.type === \"string\") {\n targetContent = result.value;\n } else if (result.type === \"boolean\") {\n targetContent = result.value;\n } else {\n // Error or other type, copy as-is\n targetContent = cellContent;\n }\n }\n } else {\n // Copy formula\n if (typeof cellContent === \"string\" && cellContent.startsWith(\"=\")) {\n // Adjust formula references\n targetContent = this.adjustFormulaReferences(\n cellContent,\n {\n colIndex: sourceCell.colIndex,\n rowIndex: sourceCell.rowIndex,\n },\n {\n colIndex: targetCell.colIndex,\n rowIndex: targetCell.rowIndex,\n }\n );\n } else {\n // Not a formula, copy as-is\n targetContent = cellContent;\n }\n }\n\n // Set target cell content (using the engine's method through workbook manager)\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.set(targetKey, targetContent);\n }\n\n // Copy metadata if requested\n if (this.shouldInclude(options, \"metadata\")) {\n const sourceMetadata = this.workbookManager.getCellMetadata(sourceCell);\n if (sourceMetadata) {\n this.workbookManager.setCellMetadata(targetCell, { ...sourceMetadata });\n } else {\n // Clear target metadata if source has none\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n }\n\n /**\n * Adjust formula references when copying\n * Based on autofill-utils.ts adjustFormulaReferences\n */\n private adjustFormulaReferences(\n formula: string,\n sourceAddress: LocalCellAddress,\n targetAddress: LocalCellAddress\n ): string {\n try {\n const ast = parseFormula(formula.slice(1)); // Remove the \"=\" sign\n\n const rowDelta = targetAddress.rowIndex - sourceAddress.rowIndex;\n const colDelta = targetAddress.colIndex - sourceAddress.colIndex;\n\n const adjustedAst = transformAST(ast, (node) => {\n if (node.type === \"reference\") {\n const refNode = node as ReferenceNode;\n return {\n ...refNode,\n address: {\n colIndex: refNode.isAbsolute.col\n ? refNode.address.colIndex\n : refNode.address.colIndex + colDelta,\n rowIndex: refNode.isAbsolute.row\n ? refNode.address.rowIndex\n : refNode.address.rowIndex + rowDelta,\n },\n };\n } else if (node.type === \"range\") {\n const rangeNode = node as RangeNode;\n return {\n ...rangeNode,\n range: {\n start: {\n col: rangeNode.isAbsolute.start.col\n ? rangeNode.range.start.col\n : rangeNode.range.start.col + colDelta,\n row: rangeNode.isAbsolute.start.row\n ? rangeNode.range.start.row\n : rangeNode.range.start.row + rowDelta,\n },\n end: {\n col:\n rangeNode.range.end.col.type === \"number\"\n ? rangeNode.isAbsolute.end.col\n ? rangeNode.range.end.col\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.col.value + colDelta,\n }\n : rangeNode.range.end.col,\n row:\n rangeNode.range.end.row.type === \"number\"\n ? rangeNode.isAbsolute.end.row\n ? rangeNode.range.end.row\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.row.value + rowDelta,\n }\n : rangeNode.range.end.row,\n },\n },\n };\n }\n return node;\n });\n\n return `=${astToString(adjustedAst)}`;\n } catch (error) {\n // If parsing fails, return the original formula\n console.warn(\"Failed to adjust formula references:\", error);\n return formula;\n }\n }\n\n /**\n * Copy formatting (cellStyles and conditionalStyles) from source to target\n * Clears existing cell styles in target range first (Excel behavior)\n */\n private copyFormatting(\n sourceCells: CellAddress[],\n sourceTopLeft: CellAddress,\n target: CellAddress,\n rowOffset: number,\n colOffset: number\n ): void {\n // STEP 1: Clear existing cell styles in target range (Excel-like replacement)\n const sourceRange = this.getBoundingBox(sourceCells);\n const targetRange: RangeAddress = {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(sourceRange, rowOffset, colOffset),\n };\n\n this.styleManager.clearCellStylesInRange(targetRange);\n\n // Get all styles for the source workbook\n const allConditionalStyles = this.styleManager.getAllConditionalStyles();\n const allCellStyles = this.styleManager.getAllCellStyles();\n\n // STEP 2: Copy conditional styles\n for (const style of allConditionalStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceTopLeft.workbookName &&\n area.sheetName === sourceTopLeft.sheetName\n ) {\n // Calculate intersection of style range with source bounding box\n const intersection = intersectRanges(area.range, sourceRange);\n if (intersection) {\n // Copy only the intersection, offset to target\n const newStyle: ConditionalStyle = {\n areas: [\n {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(intersection, rowOffset, colOffset),\n },\n ],\n condition: style.condition,\n };\n this.styleManager.addConditionalStyle(newStyle);\n }\n }\n }\n }\n\n // STEP 3: Copy cell styles\n for (const style of allCellStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceTopLeft.workbookName &&\n area.sheetName === sourceTopLeft.sheetName\n ) {\n // Calculate intersection of style range with source bounding box\n const intersection = intersectRanges(area.range, sourceRange);\n if (intersection) {\n // Copy only the intersection, offset to target\n const newStyle: DirectCellStyle = {\n areas: [\n {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(intersection, rowOffset, colOffset),\n },\n ],\n style: style.style,\n };\n this.styleManager.addCellStyle(newStyle);\n }\n }\n }\n }\n }\n\n /**\n * Get bounding box for a set of cells\n */\n private getBoundingBox(cells: CellAddress[]): SpreadsheetRange {\n let minRow = Infinity;\n let maxRow = -Infinity;\n let minCol = Infinity;\n let maxCol = -Infinity;\n\n for (const cell of cells) {\n minRow = Math.min(minRow, cell.rowIndex);\n maxRow = Math.max(maxRow, cell.rowIndex);\n minCol = Math.min(minCol, cell.colIndex);\n maxCol = Math.max(maxCol, cell.colIndex);\n }\n\n return {\n start: { col: minCol, row: minRow },\n end: {\n col: { type: \"number\", value: maxCol },\n row: { type: \"number\", value: maxRow },\n },\n };\n }\n\n /**\n * Adjust a range by row and column offsets\n */\n private adjustRange(\n range: SpreadsheetRange,\n rowOffset: number,\n colOffset: number\n ): SpreadsheetRange {\n return {\n start: {\n col: range.start.col + colOffset,\n row: range.start.row + rowOffset,\n },\n end: {\n col:\n range.end.col.type === \"number\"\n ? { type: \"number\", value: range.end.col.value + colOffset }\n : range.end.col,\n row:\n range.end.row.type === \"number\"\n ? { type: \"number\", value: range.end.row.value + rowOffset }\n : range.end.row,\n },\n };\n }\n\n /**\n * Clear source cells (for cut operation)\n */\n private clearSourceCells(cells: CellAddress[]): void {\n for (const cell of cells) {\n // Use setCellContent with empty string to properly clear the cell\n // This ensures indexes are updated and caches are properly managed\n this.workbookManager.setCellContent(cell, \"\");\n }\n }\n\n /**\n * Fill one or more areas with a seed range's content/style\n * Uses column-first strategy: fills down, then replicates right\n * Formulas are adjusted based on each target cell's offset from the seed\n */\n fillAreas(\n seedRange: RangeAddress,\n targetRanges: RangeAddress[],\n options: CopyCellsOptions\n ): void {\n for (const targetRange of targetRanges) {\n this.fillRangeWithSeed(seedRange, targetRange, {\n copyContent: this.shouldInclude(options, \"content\"),\n copyStyles: this.shouldInclude(options, \"style\"),\n contentType: options.type ?? \"formula\",\n adjustFormulas: true,\n });\n }\n\n // Clear seed range if cut operation\n if (options.cut) {\n const seedCells = this.expandRangeToCells(seedRange);\n this.clearSourceCells(seedCells);\n }\n }\n\n /**\n * Fill a target range with a seed range using column-first strategy\n * Step 0: Clear existing cell styles in target (Excel behavior)\n * Step 1: Fill down - extend seed pattern vertically to match target height\n * Step 2: Replicate right - copy filled columns horizontally\n */\n private fillRangeWithSeed(\n seedRange: RangeAddress,\n targetRange: RangeAddress,\n options: {\n copyContent: boolean;\n copyStyles: boolean;\n contentType: \"value\" | \"formula\";\n adjustFormulas: boolean;\n }\n ): void {\n // Step 0: Clear existing cell styles in target range (Excel-like replacement)\n if (options.copyStyles) {\n this.styleManager.clearCellStylesInRange(targetRange);\n }\n\n const seedCells = this.expandRangeToCells(seedRange);\n const seedWidth = this.getRangeWidth(seedRange);\n const seedHeight = this.getRangeHeight(seedRange);\n const targetWidth = this.getRangeWidth(targetRange);\n const targetHeight = this.getRangeHeight(targetRange);\n\n // Step 1: Fill down - replicate seed pattern vertically\n const filledColumns: Map<\n string,\n { cell: CellAddress; content: SerializedCellValue }\n > = new Map();\n\n for (let col = 0; col < seedWidth; col++) {\n for (let row = 0; row < targetHeight; row++) {\n const seedRow = row % seedHeight;\n const seedCell = seedCells.find(\n (c) =>\n c.colIndex === seedRange.range.start.col + col &&\n c.rowIndex === seedRange.range.start.row + seedRow\n );\n\n if (seedCell) {\n const targetCell: CellAddress = {\n workbookName: targetRange.workbookName,\n sheetName: targetRange.sheetName,\n colIndex: targetRange.range.start.col + col,\n rowIndex: targetRange.range.start.row + row,\n };\n\n const rowDelta = targetCell.rowIndex - seedCell.rowIndex;\n const colDelta = targetCell.colIndex - seedCell.colIndex;\n\n if (options.copyContent) {\n this.copyCellContentWithOffset(\n seedCell,\n targetCell,\n rowDelta,\n colDelta,\n {\n type: options.contentType,\n cut: false,\n include: [\"content\"],\n }\n );\n }\n\n if (options.copyStyles) {\n this.copyCellFormatting(seedCell, targetCell);\n }\n\n // Store filled column for horizontal replication\n const key = `${targetCell.colIndex}-${targetCell.rowIndex}`;\n const sheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n const cellKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n const content = sheet?.content.get(cellKey) || \"\";\n filledColumns.set(key, { cell: targetCell, content });\n }\n }\n }\n\n // Step 2: Replicate right - copy filled columns horizontally\n if (targetWidth > seedWidth) {\n for (let col = seedWidth; col < targetWidth; col++) {\n const sourceCol = col % seedWidth;\n\n for (let row = 0; row < targetHeight; row++) {\n const sourceCell: CellAddress = {\n workbookName: targetRange.workbookName,\n sheetName: targetRange.sheetName,\n colIndex: targetRange.range.start.col + sourceCol,\n rowIndex: targetRange.range.start.row + row,\n };\n\n const targetCell: CellAddress = {\n workbookName: targetRange.workbookName,\n sheetName: targetRange.sheetName,\n colIndex: targetRange.range.start.col + col,\n rowIndex: targetRange.range.start.row + row,\n };\n\n const colDelta = targetCell.colIndex - sourceCell.colIndex;\n\n if (options.copyContent) {\n this.copyCellContentWithOffset(\n sourceCell,\n targetCell,\n 0,\n colDelta,\n {\n type: options.contentType,\n cut: false,\n include: [\"content\"],\n }\n );\n }\n\n if (options.copyStyles) {\n this.copyCellFormatting(sourceCell, targetCell);\n }\n }\n }\n }\n }\n\n /**\n * Get the width of a range (number of columns)\n */\n private getRangeWidth(range: RangeAddress): number {\n if (range.range.end.col.type === \"infinity\") {\n return 100; // Default for infinite\n }\n return range.range.end.col.value - range.range.start.col + 1;\n }\n\n /**\n * Get the height of a range (number of rows)\n */\n private getRangeHeight(range: RangeAddress): number {\n if (range.range.end.row.type === \"infinity\") {\n return 100; // Default for infinite\n }\n return range.range.end.row.value - range.range.start.row + 1;\n }\n\n /**\n * Expand a RangeAddress into an array of CellAddress\n * Handles finite ranges, row-bounded, and column-bounded ranges\n */\n public expandRangeToCells(rangeAddress: RangeAddress): CellAddress[] {\n const { workbookName, sheetName, range } = rangeAddress;\n const cells: CellAddress[] = [];\n\n const startCol = range.start.col;\n const startRow = range.start.row;\n\n // Determine end column\n let endCol: number;\n if (range.end.col.type === \"infinity\") {\n // Limit infinite column ranges to a reasonable size (e.g., 100 columns)\n endCol = startCol + 99;\n } else {\n endCol = range.end.col.value;\n }\n\n // Determine end row\n let endRow: number;\n if (range.end.row.type === \"infinity\") {\n // Limit infinite row ranges to a reasonable size (e.g., 100 rows)\n endRow = startRow + 99;\n } else {\n endRow = range.end.row.value;\n }\n\n // Generate all cells in the range\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n cells.push({\n workbookName,\n sheetName,\n colIndex: col,\n rowIndex: row,\n });\n }\n }\n\n return cells;\n }\n\n /**\n * Copy cell content with explicit row/column offset for fill operations\n */\n private copyCellContentWithOffset(\n sourceCell: CellAddress,\n targetCell: CellAddress,\n rowDelta: number,\n colDelta: number,\n options: CopyCellsOptions\n ): void {\n const sheet = this.workbookManager.getSheet({\n workbookName: sourceCell.workbookName,\n sheetName: sourceCell.sheetName,\n });\n\n if (!sheet) {\n return;\n }\n\n const key = `${String.fromCharCode(65 + sourceCell.colIndex)}${\n sourceCell.rowIndex + 1\n }`;\n const cellContent = sheet.content.get(key);\n\n if (!cellContent) {\n // Source cell is empty - clear target\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.delete(targetKey);\n }\n return;\n }\n\n let targetContent: SerializedCellValue;\n const copyType = options.type ?? \"formula\";\n\n if (copyType === \"value\") {\n // Copy evaluated value\n const evalResult =\n this.evaluationManager.getCellEvaluationResult(sourceCell);\n\n if (!evalResult || evalResult.type !== \"value\") {\n // If evaluation failed or is not a value, copy as-is\n targetContent = cellContent;\n } else {\n // Convert to literal value\n const result = evalResult.result;\n if (result.type === \"number\") {\n targetContent = result.value;\n } else if (result.type === \"string\") {\n targetContent = result.value;\n } else if (result.type === \"boolean\") {\n targetContent = result.value;\n } else {\n // Error or other type, copy as-is\n targetContent = cellContent;\n }\n }\n } else {\n // Copy formula with offset adjustment\n if (typeof cellContent === \"string\" && cellContent.startsWith(\"=\")) {\n // Adjust formula references based on offset\n targetContent = this.adjustFormulaWithOffset(\n cellContent,\n rowDelta,\n colDelta\n );\n } else {\n // Not a formula, copy as-is\n targetContent = cellContent;\n }\n }\n\n // Set target cell content\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.set(targetKey, targetContent);\n }\n\n // Copy metadata if requested\n if (this.shouldInclude(options, \"metadata\")) {\n const sourceMetadata = this.workbookManager.getCellMetadata(sourceCell);\n if (sourceMetadata) {\n this.workbookManager.setCellMetadata(targetCell, { ...sourceMetadata });\n } else {\n // Clear target metadata if source has none\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n }\n\n /**\n * Adjust formula references by a specific row/column offset\n */\n private adjustFormulaWithOffset(\n formula: string,\n rowDelta: number,\n colDelta: number\n ): string {\n try {\n const ast = parseFormula(formula.slice(1)); // Remove the \"=\" sign\n\n const adjustedAst = transformAST(ast, (node) => {\n if (node.type === \"reference\") {\n const refNode = node as ReferenceNode;\n return {\n ...refNode,\n address: {\n colIndex: refNode.isAbsolute.col\n ? refNode.address.colIndex\n : refNode.address.colIndex + colDelta,\n rowIndex: refNode.isAbsolute.row\n ? refNode.address.rowIndex\n : refNode.address.rowIndex + rowDelta,\n },\n };\n } else if (node.type === \"range\") {\n const rangeNode = node as RangeNode;\n return {\n ...rangeNode,\n range: {\n start: {\n col: rangeNode.isAbsolute.start.col\n ? rangeNode.range.start.col\n : rangeNode.range.start.col + colDelta,\n row: rangeNode.isAbsolute.start.row\n ? rangeNode.range.start.row\n : rangeNode.range.start.row + rowDelta,\n },\n end: {\n col:\n rangeNode.range.end.col.type === \"number\"\n ? rangeNode.isAbsolute.end.col\n ? rangeNode.range.end.col\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.col.value + colDelta,\n }\n : rangeNode.range.end.col,\n row:\n rangeNode.range.end.row.type === \"number\"\n ? rangeNode.isAbsolute.end.row\n ? rangeNode.range.end.row\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.row.value + rowDelta,\n }\n : rangeNode.range.end.row,\n },\n },\n };\n }\n return node;\n });\n\n return `=${astToString(adjustedAst)}`;\n } catch (error) {\n // If parsing fails, return the original formula\n console.warn(\"Failed to adjust formula with offset:\", error);\n return formula;\n }\n }\n\n /**\n * Copy formatting from one cell to another\n * Clears existing cell styles at target (Excel behavior) before copying new ones\n */\n private copyCellFormatting(\n sourceCell: CellAddress,\n targetCell: CellAddress\n ): void {\n // STEP 1: Clear existing cell styles at target cell (Excel-like replacement)\n const targetCellRange: RangeAddress = {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: { col: targetCell.colIndex, row: targetCell.rowIndex },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n };\n\n this.styleManager.clearCellStylesInRange(targetCellRange);\n\n // Get all styles that intersect with the source cell\n const allConditionalStyles = this.styleManager.getAllConditionalStyles();\n const allCellStyles = this.styleManager.getAllCellStyles();\n\n const sourceCellRange: SpreadsheetRange = {\n start: { col: sourceCell.colIndex, row: sourceCell.rowIndex },\n end: {\n col: { type: \"number\", value: sourceCell.colIndex },\n row: { type: \"number\", value: sourceCell.rowIndex },\n },\n };\n\n // STEP 2: Copy conditional styles that apply to source cell\n for (const style of allConditionalStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceCell.workbookName &&\n area.sheetName === sourceCell.sheetName\n ) {\n const intersection = intersectRanges(area.range, sourceCellRange);\n if (intersection) {\n // Apply style to target cell\n const newStyle: ConditionalStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: {\n col: targetCell.colIndex,\n row: targetCell.rowIndex,\n },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n condition: style.condition,\n };\n this.styleManager.addConditionalStyle(newStyle);\n }\n }\n }\n }\n\n // STEP 3: Copy cell styles that apply to source cell\n for (const style of allCellStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceCell.workbookName &&\n area.sheetName === sourceCell.sheetName\n ) {\n const intersection = intersectRanges(area.range, sourceCellRange);\n if (intersection) {\n // Apply style to target cell\n const newStyle: DirectCellStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: {\n col: targetCell.colIndex,\n row: targetCell.rowIndex,\n },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n style: style.style,\n };\n this.styleManager.addCellStyle(newStyle);\n }\n }\n }\n }\n }\n}\n"
|
|
5
|
+
"/**\n * CopyManager - Manages cell copy/paste operations\n */\n\nimport type {\n CellAddress,\n CopyCellsOptions,\n ConditionalStyle,\n DirectCellStyle,\n LocalCellAddress,\n RangeAddress,\n SerializedCellValue,\n SpreadsheetRange,\n} from \"../types.mjs\";\nimport type { WorkbookManager } from \"./workbook-manager.mjs\";\nimport type { EvaluationManager } from \"./evaluation-manager.mjs\";\nimport type { StyleManager } from \"./style-manager.mjs\";\nimport { parseFormula } from \"../../parser/parser.mjs\";\nimport { astToString } from \"../../parser/formatter.mjs\";\nimport { transformAST } from \"../ast-traverser.mjs\";\nimport type { ReferenceNode, RangeNode } from \"../../parser/ast.mjs\";\nimport { getCellReference, isCellInRange } from \"../utils.mjs\";\nimport { intersectRanges } from \"../utils/range-utils.mjs\";\nimport {\n updateReferencesForMovedCells,\n type MovedCellsInfo,\n} from \"../cell-mover.mjs\";\n\n/**\n * Snapshot of a cell's content, metadata, and styles\n */\ninterface CellSnapshot {\n address: CellAddress;\n content: SerializedCellValue | undefined;\n metadata: unknown | undefined;\n matchingCellStyles?: DirectCellStyle[];\n matchingConditionalStyles?: ConditionalStyle[];\n}\n\nexport class CopyManager {\n constructor(\n private workbookManager: WorkbookManager,\n private evaluationManager: EvaluationManager,\n private styleManager: StyleManager\n ) {}\n\n /**\n * Normalize the include option to an array of parts to copy\n */\n private normalizeInclude(\n include: CopyCellsOptions[\"include\"]\n ): (\"content\" | \"style\" | \"metadata\")[] {\n if (!include || include === \"all\") {\n return [\"content\", \"style\", \"metadata\"];\n }\n return include;\n }\n\n /**\n * Check if a specific part should be included in the copy operation\n */\n private shouldInclude(\n options: CopyCellsOptions,\n part: \"content\" | \"style\" | \"metadata\"\n ): boolean {\n const normalized = this.normalizeInclude(options.include);\n return normalized.includes(part);\n }\n\n /**\n * Paste cells from source to target\n * Delegates to cutCells for move operations or copyOnlyCells for copy operations\n */\n pasteCells(\n source: CellAddress[],\n target: CellAddress,\n options: CopyCellsOptions\n ): void {\n if (source.length === 0) {\n return;\n }\n\n if (options.cut === true) {\n return this.cutCells(source, target, options);\n } else {\n return this.copyOnlyCells(source, target, options);\n }\n }\n\n /**\n * Cut cells: Proper snapshot flow for move operations\n * 1. Snapshot source cells (with styles)\n * 2. Remove source cells and punch holes in style areas\n * 3. Update references in OTHER cells (not in moved set)\n * 4. Update formulas in snapshot and apply to target\n */\n private cutCells(\n source: CellAddress[],\n target: CellAddress,\n options: CopyCellsOptions\n ): void {\n const topLeft = this.findTopLeft(source);\n const rowOffset = target.rowIndex - topLeft.rowIndex;\n const colOffset = target.colIndex - topLeft.colIndex;\n\n // 1. Snapshot source cells (with styles)\n const snapshot = this.snapshotCellsWithStyles(source);\n\n // 2. Remove source cells (content) and punch holes in styles\n this.clearSourceCells(source);\n\n // Punch holes in style areas for each cut cell\n if (this.shouldInclude(options, \"style\")) {\n for (const cell of source) {\n const cellRange: RangeAddress = {\n workbookName: cell.workbookName,\n sheetName: cell.sheetName,\n range: {\n start: { col: cell.colIndex, row: cell.rowIndex },\n end: {\n col: { type: \"number\", value: cell.colIndex },\n row: { type: \"number\", value: cell.rowIndex },\n },\n },\n };\n this.styleManager.clearCellStylesInRange(cellRange);\n }\n }\n\n // 3. Update references in OTHER cells (not in moved set)\n const movedCellsSet = new Set(\n source.map(\n (c) => `${c.workbookName}:${c.sheetName}:${c.colIndex}:${c.rowIndex}`\n )\n );\n\n const movedCellsInfo: MovedCellsInfo = {\n cellsSet: movedCellsSet,\n workbookName: topLeft.workbookName,\n sheetName: topLeft.sheetName,\n rowOffset,\n colOffset,\n };\n\n this.workbookManager.updateFormulasExcluding(movedCellsSet, (formula) =>\n updateReferencesForMovedCells(formula, movedCellsInfo)\n );\n\n // 4. Update formulas in snapshot and apply to target\n for (let i = 0; i < snapshot.length; i++) {\n const snap = snapshot[i]!;\n const sourceCell = source[i]!;\n const targetCell: CellAddress = {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n colIndex: sourceCell.colIndex + colOffset,\n rowIndex: sourceCell.rowIndex + rowOffset,\n };\n\n // Apply content (with formula adjustment)\n if (this.shouldInclude(options, \"content\") && snap.content) {\n let targetContent = snap.content;\n\n if (typeof snap.content === \"string\" && snap.content.startsWith(\"=\")) {\n // Adjust formula references relative to new position\n targetContent = this.adjustFormulaReferences(\n snap.content,\n {\n colIndex: snap.address.colIndex,\n rowIndex: snap.address.rowIndex,\n },\n {\n colIndex: targetCell.colIndex,\n rowIndex: targetCell.rowIndex,\n }\n );\n }\n\n // Use setCellContent to ensure proper cache invalidation and dependency tracking\n this.workbookManager.setCellContent(targetCell, targetContent);\n }\n\n // Apply metadata\n if (this.shouldInclude(options, \"metadata\")) {\n if (snap.metadata) {\n this.workbookManager.setCellMetadata(targetCell, {\n ...snap.metadata,\n });\n } else {\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n\n // Apply styles from snapshot to new location\n if (this.shouldInclude(options, \"style\")) {\n this.applyStylesFromSnapshot(snap, targetCell);\n }\n }\n }\n\n /**\n * Copy cells: Standard copy operation (not cut/move)\n * Snapshot → Copy with adjustment → Copy formatting\n */\n private copyOnlyCells(\n source: CellAddress[],\n target: CellAddress,\n options: CopyCellsOptions\n ): void {\n const topLeft = this.findTopLeft(source);\n const rowOffset = target.rowIndex - topLeft.rowIndex;\n const colOffset = target.colIndex - topLeft.colIndex;\n\n // SNAPSHOT source cells (handles overlapping ranges)\n const snapshot = this.snapshotCells(source);\n\n // Copy cell contents if requested (from snapshot, not live cells)\n if (this.shouldInclude(options, \"content\")) {\n for (let i = 0; i < source.length; i++) {\n const sourceCell = source[i]!;\n const cellSnapshot = snapshot[i]!;\n const targetCell: CellAddress = {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n colIndex: sourceCell.colIndex + colOffset,\n rowIndex: sourceCell.rowIndex + rowOffset,\n };\n\n this.copyCellContentFromSnapshot(\n cellSnapshot,\n targetCell,\n topLeft,\n options\n );\n }\n }\n\n // Copy formatting if requested\n if (this.shouldInclude(options, \"style\")) {\n this.copyFormatting(source, topLeft, target, rowOffset, colOffset);\n }\n }\n\n /**\n * Find the top-left cell (minimum row/col indices)\n */\n private findTopLeft(cells: CellAddress[]): CellAddress {\n let minRow = Infinity;\n let minCol = Infinity;\n let topLeftCell = cells[0]!;\n\n for (const cell of cells) {\n if (\n cell.rowIndex < minRow ||\n (cell.rowIndex === minRow && cell.colIndex < minCol)\n ) {\n minRow = cell.rowIndex;\n minCol = cell.colIndex;\n topLeftCell = cell;\n }\n }\n\n return topLeftCell;\n }\n\n /**\n * Create a snapshot of cells' content and metadata\n * This prevents issues with overlapping ranges where source and target overlap\n * Used for copy operations (not cut)\n */\n private snapshotCells(cells: CellAddress[]): CellSnapshot[] {\n return cells.map((cell) => {\n const sheet = this.workbookManager.getSheet({\n workbookName: cell.workbookName,\n sheetName: cell.sheetName,\n });\n\n const key = `${String.fromCharCode(65 + cell.colIndex)}${\n cell.rowIndex + 1\n }`;\n const content = sheet?.content.get(key);\n const metadata = this.workbookManager.getCellMetadata(cell);\n\n return {\n address: cell,\n content,\n metadata,\n };\n });\n }\n\n /**\n * Create a snapshot of cells with content, metadata, AND styles\n * Used for cut operations to preserve all cell information\n */\n private snapshotCellsWithStyles(cells: CellAddress[]): CellSnapshot[] {\n const allCellStyles = this.styleManager.getAllCellStyles();\n const allConditionalStyles = this.styleManager.getAllConditionalStyles();\n\n return cells.map((cell) => {\n const sheet = this.workbookManager.getSheet({\n workbookName: cell.workbookName,\n sheetName: cell.sheetName,\n });\n\n const key = getCellReference(cell);\n const content = sheet?.content.get(key);\n const metadata = this.workbookManager.getCellMetadata(cell);\n\n // Find all styles that apply to this cell\n const matchingCellStyles = allCellStyles.filter((style) =>\n style.areas.some(\n (area) =>\n area.workbookName === cell.workbookName &&\n area.sheetName === cell.sheetName &&\n isCellInRange(cell, area.range)\n )\n );\n\n const matchingConditionalStyles = allConditionalStyles.filter((style) =>\n style.areas.some(\n (area) =>\n area.workbookName === cell.workbookName &&\n area.sheetName === cell.sheetName &&\n isCellInRange(cell, area.range)\n )\n );\n\n return {\n address: cell,\n content,\n metadata,\n matchingCellStyles,\n matchingConditionalStyles,\n };\n });\n }\n\n /**\n * Apply styles from a snapshot to a target cell\n * Creates new style areas at the target location\n */\n private applyStylesFromSnapshot(\n snapshot: CellSnapshot,\n targetCell: CellAddress\n ): void {\n // Apply cell styles\n if (snapshot.matchingCellStyles) {\n for (const style of snapshot.matchingCellStyles) {\n const newStyle: DirectCellStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: { col: targetCell.colIndex, row: targetCell.rowIndex },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n style: style.style,\n };\n this.styleManager.addCellStyle(newStyle);\n }\n }\n\n // Apply conditional styles\n if (snapshot.matchingConditionalStyles) {\n for (const style of snapshot.matchingConditionalStyles) {\n const newStyle: ConditionalStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: { col: targetCell.colIndex, row: targetCell.rowIndex },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n condition: style.condition,\n };\n this.styleManager.addConditionalStyle(newStyle);\n }\n }\n }\n\n /**\n * Copy content from a cell snapshot to a target cell\n */\n private copyCellContentFromSnapshot(\n snapshot: CellSnapshot,\n targetCell: CellAddress,\n sourceTopLeft: CellAddress,\n options: CopyCellsOptions\n ): void {\n if (!snapshot.content) {\n // Source cell was empty\n return;\n }\n\n let targetContent: SerializedCellValue;\n const copyType = options.type ?? \"formula\";\n\n if (copyType === \"value\") {\n // Copy evaluated value\n const evalResult = this.evaluationManager.getCellEvaluationResult(\n snapshot.address\n );\n\n if (!evalResult || evalResult.type !== \"value\") {\n // If evaluation failed or is not a value, copy as-is\n targetContent = snapshot.content;\n } else {\n // Convert to literal value\n const result = evalResult.result;\n if (result.type === \"number\") {\n targetContent = result.value;\n } else if (result.type === \"string\") {\n targetContent = result.value;\n } else if (result.type === \"boolean\") {\n targetContent = result.value;\n } else {\n // Error or other type, copy as-is\n targetContent = snapshot.content;\n }\n }\n } else {\n // Copy formula\n if (\n typeof snapshot.content === \"string\" &&\n snapshot.content.startsWith(\"=\")\n ) {\n // Adjust formula references\n targetContent = this.adjustFormulaReferences(\n snapshot.content,\n {\n colIndex: snapshot.address.colIndex,\n rowIndex: snapshot.address.rowIndex,\n },\n {\n colIndex: targetCell.colIndex,\n rowIndex: targetCell.rowIndex,\n }\n );\n } else {\n // Not a formula, copy as-is\n targetContent = snapshot.content;\n }\n }\n\n // Set target cell content\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.set(targetKey, targetContent);\n }\n\n // Copy metadata if requested\n if (this.shouldInclude(options, \"metadata\")) {\n if (snapshot.metadata) {\n this.workbookManager.setCellMetadata(targetCell, {\n ...snapshot.metadata,\n });\n } else {\n // Clear target metadata if source has none\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n }\n\n /**\n * Update all formula references when cells are cut (moved)\n */\n /**\n * Copy content from one cell to another\n */\n private copyCellContent(\n sourceCell: CellAddress,\n targetCell: CellAddress,\n sourceTopLeft: CellAddress,\n options: CopyCellsOptions\n ): void {\n const sheet = this.workbookManager.getSheet({\n workbookName: sourceCell.workbookName,\n sheetName: sourceCell.sheetName,\n });\n\n if (!sheet) {\n return;\n }\n\n const key = `${String.fromCharCode(65 + sourceCell.colIndex)}${\n sourceCell.rowIndex + 1\n }`;\n const cellContent = sheet.content.get(key);\n\n if (!cellContent) {\n // Source cell is empty\n return;\n }\n\n let targetContent: SerializedCellValue;\n const copyType = options.type ?? \"formula\";\n\n if (copyType === \"value\") {\n // Copy evaluated value\n const evalResult =\n this.evaluationManager.getCellEvaluationResult(sourceCell);\n\n if (!evalResult || evalResult.type !== \"value\") {\n // If evaluation failed or is not a value, copy as-is\n targetContent = cellContent;\n } else {\n // Convert to literal value\n const result = evalResult.result;\n if (result.type === \"number\") {\n targetContent = result.value;\n } else if (result.type === \"string\") {\n targetContent = result.value;\n } else if (result.type === \"boolean\") {\n targetContent = result.value;\n } else {\n // Error or other type, copy as-is\n targetContent = cellContent;\n }\n }\n } else {\n // Copy formula\n if (typeof cellContent === \"string\" && cellContent.startsWith(\"=\")) {\n // Adjust formula references\n targetContent = this.adjustFormulaReferences(\n cellContent,\n {\n colIndex: sourceCell.colIndex,\n rowIndex: sourceCell.rowIndex,\n },\n {\n colIndex: targetCell.colIndex,\n rowIndex: targetCell.rowIndex,\n }\n );\n } else {\n // Not a formula, copy as-is\n targetContent = cellContent;\n }\n }\n\n // Set target cell content (using the engine's method through workbook manager)\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.set(targetKey, targetContent);\n }\n\n // Copy metadata if requested\n if (this.shouldInclude(options, \"metadata\")) {\n const sourceMetadata = this.workbookManager.getCellMetadata(sourceCell);\n if (sourceMetadata) {\n this.workbookManager.setCellMetadata(targetCell, { ...sourceMetadata });\n } else {\n // Clear target metadata if source has none\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n }\n\n /**\n * Adjust formula references when copying\n * Based on autofill-utils.ts adjustFormulaReferences\n */\n private adjustFormulaReferences(\n formula: string,\n sourceAddress: LocalCellAddress,\n targetAddress: LocalCellAddress\n ): string {\n try {\n const ast = parseFormula(formula.slice(1)); // Remove the \"=\" sign\n\n const rowDelta = targetAddress.rowIndex - sourceAddress.rowIndex;\n const colDelta = targetAddress.colIndex - sourceAddress.colIndex;\n\n const adjustedAst = transformAST(ast, (node) => {\n if (node.type === \"reference\") {\n const refNode = node as ReferenceNode;\n return {\n ...refNode,\n address: {\n colIndex: refNode.isAbsolute.col\n ? refNode.address.colIndex\n : refNode.address.colIndex + colDelta,\n rowIndex: refNode.isAbsolute.row\n ? refNode.address.rowIndex\n : refNode.address.rowIndex + rowDelta,\n },\n };\n } else if (node.type === \"range\") {\n const rangeNode = node as RangeNode;\n return {\n ...rangeNode,\n range: {\n start: {\n col: rangeNode.isAbsolute.start.col\n ? rangeNode.range.start.col\n : rangeNode.range.start.col + colDelta,\n row: rangeNode.isAbsolute.start.row\n ? rangeNode.range.start.row\n : rangeNode.range.start.row + rowDelta,\n },\n end: {\n col:\n rangeNode.range.end.col.type === \"number\"\n ? rangeNode.isAbsolute.end.col\n ? rangeNode.range.end.col\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.col.value + colDelta,\n }\n : rangeNode.range.end.col,\n row:\n rangeNode.range.end.row.type === \"number\"\n ? rangeNode.isAbsolute.end.row\n ? rangeNode.range.end.row\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.row.value + rowDelta,\n }\n : rangeNode.range.end.row,\n },\n },\n };\n }\n return node;\n });\n\n return `=${astToString(adjustedAst)}`;\n } catch (error) {\n // If parsing fails, return the original formula\n console.warn(\"Failed to adjust formula references:\", error);\n return formula;\n }\n }\n\n /**\n * Copy formatting (cellStyles and conditionalStyles) from source to target\n * Clears existing cell styles in target range first (Excel behavior)\n */\n private copyFormatting(\n sourceCells: CellAddress[],\n sourceTopLeft: CellAddress,\n target: CellAddress,\n rowOffset: number,\n colOffset: number\n ): void {\n // STEP 1: Clear existing cell styles in target range (Excel-like replacement)\n const sourceRange = this.getBoundingBox(sourceCells);\n const targetRange: RangeAddress = {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(sourceRange, rowOffset, colOffset),\n };\n\n this.styleManager.clearCellStylesInRange(targetRange);\n\n // Get all styles for the source workbook\n const allConditionalStyles = this.styleManager.getAllConditionalStyles();\n const allCellStyles = this.styleManager.getAllCellStyles();\n\n // STEP 2: Copy conditional styles\n for (const style of allConditionalStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceTopLeft.workbookName &&\n area.sheetName === sourceTopLeft.sheetName\n ) {\n // Calculate intersection of style range with source bounding box\n const intersection = intersectRanges(area.range, sourceRange);\n if (intersection) {\n // Copy only the intersection, offset to target\n const newStyle: ConditionalStyle = {\n areas: [\n {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(intersection, rowOffset, colOffset),\n },\n ],\n condition: style.condition,\n };\n this.styleManager.addConditionalStyle(newStyle);\n }\n }\n }\n }\n\n // STEP 3: Copy cell styles\n for (const style of allCellStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceTopLeft.workbookName &&\n area.sheetName === sourceTopLeft.sheetName\n ) {\n // Calculate intersection of style range with source bounding box\n const intersection = intersectRanges(area.range, sourceRange);\n if (intersection) {\n // Copy only the intersection, offset to target\n const newStyle: DirectCellStyle = {\n areas: [\n {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(intersection, rowOffset, colOffset),\n },\n ],\n style: style.style,\n };\n this.styleManager.addCellStyle(newStyle);\n }\n }\n }\n }\n }\n\n /**\n * Get bounding box for a set of cells\n */\n private getBoundingBox(cells: CellAddress[]): SpreadsheetRange {\n let minRow = Infinity;\n let maxRow = -Infinity;\n let minCol = Infinity;\n let maxCol = -Infinity;\n\n for (const cell of cells) {\n minRow = Math.min(minRow, cell.rowIndex);\n maxRow = Math.max(maxRow, cell.rowIndex);\n minCol = Math.min(minCol, cell.colIndex);\n maxCol = Math.max(maxCol, cell.colIndex);\n }\n\n return {\n start: { col: minCol, row: minRow },\n end: {\n col: { type: \"number\", value: maxCol },\n row: { type: \"number\", value: maxRow },\n },\n };\n }\n\n /**\n * Adjust a range by row and column offsets\n */\n private adjustRange(\n range: SpreadsheetRange,\n rowOffset: number,\n colOffset: number\n ): SpreadsheetRange {\n return {\n start: {\n col: range.start.col + colOffset,\n row: range.start.row + rowOffset,\n },\n end: {\n col:\n range.end.col.type === \"number\"\n ? { type: \"number\", value: range.end.col.value + colOffset }\n : range.end.col,\n row:\n range.end.row.type === \"number\"\n ? { type: \"number\", value: range.end.row.value + rowOffset }\n : range.end.row,\n },\n };\n }\n\n /**\n * Clear source cells (for cut operation)\n */\n private clearSourceCells(cells: CellAddress[]): void {\n for (const cell of cells) {\n // Use setCellContent with empty string to properly clear the cell\n // This ensures indexes are updated and caches are properly managed\n this.workbookManager.setCellContent(cell, \"\");\n }\n }\n\n /**\n * Fill one or more areas with a seed range's content/style\n * Uses column-first strategy: fills down, then replicates right\n * Formulas are adjusted based on each target cell's offset from the seed\n */\n fillAreas(\n seedRange: RangeAddress,\n targetRanges: RangeAddress[],\n options: CopyCellsOptions\n ): void {\n for (const targetRange of targetRanges) {\n this.fillRangeWithSeed(seedRange, targetRange, {\n copyContent: this.shouldInclude(options, \"content\"),\n copyStyles: this.shouldInclude(options, \"style\"),\n contentType: options.type ?? \"formula\",\n adjustFormulas: true,\n });\n }\n\n // Clear seed range if cut operation\n if (options.cut) {\n const seedCells = this.expandRangeToCells(seedRange);\n this.clearSourceCells(seedCells);\n }\n }\n\n /**\n * Fill a target range with a seed range using column-first strategy\n * Step 0: Clear existing cell styles in target (Excel behavior)\n * Step 1: Fill down - extend seed pattern vertically to match target height\n * Step 2: Replicate right - copy filled columns horizontally\n */\n private fillRangeWithSeed(\n seedRange: RangeAddress,\n targetRange: RangeAddress,\n options: {\n copyContent: boolean;\n copyStyles: boolean;\n contentType: \"value\" | \"formula\";\n adjustFormulas: boolean;\n }\n ): void {\n // Step 0: Clear existing cell styles in target range (Excel-like replacement)\n if (options.copyStyles) {\n this.styleManager.clearCellStylesInRange(targetRange);\n }\n\n const seedCells = this.expandRangeToCells(seedRange);\n const seedWidth = this.getRangeWidth(seedRange);\n const seedHeight = this.getRangeHeight(seedRange);\n const targetWidth = this.getRangeWidth(targetRange);\n const targetHeight = this.getRangeHeight(targetRange);\n\n // Step 1: Fill down - replicate seed pattern vertically\n const filledColumns: Map<\n string,\n { cell: CellAddress; content: SerializedCellValue }\n > = new Map();\n\n for (let col = 0; col < seedWidth; col++) {\n for (let row = 0; row < targetHeight; row++) {\n const seedRow = row % seedHeight;\n const seedCell = seedCells.find(\n (c) =>\n c.colIndex === seedRange.range.start.col + col &&\n c.rowIndex === seedRange.range.start.row + seedRow\n );\n\n if (seedCell) {\n const targetCell: CellAddress = {\n workbookName: targetRange.workbookName,\n sheetName: targetRange.sheetName,\n colIndex: targetRange.range.start.col + col,\n rowIndex: targetRange.range.start.row + row,\n };\n\n const rowDelta = targetCell.rowIndex - seedCell.rowIndex;\n const colDelta = targetCell.colIndex - seedCell.colIndex;\n\n if (options.copyContent) {\n this.copyCellContentWithOffset(\n seedCell,\n targetCell,\n rowDelta,\n colDelta,\n {\n type: options.contentType,\n cut: false,\n include: [\"content\"],\n }\n );\n }\n\n if (options.copyStyles) {\n this.copyCellFormatting(seedCell, targetCell);\n }\n\n // Store filled column for horizontal replication\n const key = `${targetCell.colIndex}-${targetCell.rowIndex}`;\n const sheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n const cellKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n const content = sheet?.content.get(cellKey) || \"\";\n filledColumns.set(key, { cell: targetCell, content });\n }\n }\n }\n\n // Step 2: Replicate right - copy filled columns horizontally\n if (targetWidth > seedWidth) {\n for (let col = seedWidth; col < targetWidth; col++) {\n const sourceCol = col % seedWidth;\n\n for (let row = 0; row < targetHeight; row++) {\n const sourceCell: CellAddress = {\n workbookName: targetRange.workbookName,\n sheetName: targetRange.sheetName,\n colIndex: targetRange.range.start.col + sourceCol,\n rowIndex: targetRange.range.start.row + row,\n };\n\n const targetCell: CellAddress = {\n workbookName: targetRange.workbookName,\n sheetName: targetRange.sheetName,\n colIndex: targetRange.range.start.col + col,\n rowIndex: targetRange.range.start.row + row,\n };\n\n const colDelta = targetCell.colIndex - sourceCell.colIndex;\n\n if (options.copyContent) {\n this.copyCellContentWithOffset(\n sourceCell,\n targetCell,\n 0,\n colDelta,\n {\n type: options.contentType,\n cut: false,\n include: [\"content\"],\n }\n );\n }\n\n if (options.copyStyles) {\n this.copyCellFormatting(sourceCell, targetCell);\n }\n }\n }\n }\n }\n\n /**\n * Get the width of a range (number of columns)\n */\n private getRangeWidth(range: RangeAddress): number {\n if (range.range.end.col.type === \"infinity\") {\n return 100; // Default for infinite\n }\n return range.range.end.col.value - range.range.start.col + 1;\n }\n\n /**\n * Get the height of a range (number of rows)\n */\n private getRangeHeight(range: RangeAddress): number {\n if (range.range.end.row.type === \"infinity\") {\n return 100; // Default for infinite\n }\n return range.range.end.row.value - range.range.start.row + 1;\n }\n\n /**\n * Expand a RangeAddress into an array of CellAddress\n * Handles finite ranges, row-bounded, and column-bounded ranges\n */\n public expandRangeToCells(rangeAddress: RangeAddress): CellAddress[] {\n const { workbookName, sheetName, range } = rangeAddress;\n const cells: CellAddress[] = [];\n\n const startCol = range.start.col;\n const startRow = range.start.row;\n\n // Determine end column\n let endCol: number;\n if (range.end.col.type === \"infinity\") {\n // Limit infinite column ranges to a reasonable size (e.g., 100 columns)\n endCol = startCol + 99;\n } else {\n endCol = range.end.col.value;\n }\n\n // Determine end row\n let endRow: number;\n if (range.end.row.type === \"infinity\") {\n // Limit infinite row ranges to a reasonable size (e.g., 100 rows)\n endRow = startRow + 99;\n } else {\n endRow = range.end.row.value;\n }\n\n // Generate all cells in the range\n for (let row = startRow; row <= endRow; row++) {\n for (let col = startCol; col <= endCol; col++) {\n cells.push({\n workbookName,\n sheetName,\n colIndex: col,\n rowIndex: row,\n });\n }\n }\n\n return cells;\n }\n\n /**\n * Copy cell content with explicit row/column offset for fill operations\n */\n private copyCellContentWithOffset(\n sourceCell: CellAddress,\n targetCell: CellAddress,\n rowDelta: number,\n colDelta: number,\n options: CopyCellsOptions\n ): void {\n const sheet = this.workbookManager.getSheet({\n workbookName: sourceCell.workbookName,\n sheetName: sourceCell.sheetName,\n });\n\n if (!sheet) {\n return;\n }\n\n const key = `${String.fromCharCode(65 + sourceCell.colIndex)}${\n sourceCell.rowIndex + 1\n }`;\n const cellContent = sheet.content.get(key);\n\n if (!cellContent) {\n // Source cell is empty - clear target\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.delete(targetKey);\n }\n return;\n }\n\n let targetContent: SerializedCellValue;\n const copyType = options.type ?? \"formula\";\n\n if (copyType === \"value\") {\n // Copy evaluated value\n const evalResult =\n this.evaluationManager.getCellEvaluationResult(sourceCell);\n\n if (!evalResult || evalResult.type !== \"value\") {\n // If evaluation failed or is not a value, copy as-is\n targetContent = cellContent;\n } else {\n // Convert to literal value\n const result = evalResult.result;\n if (result.type === \"number\") {\n targetContent = result.value;\n } else if (result.type === \"string\") {\n targetContent = result.value;\n } else if (result.type === \"boolean\") {\n targetContent = result.value;\n } else {\n // Error or other type, copy as-is\n targetContent = cellContent;\n }\n }\n } else {\n // Copy formula with offset adjustment\n if (typeof cellContent === \"string\" && cellContent.startsWith(\"=\")) {\n // Adjust formula references based on offset\n targetContent = this.adjustFormulaWithOffset(\n cellContent,\n rowDelta,\n colDelta\n );\n } else {\n // Not a formula, copy as-is\n targetContent = cellContent;\n }\n }\n\n // Set target cell content\n const targetSheet = this.workbookManager.getSheet({\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n });\n\n if (targetSheet) {\n const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${\n targetCell.rowIndex + 1\n }`;\n targetSheet.content.set(targetKey, targetContent);\n }\n\n // Copy metadata if requested\n if (this.shouldInclude(options, \"metadata\")) {\n const sourceMetadata = this.workbookManager.getCellMetadata(sourceCell);\n if (sourceMetadata) {\n this.workbookManager.setCellMetadata(targetCell, { ...sourceMetadata });\n } else {\n // Clear target metadata if source has none\n this.workbookManager.setCellMetadata(targetCell, undefined);\n }\n }\n }\n\n /**\n * Adjust formula references by a specific row/column offset\n */\n private adjustFormulaWithOffset(\n formula: string,\n rowDelta: number,\n colDelta: number\n ): string {\n try {\n const ast = parseFormula(formula.slice(1)); // Remove the \"=\" sign\n\n const adjustedAst = transformAST(ast, (node) => {\n if (node.type === \"reference\") {\n const refNode = node as ReferenceNode;\n return {\n ...refNode,\n address: {\n colIndex: refNode.isAbsolute.col\n ? refNode.address.colIndex\n : refNode.address.colIndex + colDelta,\n rowIndex: refNode.isAbsolute.row\n ? refNode.address.rowIndex\n : refNode.address.rowIndex + rowDelta,\n },\n };\n } else if (node.type === \"range\") {\n const rangeNode = node as RangeNode;\n return {\n ...rangeNode,\n range: {\n start: {\n col: rangeNode.isAbsolute.start.col\n ? rangeNode.range.start.col\n : rangeNode.range.start.col + colDelta,\n row: rangeNode.isAbsolute.start.row\n ? rangeNode.range.start.row\n : rangeNode.range.start.row + rowDelta,\n },\n end: {\n col:\n rangeNode.range.end.col.type === \"number\"\n ? rangeNode.isAbsolute.end.col\n ? rangeNode.range.end.col\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.col.value + colDelta,\n }\n : rangeNode.range.end.col,\n row:\n rangeNode.range.end.row.type === \"number\"\n ? rangeNode.isAbsolute.end.row\n ? rangeNode.range.end.row\n : {\n type: \"number\" as const,\n value: rangeNode.range.end.row.value + rowDelta,\n }\n : rangeNode.range.end.row,\n },\n },\n };\n }\n return node;\n });\n\n return `=${astToString(adjustedAst)}`;\n } catch (error) {\n // If parsing fails, return the original formula\n console.warn(\"Failed to adjust formula with offset:\", error);\n return formula;\n }\n }\n\n /**\n * Copy formatting from one cell to another\n * Clears existing cell styles at target (Excel behavior) before copying new ones\n */\n private copyCellFormatting(\n sourceCell: CellAddress,\n targetCell: CellAddress\n ): void {\n // STEP 1: Clear existing cell styles at target cell (Excel-like replacement)\n const targetCellRange: RangeAddress = {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: { col: targetCell.colIndex, row: targetCell.rowIndex },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n };\n\n this.styleManager.clearCellStylesInRange(targetCellRange);\n\n // Get all styles that intersect with the source cell\n const allConditionalStyles = this.styleManager.getAllConditionalStyles();\n const allCellStyles = this.styleManager.getAllCellStyles();\n\n const sourceCellRange: SpreadsheetRange = {\n start: { col: sourceCell.colIndex, row: sourceCell.rowIndex },\n end: {\n col: { type: \"number\", value: sourceCell.colIndex },\n row: { type: \"number\", value: sourceCell.rowIndex },\n },\n };\n\n // STEP 2: Copy conditional styles that apply to source cell\n for (const style of allConditionalStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceCell.workbookName &&\n area.sheetName === sourceCell.sheetName\n ) {\n const intersection = intersectRanges(area.range, sourceCellRange);\n if (intersection) {\n // Apply style to target cell\n const newStyle: ConditionalStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: {\n col: targetCell.colIndex,\n row: targetCell.rowIndex,\n },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n condition: style.condition,\n };\n this.styleManager.addConditionalStyle(newStyle);\n }\n }\n }\n }\n\n // STEP 3: Copy cell styles that apply to source cell\n for (const style of allCellStyles) {\n for (const area of style.areas) {\n if (\n area.workbookName === sourceCell.workbookName &&\n area.sheetName === sourceCell.sheetName\n ) {\n const intersection = intersectRanges(area.range, sourceCellRange);\n if (intersection) {\n // Apply style to target cell\n const newStyle: DirectCellStyle = {\n areas: [\n {\n workbookName: targetCell.workbookName,\n sheetName: targetCell.sheetName,\n range: {\n start: {\n col: targetCell.colIndex,\n row: targetCell.rowIndex,\n },\n end: {\n col: { type: \"number\", value: targetCell.colIndex },\n row: { type: \"number\", value: targetCell.rowIndex },\n },\n },\n },\n ],\n style: style.style,\n };\n this.styleManager.addCellStyle(newStyle);\n }\n }\n }\n }\n }\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "9E025649C6A89F3564756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/core/types.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Core type definitions for FormulaEngine\n * This file contains all fundamental types used throughout the engine\n */\n\nimport type { EvaluationContext } from \"../evaluator/evaluation-context.mjs\";\nimport type { FormulaEvaluator } from \"../evaluator/formula-evaluator.mjs\";\nimport type { FunctionNode } from \"../parser/ast.mjs\";\nimport type { DependencyNode } from \"./managers/dependency-node.mjs\";\nimport type { LookupOrder } from \"./managers/range-eval-order-builder.mjs\";\n\n// Cell addressing types\nexport interface CellAddress {\n sheetName: string;\n workbookName: string;\n colIndex: number;\n rowIndex: number;\n}\n\nexport interface RangeAddress {\n sheetName: string;\n workbookName: string;\n range: SpreadsheetRange;\n}\n\nexport interface LocalCellAddress {\n colIndex: number;\n rowIndex: number;\n}\n\nexport type ArethmeticEvaluator = (\n left: CellValue,\n right: CellValue,\n context: EvaluationContext\n) => CellValue | ErrorEvaluationResult;\n\nexport type PositiveInfinity = {\n type: \"infinity\";\n sign: \"positive\";\n};\n\nexport type CellInfinity = {\n type: \"infinity\";\n sign: \"positive\" | \"negative\";\n};\n\nexport type CellNumber = {\n type: \"number\";\n value: number;\n};\n\nexport type SpreadsheetRangeEnd = CellNumber | PositiveInfinity;\n\nexport type SpreadsheetRange = {\n start: {\n col: number;\n row: number;\n };\n end: {\n col: SpreadsheetRangeEnd;\n row: SpreadsheetRangeEnd;\n };\n};\n\nexport type RelativeRange = {\n start: {\n col: number;\n row: number;\n };\n width: SpreadsheetRangeEnd;\n height: SpreadsheetRangeEnd;\n};\n\nexport type FiniteSpreadsheetRange = {\n start: {\n col: number;\n row: number;\n };\n end: {\n col: number;\n row: number;\n };\n};\n\nexport type CellString = {\n type: \"string\";\n value: string;\n};\n\nexport type CellBoolean = {\n type: \"boolean\";\n value: boolean;\n};\n\n// Cell value types\nexport type CellValue = CellNumber | CellString | CellBoolean | CellInfinity;\n/**\n * undefined and \"\" are considered empty values\n * undefineds are converted to \"\" in the engine\n *\n * any empty values are deleted from the sheet content\n */\nexport type SerializedCellValue = string | number | boolean | undefined;\n\n\n// Named expressions\nexport interface NamedExpression {\n name: string;\n expression: string;\n}\n\nexport interface TableDefinition {\n name: string;\n start: {\n rowIndex: number;\n colIndex: number;\n };\n headers: Map<string, { name: string; index: number }>;\n endRow: SpreadsheetRangeEnd;\n sheetName: string;\n workbookName: string;\n}\n\n// Formula errors\nexport enum FormulaError {\n DIV0 = \"#DIV/0!\",\n NA = \"#N/A\",\n NAME = \"#NAME?\",\n NUM = \"#NUM!\",\n REF = \"#REF!\",\n VALUE = \"#VALUE!\",\n CYCLE = \"#CYCLE!\",\n ERROR = \"#ERROR!\",\n SPILL = \"#SPILL!\",\n}\n\n// Sheet structure\nexport interface Sheet<TCellMetadata = unknown, TSheetMetadata = unknown> {\n name: string;\n index: number; // 0-based index of the sheet\n content: Map<string, SerializedCellValue>;\n /**\n * Cell metadata - arbitrary consumer-defined data per cell\n * Examples: rich text content, links, comments, custom app data\n * The engine stores and copies this data but doesn't interpret it\n * Keyed by cell reference (e.g., \"A1\")\n */\n metadata: Map<string, TCellMetadata>;\n /**\n * Sheet-level metadata - arbitrary consumer-defined data for the entire sheet\n * Examples: text boxes, drawings, frozen panes, print settings\n * The engine stores and copies this data but doesn't interpret it\n */\n sheetMetadata: TSheetMetadata;\n}\n\nexport interface Workbook<TCellMetadata = unknown, TSheetMetadata = unknown, TWorkbookMetadata = unknown> {\n name: string;\n sheets: Map<string, Sheet<TCellMetadata, TSheetMetadata>>;\n /**\n * Workbook-level metadata - arbitrary consumer-defined data for the entire workbook\n * Examples: themes, custom ribbons, document properties, workbook settings\n * The engine stores and copies this data but doesn't interpret it\n */\n workbookMetadata: TWorkbookMetadata;\n}\n\n/**\n * Tracked reference - a stable reference to a range that updates automatically\n * when workbooks/sheets are renamed and becomes invalid when they're deleted\n */\nexport interface TrackedReference {\n id: string; // UUID\n address: RangeAddress; // The range being tracked\n isValid: boolean; // False if sheet/workbook deleted\n}\n\nexport type ValueEvaluationResult = {\n type: \"value\";\n result: CellValue;\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n */\n sourceCell?: CellAddress;\n};\n\nexport type AwaitingEvaluationResult = {\n type: \"awaiting-evaluation\";\n waitingFor: DependencyNode;\n errAddress: DependencyNode;\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n */\n sourceCell?: CellAddress;\n};\n\nexport type DoesNotSpillResult = {\n type: \"does-not-spill\";\n};\n\nexport type ErrorEvaluationResult =\n | {\n type: \"error\";\n err: FormulaError;\n errAddress: DependencyNode;\n message: string;\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n */\n sourceCell?: CellAddress;\n }\n | AwaitingEvaluationResult;\n\nexport type SingleEvaluationResult =\n | ValueEvaluationResult\n | ErrorEvaluationResult;\n\nexport type SpilledValuesEvaluator = (\n spillOffset: { x: number; y: number },\n context: EvaluationContext\n) => SingleEvaluationResult;\n\nexport type SpilledValuesEvaluationResult = {\n type: \"spilled-values\";\n\n /**\n * When a raw range is evaluated, we will add it to the sourceRange so it can be used e.g. for context dependent functions\n */\n sourceRange?: RangeAddress;\n\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n * sourceCell will only be defined on a spilledValue when a single value is looked up,\n */\n sourceCell?: CellAddress;\n\n spillArea: (origin: CellAddress) => SpreadsheetRange;\n /**\n * for debugging we add a source string to denote where the spilled values were created\n */\n source: string;\n evaluate: SpilledValuesEvaluator;\n /**\n * evaluateAllCells evaluates all non-empty cells in the spilled range.\n * Because a spilled range can be open-ended, we need to have logic for which cells we should evaluate.\n * e.g. when evaluating a range such as D:D only the cells in the current sheet residing in\n * column D should be evaluated and cells producing spilled values that spill onto D:D.\n *\n * In order to evaluate spilled cells in D:D the range evaluateAllCells need to get all cells in the\n * the intersection of the spilled range and D:D, for that reason evaluateAllCells gets an intersection parameter,\n * where the intersection is relative to the origin.\n *\n * #### Producers:\n * In e.g. SEQUENCE and evaluateRange we have logic for which cells in a spilled range we should evaluate,\n *\n * #### Nesting:\n * e.g. evaluation of scalar operators where we want to nest e.g. `5 * right.evaluate()`\n * can be implemented by calling\n * ```ts\n * const vals = child.evaluateAllCells.call(this, options);\n * return vals.map(val => ({ ...val, result: 5 * val.result }));\n * ```\n *\n * #### Consumers:\n * Only functions that need access to all spilled values in a range end up calling evaluateAllCells, e.g.\n * SUM, MIN, MAX, MATCH. Other types of functions like INDEX doesn't need to evaluate all cells in a range,\n * but does a lookup into a spilled range using the evaluate method.\n *\n */\n evaluateAllCells: (\n this: FormulaEvaluator,\n options: {\n /**\n * an intersection relative to the origin\n */\n intersection?: SpreadsheetRange;\n evaluate: SpilledValuesEvaluator;\n context: EvaluationContext;\n /**\n * origin is the cell address that the spilled range is spilled from\n * e.g. in A3=B2:B4 the origin is A3\n */\n origin: CellAddress;\n\n lookupOrder: LookupOrder;\n }\n ) => EvaluateAllCellsResult;\n};\n\nexport type EvaluateAllCellsResult =\n | ErrorEvaluationResult\n | {\n type: \"values\";\n values: CellInRangeResult[];\n };\n\nexport type CellInRangeResult = {\n result: SingleEvaluationResult;\n relativePos: { x: number; y: number };\n};\n\nexport type FunctionEvaluationResult =\n | SingleEvaluationResult\n | SpilledValuesEvaluationResult;\n\nexport type SpilledValue = {\n /**\n * spillOnto is the range that the spilled value is spilled onto\n */\n spillOnto: SpreadsheetRange;\n /**\n * origin is the cell address that the spilled value is spilled from\n */\n origin: CellAddress;\n};\n\n/**\n * Function definition\n */\nexport interface FunctionDefinition {\n name: string;\n evaluate: (\n this: FormulaEvaluator,\n node: FunctionNode,\n context: EvaluationContext\n ) => FunctionEvaluationResult;\n aliases?: string[];\n}\n\n/**\n * Evaluation result\n */\nexport type EvaluationResult = {\n dependencies: Set<string>;\n} & FunctionEvaluationResult;\n\nexport type SCC = {\n id: number;\n nodes: Set<DependencyNode>; // All nodes considering soft + hard edges\n evaluationOrder: DependencyNode[]; // Flat topologically ordered list\n resolved: boolean;\n hardEdgeSCCs: Set<DependencyNode>[]; // SCCs formed by only hard edges (regular dependencies)\n};\n\nexport type SCCDAG = {\n sccList: SCC[];\n sccGraph: Map<number, Set<number>>; // Adjacency list of SCC dependencies\n};\n\nexport type EvaluationOrder = {\n evaluationOrder: Set<DependencyNode>;\n hasCycle: boolean;\n cycleNodes?: Set<DependencyNode>;\n hash: string;\n sccDAG?: SCCDAG;\n};\n\n// Conditional Styling types\nexport interface LCHColor {\n l: number; // Lightness: 0-100\n c: number; // Chroma: 0-150+\n h: number; // Hue: 0-360\n}\n\nexport interface FormulaStyleCondition {\n type: \"formula\";\n formula: string;\n color: LCHColor;\n}\n\nexport interface GradientStyleCondition {\n type: \"gradient\";\n min:\n | { type: \"lowest_value\"; color: LCHColor }\n | { type: \"number\"; color: LCHColor; valueFormula: string };\n max:\n | { type: \"highest_value\"; color: LCHColor }\n | { type: \"number\"; color: LCHColor; valueFormula: string };\n}\n\nexport type StyleCondition = FormulaStyleCondition | GradientStyleCondition;\n\nexport interface ConditionalStyle {\n areas: RangeAddress[];\n condition: StyleCondition;\n}\n\nexport interface DirectCellStyle {\n areas: RangeAddress[];\n style: CellStyle\n}\n\nexport interface CellStyle {\n backgroundColor?: string; // Hex color format\n color?: string; // Text color in hex format\n fontSize?: number; // Font size in pixels\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n}\n\nexport interface CopyCellsOptions {\n /**\n * Whether this is a cut operation (clears source cells after copying)\n * @default false\n */\n cut?: boolean;\n /**\n * What to include in the copy operation.\n * - Use 'all' as shorthand for ['content', 'style', 'metadata']\n * - Use array for fine-grained control over what to copy:\n * - ['content'] - copy only values/formulas\n * - ['style'] - copy only formatting\n * - ['metadata'] - copy only metadata (rich text, links, etc.)\n * - ['content', 'style'] - copy content and formatting\n * - ['content', 'metadata'] - copy content and metadata\n * - ['style', 'metadata'] - copy formatting and metadata\n * - ['content', 'style', 'metadata'] - same as 'all'\n * @default 'all'\n */\n include?: 'all' | ('content' | 'style' | 'metadata')[];\n /**\n * The type of the content to copy\n * value: Copy the value from the source to the target,\n * e.g. if the cell has the formula =123 + 123 then the value is 246\n * formula: Copy the formula from the source to the target,\n * e.g. if the cell has the formula =123 + 123 then the formula is =123 + 123 is copied\n * @default 'formula'\n */\n type?: \"value\" | \"formula\";\n}\n"
|
|
5
|
+
"/**\n * Core type definitions for FormulaEngine\n * This file contains all fundamental types used throughout the engine\n */\n\nimport type { EvaluationContext } from \"../evaluator/evaluation-context.mjs\";\nimport type { FormulaEvaluator } from \"../evaluator/formula-evaluator.mjs\";\nimport type { FunctionNode } from \"../parser/ast.mjs\";\nimport type { DependencyNode } from \"./managers/dependency-node.mjs\";\nimport type { LookupOrder } from \"./managers/range-eval-order-builder.mjs\";\n\n// Cell addressing types\nexport interface CellAddress {\n sheetName: string;\n workbookName: string;\n colIndex: number;\n rowIndex: number;\n}\n\nexport interface RangeAddress {\n sheetName: string;\n workbookName: string;\n range: SpreadsheetRange;\n}\n\nexport interface LocalCellAddress {\n colIndex: number;\n rowIndex: number;\n}\n\nexport type ArethmeticEvaluator = (\n left: CellValue,\n right: CellValue,\n context: EvaluationContext\n) => CellValue | ErrorEvaluationResult;\n\nexport type PositiveInfinity = {\n type: \"infinity\";\n sign: \"positive\";\n};\n\nexport type CellInfinity = {\n type: \"infinity\";\n sign: \"positive\" | \"negative\";\n};\n\nexport type CellNumber = {\n type: \"number\";\n value: number;\n};\n\nexport type SpreadsheetRangeEnd = CellNumber | PositiveInfinity;\n\nexport type SpreadsheetRange = {\n start: {\n col: number;\n row: number;\n };\n end: {\n col: SpreadsheetRangeEnd;\n row: SpreadsheetRangeEnd;\n };\n};\n\nexport type RelativeRange = {\n start: {\n col: number;\n row: number;\n };\n width: SpreadsheetRangeEnd;\n height: SpreadsheetRangeEnd;\n};\n\nexport type FiniteSpreadsheetRange = {\n start: {\n col: number;\n row: number;\n };\n end: {\n col: number;\n row: number;\n };\n};\n\nexport type CellString = {\n type: \"string\";\n value: string;\n};\n\nexport type CellBoolean = {\n type: \"boolean\";\n value: boolean;\n};\n\n// Cell value types\nexport type CellValue = CellNumber | CellString | CellBoolean | CellInfinity;\n/**\n * undefined and \"\" are considered empty values\n * undefineds are converted to \"\" in the engine\n *\n * any empty values are deleted from the sheet content\n */\nexport type SerializedCellValue = string | number | boolean | undefined;\n\n// Named expressions\nexport interface NamedExpression {\n name: string;\n expression: string;\n}\n\nexport interface TableDefinition {\n name: string;\n start: {\n rowIndex: number;\n colIndex: number;\n };\n headers: Map<string, { name: string; index: number }>;\n endRow: SpreadsheetRangeEnd;\n sheetName: string;\n workbookName: string;\n}\n\n// Formula errors\nexport enum FormulaError {\n DIV0 = \"#DIV/0!\",\n NA = \"#N/A\",\n NAME = \"#NAME?\",\n NUM = \"#NUM!\",\n REF = \"#REF!\",\n VALUE = \"#VALUE!\",\n CYCLE = \"#CYCLE!\",\n ERROR = \"#ERROR!\",\n SPILL = \"#SPILL!\",\n}\n\n// Sheet structure\nexport interface Sheet<TCellMetadata = unknown, TSheetMetadata = unknown> {\n name: string;\n index: number; // 0-based index of the sheet\n content: Map<string, SerializedCellValue>;\n /**\n * Cell metadata - arbitrary consumer-defined data per cell\n * Examples: rich text content, links, comments, custom app data\n * The engine stores and copies this data but doesn't interpret it\n * Keyed by cell reference (e.g., \"A1\")\n */\n metadata: Map<string, TCellMetadata>;\n /**\n * Sheet-level metadata - arbitrary consumer-defined data for the entire sheet\n * Examples: text boxes, drawings, frozen panes, print settings\n * The engine stores and copies this data but doesn't interpret it\n */\n sheetMetadata: TSheetMetadata;\n}\n\nexport interface Workbook<\n TCellMetadata = unknown,\n TSheetMetadata = unknown,\n TWorkbookMetadata = unknown\n> {\n name: string;\n sheets: Map<string, Sheet<TCellMetadata, TSheetMetadata>>;\n /**\n * Workbook-level metadata - arbitrary consumer-defined data for the entire workbook\n * Examples: themes, custom ribbons, document properties, workbook settings\n * The engine stores and copies this data but doesn't interpret it\n */\n workbookMetadata: TWorkbookMetadata;\n}\n\n/**\n * Tracked reference - a stable reference to a range that updates automatically\n * when workbooks/sheets are renamed and becomes invalid when they're deleted\n */\nexport interface TrackedReference {\n id: string; // UUID\n address: RangeAddress; // The range being tracked\n isValid: boolean; // False if sheet/workbook deleted\n}\n\nexport type ValueEvaluationResult = {\n type: \"value\";\n result: CellValue;\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n */\n sourceCell?: CellAddress;\n};\n\nexport type AwaitingEvaluationResult = {\n type: \"awaiting-evaluation\";\n waitingFor: DependencyNode;\n errAddress: DependencyNode;\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n */\n sourceCell?: CellAddress;\n};\n\nexport type DoesNotSpillResult = {\n type: \"does-not-spill\";\n};\n\nexport type ErrorEvaluationResult =\n | {\n type: \"error\";\n err: FormulaError;\n errAddress: DependencyNode;\n message: string;\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n */\n sourceCell?: CellAddress;\n }\n | AwaitingEvaluationResult;\n\nexport type SingleEvaluationResult =\n | ValueEvaluationResult\n | ErrorEvaluationResult;\n\nexport type SpilledValuesEvaluator = (\n spillOffset: { x: number; y: number },\n context: EvaluationContext\n) => SingleEvaluationResult;\n\nexport type SpilledValuesEvaluationResult = {\n type: \"spilled-values\";\n\n /**\n * When a raw range is evaluated, we will add it to the sourceRange so it can be used e.g. for context dependent functions\n */\n sourceRange?: RangeAddress;\n\n /**\n * If the terminating evaluation result is a reference (see evaluateReference)\n * then we store information about the source cell for context dependent functions like CELL\n * sourceCell will only be defined on a spilledValue when a single value is looked up,\n */\n sourceCell?: CellAddress;\n\n spillArea: (origin: CellAddress) => SpreadsheetRange;\n /**\n * for debugging we add a source string to denote where the spilled values were created\n */\n source: string;\n evaluate: SpilledValuesEvaluator;\n /**\n * evaluateAllCells evaluates all non-empty cells in the spilled range.\n * Because a spilled range can be open-ended, we need to have logic for which cells we should evaluate.\n * e.g. when evaluating a range such as D:D only the cells in the current sheet residing in\n * column D should be evaluated and cells producing spilled values that spill onto D:D.\n *\n * In order to evaluate spilled cells in D:D the range evaluateAllCells need to get all cells in the\n * the intersection of the spilled range and D:D, for that reason evaluateAllCells gets an intersection parameter,\n * where the intersection is relative to the origin.\n *\n * #### Producers:\n * In e.g. SEQUENCE and evaluateRange we have logic for which cells in a spilled range we should evaluate,\n *\n * #### Nesting:\n * e.g. evaluation of scalar operators where we want to nest e.g. `5 * right.evaluate()`\n * can be implemented by calling\n * ```ts\n * const vals = child.evaluateAllCells.call(this, options);\n * return vals.map(val => ({ ...val, result: 5 * val.result }));\n * ```\n *\n * #### Consumers:\n * Only functions that need access to all spilled values in a range end up calling evaluateAllCells, e.g.\n * SUM, MIN, MAX, MATCH. Other types of functions like INDEX doesn't need to evaluate all cells in a range,\n * but does a lookup into a spilled range using the evaluate method.\n *\n */\n evaluateAllCells: (\n this: FormulaEvaluator,\n options: {\n /**\n * an intersection relative to the origin\n */\n intersection?: SpreadsheetRange;\n evaluate: SpilledValuesEvaluator;\n context: EvaluationContext;\n /**\n * origin is the cell address that the spilled range is spilled from\n * e.g. in A3=B2:B4 the origin is A3\n */\n origin: CellAddress;\n\n lookupOrder: LookupOrder;\n }\n ) => EvaluateAllCellsResult;\n};\n\nexport type EvaluateAllCellsResult =\n | ErrorEvaluationResult\n | {\n type: \"values\";\n values: CellInRangeResult[];\n };\n\nexport type CellInRangeResult = {\n result: SingleEvaluationResult;\n relativePos: { x: number; y: number };\n};\n\nexport type FunctionEvaluationResult =\n | SingleEvaluationResult\n | SpilledValuesEvaluationResult;\n\nexport type SpilledValue = {\n /**\n * spillOnto is the range that the spilled value is spilled onto\n */\n spillOnto: SpreadsheetRange;\n /**\n * origin is the cell address that the spilled value is spilled from\n */\n origin: CellAddress;\n};\n\n/**\n * Function definition\n */\nexport interface FunctionDefinition {\n name: string;\n evaluate: (\n this: FormulaEvaluator,\n node: FunctionNode,\n context: EvaluationContext\n ) => FunctionEvaluationResult;\n aliases?: string[];\n}\n\n/**\n * Evaluation result\n */\nexport type EvaluationResult = {\n dependencies: Set<string>;\n} & FunctionEvaluationResult;\n\nexport type SCC = {\n id: number;\n nodes: Set<DependencyNode>; // All nodes considering soft + hard edges\n evaluationOrder: DependencyNode[]; // Flat topologically ordered list\n resolved: boolean;\n hardEdgeSCCs: Set<DependencyNode>[]; // SCCs formed by only hard edges (regular dependencies)\n};\n\nexport type SCCDAG = {\n sccList: SCC[];\n sccGraph: Map<number, Set<number>>; // Adjacency list of SCC dependencies\n};\n\nexport type EvaluationOrder = {\n evaluationOrder: Set<DependencyNode>;\n hasCycle: boolean;\n cycleNodes?: Set<DependencyNode>;\n hash: string;\n sccDAG?: SCCDAG;\n};\n\n// Conditional Styling types\nexport interface LCHColor {\n l: number; // Lightness: 0-100\n c: number; // Chroma: 0-150+\n h: number; // Hue: 0-360\n}\n\nexport interface FormulaStyleCondition {\n type: \"formula\";\n formula: string;\n color: LCHColor;\n}\n\nexport interface GradientStyleCondition {\n type: \"gradient\";\n min:\n | { type: \"lowest_value\"; color: LCHColor }\n | { type: \"number\"; color: LCHColor; valueFormula: string };\n max:\n | { type: \"highest_value\"; color: LCHColor }\n | { type: \"number\"; color: LCHColor; valueFormula: string };\n}\n\nexport type StyleCondition = FormulaStyleCondition | GradientStyleCondition;\n\nexport interface ConditionalStyle {\n areas: RangeAddress[];\n condition: StyleCondition;\n}\n\nexport interface DirectCellStyle {\n areas: RangeAddress[];\n style: CellStyle;\n}\n\nexport interface CellStyle {\n backgroundColor?: string; // Hex color format\n color?: string; // Text color in hex format\n fontSize?: number; // Font size in pixels\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n}\n\nexport interface CopyCellsOptions {\n /**\n * Whether this is a cut operation (clears source cells after copying)\n * @default false\n */\n cut?: boolean;\n /**\n * What to include in the copy operation.\n * - Use 'all' as shorthand for ['content', 'style', 'metadata']\n * - Use array for fine-grained control over what to copy:\n * - ['content'] - copy only values/formulas\n * - ['style'] - copy only formatting\n * - ['metadata'] - copy only metadata (rich text, links, etc.)\n * - ['content', 'style'] - copy content and formatting\n * - ['content', 'metadata'] - copy content and metadata\n * - ['style', 'metadata'] - copy formatting and metadata\n * - ['content', 'style', 'metadata'] - same as 'all'\n * @default 'all'\n */\n include?: \"all\" | (\"content\" | \"style\" | \"metadata\")[];\n /**\n * The type of the content to copy\n * value: Copy the value from the source to the target,\n * e.g. if the cell has the formula =123 + 123 then the value is 246\n * formula: Copy the formula from the source to the target,\n * e.g. if the cell has the formula =123 + 123 then the formula is =123 + 123 is copied\n * @default 'formula'\n */\n type?: \"value\" | \"formula\";\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";
|
|
7
|
+
"mappings": ";AA2HO,IAAK;AAAA,CAAL,CAAK,kBAAL;AAAA,EACL,wBAAO;AAAA,EACP,sBAAK;AAAA,EACL,wBAAO;AAAA,EACP,uBAAM;AAAA,EACN,uBAAM;AAAA,EACN,yBAAQ;AAAA,EACR,yBAAQ;AAAA,EACR,yBAAQ;AAAA,EACR,yBAAQ;AAAA,GATE;",
|
|
8
8
|
"debugId": "0E7C5AF634572D3964756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/lib.mjs
CHANGED
|
@@ -4,8 +4,19 @@ import { FormulaEngine } from "./core/engine.mjs";
|
|
|
4
4
|
export * from "./core/types.mjs";
|
|
5
5
|
export * from "./core/utils.mjs";
|
|
6
6
|
export * from "./core/utils/color-utils.mjs";
|
|
7
|
+
import { defineApi, createApi } from "./core/api/api.mjs";
|
|
8
|
+
import { TableOrm } from "./core/api/table-orm.mjs";
|
|
9
|
+
import { CellOrm } from "./core/api/cell-orm.mjs";
|
|
10
|
+
import { SchemaValidationError } from "./core/managers/api-schema-manager.mjs";
|
|
11
|
+
import { SchemaIntegrityError } from "./core/commands/command-executor.mjs";
|
|
7
12
|
export {
|
|
8
|
-
|
|
13
|
+
defineApi,
|
|
14
|
+
createApi,
|
|
15
|
+
TableOrm,
|
|
16
|
+
SchemaValidationError,
|
|
17
|
+
SchemaIntegrityError,
|
|
18
|
+
FormulaEngine,
|
|
19
|
+
CellOrm
|
|
9
20
|
};
|
|
10
21
|
|
|
11
|
-
//# debugId=
|
|
22
|
+
//# debugId=0A3DD3BE22C9A95664756E2164756E21
|
package/dist/mjs/lib.mjs.map
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"export { FormulaEngine } from \"./core/engine.mjs\";\nexport * from \"./core/types.mjs\";\nexport * from \"./core/utils.mjs\";\nexport * from \"./core/utils/color-utils.mjs\";\n"
|
|
5
|
+
"export { FormulaEngine } from \"./core/engine.mjs\";\nexport * from \"./core/types.mjs\";\nexport * from \"./core/utils.mjs\";\nexport * from \"./core/utils/color-utils.mjs\";\n\n// API Schema exports\nexport { defineApi, createApi } from \"./core/api/api.mjs\";\nexport type { CreateApi, Declaration, Api, TableApi, CellApi } from \"./core/api/api.mjs\";\nexport { TableOrm } from \"./core/api/table-orm.mjs\";\nexport { CellOrm } from \"./core/api/cell-orm.mjs\";\nexport { SchemaValidationError } from \"./core/managers/api-schema-manager.mjs\";\nexport type { ValidationResult } from \"./core/managers/api-schema-manager.mjs\";\n\n// Command Pattern exports\nexport { SchemaIntegrityError } from \"./core/commands/command-executor.mjs\";\nexport type { EngineAction, EngineCommand } from \"./core/commands/types.mjs\";\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAAA;AAAA;AACA;AACA;AACA;",
|
|
8
|
-
"debugId": "
|
|
7
|
+
"mappings": ";AAAA;AAAA;AACA;AACA;AACA;AAGA;AAEA;AACA;AACA;AAIA;",
|
|
8
|
+
"debugId": "0A3DD3BE22C9A95664756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|
package/dist/mjs/package.json
CHANGED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Builder - Constructs the working API from declarations
|
|
3
|
+
*
|
|
4
|
+
* This module is responsible for creating the actual working API
|
|
5
|
+
* from the schema declarations when attached to a FormulaEngine.
|
|
6
|
+
*/
|
|
7
|
+
import type { FormulaEngine } from "../engine";
|
|
8
|
+
import type { Declaration, Api } from "./api";
|
|
9
|
+
import type { ApiSchemaManager } from "../managers/api-schema-manager";
|
|
10
|
+
/**
|
|
11
|
+
* Build the working API surface from declarations
|
|
12
|
+
*
|
|
13
|
+
* This creates TableOrm and CellOrm instances for each declared schema
|
|
14
|
+
* and binds the custom methods to them.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildApiFromDeclaration(engine: FormulaEngine<any, any>, declaration: Declaration, schemaManager: ApiSchemaManager): Api;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Helper utilities for row/object conversion and filtering
|
|
3
|
+
*/
|
|
4
|
+
import type { CellAddress, SerializedCellValue, TableDefinition } from "../types";
|
|
5
|
+
import type { FormulaEngine } from "../engine";
|
|
6
|
+
export type ParseFunction<TCellMetadata = unknown> = (value: unknown, metadata: TCellMetadata) => unknown;
|
|
7
|
+
export type TableSchemaHeaders<TCellMetadata = unknown> = Record<string, {
|
|
8
|
+
parse: ParseFunction<TCellMetadata>;
|
|
9
|
+
index: number;
|
|
10
|
+
}>;
|
|
11
|
+
/**
|
|
12
|
+
* Convert a spreadsheet row to a typed object using header parsers
|
|
13
|
+
*/
|
|
14
|
+
export declare function rowToObject<TItem extends Record<string, unknown>>(engine: FormulaEngine<any, any>, table: TableDefinition, rowIndex: number, headers: TableSchemaHeaders, getCellMetadata?: (cell: CellAddress) => unknown): TItem;
|
|
15
|
+
/**
|
|
16
|
+
* Convert a typed object to cell values based on headers
|
|
17
|
+
*/
|
|
18
|
+
export declare function objectToRowValues<TItem extends Record<string, unknown>>(obj: TItem, headers: TableSchemaHeaders): Map<number, SerializedCellValue>;
|
|
19
|
+
/**
|
|
20
|
+
* Check if an object matches a filter predicate
|
|
21
|
+
*/
|
|
22
|
+
export declare function matchesFilter<TItem extends Record<string, unknown>>(item: TItem, filter: Partial<TItem>): boolean;
|
|
23
|
+
/**
|
|
24
|
+
* Get the number of data rows in a table (excluding header)
|
|
25
|
+
*/
|
|
26
|
+
export declare function getTableRowCount(engine: FormulaEngine<any, any>, table: TableDefinition): number;
|
|
27
|
+
/**
|
|
28
|
+
* Get the next empty row index for appending data
|
|
29
|
+
*/
|
|
30
|
+
export declare function getNextEmptyRow(engine: FormulaEngine<any, any>, table: TableDefinition): number;
|
|
31
|
+
/**
|
|
32
|
+
* Iterate over all data rows in a table
|
|
33
|
+
*/
|
|
34
|
+
export declare function iterateTableRows(engine: FormulaEngine<any, any>, table: TableDefinition): Generator<{
|
|
35
|
+
rowIndex: number;
|
|
36
|
+
isEmpty: boolean;
|
|
37
|
+
}>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import type { CellAddress } from "../types";
|
|
2
|
+
import type { CellOrm } from "./cell-orm";
|
|
3
|
+
import type { TableOrm } from "./table-orm";
|
|
4
|
+
/**
|
|
5
|
+
* Define an API schema for the FormulaEngine.
|
|
6
|
+
*
|
|
7
|
+
* The returned object contains:
|
|
8
|
+
* - `declaration`: The schema definitions for tables and cells
|
|
9
|
+
* - `api`: A type-only placeholder (undefined at runtime) for TypeScript inference
|
|
10
|
+
*
|
|
11
|
+
* The actual working API is only available through `engine.api` after
|
|
12
|
+
* attaching the definition to a FormulaEngine instance.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const myApi = defineApi<CellMetadata>()
|
|
17
|
+
* .addTableApi("users", { workbookName: "wb1", tableName: "users" }, headers, methods)
|
|
18
|
+
* .addCellApi("config", cellAddress, parse, methods);
|
|
19
|
+
*
|
|
20
|
+
* const engine = new FormulaEngine(myApi);
|
|
21
|
+
* engine.api.users.get(1); // Works!
|
|
22
|
+
* myApi.api.users.get(1); // Error: api is undefined at runtime
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare function defineApi<TCellMetadata = unknown, TCurrentApi extends Record<string, Record<string, (...args: any[]) => any>> = Record<string, Record<string, (...args: any[]) => any>>, TCurrentDeclaration extends Record<string, TableApi | CellApi> = Record<string, TableApi | CellApi>>(): CreateApi<TCellMetadata, TCurrentApi, TCurrentDeclaration>;
|
|
26
|
+
export declare const createApi: typeof defineApi;
|
|
27
|
+
type ParseFunction<TCellMetadata> = (value: unknown, metadata: TCellMetadata) => unknown;
|
|
28
|
+
export interface TableApi {
|
|
29
|
+
type: "table";
|
|
30
|
+
headers: Headers<unknown>;
|
|
31
|
+
tableName: string;
|
|
32
|
+
workbookName: string;
|
|
33
|
+
methods: TableMethods<Record<string, unknown>>;
|
|
34
|
+
}
|
|
35
|
+
export interface CellApi {
|
|
36
|
+
type: "cell";
|
|
37
|
+
cellAddress: CellAddress;
|
|
38
|
+
parse: (value: unknown, metadata: unknown) => unknown;
|
|
39
|
+
methods: CellMethods<unknown>;
|
|
40
|
+
}
|
|
41
|
+
type Headers<TCellMetadata> = Record<string, {
|
|
42
|
+
parse: ParseFunction<TCellMetadata>;
|
|
43
|
+
index: number;
|
|
44
|
+
}>;
|
|
45
|
+
type TableMethods<TItem extends Record<string, unknown>> = Record<string, (this: TableOrm<TItem>, ...args: any[]) => any>;
|
|
46
|
+
type CellMethods<TValue> = Record<string, (this: CellOrm<TValue>, ...args: any[]) => any>;
|
|
47
|
+
export type Declaration = Record<string, TableApi | CellApi>;
|
|
48
|
+
export type Api = Record<string, Record<string, (...args: any[]) => any>>;
|
|
49
|
+
export type CreateApi<TCellMetadata, TCurrentApi extends Api, TCurrentDeclaration extends Declaration> = {
|
|
50
|
+
addTableApi<T extends string, THeaders extends Headers<TCellMetadata>, TMethods extends TableMethods<{
|
|
51
|
+
[K in keyof THeaders]: ReturnType<THeaders[K]["parse"]>;
|
|
52
|
+
}>>(namespace: T, address: {
|
|
53
|
+
workbookName: string;
|
|
54
|
+
tableName: string;
|
|
55
|
+
}, headers: THeaders, methods: TMethods): CreateApi<TCellMetadata, TCurrentApi & {
|
|
56
|
+
[K in T]: {
|
|
57
|
+
[M in keyof TMethods]: (...args: Parameters<TMethods[M]>) => ReturnType<TMethods[M]>;
|
|
58
|
+
};
|
|
59
|
+
}, TCurrentDeclaration & {
|
|
60
|
+
[K in T]: {
|
|
61
|
+
type: "table";
|
|
62
|
+
tableName: string;
|
|
63
|
+
workbookName: string;
|
|
64
|
+
headers: THeaders;
|
|
65
|
+
methods: TMethods;
|
|
66
|
+
};
|
|
67
|
+
}>;
|
|
68
|
+
addCellApi<T extends string, TValue, TMethods extends CellMethods<TValue>>(namespace: T, cellAddress: CellAddress, parse: (value: unknown, metadata: TCellMetadata) => TValue, methods: TMethods): CreateApi<TCellMetadata, TCurrentApi & {
|
|
69
|
+
[K in T]: {
|
|
70
|
+
[M in keyof TMethods]: (...args: Parameters<TMethods[M]>) => ReturnType<TMethods[M]>;
|
|
71
|
+
};
|
|
72
|
+
}, TCurrentDeclaration & {
|
|
73
|
+
[K in T]: {
|
|
74
|
+
type: "cell";
|
|
75
|
+
cellAddress: CellAddress;
|
|
76
|
+
parse: (value: unknown, metadata: unknown) => unknown;
|
|
77
|
+
methods: TMethods;
|
|
78
|
+
};
|
|
79
|
+
}>;
|
|
80
|
+
api: TCurrentApi;
|
|
81
|
+
declaration: TCurrentDeclaration;
|
|
82
|
+
};
|
|
83
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CellOrm - Object-Relational Mapping for single cell data
|
|
3
|
+
*
|
|
4
|
+
* Provides read/write operations for a single cell with type-safe access.
|
|
5
|
+
* Used as the `this` context for custom cell API methods.
|
|
6
|
+
*/
|
|
7
|
+
import type { CellAddress } from "../types";
|
|
8
|
+
import type { FormulaEngine } from "../engine";
|
|
9
|
+
export type CellParseFunction<TCellMetadata, TValue> = (value: unknown, metadata: TCellMetadata) => TValue;
|
|
10
|
+
export declare class CellOrm<TValue, TCellMetadata = unknown> {
|
|
11
|
+
private engine;
|
|
12
|
+
private cellAddress;
|
|
13
|
+
private parser;
|
|
14
|
+
private namespace;
|
|
15
|
+
constructor(engine: FormulaEngine<any, any>, cellAddress: CellAddress, parser: CellParseFunction<TCellMetadata, TValue>, namespace: string);
|
|
16
|
+
/**
|
|
17
|
+
* Read the cell value and parse it using the schema's parse function
|
|
18
|
+
*/
|
|
19
|
+
read(): TValue;
|
|
20
|
+
/**
|
|
21
|
+
* Write a value to the cell
|
|
22
|
+
* The value should be the parsed type - it will be converted to a serializable value
|
|
23
|
+
*/
|
|
24
|
+
write(value: TValue): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get the cell address
|
|
27
|
+
*/
|
|
28
|
+
getAddress(): CellAddress;
|
|
29
|
+
}
|