@mog-sdk/node 0.1.10 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1311,6 +1311,106 @@ var init_schemas = __esm({
1311
1311
  }
1312
1312
  });
1313
1313
 
1314
+ // ../../kernel/src/api/worksheet/change-accumulator.ts
1315
+ function colToLetter(col) {
1316
+ let result = "";
1317
+ let c = col;
1318
+ while (c >= 0) {
1319
+ result = String.fromCharCode(c % 26 + 65) + result;
1320
+ c = Math.floor(c / 26) - 1;
1321
+ }
1322
+ return result;
1323
+ }
1324
+ function toA1(row, col) {
1325
+ return `${colToLetter(col)}${row + 1}`;
1326
+ }
1327
+ var ChangeAccumulator;
1328
+ var init_change_accumulator = __esm({
1329
+ "../../kernel/src/api/worksheet/change-accumulator.ts"() {
1330
+ "use strict";
1331
+ init_esm_shims();
1332
+ ChangeAccumulator = class {
1333
+ constructor() {
1334
+ this.trackers = /* @__PURE__ */ new Set();
1335
+ /**
1336
+ * Pending direct edits set before a mutation, consumed by the next ingest().
1337
+ * Since JS is single-threaded, setDirectEdits() before the bridge call
1338
+ * guarantees these are consumed by the corresponding ingest().
1339
+ */
1340
+ this.pendingDirectEdits = null;
1341
+ }
1342
+ /**
1343
+ * Set the direct edit positions for the next mutation.
1344
+ * Called by cell-operations before triggering the bridge call.
1345
+ * Consumed (cleared) by the next ingest() call.
1346
+ */
1347
+ setDirectEdits(edits) {
1348
+ this.pendingDirectEdits = edits;
1349
+ }
1350
+ /**
1351
+ * Called by MutationResultHandler after every mutation.
1352
+ *
1353
+ * @param changedCells - RecalcResult.changedCells from the MutationResult
1354
+ * @param directEdits - The (sheetId, row, col) tuples that were directly written
1355
+ * (to distinguish direct vs cascade)
1356
+ * @param source - user or remote
1357
+ */
1358
+ ingest(changedCells, directEdits, source) {
1359
+ if (this.trackers.size === 0) {
1360
+ this.pendingDirectEdits = null;
1361
+ return;
1362
+ }
1363
+ if (changedCells.length === 0) {
1364
+ this.pendingDirectEdits = null;
1365
+ return;
1366
+ }
1367
+ const edits = directEdits ?? this.pendingDirectEdits;
1368
+ this.pendingDirectEdits = null;
1369
+ const directSet = /* @__PURE__ */ new Set();
1370
+ if (edits) {
1371
+ for (const e of edits) {
1372
+ directSet.add(`${e.sheetId}:${e.row}:${e.col}`);
1373
+ }
1374
+ }
1375
+ const recordsBySheet = /* @__PURE__ */ new Map();
1376
+ for (const cell of changedCells) {
1377
+ const key = `${cell.sheetId}:${cell.row}:${cell.col}`;
1378
+ const origin = source === "remote" ? "remote" : directSet.has(key) ? "direct" : "cascade";
1379
+ const record = {
1380
+ address: toA1(cell.row, cell.col),
1381
+ row: cell.row,
1382
+ col: cell.col,
1383
+ origin,
1384
+ type: "modified"
1385
+ };
1386
+ let list = recordsBySheet.get(cell.sheetId);
1387
+ if (!list) {
1388
+ list = [];
1389
+ recordsBySheet.set(cell.sheetId, list);
1390
+ }
1391
+ list.push(record);
1392
+ }
1393
+ for (const tracker of this.trackers) {
1394
+ const records = recordsBySheet.get(tracker.sheetId);
1395
+ if (records && records.length > 0) {
1396
+ tracker._ingest(records);
1397
+ }
1398
+ }
1399
+ }
1400
+ register(tracker) {
1401
+ this.trackers.add(tracker);
1402
+ }
1403
+ unregister(tracker) {
1404
+ this.trackers.delete(tracker);
1405
+ }
1406
+ /** Number of active trackers. */
1407
+ get activeCount() {
1408
+ return this.trackers.size;
1409
+ }
1410
+ };
1411
+ }
1412
+ });
1413
+
1314
1414
  // ../../kernel/src/bridges/mutation-result-handler.ts
