@pixerate/editor 0.23.0 → 0.24.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (155) hide show
  1. package/README.md +96 -1
  2. package/THIRD_PARTY_NOTICES.md +51 -0
  3. package/dist/agent/index.cjs +9 -8
  4. package/dist/agent/index.cjs.map +1 -1
  5. package/dist/agent/index.d.cts +4 -3
  6. package/dist/agent/index.d.ts +4 -3
  7. package/dist/agent/index.js +3 -2
  8. package/dist/agent/index.js.map +1 -1
  9. package/dist/canvas/index.cjs +1210 -17
  10. package/dist/canvas/index.cjs.map +1 -1
  11. package/dist/canvas/index.d.cts +318 -1
  12. package/dist/canvas/index.d.ts +318 -1
  13. package/dist/canvas/index.js +1199 -6
  14. package/dist/canvas/index.js.map +1 -1
  15. package/dist/{chunk-QBJ22YZR.js → chunk-3CN2WD3X.js} +1354 -206
  16. package/dist/chunk-3CN2WD3X.js.map +1 -0
  17. package/dist/{chunk-JJDLPEWL.js → chunk-3LV6RRPH.js} +2 -2
  18. package/dist/{chunk-MJZBNWG7.js → chunk-5S3Z4PPF.js} +78 -557
  19. package/dist/chunk-5S3Z4PPF.js.map +1 -0
  20. package/dist/chunk-664LQYFJ.js +115 -0
  21. package/dist/chunk-664LQYFJ.js.map +1 -0
  22. package/dist/{chunk-AA4ZEVCC.cjs → chunk-D27YFC46.cjs} +101 -580
  23. package/dist/chunk-D27YFC46.cjs.map +1 -0
  24. package/dist/chunk-D6FH2YAX.cjs +131 -0
  25. package/dist/chunk-D6FH2YAX.cjs.map +1 -0
  26. package/dist/{chunk-4SUNJZWB.cjs → chunk-FD4LPFAE.cjs} +48 -200
  27. package/dist/chunk-FD4LPFAE.cjs.map +1 -0
  28. package/dist/chunk-FODNLX5N.js +749 -0
  29. package/dist/chunk-FODNLX5N.js.map +1 -0
  30. package/dist/{chunk-OYXSKQFR.js → chunk-FPENXAEJ.js} +35 -187
  31. package/dist/chunk-FPENXAEJ.js.map +1 -0
  32. package/dist/chunk-HLIMTC6N.js +1 -0
  33. package/dist/chunk-HLIMTC6N.js.map +1 -0
  34. package/dist/{chunk-QGHGJ56O.js → chunk-ITBSKI26.js} +1483 -19
  35. package/dist/chunk-ITBSKI26.js.map +1 -0
  36. package/dist/{chunk-XDMXXC4Z.cjs → chunk-MA2F5KHF.cjs} +350 -227
  37. package/dist/chunk-MA2F5KHF.cjs.map +1 -0
  38. package/dist/{chunk-RIKBJLS2.cjs → chunk-MCSJFWAO.cjs} +1356 -208
  39. package/dist/chunk-MCSJFWAO.cjs.map +1 -0
  40. package/dist/chunk-MKA3AHLV.cjs +256 -0
  41. package/dist/chunk-MKA3AHLV.cjs.map +1 -0
  42. package/dist/chunk-OLZJXL4R.cjs +749 -0
  43. package/dist/chunk-OLZJXL4R.cjs.map +1 -0
  44. package/dist/chunk-OXSV64JX.js +689 -0
  45. package/dist/chunk-OXSV64JX.js.map +1 -0
  46. package/dist/chunk-P3RQ5UJE.cjs +689 -0
  47. package/dist/chunk-P3RQ5UJE.cjs.map +1 -0
  48. package/dist/chunk-P6ODPZ4W.js +256 -0
  49. package/dist/chunk-P6ODPZ4W.js.map +1 -0
  50. package/dist/chunk-PGNZKFQS.js +685 -0
  51. package/dist/chunk-PGNZKFQS.js.map +1 -0
  52. package/dist/chunk-PL4JB3BF.cjs +1 -0
  53. package/dist/chunk-PL4JB3BF.cjs.map +1 -0
  54. package/dist/{chunk-GVSMRPHB.cjs → chunk-SBCZ6RN5.cjs} +1568 -104
  55. package/dist/chunk-SBCZ6RN5.cjs.map +1 -0
  56. package/dist/{chunk-CL37JGFW.cjs → chunk-SML64VJG.cjs} +4 -4
  57. package/dist/{chunk-CL37JGFW.cjs.map → chunk-SML64VJG.cjs.map} +1 -1
  58. package/dist/chunk-TNNJXF46.cjs +115 -0
  59. package/dist/chunk-TNNJXF46.cjs.map +1 -0
  60. package/dist/chunk-U5HZSFCS.js +131 -0
  61. package/dist/chunk-U5HZSFCS.js.map +1 -0
  62. package/dist/{chunk-K3R5NG2D.js → chunk-U5KWZU4X.js} +251 -128
  63. package/dist/chunk-U5KWZU4X.js.map +1 -0
  64. package/dist/chunk-XNORY7M6.cjs +685 -0
  65. package/dist/chunk-XNORY7M6.cjs.map +1 -0
  66. package/dist/commands/index.d.cts +5 -353
  67. package/dist/commands/index.d.ts +5 -353
  68. package/dist/comment-store-BEMgVlAA.d.cts +135 -0
  69. package/dist/comment-store-BEMgVlAA.d.ts +135 -0
  70. package/dist/compare/index.cjs +15 -0
  71. package/dist/compare/index.cjs.map +1 -0
  72. package/dist/compare/index.d.cts +58 -0
  73. package/dist/compare/index.d.ts +58 -0
  74. package/dist/compare/index.js +15 -0
  75. package/dist/compare/index.js.map +1 -0
  76. package/dist/{controller-pePCJLT1.d.cts → controller-BhLLAoi8.d.cts} +45 -4
  77. package/dist/{controller-pePCJLT1.d.ts → controller-BhLLAoi8.d.ts} +45 -4
  78. package/dist/documents-BQjzJNe2.d.ts +76 -0
  79. package/dist/documents-KRTPhvst.d.cts +76 -0
  80. package/dist/extensions/index.cjs +53 -5
  81. package/dist/extensions/index.cjs.map +1 -1
  82. package/dist/extensions/index.d.cts +7 -3
  83. package/dist/extensions/index.d.ts +7 -3
  84. package/dist/extensions/index.js +52 -4
  85. package/dist/generation/index.cjs +1373 -0
  86. package/dist/generation/index.cjs.map +1 -0
  87. package/dist/generation/index.d.cts +554 -0
  88. package/dist/generation/index.d.ts +554 -0
  89. package/dist/generation/index.js +1373 -0
  90. package/dist/generation/index.js.map +1 -0
  91. package/dist/grammar/index.cjs +48 -3
  92. package/dist/grammar/index.cjs.map +1 -1
  93. package/dist/grammar/index.d.cts +322 -100
  94. package/dist/grammar/index.d.ts +322 -100
  95. package/dist/grammar/index.js +54 -9
  96. package/dist/image-editor/index.cjs +1831 -30
  97. package/dist/image-editor/index.cjs.map +1 -1
  98. package/dist/image-editor/index.d.cts +590 -3
  99. package/dist/image-editor/index.d.ts +590 -3
  100. package/dist/image-editor/index.js +1807 -6
  101. package/dist/image-editor/index.js.map +1 -1
  102. package/dist/{index-CCr_z9kF.d.cts → index-BhJBSm2d.d.cts} +370 -4
  103. package/dist/{index-Ck6ajwXh.d.ts → index-fJrlkJCd.d.ts} +370 -4
  104. package/dist/index.cjs +162 -25
  105. package/dist/index.cjs.map +1 -1
  106. package/dist/index.d.cts +14 -8
  107. package/dist/index.d.ts +14 -8
  108. package/dist/index.js +174 -37
  109. package/dist/index.js.map +1 -1
  110. package/dist/migrate-iTlm3a8h.d.cts +112 -0
  111. package/dist/migrate-iTlm3a8h.d.ts +112 -0
  112. package/dist/persistence/index.cjs +676 -0
  113. package/dist/persistence/index.cjs.map +1 -0
  114. package/dist/persistence/index.d.cts +347 -0
  115. package/dist/persistence/index.d.ts +347 -0
  116. package/dist/persistence/index.js +676 -0
  117. package/dist/persistence/index.js.map +1 -0
  118. package/dist/{registry-D5-R90p0.d.cts → registry-BDe-vlv3.d.ts} +2 -40
  119. package/dist/registry-D32LpIc4.d.cts +354 -0
  120. package/dist/{registry-D5-R90p0.d.ts → registry-DnzpgY27.d.cts} +2 -40
  121. package/dist/registry-evKTP4ls.d.ts +354 -0
  122. package/dist/schema-DYDGdYL9.d.cts +41 -0
  123. package/dist/schema-DYDGdYL9.d.ts +41 -0
  124. package/dist/serializers/index.cjs +4 -3
  125. package/dist/serializers/index.cjs.map +1 -1
  126. package/dist/serializers/index.d.cts +2 -1
  127. package/dist/serializers/index.d.ts +2 -1
  128. package/dist/serializers/index.js +3 -2
  129. package/dist/sourcemap-C8AH3MBQ.d.cts +91 -0
  130. package/dist/sourcemap-DA1Evhrv.d.ts +91 -0
  131. package/dist/spreadsheet/index.cjs +37 -3
  132. package/dist/spreadsheet/index.cjs.map +1 -1
  133. package/dist/spreadsheet/index.d.cts +188 -17
  134. package/dist/spreadsheet/index.d.ts +188 -17
  135. package/dist/spreadsheet/index.js +43 -9
  136. package/dist/{tokens-CyLZmIei.d.cts → tokens-D7yXvUU6.d.cts} +15 -2
  137. package/dist/{tokens-CyLZmIei.d.ts → tokens-D7yXvUU6.d.ts} +15 -2
  138. package/dist/{track-changes-BSF58RK0.d.ts → track-changes-BK5sVf4_.d.cts} +18 -136
  139. package/dist/{track-changes-BSF58RK0.d.cts → track-changes-CDjCrwKe.d.ts} +18 -136
  140. package/package.json +16 -1
  141. package/dist/chunk-4SUNJZWB.cjs.map +0 -1
  142. package/dist/chunk-AA4ZEVCC.cjs.map +0 -1
  143. package/dist/chunk-AXV2ZW34.cjs +0 -118
  144. package/dist/chunk-AXV2ZW34.cjs.map +0 -1
  145. package/dist/chunk-B2ZRLN4S.js +0 -118
  146. package/dist/chunk-B2ZRLN4S.js.map +0 -1
  147. package/dist/chunk-GVSMRPHB.cjs.map +0 -1
  148. package/dist/chunk-K3R5NG2D.js.map +0 -1
  149. package/dist/chunk-MJZBNWG7.js.map +0 -1
  150. package/dist/chunk-OYXSKQFR.js.map +0 -1
  151. package/dist/chunk-QBJ22YZR.js.map +0 -1
  152. package/dist/chunk-QGHGJ56O.js.map +0 -1
  153. package/dist/chunk-RIKBJLS2.cjs.map +0 -1
  154. package/dist/chunk-XDMXXC4Z.cjs.map +0 -1
  155. /package/dist/{chunk-JJDLPEWL.js.map → chunk-3LV6RRPH.js.map} +0 -0
