@pixerate/editor 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -13
- package/THIRD_PARTY_NOTICES.md +88 -0
- package/dist/agent/index.cjs +86 -111
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +69 -211
- package/dist/agent/index.d.ts +69 -211
- package/dist/agent/index.js +77 -102
- package/dist/agent/index.js.map +1 -1
- package/dist/arrangeShortcuts-B8O3f8-P.d.cts +184 -0
- package/dist/arrangeShortcuts-sLlD2rSX.d.ts +184 -0
- package/dist/canvas/index.cjs +2112 -60
- package/dist/canvas/index.cjs.map +1 -1
- package/dist/canvas/index.d.cts +712 -181
- package/dist/canvas/index.d.ts +712 -181
- package/dist/canvas/index.js +2105 -53
- package/dist/canvas/index.js.map +1 -1
- package/dist/chunk-26BVFKHU.cjs +453 -0
- package/dist/chunk-26BVFKHU.cjs.map +1 -0
- package/dist/chunk-2H7ZHPEJ.js +762 -0
- package/dist/chunk-2H7ZHPEJ.js.map +1 -0
- package/dist/chunk-7DWMJCAT.js +453 -0
- package/dist/chunk-7DWMJCAT.js.map +1 -0
- package/dist/{chunk-TVRC4KVT.cjs → chunk-AA4ZEVCC.cjs} +845 -90
- package/dist/chunk-AA4ZEVCC.cjs.map +1 -0
- package/dist/chunk-ARRTP33I.js +101 -0
- package/dist/chunk-ARRTP33I.js.map +1 -0
- package/dist/{chunk-LA7PEGU3.cjs → chunk-CL37JGFW.cjs} +4 -4
- package/dist/{chunk-LA7PEGU3.cjs.map → chunk-CL37JGFW.cjs.map} +1 -1
- package/dist/chunk-CPOKFNBG.cjs +101 -0
- package/dist/chunk-CPOKFNBG.cjs.map +1 -0
- package/dist/chunk-G2I4QJOT.cjs +762 -0
- package/dist/chunk-G2I4QJOT.cjs.map +1 -0
- package/dist/{chunk-4QPLEUL2.cjs → chunk-GVSMRPHB.cjs} +1046 -54
- package/dist/chunk-GVSMRPHB.cjs.map +1 -0
- package/dist/{chunk-KYRZDWM4.js → chunk-JJDLPEWL.js} +2 -2
- package/dist/{chunk-GVW4P7BG.js → chunk-K3R5NG2D.js} +448 -54
- package/dist/chunk-K3R5NG2D.js.map +1 -0
- package/dist/{chunk-3TYMNULT.js → chunk-MJZBNWG7.js} +807 -52
- package/dist/chunk-MJZBNWG7.js.map +1 -0
- package/dist/{chunk-A7DKIA72.js → chunk-QBJ22YZR.js} +1059 -93
- package/dist/chunk-QBJ22YZR.js.map +1 -0
- package/dist/{chunk-CYFJCKC4.js → chunk-QGHGJ56O.js} +997 -5
- package/dist/chunk-QGHGJ56O.js.map +1 -0
- package/dist/{chunk-JYRIOFEN.cjs → chunk-RIKBJLS2.cjs} +1064 -98
- package/dist/chunk-RIKBJLS2.cjs.map +1 -0
- package/dist/{chunk-U6NDQFOK.cjs → chunk-XDMXXC4Z.cjs} +569 -175
- package/dist/chunk-XDMXXC4Z.cjs.map +1 -0
- package/dist/commands/index.cjs +860 -0
- package/dist/commands/index.cjs.map +1 -0
- package/dist/commands/index.d.cts +592 -0
- package/dist/commands/index.d.ts +592 -0
- package/dist/commands/index.js +860 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/{controller-OUdxPY-X.d.ts → controller-pePCJLT1.d.cts} +216 -11
- package/dist/{controller-OUdxPY-X.d.cts → controller-pePCJLT1.d.ts} +216 -11
- package/dist/extensions/index.cjs +14 -4
- package/dist/extensions/index.cjs.map +1 -1
- package/dist/extensions/index.d.cts +3 -3
- package/dist/extensions/index.d.ts +3 -3
- package/dist/extensions/index.js +13 -3
- package/dist/history/index.cjs +12 -2
- package/dist/history/index.cjs.map +1 -1
- package/dist/history/index.d.cts +211 -7
- package/dist/history/index.d.ts +211 -7
- package/dist/history/index.js +13 -3
- package/dist/image-editor/index.cjs +418 -13
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +154 -3
- package/dist/image-editor/index.d.ts +154 -3
- package/dist/image-editor/index.js +417 -12
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{index-k3mFbPx_.d.cts → index-CCr_z9kF.d.cts} +3 -3
- package/dist/{index-Ng1pG7JE.d.ts → index-Ck6ajwXh.d.ts} +3 -3
- package/dist/index.cjs +275 -83
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +296 -47
- package/dist/index.d.ts +296 -47
- package/dist/index.js +266 -74
- package/dist/index.js.map +1 -1
- package/dist/registry-D5-R90p0.d.cts +209 -0
- package/dist/registry-D5-R90p0.d.ts +209 -0
- package/dist/{registry-iAHbqkYt.d.cts → registry-GJI4gToU.d.cts} +15 -4
- package/dist/{registry-iAHbqkYt.d.ts → registry-GJI4gToU.d.ts} +15 -4
- package/dist/serializers/index.cjs +3 -3
- package/dist/serializers/index.d.cts +1 -1
- package/dist/serializers/index.d.ts +1 -1
- package/dist/serializers/index.js +2 -2
- package/dist/spreadsheet/index.cjs +23 -3
- package/dist/spreadsheet/index.cjs.map +1 -1
- package/dist/spreadsheet/index.d.cts +97 -10
- package/dist/spreadsheet/index.d.ts +97 -10
- package/dist/spreadsheet/index.js +22 -2
- package/dist/{track-changes-G8JcWB8b.d.cts → track-changes-BSF58RK0.d.cts} +92 -9
- package/dist/{track-changes-G8JcWB8b.d.ts → track-changes-BSF58RK0.d.ts} +92 -9
- package/dist/{types-DMe0vFB1.d.cts → types-DX4Mh4SL.d.cts} +1 -1
- package/dist/{types-DMe0vFB1.d.ts → types-DX4Mh4SL.d.ts} +1 -1
- package/dist/types-GT5a5YAX.d.cts +86 -0
- package/dist/types-GT5a5YAX.d.ts +86 -0
- package/package.json +8 -2
- package/dist/chunk-2TWGLC5K.cjs +0 -262
- package/dist/chunk-2TWGLC5K.cjs.map +0 -1
- package/dist/chunk-3TYMNULT.js.map +0 -1
- package/dist/chunk-4QPLEUL2.cjs.map +0 -1
- package/dist/chunk-A7DKIA72.js.map +0 -1
- package/dist/chunk-CYFJCKC4.js.map +0 -1
- package/dist/chunk-GVW4P7BG.js.map +0 -1
- package/dist/chunk-JYRIOFEN.cjs.map +0 -1
- package/dist/chunk-KAADNAPF.js +0 -262
- package/dist/chunk-KAADNAPF.js.map +0 -1
- package/dist/chunk-TVRC4KVT.cjs.map +0 -1
- package/dist/chunk-U6NDQFOK.cjs.map +0 -1
- package/dist/types-BZgcDsC5.d.cts +0 -42
- package/dist/types-BZgcDsC5.d.ts +0 -42
- /package/dist/{chunk-KYRZDWM4.js.map → chunk-JJDLPEWL.js.map} +0 -0
|
@@ -10,7 +10,15 @@
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
var _chunkRIKBJLS2cjs = require('./chunk-RIKBJLS2.cjs');
|
|
14
22
|
|
|
15
23
|
// src/spreadsheet/formula/dependency-graph.ts
|
|
16
24
|
var columnDependencyKey = (col) => `${col.toUpperCase()}:`;
|
|
@@ -19,22 +27,24 @@ function extractCellDependencies(node) {
|
|
|
19
27
|
const visit = (curr) => {
|
|
20
28
|
if (curr.type === "CellRef") {
|
|
21
29
|
deps.push({ col: curr.col, row: curr.row });
|
|
22
|
-
} else if (curr.type === "
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
} else if (curr.type === "SpillRef") {
|
|
31
|
+
deps.push({ col: curr.col, row: curr.row });
|
|
32
|
+
} else if (curr.type === "Range" && curr.endRow >= _chunkRIKBJLS2cjs.WHOLE_COLUMN_END_ROW) {
|
|
33
|
+
const startC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, curr.startCol);
|
|
34
|
+
const endC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, curr.endCol);
|
|
25
35
|
for (let c = Math.min(startC, endC); c <= Math.max(startC, endC); c++) {
|
|
26
|
-
deps.push({ col:
|
|
36
|
+
deps.push({ col: _chunkRIKBJLS2cjs.indexToColName.call(void 0, c), row: 0 });
|
|
27
37
|
}
|
|
28
38
|
} else if (curr.type === "Range") {
|
|
29
|
-
const startC =
|
|
30
|
-
const endC =
|
|
39
|
+
const startC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, curr.startCol);
|
|
40
|
+
const endC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, curr.endCol);
|
|
31
41
|
const minC = Math.min(startC, endC);
|
|
32
42
|
const maxC = Math.max(startC, endC);
|
|
33
43
|
const minR = Math.min(curr.startRow, curr.endRow);
|
|
34
44
|
const maxR = Math.max(curr.startRow, curr.endRow);
|
|
35
45
|
for (let c = minC; c <= maxC; c++) {
|
|
36
46
|
for (let r = minR; r <= maxR; r++) {
|
|
37
|
-
deps.push({ col:
|
|
47
|
+
deps.push({ col: _chunkRIKBJLS2cjs.indexToColName.call(void 0, c), row: r });
|
|
38
48
|
}
|
|
39
49
|
}
|
|
40
50
|
} else if (curr.type === "BinaryOp") {
|
|
@@ -49,11 +59,19 @@ function extractCellDependencies(node) {
|
|
|
49
59
|
visit(node);
|
|
50
60
|
return deps;
|
|
51
61
|
}
|
|
52
|
-
var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this); }
|
|
62
|
+
var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);_class.prototype.__init5.call(this); }
|
|
53
63
|
// Map of cellKey (e.g. "B2") -> Set of cellKeys that this cell depends ON
|
|
54
64
|
__init() {this.dependencies = /* @__PURE__ */ new Map()}
|
|
55
65
|
// Map of cellKey (e.g. "A1") -> Set of cellKeys that depend ON this cell (dependents)
|
|
56
66
|
__init2() {this.dependents = /* @__PURE__ */ new Map()}
|
|
67
|
+
// Dynamic-array edges, set by the controller after evaluating an anchor:
|
|
68
|
+
// spilled cells depend on their anchor, and a blocked (#SPILL!) anchor
|
|
69
|
+
// depends on the cells blocking it. Kept apart from formula dependencies,
|
|
70
|
+
// so re-entering a formula doesn't drop them.
|
|
71
|
+
__init3() {this.spillDependencies = /* @__PURE__ */ new Map()}
|
|
72
|
+
__init4() {this.spillDependents = /* @__PURE__ */ new Map()}
|
|
73
|
+
// anchor -> the edges it registered (so they can be replaced).
|
|
74
|
+
__init5() {this.spillEdges = /* @__PURE__ */ new Map()}
|
|
57
75
|
setCellFormula(cellKey, formulaStr) {
|
|
58
76
|
const key = cellKey.toUpperCase();
|
|
59
77
|
const oldDeps = this.dependencies.get(key) || /* @__PURE__ */ new Set();
|
|
@@ -65,7 +83,7 @@ var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.c
|
|
|
65
83
|
return;
|
|
66
84
|
}
|
|
67
85
|
try {
|
|
68
|
-
const ast =
|
|
86
|
+
const ast = _chunkRIKBJLS2cjs.parseFormula.call(void 0, formulaStr);
|
|
69
87
|
const deps = extractCellDependencies(ast);
|
|
70
88
|
const newDeps = /* @__PURE__ */ new Set();
|
|
71
89
|
for (const d of deps) {
|
|
@@ -84,12 +102,49 @@ var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.c
|
|
|
84
102
|
clear() {
|
|
85
103
|
this.dependencies.clear();
|
|
86
104
|
this.dependents.clear();
|
|
105
|
+
this.spillDependencies.clear();
|
|
106
|
+
this.spillDependents.clear();
|
|
107
|
+
this.spillEdges.clear();
|
|
87
108
|
}
|
|
109
|
+
/**
|
|
110
|
+
* Records the dynamic-array edges of the anchor `anchorKey`, replacing its
|
|
111
|
+
* previous ones: every key in `spilledKeys` (cells holding its spilled
|
|
112
|
+
* values) depends on the anchor, and the anchor depends on every key in
|
|
113
|
+
* `blockingKeys` (cells that stop it spilling). Pass empty lists to remove
|
|
114
|
+
* the anchor's edges.
|
|
115
|
+
*/
|
|
116
|
+
setSpillEdges(anchorKey, spilledKeys, blockingKeys = []) {
|
|
117
|
+
const anchor = anchorKey.toUpperCase();
|
|
118
|
+
for (const [from, to] of _nullishCoalesce(this.spillEdges.get(anchor), () => ( []))) {
|
|
119
|
+
_optionalChain([this, 'access', _7 => _7.spillDependencies, 'access', _8 => _8.get, 'call', _9 => _9(from), 'optionalAccess', _10 => _10.delete, 'call', _11 => _11(to)]);
|
|
120
|
+
_optionalChain([this, 'access', _12 => _12.spillDependents, 'access', _13 => _13.get, 'call', _14 => _14(to), 'optionalAccess', _15 => _15.delete, 'call', _16 => _16(from)]);
|
|
121
|
+
}
|
|
122
|
+
const edges = [];
|
|
123
|
+
for (const key of spilledKeys) edges.push([key.toUpperCase(), anchor]);
|
|
124
|
+
for (const key of blockingKeys) edges.push([anchor, key.toUpperCase()]);
|
|
125
|
+
for (const [from, to] of edges) {
|
|
126
|
+
if (!this.spillDependencies.has(from)) this.spillDependencies.set(from, /* @__PURE__ */ new Set());
|
|
127
|
+
this.spillDependencies.get(from).add(to);
|
|
128
|
+
if (!this.spillDependents.has(to)) this.spillDependents.set(to, /* @__PURE__ */ new Set());
|
|
129
|
+
this.spillDependents.get(to).add(from);
|
|
130
|
+
}
|
|
131
|
+
if (edges.length > 0) this.spillEdges.set(anchor, edges);
|
|
132
|
+
else this.spillEdges.delete(anchor);
|
|
133
|
+
}
|
|
134
|
+
/** The spilled cells registered for `anchorKey` by `setSpillEdges`. */
|
|
135
|
+
getSpilledKeys(anchorKey) {
|
|
136
|
+
const anchor = anchorKey.toUpperCase();
|
|
137
|
+
return (_nullishCoalesce(this.spillEdges.get(anchor), () => ( []))).filter(([, to]) => to === anchor).map(([from]) => from);
|
|
138
|
+
}
|
|
139
|
+
/** Formula dependencies plus dynamic-array (spill) dependencies of a cell. */
|
|
88
140
|
getDependencies(cellKey) {
|
|
89
|
-
|
|
141
|
+
const key = cellKey.toUpperCase();
|
|
142
|
+
return unionOf(this.dependencies.get(key), this.spillDependencies.get(key));
|
|
90
143
|
}
|
|
144
|
+
/** Cells depending on `cellKey`, through formulas or spills. */
|
|
91
145
|
getDependents(cellKey) {
|
|
92
|
-
|
|
146
|
+
const key = cellKey.toUpperCase();
|
|
147
|
+
return unionOf(this.dependents.get(key), this.spillDependents.get(key));
|
|
93
148
|
}
|
|
94
149
|
/**
|
|
95
150
|
* Detects if there is a cycle containing cellKey.
|
|
@@ -101,7 +156,7 @@ var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.c
|
|
|
101
156
|
const dfs = (node) => {
|
|
102
157
|
visited.add(node);
|
|
103
158
|
recStack.add(node);
|
|
104
|
-
const deps = this.
|
|
159
|
+
const deps = this.getDependencies(node);
|
|
105
160
|
for (const neighbor of deps) {
|
|
106
161
|
if (!visited.has(neighbor)) {
|
|
107
162
|
if (dfs(neighbor)) return true;
|
|
@@ -180,6 +235,7 @@ var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.c
|
|
|
180
235
|
const node = queue.pop();
|
|
181
236
|
const direct = [
|
|
182
237
|
..._nullishCoalesce(this.dependents.get(node), () => ( [])),
|
|
238
|
+
..._nullishCoalesce(this.spillDependents.get(node), () => ( [])),
|
|
183
239
|
..._nullishCoalesce(this.dependents.get(columnDependencyKey(node.replace(/\d+$/, ""))), () => ( []))
|
|
184
240
|
];
|
|
185
241
|
for (const dep of direct) {
|
|
@@ -192,7 +248,7 @@ var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.c
|
|
|
192
248
|
}
|
|
193
249
|
const neighbors = (node) => {
|
|
194
250
|
const result = [];
|
|
195
|
-
for (const dep of
|
|
251
|
+
for (const dep of this.getDependencies(node)) {
|
|
196
252
|
if (dep.endsWith(":")) {
|
|
197
253
|
const col = dep.slice(0, -1);
|
|
198
254
|
for (const candidate of nodes) {
|
|
@@ -258,6 +314,11 @@ var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.c
|
|
|
258
314
|
return { order, cyclic };
|
|
259
315
|
}
|
|
260
316
|
}, _class);
|
|
317
|
+
function unionOf(a, b) {
|
|
318
|
+
if (!b || b.size === 0) return Array.from(_nullishCoalesce(a, () => ( [])));
|
|
319
|
+
if (!a || a.size === 0) return Array.from(b);
|
|
320
|
+
return Array.from(/* @__PURE__ */ new Set([...a, ...b]));
|
|
321
|
+
}
|
|
261
322
|
|
|
262
323
|
// src/spreadsheet/formula/references.ts
|
|
263
324
|
var CELL_PART = /^(\$?)([A-Za-z]+)(\$?)(\d+)$/;
|
|
@@ -268,19 +329,19 @@ function parsePart(text) {
|
|
|
268
329
|
if (cell) {
|
|
269
330
|
return {
|
|
270
331
|
colAbs: cell[1],
|
|
271
|
-
col:
|
|
332
|
+
col: _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, cell[2]),
|
|
272
333
|
rowAbs: cell[3],
|
|
273
334
|
row: parseInt(cell[4], 10) - 1
|
|
274
335
|
};
|
|
275
336
|
}
|
|
276
337
|
const column = COLUMN_PART.exec(text);
|
|
277
338
|
if (column) {
|
|
278
|
-
return { colAbs: column[1], col:
|
|
339
|
+
return { colAbs: column[1], col: _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, column[2]), rowAbs: "", row: null };
|
|
279
340
|
}
|
|
280
341
|
return null;
|
|
281
342
|
}
|
|
282
343
|
function formatPart(part) {
|
|
283
|
-
const col = `${part.colAbs}${
|
|
344
|
+
const col = `${part.colAbs}${_chunkRIKBJLS2cjs.indexToColName.call(void 0, part.col)}`;
|
|
284
345
|
return part.row === null ? col : `${col}${part.rowAbs}${part.row + 1}`;
|
|
285
346
|
}
|
|
286
347
|
function shiftCoordinate(value, change) {
|
|
@@ -327,7 +388,7 @@ function mapFormulaReferences(formula, rewrite) {
|
|
|
327
388
|
if (!formula.startsWith("=")) return formula;
|
|
328
389
|
let tokens;
|
|
329
390
|
try {
|
|
330
|
-
tokens =
|
|
391
|
+
tokens = _chunkRIKBJLS2cjs.tokenizeFormula.call(void 0, formula);
|
|
331
392
|
} catch (e2) {
|
|
332
393
|
return formula;
|
|
333
394
|
}
|
|
@@ -335,11 +396,17 @@ function mapFormulaReferences(formula, rewrite) {
|
|
|
335
396
|
let cursor = 0;
|
|
336
397
|
for (let i = 0; i < tokens.length; i++) {
|
|
337
398
|
const token = tokens[i];
|
|
338
|
-
if (token.type !== "CELL_REF" && token.type !== "RANGE") continue;
|
|
339
|
-
if (_optionalChain([tokens, 'access',
|
|
399
|
+
if (token.type !== "CELL_REF" && token.type !== "RANGE" && token.type !== "SPILL_REF") continue;
|
|
400
|
+
if (_optionalChain([tokens, 'access', _17 => _17[i + 1], 'optionalAccess', _18 => _18.type]) === "LPAREN") continue;
|
|
340
401
|
let end = token.position;
|
|
341
402
|
while (end < formula.length && REF_CHAR.test(formula[end])) end++;
|
|
342
403
|
const original = formula.slice(token.position, end);
|
|
404
|
+
if (token.type === "SPILL_REF") {
|
|
405
|
+
const rewritten = rewrite(original);
|
|
406
|
+
result += formula.slice(cursor, token.position) + (rewritten === "#REF!" ? rewritten : `${rewritten}#`);
|
|
407
|
+
cursor = end + 1;
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
343
410
|
result += formula.slice(cursor, token.position) + rewrite(original);
|
|
344
411
|
cursor = end;
|
|
345
412
|
}
|
|
@@ -459,7 +526,7 @@ function innermostCall(stack) {
|
|
|
459
526
|
}
|
|
460
527
|
var toSuggestion = (def) => ({
|
|
461
528
|
name: def.name,
|
|
462
|
-
signature:
|
|
529
|
+
signature: _chunkRIKBJLS2cjs.getFormulaSignature.call(void 0, def),
|
|
463
530
|
description: def.description,
|
|
464
531
|
category: def.category
|
|
465
532
|
});
|
|
@@ -468,20 +535,20 @@ function getFormulaHints(input, caret = input.length, options = {}) {
|
|
|
468
535
|
let suggestions = [];
|
|
469
536
|
if (context.prefix) {
|
|
470
537
|
const query = context.prefix.text.toUpperCase();
|
|
471
|
-
suggestions =
|
|
538
|
+
suggestions = _chunkRIKBJLS2cjs.searchFormulaFunctions.call(void 0, query, { limit: void 0 }).filter((def) => def.name.startsWith(query)).slice(0, _nullishCoalesce(options.limit, () => ( 8))).map(toSuggestion);
|
|
472
539
|
const followedByParen = input.slice(context.prefix.end).trimStart().startsWith("(");
|
|
473
540
|
if (followedByParen || suggestions.length === 1 && suggestions[0].name === query) suggestions = [];
|
|
474
541
|
}
|
|
475
542
|
let activeCall = null;
|
|
476
543
|
if (context.call) {
|
|
477
|
-
const def =
|
|
544
|
+
const def = _chunkRIKBJLS2cjs.getFormulaFunction.call(void 0, context.call.name);
|
|
478
545
|
if (def) {
|
|
479
|
-
const specIndex =
|
|
546
|
+
const specIndex = _chunkRIKBJLS2cjs.getFormulaArgumentSpecIndex.call(void 0, def, context.call.argIndex);
|
|
480
547
|
activeCall = {
|
|
481
548
|
name: def.name,
|
|
482
|
-
signature:
|
|
549
|
+
signature: _chunkRIKBJLS2cjs.getFormulaSignature.call(void 0, def),
|
|
483
550
|
description: def.description,
|
|
484
|
-
parts:
|
|
551
|
+
parts: _chunkRIKBJLS2cjs.getFormulaSignatureParts.call(void 0, def, context.call.argIndex),
|
|
485
552
|
argIndex: context.call.argIndex,
|
|
486
553
|
argument: specIndex >= 0 ? def.args[specIndex] : null
|
|
487
554
|
};
|
|
@@ -491,8 +558,8 @@ function getFormulaHints(input, caret = input.length, options = {}) {
|
|
|
491
558
|
}
|
|
492
559
|
function applyFormulaSuggestion(input, caret, name) {
|
|
493
560
|
const context = getFormulaCaretContext(input, caret);
|
|
494
|
-
const start = _nullishCoalesce(_optionalChain([context, 'access',
|
|
495
|
-
const end = _nullishCoalesce(_optionalChain([context, 'access',
|
|
561
|
+
const start = _nullishCoalesce(_optionalChain([context, 'access', _19 => _19.prefix, 'optionalAccess', _20 => _20.start]), () => ( caret));
|
|
562
|
+
const end = _nullishCoalesce(_optionalChain([context, 'access', _21 => _21.prefix, 'optionalAccess', _22 => _22.end]), () => ( caret));
|
|
496
563
|
const hasParen = input[end] === "(";
|
|
497
564
|
const insert = hasParen ? name.toUpperCase() : `${name.toUpperCase()}(`;
|
|
498
565
|
const value = input.slice(0, start) + insert + input.slice(end);
|
|
@@ -500,8 +567,8 @@ function applyFormulaSuggestion(input, caret, name) {
|
|
|
500
567
|
}
|
|
501
568
|
|
|
502
569
|
// src/spreadsheet/datasource/index.ts
|
|
503
|
-
var DataSourceBinder = (_class2 = class {constructor() { _class2.prototype.
|
|
504
|
-
|
|
570
|
+
var DataSourceBinder = (_class2 = class {constructor() { _class2.prototype.__init6.call(this); }
|
|
571
|
+
__init6() {this.dataSources = /* @__PURE__ */ new Map()}
|
|
505
572
|
register(dataSource) {
|
|
506
573
|
this.dataSources.set(dataSource.id, dataSource);
|
|
507
574
|
}
|
|
@@ -532,10 +599,10 @@ var DataSourceBinder = (_class2 = class {constructor() { _class2.prototype.__ini
|
|
|
532
599
|
for (const record of records) {
|
|
533
600
|
const existing = existingRecordRowMap.get(record.id);
|
|
534
601
|
nextRows.push({
|
|
535
|
-
..._optionalChain([existing, 'optionalAccess',
|
|
536
|
-
id: _optionalChain([existing, 'optionalAccess',
|
|
602
|
+
..._optionalChain([existing, 'optionalAccess', _23 => _23.hidden]) ? { hidden: true } : {},
|
|
603
|
+
id: _optionalChain([existing, 'optionalAccess', _24 => _24.id]) || `row_${record.id}`,
|
|
537
604
|
index: rowIndex++,
|
|
538
|
-
height: _optionalChain([existing, 'optionalAccess',
|
|
605
|
+
height: _optionalChain([existing, 'optionalAccess', _25 => _25.height]) || 32,
|
|
539
606
|
recordId: record.id,
|
|
540
607
|
type: "record"
|
|
541
608
|
});
|
|
@@ -617,28 +684,41 @@ function compareCellValues(a, b, direction = "asc") {
|
|
|
617
684
|
const aBlank = isBlankValue(a);
|
|
618
685
|
const bBlank = isBlankValue(b);
|
|
619
686
|
if (aBlank || bBlank) return aBlank === bBlank ? 0 : aBlank ? 1 : -1;
|
|
620
|
-
const aNum = toNumber(a);
|
|
621
|
-
const bNum = toNumber(b);
|
|
622
687
|
let result;
|
|
623
|
-
if (
|
|
624
|
-
|
|
625
|
-
else
|
|
626
|
-
|
|
688
|
+
if (isPlainText(a) && isPlainText(b) && !(_chunkRIKBJLS2cjs.parseIsoDate.call(void 0, a) && _chunkRIKBJLS2cjs.parseIsoDate.call(void 0, b))) {
|
|
689
|
+
result = compareText(a, b);
|
|
690
|
+
} else {
|
|
691
|
+
result = _chunkRIKBJLS2cjs.sortCompareValues.call(void 0, a, b);
|
|
692
|
+
}
|
|
627
693
|
if (result === 0) return 0;
|
|
628
694
|
return direction === "desc" ? -Math.sign(result) : Math.sign(result);
|
|
629
695
|
}
|
|
696
|
+
var isPlainText = (value) => typeof value === "string" && !_chunkRIKBJLS2cjs.isFormulaError.call(void 0, value);
|
|
697
|
+
function filterValue(value) {
|
|
698
|
+
if (isBlankValue(value) || _chunkRIKBJLS2cjs.isFormulaError.call(void 0, value)) return null;
|
|
699
|
+
if (typeof value === "number") return Number.isFinite(value) ? { value, kind: "number" } : null;
|
|
700
|
+
if (typeof value === "boolean") return { value, kind: "boolean" };
|
|
701
|
+
const num = _chunkRIKBJLS2cjs.numericValue.call(void 0, value);
|
|
702
|
+
if (num !== null) return { value: num, kind: "number" };
|
|
703
|
+
const text = String(value);
|
|
704
|
+
return { value: text, kind: _chunkRIKBJLS2cjs.parseIsoDate.call(void 0, text) ? "number" : "text" };
|
|
705
|
+
}
|
|
706
|
+
function filterOperand(operand) {
|
|
707
|
+
if (typeof operand !== "string") return filterValue(operand);
|
|
708
|
+
if (operand.trim() === "") return null;
|
|
709
|
+
const parsed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, operand.trim());
|
|
710
|
+
if (parsed.type === "number" || parsed.type === "date" || parsed.type === "boolean") return filterValue(parsed.value);
|
|
711
|
+
return { value: operand, kind: "text" };
|
|
712
|
+
}
|
|
630
713
|
function compareForFilter(value, operand) {
|
|
631
|
-
|
|
632
|
-
const
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
if (a !== null || b !== null) return null;
|
|
636
|
-
return compareText(String(value), String(operand));
|
|
714
|
+
const a = filterValue(value);
|
|
715
|
+
const b = filterOperand(operand);
|
|
716
|
+
if (!a || !b || a.kind !== b.kind) return null;
|
|
717
|
+
return _chunkRIKBJLS2cjs.compareValues.call(void 0, a.value, b.value);
|
|
637
718
|
}
|
|
638
719
|
function looselyEquals(value, operand) {
|
|
639
|
-
const
|
|
640
|
-
|
|
641
|
-
if (a !== null && b !== null) return a === b;
|
|
720
|
+
const c = compareForFilter(value, operand);
|
|
721
|
+
if (c !== null) return c === 0;
|
|
642
722
|
return String(_nullishCoalesce(value, () => ( ""))).trim().toLowerCase() === String(_nullishCoalesce(operand, () => ( ""))).trim().toLowerCase();
|
|
643
723
|
}
|
|
644
724
|
function matchesFilterRule(value, rule) {
|
|
@@ -713,7 +793,8 @@ function classifyFillValue(raw) {
|
|
|
713
793
|
if (raw.trim() === "") return { kind: "blank" };
|
|
714
794
|
const num = toNumber(raw);
|
|
715
795
|
if (num !== null) return { kind: "number", value: num };
|
|
716
|
-
const
|
|
796
|
+
const typed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, raw);
|
|
797
|
+
const date = ISO_DATE_PATTERN.exec(typed.type === "date" ? String(typed.value) : raw.trim());
|
|
717
798
|
if (date) {
|
|
718
799
|
const [year, month, day] = [Number(date[1]), Number(date[2]), Number(date[3])];
|
|
719
800
|
const time = Date.UTC(year, month - 1, day);
|
|
@@ -991,8 +1072,8 @@ function parseHtmlTable(html) {
|
|
|
991
1072
|
while (cellMatch = cellPattern.exec(rowMatch[1])) {
|
|
992
1073
|
while (taken.has(col)) row[col++] = "";
|
|
993
1074
|
const attrs = _nullishCoalesce(cellMatch[2], () => ( ""));
|
|
994
|
-
const colspan = Math.max(1, parseInt(_nullishCoalesce(_optionalChain([/colspan\s*=\s*["']?(\d+)/i, 'access',
|
|
995
|
-
const rowspan = Math.max(1, parseInt(_nullishCoalesce(_optionalChain([/rowspan\s*=\s*["']?(\d+)/i, 'access',
|
|
1075
|
+
const colspan = Math.max(1, parseInt(_nullishCoalesce(_optionalChain([/colspan\s*=\s*["']?(\d+)/i, 'access', _26 => _26.exec, 'call', _27 => _27(attrs), 'optionalAccess', _28 => _28[1]]), () => ( "1")), 10));
|
|
1076
|
+
const rowspan = Math.max(1, parseInt(_nullishCoalesce(_optionalChain([/rowspan\s*=\s*["']?(\d+)/i, 'access', _29 => _29.exec, 'call', _30 => _30(attrs), 'optionalAccess', _31 => _31[1]]), () => ( "1")), 10));
|
|
996
1077
|
row[col] = cellHtmlToText(cellMatch[3]);
|
|
997
1078
|
for (let c = col; c < col + colspan; c++) {
|
|
998
1079
|
if (c > col) row[c] = "";
|
|
@@ -1010,11 +1091,16 @@ function parseHtmlTable(html) {
|
|
|
1010
1091
|
return rows.length > 0 ? rows : null;
|
|
1011
1092
|
}
|
|
1012
1093
|
function createSpreadsheetClipboardData(cells, origin) {
|
|
1013
|
-
const
|
|
1014
|
-
const payload = {
|
|
1094
|
+
const texts = cells.map((row) => row.map((cell) => _nullishCoalesce(cell.text, () => ( displayText(cell.value)))));
|
|
1095
|
+
const payload = {
|
|
1096
|
+
type: "pixerate-spreadsheet",
|
|
1097
|
+
version: 1,
|
|
1098
|
+
origin,
|
|
1099
|
+
cells: cells.map((row) => row.map(({ raw, value }) => ({ raw, value })))
|
|
1100
|
+
};
|
|
1015
1101
|
return {
|
|
1016
|
-
"text/plain": serializeTsv(
|
|
1017
|
-
"text/html": serializeHtmlTable(
|
|
1102
|
+
"text/plain": serializeTsv(texts),
|
|
1103
|
+
"text/html": serializeHtmlTable(texts),
|
|
1018
1104
|
[SPREADSHEET_CLIPBOARD_MIME]: JSON.stringify(payload)
|
|
1019
1105
|
};
|
|
1020
1106
|
}
|
|
@@ -1031,7 +1117,7 @@ function readFormat(source, format) {
|
|
|
1031
1117
|
function parsePayload(json) {
|
|
1032
1118
|
try {
|
|
1033
1119
|
const payload = JSON.parse(json);
|
|
1034
|
-
if (_optionalChain([payload, 'optionalAccess',
|
|
1120
|
+
if (_optionalChain([payload, 'optionalAccess', _32 => _32.type]) !== "pixerate-spreadsheet" || !Array.isArray(payload.cells) || !payload.cells.every((row) => Array.isArray(row)) || typeof _optionalChain([payload, 'access', _33 => _33.origin, 'optionalAccess', _34 => _34.row]) !== "number" || typeof _optionalChain([payload, 'access', _35 => _35.origin, 'optionalAccess', _36 => _36.col]) !== "number") {
|
|
1035
1121
|
return null;
|
|
1036
1122
|
}
|
|
1037
1123
|
return payload;
|
|
@@ -1045,7 +1131,7 @@ function readSpreadsheetClipboard(source) {
|
|
|
1045
1131
|
return {
|
|
1046
1132
|
format: "internal",
|
|
1047
1133
|
origin: payload.origin,
|
|
1048
|
-
rows: payload.cells.map((row) => row.map((cell) => typeof _optionalChain([cell, 'optionalAccess',
|
|
1134
|
+
rows: payload.cells.map((row) => row.map((cell) => typeof _optionalChain([cell, 'optionalAccess', _37 => _37.raw]) === "string" ? cell.raw : displayText(_optionalChain([cell, 'optionalAccess', _38 => _38.value]))))
|
|
1049
1135
|
};
|
|
1050
1136
|
}
|
|
1051
1137
|
const html = readFormat(source, "text/html");
|
|
@@ -1074,8 +1160,8 @@ var DEFAULT_COLUMN_WIDTH = 130;
|
|
|
1074
1160
|
var clampCount = (value, max) => Math.max(0, Math.min(Math.floor(_nullishCoalesce(value, () => ( 0))), max));
|
|
1075
1161
|
function getTableSections(doc) {
|
|
1076
1162
|
const total = doc.rows.length;
|
|
1077
|
-
const headerRows = clampCount(_optionalChain([doc, 'access',
|
|
1078
|
-
const footerRows = clampCount(_optionalChain([doc, 'access',
|
|
1163
|
+
const headerRows = clampCount(_optionalChain([doc, 'access', _39 => _39.table, 'optionalAccess', _40 => _40.headerRowCount]), total);
|
|
1164
|
+
const footerRows = clampCount(_optionalChain([doc, 'access', _41 => _41.table, 'optionalAccess', _42 => _42.footerRowCount]), total - headerRows);
|
|
1079
1165
|
return { headerRows, footerRows };
|
|
1080
1166
|
}
|
|
1081
1167
|
function getRowSection(doc, rowIndex) {
|
|
@@ -1085,8 +1171,8 @@ function getRowSection(doc, rowIndex) {
|
|
|
1085
1171
|
return "body";
|
|
1086
1172
|
}
|
|
1087
1173
|
function rowPassesFilters(doc, rowIndex, getValue) {
|
|
1088
|
-
const filter = _optionalChain([doc, 'access',
|
|
1089
|
-
if (!_optionalChain([filter, 'optionalAccess',
|
|
1174
|
+
const filter = _optionalChain([doc, 'access', _43 => _43.table, 'optionalAccess', _44 => _44.filter]);
|
|
1175
|
+
if (!_optionalChain([filter, 'optionalAccess', _45 => _45.enabled]) || filter.rules.length === 0) return true;
|
|
1090
1176
|
if (getRowSection(doc, rowIndex) !== "body") return true;
|
|
1091
1177
|
return filter.rules.every((rule) => {
|
|
1092
1178
|
const colIndex = doc.columns.findIndex((c) => c.id === rule.colId);
|
|
@@ -1095,7 +1181,7 @@ function rowPassesFilters(doc, rowIndex, getValue) {
|
|
|
1095
1181
|
});
|
|
1096
1182
|
}
|
|
1097
1183
|
function computeRowGroups(doc, getValue) {
|
|
1098
|
-
const grouping = _optionalChain([doc, 'access',
|
|
1184
|
+
const grouping = _optionalChain([doc, 'access', _46 => _46.table, 'optionalAccess', _47 => _47.grouping]);
|
|
1099
1185
|
if (!grouping) return [];
|
|
1100
1186
|
const groupCol = doc.columns.findIndex((c) => c.id === grouping.colId);
|
|
1101
1187
|
if (groupCol === -1) return [];
|
|
@@ -1125,9 +1211,9 @@ function computeRowGroups(doc, getValue) {
|
|
|
1125
1211
|
}
|
|
1126
1212
|
function buildSpreadsheetView(doc, getValue) {
|
|
1127
1213
|
const { headerRows, footerRows } = getTableSections(doc);
|
|
1128
|
-
const frozenRows = clampCount(_optionalChain([doc, 'access',
|
|
1129
|
-
const frozenCols = clampCount(_optionalChain([doc, 'access',
|
|
1130
|
-
const headerCols = clampCount(_optionalChain([doc, 'access',
|
|
1214
|
+
const frozenRows = clampCount(_optionalChain([doc, 'access', _48 => _48.table, 'optionalAccess', _49 => _49.frozenRowCount]), doc.rows.length);
|
|
1215
|
+
const frozenCols = clampCount(_optionalChain([doc, 'access', _50 => _50.table, 'optionalAccess', _51 => _51.frozenColumnCount]), doc.columns.length);
|
|
1216
|
+
const headerCols = clampCount(_optionalChain([doc, 'access', _52 => _52.table, 'optionalAccess', _53 => _53.headerColumnCount]), doc.columns.length);
|
|
1131
1217
|
const columns = [];
|
|
1132
1218
|
let left = 0;
|
|
1133
1219
|
let hiddenColumnCount = 0;
|
|
@@ -1157,7 +1243,7 @@ function buildSpreadsheetView(doc, getValue) {
|
|
|
1157
1243
|
if (doc.rows[r].hidden) hiddenRowCount++;
|
|
1158
1244
|
else if (!rowPassesFilters(doc, r, getValue)) filteredOutCount++;
|
|
1159
1245
|
}
|
|
1160
|
-
const grouping = _optionalChain([doc, 'access',
|
|
1246
|
+
const grouping = _optionalChain([doc, 'access', _54 => _54.table, 'optionalAccess', _55 => _55.grouping]);
|
|
1161
1247
|
if (grouping && doc.columns.some((c) => c.id === grouping.colId)) {
|
|
1162
1248
|
for (const group of groups) {
|
|
1163
1249
|
rows.push({ kind: "group", group });
|
|
@@ -1191,7 +1277,7 @@ function buildSpreadsheetView(doc, getValue) {
|
|
|
1191
1277
|
while (run < visible.length && positions.get(visible[run]) === positions.get(visible[0]) + run) run++;
|
|
1192
1278
|
return { first: visible[0], run };
|
|
1193
1279
|
};
|
|
1194
|
-
for (const raw of _nullishCoalesce(_optionalChain([doc, 'access',
|
|
1280
|
+
for (const raw of _nullishCoalesce(_optionalChain([doc, 'access', _56 => _56.table, 'optionalAccess', _57 => _57.merges]), () => ( []))) {
|
|
1195
1281
|
const merge = normalizeRange(raw);
|
|
1196
1282
|
const rowIdx = [];
|
|
1197
1283
|
const colIdx = [];
|
|
@@ -1228,29 +1314,45 @@ function buildSpreadsheetView(doc, getValue) {
|
|
|
1228
1314
|
|
|
1229
1315
|
// src/spreadsheet/controller.ts
|
|
1230
1316
|
var nextIdSequence = 0;
|
|
1317
|
+
var DEFAULT_MAX_HISTORY_BYTES = 64 * 1024 * 1024;
|
|
1318
|
+
var MAX_SPILL_PASSES = 25;
|
|
1319
|
+
var spillCellId = (rowId, colId) => `${rowId}\0${colId}`;
|
|
1231
1320
|
var SpreadsheetController = (_class3 = class {
|
|
1232
1321
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1322
|
+
__init7() {this.activeCell = null}
|
|
1323
|
+
__init8() {this.selectedRange = null}
|
|
1324
|
+
__init9() {this.editingCell = null}
|
|
1325
|
+
__init10() {this.draftValue = ""}
|
|
1326
|
+
__init11() {this.binder = new DataSourceBinder()}
|
|
1327
|
+
__init12() {this.depGraph = new DependencyGraph()}
|
|
1239
1328
|
|
|
1240
1329
|
|
|
1241
1330
|
|
|
1242
1331
|
|
|
1243
1332
|
|
|
1244
1333
|
// History stack for undo/redo
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1334
|
+
__init13() {this.undoStack = []}
|
|
1335
|
+
__init14() {this.redoStack = []}
|
|
1336
|
+
__init15() {this.isApplyingHistory = false}
|
|
1337
|
+
|
|
1248
1338
|
// Set while importing TSV: history and recalculation are done once at the end.
|
|
1249
|
-
|
|
1250
|
-
|
|
1339
|
+
__init16() {this.batching = false}
|
|
1340
|
+
__init17() {this.pendingCommits = []}
|
|
1251
1341
|
// Row being evaluated, so [property] references resolve per row.
|
|
1252
|
-
|
|
1253
|
-
|
|
1342
|
+
__init18() {this.evaluatingRowIndex = null}
|
|
1343
|
+
// Cell being evaluated, for implicit intersection (`=@A:A`).
|
|
1344
|
+
__init19() {this.evaluatingCell = null}
|
|
1345
|
+
// Dynamic arrays. Spilled values are derived state: they live here, not in
|
|
1346
|
+
// the document, and every recalculation rebuilds them.
|
|
1347
|
+
__init20() {this.spills = /* @__PURE__ */ new Map()}
|
|
1348
|
+
// anchor key -> spill
|
|
1349
|
+
__init21() {this.spilledBy = /* @__PURE__ */ new Map()}
|
|
1350
|
+
// spilled cell key -> anchor key
|
|
1351
|
+
__init22() {this.spillCells = /* @__PURE__ */ new Map()}
|
|
1352
|
+
// spillCellId -> displayed cell
|
|
1353
|
+
// Cells whose spill ownership changed during the current pass.
|
|
1354
|
+
__init23() {this.spillChanges = null}
|
|
1355
|
+
constructor(options = {}) {;_class3.prototype.__init7.call(this);_class3.prototype.__init8.call(this);_class3.prototype.__init9.call(this);_class3.prototype.__init10.call(this);_class3.prototype.__init11.call(this);_class3.prototype.__init12.call(this);_class3.prototype.__init13.call(this);_class3.prototype.__init14.call(this);_class3.prototype.__init15.call(this);_class3.prototype.__init16.call(this);_class3.prototype.__init17.call(this);_class3.prototype.__init18.call(this);_class3.prototype.__init19.call(this);_class3.prototype.__init20.call(this);_class3.prototype.__init21.call(this);_class3.prototype.__init22.call(this);_class3.prototype.__init23.call(this);_class3.prototype.__init24.call(this);
|
|
1254
1356
|
const defaultCols = [
|
|
1255
1357
|
{ id: "col_a", key: "A", title: "A", width: 120, type: "freeform" },
|
|
1256
1358
|
{ id: "col_b", key: "B", title: "B", width: 120, type: "freeform" },
|
|
@@ -1264,28 +1366,32 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1264
1366
|
type: "freeform"
|
|
1265
1367
|
}));
|
|
1266
1368
|
this.document = {
|
|
1267
|
-
id: _optionalChain([options, 'access',
|
|
1268
|
-
name: _optionalChain([options, 'access',
|
|
1269
|
-
columns: _optionalChain([options, 'access',
|
|
1270
|
-
rows: _optionalChain([options, 'access',
|
|
1271
|
-
cells: _optionalChain([options, 'access',
|
|
1272
|
-
createdAt: _optionalChain([options, 'access',
|
|
1273
|
-
updatedAt: _optionalChain([options, 'access',
|
|
1274
|
-
..._optionalChain([options, 'access',
|
|
1369
|
+
id: _optionalChain([options, 'access', _58 => _58.document, 'optionalAccess', _59 => _59.id]) || `sheet_${Date.now()}`,
|
|
1370
|
+
name: _optionalChain([options, 'access', _60 => _60.document, 'optionalAccess', _61 => _61.name]) || "Sheet 1",
|
|
1371
|
+
columns: _optionalChain([options, 'access', _62 => _62.document, 'optionalAccess', _63 => _63.columns]) || defaultCols,
|
|
1372
|
+
rows: _optionalChain([options, 'access', _64 => _64.document, 'optionalAccess', _65 => _65.rows]) || defaultRows,
|
|
1373
|
+
cells: _optionalChain([options, 'access', _66 => _66.document, 'optionalAccess', _67 => _67.cells]) || {},
|
|
1374
|
+
createdAt: _optionalChain([options, 'access', _68 => _68.document, 'optionalAccess', _69 => _69.createdAt]) || Date.now(),
|
|
1375
|
+
updatedAt: _optionalChain([options, 'access', _70 => _70.document, 'optionalAccess', _71 => _71.updatedAt]) || Date.now(),
|
|
1376
|
+
..._optionalChain([options, 'access', _72 => _72.document, 'optionalAccess', _73 => _73.table]) ? { table: options.document.table } : {}
|
|
1275
1377
|
};
|
|
1276
1378
|
this.primaryDataSourceId = options.primaryDataSourceId;
|
|
1379
|
+
this.maxHistoryBytes = Math.max(0, _nullishCoalesce(options.maxHistoryBytes, () => ( DEFAULT_MAX_HISTORY_BYTES)));
|
|
1277
1380
|
this.onDocumentChange = options.onDocumentChange;
|
|
1278
1381
|
this.onSelectionChange = options.onSelectionChange;
|
|
1279
1382
|
this.onCellCommit = options.onCellCommit;
|
|
1280
1383
|
if (options.dataSources) {
|
|
1281
1384
|
options.dataSources.forEach((ds) => this.binder.register(ds));
|
|
1282
1385
|
}
|
|
1283
|
-
this.evaluator = new (0,
|
|
1386
|
+
this.evaluator = new (0, _chunkRIKBJLS2cjs.FormulaEvaluator)({
|
|
1284
1387
|
resolveCell: (colStr, rowNum) => this.resolveCellByCoord(colStr, rowNum),
|
|
1285
1388
|
resolveRange: (sCol, sRow, eCol, eRow) => this.resolveRangeByCoords(sCol, sRow, eCol, eRow),
|
|
1286
|
-
resolveProperty: (prop) => this.resolveCurrentRowProperty(prop)
|
|
1389
|
+
resolveProperty: (prop) => this.resolveCurrentRowProperty(prop),
|
|
1390
|
+
resolveSpill: (colStr, rowNum) => this.resolveSpillByCoord(colStr, rowNum),
|
|
1391
|
+
getFormulaCell: () => this.evaluatingCell
|
|
1287
1392
|
});
|
|
1288
1393
|
this.syncWithDataSource();
|
|
1394
|
+
this.rederiveTypedValues();
|
|
1289
1395
|
this.recalculateAll();
|
|
1290
1396
|
}
|
|
1291
1397
|
loadDocument(document) {
|
|
@@ -1297,9 +1403,63 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1297
1403
|
this.undoStack = [];
|
|
1298
1404
|
this.redoStack = [];
|
|
1299
1405
|
this.syncWithDataSource();
|
|
1406
|
+
this.rederiveTypedValues();
|
|
1300
1407
|
this.recalculateAll();
|
|
1301
1408
|
this.notifyChange();
|
|
1302
1409
|
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Re-parses the value of every stored typed (non-formula) cell from its
|
|
1412
|
+
* `raw` input, so documents saved before typed input was parsed (whose
|
|
1413
|
+
* values are text such as `"120"`) compare and sort as numbers. Cells of
|
|
1414
|
+
* bound columns in record rows keep their value: it belongs to the data
|
|
1415
|
+
* source.
|
|
1416
|
+
*/
|
|
1417
|
+
rederiveTypedValues() {
|
|
1418
|
+
for (const row of this.document.rows) {
|
|
1419
|
+
const cells = this.document.cells[row.id];
|
|
1420
|
+
if (!cells) continue;
|
|
1421
|
+
for (const col of this.document.columns) {
|
|
1422
|
+
const cell = cells[col.id];
|
|
1423
|
+
if (!cell || typeof cell.raw !== "string" || cell.raw.startsWith("=")) continue;
|
|
1424
|
+
if (col.type === "bound" && col.binding && row.recordId) continue;
|
|
1425
|
+
const typed = this.typedCell(cell.raw, cell.format);
|
|
1426
|
+
cell.value = typed.value;
|
|
1427
|
+
if (typed.numberFormat) cell.numberFormat = typed.numberFormat;
|
|
1428
|
+
else delete cell.numberFormat;
|
|
1429
|
+
if (typed.format) cell.format = typed.format;
|
|
1430
|
+
}
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
/**
|
|
1434
|
+
* Value of typed (non-formula) input: a number, boolean, ISO date, error
|
|
1435
|
+
* or text (see `parseCellInput`), its automatic number format, and the
|
|
1436
|
+
* `CellFormat` to use: the automatic one (currency, percentage, date,
|
|
1437
|
+
* number) when `format` is unset or `text` (the default of new columns).
|
|
1438
|
+
*/
|
|
1439
|
+
typedCell(raw, format) {
|
|
1440
|
+
const parsed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, raw);
|
|
1441
|
+
return {
|
|
1442
|
+
value: parsed.value,
|
|
1443
|
+
...parsed.numberFormat ? { numberFormat: parsed.numberFormat } : {},
|
|
1444
|
+
format: parsed.cellFormat && (!format || format === "text") ? parsed.cellFormat : format
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
/**
|
|
1448
|
+
* Typed input for a bound field, coerced by the field's declared type:
|
|
1449
|
+
* number, boolean and date fields get a number, boolean or ISO date when
|
|
1450
|
+
* the input parses as one; string and enum fields (and unknown fields)
|
|
1451
|
+
* keep the text exactly as typed.
|
|
1452
|
+
*/
|
|
1453
|
+
boundInputValue(dataSourceId, field, raw) {
|
|
1454
|
+
if (raw.startsWith("=")) return raw;
|
|
1455
|
+
const type = _optionalChain([this, 'access', _74 => _74.binder, 'access', _75 => _75.getDataSource, 'call', _76 => _76(dataSourceId), 'optionalAccess', _77 => _77.getFields, 'call', _78 => _78(), 'access', _79 => _79.find, 'call', _80 => _80((f) => f.key === field), 'optionalAccess', _81 => _81.type]);
|
|
1456
|
+
if (type !== "number" && type !== "boolean" && type !== "date") return raw;
|
|
1457
|
+
const parsed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, raw);
|
|
1458
|
+
if (type === "number" && parsed.type === "number") return parsed.value;
|
|
1459
|
+
if (type === "boolean" && parsed.type === "boolean") return parsed.value;
|
|
1460
|
+
if (type === "date" && parsed.type === "date") return parsed.value;
|
|
1461
|
+
return raw;
|
|
1462
|
+
}
|
|
1303
1463
|
registerDataSource(ds) {
|
|
1304
1464
|
this.binder.register(ds);
|
|
1305
1465
|
this.syncWithDataSource();
|
|
@@ -1320,7 +1480,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1320
1480
|
r.index = idx;
|
|
1321
1481
|
});
|
|
1322
1482
|
this.document.columns.forEach((c, idx) => {
|
|
1323
|
-
c.key =
|
|
1483
|
+
c.key = _chunkRIKBJLS2cjs.indexToColName.call(void 0, idx);
|
|
1324
1484
|
});
|
|
1325
1485
|
}
|
|
1326
1486
|
getColumn(colIdOrKey) {
|
|
@@ -1335,7 +1495,12 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1335
1495
|
return this.document.rows.find((r) => r.id === rowIdOrIndex);
|
|
1336
1496
|
}
|
|
1337
1497
|
getCell(rowId, colId) {
|
|
1338
|
-
const existing = _optionalChain([this, 'access',
|
|
1498
|
+
const existing = _optionalChain([this, 'access', _82 => _82.document, 'access', _83 => _83.cells, 'access', _84 => _84[rowId], 'optionalAccess', _85 => _85[colId]]);
|
|
1499
|
+
if (existing && existing.raw !== "") return existing;
|
|
1500
|
+
if (this.spillCells.size > 0) {
|
|
1501
|
+
const spilled = this.spillCells.get(spillCellId(rowId, colId));
|
|
1502
|
+
if (spilled) return spilled;
|
|
1503
|
+
}
|
|
1339
1504
|
if (existing) return existing;
|
|
1340
1505
|
const col = this.document.columns.find((c) => c.id === colId);
|
|
1341
1506
|
const row = this.document.rows.find((r) => r.id === rowId);
|
|
@@ -1362,7 +1527,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1362
1527
|
format: col.format
|
|
1363
1528
|
};
|
|
1364
1529
|
}
|
|
1365
|
-
return { raw: "", value: "", format: _optionalChain([col, 'optionalAccess',
|
|
1530
|
+
return { raw: "", value: "", format: _optionalChain([col, 'optionalAccess', _86 => _86.format]) };
|
|
1366
1531
|
}
|
|
1367
1532
|
setCellValue(rowId, colId, raw) {
|
|
1368
1533
|
this.recordSnapshot();
|
|
@@ -1371,21 +1536,20 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1371
1536
|
}
|
|
1372
1537
|
const col = this.document.columns.find((c) => c.id === colId);
|
|
1373
1538
|
const row = this.document.rows.find((r) => r.id === rowId);
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1539
|
+
const isFormula = raw.startsWith("=");
|
|
1540
|
+
let cell;
|
|
1541
|
+
if (_optionalChain([col, 'optionalAccess', _87 => _87.type]) === "bound" && col.binding && _optionalChain([row, 'optionalAccess', _88 => _88.recordId])) {
|
|
1542
|
+
const value = this.boundInputValue(col.binding.dataSource, col.binding.field, raw);
|
|
1543
|
+
this.binder.commitBoundValue(col.binding.dataSource, row.recordId, col.binding.field, value);
|
|
1544
|
+
cell = { raw, value, format: col.format };
|
|
1545
|
+
} else if (isFormula) {
|
|
1546
|
+
cell = { raw, value: raw, format: _optionalChain([col, 'optionalAccess', _89 => _89.format]) };
|
|
1547
|
+
} else {
|
|
1548
|
+
cell = { raw, ...this.typedCell(raw, _optionalChain([col, 'optionalAccess', _90 => _90.format])) };
|
|
1381
1549
|
}
|
|
1382
1550
|
const cellKey = this.getCellKey(rowId, colId);
|
|
1383
|
-
this.depGraph.setCellFormula(cellKey,
|
|
1384
|
-
this.document.cells[rowId][colId] =
|
|
1385
|
-
raw,
|
|
1386
|
-
value: raw,
|
|
1387
|
-
format: _optionalChain([col, 'optionalAccess', _71 => _71.format])
|
|
1388
|
-
};
|
|
1551
|
+
this.depGraph.setCellFormula(cellKey, isFormula ? raw : null);
|
|
1552
|
+
this.document.cells[rowId][colId] = cell;
|
|
1389
1553
|
this.document.updatedAt = Date.now();
|
|
1390
1554
|
if (this.batching) {
|
|
1391
1555
|
this.pendingCommits.push([rowId, colId, raw]);
|
|
@@ -1393,8 +1557,8 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1393
1557
|
}
|
|
1394
1558
|
this.recalculateCell(rowId, colId);
|
|
1395
1559
|
this.notifyChange();
|
|
1396
|
-
const evaluatedVal = _optionalChain([this, 'access',
|
|
1397
|
-
_optionalChain([this, 'access',
|
|
1560
|
+
const evaluatedVal = _optionalChain([this, 'access', _91 => _91.document, 'access', _92 => _92.cells, 'access', _93 => _93[rowId], 'access', _94 => _94[colId], 'optionalAccess', _95 => _95.value]);
|
|
1561
|
+
_optionalChain([this, 'access', _96 => _96.onCellCommit, 'optionalCall', _97 => _97(rowId, colId, raw, evaluatedVal)]);
|
|
1398
1562
|
}
|
|
1399
1563
|
getCellKey(rowId, colId) {
|
|
1400
1564
|
const row = this.document.rows.find((r) => r.id === rowId);
|
|
@@ -1408,7 +1572,30 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1408
1572
|
*/
|
|
1409
1573
|
recalculateCell(rowId, colId) {
|
|
1410
1574
|
const cellKey = this.getCellKey(rowId, colId);
|
|
1411
|
-
this.
|
|
1575
|
+
const anchor = this.spilledBy.get(cellKey);
|
|
1576
|
+
this.recalculateKeys(anchor ? [cellKey, anchor] : [cellKey], true);
|
|
1577
|
+
}
|
|
1578
|
+
/**
|
|
1579
|
+
* Recalculates `keys` (and, with `includeDependents`, their dependents) in
|
|
1580
|
+
* dependency order. Spill ranges are only known after evaluating their
|
|
1581
|
+
* anchors, so when a pass changes which cells hold spilled values (and so
|
|
1582
|
+
* the dependency graph), the dependents of those cells are recalculated in
|
|
1583
|
+
* another pass, until nothing changes.
|
|
1584
|
+
*/
|
|
1585
|
+
recalculateKeys(keys, includeDependents) {
|
|
1586
|
+
let pending = Array.from(keys);
|
|
1587
|
+
let withDependents = includeDependents;
|
|
1588
|
+
for (let pass = 0; pass < MAX_SPILL_PASSES && pending.length > 0; pass++) {
|
|
1589
|
+
const changed = /* @__PURE__ */ new Set();
|
|
1590
|
+
this.spillChanges = changed;
|
|
1591
|
+
try {
|
|
1592
|
+
this.runEvaluationPlan(this.depGraph.getEvaluationPlan(pending, { includeDependents: withDependents }));
|
|
1593
|
+
} finally {
|
|
1594
|
+
this.spillChanges = null;
|
|
1595
|
+
}
|
|
1596
|
+
pending = Array.from(changed);
|
|
1597
|
+
withDependents = true;
|
|
1598
|
+
}
|
|
1412
1599
|
}
|
|
1413
1600
|
/**
|
|
1414
1601
|
* Rebuilds the dependency graph from scratch and recalculates every formula
|
|
@@ -1416,10 +1603,13 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1416
1603
|
*/
|
|
1417
1604
|
recalculateAll() {
|
|
1418
1605
|
this.depGraph.clear();
|
|
1606
|
+
this.spills.clear();
|
|
1607
|
+
this.spilledBy.clear();
|
|
1608
|
+
this.spillCells.clear();
|
|
1419
1609
|
const formulaKeys = [];
|
|
1420
1610
|
for (const row of this.document.rows) {
|
|
1421
1611
|
for (const col of this.document.columns) {
|
|
1422
|
-
const cell = _nullishCoalesce(_optionalChain([this, 'access',
|
|
1612
|
+
const cell = _nullishCoalesce(_optionalChain([this, 'access', _98 => _98.document, 'access', _99 => _99.cells, 'access', _100 => _100[row.id], 'optionalAccess', _101 => _101[col.id]]), () => ( this.getDerivedCell(row, col)));
|
|
1423
1613
|
if (cell.raw.startsWith("=")) {
|
|
1424
1614
|
const cellKey = `${col.key}${row.index + 1}`.toUpperCase();
|
|
1425
1615
|
this.depGraph.setCellFormula(cellKey, cell.raw);
|
|
@@ -1427,7 +1617,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1427
1617
|
}
|
|
1428
1618
|
}
|
|
1429
1619
|
}
|
|
1430
|
-
this.
|
|
1620
|
+
this.recalculateKeys(formulaKeys, false);
|
|
1431
1621
|
}
|
|
1432
1622
|
runEvaluationPlan(plan) {
|
|
1433
1623
|
for (const key of plan.order) {
|
|
@@ -1454,7 +1644,10 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1454
1644
|
if (!this.document.cells[row.id]) this.document.cells[row.id] = {};
|
|
1455
1645
|
const deps = this.depGraph.getDependencies(cellKey);
|
|
1456
1646
|
const selfReference = deps.includes(cellKey) || deps.includes(`${col.key.toUpperCase()}:`);
|
|
1457
|
-
const
|
|
1647
|
+
const spilledKeys = this.depGraph.getSpilledKeys(cellKey);
|
|
1648
|
+
const ownSpill = deps.find((dep) => spilledKeys.includes(dep));
|
|
1649
|
+
const errorMessage = selfReference ? "This formula can't reference its own cell." : ownSpill ? `This formula refers to ${ownSpill}, which holds its own spilled results (a circular reference).` : "This formula is part of a circular reference: it depends on its own result through other cells.";
|
|
1650
|
+
this.clearSpill(cellKey.toUpperCase(), true);
|
|
1458
1651
|
this.document.cells[row.id][col.id] = { ...cell, value: "#CYCLE!", error: "#CYCLE!", errorMessage };
|
|
1459
1652
|
}
|
|
1460
1653
|
evalSingleCellByKey(cellKey) {
|
|
@@ -1471,26 +1664,177 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1471
1664
|
cell.error = void 0;
|
|
1472
1665
|
cell.errorMessage = void 0;
|
|
1473
1666
|
}
|
|
1667
|
+
this.clearSpill(`${colName}${rowNum}`);
|
|
1474
1668
|
return;
|
|
1475
1669
|
}
|
|
1476
1670
|
try {
|
|
1477
1671
|
this.evaluatingRowIndex = rowNum - 1;
|
|
1672
|
+
this.evaluatingCell = { col: colName, row: rowNum };
|
|
1478
1673
|
const result = this.evaluator.evaluateWithDiagnostics(cell.raw);
|
|
1479
1674
|
if (!this.document.cells[row.id]) {
|
|
1480
1675
|
this.document.cells[row.id] = {};
|
|
1481
1676
|
}
|
|
1677
|
+
let { value, error, message } = result;
|
|
1678
|
+
if (result.array) {
|
|
1679
|
+
const blocked = this.placeSpill(`${colName}${rowNum}`, rowNum - 1, this.document.columns.indexOf(col), result.array);
|
|
1680
|
+
if (blocked) {
|
|
1681
|
+
value = "#SPILL!";
|
|
1682
|
+
error = "#SPILL!";
|
|
1683
|
+
message = blocked;
|
|
1684
|
+
}
|
|
1685
|
+
} else {
|
|
1686
|
+
this.clearSpill(`${colName}${rowNum}`);
|
|
1687
|
+
}
|
|
1482
1688
|
this.document.cells[row.id][col.id] = {
|
|
1483
1689
|
...cell,
|
|
1484
|
-
value
|
|
1690
|
+
value,
|
|
1485
1691
|
// `#ERROR!` (malformed formula, wrong argument count) keeps its
|
|
1486
1692
|
// message in `error`, as before; other errors store their code.
|
|
1487
|
-
error:
|
|
1488
|
-
errorMessage:
|
|
1693
|
+
error: error === "#ERROR!" ? message : error,
|
|
1694
|
+
errorMessage: message
|
|
1489
1695
|
};
|
|
1490
1696
|
} finally {
|
|
1491
1697
|
this.evaluatingRowIndex = null;
|
|
1698
|
+
this.evaluatingCell = null;
|
|
1492
1699
|
}
|
|
1493
1700
|
}
|
|
1701
|
+
// --- Dynamic arrays (spilling) ---
|
|
1702
|
+
/**
|
|
1703
|
+
* Spills `array` from the anchor at (row, col) into the cells below and to
|
|
1704
|
+
* the right. Returns why it can't (the anchor then shows `#SPILL!`), or
|
|
1705
|
+
* null once placed. The grid never grows to fit an array, as in Excel.
|
|
1706
|
+
*/
|
|
1707
|
+
placeSpill(anchor, row, col, array) {
|
|
1708
|
+
const { rows, cols } = array;
|
|
1709
|
+
const area = { startRow: row, startCol: col, endRow: row + rows - 1, endCol: col + cols - 1 };
|
|
1710
|
+
const label = `${_chunkRIKBJLS2cjs.indexToColName.call(void 0, area.startCol)}${area.startRow + 1}:${_chunkRIKBJLS2cjs.indexToColName.call(void 0, area.endCol)}${area.endRow + 1}`;
|
|
1711
|
+
let reason = null;
|
|
1712
|
+
const blockers = [];
|
|
1713
|
+
if (area.endRow >= this.document.rows.length || area.endCol >= this.document.columns.length) {
|
|
1714
|
+
reason = `The ${rows}\xD7${cols} result needs ${label}, which extends past the edge of the sheet.`;
|
|
1715
|
+
} else if (this.getMerges().some((m) => rangesIntersect(m, area))) {
|
|
1716
|
+
reason = `The result can't spill into merged cells (it needs ${label}).`;
|
|
1717
|
+
} else {
|
|
1718
|
+
for (let c = area.startCol; c <= area.endCol; c++) {
|
|
1719
|
+
const column = this.document.columns[c];
|
|
1720
|
+
for (let r = area.startRow; r <= area.endRow; r++) {
|
|
1721
|
+
if (r === row && c === col) continue;
|
|
1722
|
+
const rowObj = this.document.rows[r];
|
|
1723
|
+
const key = `${column.key}${r + 1}`.toUpperCase();
|
|
1724
|
+
const stored = _optionalChain([this, 'access', _102 => _102.document, 'access', _103 => _103.cells, 'access', _104 => _104[rowObj.id], 'optionalAccess', _105 => _105[column.id]]);
|
|
1725
|
+
const raw = stored ? stored.raw : this.getDerivedCell(rowObj, column).raw;
|
|
1726
|
+
const owner = this.spilledBy.get(key);
|
|
1727
|
+
if (raw !== "") {
|
|
1728
|
+
blockers.push(key);
|
|
1729
|
+
reason ??= `The result needs ${label}, but ${key} isn't empty.`;
|
|
1730
|
+
} else if (owner && owner !== anchor) {
|
|
1731
|
+
blockers.push(key);
|
|
1732
|
+
reason ??= `The result needs ${label}, but ${key} already holds values spilled from ${owner}.`;
|
|
1733
|
+
}
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
if (reason) {
|
|
1738
|
+
this.clearSpill(anchor);
|
|
1739
|
+
this.depGraph.setSpillEdges(anchor, [], blockers);
|
|
1740
|
+
return reason;
|
|
1741
|
+
}
|
|
1742
|
+
const previous = this.spills.get(anchor);
|
|
1743
|
+
const cells = [];
|
|
1744
|
+
for (let c = 0; c < cols; c++) {
|
|
1745
|
+
const column = this.document.columns[col + c];
|
|
1746
|
+
for (let r = 0; r < rows; r++) {
|
|
1747
|
+
if (r === 0 && c === 0) continue;
|
|
1748
|
+
const rowObj = this.document.rows[row + r];
|
|
1749
|
+
const key = `${column.key}${row + r + 1}`.toUpperCase();
|
|
1750
|
+
const value = _nullishCoalesce(array.values[c * rows + r], () => ( ""));
|
|
1751
|
+
const display = { raw: "", value, format: column.format, spillAnchor: anchor };
|
|
1752
|
+
if (_chunkRIKBJLS2cjs.isFormulaError.call(void 0, value)) {
|
|
1753
|
+
display.error = value;
|
|
1754
|
+
display.errorMessage = _chunkRIKBJLS2cjs.describeFormulaError.call(void 0, value);
|
|
1755
|
+
}
|
|
1756
|
+
this.spillCells.set(spillCellId(rowObj.id, column.id), display);
|
|
1757
|
+
if (this.spilledBy.get(key) !== anchor) {
|
|
1758
|
+
this.spilledBy.set(key, anchor);
|
|
1759
|
+
_optionalChain([this, 'access', _106 => _106.spillChanges, 'optionalAccess', _107 => _107.add, 'call', _108 => _108(key)]);
|
|
1760
|
+
}
|
|
1761
|
+
cells.push({ key, rowId: rowObj.id, colId: column.id });
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
if (previous) {
|
|
1765
|
+
const kept = new Set(cells.map((cell) => cell.key));
|
|
1766
|
+
for (const old of previous.cells) {
|
|
1767
|
+
if (kept.has(old.key)) continue;
|
|
1768
|
+
this.forgetSpilledCell(anchor, old);
|
|
1769
|
+
}
|
|
1770
|
+
}
|
|
1771
|
+
this.spills.set(anchor, { anchor, row, col, rows, cols, values: array.values, cells });
|
|
1772
|
+
this.depGraph.setSpillEdges(anchor, cells.map((cell) => cell.key));
|
|
1773
|
+
return null;
|
|
1774
|
+
}
|
|
1775
|
+
/** Removes the array spilled from `anchor`. With `keepEdges`, its dependency edges stay. */
|
|
1776
|
+
clearSpill(anchor, keepEdges = false) {
|
|
1777
|
+
const record = this.spills.get(anchor);
|
|
1778
|
+
if (record) {
|
|
1779
|
+
for (const cell of record.cells) this.forgetSpilledCell(anchor, cell);
|
|
1780
|
+
this.spills.delete(anchor);
|
|
1781
|
+
}
|
|
1782
|
+
if (!keepEdges) this.depGraph.setSpillEdges(anchor, []);
|
|
1783
|
+
}
|
|
1784
|
+
forgetSpilledCell(anchor, cell) {
|
|
1785
|
+
if (this.spilledBy.get(cell.key) !== anchor) return;
|
|
1786
|
+
this.spilledBy.delete(cell.key);
|
|
1787
|
+
this.spillCells.delete(spillCellId(cell.rowId, cell.colId));
|
|
1788
|
+
_optionalChain([this, 'access', _109 => _109.spillChanges, 'optionalAccess', _110 => _110.add, 'call', _111 => _111(cell.key)]);
|
|
1789
|
+
}
|
|
1790
|
+
resolveSpillByCoord(colStr, rowNum) {
|
|
1791
|
+
const record = this.spills.get(`${colStr}${rowNum}`.toUpperCase());
|
|
1792
|
+
if (record) return { rows: record.rows, cols: record.cols, values: record.values };
|
|
1793
|
+
const value = this.resolveCellByCoord(colStr, rowNum);
|
|
1794
|
+
return _chunkRIKBJLS2cjs.isFormulaError.call(void 0, value) ? value : "#REF!";
|
|
1795
|
+
}
|
|
1796
|
+
toSpill(record) {
|
|
1797
|
+
const row = this.document.rows[record.row];
|
|
1798
|
+
const col = this.document.columns[record.col];
|
|
1799
|
+
return {
|
|
1800
|
+
key: record.anchor,
|
|
1801
|
+
anchor: { row: record.row, col: record.col },
|
|
1802
|
+
range: {
|
|
1803
|
+
startRow: record.row,
|
|
1804
|
+
startCol: record.col,
|
|
1805
|
+
endRow: record.row + record.rows - 1,
|
|
1806
|
+
endCol: record.col + record.cols - 1
|
|
1807
|
+
},
|
|
1808
|
+
formula: row && col ? this.getCell(row.id, col.id).raw : ""
|
|
1809
|
+
};
|
|
1810
|
+
}
|
|
1811
|
+
/**
|
|
1812
|
+
* The dynamic array covering (row, col), whether it is the anchor (the cell
|
|
1813
|
+
* holding the formula) or a spilled cell; null when there is none.
|
|
1814
|
+
*/
|
|
1815
|
+
getSpillAt(row, col) {
|
|
1816
|
+
if (this.spills.size === 0) return null;
|
|
1817
|
+
const key = `${_chunkRIKBJLS2cjs.indexToColName.call(void 0, col)}${row + 1}`;
|
|
1818
|
+
const record = _nullishCoalesce(this.spills.get(key), () => ( this.spills.get(_nullishCoalesce(this.spilledBy.get(key), () => ( "")))));
|
|
1819
|
+
return record ? this.toSpill(record) : null;
|
|
1820
|
+
}
|
|
1821
|
+
/** Every dynamic array currently spilled. */
|
|
1822
|
+
getSpills() {
|
|
1823
|
+
return Array.from(this.spills.values(), (record) => this.toSpill(record));
|
|
1824
|
+
}
|
|
1825
|
+
/** Whether `range` overlaps a spilled array (its anchor or spilled cells). */
|
|
1826
|
+
intersectsSpill(range) {
|
|
1827
|
+
for (const record of this.spills.values()) {
|
|
1828
|
+
const area = {
|
|
1829
|
+
startRow: record.row,
|
|
1830
|
+
startCol: record.col,
|
|
1831
|
+
endRow: record.row + record.rows - 1,
|
|
1832
|
+
endCol: record.col + record.cols - 1
|
|
1833
|
+
};
|
|
1834
|
+
if (rangesIntersect(area, range)) return true;
|
|
1835
|
+
}
|
|
1836
|
+
return false;
|
|
1837
|
+
}
|
|
1494
1838
|
resolveCellByCoord(colStr, rowNum) {
|
|
1495
1839
|
const col = this.document.columns.find((c) => c.key.toUpperCase() === colStr.toUpperCase());
|
|
1496
1840
|
const row = this.document.rows[rowNum - 1];
|
|
@@ -1498,15 +1842,15 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1498
1842
|
return _nullishCoalesce(this.getCell(row.id, col.id).value, () => ( ""));
|
|
1499
1843
|
}
|
|
1500
1844
|
resolveRangeByCoords(sCol, sRow, eCol, eRow) {
|
|
1501
|
-
const startC =
|
|
1502
|
-
const endC =
|
|
1845
|
+
const startC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, sCol);
|
|
1846
|
+
const endC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, eCol);
|
|
1503
1847
|
const minC = Math.min(startC, endC);
|
|
1504
1848
|
const maxC = Math.max(startC, endC);
|
|
1505
1849
|
const minR = Math.min(sRow, eRow);
|
|
1506
|
-
const maxR = Math.min(Math.max(sRow, eRow),
|
|
1850
|
+
const maxR = Math.min(Math.max(sRow, eRow), _chunkRIKBJLS2cjs.WHOLE_COLUMN_END_ROW, this.document.rows.length);
|
|
1507
1851
|
const results = [];
|
|
1508
1852
|
for (let c = minC; c <= maxC; c++) {
|
|
1509
|
-
const colName =
|
|
1853
|
+
const colName = _chunkRIKBJLS2cjs.indexToColName.call(void 0, c);
|
|
1510
1854
|
const col = this.document.columns.find((colDef) => colDef.key.toUpperCase() === colName);
|
|
1511
1855
|
if (!col) continue;
|
|
1512
1856
|
for (let r = minR; r <= maxR; r++) {
|
|
@@ -1518,7 +1862,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1518
1862
|
return results;
|
|
1519
1863
|
}
|
|
1520
1864
|
resolveCurrentRowProperty(prop) {
|
|
1521
|
-
const rowIndex = _nullishCoalesce(this.evaluatingRowIndex, () => ( _optionalChain([this, 'access',
|
|
1865
|
+
const rowIndex = _nullishCoalesce(this.evaluatingRowIndex, () => ( _optionalChain([this, 'access', _112 => _112.activeCell, 'optionalAccess', _113 => _113.row])));
|
|
1522
1866
|
if (rowIndex === void 0 || rowIndex === null) return 0;
|
|
1523
1867
|
const row = this.document.rows[rowIndex];
|
|
1524
1868
|
if (!row || !row.recordId || !this.primaryDataSourceId) return 0;
|
|
@@ -1536,8 +1880,8 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1536
1880
|
this.activeCell = {
|
|
1537
1881
|
row: activeRow,
|
|
1538
1882
|
col: activeCol,
|
|
1539
|
-
rowId: _optionalChain([rowObj, 'optionalAccess',
|
|
1540
|
-
colId: _optionalChain([colObj, 'optionalAccess',
|
|
1883
|
+
rowId: _optionalChain([rowObj, 'optionalAccess', _114 => _114.id]),
|
|
1884
|
+
colId: _optionalChain([colObj, 'optionalAccess', _115 => _115.id])
|
|
1541
1885
|
};
|
|
1542
1886
|
if (extendSelection && this.selectedRange) {
|
|
1543
1887
|
this.selectedRange = this.expandRangeToMerges({
|
|
@@ -1556,16 +1900,16 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1556
1900
|
endCol: clampedCol
|
|
1557
1901
|
};
|
|
1558
1902
|
}
|
|
1559
|
-
_optionalChain([this, 'access',
|
|
1903
|
+
_optionalChain([this, 'access', _116 => _116.onSelectionChange, 'optionalCall', _117 => _117(this.activeCell, this.selectedRange)]);
|
|
1560
1904
|
}
|
|
1561
1905
|
selectRange(range) {
|
|
1562
1906
|
this.selectedRange = range;
|
|
1563
|
-
_optionalChain([this, 'access',
|
|
1907
|
+
_optionalChain([this, 'access', _118 => _118.onSelectionChange, 'optionalCall', _119 => _119(this.activeCell, this.selectedRange)]);
|
|
1564
1908
|
}
|
|
1565
1909
|
startEditing(row, col, initialValue) {
|
|
1566
|
-
this.selectCell(_nullishCoalesce(_nullishCoalesce(row, () => ( _optionalChain([this, 'access',
|
|
1567
|
-
const targetRow = _nullishCoalesce(_optionalChain([this, 'access',
|
|
1568
|
-
const targetCol = _nullishCoalesce(_optionalChain([this, 'access',
|
|
1910
|
+
this.selectCell(_nullishCoalesce(_nullishCoalesce(row, () => ( _optionalChain([this, 'access', _120 => _120.activeCell, 'optionalAccess', _121 => _121.row]))), () => ( 0)), _nullishCoalesce(_nullishCoalesce(col, () => ( _optionalChain([this, 'access', _122 => _122.activeCell, 'optionalAccess', _123 => _123.col]))), () => ( 0)));
|
|
1911
|
+
const targetRow = _nullishCoalesce(_optionalChain([this, 'access', _124 => _124.activeCell, 'optionalAccess', _125 => _125.row]), () => ( 0));
|
|
1912
|
+
const targetCol = _nullishCoalesce(_optionalChain([this, 'access', _126 => _126.activeCell, 'optionalAccess', _127 => _127.col]), () => ( 0));
|
|
1569
1913
|
const rowObj = this.document.rows[targetRow];
|
|
1570
1914
|
const colObj = this.document.columns[targetCol];
|
|
1571
1915
|
if (!rowObj || !colObj) return;
|
|
@@ -1619,17 +1963,17 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1619
1963
|
// --- Grid Structure Mutations ---
|
|
1620
1964
|
insertColumn(index, config) {
|
|
1621
1965
|
this.recordSnapshot();
|
|
1622
|
-
const newId = _optionalChain([config, 'optionalAccess',
|
|
1966
|
+
const newId = _optionalChain([config, 'optionalAccess', _128 => _128.id]) || this.generateId("col");
|
|
1623
1967
|
const newCol = {
|
|
1624
1968
|
id: newId,
|
|
1625
|
-
key:
|
|
1626
|
-
title: _optionalChain([config, 'optionalAccess',
|
|
1627
|
-
width: _optionalChain([config, 'optionalAccess',
|
|
1628
|
-
type: _optionalChain([config, 'optionalAccess',
|
|
1629
|
-
binding: _optionalChain([config, 'optionalAccess',
|
|
1630
|
-
formula: _optionalChain([config, 'optionalAccess',
|
|
1631
|
-
format: _optionalChain([config, 'optionalAccess',
|
|
1632
|
-
readOnly: _optionalChain([config, 'optionalAccess',
|
|
1969
|
+
key: _chunkRIKBJLS2cjs.indexToColName.call(void 0, index),
|
|
1970
|
+
title: _optionalChain([config, 'optionalAccess', _129 => _129.title]) || _chunkRIKBJLS2cjs.indexToColName.call(void 0, index),
|
|
1971
|
+
width: _optionalChain([config, 'optionalAccess', _130 => _130.width]) || 130,
|
|
1972
|
+
type: _optionalChain([config, 'optionalAccess', _131 => _131.type]) || "freeform",
|
|
1973
|
+
binding: _optionalChain([config, 'optionalAccess', _132 => _132.binding]),
|
|
1974
|
+
formula: _optionalChain([config, 'optionalAccess', _133 => _133.formula]),
|
|
1975
|
+
format: _optionalChain([config, 'optionalAccess', _134 => _134.format]) || "text",
|
|
1976
|
+
readOnly: _optionalChain([config, 'optionalAccess', _135 => _135.readOnly])
|
|
1633
1977
|
};
|
|
1634
1978
|
this.shiftReferences({ axis: "col", index, type: "insert" });
|
|
1635
1979
|
this.adjustTableForStructuralChange({ axis: "col", index, type: "insert" });
|
|
@@ -1654,13 +1998,13 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1654
1998
|
}
|
|
1655
1999
|
insertRow(index, config) {
|
|
1656
2000
|
this.recordSnapshot();
|
|
1657
|
-
const newId = _optionalChain([config, 'optionalAccess',
|
|
2001
|
+
const newId = _optionalChain([config, 'optionalAccess', _136 => _136.id]) || this.generateId("row");
|
|
1658
2002
|
const newRow = {
|
|
1659
2003
|
id: newId,
|
|
1660
2004
|
index,
|
|
1661
|
-
height: _optionalChain([config, 'optionalAccess',
|
|
1662
|
-
recordId: _optionalChain([config, 'optionalAccess',
|
|
1663
|
-
type: _optionalChain([config, 'optionalAccess',
|
|
2005
|
+
height: _optionalChain([config, 'optionalAccess', _137 => _137.height]) || 32,
|
|
2006
|
+
recordId: _optionalChain([config, 'optionalAccess', _138 => _138.recordId]),
|
|
2007
|
+
type: _optionalChain([config, 'optionalAccess', _139 => _139.type]) || "freeform"
|
|
1664
2008
|
};
|
|
1665
2009
|
this.shiftReferences({ axis: "row", index, type: "insert" });
|
|
1666
2010
|
this.adjustTableForStructuralChange({ axis: "row", index, type: "insert" });
|
|
@@ -1691,14 +2035,14 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1691
2035
|
shiftReferences(change) {
|
|
1692
2036
|
for (const rowCells of Object.values(this.document.cells)) {
|
|
1693
2037
|
for (const cell of Object.values(rowCells)) {
|
|
1694
|
-
if (_optionalChain([cell, 'access',
|
|
2038
|
+
if (_optionalChain([cell, 'access', _140 => _140.raw, 'optionalAccess', _141 => _141.startsWith, 'call', _142 => _142("=")])) {
|
|
1695
2039
|
cell.raw = shiftFormulaReferences(cell.raw, change);
|
|
1696
2040
|
}
|
|
1697
2041
|
}
|
|
1698
2042
|
}
|
|
1699
2043
|
if (change.axis === "col") {
|
|
1700
2044
|
for (const col of this.document.columns) {
|
|
1701
|
-
if (_optionalChain([col, 'access',
|
|
2045
|
+
if (_optionalChain([col, 'access', _143 => _143.formula, 'optionalAccess', _144 => _144.startsWith, 'call', _145 => _145("=")])) {
|
|
1702
2046
|
col.formula = shiftFormulaReferences(col.formula, change);
|
|
1703
2047
|
}
|
|
1704
2048
|
}
|
|
@@ -1721,7 +2065,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1721
2065
|
let maxLen = (col.title || "").length + (col.key ? col.key.length + 3 : 0);
|
|
1722
2066
|
for (const row of this.document.rows) {
|
|
1723
2067
|
const cell = this.getCell(row.id, col.id);
|
|
1724
|
-
const valStr =
|
|
2068
|
+
const valStr = _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cell);
|
|
1725
2069
|
if (valStr.length > maxLen) {
|
|
1726
2070
|
maxLen = valStr.length;
|
|
1727
2071
|
}
|
|
@@ -1745,8 +2089,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1745
2089
|
) : this.document.columns;
|
|
1746
2090
|
return rows.map(
|
|
1747
2091
|
(row) => columns.map((col) => {
|
|
1748
|
-
|
|
1749
|
-
return String(_nullishCoalesce(cell.value, () => ( ""))).replace(/\t/g, " ");
|
|
2092
|
+
return _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, this.getCell(row.id, col.id)).replace(/\t/g, " ");
|
|
1750
2093
|
}).join(" ")
|
|
1751
2094
|
).join("\n");
|
|
1752
2095
|
}
|
|
@@ -1766,7 +2109,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1766
2109
|
this.document.rows.push({ id: this.generateId("row"), index, height: 32, type: "freeform" });
|
|
1767
2110
|
}
|
|
1768
2111
|
while (colIndex >= this.document.columns.length) {
|
|
1769
|
-
const key =
|
|
2112
|
+
const key = _chunkRIKBJLS2cjs.indexToColName.call(void 0, this.document.columns.length);
|
|
1770
2113
|
this.document.columns.push({
|
|
1771
2114
|
id: this.generateId("col"),
|
|
1772
2115
|
key,
|
|
@@ -1813,7 +2156,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1813
2156
|
const commits = this.pendingCommits;
|
|
1814
2157
|
this.pendingCommits = [];
|
|
1815
2158
|
for (const [rowId, colId, raw] of commits) {
|
|
1816
|
-
_optionalChain([this, 'access',
|
|
2159
|
+
_optionalChain([this, 'access', _146 => _146.onCellCommit, 'optionalCall', _147 => _147(rowId, colId, raw, _optionalChain([this, 'access', _148 => _148.document, 'access', _149 => _149.cells, 'access', _150 => _150[rowId], 'optionalAccess', _151 => _151[colId], 'optionalAccess', _152 => _152.value]))]);
|
|
1817
2160
|
}
|
|
1818
2161
|
}
|
|
1819
2162
|
// --- CSV ---
|
|
@@ -1823,7 +2166,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1823
2166
|
*/
|
|
1824
2167
|
exportToCsv(options = {}) {
|
|
1825
2168
|
const matrix = this.readMatrix(_nullishCoalesce(options.range, () => ( null))).map(
|
|
1826
|
-
(row) => row.map((cell) => options.formulas ? cell.raw :
|
|
2169
|
+
(row) => row.map((cell) => options.formulas ? cell.raw : _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cell))
|
|
1827
2170
|
);
|
|
1828
2171
|
return serializeCsv(matrix, {
|
|
1829
2172
|
delimiter: options.delimiter,
|
|
@@ -1861,7 +2204,16 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1861
2204
|
*/
|
|
1862
2205
|
copyToClipboardData(range = this.selectedRange) {
|
|
1863
2206
|
const r = range ? normalizeRange(range) : { startRow: 0, startCol: 0, endRow: this.document.rows.length - 1, endCol: this.document.columns.length - 1 };
|
|
1864
|
-
const cells = this.readMatrix(r).map(
|
|
2207
|
+
const cells = this.readMatrix(r).map(
|
|
2208
|
+
(row) => row.map((cell) => {
|
|
2209
|
+
const value = cell.error || cell.value;
|
|
2210
|
+
const text = _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cell);
|
|
2211
|
+
if (cell.spillAnchor && !this.spillAnchorInRange(cell.spillAnchor, r)) {
|
|
2212
|
+
return { raw: text, value, text };
|
|
2213
|
+
}
|
|
2214
|
+
return { raw: cell.raw, value, text };
|
|
2215
|
+
})
|
|
2216
|
+
);
|
|
1865
2217
|
return createSpreadsheetClipboardData(cells, { row: r.startRow, col: r.startCol });
|
|
1866
2218
|
}
|
|
1867
2219
|
/**
|
|
@@ -1884,12 +2236,16 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1884
2236
|
this.selectRange(r);
|
|
1885
2237
|
return true;
|
|
1886
2238
|
}
|
|
2239
|
+
spillAnchorInRange(anchor, range) {
|
|
2240
|
+
const record = this.spills.get(anchor);
|
|
2241
|
+
return !!record && rangeContains(range, record.row, record.col);
|
|
2242
|
+
}
|
|
1887
2243
|
getSelectionTopLeft() {
|
|
1888
2244
|
if (this.selectedRange) {
|
|
1889
2245
|
const r = normalizeRange(this.selectedRange);
|
|
1890
2246
|
return { row: r.startRow, col: r.startCol };
|
|
1891
2247
|
}
|
|
1892
|
-
return { row: _nullishCoalesce(_optionalChain([this, 'access',
|
|
2248
|
+
return { row: _nullishCoalesce(_optionalChain([this, 'access', _153 => _153.activeCell, 'optionalAccess', _154 => _154.row]), () => ( 0)), col: _nullishCoalesce(_optionalChain([this, 'access', _155 => _155.activeCell, 'optionalAccess', _156 => _156.col]), () => ( 0)) };
|
|
1893
2249
|
}
|
|
1894
2250
|
// --- Table operations: shared helpers ---
|
|
1895
2251
|
/** The table settings object, created on first use. */
|
|
@@ -1913,7 +2269,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1913
2269
|
const { headerRows, footerRows } = getTableSections(this.document);
|
|
1914
2270
|
return { start: headerRows, end: this.document.rows.length - footerRows - 1 };
|
|
1915
2271
|
}
|
|
1916
|
-
|
|
2272
|
+
__init24() {this.getCellValueAt = (rowIndex, colIndex) => {
|
|
1917
2273
|
const row = this.document.rows[rowIndex];
|
|
1918
2274
|
const col = this.document.columns[colIndex];
|
|
1919
2275
|
if (!row || !col) return "";
|
|
@@ -1923,7 +2279,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1923
2279
|
remapAllFormulas(moveCell) {
|
|
1924
2280
|
for (const rowCells of Object.values(this.document.cells)) {
|
|
1925
2281
|
for (const cell of Object.values(rowCells)) {
|
|
1926
|
-
if (_optionalChain([cell, 'access',
|
|
2282
|
+
if (_optionalChain([cell, 'access', _157 => _157.raw, 'optionalAccess', _158 => _158.startsWith, 'call', _159 => _159("=")])) {
|
|
1927
2283
|
cell.raw = remapFormulaReferences(cell.raw, moveCell);
|
|
1928
2284
|
}
|
|
1929
2285
|
}
|
|
@@ -1935,8 +2291,8 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1935
2291
|
* merges reduced to a single cell are dropped.
|
|
1936
2292
|
*/
|
|
1937
2293
|
adjustTableForStructuralChange(change) {
|
|
1938
|
-
const merges = _optionalChain([this, 'access',
|
|
1939
|
-
if (!_optionalChain([merges, 'optionalAccess',
|
|
2294
|
+
const merges = _optionalChain([this, 'access', _160 => _160.document, 'access', _161 => _161.table, 'optionalAccess', _162 => _162.merges]);
|
|
2295
|
+
if (!_optionalChain([merges, 'optionalAccess', _163 => _163.length])) return;
|
|
1940
2296
|
const startKey = change.axis === "row" ? "startRow" : "startCol";
|
|
1941
2297
|
const endKey = change.axis === "row" ? "endRow" : "endCol";
|
|
1942
2298
|
const next = [];
|
|
@@ -1967,8 +2323,8 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1967
2323
|
const colCount = this.document.columns.length;
|
|
1968
2324
|
const body = this.getBodyRowBounds();
|
|
1969
2325
|
const range = options.range ? normalizeRange(options.range) : null;
|
|
1970
|
-
const startRow = Math.max(_nullishCoalesce(_optionalChain([range, 'optionalAccess',
|
|
1971
|
-
const endRow = Math.min(_nullishCoalesce(_optionalChain([range, 'optionalAccess',
|
|
2326
|
+
const startRow = Math.max(_nullishCoalesce(_optionalChain([range, 'optionalAccess', _164 => _164.startRow]), () => ( body.start)), body.start);
|
|
2327
|
+
const endRow = Math.min(_nullishCoalesce(_optionalChain([range, 'optionalAccess', _165 => _165.endRow]), () => ( body.end)), body.end);
|
|
1972
2328
|
const startCol = range ? Math.max(0, range.startCol) : 0;
|
|
1973
2329
|
const endCol = range ? Math.min(colCount - 1, range.endCol) : colCount - 1;
|
|
1974
2330
|
if (endRow - startRow < 1 || startCol > endCol) return false;
|
|
@@ -1978,7 +2334,8 @@ var SpreadsheetController = (_class3 = class {
|
|
|
1978
2334
|
}));
|
|
1979
2335
|
if (keyCols.length === 0 || keyCols.some((k) => k.index < startCol || k.index > endCol)) return false;
|
|
1980
2336
|
const area = { startRow, startCol, endRow, endCol };
|
|
1981
|
-
if ((_nullishCoalesce(_optionalChain([this, 'access',
|
|
2337
|
+
if ((_nullishCoalesce(_optionalChain([this, 'access', _166 => _166.document, 'access', _167 => _167.table, 'optionalAccess', _168 => _168.merges]), () => ( []))).some((m) => rangesIntersect(m, area))) return false;
|
|
2338
|
+
if (this.intersectsSpill(area)) return false;
|
|
1982
2339
|
const sourceRows = [];
|
|
1983
2340
|
for (let r = startRow; r <= endRow; r++) sourceRows.push(r);
|
|
1984
2341
|
const sorted = sourceRows.map((r) => ({ r, values: keyCols.map((k) => this.getCellValueAt(r, k.index)) })).sort((a, b) => {
|
|
@@ -2005,7 +2362,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2005
2362
|
const colIds = this.document.columns.slice(startCol, endCol + 1).map((c) => c.id);
|
|
2006
2363
|
const snapshot = sorted.map((oldRow) => {
|
|
2007
2364
|
const rowId = this.document.rows[oldRow].id;
|
|
2008
|
-
return colIds.map((colId) => _optionalChain([this, 'access',
|
|
2365
|
+
return colIds.map((colId) => _optionalChain([this, 'access', _169 => _169.document, 'access', _170 => _170.cells, 'access', _171 => _171[rowId], 'optionalAccess', _172 => _172[colId]]));
|
|
2009
2366
|
});
|
|
2010
2367
|
snapshot.forEach((cells, i) => {
|
|
2011
2368
|
const rowId = this.document.rows[startRow + i].id;
|
|
@@ -2021,7 +2378,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2021
2378
|
}
|
|
2022
2379
|
// --- Filters ---
|
|
2023
2380
|
getFilterState() {
|
|
2024
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
2381
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _173 => _173.document, 'access', _174 => _174.table, 'optionalAccess', _175 => _175.filter]), () => ( { enabled: false, rules: [] }));
|
|
2025
2382
|
}
|
|
2026
2383
|
/** Replaces all filter rules (and turns filters on when there are any). */
|
|
2027
2384
|
setFilterRules(rules) {
|
|
@@ -2098,7 +2455,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2098
2455
|
}
|
|
2099
2456
|
setTableCount(key, count, max) {
|
|
2100
2457
|
const value = Math.max(0, Math.min(Math.floor(count), max));
|
|
2101
|
-
if ((_nullishCoalesce(_optionalChain([this, 'access',
|
|
2458
|
+
if ((_nullishCoalesce(_optionalChain([this, 'access', _176 => _176.document, 'access', _177 => _177.table, 'optionalAccess', _178 => _178[key]]), () => ( 0))) === value) return;
|
|
2102
2459
|
this.applyTableChange(() => {
|
|
2103
2460
|
this.table[key] = value;
|
|
2104
2461
|
});
|
|
@@ -2139,7 +2496,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2139
2496
|
}
|
|
2140
2497
|
// --- Merged cells ---
|
|
2141
2498
|
getMerges() {
|
|
2142
|
-
return _nullishCoalesce(_optionalChain([this, 'access',
|
|
2499
|
+
return _nullishCoalesce(_optionalChain([this, 'access', _179 => _179.document, 'access', _180 => _180.table, 'optionalAccess', _181 => _181.merges]), () => ( []));
|
|
2143
2500
|
}
|
|
2144
2501
|
/** The merge containing (row, col), or null. */
|
|
2145
2502
|
getMergeAt(row, col) {
|
|
@@ -2186,12 +2543,13 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2186
2543
|
}
|
|
2187
2544
|
const merges = this.getMerges();
|
|
2188
2545
|
if (merges.some((m) => rangesIntersect(m, r) && !rangeContainsRange(r, m))) return false;
|
|
2546
|
+
if (this.intersectsSpill(r)) return false;
|
|
2189
2547
|
this.applyTableChange(() => {
|
|
2190
2548
|
for (let row = r.startRow; row <= r.endRow; row++) {
|
|
2191
2549
|
const rowId = this.document.rows[row].id;
|
|
2192
2550
|
for (let col = r.startCol; col <= r.endCol; col++) {
|
|
2193
2551
|
if (row === r.startRow && col === r.startCol) continue;
|
|
2194
|
-
_optionalChainDelete([this, 'access',
|
|
2552
|
+
_optionalChainDelete([this, 'access', _182 => _182.document, 'access', _183 => _183.cells, 'access', _184 => _184[rowId], 'optionalAccess', _185 => _185[this.document.columns[col].id]]);
|
|
2195
2553
|
}
|
|
2196
2554
|
}
|
|
2197
2555
|
this.table.merges = [...merges.filter((m) => !rangeContainsRange(r, m)), r];
|
|
@@ -2207,7 +2565,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2207
2565
|
if (remaining.length === merges.length) return false;
|
|
2208
2566
|
this.applyTableChange(() => {
|
|
2209
2567
|
this.table.merges = remaining;
|
|
2210
|
-
});
|
|
2568
|
+
}, { recalculate: true });
|
|
2211
2569
|
return true;
|
|
2212
2570
|
}
|
|
2213
2571
|
// --- Autofill ---
|
|
@@ -2277,14 +2635,14 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2277
2635
|
});
|
|
2278
2636
|
}
|
|
2279
2637
|
ungroupRows() {
|
|
2280
|
-
if (!_optionalChain([this, 'access',
|
|
2638
|
+
if (!_optionalChain([this, 'access', _186 => _186.document, 'access', _187 => _187.table, 'optionalAccess', _188 => _188.grouping])) return;
|
|
2281
2639
|
this.applyTableChange(() => {
|
|
2282
2640
|
delete this.table.grouping;
|
|
2283
2641
|
});
|
|
2284
2642
|
}
|
|
2285
2643
|
/** Sets (or with `null`, removes) the group summary for a column. */
|
|
2286
2644
|
setGroupSummary(colId, aggregate) {
|
|
2287
|
-
const grouping = _optionalChain([this, 'access',
|
|
2645
|
+
const grouping = _optionalChain([this, 'access', _189 => _189.document, 'access', _190 => _190.table, 'optionalAccess', _191 => _191.grouping]);
|
|
2288
2646
|
if (!grouping) return;
|
|
2289
2647
|
this.applyTableChange(() => {
|
|
2290
2648
|
const others = grouping.summaries.filter((s) => s.colId !== colId);
|
|
@@ -2295,7 +2653,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2295
2653
|
});
|
|
2296
2654
|
}
|
|
2297
2655
|
setGroupCollapsed(key, collapsed) {
|
|
2298
|
-
const grouping = _optionalChain([this, 'access',
|
|
2656
|
+
const grouping = _optionalChain([this, 'access', _192 => _192.document, 'access', _193 => _193.table, 'optionalAccess', _194 => _194.grouping]);
|
|
2299
2657
|
if (!grouping || grouping.collapsed.includes(key) === collapsed) return;
|
|
2300
2658
|
this.applyTableChange(() => {
|
|
2301
2659
|
this.table.grouping = {
|
|
@@ -2305,7 +2663,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2305
2663
|
});
|
|
2306
2664
|
}
|
|
2307
2665
|
toggleGroupCollapsed(key) {
|
|
2308
|
-
const grouping = _optionalChain([this, 'access',
|
|
2666
|
+
const grouping = _optionalChain([this, 'access', _195 => _195.document, 'access', _196 => _196.table, 'optionalAccess', _197 => _197.grouping]);
|
|
2309
2667
|
if (!grouping) return;
|
|
2310
2668
|
this.setGroupCollapsed(key, !grouping.collapsed.includes(key));
|
|
2311
2669
|
}
|
|
@@ -2328,6 +2686,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2328
2686
|
const width = s.endCol - s.startCol + 1;
|
|
2329
2687
|
const t = { startRow: s.startRow, startCol: s.startCol, endRow: s.startRow + width - 1, endCol: s.startCol + height - 1 };
|
|
2330
2688
|
if (this.getMerges().some((m) => rangesIntersect(m, s) || rangesIntersect(m, t))) return false;
|
|
2689
|
+
if (this.intersectsSpill(s) || this.intersectsSpill(t)) return false;
|
|
2331
2690
|
this.applyTableChange(() => {
|
|
2332
2691
|
this.growGrid(t.endRow, t.endCol);
|
|
2333
2692
|
this.remapAllFormulas(({ row, col }) => {
|
|
@@ -2342,9 +2701,9 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2342
2701
|
moved.push({
|
|
2343
2702
|
row: s.startRow + (c - s.startCol),
|
|
2344
2703
|
col: s.startCol + (r - s.startRow),
|
|
2345
|
-
cell: _optionalChain([this, 'access',
|
|
2704
|
+
cell: _optionalChain([this, 'access', _198 => _198.document, 'access', _199 => _199.cells, 'access', _200 => _200[rowId(r)], 'optionalAccess', _201 => _201[colId(c)]])
|
|
2346
2705
|
});
|
|
2347
|
-
_optionalChainDelete([this, 'access',
|
|
2706
|
+
_optionalChainDelete([this, 'access', _202 => _202.document, 'access', _203 => _203.cells, 'access', _204 => _204[rowId(r)], 'optionalAccess', _205 => _205[colId(c)]]);
|
|
2348
2707
|
}
|
|
2349
2708
|
}
|
|
2350
2709
|
for (const { row, col, cell } of moved) {
|
|
@@ -2371,6 +2730,28 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2371
2730
|
this.undoStack.push(JSON.stringify(this.document));
|
|
2372
2731
|
if (this.undoStack.length > 50) this.undoStack.shift();
|
|
2373
2732
|
this.redoStack = [];
|
|
2733
|
+
this.trimHistory();
|
|
2734
|
+
}
|
|
2735
|
+
/** Drops the oldest snapshots beyond `maxHistoryBytes`, always keeping the newest. */
|
|
2736
|
+
trimHistory() {
|
|
2737
|
+
if (this.maxHistoryBytes <= 0 || this.undoStack.length <= 1) return;
|
|
2738
|
+
let total = 0;
|
|
2739
|
+
for (const s of this.undoStack) total += s.length * 2;
|
|
2740
|
+
for (const s of this.redoStack) total += s.length * 2;
|
|
2741
|
+
while (total > this.maxHistoryBytes && this.undoStack.length > 1) {
|
|
2742
|
+
total -= this.undoStack.shift().length * 2;
|
|
2743
|
+
}
|
|
2744
|
+
}
|
|
2745
|
+
/** Approximate bytes held by the undo/redo snapshots (UTF-16 size). */
|
|
2746
|
+
getHistoryByteSize() {
|
|
2747
|
+
let total = 0;
|
|
2748
|
+
for (const s of this.undoStack) total += s.length * 2;
|
|
2749
|
+
for (const s of this.redoStack) total += s.length * 2;
|
|
2750
|
+
return total;
|
|
2751
|
+
}
|
|
2752
|
+
/** Number of undo / redo snapshots currently held. */
|
|
2753
|
+
getHistoryDepth() {
|
|
2754
|
+
return { undo: this.undoStack.length, redo: this.redoStack.length };
|
|
2374
2755
|
}
|
|
2375
2756
|
undo() {
|
|
2376
2757
|
if (this.undoStack.length === 0) return;
|
|
@@ -2397,7 +2778,7 @@ var SpreadsheetController = (_class3 = class {
|
|
|
2397
2778
|
}
|
|
2398
2779
|
}
|
|
2399
2780
|
notifyChange() {
|
|
2400
|
-
_optionalChain([this, 'access',
|
|
2781
|
+
_optionalChain([this, 'access', _206 => _206.onDocumentChange, 'optionalCall', _207 => _207(this.document)]);
|
|
2401
2782
|
}
|
|
2402
2783
|
}, _class3);
|
|
2403
2784
|
function stepInOrder(order, from, delta) {
|
|
@@ -2412,6 +2793,17 @@ function stepInOrder(order, from, delta) {
|
|
|
2412
2793
|
}
|
|
2413
2794
|
|
|
2414
2795
|
// src/spreadsheet/menu.ts
|
|
2796
|
+
function clampMenuPosition(point, size, viewport, margin = 4) {
|
|
2797
|
+
const place = (start, length, limit) => {
|
|
2798
|
+
if (start + length <= limit - margin) return Math.max(margin, start);
|
|
2799
|
+
const flipped = start - length;
|
|
2800
|
+
return Math.max(margin, flipped >= margin ? flipped : limit - margin - length);
|
|
2801
|
+
};
|
|
2802
|
+
return {
|
|
2803
|
+
x: place(point.x, size.width, viewport.width),
|
|
2804
|
+
y: place(point.y, size.height, viewport.height)
|
|
2805
|
+
};
|
|
2806
|
+
}
|
|
2415
2807
|
var quote = (value) => {
|
|
2416
2808
|
const text = String(_nullishCoalesce(value, () => ( "")));
|
|
2417
2809
|
return text.length > 24 ? `"${text.slice(0, 23)}\u2026"` : `"${text}"`;
|
|
@@ -2422,8 +2814,9 @@ function getSpreadsheetMenuItems(controller, cell) {
|
|
|
2422
2814
|
const row = doc.rows[cell.row];
|
|
2423
2815
|
if (!column || !row) return [];
|
|
2424
2816
|
const selection = controller.selectedRange && rangeContains(controller.selectedRange, cell.row, cell.col) ? normalizeRange(controller.selectedRange) : { startRow: cell.row, startCol: cell.col, endRow: cell.row, endCol: cell.col };
|
|
2425
|
-
const colName =
|
|
2426
|
-
const
|
|
2817
|
+
const colName = _chunkRIKBJLS2cjs.indexToColName.call(void 0, cell.col);
|
|
2818
|
+
const cellData = controller.getCell(row.id, column.id);
|
|
2819
|
+
const value = cellData.value;
|
|
2427
2820
|
const table = _nullishCoalesce(doc.table, () => ( {}));
|
|
2428
2821
|
const filter = controller.getFilterState();
|
|
2429
2822
|
const grouping = table.grouping;
|
|
@@ -2445,7 +2838,7 @@ function getSpreadsheetMenuItems(controller, cell) {
|
|
|
2445
2838
|
},
|
|
2446
2839
|
{
|
|
2447
2840
|
id: "filter-equals",
|
|
2448
|
-
label: `Show only rows where ${colName} = ${quote(
|
|
2841
|
+
label: `Show only rows where ${colName} = ${quote(_chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cellData))}`,
|
|
2449
2842
|
separatorBefore: true,
|
|
2450
2843
|
run: () => controller.addFilterRule({ colId: column.id, operator: "equals", value: String(_nullishCoalesce(value, () => ( ""))) })
|
|
2451
2844
|
},
|
|
@@ -2702,5 +3095,6 @@ async function importFileIntoSpreadsheet(controller, input, options) {
|
|
|
2702
3095
|
|
|
2703
3096
|
|
|
2704
3097
|
|
|
2705
|
-
|
|
2706
|
-
|
|
3098
|
+
|
|
3099
|
+
exports.columnDependencyKey = columnDependencyKey; exports.extractCellDependencies = extractCellDependencies; exports.DependencyGraph = DependencyGraph; exports.shiftFormulaReferences = shiftFormulaReferences; exports.mapFormulaReferences = mapFormulaReferences; exports.offsetFormulaReferences = offsetFormulaReferences; exports.remapFormulaReferences = remapFormulaReferences; exports.getFormulaCaretContext = getFormulaCaretContext; exports.getFormulaHints = getFormulaHints; exports.applyFormulaSuggestion = applyFormulaSuggestion; exports.DataSourceBinder = DataSourceBinder; exports.normalizeRange = normalizeRange; exports.rangeContains = rangeContains; exports.rangesIntersect = rangesIntersect; exports.rangeContainsRange = rangeContainsRange; exports.isSingleCellRange = isSingleCellRange; exports.isBlankValue = isBlankValue; exports.toNumber = toNumber; exports.compareCellValues = compareCellValues; exports.matchesFilterRule = matchesFilterRule; exports.aggregateValues = aggregateValues; exports.roundFloat = roundFloat; exports.fillSeries = fillSeries; exports.computeFillTarget = computeFillTarget; exports.getFillDirection = getFillDirection; exports.parseCsv = parseCsv; exports.escapeCsvField = escapeCsvField; exports.serializeCsv = serializeCsv; exports.parseTsv = parseTsv; exports.serializeTsv = serializeTsv; exports.SPREADSHEET_CLIPBOARD_MIME = SPREADSHEET_CLIPBOARD_MIME; exports.serializeHtmlTable = serializeHtmlTable; exports.parseHtmlTable = parseHtmlTable; exports.createSpreadsheetClipboardData = createSpreadsheetClipboardData; exports.readSpreadsheetClipboard = readSpreadsheetClipboard; exports.rebaseClipboardRows = rebaseClipboardRows; exports.DEFAULT_ROW_HEIGHT = DEFAULT_ROW_HEIGHT; exports.DEFAULT_COLUMN_WIDTH = DEFAULT_COLUMN_WIDTH; exports.getTableSections = getTableSections; exports.getRowSection = getRowSection; exports.rowPassesFilters = rowPassesFilters; exports.computeRowGroups = computeRowGroups; exports.buildSpreadsheetView = buildSpreadsheetView; exports.SpreadsheetController = SpreadsheetController; exports.clampMenuPosition = clampMenuPosition; exports.getSpreadsheetMenuItems = getSpreadsheetMenuItems; exports.SPREADSHEET_TABLE_ACTIONS = SPREADSHEET_TABLE_ACTIONS; exports.bindSpreadsheetTableActions = bindSpreadsheetTableActions; exports.csvImportAdapter = csvImportAdapter; exports.tsvImportAdapter = tsvImportAdapter; exports.SPREADSHEET_IMPORT_ADAPTERS = SPREADSHEET_IMPORT_ADAPTERS; exports.registerSpreadsheetImportAdapters = registerSpreadsheetImportAdapters; exports.importFileIntoSpreadsheet = importFileIntoSpreadsheet;
|
|
3100
|
+
//# sourceMappingURL=chunk-XDMXXC4Z.cjs.map
|