@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.cjs CHANGED
@@ -1334,6 +1334,106 @@ var init_schemas = __esm({
1334
1334
  }
1335
1335
  });
1336
1336
 
1337
+ // ../../kernel/src/api/worksheet/change-accumulator.ts
1338
+ function colToLetter(col) {
1339
+ let result = "";
1340
+ let c = col;
1341
+ while (c >= 0) {
1342
+ result = String.fromCharCode(c % 26 + 65) + result;
1343
+ c = Math.floor(c / 26) - 1;
1344
+ }
1345
+ return result;
1346
+ }
1347
+ function toA1(row, col) {
1348
+ return `${colToLetter(col)}${row + 1}`;
1349
+ }
1350
+ var ChangeAccumulator;
1351
+ var init_change_accumulator = __esm({
1352
+ "../../kernel/src/api/worksheet/change-accumulator.ts"() {
1353
+ "use strict";
1354
+ init_cjs_shims();
1355
+ ChangeAccumulator = class {
1356
+ constructor() {
1357
+ this.trackers = /* @__PURE__ */ new Set();
1358
+ /**
1359
+ * Pending direct edits set before a mutation, consumed by the next ingest().
1360
+ * Since JS is single-threaded, setDirectEdits() before the bridge call
1361
+ * guarantees these are consumed by the corresponding ingest().
1362
+ */
1363
+ this.pendingDirectEdits = null;
1364
+ }
1365
+ /**
1366
+ * Set the direct edit positions for the next mutation.
1367
+ * Called by cell-operations before triggering the bridge call.
1368
+ * Consumed (cleared) by the next ingest() call.
1369
+ */
1370
+ setDirectEdits(edits) {
1371
+ this.pendingDirectEdits = edits;
1372
+ }
1373
+ /**
1374
+ * Called by MutationResultHandler after every mutation.
1375
+ *
1376
+ * @param changedCells - RecalcResult.changedCells from the MutationResult
1377
+ * @param directEdits - The (sheetId, row, col) tuples that were directly written
1378
+ * (to distinguish direct vs cascade)
1379
+ * @param source - user or remote
1380
+ */
1381
+ ingest(changedCells, directEdits, source) {
1382
+ if (this.trackers.size === 0) {
1383
+ this.pendingDirectEdits = null;
1384
+ return;
1385
+ }
1386
+ if (changedCells.length === 0) {
1387
+ this.pendingDirectEdits = null;
1388
+ return;
1389
+ }
1390
+ const edits = directEdits ?? this.pendingDirectEdits;
1391
+ this.pendingDirectEdits = null;
1392
+ const directSet = /* @__PURE__ */ new Set();
1393
+ if (edits) {
1394
+ for (const e of edits) {
1395
+ directSet.add(`${e.sheetId}:${e.row}:${e.col}`);
1396
+ }
1397
+ }
1398
+ const recordsBySheet = /* @__PURE__ */ new Map();
1399
+ for (const cell of changedCells) {
1400
+ const key = `${cell.sheetId}:${cell.row}:${cell.col}`;
1401
+ const origin = source === "remote" ? "remote" : directSet.has(key) ? "direct" : "cascade";
1402
+ const record = {
1403
+ address: toA1(cell.row, cell.col),
1404
+ row: cell.row,
1405
+ col: cell.col,
1406
+ origin,
1407
+ type: "modified"
1408
+ };
1409
+ let list = recordsBySheet.get(cell.sheetId);
1410
+ if (!list) {
1411
+ list = [];
1412
+ recordsBySheet.set(cell.sheetId, list);
1413
+ }
1414
+ list.push(record);
1415
+ }
1416
+ for (const tracker of this.trackers) {
1417
+ const records = recordsBySheet.get(tracker.sheetId);
1418
+ if (records && records.length > 0) {
1419
+ tracker._ingest(records);
1420
+ }
1421
+ }
1422
+ }
1423
+ register(tracker) {
1424
+ this.trackers.add(tracker);
1425
+ }
1426
+ unregister(tracker) {
1427
+ this.trackers.delete(tracker);
1428
+ }
1429
+ /** Number of active trackers. */
1430
+ get activeCount() {
1431
+ return this.trackers.size;
1432
+ }
1433
+ };
1434
+ }
1435
+ });
1436
+
1337
1437
  // ../../kernel/src/bridges/mutation-result-handler.ts