@@ -3,6 +3,7 @@
3
3
 
4
4
 
5
5
 
6
+ var _chunkTNNJXF46cjs = require('./chunk-TNNJXF46.cjs');
6
7
 
7
8
 
8
9
 
@@ -18,7 +19,15 @@
18
19
 
19
20
 
20
21
 
21
- var _chunkRIKBJLS2cjs = require('./chunk-RIKBJLS2.cjs');
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+ var _chunkMCSJFWAOcjs = require('./chunk-MCSJFWAO.cjs');
22
31
 
23
32
  // src/spreadsheet/formula/dependency-graph.ts
24
33
  var columnDependencyKey = (col) => `${col.toUpperCase()}:`;
@@ -29,22 +38,22 @@ function extractCellDependencies(node) {
29
38
  deps.push({ col: curr.col, row: curr.row });
30
39
  } else if (curr.type === "SpillRef") {
31
40
  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);
41
+ } else if (curr.type === "Range" && curr.endRow >= _chunkMCSJFWAOcjs.WHOLE_COLUMN_END_ROW) {
42
+ const startC = _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, curr.startCol);
43
+ const endC = _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, curr.endCol);
35
44
  for (let c = Math.min(startC, endC); c <= Math.max(startC, endC); c++) {
36
- deps.push({ col: _chunkRIKBJLS2cjs.indexToColName.call(void 0, c), row: 0 });
45
+ deps.push({ col: _chunkMCSJFWAOcjs.indexToColName.call(void 0, c), row: 0 });
37
46
  }
38
47
  } else if (curr.type === "Range") {
39
- const startC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, curr.startCol);
40
- const endC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, curr.endCol);
48
+ const startC = _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, curr.startCol);
49
+ const endC = _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, curr.endCol);
41
50
  const minC = Math.min(startC, endC);
42
51
  const maxC = Math.max(startC, endC);
43
52
  const minR = Math.min(curr.startRow, curr.endRow);
44
53
  const maxR = Math.max(curr.startRow, curr.endRow);
45
54
  for (let c = minC; c <= maxC; c++) {
46
55
  for (let r = minR; r <= maxR; r++) {
47
- deps.push({ col: _chunkRIKBJLS2cjs.indexToColName.call(void 0, c), row: r });
56
+ deps.push({ col: _chunkMCSJFWAOcjs.indexToColName.call(void 0, c), row: r });
48
57
  }
49
58
  }
