@ricsam/formula-engine 0.0.6 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,236 @@
1
+ // src/core/managers/copy-manager.ts
2
+ import { parseFormula } from "../../parser/parser.mjs";
3
+ import { astToString } from "../../parser/formatter.mjs";
4
+ import { transformAST } from "../ast-traverser.mjs";
5
+
6
+ class CopyManager {
7
+ workbookManager;
8
+ evaluationManager;
9
+ styleManager;
10
+ constructor(workbookManager, evaluationManager, styleManager) {
11
+ this.workbookManager = workbookManager;
12
+ this.evaluationManager = evaluationManager;
13
+ this.styleManager = styleManager;
14
+ }
15
+ copyCells(source, target, options) {
16
+ if (source.length === 0) {
17
+ return;
18
+ }
19
+ const topLeft = this.findTopLeft(source);
20
+ const rowOffset = target.rowIndex - topLeft.rowIndex;
21
+ const colOffset = target.colIndex - topLeft.colIndex;
22
+ for (const sourceCell of source) {
23
+ const targetCell = {
24
+ workbookName: target.workbookName,
25
+ sheetName: target.sheetName,
26
+ colIndex: sourceCell.colIndex + colOffset,
27
+ rowIndex: sourceCell.rowIndex + rowOffset
28
+ };
29
+ this.copyCellContent(sourceCell, targetCell, topLeft, options);
30
+ }
31
+ if (options.formatting) {
32
+ this.copyFormatting(source, topLeft, target, rowOffset, colOffset);
33
+ }
34
+ if (options.cut) {
35
+ this.clearSourceCells(source);
36
+ }
37
+ }
38
+ findTopLeft(cells) {
39
+ let minRow = Infinity;
40
+ let minCol = Infinity;
41
+ let topLeftCell = cells[0];
42
+ for (const cell of cells) {
43
+ if (cell.rowIndex < minRow || cell.rowIndex === minRow && cell.colIndex < minCol) {
44
+ minRow = cell.rowIndex;
45
+ minCol = cell.colIndex;
46
+ topLeftCell = cell;
47
+ }
48
+ }
49
+ return topLeftCell;
50
+ }
51
+ copyCellContent(sourceCell, targetCell, sourceTopLeft, options) {
52
+ const sheet = this.workbookManager.getSheet({
53
+ workbookName: sourceCell.workbookName,
54
+ sheetName: sourceCell.sheetName
55
+ });
56
+ if (!sheet) {
57
+ return;
58
+ }
59
+ const key = `${String.fromCharCode(65 + sourceCell.colIndex)}${sourceCell.rowIndex + 1}`;
60
+ const cellContent = sheet.content.get(key);
61
+ if (!cellContent) {
62
+ return;
63
+ }
64
+ let targetContent;
65
+ if (options.type === "value") {
66
+ const evalResult = this.evaluationManager.getCellEvaluationResult(sourceCell);
67
+ if (!evalResult || evalResult.type !== "value") {
68
+ targetContent = cellContent;
69
+ } else {
70
+ const result = evalResult.result;
71
+ if (result.type === "number") {
72
+ targetContent = result.value;
73
+ } else if (result.type === "string") {
74
+ targetContent = result.value;
75
+ } else if (result.type === "boolean") {
76
+ targetContent = result.value;
77
+ } else {
78
+ targetContent = cellContent;
79
+ }
80
+ }
81
+ } else {
82
+ if (typeof cellContent === "string" && cellContent.startsWith("=")) {
83
+ targetContent = this.adjustFormulaReferences(cellContent, {
84
+ colIndex: sourceCell.colIndex,
85
+ rowIndex: sourceCell.rowIndex
86
+ }, {
87
+ colIndex: targetCell.colIndex,
88
+ rowIndex: targetCell.rowIndex
89
+ });
90
+ } else {
91
+ targetContent = cellContent;
92
+ }
93
+ }
94
+ const targetSheet = this.workbookManager.getSheet({
95
+ workbookName: targetCell.workbookName,
96
+ sheetName: targetCell.sheetName
97
+ });
98
+ if (targetSheet) {
99
+ const targetKey = `${String.fromCharCode(65 + targetCell.colIndex)}${targetCell.rowIndex + 1}`;
100
+ targetSheet.content.set(targetKey, targetContent);
101
+ }
102
+ }
103
+ adjustFormulaReferences(formula, sourceAddress, targetAddress) {
104
+ try {
105
+ const ast = parseFormula(formula.slice(1));
106
+ const rowDelta = targetAddress.rowIndex - sourceAddress.rowIndex;
107
+ const colDelta = targetAddress.colIndex - sourceAddress.colIndex;
108
+ const adjustedAst = transformAST(ast, (node) => {
109
+ if (node.type === "reference") {
110
+ const refNode = node;
111
+ return {
112
+ ...refNode,
113
+ address: {
114
+ colIndex: refNode.isAbsolute.col ? refNode.address.colIndex : refNode.address.colIndex + colDelta,
115
+ rowIndex: refNode.isAbsolute.row ? refNode.address.rowIndex : refNode.address.rowIndex + rowDelta
116
+ }
117
+ };
118
+ } else if (node.type === "range") {
119
+ const rangeNode = node;
120
+ return {
121
+ ...rangeNode,
122
+ range: {
123
+ start: {
124
+ col: rangeNode.isAbsolute.start.col ? rangeNode.range.start.col : rangeNode.range.start.col + colDelta,
125
+ row: rangeNode.isAbsolute.start.row ? rangeNode.range.start.row : rangeNode.range.start.row + rowDelta
126
+ },
127
+ end: {
128
+ col: rangeNode.range.end.col.type === "number" ? rangeNode.isAbsolute.end.col ? rangeNode.range.end.col : {
129
+ type: "number",
130
+ value: rangeNode.range.end.col.value + colDelta
131
+ } : rangeNode.range.end.col,
132
+ row: rangeNode.range.end.row.type === "number" ? rangeNode.isAbsolute.end.row ? rangeNode.range.end.row : {
133
+ type: "number",
134
+ value: rangeNode.range.end.row.value + rowDelta
135
+ } : rangeNode.range.end.row
136
+ }
137
+ }
138
+ };
139
+ }
140
+ return node;
141
+ });
142
+ return `=${astToString(adjustedAst)}`;
143
+ } catch (error) {
144
+ console.warn("Failed to adjust formula references:", error);
145
+ return formula;
146
+ }
147
+ }
148
+ copyFormatting(sourceCells, sourceTopLeft, target, rowOffset, colOffset) {
149
+ const allConditionalStyles = this.styleManager.getAllConditionalStyles();
150
+ const allCellStyles = this.styleManager.getAllCellStyles();
151
+ const sourceRange = this.getBoundingBox(sourceCells);
152
+ for (const style of allConditionalStyles) {
153
+ if (style.area.workbookName === sourceTopLeft.workbookName && style.area.sheetName === sourceTopLeft.sheetName && this.rangesIntersect(style.area.range, sourceRange)) {
154
+ const newStyle = {
155
+ area: {
156
+ workbookName: target.workbookName,
157
+ sheetName: target.sheetName,
158
+ range: this.adjustRange(style.area.range, rowOffset, colOffset)
159
+ },
160
+ condition: style.condition
161
+ };
162
+ this.styleManager.addConditionalStyle(newStyle);
163
+ }
164
+ }
165
+ for (const style of allCellStyles) {
166
+ if (style.area.workbookName === sourceTopLeft.workbookName && style.area.sheetName === sourceTopLeft.sheetName && this.rangesIntersect(style.area.range, sourceRange)) {
167
+ const newStyle = {
168
+ area: {
169
+ workbookName: target.workbookName,
170
+ sheetName: target.sheetName,
171
+ range: this.adjustRange(style.area.range, rowOffset, colOffset)
172
+ },
173
+ style: style.style
174
+ };
175
+ this.styleManager.addCellStyle(newStyle);
176
+ }
177
+ }
178
+ }
179
+ getBoundingBox(cells) {
180
+ let minRow = Infinity;
181
+ let maxRow = -Infinity;
182
+ let minCol = Infinity;
183
+ let maxCol = -Infinity;
184
+ for (const cell of cells) {
185
+ minRow = Math.min(minRow, cell.rowIndex);
186
+ maxRow = Math.max(maxRow, cell.rowIndex);
187
+ minCol = Math.min(minCol, cell.colIndex);
188
+ maxCol = Math.max(maxCol, cell.colIndex);
189
+ }
190
+ return {
191
+ start: { col: minCol, row: minRow },
192
+ end: {
193
+ col: { type: "number", value: maxCol },
194
+ row: { type: "number", value: maxRow }
195
+ }
196
+ };
197
+ }
198
+ rangesIntersect(range1, range2) {
199
+ const r1EndCol = range1.end.col.type === "number" ? range1.end.col.value : Infinity;
200
+ const r1EndRow = range1.end.row.type === "number" ? range1.end.row.value : Infinity;
201
+ const r2EndCol = range2.end.col.type === "number" ? range2.end.col.value : Infinity;
202
+ const r2EndRow = range2.end.row.type === "number" ? range2.end.row.value : Infinity;
203
+ const colOverlap = range1.start.col <= r2EndCol && range2.start.col <= r1EndCol;
204
+ const rowOverlap = range1.start.row <= r2EndRow && range2.start.row <= r1EndRow;
205
+ return colOverlap && rowOverlap;
206
+ }
207
+ adjustRange(range, rowOffset, colOffset) {
208
+ return {
209
+ start: {
210
+ col: range.start.col + colOffset,
211
+ row: range.start.row + rowOffset
212
+ },
213
+ end: {
214
+ col: range.end.col.type === "number" ? { type: "number", value: range.end.col.value + colOffset } : range.end.col,
215
+ row: range.end.row.type === "number" ? { type: "number", value: range.end.row.value + rowOffset } : range.end.row
216
+ }
217
+ };
218
+ }
219
+ clearSourceCells(cells) {
220
+ for (const cell of cells) {
221
+ const sheet = this.workbookManager.getSheet({
222
+ workbookName: cell.workbookName,
223
+ sheetName: cell.sheetName
224
+ });
225
+ if (sheet) {
226
+ const key = `${String.fromCharCode(65 + cell.colIndex)}${cell.rowIndex + 1}`;
227
+ sheet.content.delete(key);
228
+ }
229
+ }
230
+ }
231
+ }
232
+ export {
233
+ CopyManager
234
+ };
235
+
236
+ //# debugId=8CA951C1BABE115764756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/core/managers/copy-manager.ts"],
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 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 { isCellInRange } from \"../utils.mjs\";\n\nexport class CopyManager {\n constructor(\n private workbookManager: WorkbookManager,\n private evaluationManager: EvaluationManager,\n private styleManager: StyleManager\n ) {}\n\n /**\n * Copy cells from source to target\n */\n copyCells(\n source: CellAddress[],\n target: CellAddress,\n options: CopyCellsOptions\n ): void {\n if (source.length === 0) {\n return;\n }\n\n // Find top-left cell of source (minimum row/col indices)\n const topLeft = this.findTopLeft(source);\n\n // Calculate offset from source top-left to target\n const rowOffset = target.rowIndex - topLeft.rowIndex;\n const colOffset = target.colIndex - topLeft.colIndex;\n\n // Copy cell contents\n for (const sourceCell of source) {\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.copyCellContent(sourceCell, targetCell, topLeft, options);\n }\n\n // Copy formatting if requested\n if (options.formatting) {\n this.copyFormatting(source, topLeft, target, rowOffset, colOffset);\n }\n\n // Clear source cells if cut\n if (options.cut) {\n this.clearSourceCells(source);\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 * 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\n if (options.type === \"value\") {\n // Copy evaluated value\n const evalResult = 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\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 */\n private copyFormatting(\n sourceCells: CellAddress[],\n sourceTopLeft: CellAddress,\n target: CellAddress,\n rowOffset: number,\n colOffset: number\n ): void {\n // Get all styles for the source workbook\n const allConditionalStyles = this.styleManager.getAllConditionalStyles();\n const allCellStyles = this.styleManager.getAllCellStyles();\n\n // Find styles that intersect with source cells\n const sourceRange = this.getBoundingBox(sourceCells);\n\n // Copy conditional styles\n for (const style of allConditionalStyles) {\n if (\n style.area.workbookName === sourceTopLeft.workbookName &&\n style.area.sheetName === sourceTopLeft.sheetName &&\n this.rangesIntersect(style.area.range, sourceRange)\n ) {\n // Create a new style with adjusted range\n const newStyle: ConditionalStyle = {\n area: {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(style.area.range, rowOffset, colOffset),\n },\n condition: style.condition,\n };\n this.styleManager.addConditionalStyle(newStyle);\n }\n }\n\n // Copy cell styles\n for (const style of allCellStyles) {\n if (\n style.area.workbookName === sourceTopLeft.workbookName &&\n style.area.sheetName === sourceTopLeft.sheetName &&\n this.rangesIntersect(style.area.range, sourceRange)\n ) {\n // Create a new style with adjusted range\n const newStyle: DirectCellStyle = {\n area: {\n workbookName: target.workbookName,\n sheetName: target.sheetName,\n range: this.adjustRange(style.area.range, rowOffset, colOffset),\n },\n style: style.style,\n };\n this.styleManager.addCellStyle(newStyle);\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 * Check if two ranges intersect\n */\n private rangesIntersect(\n range1: SpreadsheetRange,\n range2: SpreadsheetRange\n ): boolean {\n // Get finite end values\n const r1EndCol =\n range1.end.col.type === \"number\" ? range1.end.col.value : Infinity;\n const r1EndRow =\n range1.end.row.type === \"number\" ? range1.end.row.value : Infinity;\n const r2EndCol =\n range2.end.col.type === \"number\" ? range2.end.col.value : Infinity;\n const r2EndRow =\n range2.end.row.type === \"number\" ? range2.end.row.value : Infinity;\n\n // Check if ranges overlap\n const colOverlap =\n range1.start.col <= r2EndCol && range2.start.col <= r1EndCol;\n const rowOverlap =\n range1.start.row <= r2EndRow && range2.start.row <= r1EndRow;\n\n return colOverlap && rowOverlap;\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 const sheet = this.workbookManager.getSheet({\n workbookName: cell.workbookName,\n sheetName: cell.sheetName,\n });\n\n if (sheet) {\n const key = `${String.fromCharCode(65 + cell.colIndex)}${\n cell.rowIndex + 1\n }`;\n sheet.content.delete(key);\n }\n }\n }\n}\n\n"
6
+ ],
7
+ "mappings": ";AAgBA;AACA;AACA;AAAA;AAIO,MAAM,YAAY;AAAA,EAEb;AAAA,EACA;AAAA,EACA;AAAA,EAHV,WAAW,CACD,iBACA,mBACA,cACR;AAAA,IAHQ;AAAA,IACA;AAAA,IACA;AAAA;AAAA,EAMV,SAAS,CACP,QACA,QACA,SACM;AAAA,IACN,IAAI,OAAO,WAAW,GAAG;AAAA,MACvB;AAAA,IACF;AAAA,IAGA,MAAM,UAAU,KAAK,YAAY,MAAM;AAAA,IAGvC,MAAM,YAAY,OAAO,WAAW,QAAQ;AAAA,IAC5C,MAAM,YAAY,OAAO,WAAW,QAAQ;AAAA,IAG5C,WAAW,cAAc,QAAQ;AAAA,MAC/B,MAAM,aAA0B;AAAA,QAC9B,cAAc,OAAO;AAAA,QACrB,WAAW,OAAO;AAAA,QAClB,UAAU,WAAW,WAAW;AAAA,QAChC,UAAU,WAAW,WAAW;AAAA,MAClC;AAAA,MAEA,KAAK,gBAAgB,YAAY,YAAY,SAAS,OAAO;AAAA,IAC/D;AAAA,IAGA,IAAI,QAAQ,YAAY;AAAA,MACtB,KAAK,eAAe,QAAQ,SAAS,QAAQ,WAAW,SAAS;AAAA,IACnE;AAAA,IAGA,IAAI,QAAQ,KAAK;AAAA,MACf,KAAK,iBAAiB,MAAM;AAAA,IAC9B;AAAA;AAAA,EAMM,WAAW,CAAC,OAAmC;AAAA,IACrD,IAAI,SAAS;AAAA,IACb,IAAI,SAAS;AAAA,IACb,IAAI,cAAc,MAAM;AAAA,IAExB,WAAW,QAAQ,OAAO;AAAA,MACxB,IACE,KAAK,WAAW,UACf,KAAK,aAAa,UAAU,KAAK,WAAW,QAC7C;AAAA,QACA,SAAS,KAAK;AAAA,QACd,SAAS,KAAK;AAAA,QACd,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,IAEA,OAAO;AAAA;AAAA,EAMD,eAAe,CACrB,YACA,YACA,eACA,SACM;AAAA,IACN,MAAM,QAAQ,KAAK,gBAAgB,SAAS;AAAA,MAC1C,cAAc,WAAW;AAAA,MACzB,WAAW,WAAW;AAAA,IACxB,CAAC;AAAA,IAED,IAAI,CAAC,OAAO;AAAA,MACV;AAAA,IACF;AAAA,IAEA,MAAM,MAAM,GAAG,OAAO,aAAa,KAAK,WAAW,QAAQ,IACzD,WAAW,WAAW;AAAA,IAExB,MAAM,cAAc,MAAM,QAAQ,IAAI,GAAG;AAAA,IAEzC,IAAI,CAAC,aAAa;AAAA,MAEhB;AAAA,IACF;AAAA,IAEA,IAAI;AAAA,IAEJ,IAAI,QAAQ,SAAS,SAAS;AAAA,MAE5B,MAAM,aAAa,KAAK,kBAAkB,wBAAwB,UAAU;AAAA,MAE5E,IAAI,CAAC,cAAc,WAAW,SAAS,SAAS;AAAA,QAE9C,gBAAgB;AAAA,MAClB,EAAO;AAAA,QAEL,MAAM,SAAS,WAAW;AAAA,QAC1B,IAAI,OAAO,SAAS,UAAU;AAAA,UAC5B,gBAAgB,OAAO;AAAA,QACzB,EAAO,SAAI,OAAO,SAAS,UAAU;AAAA,UACnC,gBAAgB,OAAO;AAAA,QACzB,EAAO,SAAI,OAAO,SAAS,WAAW;AAAA,UACpC,gBAAgB,OAAO;AAAA,QACzB,EAAO;AAAA,UAEL,gBAAgB;AAAA;AAAA;AAAA,IAGtB,EAAO;AAAA,MAEL,IAAI,OAAO,gBAAgB,YAAY,YAAY,WAAW,GAAG,GAAG;AAAA,QAElE,gBAAgB,KAAK,wBACnB,aACA;AAAA,UACE,UAAU,WAAW;AAAA,UACrB,UAAU,WAAW;AAAA,QACvB,GACA;AAAA,UACE,UAAU,WAAW;AAAA,UACrB,UAAU,WAAW;AAAA,QACvB,CACF;AAAA,MACF,EAAO;AAAA,QAEL,gBAAgB;AAAA;AAAA;AAAA,IAKpB,MAAM,cAAc,KAAK,gBAAgB,SAAS;AAAA,MAChD,cAAc,WAAW;AAAA,MACzB,WAAW,WAAW;AAAA,IACxB,CAAC;AAAA,IAED,IAAI,aAAa;AAAA,MACf,MAAM,YAAY,GAAG,OAAO,aAAa,KAAK,WAAW,QAAQ,IAC/D,WAAW,WAAW;AAAA,MAExB,YAAY,QAAQ,IAAI,WAAW,aAAa;AAAA,IAClD;AAAA;AAAA,EAOM,uBAAuB,CAC7B,SACA,eACA,eACQ;AAAA,IACR,IAAI;AAAA,MACF,MAAM,MAAM,aAAa,QAAQ,MAAM,CAAC,CAAC;AAAA,MAEzC,MAAM,WAAW,cAAc,WAAW,cAAc;AAAA,MACxD,MAAM,WAAW,cAAc,WAAW,cAAc;AAAA,MAExD,MAAM,cAAc,aAAa,KAAK,CAAC,SAAS;AAAA,QAC9C,IAAI,KAAK,SAAS,aAAa;AAAA,UAC7B,MAAM,UAAU;AAAA,UAChB,OAAO;AAAA,eACF;AAAA,YACH,SAAS;AAAA,cACP,UAAU,QAAQ,WAAW,MACzB,QAAQ,QAAQ,WAChB,QAAQ,QAAQ,WAAW;AAAA,cAC/B,UAAU,QAAQ,WAAW,MACzB,QAAQ,QAAQ,WAChB,QAAQ,QAAQ,WAAW;AAAA,YACjC;AAAA,UACF;AAAA,QACF,EAAO,SAAI,KAAK,SAAS,SAAS;AAAA,UAChC,MAAM,YAAY;AAAA,UAClB,OAAO;AAAA,eACF;AAAA,YACH,OAAO;AAAA,cACL,OAAO;AAAA,gBACL,KAAK,UAAU,WAAW,MAAM,MAC5B,UAAU,MAAM,MAAM,MACtB,UAAU,MAAM,MAAM,MAAM;AAAA,gBAChC,KAAK,UAAU,WAAW,MAAM,MAC5B,UAAU,MAAM,MAAM,MACtB,UAAU,MAAM,MAAM,MAAM;AAAA,cAClC;AAAA,cACA,KAAK;AAAA,gBACH,KACE,UAAU,MAAM,IAAI,IAAI,SAAS,WAC7B,UAAU,WAAW,IAAI,MACvB,UAAU,MAAM,IAAI,MACpB;AAAA,kBACE,MAAM;AAAA,kBACN,OAAO,UAAU,MAAM,IAAI,IAAI,QAAQ;AAAA,gBACzC,IACF,UAAU,MAAM,IAAI;AAAA,gBAC1B,KACE,UAAU,MAAM,IAAI,IAAI,SAAS,WAC7B,UAAU,WAAW,IAAI,MACvB,UAAU,MAAM,IAAI,MACpB;AAAA,kBACE,MAAM;AAAA,kBACN,OAAO,UAAU,MAAM,IAAI,IAAI,QAAQ;AAAA,gBACzC,IACF,UAAU,MAAM,IAAI;AAAA,cAC5B;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,QACA,OAAO;AAAA,OACR;AAAA,MAED,OAAO,IAAI,YAAY,WAAW;AAAA,MAClC,OAAO,OAAO;AAAA,MAEd,QAAQ,KAAK,wCAAwC,KAAK;AAAA,MAC1D,OAAO;AAAA;AAAA;AAAA,EAOH,cAAc,CACpB,aACA,eACA,QACA,WACA,WACM;AAAA,IAEN,MAAM,uBAAuB,KAAK,aAAa,wBAAwB;AAAA,IACvE,MAAM,gBAAgB,KAAK,aAAa,iBAAiB;AAAA,IAGzD,MAAM,cAAc,KAAK,eAAe,WAAW;AAAA,IAGnD,WAAW,SAAS,sBAAsB;AAAA,MACxC,IACE,MAAM,KAAK,iBAAiB,cAAc,gBAC1C,MAAM,KAAK,cAAc,cAAc,aACvC,KAAK,gBAAgB,MAAM,KAAK,OAAO,WAAW,GAClD;AAAA,QAEA,MAAM,WAA6B;AAAA,UACjC,MAAM;AAAA,YACJ,cAAc,OAAO;AAAA,YACrB,WAAW,OAAO;AAAA,YAClB,OAAO,KAAK,YAAY,MAAM,KAAK,OAAO,WAAW,SAAS;AAAA,UAChE;AAAA,UACA,WAAW,MAAM;AAAA,QACnB;AAAA,QACA,KAAK,aAAa,oBAAoB,QAAQ;AAAA,MAChD;AAAA,IACF;AAAA,IAGA,WAAW,SAAS,eAAe;AAAA,MACjC,IACE,MAAM,KAAK,iBAAiB,cAAc,gBAC1C,MAAM,KAAK,cAAc,cAAc,aACvC,KAAK,gBAAgB,MAAM,KAAK,OAAO,WAAW,GAClD;AAAA,QAEA,MAAM,WAA4B;AAAA,UAChC,MAAM;AAAA,YACJ,cAAc,OAAO;AAAA,YACrB,WAAW,OAAO;AAAA,YAClB,OAAO,KAAK,YAAY,MAAM,KAAK,OAAO,WAAW,SAAS;AAAA,UAChE;AAAA,UACA,OAAO,MAAM;AAAA,QACf;AAAA,QACA,KAAK,aAAa,aAAa,QAAQ;AAAA,MACzC;AAAA,IACF;AAAA;AAAA,EAMM,cAAc,CAAC,OAAwC;AAAA,IAC7D,IAAI,SAAS;AAAA,IACb,IAAI,SAAS;AAAA,IACb,IAAI,SAAS;AAAA,IACb,IAAI,SAAS;AAAA,IAEb,WAAW,QAAQ,OAAO;AAAA,MACxB,SAAS,KAAK,IAAI,QAAQ,KAAK,QAAQ;AAAA,MACvC,SAAS,KAAK,IAAI,QAAQ,KAAK,QAAQ;AAAA,MACvC,SAAS,KAAK,IAAI,QAAQ,KAAK,QAAQ;AAAA,MACvC,SAAS,KAAK,IAAI,QAAQ,KAAK,QAAQ;AAAA,IACzC;AAAA,IAEA,OAAO;AAAA,MACL,OAAO,EAAE,KAAK,QAAQ,KAAK,OAAO;AAAA,MAClC,KAAK;AAAA,QACH,KAAK,EAAE,MAAM,UAAU,OAAO,OAAO;AAAA,QACrC,KAAK,EAAE,MAAM,UAAU,OAAO,OAAO;AAAA,MACvC;AAAA,IACF;AAAA;AAAA,EAMM,eAAe,CACrB,QACA,QACS;AAAA,IAET,MAAM,WACJ,OAAO,IAAI,IAAI,SAAS,WAAW,OAAO,IAAI,IAAI,QAAQ;AAAA,IAC5D,MAAM,WACJ,OAAO,IAAI,IAAI,SAAS,WAAW,OAAO,IAAI,IAAI,QAAQ;AAAA,IAC5D,MAAM,WACJ,OAAO,IAAI,IAAI,SAAS,WAAW,OAAO,IAAI,IAAI,QAAQ;AAAA,IAC5D,MAAM,WACJ,OAAO,IAAI,IAAI,SAAS,WAAW,OAAO,IAAI,IAAI,QAAQ;AAAA,IAG5D,MAAM,aACJ,OAAO,MAAM,OAAO,YAAY,OAAO,MAAM,OAAO;AAAA,IACtD,MAAM,aACJ,OAAO,MAAM,OAAO,YAAY,OAAO,MAAM,OAAO;AAAA,IAEtD,OAAO,cAAc;AAAA;AAAA,EAMf,WAAW,CACjB,OACA,WACA,WACkB;AAAA,IAClB,OAAO;AAAA,MACL,OAAO;AAAA,QACL,KAAK,MAAM,MAAM,MAAM;AAAA,QACvB,KAAK,MAAM,MAAM,MAAM;AAAA,MACzB;AAAA,MACA,KAAK;AAAA,QACH,KACE,MAAM,IAAI,IAAI,SAAS,WACnB,EAAE,MAAM,UAAU,OAAO,MAAM,IAAI,IAAI,QAAQ,UAAU,IACzD,MAAM,IAAI;AAAA,QAChB,KACE,MAAM,IAAI,IAAI,SAAS,WACnB,EAAE,MAAM,UAAU,OAAO,MAAM,IAAI,IAAI,QAAQ,UAAU,IACzD,MAAM,IAAI;AAAA,MAClB;AAAA,IACF;AAAA;AAAA,EAMM,gBAAgB,CAAC,OAA4B;AAAA,IACnD,WAAW,QAAQ,OAAO;AAAA,MACxB,MAAM,QAAQ,KAAK,gBAAgB,SAAS;AAAA,QAC1C,cAAc,KAAK;AAAA,QACnB,WAAW,KAAK;AAAA,MAClB,CAAC;AAAA,MAED,IAAI,OAAO;AAAA,QACT,MAAM,MAAM,GAAG,OAAO,aAAa,KAAK,KAAK,QAAQ,IACnD,KAAK,WAAW;AAAA,QAElB,MAAM,QAAQ,OAAO,GAAG;AAAA,MAC1B;AAAA,IACF;AAAA;AAEJ;",
8
+ "debugId": "8CA951C1BABE115764756E2164756E21",
9
+ "names": []
10
+ }
@@ -139,10 +139,7 @@ class StyleManager {
139
139
  continue;
140
140
  }