1315
1415
  function resolvedPosition(row, col) {
1316
1416
  if (row === POSITION_SENTINEL || col === POSITION_SENTINEL) {
@@ -1323,6 +1423,7 @@ var init_mutation_result_handler = __esm({
1323
1423
  "../../kernel/src/bridges/mutation-result-handler.ts"() {
1324
1424
  "use strict";
1325
1425
  init_esm_shims();
1426
+ init_change_accumulator();
1326
1427
  POSITION_SENTINEL = 4294967295;
1327
1428
  MutationResultHandler = class {
1328
1429
  constructor(eventBus, onUndoDescription) {
@@ -1332,6 +1433,7 @@ var init_mutation_result_handler = __esm({
1332
1433
  this.errorCallbacks = [];
1333
1434
  this.eventBus = eventBus;
1334
1435
  this.onUndoDescription = onUndoDescription;
1436
+ this.changeAccumulator = new ChangeAccumulator();
1335
1437
  }
1336
1438
  /** Set the ViewportCoordinatorRegistry for per-viewport dimension patching. */
1337
1439
  setCoordinatorRegistry(registry2) {
@@ -1353,8 +1455,9 @@ var init_mutation_result_handler = __esm({
1353
1455
  *
1354
1456
  * @param result - MutationResult from a Rust IPC command
1355
1457
  * @param source - Whether this mutation originated from the local user or remote collaboration
1458
+ * @param directEdits - Optional positions of directly-written cells (to distinguish direct vs cascade)
1356
1459
  */
1357
- applyAndNotify(result, source = "user") {
1460
+ applyAndNotify(result, source = "user", directEdits) {
1358
1461
  if (result.recalc) {
1359
1462
  this.handleRecalcResult(result.recalc, source);
1360
1463
  }
@@ -1415,6 +1518,9 @@ var init_mutation_result_handler = __esm({
1415
1518
  if (result.undoDescription) {
1416
1519
  this.handleUndoDescription(result.undoDescription);
1417
1520
  }
1521
+ if (this.changeAccumulator.activeCount > 0 && result.recalc?.changedCells?.length) {
1522
+ this.changeAccumulator.ingest(result.recalc.changedCells, directEdits ?? null, source);
1523
+ }
1418
1524
  }
1419
1525
  /**
1420
1526
  * Register an error callback for mutation failures.
@@ -5978,6 +6084,9 @@ var init_compute_bridge_gen = __esm({
5978
6084
  getCellFormatWithCf(sheetId, cellId, row, col) {
5979
6085
  return this.core.query(this.core.transport.call("compute_get_cell_format_with_cf", { docId: this.core.docId, sheetId, cellId, row, col }));
5980
6086
  }
6087
+ getResolvedFormat(sheetId, row, col) {
6088
+ return this.core.query(this.core.transport.call("compute_get_resolved_format", { docId: this.core.docId, sheetId, row, col }));
6089
+ }
5981
6090
  setCellFormat(sheetId, cellId, format) {
5982
6091
  return this.core.mutatePlain(this.core.transport.call("compute_set_cell_format", { docId: this.core.docId, sheetId, cellId, format }));
5983
6092
  }
@@ -7784,16 +7893,18 @@ var init_core_defaults = __esm({
7784
7893
  async function getMeta(ctx, sheetId) {
7785
7894
  const name = await ctx.computeBridge.getSheetName(sheetId);
7786
7895
  if (name === null) return void 0;
7787
- const [frozen, tabColor, hidden] = await Promise.all([
7896
+ const [frozen, tabColor, hidden, defaultRowHeight, defaultColWidth] = await Promise.all([
7788
7897
  ctx.computeBridge.getFrozenPanesQuery(sheetId),
7789
7898
  ctx.computeBridge.getTabColorQuery(sheetId),
7790
- ctx.computeBridge.isSheetHidden(sheetId)
7899
+ ctx.computeBridge.isSheetHidden(sheetId),
7900
+ ctx.computeBridge.getDefaultRowHeight(sheetId),
7901
+ ctx.computeBridge.getDefaultColWidth(sheetId)
7791
7902
  ]);
7792
7903
  return {
7793
7904
  id: sheetId,
7794
7905
  name,
7795
- defaultRowHeight: 20,
7796
- defaultColWidth: 100,
7906
+ defaultRowHeight,
7907
+ defaultColWidth,
7797
7908
  frozenRows: frozen.rows,
7798
7909
  frozenCols: frozen.cols,
7799
7910
  tabColor: tabColor ?? void 0,
@@ -7840,7 +7951,7 @@ var init_range = __esm({
7840
7951
  });
7841
7952
 
7842
7953
  // ../../spreadsheet-utils/src/a1.ts
7843
- function colToLetter2(col) {
7954
+ function colToLetter3(col) {
7844
7955
  if (col < 0) {
7845
7956
  throw new Error("Column number must be >= 0");
7846
7957
  }
@@ -7860,8 +7971,8 @@ function letterToCol(letters) {
7860
7971
  }
7861
7972
  return result - 1;
7862
7973
  }
7863
- function toA1(row, col) {
7864
- return `${colToLetter2(col)}${row + 1}`;
7974
+ function toA12(row, col) {
7975
+ return `${colToLetter3(col)}${row + 1}`;
7865
7976
  }
7866
7977
  function parseCellAddress(ref) {
7867
7978
  const match = ref.match(CELL_ADDRESS_REGEX);
@@ -77295,6 +77406,10 @@ async function getRefersToA1(ctx, name) {
77295
77406
  const a1 = await ctx.computeBridge.toA1Display(NIL_SHEET_ID, wire);
77296
77407
  return a1.startsWith("=") ? a1 : `=${a1}`;
77297
77408
  }
77409
+ async function getVisible(ctx) {
77410
+ const rustNames = await ctx.computeBridge.getVisibleNamedRanges();
77411
+ return rustNames.map(mapRustNamedRange);
77412
+ }
77298
77413
  async function create2(ctx, input, contextSheet, _origin = "user") {
77299
77414
  const formula = await ctx.computeBridge.toIdentityFormula(contextSheet, input.refersToA1);
77300
77415
  const rawFormula = formula;
@@ -77380,7 +77495,7 @@ async function update2(ctx, id, updates, contextSheet, _origin = "user") {
77380
77495
  }
77381
77496
  const newName = updates.name ?? existing.name;
77382
77497
  if (newName !== existing.name) {
77383
- void ctx.computeBridge.removeNamedRange(existing.name);
77498
+ void ctx.computeBridge.removeNamedRangeById(existing.id);
77384
77499
  }
77385
77500
  let refersToWire = identityFormulaToWire(existing.refersTo);
77386
77501
  if (updates.refersToA1) {
@@ -77467,7 +77582,7 @@ async function remove(ctx, id, _origin = "user") {
77467
77582
  if (!existing) {
77468
77583
  throw new KernelError("DOMAIN_DEFINED_NAME_NOT_FOUND", `Defined name with ID ${id} not found`);
77469
77584
  }
77470
- void ctx.computeBridge.removeNamedRange(existing.name);
77585
+ void ctx.computeBridge.removeNamedRangeById(existing.id);
77471
77586
  }
77472
77587
  async function exportNames(ctx) {
77473
77588
  const all = await getAll(ctx);
@@ -77492,7 +77607,7 @@ function sanitizeLabel(label) {
77492
77607
  }
77493
77608
  return name;
77494
77609
  }
77495
- function colToLetter(col) {
77610
+ function colToLetter2(col) {
77496
77611
  let result = "";
77497
77612
  let c = col;
77498
77613
  while (c >= 0) {
@@ -77566,7 +77681,7 @@ async function createFromSelection(ctx, sheetId, range2, options, _origin = "use
77566
77681
  result.skippedReasons.push({ label: name, reason: validation.message ?? "invalid name" });
77567
77682
  return;
77568
77683
  }
77569
- const refersToA1 = refStartRow === refEndRow && refStartCol === refEndCol ? `=$${colToLetter(refStartCol)}$${refStartRow + 1}` : `=$${colToLetter(refStartCol)}$${refStartRow + 1}:$${colToLetter(refEndCol)}$${refEndRow + 1}`;
77684
+ const refersToA1 = refStartRow === refEndRow && refStartCol === refEndCol ? `=$${colToLetter2(refStartCol)}$${refStartRow + 1}` : `=$${colToLetter2(refStartCol)}$${refStartRow + 1}:$${colToLetter2(refEndCol)}$${refEndRow + 1}`;
77570
77685
  try {
77571
77686
  await create2(ctx, { name: sanitized, refersToA1 }, sheetId);
77572
77687
  existingKeys.add(key);
@@ -78838,6 +78953,7 @@ init_cell_properties();
78838
78953
  var MAX_RANGE_CELLS = 1e4;
78839
78954
  var MAX_RANGE_BOUNDING_BOX = 5e5;
78840
78955
  var MAX_DESCRIBE_OUTPUT_CHARS = 5e4;
78956
+ var MAX_SUMMARY_NAMED_RANGES = 20;
78841
78957
  async function getStyleHints(ctx, sheetId, row, col) {
78842
78958
  const format = await getFormat(ctx, sheetId, row, col);
78843
78959
  if (!format) return null;
@@ -78927,7 +79043,7 @@ function generateFormulaDocumentation(analysis) {
78927
79043
  const lines = [""];
78928
79044
  for (const info of significantPatterns) {
78929
79045
  const examples = info.cells.slice(0, 2).map((cell) => {
78930
- const addr = `${colToLetter2(cell.col)}${cell.row + 1}`;
79046
+ const addr = `${colToLetter3(cell.col)}${cell.row + 1}`;
78931
79047
  return `${addr}: =${cell.formula}`;
78932
79048
  });
78933
79049
  const exampleStr = examples.length > 0 ? ` (e.g. ${examples.join(", ")})` : "";
@@ -78986,7 +79102,7 @@ function buildLeftContext(leftCells, startRow, startCol, endRow) {
78986
79102
  found.sort((a, b) => a.col - b.col);
78987
79103
  const tokens = found.map((f) => {
78988
79104
  const prefix = "\u2192".repeat(Math.max(0, f.indent));
78989
- const addr = `${colToLetter2(f.col)}${row + 1}`;
79105
+ const addr = `${colToLetter3(f.col)}${row + 1}`;
78990
79106
  return `${prefix}${addr}:${f.text}`;
78991
79107
  });
78992
79108
  lines.push(tokens.join(" | "));
@@ -79058,7 +79174,7 @@ function buildAboveContext(aboveCells, startRow, startCol, endCol) {
79058
79174
  sawNumeric = true;
79059
79175
  continue;
79060
79176
  }
79061
- const addr = `${colToLetter2(c)}${bestRow + 1}`;
79177
+ const addr = `${colToLetter3(c)}${bestRow + 1}`;
79062
79178
  if (tokens.length > 0 && sawNumeric) tokens.push("...");
79063
79179
  tokens.push(`${addr}:${d}`);
79064
79180
  sawNumeric = false;
@@ -79116,8 +79232,8 @@ function consolidateRanges(cells) {
79116
79232
  covered.add(`${r},${c}`);
79117
79233
  }
79118
79234
  }
79119
- const start = `${colToLetter2(cell.col)}${cell.row + 1}`;
79120
- const end = `${colToLetter2(endCol)}${endRow + 1}`;
79235
+ const start = `${colToLetter3(cell.col)}${cell.row + 1}`;
79236
+ const end = `${colToLetter3(endCol)}${endRow + 1}`;
79121
79237
  ranges.push(start === end ? start : `${start}:${end}`);
79122
79238
  }
79123
79239
  return ranges;
@@ -79188,9 +79304,12 @@ async function getDisplayValue(ctx, sheetId, row, col) {
79188
79304
  async function getCell(ctx, sheetId, row, col) {
79189
79305
  const data = await getData(ctx, sheetId, row, col);
79190
79306
  if (!data) return void 0;
79307
+ const fmt = await getFormat(ctx, sheetId, row, col);
79191
79308
  return {
79192
79309
  value: (data.formula !== void 0 ? data.computed : rawToCellValue(data.raw)) ?? null,
79193
- formula: data.formula
79310
+ formula: data.formula,
79311
+ format: fmt ?? void 0,
79312
+ formatted: await getDisplayValue(ctx, sheetId, row, col) ?? void 0
79194
79313
  };
79195
79314
  }
79196
79315
  async function getDisplayValue2(ctx, sheetId, row, col) {
@@ -79211,10 +79330,11 @@ async function setCell(ctx, sheetId, row, col, value) {
79211
79330
  throw KernelError.from(null, "COMPUTE_ERROR", `Invalid cell address: row=${row}, col=${col}`);
79212
79331
  }
79213
79332
  const input = value === null || value === void 0 ? "" : value === "" ? "\0" : String(value);
79214
- const result = await ctx.computeBridge.setCellsByPosition(sheetId, [{ row, col, input }]);
79333
+ ctx.computeBridge.getMutationHandler()?.changeAccumulator.setDirectEdits([{ sheetId, row, col }]);
79334
+ await ctx.computeBridge.setCellsByPosition(sheetId, [{ row, col, input }]);
79215
79335
  }
79216
79336
  async function setCells(ctx, sheetId, cells) {
79217
- if (cells.length === 0) return { cellsWritten: 0 };
79337
+ if (cells.length === 0) return { cellsWritten: 0, errors: null };
79218
79338
  const edits = cells.map((cell) => {
79219
79339
  let row;
79220
79340
  let col;
@@ -79236,8 +79356,11 @@ async function setCells(ctx, sheetId, cells) {
79236
79356
  }
79237
79357
  const uniqueEdits = Array.from(deduped.values());
79238
79358
  const duplicatesRemoved = edits.length - uniqueEdits.length;
79359
+ ctx.computeBridge.getMutationHandler()?.changeAccumulator.setDirectEdits(
79360
+ uniqueEdits.map((e) => ({ sheetId, row: e.row, col: e.col }))
79361
+ );
79239
79362
  await ctx.computeBridge.setCellsByPosition(sheetId, uniqueEdits);
79240
- const result = { cellsWritten: uniqueEdits.length };
79363
+ const result = { cellsWritten: uniqueEdits.length, errors: null };
79241
79364
  if (duplicatesRemoved > 0) {
79242
79365
  result.warnings = [
79243
79366
  createWarning("API_DUPLICATE_COORDINATES", `${duplicatesRemoved} duplicate coordinate(s) resolved by last-write-wins`, {
@@ -79343,7 +79466,7 @@ async function batchGetCellPositions(ctx, sheetId, cellIds) {
79343
79466
 
79344
79467
  // ../../kernel/src/api/worksheet/operations/dependency-operations.ts
79345
79468
  init_esm_shims();
79346
- function colToLetter3(col) {
79469
+ function colToLetter4(col) {
79347
79470
  let result = "";
79348
79471
  let c = col;
79349
79472
  while (c >= 0) {
@@ -79354,11 +79477,11 @@ function colToLetter3(col) {
79354
79477
  }
79355
79478
  async function getDependents(ctx, sheetId, row, col) {
79356
79479
  const results = await ctx.computeBridge.getDependents(sheetId, row, col);
79357
- return results.map((r) => `${colToLetter3(r.col)}${r.row + 1}`);
79480
+ return results.map((r) => `${colToLetter4(r.col)}${r.row + 1}`);
79358
79481
  }
79359
79482
  async function getPrecedents(ctx, sheetId, row, col) {
79360
79483
  const results = await ctx.computeBridge.getPrecedents(sheetId, row, col);
79361
- return results.map((r) => `${colToLetter3(r.col)}${r.row + 1}`);
79484
+ return results.map((r) => `${colToLetter4(r.col)}${r.row + 1}`);
79362
79485
  }
79363
79486
 
79364
79487
  // ../../kernel/src/api/worksheet/operations/fill-operations.ts
@@ -79411,7 +79534,8 @@ async function autoFill(ctx, sheetId, sourceRange, targetRange, mode) {
79411
79534
  return {
79412
79535
  patternType: fillData?.patternType ?? "copy",
79413
79536
  filledCellCount: fillData?.filledCellCount ?? 0,
79414
- warnings: fillData?.warnings ?? []
79537
+ warnings: fillData?.warnings ?? [],
79538
+ changes: fillData?.changes ?? []
79415
79539
  };
79416
79540
  }
79417
79541
  function splitRangeForSeries(range2, direction) {
@@ -79735,14 +79859,14 @@ async function regexSearch(ctx, sheetId, patterns, options) {
79735
79859
  for (const { regex, source } of compiledPatterns) {
79736
79860
  regex.lastIndex = 0;
79737
79861
  if (regex.test(valueStr)) {
79738
- const address = `${colToLetter2(cell.col)}${cell.row + 1}`;
79862
+ const address = `${colToLetter3(cell.col)}${cell.row + 1}`;
79739
79863
  results.push({ address, value: valueStr, sheetName, matchedPattern: source });
79740
79864
  break;
79741
79865
  }
79742
79866
  if (options?.includeFormulas && cell.formula) {
79743
79867
  regex.lastIndex = 0;
79744
79868
  if (regex.test(cell.formula)) {
79745
- const address = `${colToLetter2(cell.col)}${cell.row + 1}`;
79869
+ const address = `${colToLetter3(cell.col)}${cell.row + 1}`;
79746
79870
  results.push({ address, value: valueStr, sheetName, matchedPattern: source });
79747
79871
  break;
79748
79872
  }
@@ -79898,7 +80022,7 @@ async function clearRange2(ctx, sheetId, range2) {
79898
80022
  }
79899
80023
  }
79900
80024
  }
79901
- return { success: true, data: void 0, affectedCells };
80025
+ return { success: true, data: { cellCount }, affectedCells };
79902
80026
  } catch (e) {
79903
80027
  return {
79904
80028
  success: false,
@@ -79930,6 +80054,8 @@ async function clearWithMode(ctx, sheetId, range2, applyTo = "all") {
79930
80054
  promises.push(clearHyperlinksInRange(ctx, sheetId, n));
79931
80055
  }
79932
80056
  await Promise.all(promises);
80057
+ const cellCount = (n.endRow - n.startRow + 1) * (n.endCol - n.startCol + 1);
80058
+ return { cellCount };
79933
80059
  }
79934
80060
  async function clearHyperlinksInRange(ctx, sheetId, range2) {
79935
80061
  const rangeResult = await ctx.computeBridge.queryRange(
@@ -80048,7 +80174,7 @@ async function findInRange(ctx, sheetId, range2, text, options) {
80048
80174
  const valueStr = cell.formatted ?? viewportCellValueToString(cell.value);
80049
80175
  if (pattern.test(valueStr)) {
80050
80176
  return {
80051
- address: `${colToLetter2(cell.col)}${cell.row + 1}`,
80177
+ address: `${colToLetter3(cell.col)}${cell.row + 1}`,
80052
80178
  value: valueStr
80053
80179
  };
80054
80180
  }
@@ -80935,6 +81061,84 @@ var WorksheetBindingsImpl = class {
80935
81061
  }
80936
81062
  };
80937
81063
 
81064
+ // ../../kernel/src/api/worksheet/index.ts
81065
+ init_change_accumulator();
81066
+
81067
+ // ../../kernel/src/api/worksheet/changes.ts
81068
+ init_esm_shims();
81069
+ function parseRangeScope(scope) {
81070
+ const match = scope.match(/^([A-Z]+)(\d+):([A-Z]+)(\d+)$/i);
81071
+ if (!match) return null;
81072
+ const startCol = letterToCol2(match[1].toUpperCase());
81073
+ const startRow = parseInt(match[2], 10) - 1;
81074
+ const endCol = letterToCol2(match[3].toUpperCase());
81075
+ const endRow = parseInt(match[4], 10) - 1;
81076
+ return { startRow, startCol, endRow, endCol };
81077
+ }
81078
+ function letterToCol2(letters) {
81079
+ let col = 0;
81080
+ for (let i = 0; i < letters.length; i++) {
81081
+ col = col * 26 + (letters.charCodeAt(i) - 64);
81082
+ }
81083
+ return col - 1;
81084
+ }
81085
+ var ChangeTrackerImpl = class {
81086
+ constructor(sheetId, options, unregister) {
81087
+ this._active = true;
81088
+ this.buffer = [];
81089
+ this.sheetId = sheetId;
81090
+ this.unregister = unregister;
81091
+ this.scopeBounds = options?.scope ? parseRangeScope(options.scope) : null;
81092
+ this.excludeOrigins = options?.excludeOrigins && options.excludeOrigins.length > 0 ? new Set(options.excludeOrigins) : null;
81093
+ }
81094
+ // --- TrackerHandle (called by ChangeAccumulator) ---
81095
+ _ingest(records) {
81096
+ if (!this._active) return;
81097
+ for (const record of records) {
81098
+ if (this.excludeOrigins?.has(record.origin)) continue;
81099
+ if (this.scopeBounds) {
81100
+ const { startRow, startCol, endRow, endCol } = this.scopeBounds;
81101
+ if (record.row < startRow || record.row > endRow || record.col < startCol || record.col > endCol) {
81102
+ continue;
81103
+ }
81104
+ }
81105
+ this.buffer.push(record);
81106
+ }
81107
+ }
81108
+ // --- ChangeTracker public API ---
81109
+ collect() {
81110
+ const result = this.buffer;
81111
+ this.buffer = [];
81112
+ return result;
81113
+ }
81114
+ close() {
81115
+ if (!this._active) return;
81116
+ this._active = false;
81117
+ this.buffer = [];
81118
+ this.unregister();
81119
+ }
81120
+ get active() {
81121
+ return this._active;
81122
+ }
81123
+ };
81124
+ var WorksheetChangesImpl = class {
81125
+ constructor(ctx, sheetId) {
81126
+ this.ctx = ctx;
81127
+ this.sheetId = sheetId;
81128
+ }
81129
+ track(options) {
81130
+ const accumulator = this.ctx.computeBridge.getMutationHandler()?.changeAccumulator;
81131
+ if (!accumulator) {
81132
+ throw new Error("Change tracking unavailable: MutationResultHandler not initialized");
81133
+ }
81134
+ const tracker = new ChangeTrackerImpl(this.sheetId, options, () => {
81135
+ accumulator.unregister(tracker);
81136
+ });
81137
+ accumulator.register(tracker);
81138
+ return tracker;
81139
+ }
81140
+ };
81141
+
80938
81142
  // ../../kernel/src/api/worksheet/charts.ts
80939
81143
  init_esm_shims();
80940
81144
  function buildStatisticalExtra(config) {
@@ -81364,7 +81568,7 @@ function cellRefToA1(cellRef) {
81364
81568
  const col = parseInt(parts[0], 10);
81365
81569
  const row = parseInt(parts[1], 10);
81366
81570
  if (isNaN(col) || isNaN(row)) return cellRef;
81367
- return toA1(row, col);
81571
+ return toA12(row, col);
81368
81572
  }
81369
81573
  function toApiComment(c) {
81370
81574
  const text = c.content ?? c.runs.map((r) => r.text).join("");
@@ -81465,7 +81669,7 @@ var WorksheetCommentsImpl = class {
81465
81669
  return {
81466
81670
  content,
81467
81671
  author: first.author,
81468
- cellAddress: toA1(row, col)
81672
+ cellAddress: toA12(row, col)
81469
81673
  };
81470
81674
  }
81471
81675
  async removeNote(a, b) {
@@ -81808,7 +82012,7 @@ var WorksheetFiltersImpl = class {
81808
82012
  }
81809
82013
  }
81810
82014
  return {
81811
- range: `${toA1(filter.startRow ?? 0, filter.startCol ?? 0)}:${toA1(filter.endRow ?? 0, filter.endCol ?? 0)}`,
82015
+ range: `${toA12(filter.startRow ?? 0, filter.startCol ?? 0)}:${toA12(filter.endRow ?? 0, filter.endCol ?? 0)}`,
81812
82016
  columns
81813
82017
  };
81814
82018
  }
@@ -82183,7 +82387,8 @@ var WorksheetFormatsImpl = class {
82183
82387
  col = b;
82184
82388
  format = c;
82185
82389
  }
82186
- await this.ctx.computeBridge.setFormatForRanges(this.sheetId, [[row, col, row, col]], format);
82390
+ const result = await this.ctx.computeBridge.setFormatForRanges(this.sheetId, [[row, col, row, col]], format);
82391
+ return { cellCount: result.propertyChanges?.length ?? 0 };
82187
82392
  }
82188
82393
  async setRange(a, b) {
82189
82394
  let range2;
@@ -82195,11 +82400,12 @@ var WorksheetFormatsImpl = class {
82195
82400
  range2 = a;
82196
82401
  }
82197
82402
  const n = normalizeRange(range2);
82198
- await this.ctx.computeBridge.setFormatForRanges(
82403
+ const result = await this.ctx.computeBridge.setFormatForRanges(
82199
82404
  this.sheetId,
82200
82405
  [[n.startRow, n.startCol, n.endRow, n.endCol]],
82201
82406
  b
82202
82407
  );
82408
+ return { cellCount: result.propertyChanges?.length ?? 0 };
82203
82409
  }
82204
82410
  async setRanges(ranges, format) {
82205
82411
  const boundedRanges = [];
@@ -82230,9 +82436,7 @@ var WorksheetFormatsImpl = class {
82230
82436
  }
82231
82437
  async get(a, b) {
82232
82438
  const { row, col } = resolveCell(a, b);
82233
- const result = await this.ctx.computeBridge.queryRange(this.sheetId, row, col, row, col);
82234
- if (!result?.cells || result.cells.length === 0) return null;
82235
- return result.cells[0]?.format ?? null;
82439
+ return this.ctx.computeBridge.getResolvedFormat(this.sheetId, row, col);
82236
82440
  }
82237
82441
  async adjustIndent(a, b, c) {
82238
82442
  let row, col, amount;
@@ -82256,7 +82460,8 @@ var WorksheetFormatsImpl = class {
82256
82460
  async clearFill(a, b) {
82257
82461
  const { row, col } = resolveCell(a, b);
82258
82462
  const rangeTuple = [row, col, row, col];
82259
- const current = await this.get(row, col);
82463
+ const result = await this.ctx.computeBridge.queryRange(this.sheetId, row, col, row, col);
82464
+ const current = result?.cells?.[0]?.format ?? null;
82260
82465
  await this.ctx.computeBridge.clearFormatForRanges(this.sheetId, [rangeTuple]);
82261
82466
  if (current) {
82262
82467
  const { backgroundColor, patternType, patternForegroundColor, gradientFill, ...rest } = current;
@@ -83016,8 +83221,8 @@ init_esm_shims();
83016
83221
  init_errors();
83017
83222
  function formatDataSource(sourceSheetName, sourceRange) {
83018
83223
  if (!sourceRange) return "";
83019
- const start = toA1(sourceRange.startRow, sourceRange.startCol);
83020
- const end = toA1(sourceRange.endRow, sourceRange.endCol);
83224
+ const start = toA12(sourceRange.startRow, sourceRange.startCol);
83225
+ const end = toA12(sourceRange.endRow, sourceRange.endCol);
83021
83226
  const sheetRef = sourceSheetName ?? "Unknown";
83022
83227
  const needsQuotes = /[^A-Za-z0-9_]/.test(sheetRef);
83023
83228
  const quotedSheet = needsQuotes ? `'${sheetRef}'` : sheetRef;
@@ -83109,7 +83314,7 @@ var WorksheetPivotsImpl = class _WorksheetPivotsImpl {
83109
83314
  }
83110
83315
  return pivots.map((p) => {
83111
83316
  const apiConfig = dataConfigToApiConfig(p, p.sourceSheetName);
83112
- const location = p.outputLocation ? toA1(p.outputLocation.row, p.outputLocation.col) : void 0;
83317
+ const location = p.outputLocation ? toA12(p.outputLocation.row, p.outputLocation.col) : void 0;
83113
83318
  return {
83114
83319
  name: p.name ?? p.id,
83115
83320
  dataSource: apiConfig.dataSource,
@@ -83642,7 +83847,7 @@ function parseCellRef2(ref) {
83642
83847
  }
83643
83848
  return { row: rowNum - 1, col: col - 1 };
83644
83849
  }
83645
- function colToLetter4(col) {
83850
+ function colToLetter5(col) {
83646
83851
  let result = "";
83647
83852
  let c = col;
83648
83853
  while (c >= 0) {
@@ -83652,8 +83857,8 @@ function colToLetter4(col) {
83652
83857
  return result;
83653
83858
  }
83654
83859
  function printRangeToA1(range2) {
83655
- const startRef = `${colToLetter4(range2.startCol)}${range2.startRow + 1}`;
83656
- const endRef = `${colToLetter4(range2.endCol)}${range2.endRow + 1}`;
83860
+ const startRef = `${colToLetter5(range2.startCol)}${range2.startRow + 1}`;
83861
+ const endRef = `${colToLetter5(range2.endCol)}${range2.endRow + 1}`;
83657
83862
  return `${startRef}:${endRef}`;
83658
83863
  }
83659
83864
  async function getPageBreaks(ctx, sheetId) {
@@ -84053,7 +84258,11 @@ var WorksheetSlicersImpl = class {
84053
84258
  this.sheetId = sheetId;
84054
84259
  }
84055
84260
  async add(config) {
84056
- const storedConfig = config;
84261
+ const caption = config.caption ?? config.name ?? "";
84262
+ const storedConfig = {
84263
+ ...config,
84264
+ caption
84265
+ };
84057
84266
  await this.ctx.computeBridge.createSlicer(this.sheetId, storedConfig);
84058
84267
  return storedConfig.id ?? "";
84059
84268
  }
@@ -84767,7 +84976,7 @@ var WorksheetStructureImpl = class {
84767
84976
  async getMergedRegions() {
84768
84977
  const regions = await getAll3(this.ctx, this.sheetId);
84769
84978
  return regions.map((r) => ({
84770
- range: `${toA1(r.startRow, r.startCol)}:${toA1(r.endRow, r.endCol)}`,
84979
+ range: `${toA12(r.startRow, r.startCol)}:${toA12(r.endRow, r.endCol)}`,
84771
84980
  startRow: r.startRow,
84772
84981
  startCol: r.startCol,
84773
84982
  endRow: r.endRow,
@@ -84830,8 +85039,8 @@ function parseA1Range(range2) {
84830
85039
  };
84831
85040
  }
84832
85041
  function bridgeTableToTableInfo(table) {
84833
- const startLetter = colToLetter2(table.range.startCol);
84834
- const endLetter = colToLetter2(table.range.endCol);
85042
+ const startLetter = colToLetter3(table.range.startCol);
85043
+ const endLetter = colToLetter3(table.range.endCol);
84835
85044
  const startRowA1 = table.range.startRow + 1;
84836
85045
  const endRowA1 = table.range.endRow + 1;
84837
85046
  const range2 = `${startLetter}${startRowA1}:${endLetter}${endRowA1}`;
@@ -84876,16 +85085,16 @@ function getDataBodyRangeFromInfo(table) {
84876
85085
  const dataStartRow = table.hasHeaders ? parsed.startRow + 1 : parsed.startRow;
84877
85086
  const dataEndRow = table.showTotals ? parsed.endRow - 1 : parsed.endRow;
84878
85087
  if (dataStartRow > dataEndRow) return null;
84879
- const startLetter = colToLetter2(parsed.startCol);
84880
- const endLetter = colToLetter2(parsed.endCol);
85088
+ const startLetter = colToLetter3(parsed.startCol);
85089
+ const endLetter = colToLetter3(parsed.endCol);
84881
85090
  return `${startLetter}${dataStartRow + 1}:${endLetter}${dataEndRow + 1}`;
84882
85091
  }
84883
85092
  function getHeaderRowRangeFromInfo(table) {
84884
85093
  if (!table.hasHeaders) return null;
84885
85094
  const parsed = parseA1Range(table.range);
84886
85095
  if (!parsed) return null;
84887
- const startLetter = colToLetter2(parsed.startCol);
84888
- const endLetter = colToLetter2(parsed.endCol);
85096
+ const startLetter = colToLetter3(parsed.startCol);
85097
+ const endLetter = colToLetter3(parsed.endCol);
84889
85098
  const headerRow = parsed.startRow + 1;
84890
85099
  return `${startLetter}${headerRow}:${endLetter}${headerRow}`;
84891
85100
  }
@@ -84893,8 +85102,8 @@ function getTotalRowRangeFromInfo(table) {
84893
85102
  if (!table.showTotals) return null;
84894
85103
  const parsed = parseA1Range(table.range);
84895
85104
  if (!parsed) return null;
84896
- const startLetter = colToLetter2(parsed.startCol);
84897
- const endLetter = colToLetter2(parsed.endCol);
85105
+ const startLetter = colToLetter3(parsed.startCol);
85106
+ const endLetter = colToLetter3(parsed.endCol);
84898
85107
  const totalRow = parsed.endRow + 1;
84899
85108
  return `${startLetter}${totalRow}:${endLetter}${totalRow}`;
84900
85109
  }
@@ -84937,9 +85146,9 @@ var WorksheetTablesImpl = class {
84937
85146
  if (!match) {
84938
85147
  throw new KernelError("COMPUTE_ERROR", `Invalid range: ${range2}`);
84939
85148
  }
84940
- const startCol = letterToCol2(match[1]);
85149
+ const startCol = letterToCol3(match[1]);
84941
85150
  const startRow = parseInt(match[2], 10) - 1;
84942
- const endCol = letterToCol2(match[3]);
85151
+ const endCol = letterToCol3(match[3]);
84943
85152
  const endRow = parseInt(match[4], 10) - 1;
84944
85153
  await this.ctx.computeBridge.createTable(
84945
85154
  this.sheetId,
@@ -85019,9 +85228,9 @@ var WorksheetTablesImpl = class {
85019
85228
  if (!parsed) {
85020
85229
  throw new KernelError("COMPUTE_ERROR", `Invalid table range: ${table.range}`);
85021
85230
  }
85022
- const startCol = letterToCol2(parsed[1]);
85231
+ const startCol = letterToCol3(parsed[1]);
85023
85232
  const startRow = parseInt(parsed[2], 10) - 1;
85024
- const endCol = letterToCol2(parsed[3]);
85233
+ const endCol = letterToCol3(parsed[3]);
85025
85234
  const endRow = parseInt(parsed[4], 10) - 1;
85026
85235
  const filter = await getFilterForRange(this.ctx, this.sheetId, {
85027
85236
  startRow,
@@ -85042,9 +85251,9 @@ var WorksheetTablesImpl = class {
85042
85251
  if (!match) {
85043
85252
  throw new KernelError("COMPUTE_ERROR", `Invalid range: ${newRange}`);
85044
85253
  }
85045
- const startCol = letterToCol2(match[1]);
85254
+ const startCol = letterToCol3(match[1]);
85046
85255
  const startRow = parseInt(match[2], 10) - 1;
85047
- const endCol = letterToCol2(match[3]);
85256
+ const endCol = letterToCol3(match[3]);
85048
85257
  const endRow = parseInt(match[4], 10) - 1;
85049
85258
  await this.ctx.computeBridge.resizeTable(name, startRow, startCol, endRow, endCol);
85050
85259
  }
@@ -85175,8 +85384,8 @@ var WorksheetTablesImpl = class {
85175
85384
  if (!parsed) throw new KernelError("COMPUTE_ERROR", `Invalid table range: ${table.range}`);
85176
85385
  const dataStartRow = table.hasHeaders ? parsed.startRow + 1 : parsed.startRow;
85177
85386
  const absRow = dataStartRow + index;
85178
- const startLetter = colToLetter2(parsed.startCol);
85179
- const endLetter = colToLetter2(parsed.endCol);
85387
+ const startLetter = colToLetter3(parsed.startCol);
85388
+ const endLetter = colToLetter3(parsed.endCol);
85180
85389
  return `${startLetter}${absRow + 1}:${endLetter}${absRow + 1}`;
85181
85390
  }
85182
85391
  async getRowValues(tableName, index) {
@@ -85215,7 +85424,7 @@ var WorksheetTablesImpl = class {
85215
85424
  const dataStartRow = table.hasHeaders ? parsed.startRow + 1 : parsed.startRow;
85216
85425
  const dataEndRow = table.showTotals ? parsed.endRow - 1 : parsed.endRow;
85217
85426
  if (dataStartRow > dataEndRow) return null;
85218
- const letter = colToLetter2(col);
85427
+ const letter = colToLetter3(col);
85219
85428
  return `${letter}${dataStartRow + 1}:${letter}${dataEndRow + 1}`;
85220
85429
  }
85221
85430
  async getColumnHeaderRange(tableName, columnIndex) {
@@ -85225,7 +85434,7 @@ var WorksheetTablesImpl = class {
85225
85434
  if (!parsed) return null;
85226
85435
  const col = parsed.startCol + columnIndex;
85227
85436
  if (col > parsed.endCol) return null;
85228
- const letter = colToLetter2(col);
85437
+ const letter = colToLetter3(col);
85229
85438
  const headerRow = parsed.startRow + 1;
85230
85439
  return `${letter}${headerRow}`;
85231
85440
  }
@@ -85236,7 +85445,7 @@ var WorksheetTablesImpl = class {
85236
85445
  if (!parsed) return null;
85237
85446
  const col = parsed.startCol + columnIndex;
85238
85447
  if (col > parsed.endCol) return null;
85239
- const letter = colToLetter2(col);
85448
+ const letter = colToLetter3(col);
85240
85449
  return `${letter}${parsed.startRow + 1}:${letter}${parsed.endRow + 1}`;
85241
85450
  }
85242
85451
  async getColumnTotalRange(tableName, columnIndex) {
@@ -85246,7 +85455,7 @@ var WorksheetTablesImpl = class {
85246
85455
  if (!parsed) return null;
85247
85456
  const col = parsed.startCol + columnIndex;
85248
85457
  if (col > parsed.endCol) return null;
85249
- const letter = colToLetter2(col);
85458
+ const letter = colToLetter3(col);
85250
85459
  const totalRow = parsed.endRow + 1;
85251
85460
  return `${letter}${totalRow}`;
85252
85461
  }
@@ -85345,7 +85554,7 @@ var WorksheetTablesImpl = class {
85345
85554
  async sortClear(_tableName) {
85346
85555
  }
85347
85556
  };
85348
- function letterToCol2(letters) {
85557
+ function letterToCol3(letters) {
85349
85558
  let col = 0;
85350
85559
  for (let i = 0; i < letters.length; i++) {
85351
85560
  col = col * 26 + (letters.toUpperCase().charCodeAt(i) - 64);
@@ -85356,9 +85565,9 @@ function parseA1Range2(range2) {
85356
85565
  const match = range2.match(/^([A-Z]+)(\d+):([A-Z]+)(\d+)$/i);
85357
85566
  if (!match) return null;
85358
85567
  return {
85359
- startCol: letterToCol2(match[1]),
85568
+ startCol: letterToCol3(match[1]),
85360
85569
  startRow: parseInt(match[2], 10) - 1,
85361
- endCol: letterToCol2(match[3]),
85570
+ endCol: letterToCol3(match[3]),
85362
85571
  endRow: parseInt(match[4], 10) - 1
85363
85572
  };
85364
85573
  }
@@ -85547,8 +85756,8 @@ function rangeSchemaToValidationRule(schema) {
85547
85756
  const start = parseRefIdSimple(ref.startId);
85548
85757
  const end = parseRefIdSimple(ref.endId);
85549
85758
  if (start && end) {
85550
- const startA1 = toA1(start.row, start.col);
85551
- const endA1 = toA1(end.row, end.col);
85759
+ const startA1 = toA12(start.row, start.col);
85760
+ const endA1 = toA12(end.row, end.col);
85552
85761
  range2 = startA1 === endA1 ? startA1 : `${startA1}:${endA1}`;
85553
85762
  }
85554
85763
  }
@@ -85581,8 +85790,8 @@ function rangeSchemaToValidationRule(schema) {
85581
85790
  const srcStart = parseRefIdSimple(src.startId);
85582
85791
  const srcEnd = parseRefIdSimple(src.endId);
85583
85792
  if (srcStart && srcEnd) {
85584
- const srcStartA1 = toA1(srcStart.row, srcStart.col);
85585
- const srcEndA1 = toA1(srcEnd.row, srcEnd.col);
85793
+ const srcStartA1 = toA12(srcStart.row, srcStart.col);
85794
+ const srcEndA1 = toA12(srcEnd.row, srcEnd.col);
85586
85795
  rule.listSource = srcStartA1 === srcEndA1 ? `=${srcStartA1}` : `=${srcStartA1}:${srcEndA1}`;
85587
85796
  }
85588
85797
  }
@@ -87799,11 +88008,12 @@ var WorksheetImpl = class {
87799
88008
  if (!result.success) {
87800
88009
  throw result.error;
87801
88010
  }
88011
+ return result.data;
87802
88012
  }
87803
88013
  async clear(range2, applyTo) {
87804
88014
  const parsed = parseCellRange(range2);
87805
88015
  if (!parsed) throw new KernelError("COMPUTE_ERROR", `Invalid range: "${range2}"`);
87806
- await clearWithMode(
88016
+ return clearWithMode(
87807
88017
  this.ctx,
87808
88018
  this.sheetId,
87809
88019
  { sheetId: this.sheetId, ...parsed },
@@ -87851,7 +88061,7 @@ var WorksheetImpl = class {
87851
88061
  format: format ?? void 0,
87852
88062
  hyperlink: hyperlink ?? void 0,
87853
88063
  isMerged: mergeInfo !== void 0,
87854
- mergedRegion: mergeInfo ? `${toA1(mergeInfo.startRow, mergeInfo.startCol)}:${toA1(mergeInfo.endRow, mergeInfo.endCol)}` : void 0
88064
+ mergedRegion: mergeInfo ? `${toA12(mergeInfo.startRow, mergeInfo.startCol)}:${toA12(mergeInfo.endRow, mergeInfo.endCol)}` : void 0
87855
88065
  };
87856
88066
  }
87857
88067
  async getRawRangeData(range2, _includeFormula) {
@@ -87878,7 +88088,8 @@ var WorksheetImpl = class {
87878
88088
  } else {
87879
88089
  rowData.push({
87880
88090
  value: viewportCellValueToCellValue(vc.value) ?? null,
87881
- formula: vc.formula
88091
+ formula: vc.formula,
88092
+ format: vc.format ?? void 0
87882
88093
  });
87883
88094
  }
87884
88095
  }
@@ -87903,10 +88114,10 @@ var WorksheetImpl = class {
87903
88114
  const { row, col } = resolveCell(address);
87904
88115
  const data = await getCell(this.ctx, this.sheetId, row, col);
87905
88116
  if (!data) return "";
87906
- const rawValue = viewportCellValueToString(data.value);
87907
- let result = rawValue;
88117
+ const displayValue = await getDisplayValue2(this.ctx, this.sheetId, row, col);
88118
+ let result = displayValue;
87908
88119
  if (data.formula) {
87909
- result = rawValue !== "" ? `${rawValue}(${data.formula})` : `(${data.formula})`;
88120
+ result = displayValue !== "" ? `${displayValue}(${data.formula})` : `(${data.formula})`;
87910
88121
  }
87911
88122
  const styleHintsStr = await getStyleHints(this.ctx, this.sheetId, row, col);
87912
88123
  if (styleHintsStr) {
@@ -87965,17 +88176,15 @@ var WorksheetImpl = class {
87965
88176
  }
87966
88177
  for (let row = parsed.startRow; row <= parsed.endRow; row++) {
87967
88178
  const rowValues = [];
87968
- let hasContent = false;
87969
88179
  for (let col = parsed.startCol; col <= parsed.endCol; col++) {
87970
- const cellAddr = toA1(row, col);
88180
+ const cellAddr = toA12(row, col);
87971
88181
  const vc = cellMap.get(`${row},${col}`);
87972
88182
  if (!vc) {
87973
88183
  rowValues.push(`${cellAddr}:`);
87974
88184
  continue;
87975
88185
  }
87976
- const rawValue = viewportCellValueToString(vc.value);
87977
- let cellStr = rawValue;
87978
- hasContent = true;
88186
+ const displayValue = vc.formatted ?? viewportCellValueToString(vc.value);
88187
+ let cellStr = displayValue;
87979
88188
  if (vc.formula) {
87980
88189
  const abbreviation = formulaAnalysis.formulaToId.get(`${row},${col}`);
87981
88190
  if (abbreviation) {
@@ -87986,9 +88195,7 @@ var WorksheetImpl = class {
87986
88195
  }
87987
88196
  rowValues.push(`${cellAddr}:${cellStr}`);
87988
88197
  }
87989
- if (hasContent) {
87990
- outputParts.push(rowValues.join(" | "));
87991
- }
88198
+ outputParts.push(rowValues.join(" | "));
87992
88199
  }
87993
88200
  const formulaDocs = generateFormulaDocumentation(formulaAnalysis);
87994
88201
  if (formulaDocs.length > 0) {
@@ -88077,8 +88284,8 @@ var WorksheetImpl = class {
88077
88284
  lines.push(`Sheet: ${meta.name}`);
88078
88285
  const bounds = await this.ctx.computeBridge.getDataBounds(this.sheetId);
88079
88286
  if (bounds) {
88080
- const startAddr = toA1(bounds.minRow, bounds.minCol);
88081
- const endAddr = toA1(bounds.maxRow, bounds.maxCol);
88287
+ const startAddr = toA12(bounds.minRow, bounds.minCol);
88288
+ const endAddr = toA12(bounds.maxRow, bounds.maxCol);
88082
88289
  lines.push(`Used Range: ${startAddr}:${endAddr}`);
88083
88290
  lines.push(
88084
88291
  `Dimensions: ${bounds.maxRow - bounds.minRow + 1} rows x ${bounds.maxCol - bounds.minCol + 1} columns`
@@ -88098,20 +88305,31 @@ var WorksheetImpl = class {
88098
88305
  const tables = await getTablesInSheet(this.ctx, this.sheetId);
88099
88306
  if (tables.length > 0) {
88100
88307
  const tableDescs = tables.map((t) => {
88101
- const r = `${toA1(t.range.startRow, t.range.startCol)}:${toA1(t.range.endRow, t.range.endCol)}`;
88308
+ const r = `${toA12(t.range.startRow, t.range.startCol)}:${toA12(t.range.endRow, t.range.endCol)}`;
88102
88309
  return `${t.name} at ${r}`;
88103
88310
  });
88104
88311
  lines.push(`Tables: ${tables.length} (${tableDescs.join(", ")})`);
88105
88312
  }
88106
- const allNamedRanges = await getAll(this.ctx);
88107
- const sheetNamedRanges = allNamedRanges.filter((nr) => nr.scope === this.sheetId || !nr.scope);
88108
- if (sheetNamedRanges.length > 0) {
88313
+ const allVisible = await getVisible(this.ctx);
88314
+ const scoped = allVisible.filter((nr) => nr.scope === this.sheetId || !nr.scope);
88315
+ const valid = scoped.filter((nr) => !nr.refersTo.template.includes("#REF!"));
88316
+ const broken = scoped.length - valid.length;
88317
+ if (valid.length > 0 || broken > 0) {
88318
+ const toShow = valid.slice(0, MAX_SUMMARY_NAMED_RANGES);
88109
88319
  const nrDescs = [];
88110
- for (const nr of sheetNamedRanges) {
88320
+ for (const nr of toShow) {
88111
88321
  const a1 = await getRefersToA1(this.ctx, nr);
88112
88322
  nrDescs.push(`${nr.name}=${a1}`);
88113
88323
  }
88114
- lines.push(`Named Ranges: ${sheetNamedRanges.length} (${nrDescs.join(", ")})`);
88324
+ let label = `Named Ranges: ${valid.length}`;
88325
+ if (broken > 0) label += ` valid, ${broken} broken (#REF!) omitted`;
88326
+ if (nrDescs.length > 0) {
88327
+ const showing = valid.length > MAX_SUMMARY_NAMED_RANGES ? `showing ${MAX_SUMMARY_NAMED_RANGES}: ` : "";
88328
+ const more = valid.length > MAX_SUMMARY_NAMED_RANGES ? ` \u2014 ${valid.length - MAX_SUMMARY_NAMED_RANGES} more not shown` : "";
88329
+ lines.push(`${label} (${showing}${nrDescs.join(", ")})${more}`);
88330
+ } else {
88331
+ lines.push(label);
88332
+ }
88115
88333
  }
88116
88334
  const maxRows = options?.maxRows;
88117
88335
  const maxCols = options?.maxCols;
@@ -88180,7 +88398,7 @@ var WorksheetImpl = class {
88180
88398
  const rowData = [];
88181
88399
  for (const vc of cells) {
88182
88400
  const rawValue = viewportCellValueToString(vc.value);
88183
- const addr = toA1(vc.row, vc.col);
88401
+ const addr = toA12(vc.row, vc.col);
88184
88402
  if (vc.formula) {
88185
88403
  rowData.push(`${addr}:${rawValue}(=${vc.formula})`);
88186
88404
  } else {
@@ -88204,7 +88422,7 @@ var WorksheetImpl = class {
88204
88422
  async getUsedRange() {
88205
88423
  const range2 = await getUsedRange2(this.ctx, this.sheetId);
88206
88424
  if (!range2) return null;
88207
- return `${toA1(range2.startRow, range2.startCol)}:${toA1(range2.endRow, range2.endCol)}`;
88425
+ return `${toA12(range2.startRow, range2.startCol)}:${toA12(range2.endRow, range2.endCol)}`;
88208
88426
  }
88209
88427
  async getCurrentRegion(row, col) {
88210
88428
  return getCurrentRegion(this.ctx, this.sheetId, row, col);
@@ -88214,15 +88432,15 @@ var WorksheetImpl = class {
88214
88432
  }
88215
88433
  async findCells(predicate) {
88216
88434
  const addresses = await findCells(this.ctx, this.sheetId, predicate);
88217
- return addresses.map((a) => toA1(a.row, a.col));
88435
+ return addresses.map((a) => toA12(a.row, a.col));
88218
88436
  }
88219
88437
  async findByValue(value) {
88220
88438
  const addresses = await findByValue(this.ctx, this.sheetId, value);
88221
- return addresses.map((a) => toA1(a.row, a.col));
88439
+ return addresses.map((a) => toA12(a.row, a.col));
88222
88440
  }
88223
88441
  async findByFormula(pattern) {
88224
88442
  const addresses = await findByFormula(this.ctx, this.sheetId, pattern);
88225
- return addresses.map((a) => toA1(a.row, a.col));
88443
+ return addresses.map((a) => toA12(a.row, a.col));
88226
88444
  }
88227
88445
  async regexSearch(patterns, options) {
88228
88446
  const results = await regexSearch(this.ctx, this.sheetId, patterns, {
@@ -88361,7 +88579,7 @@ var WorksheetImpl = class {
88361
88579
  await this.setRange(start.row, start.col, allRows);
88362
88580
  const endRow = start.row + allRows.length - 1;
88363
88581
  const endCol = start.col + headers.length - 1;
88364
- const rangeA1 = `${toA1(start.row, start.col)}:${toA1(endRow, endCol)}`;
88582
+ const rangeA1 = `${toA12(start.row, start.col)}:${toA12(endRow, endCol)}`;
88365
88583
  await this.tables.add(rangeA1, { name, hasHeaders: true });
88366
88584
  }
88367
88585
  // ===========================================================================
@@ -88754,6 +88972,9 @@ var WorksheetImpl = class {
88754
88972
  }
88755
88973
  return this._cellMetadata;
88756
88974
  }
88975
+ get changes() {
88976
+ return this._changes ??= new WorksheetChangesImpl(this.ctx, this.sheetId);
88977
+ }
88757
88978
  get formats() {
88758
88979
  return this._formats ??= new WorksheetFormatsImpl(this.ctx, this.sheetId);
88759
88980
  }
@@ -91087,6 +91308,31 @@ var WorkbookImpl = class {
91087
91308
  calculationSettings: calcSettings
91088
91309
  });
91089
91310
  }
91311
+ async getIterativeCalculation() {
91312
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91313
+ return settings.calculationSettings?.enableIterativeCalculation ?? false;
91314
+ }
91315
+ async setIterativeCalculation(enabled) {
91316
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91317
+ const calcSettings = { ...settings.calculationSettings ?? {}, enableIterativeCalculation: enabled };
91318
+ await this.ctx.computeBridge.patchWorkbookSettings({
91319
+ calculationSettings: calcSettings
91320
+ });
91321
+ }
91322
+ async setMaxIterations(n) {
91323
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91324
+ const calcSettings = { ...settings.calculationSettings ?? {}, maxIterations: n };
91325
+ await this.ctx.computeBridge.patchWorkbookSettings({
91326
+ calculationSettings: calcSettings
91327
+ });
91328
+ }
91329
+ async setConvergenceThreshold(threshold) {
91330
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91331
+ const calcSettings = { ...settings.calculationSettings ?? {}, maxChange: threshold };
91332
+ await this.ctx.computeBridge.patchWorkbookSettings({
91333
+ calculationSettings: calcSettings
91334
+ });
91335
+ }
91090
91336
  async getUsePrecisionAsDisplayed() {
91091
91337
  const settings = await this.ctx.computeBridge.getWorkbookSettings();
91092
91338
  return !(settings.calculationSettings?.fullPrecision ?? true);
@@ -91246,7 +91492,7 @@ var WorkbookImpl = class {
91246
91492
  // Utilities (sync)
91247
91493
  // ===========================================================================
91248
91494
  indexToAddress(row, col) {
91249
- return toA1(row, col);
91495
+ return toA12(row, col);
91250
91496
  }
91251
91497
  addressToIndex(address) {
91252
91498
  const parsed = parseCellAddress(address);
@@ -91498,6 +91744,7 @@ var api_spec_default = {
91498
91744
  },
91499
91745
  ws: {
91500
91746
  smartArt: "WorksheetSmartArt",
91747
+ changes: "WorksheetChanges",
91501
91748
  formats: "WorksheetFormats",
91502
91749
  layout: "WorksheetLayout",
91503
91750
  view: "WorksheetView",
@@ -91609,6 +91856,26 @@ var api_spec_default = {
91609
91856
  docstring: "Set the calculation mode.\nConvenience mutator \u2014 patches `calculationSettings.calcMode`.",
91610
91857
  usedTypes: []
91611
91858
  },
91859
+ getIterativeCalculation: {
91860
+ signature: "getIterativeCalculation(): Promise<boolean>;",
91861
+ docstring: "Get whether iterative calculation is enabled for circular references.\nConvenience accessor \u2014 equivalent to `(await getSettings()).calculationSettings.enableIterativeCalculation`.",
91862
+ usedTypes: []
91863
+ },
91864
+ setIterativeCalculation: {
91865
+ signature: "setIterativeCalculation(enabled: boolean): Promise<void>;",
91866
+ docstring: "Set whether iterative calculation is enabled for circular references.\nConvenience mutator \u2014 patches `calculationSettings.enableIterativeCalculation`.",
91867
+ usedTypes: []
91868
+ },
91869
+ setMaxIterations: {
91870
+ signature: "setMaxIterations(n: number): Promise<void>;",
91871
+ docstring: "Set the maximum number of iterations for iterative calculation.\nConvenience mutator \u2014 patches `calculationSettings.maxIterations`.",
91872
+ usedTypes: []
91873
+ },
91874
+ setConvergenceThreshold: {
91875
+ signature: "setConvergenceThreshold(threshold: number): Promise<void>;",
91876
+ docstring: "Set the convergence threshold (maximum change) for iterative calculation.\nConvenience mutator \u2014 patches `calculationSettings.maxChange`.",
91877
+ usedTypes: []
91878
+ },
91612
91879
  getUsePrecisionAsDisplayed: {
91613
91880
  signature: "getUsePrecisionAsDisplayed(): Promise<boolean>;",
91614
91881
  docstring: "Whether to use displayed precision instead of full (15-digit) precision.\nConvenience accessor \u2014 inverted from `calculationSettings.fullPrecision`.",
@@ -91820,18 +92087,21 @@ var api_spec_default = {
91820
92087
  usedTypes: []
91821
92088
  },
91822
92089
  clearData: {
91823
- signature: "clearData(range: string): Promise<void>;",
92090
+ signature: "clearData(range: string): Promise<ClearResult>;",
91824
92091
  docstring: 'Clear all cell data (values and formulas) in a range (A1 notation, e.g. "A1:C3").',
91825
- usedTypes: []
92092
+ usedTypes: [
92093
+ "ClearResult"
92094
+ ]
91826
92095
  },
91827
92096
  clear: {
91828
- signature: "clear(range: string, applyTo?: ClearApplyTo): Promise<void>;",
92097
+ signature: "clear(range: string, applyTo?: ClearApplyTo): Promise<ClearResult>;",
91829
92098
  docstring: `Unified clear with mode selection (OfficeJS Range.clear equivalent).
91830
92099
 
91831
92100
  @param range - A1 range string (e.g. "A1:C3")
91832
92101
  @param applyTo - What to clear: 'all' (default), 'contents', 'formats', 'hyperlinks'`,
91833
92102
  usedTypes: [
91834
- "ClearApplyTo"
92103
+ "ClearApplyTo",
92104
+ "ClearResult"
91835
92105
  ]
91836
92106
  },
91837
92107
  getValue: {
@@ -92710,21 +92980,36 @@ var api_spec_default = {
92710
92980
  }
92711
92981
  }
92712
92982
  },
92983
+ WorksheetChanges: {
92984
+ docstring: "Sub-API for opt-in change tracking on a worksheet.",
92985
+ functions: {
92986
+ track: {
92987
+ signature: "track(options?: ChangeTrackOptions): ChangeTracker;",
92988
+ docstring: "Create a change tracker that accumulates cell-level change records\nfrom this point forward.\n\n@param options - Optional scope and origin filters\n@returns A ChangeTracker handle \u2014 call collect() to drain, close() when done",
92989
+ usedTypes: [
92990
+ "ChangeTrackOptions",
92991
+ "ChangeTracker"
92992
+ ]
92993
+ }
92994
+ }
92995
+ },
92713
92996
  WorksheetFormats: {
92714
92997
  docstring: "Sub-API for cell formatting operations on a worksheet.",
92715
92998
  functions: {
92716
92999
  set: {
92717
- signature: "set(address: string, format: CellFormat): Promise<void>;",
93000
+ signature: "set(address: string, format: CellFormat): Promise<FormatChangeResult>;",
92718
93001
  docstring: 'Set format for a single cell.\n\n@param address - A1-style cell address (e.g. "A1", "B3")\n@param format - Format properties to apply',
92719
93002
  usedTypes: [
92720
- "CellFormat"
93003
+ "CellFormat",
93004
+ "FormatChangeResult"
92721
93005
  ]
92722
93006
  },
92723
93007
  setRange: {
92724
- signature: "setRange(range: string, format: CellFormat): Promise<void>;",
93008
+ signature: "setRange(range: string, format: CellFormat): Promise<FormatChangeResult>;",
92725
93009
  docstring: 'Set format for a contiguous range.\n\n@param range - A1-style range string (e.g. "A1:B2")\n@param format - Format properties to apply',
92726
93010
  usedTypes: [
92727
- "CellFormat"
93011
+ "CellFormat",
93012
+ "FormatChangeResult"
92728
93013
  ]
92729
93014
  },
92730
93015
  setRanges: {
@@ -92741,10 +93026,10 @@ var api_spec_default = {
92741
93026
  usedTypes: []
92742
93027
  },
92743
93028
  get: {
92744
- signature: "get(address: string): Promise<CellFormat | null>;",
92745
- docstring: "Get the format of a single cell.\n\n@param address - A1-style cell address\n@returns The cell format, or null if no format is set",
93029
+ signature: "get(address: string): Promise<ResolvedCellFormat>;",
93030
+ docstring: "Get the fully-resolved format of a single cell.\n\nReturns a dense CellFormat with all fields present (null for unset properties,\nnever undefined). Includes the full cascade (default \u2192 col \u2192 row \u2192 table \u2192 cell \u2192 CF)\nwith theme colors resolved to hex.\n\n@param address - A1-style cell address\n@returns The resolved cell format (always an object, never null)",
92746
93031
  usedTypes: [
92747
- "CellFormat"
93032
+ "ResolvedCellFormat"
92748
93033
  ]
92749
93034
  },
92750
93035
  adjustIndent: {
@@ -94871,6 +95156,11 @@ var api_spec_default = {
94871
95156
  definition: "'standard' | 'stacked' | 'percentStacked'",
94872
95157
  docstring: ""
94873
95158
  },
95159
+ AutoFillChange: {
95160
+ name: "AutoFillChange",
95161
+ definition: "{\n row: number;\n col: number;\n type: 'value' | 'formula' | 'format' | 'clear';\n}",
95162
+ docstring: "A single cell change produced by the fill engine."
95163
+ },
94874
95164
  AutoFillMode: {
94875
95165
  name: "AutoFillMode",
94876
95166
  definition: "| 'auto' // Detect pattern automatically (default)\n | 'copy' // Always copy (no series)\n | 'series' // Force series interpretation\n | 'days' // Force date unit: days\n | 'weekdays' // Force date unit: weekdays\n | 'months' // Force date unit: months\n | 'years' // Force date unit: years\n | 'formats' // Copy formats only\n | 'values' // Copy values only (no formats)\n | 'withoutFormats' // Copy values + formulas, skip formats\n | 'linearTrend' // Force linear regression trend\n | 'growthTrend'",
@@ -94878,7 +95168,7 @@ var api_spec_default = {
94878
95168
  },
94879
95169
  AutoFillResult: {
94880
95170
  name: "AutoFillResult",
94881
- definition: "{\n /** The pattern that was detected (or forced by mode) */\n patternType: FillPatternType;\n /** Number of cells that were filled */\n filledCellCount: number;\n /** Any warnings generated during fill */\n warnings: AutoFillWarning[];\n}",
95171
+ definition: "{\n /** The pattern that was detected (or forced by mode) */\n patternType: FillPatternType;\n /** Number of cells that were filled */\n filledCellCount: number;\n /** Any warnings generated during fill */\n warnings: AutoFillWarning[];\n /** Per-cell changes listing each cell written */\n changes: AutoFillChange[];\n}",
94882
95172
  docstring: "Result from autoFill() \u2014 summary of what the fill engine did."
94883
95173
  },
94884
95174
  AutoFillWarning: {
@@ -95225,6 +95515,37 @@ Example: { ignoreError: true } to suppress error indicators. */
95225
95515
  definition: "{\n /** If true, value is treated as a formula (prefixed with =) */\n asFormula?: boolean;\n}",
95226
95516
  docstring: "Options controlling how a cell value is interpreted when written."
95227
95517
  },
95518
+ ChangeOrigin: {
95519
+ name: "ChangeOrigin",
95520
+ definition: "'direct' | 'cascade' | 'remote'",
95521
+ docstring: "Origin of a change: direct write, formula recalculation, or remote collaborator."
95522
+ },
95523
+ ChangeRecord: {
95524
+ name: "ChangeRecord",
95525
+ definition: `{
95526
+ /** Cell address in A1 notation (e.g. "B1"). */
95527
+ address: string;
95528
+ /** 0-based row index. */
95529
+ row: number;
95530
+ /** 0-based column index. */
95531
+ col: number;
95532
+ /** What caused this change. */
95533
+ origin: ChangeOrigin;
95534
+ /** Type of change. */
95535
+ type: 'modified';
95536
+ }`,
95537
+ docstring: "WorksheetChanges \u2014 Sub-API for opt-in change tracking.\n\nCreates lightweight trackers that accumulate cell-level change records\nacross mutations. Trackers are opt-in to avoid bloating return values;\nthey return addresses + metadata only (no cell values) so callers can\nhydrate via getRange() when needed.\n\nInspired by:\n- Excel OfficeJS onChanged (lightweight payload + lazy hydration)\n- Firestore onSnapshot (query-scoped subscriptions)\n- Yjs transaction.origin (source/origin tagging for collab)"
95538
+ },
95539
+ ChangeTrackOptions: {
95540
+ name: "ChangeTrackOptions",
95541
+ definition: '{\n /** Only track changes within this range (A1 notation, e.g. "A1:Z100"). Omit for whole-sheet. */\n scope?: string;\n /** Exclude changes from these origin types. */\n excludeOrigins?: ChangeOrigin[];\n}',
95542
+ docstring: "Options for creating a change tracker."
95543
+ },
95544
+ ChangeTracker: {
95545
+ name: "ChangeTracker",
95546
+ definition: "{\n /** Drain all accumulated changes since creation or last collect() call.\nReturns addresses + metadata only (no cell values) \u2014 call ws.getRange()\nto hydrate if needed. */\n collect(): ChangeRecord[];;\n /** Stop tracking and release internal resources. */\n close(): void;;\n /** Whether this tracker is still active (not closed). */\n active: boolean;\n}",
95547
+ docstring: "A handle that accumulates change records across mutations."
95548
+ },
95228
95549
  Chart: {
95229
95550
  name: "Chart",
95230
95551
  definition: "{\n id: string;\n sheetId?: string;\n createdAt?: number;\n updatedAt?: number;\n}",
@@ -95359,6 +95680,11 @@ that are stored on the chart but not part of the core config schema. */
95359
95680
  definition: "'all' | 'contents' | 'formats' | 'hyperlinks'",
95360
95681
  docstring: "Determines which aspects of a range to clear.\nMatches OfficeJS Excel.ClearApplyTo enum."
95361
95682
  },
95683
+ ClearResult: {
95684
+ name: "ClearResult",
95685
+ definition: "{\n /** Number of cells in the cleared range. */\n cellCount: number;\n}",
95686
+ docstring: "Confirmation returned by clearData() and clear()."
95687
+ },
95362
95688
  CodeResult: {
95363
95689
  name: "CodeResult",
95364
95690
  definition: "{\n /** Whether execution completed successfully */\n success: boolean;\n /** Captured console output */\n output?: string;\n /** Error message (if success is false) */\n error?: string;\n /** Execution duration in milliseconds */\n duration?: number;\n}",
@@ -95572,6 +95898,11 @@ Used in condition filters where users specify rules like
95572
95898
  definition: "| 'shape'\n | 'connector'\n | 'picture'\n | 'textbox'\n | 'chart'\n | 'camera'\n | 'equation'\n | 'smartart'\n | 'drawing'\n | 'oleObject'\n | 'formControl'\n | 'slicer'\n | 'wordart'",
95573
95899
  docstring: "Type discriminator for floating objects. Superset of Rust FloatingObjectKind (12 variants) + legacy TS-only 'wordart'."
95574
95900
  },
95901
+ FormatChangeResult: {
95902
+ name: "FormatChangeResult",
95903
+ definition: "{\n /** Number of cells whose formatting was changed */\n cellCount: number;\n}",
95904
+ docstring: "Result of a format set/setRange operation."
95905
+ },
95575
95906
  FormatEntry: {
95576
95907
  name: "FormatEntry",
95577
95908
  definition: '{\n /** Cell value descriptor */\n value: { type: string; value?: unknown };\n /** Number format code (e.g., "#,##0.00") */\n formatCode: string;\n}',
@@ -95940,6 +96271,11 @@ Used in condition filters where users specify rules like
95940
96271
  definition: "{\n /** Number of duplicate rows removed */\n removedCount: number;\n /** Number of unique rows remaining */\n remainingCount: number;\n}",
95941
96272
  docstring: "Result of a remove-duplicates operation."
95942
96273
  },
96274
+ ResolvedCellFormat: {
96275
+ name: "ResolvedCellFormat",
96276
+ definition: "{\n [K in keyof CellFormat]-?: CellFormat[K] | null;\n}",
96277
+ docstring: "Dense cell format where every property is explicitly present (null when unset). Returned by formats.get()."
96278
+ },
95943
96279
  RichTextSegment: {
95944
96280
  name: "RichTextSegment",
95945
96281
  definition: "{\n text: string;\n bold?: boolean;\n italic?: boolean;\n underline?: boolean;\n strikethrough?: boolean;\n color?: string;\n fontName?: string;\n fontSize?: number;\n}",
@@ -96020,7 +96356,7 @@ Used in condition filters where users specify rules like
96020
96356
  },
96021
96357
  SetCellsResult: {
96022
96358
  name: "SetCellsResult",
96023
- definition: "{\n /** Number of cells successfully written */\n cellsWritten: number;\n /** Per-cell errors, if any (omitted when all succeed) */\n errors?: Array<{ addr: string; error: string }>;\n /** Non-fatal warnings (e.g., deduplication, coercion) */\n warnings?: OperationWarning[];\n}",
96359
+ definition: "{\n /** Number of cells successfully written */\n cellsWritten: number;\n /** Per-cell errors, if any (omitted when all succeed) */\n errors?: Array<{ addr: string; error: string }> | null;\n /** Non-fatal warnings (e.g., deduplication, coercion) */\n warnings?: OperationWarning[];\n}",
96024
96360
  docstring: "Result of a bulk setCells() operation."
96025
96361
  },
96026
96362
  ShadowAlignment: {
@@ -96424,8 +96760,7 @@ Used in condition filters where users specify rules like
96424
96760
  definition: "{\n /** All sheets in the workbook */\n sheets: SheetSnapshot[];\n /** ID of the currently active sheet */\n activeSheetId: string;\n /** Total number of sheets */\n sheetCount: number;\n}",
96425
96761
  docstring: "A summary snapshot of the entire workbook state."
96426
96762
  }
96427
- },
96428
- generated: "2026-04-02T22:03:24.772Z"
96763
+ }
96429
96764
  };
96430
96765
 
96431
96766
  // src/api-describe.ts