50
59
  } else if (curr.type === "BinaryOp") {
@@ -83,7 +92,7 @@ var DependencyGraph = (_class = class {constructor() { _class.prototype.__init.c
83
92
  return;
84
93
  }
85
94
  try {
86
- const ast = _chunkRIKBJLS2cjs.parseFormula.call(void 0, formulaStr);
95
+ const ast = _chunkMCSJFWAOcjs.parseFormula.call(void 0, formulaStr);
87
96
  const deps = extractCellDependencies(ast);
88
97
  const newDeps = /* @__PURE__ */ new Set();
89
98
  for (const d of deps) {
@@ -329,19 +338,19 @@ function parsePart(text) {
329
338
  if (cell) {
330
339
  return {
331
340
  colAbs: cell[1],
332
- col: _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, cell[2]),
341
+ col: _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, cell[2]),
333
342
  rowAbs: cell[3],
334
343
  row: parseInt(cell[4], 10) - 1
335
344
  };
336
345
  }
337
346
  const column = COLUMN_PART.exec(text);
338
347
  if (column) {
339
- return { colAbs: column[1], col: _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, column[2]), rowAbs: "", row: null };
348
+ return { colAbs: column[1], col: _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, column[2]), rowAbs: "", row: null };
340
349
  }
341
350
  return null;
342
351
  }
343
352
  function formatPart(part) {
344
- const col = `${part.colAbs}${_chunkRIKBJLS2cjs.indexToColName.call(void 0, part.col)}`;
353
+ const col = `${part.colAbs}${_chunkMCSJFWAOcjs.indexToColName.call(void 0, part.col)}`;
345
354
  return part.row === null ? col : `${col}${part.rowAbs}${part.row + 1}`;
346
355
  }
347
356
  function shiftCoordinate(value, change) {
@@ -388,7 +397,7 @@ function mapFormulaReferences(formula, rewrite) {
388
397
  if (!formula.startsWith("=")) return formula;
389
398
  let tokens;
390
399
  try {
391
- tokens = _chunkRIKBJLS2cjs.tokenizeFormula.call(void 0, formula);
400
+ tokens = _chunkMCSJFWAOcjs.tokenizeFormula.call(void 0, formula);
392
401
  } catch (e2) {
393
402
  return formula;
394
403
  }
@@ -526,7 +535,7 @@ function innermostCall(stack) {
526
535
  }
527
536
  var toSuggestion = (def) => ({
528
537
  name: def.name,
529
- signature: _chunkRIKBJLS2cjs.getFormulaSignature.call(void 0, def),
538
+ signature: _chunkMCSJFWAOcjs.getFormulaSignature.call(void 0, def),
530
539
  description: def.description,
531
540
  category: def.category
532
541
  });
@@ -535,20 +544,20 @@ function getFormulaHints(input, caret = input.length, options = {}) {
535
544
  let suggestions = [];
536
545
  if (context.prefix) {
537
546
  const query = context.prefix.text.toUpperCase();
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);
547
+ suggestions = _chunkMCSJFWAOcjs.searchFormulaFunctions.call(void 0, query, { limit: void 0 }).filter((def) => def.name.startsWith(query)).slice(0, _nullishCoalesce(options.limit, () => ( 8))).map(toSuggestion);
539
548
  const followedByParen = input.slice(context.prefix.end).trimStart().startsWith("(");
540
549
  if (followedByParen || suggestions.length === 1 && suggestions[0].name === query) suggestions = [];
541
550
  }
542
551
  let activeCall = null;
543
552
  if (context.call) {
544
- const def = _chunkRIKBJLS2cjs.getFormulaFunction.call(void 0, context.call.name);
553
+ const def = _chunkMCSJFWAOcjs.getFormulaFunction.call(void 0, context.call.name);
545
554
  if (def) {
546
- const specIndex = _chunkRIKBJLS2cjs.getFormulaArgumentSpecIndex.call(void 0, def, context.call.argIndex);
555
+ const specIndex = _chunkMCSJFWAOcjs.getFormulaArgumentSpecIndex.call(void 0, def, context.call.argIndex);
547
556
  activeCall = {
548
557
  name: def.name,
549
- signature: _chunkRIKBJLS2cjs.getFormulaSignature.call(void 0, def),
558
+ signature: _chunkMCSJFWAOcjs.getFormulaSignature.call(void 0, def),
550
559
  description: def.description,
551
- parts: _chunkRIKBJLS2cjs.getFormulaSignatureParts.call(void 0, def, context.call.argIndex),
560
+ parts: _chunkMCSJFWAOcjs.getFormulaSignatureParts.call(void 0, def, context.call.argIndex),
552
561
  argIndex: context.call.argIndex,
553
562
  argument: specIndex >= 0 ? def.args[specIndex] : null
554
563
  };
@@ -566,6 +575,68 @@ function applyFormulaSuggestion(input, caret, name) {
566
575
  return { value, caret: start + insert.length + (hasParen ? 1 : 0) };
567
576
  }
568
577
 
578
+ // src/spreadsheet/numfmt/presets.ts
579
+ var NUMBER_FORMAT_PRESETS = [
580
+ { id: "general", label: "General", code: "General" },
581
+ { id: "number", label: "Number (0.00)", code: "0.00" },
582
+ { id: "currency", label: "Currency ($1,234.50)", code: '"$"#,##0.00' },
583
+ { id: "percent", label: "Percent (12.5%)", code: "0.0%" },
584
+ { id: "date", label: "Date (3/14/2026)", code: "m/d/yyyy" },
585
+ { id: "time", label: "Time (1:30 PM)", code: "h:mm AM/PM" }
586
+ ];
587
+ function numberFormatForCellFormat(format) {
588
+ switch (format) {
589
+ case "currency":
590
+ return '"$"#,##0.00';
591
+ case "percentage":
592
+ return "0%";
593
+ case "date":
594
+ return "m/d/yyyy";
595
+ default:
596
+ return void 0;
597
+ }
598
+ }
599
+ function cellFormatForNumberFormat(code) {
600
+ switch (_chunkMCSJFWAOcjs.NumberFormat.parseCached(code).kind()) {
601
+ case "number":
602
+ case "fraction":
603
+ case "scientific":
604
+ case "special":
605
+ return "number";
606
+ case "currency":
607
+ case "accounting":
608
+ return "currency";
609
+ case "percentage":
610
+ return "percentage";
611
+ case "date":
612
+ return "date";
613
+ case "text":
614
+ return "text";
615
+ default:
616
+ return void 0;
617
+ }
618
+ }
619
+ var isGeneralNumberFormat = (code) => code === void 0 || _chunkMCSJFWAOcjs.NumberFormat.parseCached(code).isGeneral();
620
+
621
+ // src/spreadsheet/formula/format.ts
622
+ function formatCellForDisplay(cell) {
623
+ if (!cell) return { text: "", numeric: false };
624
+ if (cell.error) return { text: cell.error, numeric: false };
625
+ const { value } = cell;
626
+ const code = _nullishCoalesce(cell.numberFormat, () => ( (typeof value === "number" ? numberFormatForCellFormat(cell.format) : void 0)));
627
+ if (code !== void 0 && !isGeneralNumberFormat(code) && !_chunkMCSJFWAOcjs.isBlank.call(void 0, value) && typeof value !== "boolean") {
628
+ return _chunkMCSJFWAOcjs.NumberFormat.parseCached(code).format(value);
629
+ }
630
+ return { text: _chunkMCSJFWAOcjs.toText.call(void 0, value), numeric: typeof value === "number" };
631
+ }
632
+ function formatCellDisplay(cell) {
633
+ return formatCellForDisplay(cell).text;
634
+ }
635
+ function formatValueWithCode(value, format) {
636
+ const result = _chunkMCSJFWAOcjs.formatTextFunction.call(void 0, value, format);
637
+ return "text" in result ? result.text : null;
638
+ }
639
+
569
640
  // src/spreadsheet/datasource/index.ts
570
641
  var DataSourceBinder = (_class2 = class {constructor() { _class2.prototype.__init6.call(this); }
571
642
  __init6() {this.dataSources = /* @__PURE__ */ new Map()}
@@ -685,28 +756,28 @@ function compareCellValues(a, b, direction = "asc") {
685
756
  const bBlank = isBlankValue(b);
686
757
  if (aBlank || bBlank) return aBlank === bBlank ? 0 : aBlank ? 1 : -1;
687
758
  let result;
688
- if (isPlainText(a) && isPlainText(b) && !(_chunkRIKBJLS2cjs.parseIsoDate.call(void 0, a) && _chunkRIKBJLS2cjs.parseIsoDate.call(void 0, b))) {
759
+ if (isPlainText(a) && isPlainText(b) && !(_chunkMCSJFWAOcjs.parseIsoDate.call(void 0, a) && _chunkMCSJFWAOcjs.parseIsoDate.call(void 0, b))) {
689
760
  result = compareText(a, b);
690
761
  } else {
691
- result = _chunkRIKBJLS2cjs.sortCompareValues.call(void 0, a, b);
762
+ result = _chunkMCSJFWAOcjs.sortCompareValues.call(void 0, a, b);
692
763
  }
693
764
  if (result === 0) return 0;
694
765
  return direction === "desc" ? -Math.sign(result) : Math.sign(result);
695
766
  }
696
- var isPlainText = (value) => typeof value === "string" && !_chunkRIKBJLS2cjs.isFormulaError.call(void 0, value);
767
+ var isPlainText = (value) => typeof value === "string" && !_chunkMCSJFWAOcjs.isFormulaError.call(void 0, value);
697
768
  function filterValue(value) {
698
- if (isBlankValue(value) || _chunkRIKBJLS2cjs.isFormulaError.call(void 0, value)) return null;
769
+ if (isBlankValue(value) || _chunkMCSJFWAOcjs.isFormulaError.call(void 0, value)) return null;
699
770
  if (typeof value === "number") return Number.isFinite(value) ? { value, kind: "number" } : null;
700
771
  if (typeof value === "boolean") return { value, kind: "boolean" };
701
- const num = _chunkRIKBJLS2cjs.numericValue.call(void 0, value);
772
+ const num = _chunkMCSJFWAOcjs.numericValue.call(void 0, value);
702
773
  if (num !== null) return { value: num, kind: "number" };
703
774
  const text = String(value);
704
- return { value: text, kind: _chunkRIKBJLS2cjs.parseIsoDate.call(void 0, text) ? "number" : "text" };
775
+ return { value: text, kind: _chunkMCSJFWAOcjs.parseIsoDate.call(void 0, text) ? "number" : "text" };
705
776
  }
706
777
  function filterOperand(operand) {
707
778
  if (typeof operand !== "string") return filterValue(operand);
708
779
  if (operand.trim() === "") return null;
709
- const parsed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, operand.trim());
780
+ const parsed = _chunkMCSJFWAOcjs.parseCellInput.call(void 0, operand.trim());
710
781
  if (parsed.type === "number" || parsed.type === "date" || parsed.type === "boolean") return filterValue(parsed.value);
711
782
  return { value: operand, kind: "text" };
712
783
  }
@@ -714,7 +785,7 @@ function compareForFilter(value, operand) {
714
785
  const a = filterValue(value);
715
786
  const b = filterOperand(operand);
716
787
  if (!a || !b || a.kind !== b.kind) return null;
717
- return _chunkRIKBJLS2cjs.compareValues.call(void 0, a.value, b.value);
788
+ return _chunkMCSJFWAOcjs.compareValues.call(void 0, a.value, b.value);
718
789
  }
719
790
  function looselyEquals(value, operand) {
720
791
  const c = compareForFilter(value, operand);
@@ -793,7 +864,7 @@ function classifyFillValue(raw) {
793
864
  if (raw.trim() === "") return { kind: "blank" };
794
865
  const num = toNumber(raw);
795
866
  if (num !== null) return { kind: "number", value: num };
796
- const typed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, raw);
867
+ const typed = _chunkMCSJFWAOcjs.parseCellInput.call(void 0, raw);
797
868
  const date = ISO_DATE_PATTERN.exec(typed.type === "date" ? String(typed.value) : raw.trim());
798
869
  if (date) {
799
870
  const [year, month, day] = [Number(date[1]), Number(date[2]), Number(date[3])];
@@ -912,113 +983,6 @@ function getFillDirection(source, target) {
912
983
  return null;
913
984
  }
914
985
 
915
- // src/spreadsheet/csv.ts
916
- var BOM = "\uFEFF";
917
- function parseCsv(text, options = {}) {
918
- const delimiter = _nullishCoalesce(options.delimiter, () => ( ","));
919
- if (delimiter.length !== 1 || delimiter === '"' || delimiter === "\n" || delimiter === "\r") {
920
- throw new Error(`Invalid CSV delimiter: ${JSON.stringify(delimiter)}`);
921
- }
922
- const input = text.startsWith(BOM) ? text.slice(1) : text;
923
- const records = [];
924
- let record = [];
925
- let field = "";
926
- let i = 0;
927
- let recordStarted = false;
928
- const endField = () => {
929
- record.push(field);
930
- field = "";
931
- };
932
- const endRecord = () => {
933
- endField();
934
- records.push(record);
935
- record = [];
936
- recordStarted = false;
937
- };
938
- let atFieldStart = true;
939
- while (i < input.length) {
940
- const char = input[i];
941
- if (char === '"' && atFieldStart) {
942
- const quoted = readQuoted(input, i, delimiter);
943
- if (quoted.wellFormed || !options.requireWellFormedQuotes) {
944
- recordStarted = true;
945
- atFieldStart = false;
946
- field += quoted.value;
947
- i = quoted.end;
948
- continue;
949
- }
950
- }
951
- if (char === delimiter) {
952
- recordStarted = true;
953
- endField();
954
- atFieldStart = true;
955
- i++;
956
- continue;
957
- }
958
- if (char === "\r" || char === "\n") {
959
- endRecord();
960
- atFieldStart = true;
961
- i += char === "\r" && input[i + 1] === "\n" ? 2 : 1;
962
- continue;
963
- }
964
- recordStarted = true;
965
- atFieldStart = false;
966
- field += char;
967
- i++;
968
- }
969
- if (recordStarted || field !== "" || record.length > 0) endRecord();
970
- return records;
971
- }
972
- function readQuoted(input, start, delimiter) {
973
- let value = "";
974
- let i = start + 1;
975
- while (i < input.length) {
976
- if (input[i] === '"') {
977
- if (input[i + 1] === '"') {
978
- value += '"';
979
- i += 2;
980
- continue;
981
- }
982
- const next = input[i + 1];
983
- const wellFormed = next === void 0 || next === delimiter || next === "\r" || next === "\n";
984
- return { value, end: i + 1, wellFormed };
985
- }
986
- value += input[i];
987
- i++;
988
- }
989
- return { value, end: i, wellFormed: false };
990
- }
991
- function escapeCsvField(value, delimiter = ",", quoteAll = false) {
992
- if (quoteAll || value.includes(delimiter) || /["\r\n]/.test(value)) {
993
- return `"${value.replace(/"/g, '""')}"`;
994
- }
995
- return value;
996
- }
997
- function serializeCsv(rows, options = {}) {
998
- const delimiter = _nullishCoalesce(options.delimiter, () => ( ","));
999
- const lineEnding = _nullishCoalesce(options.lineEnding, () => ( "\r\n"));
1000
- const body = rows.map(
1001
- (row) => row.map((value) => escapeCsvField(value == null ? "" : String(value), delimiter, options.quoteAll)).join(delimiter)
1002
- ).join(lineEnding);
1003
- return options.bom ? BOM + body : body;
1004
- }
1005
- function parseTsv(text) {
1006
- const normalized = text.startsWith(BOM) ? text.slice(1) : text;
1007
- if (!normalized.includes('"')) {
1008
- const body = normalized.replace(/\r\n?/g, "\n").replace(/\n$/, "");
1009
- return body === "" ? [] : body.split("\n").map((line) => line.split(" "));
1010
- }
1011
- return parseCsv(normalized, { delimiter: " ", requireWellFormedQuotes: true });
1012
- }
1013
- function serializeTsv(rows) {
1014
- return rows.map(
1015
- (row) => row.map((value) => {
1016
- const text = value == null ? "" : String(value);
1017
- return /[\t\r\n]/.test(text) || text.startsWith('"') ? `"${text.replace(/"/g, '""')}"` : text;
1018
- }).join(" ")
1019
- ).join("\n");
1020
- }
1021
-
1022
986
  // src/spreadsheet/clipboard.ts
1023
987
  var SPREADSHEET_CLIPBOARD_MIME = "application/x.pixerate.spreadsheet+json";
1024
988
  var displayText = (value) => value === null || value === void 0 ? "" : String(value);
@@ -1099,7 +1063,7 @@ function createSpreadsheetClipboardData(cells, origin) {
1099
1063
  cells: cells.map((row) => row.map(({ raw, value }) => ({ raw, value })))
1100
1064
  };
1101
1065
  return {
1102
- "text/plain": serializeTsv(texts),
1066
+ "text/plain": _chunkTNNJXF46cjs.serializeTsv.call(void 0, texts),
1103
1067
  "text/html": serializeHtmlTable(texts),
1104
1068
  [SPREADSHEET_CLIPBOARD_MIME]: JSON.stringify(payload)
1105
1069
  };
@@ -1141,7 +1105,7 @@ function readSpreadsheetClipboard(source) {
1141
1105
  }
1142
1106
  const text = readFormat(source, "text/plain");
1143
1107
  if (text) {
1144
- const rows = parseTsv(text);
1108
+ const rows = _chunkTNNJXF46cjs.parseTsv.call(void 0, text);
1145
1109
  if (rows.length > 0) return { format: "text", rows };
1146
1110
  }
1147
1111
  return null;
@@ -1383,7 +1347,7 @@ var SpreadsheetController = (_class3 = class {
1383
1347
  if (options.dataSources) {
1384
1348
  options.dataSources.forEach((ds) => this.binder.register(ds));
1385
1349
  }
1386
- this.evaluator = new (0, _chunkRIKBJLS2cjs.FormulaEvaluator)({
1350
+ this.evaluator = new (0, _chunkMCSJFWAOcjs.FormulaEvaluator)({
1387
1351
  resolveCell: (colStr, rowNum) => this.resolveCellByCoord(colStr, rowNum),
1388
1352
  resolveRange: (sCol, sRow, eCol, eRow) => this.resolveRangeByCoords(sCol, sRow, eCol, eRow),
1389
1353
  resolveProperty: (prop) => this.resolveCurrentRowProperty(prop),
@@ -1422,7 +1386,7 @@ var SpreadsheetController = (_class3 = class {
1422
1386
  const cell = cells[col.id];
1423
1387
  if (!cell || typeof cell.raw !== "string" || cell.raw.startsWith("=")) continue;
1424
1388
  if (col.type === "bound" && col.binding && row.recordId) continue;
1425
- const typed = this.typedCell(cell.raw, cell.format);
1389
+ const typed = this.typedCell(cell.raw, cell.format, col, cell);
1426
1390
  cell.value = typed.value;
1427
1391
  if (typed.numberFormat) cell.numberFormat = typed.numberFormat;
1428
1392
  else delete cell.numberFormat;
@@ -1436,14 +1400,31 @@ var SpreadsheetController = (_class3 = class {
1436
1400
  * `CellFormat` to use: the automatic one (currency, percentage, date,
1437
1401
  * number) when `format` is unset or `text` (the default of new columns).
1438
1402
  */
1439
- typedCell(raw, format) {
1440
- const parsed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, raw);
1403
+ typedCell(raw, format, col, existing) {
1404
+ const parsed = _chunkMCSJFWAOcjs.parseCellInput.call(void 0, raw);
1405
+ const fixed = this.fixedNumberFormat(col, existing);
1406
+ const numberFormat = _nullishCoalesce(fixed, () => ( parsed.numberFormat));
1441
1407
  return {
1442
1408
  value: parsed.value,
1443
- ...parsed.numberFormat ? { numberFormat: parsed.numberFormat } : {},
1444
- format: parsed.cellFormat && (!format || format === "text") ? parsed.cellFormat : format
1409
+ ...numberFormat ? { numberFormat } : {},
1410
+ ..._optionalChain([existing, 'optionalAccess', _74 => _74.explicitNumberFormat]) ? { explicitNumberFormat: true } : {},
1411
+ format: fixed === void 0 && parsed.cellFormat && (!format || format === "text") ? parsed.cellFormat : format
1445
1412
  };
1446
1413
  }
1414
+ /**
1415
+ * The number format a cell keeps whatever is typed into it: its explicit
1416
+ * one, else its column's. Undefined lets typed input choose one.
1417
+ */
1418
+ fixedNumberFormat(col, existing) {
1419
+ if (_optionalChain([existing, 'optionalAccess', _75 => _75.explicitNumberFormat]) && existing.numberFormat !== void 0) return existing.numberFormat;
1420
+ return _optionalChain([col, 'optionalAccess', _76 => _76.numberFormat]) && !isGeneralNumberFormat(col.numberFormat) ? col.numberFormat : void 0;
1421
+ }
1422
+ /** `numberFormat` / `explicitNumberFormat` fields for a formula, bound or spilled cell. */
1423
+ fixedNumberFormatFields(col, existing) {
1424
+ const numberFormat = this.fixedNumberFormat(col, existing);
1425
+ if (numberFormat === void 0) return {};
1426
+ return _optionalChain([existing, 'optionalAccess', _77 => _77.explicitNumberFormat]) ? { numberFormat, explicitNumberFormat: true } : { numberFormat };
1427
+ }
1447
1428
  /**
1448
1429
  * Typed input for a bound field, coerced by the field's declared type:
1449
1430
  * number, boolean and date fields get a number, boolean or ISO date when
@@ -1452,9 +1433,9 @@ var SpreadsheetController = (_class3 = class {
1452
1433
  */
1453
1434
  boundInputValue(dataSourceId, field, raw) {
1454
1435
  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]);
1436
+ const type = _optionalChain([this, 'access', _78 => _78.binder, 'access', _79 => _79.getDataSource, 'call', _80 => _80(dataSourceId), 'optionalAccess', _81 => _81.getFields, 'call', _82 => _82(), 'access', _83 => _83.find, 'call', _84 => _84((f) => f.key === field), 'optionalAccess', _85 => _85.type]);
1456
1437
  if (type !== "number" && type !== "boolean" && type !== "date") return raw;
1457
- const parsed = _chunkRIKBJLS2cjs.parseCellInput.call(void 0, raw);
1438
+ const parsed = _chunkMCSJFWAOcjs.parseCellInput.call(void 0, raw);
1458
1439
  if (type === "number" && parsed.type === "number") return parsed.value;
1459
1440
  if (type === "boolean" && parsed.type === "boolean") return parsed.value;
1460
1441
  if (type === "date" && parsed.type === "date") return parsed.value;
@@ -1480,7 +1461,7 @@ var SpreadsheetController = (_class3 = class {
1480
1461
  r.index = idx;
1481
1462
  });
1482
1463
  this.document.columns.forEach((c, idx) => {
1483
- c.key = _chunkRIKBJLS2cjs.indexToColName.call(void 0, idx);
1464
+ c.key = _chunkMCSJFWAOcjs.indexToColName.call(void 0, idx);
1484
1465
  });
1485
1466
  }
1486
1467
  getColumn(colIdOrKey) {
@@ -1495,16 +1476,19 @@ var SpreadsheetController = (_class3 = class {
1495
1476
  return this.document.rows.find((r) => r.id === rowIdOrIndex);
1496
1477
  }
1497
1478
  getCell(rowId, colId) {
1498
- const existing = _optionalChain([this, 'access', _82 => _82.document, 'access', _83 => _83.cells, 'access', _84 => _84[rowId], 'optionalAccess', _85 => _85[colId]]);
1479
+ const existing = _optionalChain([this, 'access', _86 => _86.document, 'access', _87 => _87.cells, 'access', _88 => _88[rowId], 'optionalAccess', _89 => _89[colId]]);
1499
1480
  if (existing && existing.raw !== "") return existing;
1500
1481
  if (this.spillCells.size > 0) {
1501
1482
  const spilled = this.spillCells.get(spillCellId(rowId, colId));
1502
1483
  if (spilled) return spilled;
1503
1484
  }
1504
- if (existing) return existing;
1485
+ if (existing && !existing.explicitNumberFormat) return existing;
1505
1486
  const col = this.document.columns.find((c) => c.id === colId);
1506
1487
  const row = this.document.rows.find((r) => r.id === rowId);
1507
- return this.getDerivedCell(row, col);
1488
+ const derived = this.getDerivedCell(row, col);
1489
+ if (!existing) return derived;
1490
+ if (derived.raw === "") return existing;
1491
+ return { ...derived, numberFormat: existing.numberFormat, explicitNumberFormat: true };
1508
1492
  }
1509
1493
  /** Value of a cell with no stored data: bound record value, column formula, or blank. */
1510
1494
  getDerivedCell(row, col) {
@@ -1517,17 +1501,19 @@ var SpreadsheetController = (_class3 = class {
1517
1501
  return {
1518
1502
  raw: boundVal !== void 0 ? String(boundVal) : "",
1519
1503
  value: _nullishCoalesce(boundVal, () => ( "")),
1520
- format: col.format
1504
+ format: col.format,
1505
+ ...this.fixedNumberFormatFields(col, void 0)
1521
1506
  };
1522
1507
  }
1523
1508
  if (col && col.type === "formula" && col.formula) {
1524
1509
  return {
1525
1510
  raw: col.formula,
1526
1511
  value: "",
1527
- format: col.format
1512
+ format: col.format,
1513
+ ...this.fixedNumberFormatFields(col, void 0)
1528
1514
  };
1529
1515
  }
1530
- return { raw: "", value: "", format: _optionalChain([col, 'optionalAccess', _86 => _86.format]) };
1516
+ return { raw: "", value: "", format: _optionalChain([col, 'optionalAccess', _90 => _90.format]), ...this.fixedNumberFormatFields(col, void 0) };
1531
1517
  }
1532
1518
  setCellValue(rowId, colId, raw) {
1533
1519
  this.recordSnapshot();
@@ -1537,15 +1523,16 @@ var SpreadsheetController = (_class3 = class {
1537
1523
  const col = this.document.columns.find((c) => c.id === colId);
1538
1524
  const row = this.document.rows.find((r) => r.id === rowId);
1539
1525
  const isFormula = raw.startsWith("=");
1526
+ const existing = this.document.cells[rowId][colId];
1540
1527
  let cell;
1541
- if (_optionalChain([col, 'optionalAccess', _87 => _87.type]) === "bound" && col.binding && _optionalChain([row, 'optionalAccess', _88 => _88.recordId])) {
1528
+ if (_optionalChain([col, 'optionalAccess', _91 => _91.type]) === "bound" && col.binding && _optionalChain([row, 'optionalAccess', _92 => _92.recordId])) {
1542
1529
  const value = this.boundInputValue(col.binding.dataSource, col.binding.field, raw);
1543
1530
  this.binder.commitBoundValue(col.binding.dataSource, row.recordId, col.binding.field, value);
1544
- cell = { raw, value, format: col.format };
1531
+ cell = { raw, value, format: col.format, ...this.fixedNumberFormatFields(col, existing) };
1545
1532
  } else if (isFormula) {
1546
- cell = { raw, value: raw, format: _optionalChain([col, 'optionalAccess', _89 => _89.format]) };
1533
+ cell = { raw, value: raw, format: _optionalChain([col, 'optionalAccess', _93 => _93.format]), ...this.fixedNumberFormatFields(col, existing) };
1547
1534
  } else {
1548
- cell = { raw, ...this.typedCell(raw, _optionalChain([col, 'optionalAccess', _90 => _90.format])) };
1535
+ cell = { raw, ...this.typedCell(raw, _optionalChain([col, 'optionalAccess', _94 => _94.format]), col, existing) };
1549
1536
  }
1550
1537
  const cellKey = this.getCellKey(rowId, colId);
1551
1538
  this.depGraph.setCellFormula(cellKey, isFormula ? raw : null);
@@ -1557,8 +1544,8 @@ var SpreadsheetController = (_class3 = class {
1557
1544
  }
1558
1545
  this.recalculateCell(rowId, colId);
1559
1546
  this.notifyChange();
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)]);
1547
+ const evaluatedVal = _optionalChain([this, 'access', _95 => _95.document, 'access', _96 => _96.cells, 'access', _97 => _97[rowId], 'access', _98 => _98[colId], 'optionalAccess', _99 => _99.value]);
1548
+ _optionalChain([this, 'access', _100 => _100.onCellCommit, 'optionalCall', _101 => _101(rowId, colId, raw, evaluatedVal)]);
1562
1549
  }
1563
1550
  getCellKey(rowId, colId) {
1564
1551
  const row = this.document.rows.find((r) => r.id === rowId);
@@ -1609,7 +1596,7 @@ var SpreadsheetController = (_class3 = class {
1609
1596
  const formulaKeys = [];
1610
1597
  for (const row of this.document.rows) {
1611
1598
  for (const col of this.document.columns) {
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)));
1599
+ const cell = _nullishCoalesce(_optionalChain([this, 'access', _102 => _102.document, 'access', _103 => _103.cells, 'access', _104 => _104[row.id], 'optionalAccess', _105 => _105[col.id]]), () => ( this.getDerivedCell(row, col)));
1613
1600
  if (cell.raw.startsWith("=")) {
1614
1601
  const cellKey = `${col.key}${row.index + 1}`.toUpperCase();
1615
1602
  this.depGraph.setCellFormula(cellKey, cell.raw);
@@ -1707,7 +1694,7 @@ var SpreadsheetController = (_class3 = class {
1707
1694
  placeSpill(anchor, row, col, array) {
1708
1695
  const { rows, cols } = array;
1709
1696
  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}`;
1697
+ const label = `${_chunkMCSJFWAOcjs.indexToColName.call(void 0, area.startCol)}${area.startRow + 1}:${_chunkMCSJFWAOcjs.indexToColName.call(void 0, area.endCol)}${area.endRow + 1}`;
1711
1698
  let reason = null;
1712
1699
  const blockers = [];
1713
1700
  if (area.endRow >= this.document.rows.length || area.endCol >= this.document.columns.length) {
@@ -1721,7 +1708,7 @@ var SpreadsheetController = (_class3 = class {
1721
1708
  if (r === row && c === col) continue;
1722
1709
  const rowObj = this.document.rows[r];
1723
1710
  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]]);
1711
+ const stored = _optionalChain([this, 'access', _106 => _106.document, 'access', _107 => _107.cells, 'access', _108 => _108[rowObj.id], 'optionalAccess', _109 => _109[column.id]]);
1725
1712
  const raw = stored ? stored.raw : this.getDerivedCell(rowObj, column).raw;
1726
1713
  const owner = this.spilledBy.get(key);
1727
1714
  if (raw !== "") {
@@ -1748,15 +1735,21 @@ var SpreadsheetController = (_class3 = class {
1748
1735
  const rowObj = this.document.rows[row + r];
1749
1736
  const key = `${column.key}${row + r + 1}`.toUpperCase();
1750
1737
  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)) {
1738
+ const display = {
1739
+ raw: "",
1740
+ value,
1741
+ format: column.format,
1742
+ spillAnchor: anchor,
1743
+ ...this.fixedNumberFormatFields(column, _optionalChain([this, 'access', _110 => _110.document, 'access', _111 => _111.cells, 'access', _112 => _112[rowObj.id], 'optionalAccess', _113 => _113[column.id]]))
1744
+ };
1745
+ if (_chunkMCSJFWAOcjs.isFormulaError.call(void 0, value)) {
1753
1746
  display.error = value;
1754
- display.errorMessage = _chunkRIKBJLS2cjs.describeFormulaError.call(void 0, value);
1747
+ display.errorMessage = _chunkMCSJFWAOcjs.describeFormulaError.call(void 0, value);
1755
1748
  }
1756
1749
  this.spillCells.set(spillCellId(rowObj.id, column.id), display);
1757
1750
  if (this.spilledBy.get(key) !== anchor) {
1758
1751
  this.spilledBy.set(key, anchor);
1759
- _optionalChain([this, 'access', _106 => _106.spillChanges, 'optionalAccess', _107 => _107.add, 'call', _108 => _108(key)]);
1752
+ _optionalChain([this, 'access', _114 => _114.spillChanges, 'optionalAccess', _115 => _115.add, 'call', _116 => _116(key)]);
1760
1753
  }
1761
1754
  cells.push({ key, rowId: rowObj.id, colId: column.id });
1762
1755
  }
@@ -1785,13 +1778,13 @@ var SpreadsheetController = (_class3 = class {
1785
1778
  if (this.spilledBy.get(cell.key) !== anchor) return;
1786
1779
  this.spilledBy.delete(cell.key);
1787
1780
  this.spillCells.delete(spillCellId(cell.rowId, cell.colId));
1788
- _optionalChain([this, 'access', _109 => _109.spillChanges, 'optionalAccess', _110 => _110.add, 'call', _111 => _111(cell.key)]);
1781
+ _optionalChain([this, 'access', _117 => _117.spillChanges, 'optionalAccess', _118 => _118.add, 'call', _119 => _119(cell.key)]);
1789
1782
  }
1790
1783
  resolveSpillByCoord(colStr, rowNum) {
1791
1784
  const record = this.spills.get(`${colStr}${rowNum}`.toUpperCase());
1792
1785
  if (record) return { rows: record.rows, cols: record.cols, values: record.values };
1793
1786
  const value = this.resolveCellByCoord(colStr, rowNum);
1794
- return _chunkRIKBJLS2cjs.isFormulaError.call(void 0, value) ? value : "#REF!";
1787
+ return _chunkMCSJFWAOcjs.isFormulaError.call(void 0, value) ? value : "#REF!";
1795
1788
  }
1796
1789
  toSpill(record) {
1797
1790
  const row = this.document.rows[record.row];
@@ -1814,7 +1807,7 @@ var SpreadsheetController = (_class3 = class {
1814
1807
  */
1815
1808
  getSpillAt(row, col) {
1816
1809
  if (this.spills.size === 0) return null;
1817
- const key = `${_chunkRIKBJLS2cjs.indexToColName.call(void 0, col)}${row + 1}`;
1810
+ const key = `${_chunkMCSJFWAOcjs.indexToColName.call(void 0, col)}${row + 1}`;
1818
1811
  const record = _nullishCoalesce(this.spills.get(key), () => ( this.spills.get(_nullishCoalesce(this.spilledBy.get(key), () => ( "")))));
1819
1812
  return record ? this.toSpill(record) : null;
1820
1813
  }
@@ -1842,15 +1835,15 @@ var SpreadsheetController = (_class3 = class {
1842
1835
  return _nullishCoalesce(this.getCell(row.id, col.id).value, () => ( ""));
1843
1836
  }
1844
1837
  resolveRangeByCoords(sCol, sRow, eCol, eRow) {
1845
- const startC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, sCol);
1846
- const endC = _chunkRIKBJLS2cjs.colNameToIndex.call(void 0, eCol);
1838
+ const startC = _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, sCol);
1839
+ const endC = _chunkMCSJFWAOcjs.colNameToIndex.call(void 0, eCol);
1847
1840
  const minC = Math.min(startC, endC);
1848
1841
  const maxC = Math.max(startC, endC);
1849
1842
  const minR = Math.min(sRow, eRow);
1850
- const maxR = Math.min(Math.max(sRow, eRow), _chunkRIKBJLS2cjs.WHOLE_COLUMN_END_ROW, this.document.rows.length);
1843
+ const maxR = Math.min(Math.max(sRow, eRow), _chunkMCSJFWAOcjs.WHOLE_COLUMN_END_ROW, this.document.rows.length);
1851
1844
  const results = [];
1852
1845
  for (let c = minC; c <= maxC; c++) {
1853
- const colName = _chunkRIKBJLS2cjs.indexToColName.call(void 0, c);
1846
+ const colName = _chunkMCSJFWAOcjs.indexToColName.call(void 0, c);
1854
1847
  const col = this.document.columns.find((colDef) => colDef.key.toUpperCase() === colName);
1855
1848
  if (!col) continue;
1856
1849
  for (let r = minR; r <= maxR; r++) {
@@ -1862,7 +1855,7 @@ var SpreadsheetController = (_class3 = class {
1862
1855
  return results;
1863
1856
  }
1864
1857
  resolveCurrentRowProperty(prop) {
1865
- const rowIndex = _nullishCoalesce(this.evaluatingRowIndex, () => ( _optionalChain([this, 'access', _112 => _112.activeCell, 'optionalAccess', _113 => _113.row])));
1858
+ const rowIndex = _nullishCoalesce(this.evaluatingRowIndex, () => ( _optionalChain([this, 'access', _120 => _120.activeCell, 'optionalAccess', _121 => _121.row])));
1866
1859
  if (rowIndex === void 0 || rowIndex === null) return 0;
1867
1860
  const row = this.document.rows[rowIndex];
1868
1861
  if (!row || !row.recordId || !this.primaryDataSourceId) return 0;
@@ -1880,8 +1873,8 @@ var SpreadsheetController = (_class3 = class {
1880
1873
  this.activeCell = {
1881
1874
  row: activeRow,
1882
1875
  col: activeCol,
1883
- rowId: _optionalChain([rowObj, 'optionalAccess', _114 => _114.id]),
1884
- colId: _optionalChain([colObj, 'optionalAccess', _115 => _115.id])
1876
+ rowId: _optionalChain([rowObj, 'optionalAccess', _122 => _122.id]),
1877
+ colId: _optionalChain([colObj, 'optionalAccess', _123 => _123.id])
1885
1878
  };
1886
1879
  if (extendSelection && this.selectedRange) {
1887
1880
  this.selectedRange = this.expandRangeToMerges({
@@ -1900,16 +1893,16 @@ var SpreadsheetController = (_class3 = class {
1900
1893
  endCol: clampedCol
1901
1894
  };
1902
1895
  }
1903
- _optionalChain([this, 'access', _116 => _116.onSelectionChange, 'optionalCall', _117 => _117(this.activeCell, this.selectedRange)]);
1896
+ _optionalChain([this, 'access', _124 => _124.onSelectionChange, 'optionalCall', _125 => _125(this.activeCell, this.selectedRange)]);
1904
1897
  }
1905
1898
  selectRange(range) {
1906
1899
  this.selectedRange = range;
1907
- _optionalChain([this, 'access', _118 => _118.onSelectionChange, 'optionalCall', _119 => _119(this.activeCell, this.selectedRange)]);
1900
+ _optionalChain([this, 'access', _126 => _126.onSelectionChange, 'optionalCall', _127 => _127(this.activeCell, this.selectedRange)]);
1908
1901
  }
1909
1902
  startEditing(row, col, initialValue) {
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));
1903
+ this.selectCell(_nullishCoalesce(_nullishCoalesce(row, () => ( _optionalChain([this, 'access', _128 => _128.activeCell, 'optionalAccess', _129 => _129.row]))), () => ( 0)), _nullishCoalesce(_nullishCoalesce(col, () => ( _optionalChain([this, 'access', _130 => _130.activeCell, 'optionalAccess', _131 => _131.col]))), () => ( 0)));
1904
+ const targetRow = _nullishCoalesce(_optionalChain([this, 'access', _132 => _132.activeCell, 'optionalAccess', _133 => _133.row]), () => ( 0));
1905
+ const targetCol = _nullishCoalesce(_optionalChain([this, 'access', _134 => _134.activeCell, 'optionalAccess', _135 => _135.col]), () => ( 0));
1913
1906
  const rowObj = this.document.rows[targetRow];
1914
1907
  const colObj = this.document.columns[targetCol];
1915
1908
  if (!rowObj || !colObj) return;
@@ -1963,17 +1956,18 @@ var SpreadsheetController = (_class3 = class {
1963
1956
  // --- Grid Structure Mutations ---
1964
1957
  insertColumn(index, config) {
1965
1958
  this.recordSnapshot();
1966
- const newId = _optionalChain([config, 'optionalAccess', _128 => _128.id]) || this.generateId("col");
1959
+ const newId = _optionalChain([config, 'optionalAccess', _136 => _136.id]) || this.generateId("col");
1967
1960
  const newCol = {
1968
1961
  id: newId,
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])
1962
+ key: _chunkMCSJFWAOcjs.indexToColName.call(void 0, index),
1963
+ title: _optionalChain([config, 'optionalAccess', _137 => _137.title]) || _chunkMCSJFWAOcjs.indexToColName.call(void 0, index),
1964
+ width: _optionalChain([config, 'optionalAccess', _138 => _138.width]) || 130,
1965
+ type: _optionalChain([config, 'optionalAccess', _139 => _139.type]) || "freeform",
1966
+ binding: _optionalChain([config, 'optionalAccess', _140 => _140.binding]),
1967
+ formula: _optionalChain([config, 'optionalAccess', _141 => _141.formula]),
1968
+ format: _optionalChain([config, 'optionalAccess', _142 => _142.format]) || "text",
1969
+ ..._optionalChain([config, 'optionalAccess', _143 => _143.numberFormat]) ? { numberFormat: config.numberFormat } : {},
1970
+ readOnly: _optionalChain([config, 'optionalAccess', _144 => _144.readOnly])
1977
1971
  };
1978
1972
  this.shiftReferences({ axis: "col", index, type: "insert" });
1979
1973
  this.adjustTableForStructuralChange({ axis: "col", index, type: "insert" });
@@ -1998,13 +1992,13 @@ var SpreadsheetController = (_class3 = class {
1998
1992
  }
1999
1993
  insertRow(index, config) {
2000
1994
  this.recordSnapshot();
2001
- const newId = _optionalChain([config, 'optionalAccess', _136 => _136.id]) || this.generateId("row");
1995
+ const newId = _optionalChain([config, 'optionalAccess', _145 => _145.id]) || this.generateId("row");
2002
1996
  const newRow = {
2003
1997
  id: newId,
2004
1998
  index,
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"
1999
+ height: _optionalChain([config, 'optionalAccess', _146 => _146.height]) || 32,
2000
+ recordId: _optionalChain([config, 'optionalAccess', _147 => _147.recordId]),
2001
+ type: _optionalChain([config, 'optionalAccess', _148 => _148.type]) || "freeform"
2008
2002
  };
2009
2003
  this.shiftReferences({ axis: "row", index, type: "insert" });
2010
2004
  this.adjustTableForStructuralChange({ axis: "row", index, type: "insert" });
@@ -2035,14 +2029,14 @@ var SpreadsheetController = (_class3 = class {
2035
2029
  shiftReferences(change) {
2036
2030
  for (const rowCells of Object.values(this.document.cells)) {
2037
2031
  for (const cell of Object.values(rowCells)) {
2038
- if (_optionalChain([cell, 'access', _140 => _140.raw, 'optionalAccess', _141 => _141.startsWith, 'call', _142 => _142("=")])) {
2032
+ if (_optionalChain([cell, 'access', _149 => _149.raw, 'optionalAccess', _150 => _150.startsWith, 'call', _151 => _151("=")])) {
2039
2033
  cell.raw = shiftFormulaReferences(cell.raw, change);
2040
2034
  }
2041
2035
  }
2042
2036
  }
2043
2037
  if (change.axis === "col") {
2044
2038
  for (const col of this.document.columns) {
2045
- if (_optionalChain([col, 'access', _143 => _143.formula, 'optionalAccess', _144 => _144.startsWith, 'call', _145 => _145("=")])) {
2039
+ if (_optionalChain([col, 'access', _152 => _152.formula, 'optionalAccess', _153 => _153.startsWith, 'call', _154 => _154("=")])) {
2046
2040
  col.formula = shiftFormulaReferences(col.formula, change);
2047
2041
  }
2048
2042
  }
@@ -2065,7 +2059,7 @@ var SpreadsheetController = (_class3 = class {
2065
2059
  let maxLen = (col.title || "").length + (col.key ? col.key.length + 3 : 0);
2066
2060
  for (const row of this.document.rows) {
2067
2061
  const cell = this.getCell(row.id, col.id);
2068
- const valStr = _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cell);
2062
+ const valStr = formatCellDisplay(cell);
2069
2063
  if (valStr.length > maxLen) {
2070
2064
  maxLen = valStr.length;
2071
2065
  }
@@ -2089,7 +2083,7 @@ var SpreadsheetController = (_class3 = class {
2089
2083
  ) : this.document.columns;
2090
2084
  return rows.map(
2091
2085
  (row) => columns.map((col) => {
2092
- return _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, this.getCell(row.id, col.id)).replace(/\t/g, " ");
2086
+ return formatCellDisplay(this.getCell(row.id, col.id)).replace(/\t/g, " ");
2093
2087
  }).join(" ")
2094
2088
  ).join("\n");
2095
2089
  }
@@ -2109,7 +2103,7 @@ var SpreadsheetController = (_class3 = class {
2109
2103
  this.document.rows.push({ id: this.generateId("row"), index, height: 32, type: "freeform" });
2110
2104
  }
2111
2105
  while (colIndex >= this.document.columns.length) {
2112
- const key = _chunkRIKBJLS2cjs.indexToColName.call(void 0, this.document.columns.length);
2106
+ const key = _chunkMCSJFWAOcjs.indexToColName.call(void 0, this.document.columns.length);
2113
2107
  this.document.columns.push({
2114
2108
  id: this.generateId("col"),
2115
2109
  key,
@@ -2156,7 +2150,7 @@ var SpreadsheetController = (_class3 = class {
2156
2150
  const commits = this.pendingCommits;
2157
2151
  this.pendingCommits = [];
2158
2152
  for (const [rowId, colId, raw] of commits) {
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]))]);
2153
+ _optionalChain([this, 'access', _155 => _155.onCellCommit, 'optionalCall', _156 => _156(rowId, colId, raw, _optionalChain([this, 'access', _157 => _157.document, 'access', _158 => _158.cells, 'access', _159 => _159[rowId], 'optionalAccess', _160 => _160[colId], 'optionalAccess', _161 => _161.value]))]);
2160
2154
  }
2161
2155
  }
2162
2156
  // --- CSV ---
@@ -2166,9 +2160,9 @@ var SpreadsheetController = (_class3 = class {
2166
2160
  */
2167
2161
  exportToCsv(options = {}) {
2168
2162
  const matrix = this.readMatrix(_nullishCoalesce(options.range, () => ( null))).map(
2169
- (row) => row.map((cell) => options.formulas ? cell.raw : _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cell))
2163
+ (row) => row.map((cell) => options.formulas ? cell.raw : formatCellDisplay(cell))
2170
2164
  );
2171
- return serializeCsv(matrix, {
2165
+ return _chunkTNNJXF46cjs.serializeCsv.call(void 0, matrix, {
2172
2166
  delimiter: options.delimiter,
2173
2167
  lineEnding: options.lineEnding,
2174
2168
  bom: options.bom
@@ -2179,7 +2173,7 @@ var SpreadsheetController = (_class3 = class {
2179
2173
  * as needed. The whole import is a single undo step.
2180
2174
  */
2181
2175
  importFromCsv(csv, options = {}) {
2182
- const matrix = parseCsv(csv, { delimiter: options.delimiter });
2176
+ const matrix = _chunkTNNJXF46cjs.parseCsv.call(void 0, csv, { delimiter: options.delimiter });
2183
2177
  this.writeMatrix(matrix, _nullishCoalesce(options.startRow, () => ( 0)), _nullishCoalesce(options.startCol, () => ( 0)));
2184
2178
  }
2185
2179
  /**
@@ -2207,7 +2201,7 @@ var SpreadsheetController = (_class3 = class {
2207
2201
  const cells = this.readMatrix(r).map(
2208
2202
  (row) => row.map((cell) => {
2209
2203
  const value = cell.error || cell.value;
2210
- const text = _chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cell);
2204
+ const text = formatCellDisplay(cell);
2211
2205
  if (cell.spillAnchor && !this.spillAnchorInRange(cell.spillAnchor, r)) {
2212
2206
  return { raw: text, value, text };
2213
2207
  }
@@ -2245,7 +2239,7 @@ var SpreadsheetController = (_class3 = class {
2245
2239
  const r = normalizeRange(this.selectedRange);
2246
2240
  return { row: r.startRow, col: r.startCol };
2247
2241
  }
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)) };
2242
+ return { row: _nullishCoalesce(_optionalChain([this, 'access', _162 => _162.activeCell, 'optionalAccess', _163 => _163.row]), () => ( 0)), col: _nullishCoalesce(_optionalChain([this, 'access', _164 => _164.activeCell, 'optionalAccess', _165 => _165.col]), () => ( 0)) };
2249
2243
  }
2250
2244
  // --- Table operations: shared helpers ---
2251
2245
  /** The table settings object, created on first use. */
@@ -2279,7 +2273,7 @@ var SpreadsheetController = (_class3 = class {
2279
2273
  remapAllFormulas(moveCell) {
2280
2274
  for (const rowCells of Object.values(this.document.cells)) {
2281
2275
  for (const cell of Object.values(rowCells)) {
2282
- if (_optionalChain([cell, 'access', _157 => _157.raw, 'optionalAccess', _158 => _158.startsWith, 'call', _159 => _159("=")])) {
2276
+ if (_optionalChain([cell, 'access', _166 => _166.raw, 'optionalAccess', _167 => _167.startsWith, 'call', _168 => _168("=")])) {
2283
2277
  cell.raw = remapFormulaReferences(cell.raw, moveCell);
2284
2278
  }
2285
2279
  }
@@ -2291,8 +2285,8 @@ var SpreadsheetController = (_class3 = class {
2291
2285
  * merges reduced to a single cell are dropped.
2292
2286
  */
2293
2287
  adjustTableForStructuralChange(change) {
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;
2288
+ const merges = _optionalChain([this, 'access', _169 => _169.document, 'access', _170 => _170.table, 'optionalAccess', _171 => _171.merges]);
2289
+ if (!_optionalChain([merges, 'optionalAccess', _172 => _172.length])) return;
2296
2290
  const startKey = change.axis === "row" ? "startRow" : "startCol";
2297
2291
  const endKey = change.axis === "row" ? "endRow" : "endCol";
2298
2292
  const next = [];
@@ -2323,8 +2317,8 @@ var SpreadsheetController = (_class3 = class {
2323
2317
  const colCount = this.document.columns.length;
2324
2318
  const body = this.getBodyRowBounds();
2325
2319
  const range = options.range ? normalizeRange(options.range) : null;
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);
2320
+ const startRow = Math.max(_nullishCoalesce(_optionalChain([range, 'optionalAccess', _173 => _173.startRow]), () => ( body.start)), body.start);
2321
+ const endRow = Math.min(_nullishCoalesce(_optionalChain([range, 'optionalAccess', _174 => _174.endRow]), () => ( body.end)), body.end);
2328
2322
  const startCol = range ? Math.max(0, range.startCol) : 0;
2329
2323
  const endCol = range ? Math.min(colCount - 1, range.endCol) : colCount - 1;
2330
2324
  if (endRow - startRow < 1 || startCol > endCol) return false;
@@ -2334,7 +2328,7 @@ var SpreadsheetController = (_class3 = class {
2334
2328
  }));
2335
2329
  if (keyCols.length === 0 || keyCols.some((k) => k.index < startCol || k.index > endCol)) return false;
2336
2330
  const area = { startRow, startCol, endRow, endCol };
2337
- if ((_nullishCoalesce(_optionalChain([this, 'access', _166 => _166.document, 'access', _167 => _167.table, 'optionalAccess', _168 => _168.merges]), () => ( []))).some((m) => rangesIntersect(m, area))) return false;
2331
+ if ((_nullishCoalesce(_optionalChain([this, 'access', _175 => _175.document, 'access', _176 => _176.table, 'optionalAccess', _177 => _177.merges]), () => ( []))).some((m) => rangesIntersect(m, area))) return false;
2338
2332
  if (this.intersectsSpill(area)) return false;
2339
2333
  const sourceRows = [];
2340
2334
  for (let r = startRow; r <= endRow; r++) sourceRows.push(r);
@@ -2362,7 +2356,7 @@ var SpreadsheetController = (_class3 = class {
2362
2356
  const colIds = this.document.columns.slice(startCol, endCol + 1).map((c) => c.id);
2363
2357
  const snapshot = sorted.map((oldRow) => {
2364
2358
  const rowId = this.document.rows[oldRow].id;
2365
- return colIds.map((colId) => _optionalChain([this, 'access', _169 => _169.document, 'access', _170 => _170.cells, 'access', _171 => _171[rowId], 'optionalAccess', _172 => _172[colId]]));
2359
+ return colIds.map((colId) => _optionalChain([this, 'access', _178 => _178.document, 'access', _179 => _179.cells, 'access', _180 => _180[rowId], 'optionalAccess', _181 => _181[colId]]));
2366
2360
  });
2367
2361
  snapshot.forEach((cells, i) => {
2368
2362
  const rowId = this.document.rows[startRow + i].id;
@@ -2378,7 +2372,7 @@ var SpreadsheetController = (_class3 = class {
2378
2372
  }
2379
2373
  // --- Filters ---
2380
2374
  getFilterState() {
2381
- return _nullishCoalesce(_optionalChain([this, 'access', _173 => _173.document, 'access', _174 => _174.table, 'optionalAccess', _175 => _175.filter]), () => ( { enabled: false, rules: [] }));
2375
+ return _nullishCoalesce(_optionalChain([this, 'access', _182 => _182.document, 'access', _183 => _183.table, 'optionalAccess', _184 => _184.filter]), () => ( { enabled: false, rules: [] }));
2382
2376
  }
2383
2377
  /** Replaces all filter rules (and turns filters on when there are any). */
2384
2378
  setFilterRules(rules) {
@@ -2455,11 +2449,99 @@ var SpreadsheetController = (_class3 = class {
2455
2449
  }
2456
2450
  setTableCount(key, count, max) {
2457
2451
  const value = Math.max(0, Math.min(Math.floor(count), max));
2458
- if ((_nullishCoalesce(_optionalChain([this, 'access', _176 => _176.document, 'access', _177 => _177.table, 'optionalAccess', _178 => _178[key]]), () => ( 0))) === value) return;
2452
+ if ((_nullishCoalesce(_optionalChain([this, 'access', _185 => _185.document, 'access', _186 => _186.table, 'optionalAccess', _187 => _187[key]]), () => ( 0))) === value) return;
2459
2453
  this.applyTableChange(() => {
2460
2454
  this.table[key] = value;
2461
2455
  });
2462
2456
  }
2457
+ // --- Number formats ---
2458
+ //
2459
+ // Cells are replaced, never mutated in place: framework bindings compare
2460
+ // cell objects by identity to decide what to re-render.
2461
+ /**
2462
+ * Sets an explicit number format code (e.g. `0.00`, `"$"#,##0.00`,
2463
+ * `m/d/yyyy`, `[Red]0;[Blue]-0`) on every cell in `range`, including blank
2464
+ * cells, so values typed later keep it. `null` removes explicit formats: the
2465
+ * cells go back to their column's format or the one chosen for typed input.
2466
+ * Undoable as one step. Returns false when there is no range.
2467
+ */
2468
+ setCellNumberFormat(range, code) {
2469
+ if (!range) return false;
2470
+ const r = normalizeRange(range);
2471
+ this.recordSnapshot();
2472
+ const kind = code === null ? void 0 : cellFormatForNumberFormat(code);
2473
+ for (let ri = r.startRow; ri <= r.endRow; ri++) {
2474
+ const row = this.document.rows[ri];
2475
+ if (!row) continue;
2476
+ for (let ci = r.startCol; ci <= r.endCol; ci++) {
2477
+ const col = this.document.columns[ci];
2478
+ if (!col) continue;
2479
+ const cells = this.document.cells[row.id] ??= {};
2480
+ const existing = cells[col.id];
2481
+ if (code === null) {
2482
+ if (!_optionalChain([existing, 'optionalAccess', _188 => _188.explicitNumberFormat])) continue;
2483
+ if (existing.raw === "" && existing.value === "" && !existing.error) {
2484
+ delete cells[col.id];
2485
+ } else {
2486
+ const { explicitNumberFormat: _explicit, ...rest } = existing;
2487
+ cells[col.id] = this.withNumberFormat(rest, this.implicitNumberFormat(rest, col, row));
2488
+ }
2489
+ } else {
2490
+ cells[col.id] = {
2491
+ ..._nullishCoalesce(existing, () => ( { raw: "", value: "" })),
2492
+ format: _nullishCoalesce(_nullishCoalesce(kind, () => ( _optionalChain([existing, 'optionalAccess', _189 => _189.format]))), () => ( col.format)),
2493
+ numberFormat: code,
2494
+ explicitNumberFormat: true
2495
+ };
2496
+ }
2497
+ this.refreshSpilledNumberFormat(row, col);
2498
+ }
2499
+ }
2500
+ this.document.updatedAt = Date.now();
2501
+ this.notifyChange();
2502
+ return true;
2503
+ }
2504
+ /**
2505
+ * Sets the number format code of a column (`null` or `General` clears it).
2506
+ * Its cells without an explicit format of their own use it, including
2507
+ * values typed later; when cleared they go back to the format chosen for
2508
+ * typed input. Undoable.
2509
+ */
2510
+ setColumnNumberFormat(colId, code) {
2511
+ const col = this.getColumn(colId);
2512
+ if (!col) return;
2513
+ this.recordSnapshot();
2514
+ if (code === null || isGeneralNumberFormat(code)) delete col.numberFormat;
2515
+ else col.numberFormat = code;
2516
+ for (const row of this.document.rows) {
2517
+ const cells = this.document.cells[row.id];
2518
+ const cell = _optionalChain([cells, 'optionalAccess', _190 => _190[col.id]]);
2519
+ if (cells && cell && !cell.explicitNumberFormat) {
2520
+ cells[col.id] = this.withNumberFormat(cell, this.implicitNumberFormat(cell, col, row));
2521
+ }
2522
+ this.refreshSpilledNumberFormat(row, col);
2523
+ }
2524
+ this.document.updatedAt = Date.now();
2525
+ this.notifyChange();
2526
+ }
2527
+ /** The column's format, or the one typed input chose (typed cells only). */
2528
+ implicitNumberFormat(cell, col, row) {
2529
+ const typed = cell.raw !== "" && !cell.raw.startsWith("=") && !(col.type === "bound" && col.binding && row.recordId);
2530
+ return _nullishCoalesce(this.fixedNumberFormat(col, void 0), () => ( (typed ? _chunkMCSJFWAOcjs.parseCellInput.call(void 0, cell.raw).numberFormat : void 0)));
2531
+ }
2532
+ /** A copy of `cell` with `numberFormat` set, or removed when undefined. */
2533
+ withNumberFormat(cell, numberFormat) {
2534
+ const { numberFormat: _old, ...rest } = cell;
2535
+ return numberFormat === void 0 ? rest : { ...rest, numberFormat };
2536
+ }
2537
+ /** Re-applies the stored cell's (or the column's) format to a spilled value shown there. */
2538
+ refreshSpilledNumberFormat(row, col) {
2539
+ const id = spillCellId(row.id, col.id);
2540
+ const spilled = this.spillCells.get(id);
2541
+ if (!spilled) return;
2542
+ const { numberFormat: _old, explicitNumberFormat: _explicit, ...rest } = spilled;
2543
+ this.spillCells.set(id, { ...rest, ...this.fixedNumberFormatFields(col, _optionalChain([this, 'access', _191 => _191.document, 'access', _192 => _192.cells, 'access', _193 => _193[row.id], 'optionalAccess', _194 => _194[col.id]])) });
2544
+ }
2463
2545
  // --- Hide / unhide ---
2464
2546
  hideRows(indices) {
2465
2547
  this.setHidden("row", indices, true);
@@ -2496,7 +2578,7 @@ var SpreadsheetController = (_class3 = class {
2496
2578
  }
2497
2579
  // --- Merged cells ---
2498
2580
  getMerges() {
2499
- return _nullishCoalesce(_optionalChain([this, 'access', _179 => _179.document, 'access', _180 => _180.table, 'optionalAccess', _181 => _181.merges]), () => ( []));
2581
+ return _nullishCoalesce(_optionalChain([this, 'access', _195 => _195.document, 'access', _196 => _196.table, 'optionalAccess', _197 => _197.merges]), () => ( []));
2500
2582
  }
2501
2583
  /** The merge containing (row, col), or null. */
2502
2584
  getMergeAt(row, col) {
@@ -2549,7 +2631,7 @@ var SpreadsheetController = (_class3 = class {
2549
2631
  const rowId = this.document.rows[row].id;
2550
2632
  for (let col = r.startCol; col <= r.endCol; col++) {
2551
2633
  if (row === r.startRow && col === r.startCol) continue;
2552
- _optionalChainDelete([this, 'access', _182 => _182.document, 'access', _183 => _183.cells, 'access', _184 => _184[rowId], 'optionalAccess', _185 => _185[this.document.columns[col].id]]);
2634
+ _optionalChainDelete([this, 'access', _198 => _198.document, 'access', _199 => _199.cells, 'access', _200 => _200[rowId], 'optionalAccess', _201 => _201[this.document.columns[col].id]]);
2553
2635
  }
2554
2636
  }
2555
2637
  this.table.merges = [...merges.filter((m) => !rangeContainsRange(r, m)), r];
@@ -2635,14 +2717,14 @@ var SpreadsheetController = (_class3 = class {
2635
2717
  });
2636
2718
  }
2637
2719
  ungroupRows() {
2638
- if (!_optionalChain([this, 'access', _186 => _186.document, 'access', _187 => _187.table, 'optionalAccess', _188 => _188.grouping])) return;
2720
+ if (!_optionalChain([this, 'access', _202 => _202.document, 'access', _203 => _203.table, 'optionalAccess', _204 => _204.grouping])) return;
2639
2721
  this.applyTableChange(() => {
2640
2722
  delete this.table.grouping;
2641
2723
  });
2642
2724
  }
2643
2725
  /** Sets (or with `null`, removes) the group summary for a column. */
2644
2726
  setGroupSummary(colId, aggregate) {
2645
- const grouping = _optionalChain([this, 'access', _189 => _189.document, 'access', _190 => _190.table, 'optionalAccess', _191 => _191.grouping]);
2727
+ const grouping = _optionalChain([this, 'access', _205 => _205.document, 'access', _206 => _206.table, 'optionalAccess', _207 => _207.grouping]);
2646
2728
  if (!grouping) return;
2647
2729
  this.applyTableChange(() => {
2648
2730
  const others = grouping.summaries.filter((s) => s.colId !== colId);
@@ -2653,7 +2735,7 @@ var SpreadsheetController = (_class3 = class {
2653
2735
  });
2654
2736
  }
2655
2737
  setGroupCollapsed(key, collapsed) {
2656
- const grouping = _optionalChain([this, 'access', _192 => _192.document, 'access', _193 => _193.table, 'optionalAccess', _194 => _194.grouping]);
2738
+ const grouping = _optionalChain([this, 'access', _208 => _208.document, 'access', _209 => _209.table, 'optionalAccess', _210 => _210.grouping]);
2657
2739
  if (!grouping || grouping.collapsed.includes(key) === collapsed) return;
2658
2740
  this.applyTableChange(() => {
2659
2741
  this.table.grouping = {
@@ -2663,7 +2745,7 @@ var SpreadsheetController = (_class3 = class {
2663
2745
  });
2664
2746
  }
2665
2747
  toggleGroupCollapsed(key) {
2666
- const grouping = _optionalChain([this, 'access', _195 => _195.document, 'access', _196 => _196.table, 'optionalAccess', _197 => _197.grouping]);
2748
+ const grouping = _optionalChain([this, 'access', _211 => _211.document, 'access', _212 => _212.table, 'optionalAccess', _213 => _213.grouping]);
2667
2749
  if (!grouping) return;
2668
2750
  this.setGroupCollapsed(key, !grouping.collapsed.includes(key));
2669
2751
  }
@@ -2701,9 +2783,9 @@ var SpreadsheetController = (_class3 = class {
2701
2783
  moved.push({
2702
2784
  row: s.startRow + (c - s.startCol),
2703
2785
  col: s.startCol + (r - s.startRow),
2704
- cell: _optionalChain([this, 'access', _198 => _198.document, 'access', _199 => _199.cells, 'access', _200 => _200[rowId(r)], 'optionalAccess', _201 => _201[colId(c)]])
2786
+ cell: _optionalChain([this, 'access', _214 => _214.document, 'access', _215 => _215.cells, 'access', _216 => _216[rowId(r)], 'optionalAccess', _217 => _217[colId(c)]])
2705
2787
  });
2706
- _optionalChainDelete([this, 'access', _202 => _202.document, 'access', _203 => _203.cells, 'access', _204 => _204[rowId(r)], 'optionalAccess', _205 => _205[colId(c)]]);
2788
+ _optionalChainDelete([this, 'access', _218 => _218.document, 'access', _219 => _219.cells, 'access', _220 => _220[rowId(r)], 'optionalAccess', _221 => _221[colId(c)]]);
2707
2789
  }
2708
2790
  }
2709
2791
  for (const { row, col, cell } of moved) {
@@ -2778,7 +2860,7 @@ var SpreadsheetController = (_class3 = class {
2778
2860
  }
2779
2861
  }
2780
2862
  notifyChange() {
2781
- _optionalChain([this, 'access', _206 => _206.onDocumentChange, 'optionalCall', _207 => _207(this.document)]);
2863
+ _optionalChain([this, 'access', _222 => _222.onDocumentChange, 'optionalCall', _223 => _223(this.document)]);
2782
2864
  }
2783
2865
  }, _class3);
2784
2866
  function stepInOrder(order, from, delta) {
@@ -2793,6 +2875,17 @@ function stepInOrder(order, from, delta) {
2793
2875
  }
2794
2876
 
2795
2877
  // src/spreadsheet/menu.ts
2878
+ function runSpreadsheetMenuItem(item, ask) {
2879
+ if (!item.input) {
2880
+ item.run();
2881
+ return true;
2882
+ }
2883
+ const prompt = _nullishCoalesce(ask, () => ( ((label, value) => typeof window !== "undefined" && window.prompt ? window.prompt(label, value) : null)));
2884
+ const text = prompt(item.input.label, _nullishCoalesce(item.input.defaultValue, () => ( "")));
2885
+ if (text === null || text === void 0) return false;
2886
+ item.run(text);
2887
+ return true;
2888
+ }
2796
2889
  function clampMenuPosition(point, size, viewport, margin = 4) {
2797
2890
  const place = (start, length, limit) => {
2798
2891
  if (start + length <= limit - margin) return Math.max(margin, start);
@@ -2814,7 +2907,7 @@ function getSpreadsheetMenuItems(controller, cell) {
2814
2907
  const row = doc.rows[cell.row];
2815
2908
  if (!column || !row) return [];
2816
2909
  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 };
2817
- const colName = _chunkRIKBJLS2cjs.indexToColName.call(void 0, cell.col);
2910
+ const colName = _chunkMCSJFWAOcjs.indexToColName.call(void 0, cell.col);
2818
2911
  const cellData = controller.getCell(row.id, column.id);
2819
2912
  const value = cellData.value;
2820
2913
  const table = _nullishCoalesce(doc.table, () => ( {}));
@@ -2838,7 +2931,7 @@ function getSpreadsheetMenuItems(controller, cell) {
2838
2931
  },
2839
2932
  {
2840
2933
  id: "filter-equals",
2841
- label: `Show only rows where ${colName} = ${quote(_chunkRIKBJLS2cjs.formatCellDisplay.call(void 0, cellData))}`,
2934
+ label: `Show only rows where ${colName} = ${quote(formatCellDisplay(cellData))}`,
2842
2935
  separatorBefore: true,
2843
2936
  run: () => controller.addFilterRule({ colId: column.id, operator: "equals", value: String(_nullishCoalesce(value, () => ( ""))) })
2844
2937
  },
@@ -2927,6 +3020,31 @@ function getSpreadsheetMenuItems(controller, cell) {
2927
3020
  }
2928
3021
  }
2929
3022
  ];
3023
+ const currentFormat = cellData.numberFormat;
3024
+ const presetMatch = NUMBER_FORMAT_PRESETS.find(
3025
+ (p) => p.id === "general" ? isGeneralNumberFormat(currentFormat) : p.code === currentFormat
3026
+ );
3027
+ NUMBER_FORMAT_PRESETS.forEach((preset, i) => {
3028
+ items.push({
3029
+ id: `number-format-${preset.id}`,
3030
+ label: `Format cells: ${preset.label}`,
3031
+ separatorBefore: i === 0,
3032
+ checked: presetMatch === preset,
3033
+ run: () => {
3034
+ controller.setCellNumberFormat(selection, preset.code);
3035
+ }
3036
+ });
3037
+ });
3038
+ items.push({
3039
+ id: "number-format-custom",
3040
+ label: "Format cells: Custom\u2026",
3041
+ checked: !presetMatch,
3042
+ input: { label: "Number format code, e.g. #,##0.00;[Red](#,##0.00)", defaultValue: _nullishCoalesce(currentFormat, () => ( "General")) },
3043
+ run: (code) => {
3044
+ if (code === void 0) return;
3045
+ controller.setCellNumberFormat(selection, code.trim() === "" ? null : code);
3046
+ }
3047
+ });
2930
3048
  if (grouping) {
2931
3049
  items.push(
2932
3050
  {
@@ -2985,6 +3103,8 @@ var SPREADSHEET_TABLE_ACTIONS = [
2985
3103
  "toggleGroupCollapsed",
2986
3104
  "getGroups",
2987
3105
  "transposeRange",
3106
+ "setCellNumberFormat",
3107
+ "setColumnNumberFormat",
2988
3108
  "exportToCsv",
2989
3109
  "importFromCsv",
2990
3110
  "copyToClipboardData",
@@ -3007,7 +3127,7 @@ function delimitedAdapter(id, label, delimiter, mimeTypes, extensions) {
3007
3127
  extensions,
3008
3128
  target: "spreadsheet",
3009
3129
  async import(_input, context) {
3010
- return { rows: parseCsv(await context.readText(), { delimiter }), delimiter };
3130
+ return { rows: _chunkTNNJXF46cjs.parseCsv.call(void 0, await context.readText(), { delimiter }), delimiter };
3011
3131
  }
3012
3132
  };
3013
3133
  }
@@ -3096,5 +3216,8 @@ async function importFileIntoSpreadsheet(controller, input, options) {
3096
3216
 
3097
3217
 
3098
3218
 
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
3219
+
3220
+
3221
+
3222
+ 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.NUMBER_FORMAT_PRESETS = NUMBER_FORMAT_PRESETS; exports.numberFormatForCellFormat = numberFormatForCellFormat; exports.cellFormatForNumberFormat = cellFormatForNumberFormat; exports.isGeneralNumberFormat = isGeneralNumberFormat; exports.formatCellForDisplay = formatCellForDisplay; exports.formatCellDisplay = formatCellDisplay; exports.formatValueWithCode = formatValueWithCode; 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.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.runSpreadsheetMenuItem = runSpreadsheetMenuItem; 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;
3223
+ //# sourceMappingURL=chunk-MA2F5KHF.cjs.map