141
141
  if (cellStyle.area.workbookName === cellAddress.workbookName && cellStyle.area.sheetName === cellAddress.sheetName && isCellInRange(cellAddress, cellStyle.area.range)) {
142
- return {
143
- backgroundColor: cellStyle.style.backgroundColor,
144
- color: cellStyle.style.color
145
- };
142
+ return cellStyle.style;
146
143
  }
147
144
  }
148
145
  for (const style of this.conditionalStyles) {
@@ -312,4 +309,4 @@ export {
312
309
  StyleManager
313
310
  };
314
311
 
315
- //# debugId=DB5713E9E5C6BAC564756E2164756E21
312
+ //# debugId=8904835F1301129164756E2164756E21
@@ -2,9 +2,9 @@
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/core/managers/style-manager.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * StyleManager - Manages conditional styling for cells\n */\n\nimport type {\n CellAddress,\n CellStyle,\n ConditionalStyle,\n DirectCellStyle,\n RangeAddress,\n SerializedCellValue,\n} from \"../types.mjs\";\nimport type { WorkbookManager } from \"./workbook-manager.mjs\";\nimport type { EvaluationManager } from \"./evaluation-manager.mjs\";\nimport { isCellInRange } from \"../utils.mjs\";\nimport {\n calculateGradientFactor,\n interpolateLCH,\n lchToHex,\n} from \"../utils/color-utils.mjs\";\n\nexport class StyleManager {\n private conditionalStyles: ConditionalStyle[] = [];\n private cellStyles: DirectCellStyle[] = [];\n\n constructor(\n private workbookManager: WorkbookManager,\n private evaluationManager: EvaluationManager\n ) {}\n\n /**\n * Add a conditional style rule\n */\n addConditionalStyle(style: ConditionalStyle): void {\n this.conditionalStyles.push(style);\n }\n\n /**\n * Remove a conditional style rule by index for a specific workbook\n */\n removeConditionalStyle(workbookName: string, index: number): boolean {\n const workbookStyles = this.conditionalStyles.filter(\n (style) => style.area.workbookName === workbookName\n );\n if (index < 0 || index >= workbookStyles.length) {\n return false;\n }\n // Find the actual index in the full array\n let currentIndex = 0;\n for (let i = 0; i < this.conditionalStyles.length; i++) {\n const style = this.conditionalStyles[i];\n if (style && style.area.workbookName === workbookName) {\n if (currentIndex === index) {\n this.conditionalStyles.splice(i, 1);\n return true;\n }\n currentIndex++;\n }\n }\n return false;\n }\n\n /**\n * Get all conditional styles for a workbook\n */\n getConditionalStyles(workbookName: string): ConditionalStyle[] {\n return this.conditionalStyles.filter(\n (style) => style && style.area && style.area.workbookName === workbookName\n );\n }\n\n /**\n * Add a direct cell style rule\n */\n addCellStyle(style: DirectCellStyle): void {\n this.cellStyles.push(style);\n }\n\n /**\n * Remove a direct cell style rule by index for a specific workbook\n */\n removeCellStyle(workbookName: string, index: number): boolean {\n const workbookStyles = this.cellStyles.filter(\n (style) => style && style.area && style.area.workbookName === workbookName\n );\n if (index < 0 || index >= workbookStyles.length) {\n return false;\n }\n // Find the actual index in the full array\n let currentIndex = 0;\n for (let i = 0; i < this.cellStyles.length; i++) {\n const style = this.cellStyles[i];\n if (style && style.area && style.area.workbookName === workbookName) {\n if (currentIndex === index) {\n this.cellStyles.splice(i, 1);\n return true;\n }\n currentIndex++;\n }\n }\n return false;\n }\n\n /**\n * Get all direct cell styles for a workbook\n */\n getCellStyles(workbookName: string): DirectCellStyle[] {\n return this.cellStyles.filter(\n (style) => style && style.area && style.area.workbookName === workbookName\n );\n }\n\n /**\n * Get all conditional styles across all workbooks (for serialization)\n */\n getAllConditionalStyles(): ConditionalStyle[] {\n return [...this.conditionalStyles];\n }\n\n /**\n * Get all cell styles (for serialization)\n */\n getAllCellStyles(): DirectCellStyle[] {\n return [...this.cellStyles];\n }\n\n /**\n * Reset all styles (for deserialization)\n */\n resetStyles(conditionalStyles?: ConditionalStyle[], cellStyles?: DirectCellStyle[]): void {\n this.conditionalStyles = conditionalStyles ? [...conditionalStyles] : [];\n this.cellStyles = cellStyles ? [...cellStyles] : [];\n }\n\n /**\n * Remove all styles for a workbook\n */\n removeWorkbookStyles(workbookName: string): void {\n this.conditionalStyles = this.conditionalStyles.filter(\n (style) => style.area.workbookName !== workbookName\n );\n this.cellStyles = this.cellStyles.filter(\n (style) => style.area.workbookName !== workbookName\n );\n }\n\n /**\n * Update workbook name in all style references\n */\n updateWorkbookName(oldName: string, newName: string): void {\n // Update conditional styles\n this.conditionalStyles = this.conditionalStyles.map((style) => {\n if (style.area.workbookName === oldName) {\n return {\n ...style,\n area: {\n ...style.area,\n workbookName: newName,\n },\n };\n }\n return style;\n });\n // Update cell styles\n this.cellStyles = this.cellStyles.map((style) => {\n if (style.area.workbookName === oldName) {\n return {\n ...style,\n area: {\n ...style.area,\n workbookName: newName,\n },\n };\n }\n return style;\n });\n }\n\n /**\n * Update sheet name in style references\n */\n updateSheetName(\n workbookName: string,\n oldSheetName: string,\n newSheetName: string\n ): void {\n // Update conditional styles\n this.conditionalStyles = this.conditionalStyles.map((style) => {\n if (\n style.area.workbookName === workbookName &&\n style.area.sheetName === oldSheetName\n ) {\n return {\n ...style,\n area: {\n ...style.area,\n sheetName: newSheetName,\n },\n };\n }\n return style;\n });\n // Update cell styles\n this.cellStyles = this.cellStyles.map((style) => {\n if (\n style.area.workbookName === workbookName &&\n style.area.sheetName === oldSheetName\n ) {\n return {\n ...style,\n area: {\n ...style.area,\n sheetName: newSheetName,\n },\n };\n }\n return style;\n });\n }\n\n /**\n * Remove styles that reference a deleted sheet\n */\n removeSheetStyles(workbookName: string, sheetName: string): void {\n this.conditionalStyles = this.conditionalStyles.filter(\n (style) =>\n !(\n style.area.workbookName === workbookName &&\n style.area.sheetName === sheetName\n )\n );\n this.cellStyles = this.cellStyles.filter(\n (style) =>\n !(\n style.area.workbookName === workbookName &&\n style.area.sheetName === sheetName\n )\n );\n }\n\n /**\n * Get the style for a specific cell\n * Returns the first matching style (first match wins)\n * Checks cellStyles first, then conditionalStyles\n */\n getCellStyle(cellAddress: CellAddress): CellStyle | undefined {\n // First check direct cell styles\n for (const cellStyle of this.cellStyles) {\n if (!cellStyle || !cellStyle.area) {\n continue;\n }\n if (\n cellStyle.area.workbookName === cellAddress.workbookName &&\n cellStyle.area.sheetName === cellAddress.sheetName &&\n isCellInRange(cellAddress, cellStyle.area.range)\n ) {\n return {\n backgroundColor: cellStyle.style.backgroundColor,\n color: cellStyle.style.color,\n };\n }\n }\n\n // Then check conditional styles\n for (const style of this.conditionalStyles) {\n if (!style || !style.area) {\n continue;\n }\n // Check if cell is in the style's area\n if (\n style.area.sheetName !== cellAddress.sheetName ||\n style.area.workbookName !== cellAddress.workbookName\n ) {\n continue;\n }\n\n if (!isCellInRange(cellAddress, style.area.range)) {\n continue;\n }\n\n // Cell is in area, evaluate condition\n if (style.condition.type === \"formula\") {\n const result = this.evaluateFormulaCondition(cellAddress, style);\n if (result) return result;\n } else {\n const result = this.evaluateGradientCondition(cellAddress, style);\n if (result) return result;\n }\n }\n\n return undefined;\n }\n\n /**\n * Evaluate a formula-based style condition\n */\n private evaluateFormulaCondition(\n cellAddress: CellAddress,\n style: ConditionalStyle\n ): CellStyle | undefined {\n if (style.condition.type !== \"formula\") {\n return undefined;\n }\n\n try {\n // Evaluate formula in context of the cell\n // evaluateFormula expects a full cell value (with = prefix for formulas)\n const formula = style.condition.formula.startsWith(\"=\")\n ? style.condition.formula\n : `=${style.condition.formula}`;\n \n const result = this.evaluationManager.evaluateFormula(\n formula,\n cellAddress\n );\n\n // Check if result is truthy\n const isTruthy =\n result === true ||\n result === \"TRUE\" ||\n (typeof result === \"number\" && result !== 0);\n\n if (isTruthy) {\n return {\n backgroundColor: lchToHex(style.condition.color),\n };\n }\n } catch (error) {\n // If formula evaluation fails, don't apply style\n console.warn(\"Failed to evaluate formula condition:\", error);\n }\n\n return undefined;\n }\n\n /**\n * Evaluate a gradient-based style condition\n */\n private evaluateGradientCondition(\n cellAddress: CellAddress,\n style: ConditionalStyle\n ): CellStyle | undefined {\n if (style.condition.type !== \"gradient\") {\n return undefined;\n }\n\n try {\n // Get the cell's evaluation result\n const evalResult = this.evaluationManager.getCellEvaluationResult(cellAddress);\n if (!evalResult || evalResult.type !== \"value\") {\n return undefined;\n }\n if (evalResult.result.type !== \"number\") {\n return undefined;\n }\n const cellValue = evalResult.result.value;\n\n // Calculate min and max values for the gradient\n const { min: minValue, max: maxValue } = this.calculateGradientBounds(\n style,\n cellAddress\n );\n\n if (minValue === null || maxValue === null) {\n return undefined;\n }\n\n // Calculate interpolation factor\n const factor = calculateGradientFactor(cellValue, minValue, maxValue);\n\n // Interpolate between min and max colors\n const minColor = style.condition.min.color;\n const maxColor = style.condition.max.color;\n const interpolatedColor = interpolateLCH(minColor, maxColor, factor);\n\n return {\n backgroundColor: lchToHex(interpolatedColor),\n };\n } catch (error) {\n console.warn(\"Failed to evaluate gradient condition:\", error);\n return undefined;\n }\n }\n\n /**\n * Calculate min and max bounds for a gradient\n */\n private calculateGradientBounds(\n style: ConditionalStyle,\n cellAddress: CellAddress\n ): { min: number | null; max: number | null } {\n if (style.condition.type !== \"gradient\") {\n return { min: null, max: null };\n }\n\n const { min: minConfig, max: maxConfig } = style.condition;\n const topLeftCell: CellAddress = {\n workbookName: style.area.workbookName,\n sheetName: style.area.sheetName,\n colIndex: style.area.range.start.col,\n rowIndex: style.area.range.start.row,\n };\n\n // Calculate min value\n let minValue: number | null = null;\n if (minConfig.type === \"lowest_value\") {\n // Evaluate MIN(range) formula directly\n try {\n const rangeRef = this.getRangeReference(style.area);\n const result = this.evaluationManager.evaluateFormula(\n `=MIN(${rangeRef})`,\n topLeftCell\n );\n if (typeof result === \"number\") {\n minValue = result;\n }\n } catch (error) {\n console.warn(\"Failed to calculate MIN:\", error);\n }\n } else {\n // Evaluate valueFormula in context of area's top-left cell\n const formula = minConfig.valueFormula.startsWith(\"=\")\n ? minConfig.valueFormula\n : `=${minConfig.valueFormula}`;\n const result = this.evaluationManager.evaluateFormula(\n formula,\n topLeftCell\n );\n if (typeof result === \"number\") {\n minValue = result;\n }\n }\n\n // Calculate max value\n let maxValue: number | null = null;\n if (maxConfig.type === \"highest_value\") {\n // Evaluate MAX(range) formula directly\n try {\n const rangeRef = this.getRangeReference(style.area);\n const result = this.evaluationManager.evaluateFormula(\n `=MAX(${rangeRef})`,\n topLeftCell\n );\n if (typeof result === \"number\") {\n maxValue = result;\n }\n } catch (error) {\n console.warn(\"Failed to calculate MAX:\", error);\n }\n } else {\n // Evaluate valueFormula in context of area's top-left cell\n const formula = maxConfig.valueFormula.startsWith(\"=\")\n ? maxConfig.valueFormula\n : `=${maxConfig.valueFormula}`;\n const result = this.evaluationManager.evaluateFormula(\n formula,\n topLeftCell\n );\n if (typeof result === \"number\") {\n maxValue = result;\n }\n }\n\n return { min: minValue, max: maxValue };\n }\n\n /**\n * Get a range reference string from a RangeAddress\n * Follows CANONICAL_RANGES.md format:\n * - Closed: A5:D10\n * - Row-bounded (col-open): A5:10\n * - Col-bounded (row-open): A5:D\n * - Open both: A5:INFINITY\n */\n private getRangeReference(area: RangeAddress): string {\n const colToLetter = (col: number): string => {\n let result = \"\";\n let c = col;\n while (c >= 0) {\n result = String.fromCharCode(65 + (c % 26)) + result;\n c = Math.floor(c / 26) - 1;\n }\n return result;\n };\n\n const startCol = colToLetter(area.range.start.col);\n const startRow = area.range.start.row + 1; // Convert to 1-based\n\n const isColInfinity = area.range.end.col.type === \"infinity\";\n const isRowInfinity = area.range.end.row.type === \"infinity\";\n\n let rangeStr: string;\n\n if (isColInfinity && isRowInfinity) {\n // Open both: A5:INFINITY\n rangeStr = `${startCol}${startRow}:INFINITY`;\n } else if (isColInfinity) {\n // Row-bounded (col-open): A5:10\n if (area.range.end.row.type === \"number\") {\n const endRow = area.range.end.row.value + 1; // Convert to 1-based\n rangeStr = `${startCol}${startRow}:${endRow}`;\n } else {\n rangeStr = `${startCol}${startRow}:INFINITY`;\n }\n } else if (isRowInfinity) {\n // Col-bounded (row-open): A5:D\n if (area.range.end.col.type === \"number\") {\n const endCol = colToLetter(area.range.end.col.value);\n rangeStr = `${startCol}${startRow}:${endCol}`;\n } else {\n rangeStr = `${startCol}${startRow}:INFINITY`;\n }\n } else {\n // Closed rectangle: A5:D10\n if (area.range.end.col.type === \"number\" && area.range.end.row.type === \"number\") {\n const endCol = colToLetter(area.range.end.col.value);\n const endRow = area.range.end.row.value + 1; // Convert to 1-based\n rangeStr = `${startCol}${startRow}:${endCol}${endRow}`;\n } else {\n // Fallback to INFINITY if types don't match\n rangeStr = `${startCol}${startRow}:INFINITY`;\n }\n }\n\n // Quote sheet name if it contains spaces or special characters\n const needsQuotes = /[ '!]/.test(area.sheetName);\n const sheetRef = needsQuotes ? `'${area.sheetName.replace(/'/g, \"''\")}'` : area.sheetName;\n\n // Construct the full reference: [workbook]'sheet'!range\n return `[${area.workbookName}]${sheetRef}!${rangeStr}`;\n }\n}\n\n"
5
+ "/**\n * StyleManager - Manages conditional styling for cells\n */\n\nimport type {\n CellAddress,\n CellStyle,\n ConditionalStyle,\n DirectCellStyle,\n RangeAddress,\n SerializedCellValue,\n} from \"../types.mjs\";\nimport type { WorkbookManager } from \"./workbook-manager.mjs\";\nimport type { EvaluationManager } from \"./evaluation-manager.mjs\";\nimport { isCellInRange } from \"../utils.mjs\";\nimport {\n calculateGradientFactor,\n interpolateLCH,\n lchToHex,\n} from \"../utils/color-utils.mjs\";\n\nexport class StyleManager {\n private conditionalStyles: ConditionalStyle[] = [];\n private cellStyles: DirectCellStyle[] = [];\n\n constructor(\n private workbookManager: WorkbookManager,\n private evaluationManager: EvaluationManager\n ) {}\n\n /**\n * Add a conditional style rule\n */\n addConditionalStyle(style: ConditionalStyle): void {\n this.conditionalStyles.push(style);\n }\n\n /**\n * Remove a conditional style rule by index for a specific workbook\n */\n removeConditionalStyle(workbookName: string, index: number): boolean {\n const workbookStyles = this.conditionalStyles.filter(\n (style) => style.area.workbookName === workbookName\n );\n if (index < 0 || index >= workbookStyles.length) {\n return false;\n }\n // Find the actual index in the full array\n let currentIndex = 0;\n for (let i = 0; i < this.conditionalStyles.length; i++) {\n const style = this.conditionalStyles[i];\n if (style && style.area.workbookName === workbookName) {\n if (currentIndex === index) {\n this.conditionalStyles.splice(i, 1);\n return true;\n }\n currentIndex++;\n }\n }\n return false;\n }\n\n /**\n * Get all conditional styles for a workbook\n */\n getConditionalStyles(workbookName: string): ConditionalStyle[] {\n return this.conditionalStyles.filter(\n (style) => style && style.area && style.area.workbookName === workbookName\n );\n }\n\n /**\n * Add a direct cell style rule\n */\n addCellStyle(style: DirectCellStyle): void {\n this.cellStyles.push(style);\n }\n\n /**\n * Remove a direct cell style rule by index for a specific workbook\n */\n removeCellStyle(workbookName: string, index: number): boolean {\n const workbookStyles = this.cellStyles.filter(\n (style) => style && style.area && style.area.workbookName === workbookName\n );\n if (index < 0 || index >= workbookStyles.length) {\n return false;\n }\n // Find the actual index in the full array\n let currentIndex = 0;\n for (let i = 0; i < this.cellStyles.length; i++) {\n const style = this.cellStyles[i];\n if (style && style.area && style.area.workbookName === workbookName) {\n if (currentIndex === index) {\n this.cellStyles.splice(i, 1);\n return true;\n }\n currentIndex++;\n }\n }\n return false;\n }\n\n /**\n * Get all direct cell styles for a workbook\n */\n getCellStyles(workbookName: string): DirectCellStyle[] {\n return this.cellStyles.filter(\n (style) => style && style.area && style.area.workbookName === workbookName\n );\n }\n\n /**\n * Get all conditional styles across all workbooks (for serialization)\n */\n getAllConditionalStyles(): ConditionalStyle[] {\n return [...this.conditionalStyles];\n }\n\n /**\n * Get all cell styles (for serialization)\n */\n getAllCellStyles(): DirectCellStyle[] {\n return [...this.cellStyles];\n }\n\n /**\n * Reset all styles (for deserialization)\n */\n resetStyles(\n conditionalStyles?: ConditionalStyle[],\n cellStyles?: DirectCellStyle[]\n ): void {\n this.conditionalStyles = conditionalStyles ? [...conditionalStyles] : [];\n this.cellStyles = cellStyles ? [...cellStyles] : [];\n }\n\n /**\n * Remove all styles for a workbook\n */\n removeWorkbookStyles(workbookName: string): void {\n this.conditionalStyles = this.conditionalStyles.filter(\n (style) => style.area.workbookName !== workbookName\n );\n this.cellStyles = this.cellStyles.filter(\n (style) => style.area.workbookName !== workbookName\n );\n }\n\n /**\n * Update workbook name in all style references\n */\n updateWorkbookName(oldName: string, newName: string): void {\n // Update conditional styles\n this.conditionalStyles = this.conditionalStyles.map((style) => {\n if (style.area.workbookName === oldName) {\n return {\n ...style,\n area: {\n ...style.area,\n workbookName: newName,\n },\n };\n }\n return style;\n });\n // Update cell styles\n this.cellStyles = this.cellStyles.map((style) => {\n if (style.area.workbookName === oldName) {\n return {\n ...style,\n area: {\n ...style.area,\n workbookName: newName,\n },\n };\n }\n return style;\n });\n }\n\n /**\n * Update sheet name in style references\n */\n updateSheetName(\n workbookName: string,\n oldSheetName: string,\n newSheetName: string\n ): void {\n // Update conditional styles\n this.conditionalStyles = this.conditionalStyles.map((style) => {\n if (\n style.area.workbookName === workbookName &&\n style.area.sheetName === oldSheetName\n ) {\n return {\n ...style,\n area: {\n ...style.area,\n sheetName: newSheetName,\n },\n };\n }\n return style;\n });\n // Update cell styles\n this.cellStyles = this.cellStyles.map((style) => {\n if (\n style.area.workbookName === workbookName &&\n style.area.sheetName === oldSheetName\n ) {\n return {\n ...style,\n area: {\n ...style.area,\n sheetName: newSheetName,\n },\n };\n }\n return style;\n });\n }\n\n /**\n * Remove styles that reference a deleted sheet\n */\n removeSheetStyles(workbookName: string, sheetName: string): void {\n this.conditionalStyles = this.conditionalStyles.filter(\n (style) =>\n !(\n style.area.workbookName === workbookName &&\n style.area.sheetName === sheetName\n )\n );\n this.cellStyles = this.cellStyles.filter(\n (style) =>\n !(\n style.area.workbookName === workbookName &&\n style.area.sheetName === sheetName\n )\n );\n }\n\n /**\n * Get the style for a specific cell\n * Returns the first matching style (first match wins)\n * Checks cellStyles first, then conditionalStyles\n */\n getCellStyle(cellAddress: CellAddress): CellStyle | undefined {\n // First check direct cell styles\n for (const cellStyle of this.cellStyles) {\n if (!cellStyle || !cellStyle.area) {\n continue;\n }\n if (\n cellStyle.area.workbookName === cellAddress.workbookName &&\n cellStyle.area.sheetName === cellAddress.sheetName &&\n isCellInRange(cellAddress, cellStyle.area.range)\n ) {\n return cellStyle.style;\n }\n }\n\n // Then check conditional styles\n for (const style of this.conditionalStyles) {\n if (!style || !style.area) {\n continue;\n }\n // Check if cell is in the style's area\n if (\n style.area.sheetName !== cellAddress.sheetName ||\n style.area.workbookName !== cellAddress.workbookName\n ) {\n continue;\n }\n\n if (!isCellInRange(cellAddress, style.area.range)) {\n continue;\n }\n\n // Cell is in area, evaluate condition\n if (style.condition.type === \"formula\") {\n const result = this.evaluateFormulaCondition(cellAddress, style);\n if (result) return result;\n } else {\n const result = this.evaluateGradientCondition(cellAddress, style);\n if (result) return result;\n }\n }\n\n return undefined;\n }\n\n /**\n * Evaluate a formula-based style condition\n */\n private evaluateFormulaCondition(\n cellAddress: CellAddress,\n style: ConditionalStyle\n ): CellStyle | undefined {\n if (style.condition.type !== \"formula\") {\n return undefined;\n }\n\n try {\n // Evaluate formula in context of the cell\n // evaluateFormula expects a full cell value (with = prefix for formulas)\n const formula = style.condition.formula.startsWith(\"=\")\n ? style.condition.formula\n : `=${style.condition.formula}`;\n\n const result = this.evaluationManager.evaluateFormula(\n formula,\n cellAddress\n );\n\n // Check if result is truthy\n const isTruthy =\n result === true ||\n result === \"TRUE\" ||\n (typeof result === \"number\" && result !== 0);\n\n if (isTruthy) {\n return {\n backgroundColor: lchToHex(style.condition.color),\n };\n }\n } catch (error) {\n // If formula evaluation fails, don't apply style\n console.warn(\"Failed to evaluate formula condition:\", error);\n }\n\n return undefined;\n }\n\n /**\n * Evaluate a gradient-based style condition\n */\n private evaluateGradientCondition(\n cellAddress: CellAddress,\n style: ConditionalStyle\n ): CellStyle | undefined {\n if (style.condition.type !== \"gradient\") {\n return undefined;\n }\n\n try {\n // Get the cell's evaluation result\n const evalResult =\n this.evaluationManager.getCellEvaluationResult(cellAddress);\n if (!evalResult || evalResult.type !== \"value\") {\n return undefined;\n }\n if (evalResult.result.type !== \"number\") {\n return undefined;\n }\n const cellValue = evalResult.result.value;\n\n // Calculate min and max values for the gradient\n const { min: minValue, max: maxValue } = this.calculateGradientBounds(\n style,\n cellAddress\n );\n\n if (minValue === null || maxValue === null) {\n return undefined;\n }\n\n // Calculate interpolation factor\n const factor = calculateGradientFactor(cellValue, minValue, maxValue);\n\n // Interpolate between min and max colors\n const minColor = style.condition.min.color;\n const maxColor = style.condition.max.color;\n const interpolatedColor = interpolateLCH(minColor, maxColor, factor);\n\n return {\n backgroundColor: lchToHex(interpolatedColor),\n };\n } catch (error) {\n console.warn(\"Failed to evaluate gradient condition:\", error);\n return undefined;\n }\n }\n\n /**\n * Calculate min and max bounds for a gradient\n */\n private calculateGradientBounds(\n style: ConditionalStyle,\n cellAddress: CellAddress\n ): { min: number | null; max: number | null } {\n if (style.condition.type !== \"gradient\") {\n return { min: null, max: null };\n }\n\n const { min: minConfig, max: maxConfig } = style.condition;\n const topLeftCell: CellAddress = {\n workbookName: style.area.workbookName,\n sheetName: style.area.sheetName,\n colIndex: style.area.range.start.col,\n rowIndex: style.area.range.start.row,\n };\n\n // Calculate min value\n let minValue: number | null = null;\n if (minConfig.type === \"lowest_value\") {\n // Evaluate MIN(range) formula directly\n try {\n const rangeRef = this.getRangeReference(style.area);\n const result = this.evaluationManager.evaluateFormula(\n `=MIN(${rangeRef})`,\n topLeftCell\n );\n if (typeof result === \"number\") {\n minValue = result;\n }\n } catch (error) {\n console.warn(\"Failed to calculate MIN:\", error);\n }\n } else {\n // Evaluate valueFormula in context of area's top-left cell\n const formula = minConfig.valueFormula.startsWith(\"=\")\n ? minConfig.valueFormula\n : `=${minConfig.valueFormula}`;\n const result = this.evaluationManager.evaluateFormula(\n formula,\n topLeftCell\n );\n if (typeof result === \"number\") {\n minValue = result;\n }\n }\n\n // Calculate max value\n let maxValue: number | null = null;\n if (maxConfig.type === \"highest_value\") {\n // Evaluate MAX(range) formula directly\n try {\n const rangeRef = this.getRangeReference(style.area);\n const result = this.evaluationManager.evaluateFormula(\n `=MAX(${rangeRef})`,\n topLeftCell\n );\n if (typeof result === \"number\") {\n maxValue = result;\n }\n } catch (error) {\n console.warn(\"Failed to calculate MAX:\", error);\n }\n } else {\n // Evaluate valueFormula in context of area's top-left cell\n const formula = maxConfig.valueFormula.startsWith(\"=\")\n ? maxConfig.valueFormula\n : `=${maxConfig.valueFormula}`;\n const result = this.evaluationManager.evaluateFormula(\n formula,\n topLeftCell\n );\n if (typeof result === \"number\") {\n maxValue = result;\n }\n }\n\n return { min: minValue, max: maxValue };\n }\n\n /**\n * Get a range reference string from a RangeAddress\n * Follows CANONICAL_RANGES.md format:\n * - Closed: A5:D10\n * - Row-bounded (col-open): A5:10\n * - Col-bounded (row-open): A5:D\n * - Open both: A5:INFINITY\n */\n private getRangeReference(area: RangeAddress): string {\n const colToLetter = (col: number): string => {\n let result = \"\";\n let c = col;\n while (c >= 0) {\n result = String.fromCharCode(65 + (c % 26)) + result;\n c = Math.floor(c / 26) - 1;\n }\n return result;\n };\n\n const startCol = colToLetter(area.range.start.col);\n const startRow = area.range.start.row + 1; // Convert to 1-based\n\n const isColInfinity = area.range.end.col.type === \"infinity\";\n const isRowInfinity = area.range.end.row.type === \"infinity\";\n\n let rangeStr: string;\n\n if (isColInfinity && isRowInfinity) {\n // Open both: A5:INFINITY\n rangeStr = `${startCol}${startRow}:INFINITY`;\n } else if (isColInfinity) {\n // Row-bounded (col-open): A5:10\n if (area.range.end.row.type === \"number\") {\n const endRow = area.range.end.row.value + 1; // Convert to 1-based\n rangeStr = `${startCol}${startRow}:${endRow}`;\n } else {\n rangeStr = `${startCol}${startRow}:INFINITY`;\n }\n } else if (isRowInfinity) {\n // Col-bounded (row-open): A5:D\n if (area.range.end.col.type === \"number\") {\n const endCol = colToLetter(area.range.end.col.value);\n rangeStr = `${startCol}${startRow}:${endCol}`;\n } else {\n rangeStr = `${startCol}${startRow}:INFINITY`;\n }\n } else {\n // Closed rectangle: A5:D10\n if (\n area.range.end.col.type === \"number\" &&\n area.range.end.row.type === \"number\"\n ) {\n const endCol = colToLetter(area.range.end.col.value);\n const endRow = area.range.end.row.value + 1; // Convert to 1-based\n rangeStr = `${startCol}${startRow}:${endCol}${endRow}`;\n } else {\n // Fallback to INFINITY if types don't match\n rangeStr = `${startCol}${startRow}:INFINITY`;\n }\n }\n\n // Quote sheet name if it contains spaces or special characters\n const needsQuotes = /[ '!]/.test(area.sheetName);\n const sheetRef = needsQuotes\n ? `'${area.sheetName.replace(/'/g, \"''\")}'`\n : area.sheetName;\n\n // Construct the full reference: [workbook]'sheet'!range\n return `[${area.workbookName}]${sheetRef}!${rangeStr}`;\n }\n}\n"
6
6
  ],