1338
1438
  function resolvedPosition(row, col) {
1339
1439
  if (row === POSITION_SENTINEL || col === POSITION_SENTINEL) {
@@ -1346,6 +1446,7 @@ var init_mutation_result_handler = __esm({
1346
1446
  "../../kernel/src/bridges/mutation-result-handler.ts"() {
1347
1447
  "use strict";
1348
1448
  init_cjs_shims();
1449
+ init_change_accumulator();
1349
1450
  POSITION_SENTINEL = 4294967295;
1350
1451
  MutationResultHandler = class {
1351
1452
  constructor(eventBus, onUndoDescription) {
@@ -1355,6 +1456,7 @@ var init_mutation_result_handler = __esm({
1355
1456
  this.errorCallbacks = [];
1356
1457
  this.eventBus = eventBus;
1357
1458
  this.onUndoDescription = onUndoDescription;
1459
+ this.changeAccumulator = new ChangeAccumulator();
1358
1460
  }
1359
1461
  /** Set the ViewportCoordinatorRegistry for per-viewport dimension patching. */
1360
1462
  setCoordinatorRegistry(registry2) {
@@ -1376,8 +1478,9 @@ var init_mutation_result_handler = __esm({
1376
1478
  *
1377
1479
  * @param result - MutationResult from a Rust IPC command
1378
1480
  * @param source - Whether this mutation originated from the local user or remote collaboration
1481
+ * @param directEdits - Optional positions of directly-written cells (to distinguish direct vs cascade)
1379
1482
  */
1380
- applyAndNotify(result, source = "user") {
1483
+ applyAndNotify(result, source = "user", directEdits) {
1381
1484
  if (result.recalc) {
1382
1485
  this.handleRecalcResult(result.recalc, source);
1383
1486
  }
@@ -1438,6 +1541,9 @@ var init_mutation_result_handler = __esm({
1438
1541
  if (result.undoDescription) {
1439
1542
  this.handleUndoDescription(result.undoDescription);
1440
1543
  }
1544
+ if (this.changeAccumulator.activeCount > 0 && result.recalc?.changedCells?.length) {
1545
+ this.changeAccumulator.ingest(result.recalc.changedCells, directEdits ?? null, source);
1546
+ }
1441
1547
  }
1442
1548
  /**
1443
1549
  * Register an error callback for mutation failures.
@@ -6001,6 +6107,9 @@ var init_compute_bridge_gen = __esm({
6001
6107
  getCellFormatWithCf(sheetId, cellId, row, col) {
6002
6108
  return this.core.query(this.core.transport.call("compute_get_cell_format_with_cf", { docId: this.core.docId, sheetId, cellId, row, col }));
6003
6109
  }
6110
+ getResolvedFormat(sheetId, row, col) {
6111
+ return this.core.query(this.core.transport.call("compute_get_resolved_format", { docId: this.core.docId, sheetId, row, col }));
6112
+ }
6004
6113
  setCellFormat(sheetId, cellId, format) {
6005
6114
  return this.core.mutatePlain(this.core.transport.call("compute_set_cell_format", { docId: this.core.docId, sheetId, cellId, format }));
6006
6115
  }
@@ -7807,16 +7916,18 @@ var init_core_defaults = __esm({
7807
7916
  async function getMeta(ctx, sheetId) {
7808
7917
  const name = await ctx.computeBridge.getSheetName(sheetId);
7809
7918
  if (name === null) return void 0;
7810
- const [frozen, tabColor, hidden] = await Promise.all([
7919
+ const [frozen, tabColor, hidden, defaultRowHeight, defaultColWidth] = await Promise.all([
7811
7920
  ctx.computeBridge.getFrozenPanesQuery(sheetId),
7812
7921
  ctx.computeBridge.getTabColorQuery(sheetId),
7813
- ctx.computeBridge.isSheetHidden(sheetId)
7922
+ ctx.computeBridge.isSheetHidden(sheetId),
7923
+ ctx.computeBridge.getDefaultRowHeight(sheetId),
7924
+ ctx.computeBridge.getDefaultColWidth(sheetId)
7814
7925
  ]);
7815
7926
  return {
7816
7927
  id: sheetId,
7817
7928
  name,
7818
- defaultRowHeight: 20,
7819
- defaultColWidth: 100,
7929
+ defaultRowHeight,
7930
+ defaultColWidth,
7820
7931
  frozenRows: frozen.rows,
7821
7932
  frozenCols: frozen.cols,
7822
7933
  tabColor: tabColor ?? void 0,
@@ -7863,7 +7974,7 @@ var init_range = __esm({
7863
7974
  });
7864
7975
 
7865
7976
  // ../../spreadsheet-utils/src/a1.ts
7866
- function colToLetter2(col) {
7977
+ function colToLetter3(col) {
7867
7978
  if (col < 0) {
7868
7979
  throw new Error("Column number must be >= 0");
7869
7980
  }
@@ -7883,8 +7994,8 @@ function letterToCol(letters) {
7883
7994
  }
7884
7995
  return result - 1;
7885
7996
  }
7886
- function toA1(row, col) {
7887
- return `${colToLetter2(col)}${row + 1}`;
7997
+ function toA12(row, col) {
7998
+ return `${colToLetter3(col)}${row + 1}`;
7888
7999
  }
7889
8000
  function parseCellAddress(ref) {
7890
8001
  const match = ref.match(CELL_ADDRESS_REGEX);
@@ -77330,6 +77441,10 @@ async function getRefersToA1(ctx, name) {
77330
77441
  const a1 = await ctx.computeBridge.toA1Display(NIL_SHEET_ID, wire);
77331
77442
  return a1.startsWith("=") ? a1 : `=${a1}`;
77332
77443
  }
77444
+ async function getVisible(ctx) {
77445
+ const rustNames = await ctx.computeBridge.getVisibleNamedRanges();
77446
+ return rustNames.map(mapRustNamedRange);
77447
+ }
77333
77448
  async function create2(ctx, input, contextSheet, _origin = "user") {
77334
77449
  const formula = await ctx.computeBridge.toIdentityFormula(contextSheet, input.refersToA1);
77335
77450
  const rawFormula = formula;
@@ -77415,7 +77530,7 @@ async function update2(ctx, id, updates, contextSheet, _origin = "user") {
77415
77530
  }
77416
77531
  const newName = updates.name ?? existing.name;
77417
77532
  if (newName !== existing.name) {
77418
- void ctx.computeBridge.removeNamedRange(existing.name);
77533
+ void ctx.computeBridge.removeNamedRangeById(existing.id);
77419
77534
  }
77420
77535
  let refersToWire = identityFormulaToWire(existing.refersTo);
77421
77536
  if (updates.refersToA1) {
@@ -77502,7 +77617,7 @@ async function remove(ctx, id, _origin = "user") {
77502
77617
  if (!existing) {
77503
77618
  throw new KernelError("DOMAIN_DEFINED_NAME_NOT_FOUND", `Defined name with ID ${id} not found`);
77504
77619
  }
77505
- void ctx.computeBridge.removeNamedRange(existing.name);
77620
+ void ctx.computeBridge.removeNamedRangeById(existing.id);
77506
77621
  }
77507
77622
  async function exportNames(ctx) {
77508
77623
  const all = await getAll(ctx);
@@ -77527,7 +77642,7 @@ function sanitizeLabel(label) {
77527
77642
  }
77528
77643
  return name;
77529
77644
  }
77530
- function colToLetter(col) {
77645
+ function colToLetter2(col) {
77531
77646
  let result = "";
77532
77647
  let c = col;
77533
77648
  while (c >= 0) {
@@ -77601,7 +77716,7 @@ async function createFromSelection(ctx, sheetId, range2, options, _origin = "use
77601
77716
  result.skippedReasons.push({ label: name, reason: validation.message ?? "invalid name" });
77602
77717
  return;
77603
77718
  }
77604
- const refersToA1 = refStartRow === refEndRow && refStartCol === refEndCol ? `=$${colToLetter(refStartCol)}$${refStartRow + 1}` : `=$${colToLetter(refStartCol)}$${refStartRow + 1}:$${colToLetter(refEndCol)}$${refEndRow + 1}`;
77719
+ const refersToA1 = refStartRow === refEndRow && refStartCol === refEndCol ? `=$${colToLetter2(refStartCol)}$${refStartRow + 1}` : `=$${colToLetter2(refStartCol)}$${refStartRow + 1}:$${colToLetter2(refEndCol)}$${refEndRow + 1}`;
77605
77720
  try {
77606
77721
  await create2(ctx, { name: sanitized, refersToA1 }, sheetId);
77607
77722
  existingKeys.add(key);
@@ -78873,6 +78988,7 @@ init_cell_properties();
78873
78988
  var MAX_RANGE_CELLS = 1e4;
78874
78989
  var MAX_RANGE_BOUNDING_BOX = 5e5;
78875
78990
  var MAX_DESCRIBE_OUTPUT_CHARS = 5e4;
78991
+ var MAX_SUMMARY_NAMED_RANGES = 20;
78876
78992
  async function getStyleHints(ctx, sheetId, row, col) {
78877
78993
  const format = await getFormat(ctx, sheetId, row, col);
78878
78994
  if (!format) return null;
@@ -78962,7 +79078,7 @@ function generateFormulaDocumentation(analysis) {
78962
79078
  const lines = [""];
78963
79079
  for (const info of significantPatterns) {
78964
79080
  const examples = info.cells.slice(0, 2).map((cell) => {
78965
- const addr = `${colToLetter2(cell.col)}${cell.row + 1}`;
79081
+ const addr = `${colToLetter3(cell.col)}${cell.row + 1}`;
78966
79082
  return `${addr}: =${cell.formula}`;
78967
79083
  });
78968
79084
  const exampleStr = examples.length > 0 ? ` (e.g. ${examples.join(", ")})` : "";
@@ -79021,7 +79137,7 @@ function buildLeftContext(leftCells, startRow, startCol, endRow) {
79021
79137
  found.sort((a, b) => a.col - b.col);
79022
79138
  const tokens = found.map((f) => {
79023
79139
  const prefix = "\u2192".repeat(Math.max(0, f.indent));
79024
- const addr = `${colToLetter2(f.col)}${row + 1}`;
79140
+ const addr = `${colToLetter3(f.col)}${row + 1}`;
79025
79141
  return `${prefix}${addr}:${f.text}`;
79026
79142
  });
79027
79143
  lines.push(tokens.join(" | "));
@@ -79093,7 +79209,7 @@ function buildAboveContext(aboveCells, startRow, startCol, endCol) {
79093
79209
  sawNumeric = true;
79094
79210
  continue;
79095
79211
  }
79096
- const addr = `${colToLetter2(c)}${bestRow + 1}`;
79212
+ const addr = `${colToLetter3(c)}${bestRow + 1}`;
79097
79213
  if (tokens.length > 0 && sawNumeric) tokens.push("...");
79098
79214
  tokens.push(`${addr}:${d}`);
79099
79215
  sawNumeric = false;
@@ -79151,8 +79267,8 @@ function consolidateRanges(cells) {
79151
79267
  covered.add(`${r},${c}`);
79152
79268
  }
79153
79269
  }
79154
- const start = `${colToLetter2(cell.col)}${cell.row + 1}`;
79155
- const end = `${colToLetter2(endCol)}${endRow + 1}`;
79270
+ const start = `${colToLetter3(cell.col)}${cell.row + 1}`;
79271
+ const end = `${colToLetter3(endCol)}${endRow + 1}`;
79156
79272
  ranges.push(start === end ? start : `${start}:${end}`);
79157
79273
  }
79158
79274
  return ranges;
@@ -79223,9 +79339,12 @@ async function getDisplayValue(ctx, sheetId, row, col) {
79223
79339
  async function getCell(ctx, sheetId, row, col) {
79224
79340
  const data = await getData(ctx, sheetId, row, col);
79225
79341
  if (!data) return void 0;
79342
+ const fmt = await getFormat(ctx, sheetId, row, col);
79226
79343
  return {
79227
79344
  value: (data.formula !== void 0 ? data.computed : rawToCellValue(data.raw)) ?? null,
79228
- formula: data.formula
79345
+ formula: data.formula,
79346
+ format: fmt ?? void 0,
79347
+ formatted: await getDisplayValue(ctx, sheetId, row, col) ?? void 0
79229
79348
  };
79230
79349
  }
79231
79350
  async function getDisplayValue2(ctx, sheetId, row, col) {
@@ -79246,10 +79365,11 @@ async function setCell(ctx, sheetId, row, col, value) {
79246
79365
  throw KernelError.from(null, "COMPUTE_ERROR", `Invalid cell address: row=${row}, col=${col}`);
79247
79366
  }
79248
79367
  const input = value === null || value === void 0 ? "" : value === "" ? "\0" : String(value);
79249
- const result = await ctx.computeBridge.setCellsByPosition(sheetId, [{ row, col, input }]);
79368
+ ctx.computeBridge.getMutationHandler()?.changeAccumulator.setDirectEdits([{ sheetId, row, col }]);
79369
+ await ctx.computeBridge.setCellsByPosition(sheetId, [{ row, col, input }]);
79250
79370
  }
79251
79371
  async function setCells(ctx, sheetId, cells) {
79252
- if (cells.length === 0) return { cellsWritten: 0 };
79372
+ if (cells.length === 0) return { cellsWritten: 0, errors: null };
79253
79373
  const edits = cells.map((cell) => {
79254
79374
  let row;
79255
79375
  let col;
@@ -79271,8 +79391,11 @@ async function setCells(ctx, sheetId, cells) {
79271
79391
  }
79272
79392
  const uniqueEdits = Array.from(deduped.values());
79273
79393
  const duplicatesRemoved = edits.length - uniqueEdits.length;
79394
+ ctx.computeBridge.getMutationHandler()?.changeAccumulator.setDirectEdits(
79395
+ uniqueEdits.map((e) => ({ sheetId, row: e.row, col: e.col }))
79396
+ );
79274
79397
  await ctx.computeBridge.setCellsByPosition(sheetId, uniqueEdits);
79275
- const result = { cellsWritten: uniqueEdits.length };
79398
+ const result = { cellsWritten: uniqueEdits.length, errors: null };
79276
79399
  if (duplicatesRemoved > 0) {
79277
79400
  result.warnings = [
79278
79401
  createWarning("API_DUPLICATE_COORDINATES", `${duplicatesRemoved} duplicate coordinate(s) resolved by last-write-wins`, {
@@ -79378,7 +79501,7 @@ async function batchGetCellPositions(ctx, sheetId, cellIds) {
79378
79501
 
79379
79502
  // ../../kernel/src/api/worksheet/operations/dependency-operations.ts
79380
79503
  init_cjs_shims();
79381
- function colToLetter3(col) {
79504
+ function colToLetter4(col) {
79382
79505
  let result = "";
79383
79506
  let c = col;
79384
79507
  while (c >= 0) {
@@ -79389,11 +79512,11 @@ function colToLetter3(col) {
79389
79512
  }
79390
79513
  async function getDependents(ctx, sheetId, row, col) {
79391
79514
  const results = await ctx.computeBridge.getDependents(sheetId, row, col);
79392
- return results.map((r) => `${colToLetter3(r.col)}${r.row + 1}`);
79515
+ return results.map((r) => `${colToLetter4(r.col)}${r.row + 1}`);
79393
79516
  }
79394
79517
  async function getPrecedents(ctx, sheetId, row, col) {
79395
79518
  const results = await ctx.computeBridge.getPrecedents(sheetId, row, col);
79396
- return results.map((r) => `${colToLetter3(r.col)}${r.row + 1}`);
79519
+ return results.map((r) => `${colToLetter4(r.col)}${r.row + 1}`);
79397
79520
  }
79398
79521
 
79399
79522
  // ../../kernel/src/api/worksheet/operations/fill-operations.ts
@@ -79446,7 +79569,8 @@ async function autoFill(ctx, sheetId, sourceRange, targetRange, mode) {
79446
79569
  return {
79447
79570
  patternType: fillData?.patternType ?? "copy",
79448
79571
  filledCellCount: fillData?.filledCellCount ?? 0,
79449
- warnings: fillData?.warnings ?? []
79572
+ warnings: fillData?.warnings ?? [],
79573
+ changes: fillData?.changes ?? []
79450
79574
  };
79451
79575
  }
79452
79576
  function splitRangeForSeries(range2, direction) {
@@ -79770,14 +79894,14 @@ async function regexSearch(ctx, sheetId, patterns, options) {
79770
79894
  for (const { regex, source } of compiledPatterns) {
79771
79895
  regex.lastIndex = 0;
79772
79896
  if (regex.test(valueStr)) {
79773
- const address = `${colToLetter2(cell.col)}${cell.row + 1}`;
79897
+ const address = `${colToLetter3(cell.col)}${cell.row + 1}`;
79774
79898
  results.push({ address, value: valueStr, sheetName, matchedPattern: source });
79775
79899
  break;
79776
79900
  }
79777
79901
  if (options?.includeFormulas && cell.formula) {
79778
79902
  regex.lastIndex = 0;
79779
79903
  if (regex.test(cell.formula)) {
79780
- const address = `${colToLetter2(cell.col)}${cell.row + 1}`;
79904
+ const address = `${colToLetter3(cell.col)}${cell.row + 1}`;
79781
79905
  results.push({ address, value: valueStr, sheetName, matchedPattern: source });
79782
79906
  break;
79783
79907
  }
@@ -79933,7 +80057,7 @@ async function clearRange2(ctx, sheetId, range2) {
79933
80057
  }
79934
80058
  }
79935
80059
  }
79936
- return { success: true, data: void 0, affectedCells };
80060
+ return { success: true, data: { cellCount }, affectedCells };
79937
80061
  } catch (e) {
79938
80062
  return {
79939
80063
  success: false,
@@ -79965,6 +80089,8 @@ async function clearWithMode(ctx, sheetId, range2, applyTo = "all") {
79965
80089
  promises.push(clearHyperlinksInRange(ctx, sheetId, n));
79966
80090
  }
79967
80091
  await Promise.all(promises);
80092
+ const cellCount = (n.endRow - n.startRow + 1) * (n.endCol - n.startCol + 1);
80093
+ return { cellCount };
79968
80094
  }
79969
80095
  async function clearHyperlinksInRange(ctx, sheetId, range2) {
79970
80096
  const rangeResult = await ctx.computeBridge.queryRange(
@@ -80083,7 +80209,7 @@ async function findInRange(ctx, sheetId, range2, text, options) {
80083
80209
  const valueStr = cell.formatted ?? viewportCellValueToString(cell.value);
80084
80210
  if (pattern.test(valueStr)) {
80085
80211
  return {
80086
- address: `${colToLetter2(cell.col)}${cell.row + 1}`,
80212
+ address: `${colToLetter3(cell.col)}${cell.row + 1}`,
80087
80213
  value: valueStr
80088
80214
  };
80089
80215
  }
@@ -80970,6 +81096,84 @@ var WorksheetBindingsImpl = class {
80970
81096
  }
80971
81097
  };
80972
81098
 
81099
+ // ../../kernel/src/api/worksheet/index.ts
81100
+ init_change_accumulator();
81101
+
81102
+ // ../../kernel/src/api/worksheet/changes.ts
81103
+ init_cjs_shims();
81104
+ function parseRangeScope(scope) {
81105
+ const match = scope.match(/^([A-Z]+)(\d+):([A-Z]+)(\d+)$/i);
81106
+ if (!match) return null;
81107
+ const startCol = letterToCol2(match[1].toUpperCase());
81108
+ const startRow = parseInt(match[2], 10) - 1;
81109
+ const endCol = letterToCol2(match[3].toUpperCase());
81110
+ const endRow = parseInt(match[4], 10) - 1;
81111
+ return { startRow, startCol, endRow, endCol };
81112
+ }
81113
+ function letterToCol2(letters) {
81114
+ let col = 0;
81115
+ for (let i = 0; i < letters.length; i++) {
81116
+ col = col * 26 + (letters.charCodeAt(i) - 64);
81117
+ }
81118
+ return col - 1;
81119
+ }
81120
+ var ChangeTrackerImpl = class {
81121
+ constructor(sheetId, options, unregister) {
81122
+ this._active = true;
81123
+ this.buffer = [];
81124
+ this.sheetId = sheetId;
81125
+ this.unregister = unregister;
81126
+ this.scopeBounds = options?.scope ? parseRangeScope(options.scope) : null;
81127
+ this.excludeOrigins = options?.excludeOrigins && options.excludeOrigins.length > 0 ? new Set(options.excludeOrigins) : null;
81128
+ }
81129
+ // --- TrackerHandle (called by ChangeAccumulator) ---
81130
+ _ingest(records) {
81131
+ if (!this._active) return;
81132
+ for (const record of records) {
81133
+ if (this.excludeOrigins?.has(record.origin)) continue;
81134
+ if (this.scopeBounds) {
81135
+ const { startRow, startCol, endRow, endCol } = this.scopeBounds;
81136
+ if (record.row < startRow || record.row > endRow || record.col < startCol || record.col > endCol) {
81137
+ continue;
81138
+ }
81139
+ }
81140
+ this.buffer.push(record);
81141
+ }
81142
+ }
81143
+ // --- ChangeTracker public API ---
81144
+ collect() {
81145
+ const result = this.buffer;
81146
+ this.buffer = [];
81147
+ return result;
81148
+ }
81149
+ close() {
81150
+ if (!this._active) return;
81151
+ this._active = false;
81152
+ this.buffer = [];
81153
+ this.unregister();
81154
+ }
81155
+ get active() {
81156
+ return this._active;
81157
+ }
81158
+ };
81159
+ var WorksheetChangesImpl = class {
81160
+ constructor(ctx, sheetId) {
81161
+ this.ctx = ctx;
81162
+ this.sheetId = sheetId;
81163
+ }
81164
+ track(options) {
81165
+ const accumulator = this.ctx.computeBridge.getMutationHandler()?.changeAccumulator;
81166
+ if (!accumulator) {
81167
+ throw new Error("Change tracking unavailable: MutationResultHandler not initialized");
81168
+ }
81169
+ const tracker = new ChangeTrackerImpl(this.sheetId, options, () => {
81170
+ accumulator.unregister(tracker);
81171
+ });
81172
+ accumulator.register(tracker);
81173
+ return tracker;
81174
+ }
81175
+ };
81176
+
80973
81177
  // ../../kernel/src/api/worksheet/charts.ts
80974
81178
  init_cjs_shims();
80975
81179
  function buildStatisticalExtra(config) {
@@ -81399,7 +81603,7 @@ function cellRefToA1(cellRef) {
81399
81603
  const col = parseInt(parts[0], 10);
81400
81604
  const row = parseInt(parts[1], 10);
81401
81605
  if (isNaN(col) || isNaN(row)) return cellRef;
81402
- return toA1(row, col);
81606
+ return toA12(row, col);
81403
81607
  }
81404
81608
  function toApiComment(c) {
81405
81609
  const text = c.content ?? c.runs.map((r) => r.text).join("");
@@ -81500,7 +81704,7 @@ var WorksheetCommentsImpl = class {
81500
81704
  return {
81501
81705
  content,
81502
81706
  author: first.author,
81503
- cellAddress: toA1(row, col)
81707
+ cellAddress: toA12(row, col)
81504
81708
  };
81505
81709
  }
81506
81710
  async removeNote(a, b) {
@@ -81843,7 +82047,7 @@ var WorksheetFiltersImpl = class {
81843
82047
  }
81844
82048
  }
81845
82049
  return {
81846
- range: `${toA1(filter.startRow ?? 0, filter.startCol ?? 0)}:${toA1(filter.endRow ?? 0, filter.endCol ?? 0)}`,
82050
+ range: `${toA12(filter.startRow ?? 0, filter.startCol ?? 0)}:${toA12(filter.endRow ?? 0, filter.endCol ?? 0)}`,
81847
82051
  columns
81848
82052
  };
81849
82053
  }
@@ -82218,7 +82422,8 @@ var WorksheetFormatsImpl = class {
82218
82422
  col = b;
82219
82423
  format = c;
82220
82424
  }
82221
- await this.ctx.computeBridge.setFormatForRanges(this.sheetId, [[row, col, row, col]], format);
82425
+ const result = await this.ctx.computeBridge.setFormatForRanges(this.sheetId, [[row, col, row, col]], format);
82426
+ return { cellCount: result.propertyChanges?.length ?? 0 };
82222
82427
  }
82223
82428
  async setRange(a, b) {
82224
82429
  let range2;
@@ -82230,11 +82435,12 @@ var WorksheetFormatsImpl = class {
82230
82435
  range2 = a;
82231
82436
  }
82232
82437
  const n = normalizeRange(range2);
82233
- await this.ctx.computeBridge.setFormatForRanges(
82438
+ const result = await this.ctx.computeBridge.setFormatForRanges(
82234
82439
  this.sheetId,
82235
82440
  [[n.startRow, n.startCol, n.endRow, n.endCol]],
82236
82441
  b
82237
82442
  );
82443
+ return { cellCount: result.propertyChanges?.length ?? 0 };
82238
82444
  }
82239
82445
  async setRanges(ranges, format) {
82240
82446
  const boundedRanges = [];
@@ -82265,9 +82471,7 @@ var WorksheetFormatsImpl = class {
82265
82471
  }
82266
82472
  async get(a, b) {
82267
82473
  const { row, col } = resolveCell(a, b);
82268
- const result = await this.ctx.computeBridge.queryRange(this.sheetId, row, col, row, col);
82269
- if (!result?.cells || result.cells.length === 0) return null;
82270
- return result.cells[0]?.format ?? null;
82474
+ return this.ctx.computeBridge.getResolvedFormat(this.sheetId, row, col);
82271
82475
  }
82272
82476
  async adjustIndent(a, b, c) {
82273
82477
  let row, col, amount;
@@ -82291,7 +82495,8 @@ var WorksheetFormatsImpl = class {
82291
82495
  async clearFill(a, b) {
82292
82496
  const { row, col } = resolveCell(a, b);
82293
82497
  const rangeTuple = [row, col, row, col];
82294
- const current = await this.get(row, col);
82498
+ const result = await this.ctx.computeBridge.queryRange(this.sheetId, row, col, row, col);
82499
+ const current = result?.cells?.[0]?.format ?? null;
82295
82500
  await this.ctx.computeBridge.clearFormatForRanges(this.sheetId, [rangeTuple]);
82296
82501
  if (current) {
82297
82502
  const { backgroundColor, patternType, patternForegroundColor, gradientFill, ...rest } = current;
@@ -83051,8 +83256,8 @@ init_cjs_shims();
83051
83256
  init_errors();
83052
83257
  function formatDataSource(sourceSheetName, sourceRange) {
83053
83258
  if (!sourceRange) return "";
83054
- const start = toA1(sourceRange.startRow, sourceRange.startCol);
83055
- const end = toA1(sourceRange.endRow, sourceRange.endCol);
83259
+ const start = toA12(sourceRange.startRow, sourceRange.startCol);
83260
+ const end = toA12(sourceRange.endRow, sourceRange.endCol);
83056
83261
  const sheetRef = sourceSheetName ?? "Unknown";
83057
83262
  const needsQuotes = /[^A-Za-z0-9_]/.test(sheetRef);
83058
83263
  const quotedSheet = needsQuotes ? `'${sheetRef}'` : sheetRef;
@@ -83144,7 +83349,7 @@ var WorksheetPivotsImpl = class _WorksheetPivotsImpl {
83144
83349
  }
83145
83350
  return pivots.map((p) => {
83146
83351
  const apiConfig = dataConfigToApiConfig(p, p.sourceSheetName);
83147
- const location = p.outputLocation ? toA1(p.outputLocation.row, p.outputLocation.col) : void 0;
83352
+ const location = p.outputLocation ? toA12(p.outputLocation.row, p.outputLocation.col) : void 0;
83148
83353
  return {
83149
83354
  name: p.name ?? p.id,
83150
83355
  dataSource: apiConfig.dataSource,
@@ -83677,7 +83882,7 @@ function parseCellRef2(ref) {
83677
83882
  }
83678
83883
  return { row: rowNum - 1, col: col - 1 };
83679
83884
  }
83680
- function colToLetter4(col) {
83885
+ function colToLetter5(col) {
83681
83886
  let result = "";
83682
83887
  let c = col;
83683
83888
  while (c >= 0) {
@@ -83687,8 +83892,8 @@ function colToLetter4(col) {
83687
83892
  return result;
83688
83893
  }
83689
83894
  function printRangeToA1(range2) {
83690
- const startRef = `${colToLetter4(range2.startCol)}${range2.startRow + 1}`;
83691
- const endRef = `${colToLetter4(range2.endCol)}${range2.endRow + 1}`;
83895
+ const startRef = `${colToLetter5(range2.startCol)}${range2.startRow + 1}`;
83896
+ const endRef = `${colToLetter5(range2.endCol)}${range2.endRow + 1}`;
83692
83897
  return `${startRef}:${endRef}`;
83693
83898
  }
83694
83899
  async function getPageBreaks(ctx, sheetId) {
@@ -84088,7 +84293,11 @@ var WorksheetSlicersImpl = class {
84088
84293
  this.sheetId = sheetId;
84089
84294
  }
84090
84295
  async add(config) {
84091
- const storedConfig = config;
84296
+ const caption = config.caption ?? config.name ?? "";
84297
+ const storedConfig = {
84298
+ ...config,
84299
+ caption
84300
+ };
84092
84301
  await this.ctx.computeBridge.createSlicer(this.sheetId, storedConfig);
84093
84302
  return storedConfig.id ?? "";
84094
84303
  }
@@ -84802,7 +85011,7 @@ var WorksheetStructureImpl = class {
84802
85011
  async getMergedRegions() {
84803
85012
  const regions = await getAll3(this.ctx, this.sheetId);
84804
85013
  return regions.map((r) => ({
84805
- range: `${toA1(r.startRow, r.startCol)}:${toA1(r.endRow, r.endCol)}`,
85014
+ range: `${toA12(r.startRow, r.startCol)}:${toA12(r.endRow, r.endCol)}`,
84806
85015
  startRow: r.startRow,
84807
85016
  startCol: r.startCol,
84808
85017
  endRow: r.endRow,
@@ -84865,8 +85074,8 @@ function parseA1Range(range2) {
84865
85074
  };
84866
85075
  }
84867
85076
  function bridgeTableToTableInfo(table) {
84868
- const startLetter = colToLetter2(table.range.startCol);
84869
- const endLetter = colToLetter2(table.range.endCol);
85077
+ const startLetter = colToLetter3(table.range.startCol);
85078
+ const endLetter = colToLetter3(table.range.endCol);
84870
85079
  const startRowA1 = table.range.startRow + 1;
84871
85080
  const endRowA1 = table.range.endRow + 1;
84872
85081
  const range2 = `${startLetter}${startRowA1}:${endLetter}${endRowA1}`;
@@ -84911,16 +85120,16 @@ function getDataBodyRangeFromInfo(table) {
84911
85120
  const dataStartRow = table.hasHeaders ? parsed.startRow + 1 : parsed.startRow;
84912
85121
  const dataEndRow = table.showTotals ? parsed.endRow - 1 : parsed.endRow;
84913
85122
  if (dataStartRow > dataEndRow) return null;
84914
- const startLetter = colToLetter2(parsed.startCol);
84915
- const endLetter = colToLetter2(parsed.endCol);
85123
+ const startLetter = colToLetter3(parsed.startCol);
85124
+ const endLetter = colToLetter3(parsed.endCol);
84916
85125
  return `${startLetter}${dataStartRow + 1}:${endLetter}${dataEndRow + 1}`;
84917
85126
  }
84918
85127
  function getHeaderRowRangeFromInfo(table) {
84919
85128
  if (!table.hasHeaders) return null;
84920
85129
  const parsed = parseA1Range(table.range);
84921
85130
  if (!parsed) return null;
84922
- const startLetter = colToLetter2(parsed.startCol);
84923
- const endLetter = colToLetter2(parsed.endCol);
85131
+ const startLetter = colToLetter3(parsed.startCol);
85132
+ const endLetter = colToLetter3(parsed.endCol);
84924
85133
  const headerRow = parsed.startRow + 1;
84925
85134
  return `${startLetter}${headerRow}:${endLetter}${headerRow}`;
84926
85135
  }
@@ -84928,8 +85137,8 @@ function getTotalRowRangeFromInfo(table) {
84928
85137
  if (!table.showTotals) return null;
84929
85138
  const parsed = parseA1Range(table.range);
84930
85139
  if (!parsed) return null;
84931
- const startLetter = colToLetter2(parsed.startCol);
84932
- const endLetter = colToLetter2(parsed.endCol);
85140
+ const startLetter = colToLetter3(parsed.startCol);
85141
+ const endLetter = colToLetter3(parsed.endCol);
84933
85142
  const totalRow = parsed.endRow + 1;
84934
85143
  return `${startLetter}${totalRow}:${endLetter}${totalRow}`;
84935
85144
  }
@@ -84972,9 +85181,9 @@ var WorksheetTablesImpl = class {
84972
85181
  if (!match) {
84973
85182
  throw new KernelError("COMPUTE_ERROR", `Invalid range: ${range2}`);
84974
85183
  }
84975
- const startCol = letterToCol2(match[1]);
85184
+ const startCol = letterToCol3(match[1]);
84976
85185
  const startRow = parseInt(match[2], 10) - 1;
84977
- const endCol = letterToCol2(match[3]);
85186
+ const endCol = letterToCol3(match[3]);
84978
85187
  const endRow = parseInt(match[4], 10) - 1;
84979
85188
  await this.ctx.computeBridge.createTable(
84980
85189
  this.sheetId,
@@ -85054,9 +85263,9 @@ var WorksheetTablesImpl = class {
85054
85263
  if (!parsed) {
85055
85264
  throw new KernelError("COMPUTE_ERROR", `Invalid table range: ${table.range}`);
85056
85265
  }
85057
- const startCol = letterToCol2(parsed[1]);
85266
+ const startCol = letterToCol3(parsed[1]);
85058
85267
  const startRow = parseInt(parsed[2], 10) - 1;
85059
- const endCol = letterToCol2(parsed[3]);
85268
+ const endCol = letterToCol3(parsed[3]);
85060
85269
  const endRow = parseInt(parsed[4], 10) - 1;
85061
85270
  const filter = await getFilterForRange(this.ctx, this.sheetId, {
85062
85271
  startRow,
@@ -85077,9 +85286,9 @@ var WorksheetTablesImpl = class {
85077
85286
  if (!match) {
85078
85287
  throw new KernelError("COMPUTE_ERROR", `Invalid range: ${newRange}`);
85079
85288
  }
85080
- const startCol = letterToCol2(match[1]);
85289
+ const startCol = letterToCol3(match[1]);
85081
85290
  const startRow = parseInt(match[2], 10) - 1;
85082
- const endCol = letterToCol2(match[3]);
85291
+ const endCol = letterToCol3(match[3]);
85083
85292
  const endRow = parseInt(match[4], 10) - 1;
85084
85293
  await this.ctx.computeBridge.resizeTable(name, startRow, startCol, endRow, endCol);
85085
85294
  }
@@ -85210,8 +85419,8 @@ var WorksheetTablesImpl = class {
85210
85419
  if (!parsed) throw new KernelError("COMPUTE_ERROR", `Invalid table range: ${table.range}`);
85211
85420
  const dataStartRow = table.hasHeaders ? parsed.startRow + 1 : parsed.startRow;
85212
85421
  const absRow = dataStartRow + index;
85213
- const startLetter = colToLetter2(parsed.startCol);
85214
- const endLetter = colToLetter2(parsed.endCol);
85422
+ const startLetter = colToLetter3(parsed.startCol);
85423
+ const endLetter = colToLetter3(parsed.endCol);
85215
85424
  return `${startLetter}${absRow + 1}:${endLetter}${absRow + 1}`;
85216
85425
  }
85217
85426
  async getRowValues(tableName, index) {
@@ -85250,7 +85459,7 @@ var WorksheetTablesImpl = class {
85250
85459
  const dataStartRow = table.hasHeaders ? parsed.startRow + 1 : parsed.startRow;
85251
85460
  const dataEndRow = table.showTotals ? parsed.endRow - 1 : parsed.endRow;
85252
85461
  if (dataStartRow > dataEndRow) return null;
85253
- const letter = colToLetter2(col);
85462
+ const letter = colToLetter3(col);
85254
85463
  return `${letter}${dataStartRow + 1}:${letter}${dataEndRow + 1}`;
85255
85464
  }
85256
85465
  async getColumnHeaderRange(tableName, columnIndex) {
@@ -85260,7 +85469,7 @@ var WorksheetTablesImpl = class {
85260
85469
  if (!parsed) return null;
85261
85470
  const col = parsed.startCol + columnIndex;
85262
85471
  if (col > parsed.endCol) return null;
85263
- const letter = colToLetter2(col);
85472
+ const letter = colToLetter3(col);
85264
85473
  const headerRow = parsed.startRow + 1;
85265
85474
  return `${letter}${headerRow}`;
85266
85475
  }
@@ -85271,7 +85480,7 @@ var WorksheetTablesImpl = class {
85271
85480
  if (!parsed) return null;
85272
85481
  const col = parsed.startCol + columnIndex;
85273
85482
  if (col > parsed.endCol) return null;
85274
- const letter = colToLetter2(col);
85483
+ const letter = colToLetter3(col);
85275
85484
  return `${letter}${parsed.startRow + 1}:${letter}${parsed.endRow + 1}`;
85276
85485
  }
85277
85486
  async getColumnTotalRange(tableName, columnIndex) {
@@ -85281,7 +85490,7 @@ var WorksheetTablesImpl = class {
85281
85490
  if (!parsed) return null;
85282
85491
  const col = parsed.startCol + columnIndex;
85283
85492
  if (col > parsed.endCol) return null;
85284
- const letter = colToLetter2(col);
85493
+ const letter = colToLetter3(col);
85285
85494
  const totalRow = parsed.endRow + 1;
85286
85495
  return `${letter}${totalRow}`;
85287
85496
  }
@@ -85380,7 +85589,7 @@ var WorksheetTablesImpl = class {
85380
85589
  async sortClear(_tableName) {
85381
85590
  }
85382
85591
  };
85383
- function letterToCol2(letters) {
85592
+ function letterToCol3(letters) {
85384
85593
  let col = 0;
85385
85594
  for (let i = 0; i < letters.length; i++) {
85386
85595
  col = col * 26 + (letters.toUpperCase().charCodeAt(i) - 64);
@@ -85391,9 +85600,9 @@ function parseA1Range2(range2) {
85391
85600
  const match = range2.match(/^([A-Z]+)(\d+):([A-Z]+)(\d+)$/i);
85392
85601
  if (!match) return null;
85393
85602
  return {
85394
- startCol: letterToCol2(match[1]),
85603
+ startCol: letterToCol3(match[1]),
85395
85604
  startRow: parseInt(match[2], 10) - 1,
85396
- endCol: letterToCol2(match[3]),
85605
+ endCol: letterToCol3(match[3]),
85397
85606
  endRow: parseInt(match[4], 10) - 1
85398
85607
  };
85399
85608
  }
@@ -85582,8 +85791,8 @@ function rangeSchemaToValidationRule(schema) {
85582
85791
  const start = parseRefIdSimple(ref.startId);
85583
85792
  const end = parseRefIdSimple(ref.endId);
85584
85793
  if (start && end) {
85585
- const startA1 = toA1(start.row, start.col);
85586
- const endA1 = toA1(end.row, end.col);
85794
+ const startA1 = toA12(start.row, start.col);
85795
+ const endA1 = toA12(end.row, end.col);
85587
85796
  range2 = startA1 === endA1 ? startA1 : `${startA1}:${endA1}`;
85588
85797
  }
85589
85798
  }
@@ -85616,8 +85825,8 @@ function rangeSchemaToValidationRule(schema) {
85616
85825
  const srcStart = parseRefIdSimple(src.startId);
85617
85826
  const srcEnd = parseRefIdSimple(src.endId);
85618
85827
  if (srcStart && srcEnd) {
85619
- const srcStartA1 = toA1(srcStart.row, srcStart.col);
85620
- const srcEndA1 = toA1(srcEnd.row, srcEnd.col);
85828
+ const srcStartA1 = toA12(srcStart.row, srcStart.col);
85829
+ const srcEndA1 = toA12(srcEnd.row, srcEnd.col);
85621
85830
  rule.listSource = srcStartA1 === srcEndA1 ? `=${srcStartA1}` : `=${srcStartA1}:${srcEndA1}`;
85622
85831
  }
85623
85832
  }
@@ -87834,11 +88043,12 @@ var WorksheetImpl = class {
87834
88043
  if (!result.success) {
87835
88044
  throw result.error;
87836
88045
  }
88046
+ return result.data;
87837
88047
  }
87838
88048
  async clear(range2, applyTo) {
87839
88049
  const parsed = parseCellRange(range2);
87840
88050
  if (!parsed) throw new KernelError("COMPUTE_ERROR", `Invalid range: "${range2}"`);
87841
- await clearWithMode(
88051
+ return clearWithMode(
87842
88052
  this.ctx,
87843
88053
  this.sheetId,
87844
88054
  { sheetId: this.sheetId, ...parsed },
@@ -87886,7 +88096,7 @@ var WorksheetImpl = class {
87886
88096
  format: format ?? void 0,
87887
88097
  hyperlink: hyperlink ?? void 0,
87888
88098
  isMerged: mergeInfo !== void 0,
87889
- mergedRegion: mergeInfo ? `${toA1(mergeInfo.startRow, mergeInfo.startCol)}:${toA1(mergeInfo.endRow, mergeInfo.endCol)}` : void 0
88099
+ mergedRegion: mergeInfo ? `${toA12(mergeInfo.startRow, mergeInfo.startCol)}:${toA12(mergeInfo.endRow, mergeInfo.endCol)}` : void 0
87890
88100
  };
87891
88101
  }
87892
88102
  async getRawRangeData(range2, _includeFormula) {
@@ -87913,7 +88123,8 @@ var WorksheetImpl = class {
87913
88123
  } else {
87914
88124
  rowData.push({
87915
88125
  value: viewportCellValueToCellValue(vc.value) ?? null,
87916
- formula: vc.formula
88126
+ formula: vc.formula,
88127
+ format: vc.format ?? void 0
87917
88128
  });
87918
88129
  }
87919
88130
  }
@@ -87938,10 +88149,10 @@ var WorksheetImpl = class {
87938
88149
  const { row, col } = resolveCell(address);
87939
88150
  const data = await getCell(this.ctx, this.sheetId, row, col);
87940
88151
  if (!data) return "";
87941
- const rawValue = viewportCellValueToString(data.value);
87942
- let result = rawValue;
88152
+ const displayValue = await getDisplayValue2(this.ctx, this.sheetId, row, col);
88153
+ let result = displayValue;
87943
88154
  if (data.formula) {
87944
- result = rawValue !== "" ? `${rawValue}(${data.formula})` : `(${data.formula})`;
88155
+ result = displayValue !== "" ? `${displayValue}(${data.formula})` : `(${data.formula})`;
87945
88156
  }
87946
88157
  const styleHintsStr = await getStyleHints(this.ctx, this.sheetId, row, col);
87947
88158
  if (styleHintsStr) {
@@ -88000,17 +88211,15 @@ var WorksheetImpl = class {
88000
88211
  }
88001
88212
  for (let row = parsed.startRow; row <= parsed.endRow; row++) {
88002
88213
  const rowValues = [];
88003
- let hasContent = false;
88004
88214
  for (let col = parsed.startCol; col <= parsed.endCol; col++) {
88005
- const cellAddr = toA1(row, col);
88215
+ const cellAddr = toA12(row, col);
88006
88216
  const vc = cellMap.get(`${row},${col}`);
88007
88217
  if (!vc) {
88008
88218
  rowValues.push(`${cellAddr}:`);
88009
88219
  continue;
88010
88220
  }
88011
- const rawValue = viewportCellValueToString(vc.value);
88012
- let cellStr = rawValue;
88013
- hasContent = true;
88221
+ const displayValue = vc.formatted ?? viewportCellValueToString(vc.value);
88222
+ let cellStr = displayValue;
88014
88223
  if (vc.formula) {
88015
88224
  const abbreviation = formulaAnalysis.formulaToId.get(`${row},${col}`);
88016
88225
  if (abbreviation) {
@@ -88021,9 +88230,7 @@ var WorksheetImpl = class {
88021
88230
  }
88022
88231
  rowValues.push(`${cellAddr}:${cellStr}`);
88023
88232
  }
88024
- if (hasContent) {
88025
- outputParts.push(rowValues.join(" | "));
88026
- }
88233
+ outputParts.push(rowValues.join(" | "));
88027
88234
  }
88028
88235
  const formulaDocs = generateFormulaDocumentation(formulaAnalysis);
88029
88236
  if (formulaDocs.length > 0) {
@@ -88112,8 +88319,8 @@ var WorksheetImpl = class {
88112
88319
  lines.push(`Sheet: ${meta.name}`);
88113
88320
  const bounds = await this.ctx.computeBridge.getDataBounds(this.sheetId);
88114
88321
  if (bounds) {
88115
- const startAddr = toA1(bounds.minRow, bounds.minCol);
88116
- const endAddr = toA1(bounds.maxRow, bounds.maxCol);
88322
+ const startAddr = toA12(bounds.minRow, bounds.minCol);
88323
+ const endAddr = toA12(bounds.maxRow, bounds.maxCol);
88117
88324
  lines.push(`Used Range: ${startAddr}:${endAddr}`);
88118
88325
  lines.push(
88119
88326
  `Dimensions: ${bounds.maxRow - bounds.minRow + 1} rows x ${bounds.maxCol - bounds.minCol + 1} columns`
@@ -88133,20 +88340,31 @@ var WorksheetImpl = class {
88133
88340
  const tables = await getTablesInSheet(this.ctx, this.sheetId);
88134
88341
  if (tables.length > 0) {
88135
88342
  const tableDescs = tables.map((t) => {
88136
- const r = `${toA1(t.range.startRow, t.range.startCol)}:${toA1(t.range.endRow, t.range.endCol)}`;
88343
+ const r = `${toA12(t.range.startRow, t.range.startCol)}:${toA12(t.range.endRow, t.range.endCol)}`;
88137
88344
  return `${t.name} at ${r}`;
88138
88345
  });
88139
88346
  lines.push(`Tables: ${tables.length} (${tableDescs.join(", ")})`);
88140
88347
  }
88141
- const allNamedRanges = await getAll(this.ctx);
88142
- const sheetNamedRanges = allNamedRanges.filter((nr) => nr.scope === this.sheetId || !nr.scope);
88143
- if (sheetNamedRanges.length > 0) {
88348
+ const allVisible = await getVisible(this.ctx);
88349
+ const scoped = allVisible.filter((nr) => nr.scope === this.sheetId || !nr.scope);
88350
+ const valid = scoped.filter((nr) => !nr.refersTo.template.includes("#REF!"));
88351
+ const broken = scoped.length - valid.length;
88352
+ if (valid.length > 0 || broken > 0) {
88353
+ const toShow = valid.slice(0, MAX_SUMMARY_NAMED_RANGES);
88144
88354
  const nrDescs = [];
88145
- for (const nr of sheetNamedRanges) {
88355
+ for (const nr of toShow) {
88146
88356
  const a1 = await getRefersToA1(this.ctx, nr);
88147
88357
  nrDescs.push(`${nr.name}=${a1}`);
88148
88358
  }
88149
- lines.push(`Named Ranges: ${sheetNamedRanges.length} (${nrDescs.join(", ")})`);
88359
+ let label = `Named Ranges: ${valid.length}`;
88360
+ if (broken > 0) label += ` valid, ${broken} broken (#REF!) omitted`;
88361
+ if (nrDescs.length > 0) {
88362
+ const showing = valid.length > MAX_SUMMARY_NAMED_RANGES ? `showing ${MAX_SUMMARY_NAMED_RANGES}: ` : "";
88363
+ const more = valid.length > MAX_SUMMARY_NAMED_RANGES ? ` \u2014 ${valid.length - MAX_SUMMARY_NAMED_RANGES} more not shown` : "";
88364
+ lines.push(`${label} (${showing}${nrDescs.join(", ")})${more}`);
88365
+ } else {
88366
+ lines.push(label);
88367
+ }
88150
88368
  }
88151
88369
  const maxRows = options?.maxRows;
88152
88370
  const maxCols = options?.maxCols;
@@ -88215,7 +88433,7 @@ var WorksheetImpl = class {
88215
88433
  const rowData = [];
88216
88434
  for (const vc of cells) {
88217
88435
  const rawValue = viewportCellValueToString(vc.value);
88218
- const addr = toA1(vc.row, vc.col);
88436
+ const addr = toA12(vc.row, vc.col);
88219
88437
  if (vc.formula) {
88220
88438
  rowData.push(`${addr}:${rawValue}(=${vc.formula})`);
88221
88439
  } else {
@@ -88239,7 +88457,7 @@ var WorksheetImpl = class {
88239
88457
  async getUsedRange() {
88240
88458
  const range2 = await getUsedRange2(this.ctx, this.sheetId);
88241
88459
  if (!range2) return null;
88242
- return `${toA1(range2.startRow, range2.startCol)}:${toA1(range2.endRow, range2.endCol)}`;
88460
+ return `${toA12(range2.startRow, range2.startCol)}:${toA12(range2.endRow, range2.endCol)}`;
88243
88461
  }
88244
88462
  async getCurrentRegion(row, col) {
88245
88463
  return getCurrentRegion(this.ctx, this.sheetId, row, col);
@@ -88249,15 +88467,15 @@ var WorksheetImpl = class {
88249
88467
  }
88250
88468
  async findCells(predicate) {
88251
88469
  const addresses = await findCells(this.ctx, this.sheetId, predicate);
88252
- return addresses.map((a) => toA1(a.row, a.col));
88470
+ return addresses.map((a) => toA12(a.row, a.col));
88253
88471
  }
88254
88472
  async findByValue(value) {
88255
88473
  const addresses = await findByValue(this.ctx, this.sheetId, value);
88256
- return addresses.map((a) => toA1(a.row, a.col));
88474
+ return addresses.map((a) => toA12(a.row, a.col));
88257
88475
  }
88258
88476
  async findByFormula(pattern) {
88259
88477
  const addresses = await findByFormula(this.ctx, this.sheetId, pattern);
88260
- return addresses.map((a) => toA1(a.row, a.col));
88478
+ return addresses.map((a) => toA12(a.row, a.col));
88261
88479
  }
88262
88480
  async regexSearch(patterns, options) {
88263
88481
  const results = await regexSearch(this.ctx, this.sheetId, patterns, {
@@ -88396,7 +88614,7 @@ var WorksheetImpl = class {
88396
88614
  await this.setRange(start.row, start.col, allRows);
88397
88615
  const endRow = start.row + allRows.length - 1;
88398
88616
  const endCol = start.col + headers.length - 1;
88399
- const rangeA1 = `${toA1(start.row, start.col)}:${toA1(endRow, endCol)}`;
88617
+ const rangeA1 = `${toA12(start.row, start.col)}:${toA12(endRow, endCol)}`;
88400
88618
  await this.tables.add(rangeA1, { name, hasHeaders: true });
88401
88619
  }
88402
88620
  // ===========================================================================
@@ -88789,6 +89007,9 @@ var WorksheetImpl = class {
88789
89007
  }
88790
89008
  return this._cellMetadata;
88791
89009
  }
89010
+ get changes() {
89011
+ return this._changes ??= new WorksheetChangesImpl(this.ctx, this.sheetId);
89012
+ }
88792
89013
  get formats() {
88793
89014
  return this._formats ??= new WorksheetFormatsImpl(this.ctx, this.sheetId);
88794
89015
  }
@@ -91122,6 +91343,31 @@ var WorkbookImpl = class {
91122
91343
  calculationSettings: calcSettings
91123
91344
  });
91124
91345
  }
91346
+ async getIterativeCalculation() {
91347
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91348
+ return settings.calculationSettings?.enableIterativeCalculation ?? false;
91349
+ }
91350
+ async setIterativeCalculation(enabled) {
91351
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91352
+ const calcSettings = { ...settings.calculationSettings ?? {}, enableIterativeCalculation: enabled };
91353
+ await this.ctx.computeBridge.patchWorkbookSettings({
91354
+ calculationSettings: calcSettings
91355
+ });
91356
+ }
91357
+ async setMaxIterations(n) {
91358
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91359
+ const calcSettings = { ...settings.calculationSettings ?? {}, maxIterations: n };
91360
+ await this.ctx.computeBridge.patchWorkbookSettings({
91361
+ calculationSettings: calcSettings
91362
+ });
91363
+ }
91364
+ async setConvergenceThreshold(threshold) {
91365
+ const settings = await this.ctx.computeBridge.getWorkbookSettings();
91366
+ const calcSettings = { ...settings.calculationSettings ?? {}, maxChange: threshold };
91367
+ await this.ctx.computeBridge.patchWorkbookSettings({
91368
+ calculationSettings: calcSettings
91369
+ });
91370
+ }
91125
91371
  async getUsePrecisionAsDisplayed() {
91126
91372
  const settings = await this.ctx.computeBridge.getWorkbookSettings();
91127
91373
  return !(settings.calculationSettings?.fullPrecision ?? true);
@@ -91281,7 +91527,7 @@ var WorkbookImpl = class {
91281
91527
  // Utilities (sync)
91282
91528
  // ===========================================================================
91283
91529
  indexToAddress(row, col) {
91284
- return toA1(row, col);
91530
+ return toA12(row, col);
91285
91531
  }
91286
91532
  addressToIndex(address) {
91287
91533
  const parsed = parseCellAddress(address);
@@ -91533,6 +91779,7 @@ var api_spec_default = {
91533
91779
  },
91534
91780
  ws: {
91535
91781
  smartArt: "WorksheetSmartArt",
91782
+ changes: "WorksheetChanges",
91536
91783
  formats: "WorksheetFormats",
91537
91784
  layout: "WorksheetLayout",
91538
91785
  view: "WorksheetView",
@@ -91644,6 +91891,26 @@ var api_spec_default = {
91644
91891
  docstring: "Set the calculation mode.\nConvenience mutator \u2014 patches `calculationSettings.calcMode`.",
91645
91892
  usedTypes: []
91646
91893
  },
91894
+ getIterativeCalculation: {
91895
+ signature: "getIterativeCalculation(): Promise<boolean>;",
91896
+ docstring: "Get whether iterative calculation is enabled for circular references.\nConvenience accessor \u2014 equivalent to `(await getSettings()).calculationSettings.enableIterativeCalculation`.",
91897
+ usedTypes: []
91898
+ },
91899
+ setIterativeCalculation: {
91900
+ signature: "setIterativeCalculation(enabled: boolean): Promise<void>;",
91901
+ docstring: "Set whether iterative calculation is enabled for circular references.\nConvenience mutator \u2014 patches `calculationSettings.enableIterativeCalculation`.",
91902
+ usedTypes: []
91903
+ },
91904
+ setMaxIterations: {
91905
+ signature: "setMaxIterations(n: number): Promise<void>;",
91906
+ docstring: "Set the maximum number of iterations for iterative calculation.\nConvenience mutator \u2014 patches `calculationSettings.maxIterations`.",
91907
+ usedTypes: []
91908
+ },
91909
+ setConvergenceThreshold: {
91910
+ signature: "setConvergenceThreshold(threshold: number): Promise<void>;",
91911
+ docstring: "Set the convergence threshold (maximum change) for iterative calculation.\nConvenience mutator \u2014 patches `calculationSettings.maxChange`.",
91912
+ usedTypes: []
91913
+ },
91647
91914
  getUsePrecisionAsDisplayed: {
91648
91915
  signature: "getUsePrecisionAsDisplayed(): Promise<boolean>;",
91649
91916
  docstring: "Whether to use displayed precision instead of full (15-digit) precision.\nConvenience accessor \u2014 inverted from `calculationSettings.fullPrecision`.",
@@ -91855,18 +92122,21 @@ var api_spec_default = {
91855
92122
  usedTypes: []
91856
92123
  },
91857
92124
  clearData: {
91858
- signature: "clearData(range: string): Promise<void>;",
92125
+ signature: "clearData(range: string): Promise<ClearResult>;",
91859
92126
  docstring: 'Clear all cell data (values and formulas) in a range (A1 notation, e.g. "A1:C3").',
91860
- usedTypes: []
92127
+ usedTypes: [
92128
+ "ClearResult"
92129
+ ]
91861
92130
  },
91862
92131
  clear: {
91863
- signature: "clear(range: string, applyTo?: ClearApplyTo): Promise<void>;",
92132
+ signature: "clear(range: string, applyTo?: ClearApplyTo): Promise<ClearResult>;",
91864
92133
  docstring: `Unified clear with mode selection (OfficeJS Range.clear equivalent).
91865
92134
 
91866
92135
  @param range - A1 range string (e.g. "A1:C3")
91867
92136
  @param applyTo - What to clear: 'all' (default), 'contents', 'formats', 'hyperlinks'`,
91868
92137
  usedTypes: [
91869
- "ClearApplyTo"
92138
+ "ClearApplyTo",
92139
+ "ClearResult"
91870
92140
  ]
91871
92141
  },
91872
92142
  getValue: {
@@ -92745,21 +93015,36 @@ var api_spec_default = {
92745
93015
  }
92746
93016
  }
92747
93017
  },
93018
+ WorksheetChanges: {
93019
+ docstring: "Sub-API for opt-in change tracking on a worksheet.",
93020
+ functions: {
93021
+ track: {
93022
+ signature: "track(options?: ChangeTrackOptions): ChangeTracker;",
93023
+ 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",
93024
+ usedTypes: [
93025
+ "ChangeTrackOptions",
93026
+ "ChangeTracker"
93027
+ ]
93028
+ }
93029
+ }
93030
+ },
92748
93031
  WorksheetFormats: {
92749
93032
  docstring: "Sub-API for cell formatting operations on a worksheet.",
92750
93033
  functions: {
92751
93034
  set: {
92752
- signature: "set(address: string, format: CellFormat): Promise<void>;",
93035
+ signature: "set(address: string, format: CellFormat): Promise<FormatChangeResult>;",
92753
93036
  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',
92754
93037
  usedTypes: [
92755
- "CellFormat"
93038
+ "CellFormat",
93039
+ "FormatChangeResult"
92756
93040
  ]
92757
93041
  },
92758
93042
  setRange: {
92759
- signature: "setRange(range: string, format: CellFormat): Promise<void>;",
93043
+ signature: "setRange(range: string, format: CellFormat): Promise<FormatChangeResult>;",
92760
93044
  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',
92761
93045
  usedTypes: [
92762
- "CellFormat"
93046
+ "CellFormat",
93047
+ "FormatChangeResult"
92763
93048
  ]
92764
93049
  },
92765
93050
  setRanges: {
@@ -92776,10 +93061,10 @@ var api_spec_default = {
92776
93061
  usedTypes: []
92777
93062
  },
92778
93063
  get: {
92779
- signature: "get(address: string): Promise<CellFormat | null>;",
92780
- 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",
93064
+ signature: "get(address: string): Promise<ResolvedCellFormat>;",
93065
+ 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)",
92781
93066
  usedTypes: [
92782
- "CellFormat"
93067
+ "ResolvedCellFormat"
92783
93068
  ]
92784
93069
  },
92785
93070
  adjustIndent: {
@@ -94906,6 +95191,11 @@ var api_spec_default = {
94906
95191
  definition: "'standard' | 'stacked' | 'percentStacked'",
94907
95192
  docstring: ""
94908
95193
  },
95194
+ AutoFillChange: {
95195
+ name: "AutoFillChange",
95196
+ definition: "{\n row: number;\n col: number;\n type: 'value' | 'formula' | 'format' | 'clear';\n}",
95197
+ docstring: "A single cell change produced by the fill engine."
95198
+ },
94909
95199
  AutoFillMode: {
94910
95200
  name: "AutoFillMode",
94911
95201
  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'",
@@ -94913,7 +95203,7 @@ var api_spec_default = {
94913
95203
  },
94914
95204
  AutoFillResult: {
94915
95205
  name: "AutoFillResult",
94916
- 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}",
95206
+ 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}",
94917
95207
  docstring: "Result from autoFill() \u2014 summary of what the fill engine did."
94918
95208
  },
94919
95209
  AutoFillWarning: {
@@ -95260,6 +95550,37 @@ Example: { ignoreError: true } to suppress error indicators. */
95260
95550
  definition: "{\n /** If true, value is treated as a formula (prefixed with =) */\n asFormula?: boolean;\n}",
95261
95551
  docstring: "Options controlling how a cell value is interpreted when written."
95262
95552
  },
95553
+ ChangeOrigin: {
95554
+ name: "ChangeOrigin",
95555
+ definition: "'direct' | 'cascade' | 'remote'",
95556
+ docstring: "Origin of a change: direct write, formula recalculation, or remote collaborator."
95557
+ },
95558
+ ChangeRecord: {
95559
+ name: "ChangeRecord",
95560
+ definition: `{
95561
+ /** Cell address in A1 notation (e.g. "B1"). */
95562
+ address: string;
95563
+ /** 0-based row index. */
95564
+ row: number;
95565
+ /** 0-based column index. */
95566
+ col: number;
95567
+ /** What caused this change. */
95568
+ origin: ChangeOrigin;
95569
+ /** Type of change. */
95570
+ type: 'modified';
95571
+ }`,
95572
+ 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)"
95573
+ },
95574
+ ChangeTrackOptions: {
95575
+ name: "ChangeTrackOptions",
95576
+ 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}',
95577
+ docstring: "Options for creating a change tracker."
95578
+ },
95579
+ ChangeTracker: {
95580
+ name: "ChangeTracker",
95581
+ 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}",
95582
+ docstring: "A handle that accumulates change records across mutations."
95583
+ },
95263
95584
  Chart: {
95264
95585
  name: "Chart",
95265
95586
  definition: "{\n id: string;\n sheetId?: string;\n createdAt?: number;\n updatedAt?: number;\n}",
@@ -95394,6 +95715,11 @@ that are stored on the chart but not part of the core config schema. */
95394
95715
  definition: "'all' | 'contents' | 'formats' | 'hyperlinks'",
95395
95716
  docstring: "Determines which aspects of a range to clear.\nMatches OfficeJS Excel.ClearApplyTo enum."
95396
95717
  },
95718
+ ClearResult: {
95719
+ name: "ClearResult",
95720
+ definition: "{\n /** Number of cells in the cleared range. */\n cellCount: number;\n}",
95721
+ docstring: "Confirmation returned by clearData() and clear()."
95722
+ },
95397
95723
  CodeResult: {
95398
95724
  name: "CodeResult",
95399
95725
  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}",
@@ -95607,6 +95933,11 @@ Used in condition filters where users specify rules like
95607
95933
  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'",
95608
95934
  docstring: "Type discriminator for floating objects. Superset of Rust FloatingObjectKind (12 variants) + legacy TS-only 'wordart'."
95609
95935
  },
95936
+ FormatChangeResult: {
95937
+ name: "FormatChangeResult",
95938
+ definition: "{\n /** Number of cells whose formatting was changed */\n cellCount: number;\n}",
95939
+ docstring: "Result of a format set/setRange operation."
95940
+ },
95610
95941
  FormatEntry: {
95611
95942
  name: "FormatEntry",
95612
95943
  definition: '{\n /** Cell value descriptor */\n value: { type: string; value?: unknown };\n /** Number format code (e.g., "#,##0.00") */\n formatCode: string;\n}',
@@ -95975,6 +96306,11 @@ Used in condition filters where users specify rules like
95975
96306
  definition: "{\n /** Number of duplicate rows removed */\n removedCount: number;\n /** Number of unique rows remaining */\n remainingCount: number;\n}",
95976
96307
  docstring: "Result of a remove-duplicates operation."
95977
96308
  },
96309
+ ResolvedCellFormat: {
96310
+ name: "ResolvedCellFormat",
96311
+ definition: "{\n [K in keyof CellFormat]-?: CellFormat[K] | null;\n}",
96312
+ docstring: "Dense cell format where every property is explicitly present (null when unset). Returned by formats.get()."
96313
+ },
95978
96314
  RichTextSegment: {
95979
96315
  name: "RichTextSegment",
95980
96316
  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}",
@@ -96055,7 +96391,7 @@ Used in condition filters where users specify rules like
96055
96391
  },
96056
96392
  SetCellsResult: {
96057
96393
  name: "SetCellsResult",
96058
- 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}",
96394
+ 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}",
96059
96395
  docstring: "Result of a bulk setCells() operation."
96060
96396
  },
96061
96397
  ShadowAlignment: {
@@ -96459,8 +96795,7 @@ Used in condition filters where users specify rules like
96459
96795
  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}",
96460
96796
  docstring: "A summary snapshot of the entire workbook state."
96461
96797
  }
96462
- },
96463
- generated: "2026-04-02T22:03:24.772Z"
96798
+ }
96464
96799
  };
96465
96800
 
96466
96801
  // src/api-describe.ts