7
- "mappings": "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",
8
- "debugId": "DB5713E9E5C6BAC564756E2164756E21",
7
+ "mappings": ";AAcA;AACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAMO,MAAM,aAAa;AAAA,EAKd;AAAA,EACA;AAAA,EALF,oBAAwC,CAAC;AAAA,EACzC,aAAgC,CAAC;AAAA,EAEzC,WAAW,CACD,iBACA,mBACR;AAAA,IAFQ;AAAA,IACA;AAAA;AAAA,EAMV,mBAAmB,CAAC,OAA+B;AAAA,IACjD,KAAK,kBAAkB,KAAK,KAAK;AAAA;AAAA,EAMnC,sBAAsB,CAAC,cAAsB,OAAwB;AAAA,IACnE,MAAM,iBAAiB,KAAK,kBAAkB,OAC5C,CAAC,UAAU,MAAM,KAAK,iBAAiB,YACzC;AAAA,IACA,IAAI,QAAQ,KAAK,SAAS,eAAe,QAAQ;AAAA,MAC/C,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,eAAe;AAAA,IACnB,SAAS,IAAI,EAAG,IAAI,KAAK,kBAAkB,QAAQ,KAAK;AAAA,MACtD,MAAM,QAAQ,KAAK,kBAAkB;AAAA,MACrC,IAAI,SAAS,MAAM,KAAK,iBAAiB,cAAc;AAAA,QACrD,IAAI,iBAAiB,OAAO;AAAA,UAC1B,KAAK,kBAAkB,OAAO,GAAG,CAAC;AAAA,UAClC,OAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,EAMT,oBAAoB,CAAC,cAA0C;AAAA,IAC7D,OAAO,KAAK,kBAAkB,OAC5B,CAAC,UAAU,SAAS,MAAM,QAAQ,MAAM,KAAK,iBAAiB,YAChE;AAAA;AAAA,EAMF,YAAY,CAAC,OAA8B;AAAA,IACzC,KAAK,WAAW,KAAK,KAAK;AAAA;AAAA,EAM5B,eAAe,CAAC,cAAsB,OAAwB;AAAA,IAC5D,MAAM,iBAAiB,KAAK,WAAW,OACrC,CAAC,UAAU,SAAS,MAAM,QAAQ,MAAM,KAAK,iBAAiB,YAChE;AAAA,IACA,IAAI,QAAQ,KAAK,SAAS,eAAe,QAAQ;AAAA,MAC/C,OAAO;AAAA,IACT;AAAA,IAEA,IAAI,eAAe;AAAA,IACnB,SAAS,IAAI,EAAG,IAAI,KAAK,WAAW,QAAQ,KAAK;AAAA,MAC/C,MAAM,QAAQ,KAAK,WAAW;AAAA,MAC9B,IAAI,SAAS,MAAM,QAAQ,MAAM,KAAK,iBAAiB,cAAc;AAAA,QACnE,IAAI,iBAAiB,OAAO;AAAA,UAC1B,KAAK,WAAW,OAAO,GAAG,CAAC;AAAA,UAC3B,OAAO;AAAA,QACT;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IACA,OAAO;AAAA;AAAA,EAMT,aAAa,CAAC,cAAyC;AAAA,IACrD,OAAO,KAAK,WAAW,OACrB,CAAC,UAAU,SAAS,MAAM,QAAQ,MAAM,KAAK,iBAAiB,YAChE;AAAA;AAAA,EAMF,uBAAuB,GAAuB;AAAA,IAC5C,OAAO,CAAC,GAAG,KAAK,iBAAiB;AAAA;AAAA,EAMnC,gBAAgB,GAAsB;AAAA,IACpC,OAAO,CAAC,GAAG,KAAK,UAAU;AAAA;AAAA,EAM5B,WAAW,CACT,mBACA,YACM;AAAA,IACN,KAAK,oBAAoB,oBAAoB,CAAC,GAAG,iBAAiB,IAAI,CAAC;AAAA,IACvE,KAAK,aAAa,aAAa,CAAC,GAAG,UAAU,IAAI,CAAC;AAAA;AAAA,EAMpD,oBAAoB,CAAC,cAA4B;AAAA,IAC/C,KAAK,oBAAoB,KAAK,kBAAkB,OAC9C,CAAC,UAAU,MAAM,KAAK,iBAAiB,YACzC;AAAA,IACA,KAAK,aAAa,KAAK,WAAW,OAChC,CAAC,UAAU,MAAM,KAAK,iBAAiB,YACzC;AAAA;AAAA,EAMF,kBAAkB,CAAC,SAAiB,SAAuB;AAAA,IAEzD,KAAK,oBAAoB,KAAK,kBAAkB,IAAI,CAAC,UAAU;AAAA,MAC7D,IAAI,MAAM,KAAK,iBAAiB,SAAS;AAAA,QACvC,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,eACD,MAAM;AAAA,YACT,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,MACA,OAAO;AAAA,KACR;AAAA,IAED,KAAK,aAAa,KAAK,WAAW,IAAI,CAAC,UAAU;AAAA,MAC/C,IAAI,MAAM,KAAK,iBAAiB,SAAS;AAAA,QACvC,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,eACD,MAAM;AAAA,YACT,cAAc;AAAA,UAChB;AAAA,QACF;AAAA,MACF;AAAA,MACA,OAAO;AAAA,KACR;AAAA;AAAA,EAMH,eAAe,CACb,cACA,cACA,cACM;AAAA,IAEN,KAAK,oBAAoB,KAAK,kBAAkB,IAAI,CAAC,UAAU;AAAA,MAC7D,IACE,MAAM,KAAK,iBAAiB,gBAC5B,MAAM,KAAK,cAAc,cACzB;AAAA,QACA,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,eACD,MAAM;AAAA,YACT,WAAW;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAAA,MACA,OAAO;AAAA,KACR;AAAA,IAED,KAAK,aAAa,KAAK,WAAW,IAAI,CAAC,UAAU;AAAA,MAC/C,IACE,MAAM,KAAK,iBAAiB,gBAC5B,MAAM,KAAK,cAAc,cACzB;AAAA,QACA,OAAO;AAAA,aACF;AAAA,UACH,MAAM;AAAA,eACD,MAAM;AAAA,YACT,WAAW;AAAA,UACb;AAAA,QACF;AAAA,MACF;AAAA,MACA,OAAO;AAAA,KACR;AAAA;AAAA,EAMH,iBAAiB,CAAC,cAAsB,WAAyB;AAAA,IAC/D,KAAK,oBAAoB,KAAK,kBAAkB,OAC9C,CAAC,UACC,EACE,MAAM,KAAK,iBAAiB,gBAC5B,MAAM,KAAK,cAAc,UAE/B;AAAA,IACA,KAAK,aAAa,KAAK,WAAW,OAChC,CAAC,UACC,EACE,MAAM,KAAK,iBAAiB,gBAC5B,MAAM,KAAK,cAAc,UAE/B;AAAA;AAAA,EAQF,YAAY,CAAC,aAAiD;AAAA,IAE5D,WAAW,aAAa,KAAK,YAAY;AAAA,MACvC,IAAI,CAAC,aAAa,CAAC,UAAU,MAAM;AAAA,QACjC;AAAA,MACF;AAAA,MACA,IACE,UAAU,KAAK,iBAAiB,YAAY,gBAC5C,UAAU,KAAK,cAAc,YAAY,aACzC,cAAc,aAAa,UAAU,KAAK,KAAK,GAC/C;AAAA,QACA,OAAO,UAAU;AAAA,MACnB;AAAA,IACF;AAAA,IAGA,WAAW,SAAS,KAAK,mBAAmB;AAAA,MAC1C,IAAI,CAAC,SAAS,CAAC,MAAM,MAAM;AAAA,QACzB;AAAA,MACF;AAAA,MAEA,IACE,MAAM,KAAK,cAAc,YAAY,aACrC,MAAM,KAAK,iBAAiB,YAAY,cACxC;AAAA,QACA;AAAA,MACF;AAAA,MAEA,IAAI,CAAC,cAAc,aAAa,MAAM,KAAK,KAAK,GAAG;AAAA,QACjD;AAAA,MACF;AAAA,MAGA,IAAI,MAAM,UAAU,SAAS,WAAW;AAAA,QACtC,MAAM,SAAS,KAAK,yBAAyB,aAAa,KAAK;AAAA,QAC/D,IAAI;AAAA,UAAQ,OAAO;AAAA,MACrB,EAAO;AAAA,QACL,MAAM,SAAS,KAAK,0BAA0B,aAAa,KAAK;AAAA,QAChE,IAAI;AAAA,UAAQ,OAAO;AAAA;AAAA,IAEvB;AAAA,IAEA;AAAA;AAAA,EAMM,wBAAwB,CAC9B,aACA,OACuB;AAAA,IACvB,IAAI,MAAM,UAAU,SAAS,WAAW;AAAA,MACtC;AAAA,IACF;AAAA,IAEA,IAAI;AAAA,MAGF,MAAM,UAAU,MAAM,UAAU,QAAQ,WAAW,GAAG,IAClD,MAAM,UAAU,UAChB,IAAI,MAAM,UAAU;AAAA,MAExB,MAAM,SAAS,KAAK,kBAAkB,gBACpC,SACA,WACF;AAAA,MAGA,MAAM,WACJ,WAAW,QACX,WAAW,UACV,OAAO,WAAW,YAAY,WAAW;AAAA,MAE5C,IAAI,UAAU;AAAA,QACZ,OAAO;AAAA,UACL,iBAAiB,SAAS,MAAM,UAAU,KAAK;AAAA,QACjD;AAAA,MACF;AAAA,MACA,OAAO,OAAO;AAAA,MAEd,QAAQ,KAAK,yCAAyC,KAAK;AAAA;AAAA,IAG7D;AAAA;AAAA,EAMM,yBAAyB,CAC/B,aACA,OACuB;AAAA,IACvB,IAAI,MAAM,UAAU,SAAS,YAAY;AAAA,MACvC;AAAA,IACF;AAAA,IAEA,IAAI;AAAA,MAEF,MAAM,aACJ,KAAK,kBAAkB,wBAAwB,WAAW;AAAA,MAC5D,IAAI,CAAC,cAAc,WAAW,SAAS,SAAS;AAAA,QAC9C;AAAA,MACF;AAAA,MACA,IAAI,WAAW,OAAO,SAAS,UAAU;AAAA,QACvC;AAAA,MACF;AAAA,MACA,MAAM,YAAY,WAAW,OAAO;AAAA,MAGpC,QAAQ,KAAK,UAAU,KAAK,aAAa,KAAK,wBAC5C,OACA,WACF;AAAA,MAEA,IAAI,aAAa,QAAQ,aAAa,MAAM;AAAA,QAC1C;AAAA,MACF;AAAA,MAGA,MAAM,SAAS,wBAAwB,WAAW,UAAU,QAAQ;AAAA,MAGpE,MAAM,WAAW,MAAM,UAAU,IAAI;AAAA,MACrC,MAAM,WAAW,MAAM,UAAU,IAAI;AAAA,MACrC,MAAM,oBAAoB,eAAe,UAAU,UAAU,MAAM;AAAA,MAEnE,OAAO;AAAA,QACL,iBAAiB,SAAS,iBAAiB;AAAA,MAC7C;AAAA,MACA,OAAO,OAAO;AAAA,MACd,QAAQ,KAAK,0CAA0C,KAAK;AAAA,MAC5D;AAAA;AAAA;AAAA,EAOI,uBAAuB,CAC7B,OACA,aAC4C;AAAA,IAC5C,IAAI,MAAM,UAAU,SAAS,YAAY;AAAA,MACvC,OAAO,EAAE,KAAK,MAAM,KAAK,KAAK;AAAA,IAChC;AAAA,IAEA,QAAQ,KAAK,WAAW,KAAK,cAAc,MAAM;AAAA,IACjD,MAAM,cAA2B;AAAA,MAC/B,cAAc,MAAM,KAAK;AAAA,MACzB,WAAW,MAAM,KAAK;AAAA,MACtB,UAAU,MAAM,KAAK,MAAM,MAAM;AAAA,MACjC,UAAU,MAAM,KAAK,MAAM,MAAM;AAAA,IACnC;AAAA,IAGA,IAAI,WAA0B;AAAA,IAC9B,IAAI,UAAU,SAAS,gBAAgB;AAAA,MAErC,IAAI;AAAA,QACF,MAAM,WAAW,KAAK,kBAAkB,MAAM,IAAI;AAAA,QAClD,MAAM,SAAS,KAAK,kBAAkB,gBACpC,QAAQ,aACR,WACF;AAAA,QACA,IAAI,OAAO,WAAW,UAAU;AAAA,UAC9B,WAAW;AAAA,QACb;AAAA,QACA,OAAO,OAAO;AAAA,QACd,QAAQ,KAAK,4BAA4B,KAAK;AAAA;AAAA,IAElD,EAAO;AAAA,MAEL,MAAM,UAAU,UAAU,aAAa,WAAW,GAAG,IACjD,UAAU,eACV,IAAI,UAAU;AAAA,MAClB,MAAM,SAAS,KAAK,kBAAkB,gBACpC,SACA,WACF;AAAA,MACA,IAAI,OAAO,WAAW,UAAU;AAAA,QAC9B,WAAW;AAAA,MACb;AAAA;AAAA,IAIF,IAAI,WAA0B;AAAA,IAC9B,IAAI,UAAU,SAAS,iBAAiB;AAAA,MAEtC,IAAI;AAAA,QACF,MAAM,WAAW,KAAK,kBAAkB,MAAM,IAAI;AAAA,QAClD,MAAM,SAAS,KAAK,kBAAkB,gBACpC,QAAQ,aACR,WACF;AAAA,QACA,IAAI,OAAO,WAAW,UAAU;AAAA,UAC9B,WAAW;AAAA,QACb;AAAA,QACA,OAAO,OAAO;AAAA,QACd,QAAQ,KAAK,4BAA4B,KAAK;AAAA;AAAA,IAElD,EAAO;AAAA,MAEL,MAAM,UAAU,UAAU,aAAa,WAAW,GAAG,IACjD,UAAU,eACV,IAAI,UAAU;AAAA,MAClB,MAAM,SAAS,KAAK,kBAAkB,gBACpC,SACA,WACF;AAAA,MACA,IAAI,OAAO,WAAW,UAAU;AAAA,QAC9B,WAAW;AAAA,MACb;AAAA;AAAA,IAGF,OAAO,EAAE,KAAK,UAAU,KAAK,SAAS;AAAA;AAAA,EAWhC,iBAAiB,CAAC,MAA4B;AAAA,IACpD,MAAM,cAAc,CAAC,QAAwB;AAAA,MAC3C,IAAI,SAAS;AAAA,MACb,IAAI,IAAI;AAAA,MACR,OAAO,KAAK,GAAG;AAAA,QACb,SAAS,OAAO,aAAa,KAAM,IAAI,EAAG,IAAI;AAAA,QAC9C,IAAI,KAAK,MAAM,IAAI,EAAE,IAAI;AAAA,MAC3B;AAAA,MACA,OAAO;AAAA;AAAA,IAGT,MAAM,WAAW,YAAY,KAAK,MAAM,MAAM,GAAG;AAAA,IACjD,MAAM,WAAW,KAAK,MAAM,MAAM,MAAM;AAAA,IAExC,MAAM,gBAAgB,KAAK,MAAM,IAAI,IAAI,SAAS;AAAA,IAClD,MAAM,gBAAgB,KAAK,MAAM,IAAI,IAAI,SAAS;AAAA,IAElD,IAAI;AAAA,IAEJ,IAAI,iBAAiB,eAAe;AAAA,MAElC,WAAW,GAAG,WAAW;AAAA,IAC3B,EAAO,SAAI,eAAe;AAAA,MAExB,IAAI,KAAK,MAAM,IAAI,IAAI,SAAS,UAAU;AAAA,QACxC,MAAM,SAAS,KAAK,MAAM,IAAI,IAAI,QAAQ;AAAA,QAC1C,WAAW,GAAG,WAAW,YAAY;AAAA,MACvC,EAAO;AAAA,QACL,WAAW,GAAG,WAAW;AAAA;AAAA,IAE7B,EAAO,SAAI,eAAe;AAAA,MAExB,IAAI,KAAK,MAAM,IAAI,IAAI,SAAS,UAAU;AAAA,QACxC,MAAM,SAAS,YAAY,KAAK,MAAM,IAAI,IAAI,KAAK;AAAA,QACnD,WAAW,GAAG,WAAW,YAAY;AAAA,MACvC,EAAO;AAAA,QACL,WAAW,GAAG,WAAW;AAAA;AAAA,IAE7B,EAAO;AAAA,MAEL,IACE,KAAK,MAAM,IAAI,IAAI,SAAS,YAC5B,KAAK,MAAM,IAAI,IAAI,SAAS,UAC5B;AAAA,QACA,MAAM,SAAS,YAAY,KAAK,MAAM,IAAI,IAAI,KAAK;AAAA,QACnD,MAAM,SAAS,KAAK,MAAM,IAAI,IAAI,QAAQ;AAAA,QAC1C,WAAW,GAAG,WAAW,YAAY,SAAS;AAAA,MAChD,EAAO;AAAA,QAEL,WAAW,GAAG,WAAW;AAAA;AAAA;AAAA,IAK7B,MAAM,cAAc,QAAQ,KAAK,KAAK,SAAS;AAAA,IAC/C,MAAM,WAAW,cACb,IAAI,KAAK,UAAU,QAAQ,MAAM,IAAI,OACrC,KAAK;AAAA,IAGT,OAAO,IAAI,KAAK,gBAAgB,YAAY;AAAA;AAEhD;",
8
+ "debugId": "8904835F1301129164756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -2,7 +2,7 @@
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// 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 {\n name: string;\n index: number; // 0-based index of the sheet\n content: Map<string, SerializedCellValue>;\n}\n\nexport interface Workbook {\n name: string;\n sheets: Map<string, Sheet>;\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 area: RangeAddress;\n condition: StyleCondition;\n}\n\nexport interface DirectCellStyle {\n area: RangeAddress;\n style: CellStyle\n}\n\nexport interface CellStyle {\n backgroundColor?: string; // Hex color format\n color?: string; // Text color in hex format\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 {\n name: string;\n index: number; // 0-based index of the sheet\n content: Map<string, SerializedCellValue>;\n}\n\nexport interface Workbook {\n name: string;\n sheets: Map<string, Sheet>;\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 area: RangeAddress;\n condition: StyleCondition;\n}\n\nexport interface DirectCellStyle {\n area: 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 cut: boolean;\n type: \"value\" | \"formula\";\n formatting: boolean;\n}\n"
6
6
  ],
7
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",
package/dist/mjs/lib.mjs CHANGED
@@ -3,8 +3,9 @@ import { FormulaEngine } from "./core/engine.mjs";
3
3
 
4
4
  export * from "./core/types.mjs";
5
5
  export * from "./core/utils.mjs";
6
+ export * from "./core/utils/color-utils.mjs";
6
7
  export {
7
8
  FormulaEngine
8
9
  };
9
10
 
10
- //# debugId=BABF7A1B9B38C02664756E2164756E21
11
+ //# debugId=33910997D1B8156A64756E2164756E21
@@ -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\";\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"
6
6
  ],
7
- "mappings": ";AAAA;AAAA;AACA;AACA;",
8
- "debugId": "BABF7A1B9B38C02664756E2164756E21",
7
+ "mappings": ";AAAA;AAAA;AACA;AACA;AACA;",
8
+ "debugId": "33910997D1B8156A64756E2164756E21",
9
9
  "names": []
10
10
  }
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "@ricsam/formula-engine",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "type": "module"
5
5
  }
@@ -2,7 +2,7 @@
2
2
  * Main FormulaEngine class
3
3
  * Core API implementation for spreadsheet calculations
4
4
  */
5
- import { type CellAddress, type CellStyle, type ConditionalStyle, type DirectCellStyle, type NamedExpression, type RangeAddress, type SerializedCellValue, type SingleEvaluationResult, type SpreadsheetRange, type SpreadsheetRangeEnd, type TableDefinition } from "./types";
5
+ import { type CellAddress, type CellStyle, type ConditionalStyle, type CopyCellsOptions, type DirectCellStyle, type NamedExpression, type RangeAddress, type SerializedCellValue, type SingleEvaluationResult, type SpreadsheetRange, type SpreadsheetRangeEnd, type TableDefinition } from "./types";
6
6
  import type { FillDirection } from "@ricsam/selection-manager";
7
7
  import { AutoFill } from "./autofill-utils";
8
8
  import { WorkbookManager } from "./managers/workbook-manager";
@@ -24,6 +24,7 @@ export declare class FormulaEngine {
24
24
  private autoFillManager;
25
25
  private dependencyManager;
26
26
  private styleManager;
27
+ private copyManager;
27
28
  /**
28
29
  * Public access to the store manager for testing
29
30
  */
@@ -139,6 +140,10 @@ export declare class FormulaEngine {
139
140
  * Get all direct cell styles for a workbook
140
141
  */
141
142
  getCellStyles(workbookName: string): DirectCellStyle[];
143
+ /**
144
+ * Copy cells from source to target
145
+ */
146
+ copyCells(source: CellAddress[], target: CellAddress, options: CopyCellsOptions): void;
142
147
  addSheet(opts: {
143
148
  workbookName: string;
144
149
  sheetName: string;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * CopyManager - Manages cell copy/paste operations
3
+ */
4
+ import type { CellAddress, CopyCellsOptions } from "../types";
5
+ import type { WorkbookManager } from "./workbook-manager";
6
+ import type { EvaluationManager } from "./evaluation-manager";
7
+ import type { StyleManager } from "./style-manager";
8
+ export declare class CopyManager {
9
+ private workbookManager;
10
+ private evaluationManager;
11
+ private styleManager;
12
+ constructor(workbookManager: WorkbookManager, evaluationManager: EvaluationManager, styleManager: StyleManager);
13
+ /**
14
+ * Copy cells from source to target
15
+ */
16
+ copyCells(source: CellAddress[], target: CellAddress, options: CopyCellsOptions): void;
17
+ /**
18
+ * Find the top-left cell (minimum row/col indices)
19
+ */
20
+ private findTopLeft;
21
+ /**
22
+ * Copy content from one cell to another
23
+ */
24
+ private copyCellContent;
25
+ /**
26
+ * Adjust formula references when copying
27
+ * Based on autofill-utils.ts adjustFormulaReferences
28
+ */
29
+ private adjustFormulaReferences;
30
+ /**
31
+ * Copy formatting (cellStyles and conditionalStyles) from source to target
32
+ */
33
+ private copyFormatting;
34
+ /**
35
+ * Get bounding box for a set of cells
36
+ */
37
+ private getBoundingBox;
38
+ /**
39
+ * Check if two ranges intersect
40
+ */
41
+ private rangesIntersect;
42
+ /**
43
+ * Adjust a range by row and column offsets
44
+ */
45
+ private adjustRange;
46
+ /**
47
+ * Clear source cells (for cut operation)
48
+ */
49
+ private clearSourceCells;
50
+ }
@@ -311,4 +311,13 @@ export interface DirectCellStyle {
311
311
  export interface CellStyle {
312
312
  backgroundColor?: string;
313
313
  color?: string;
314
+ fontSize?: number;
315
+ bold?: boolean;
316
+ italic?: boolean;
317
+ underline?: boolean;
318
+ }
319
+ export interface CopyCellsOptions {
320
+ cut: boolean;
321
+ type: "value" | "formula";
322
+ formatting: boolean;
314
323
  }
@@ -1,3 +1,4 @@
1
1
  export { FormulaEngine } from "./core/engine";
2
2
  export * from "./core/types";
3
3
  export * from "./core/utils";
4
+ export * from "./core/utils/color-utils";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ricsam/formula-engine",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "module": "./dist/mjs/lib.mjs",
5
5
  "scripts": {
6
6
  "test": "bun test",