@ai-matrx/office 0.8.13 → 0.8.15

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.
@@ -7,8 +7,8 @@ import { electCollabHost, remoteOriginOf, REMOTE_PARAM_TAG } from "@ai-matrx/dat
7
7
 
8
8
  // src/univer/collab/covered.ts
9
9
  var COLLAB_COVERED_KEY = "__matrxCollabCovered";
10
- function stampCovered(snapshot, covered) {
11
- return { ...snapshot, [COLLAB_COVERED_KEY]: [...covered] };
10
+ function stampCovered(snapshot, covered2) {
11
+ return { ...snapshot, [COLLAB_COVERED_KEY]: [...covered2] };
12
12
  }
13
13
  function takeCovered(snapshot) {
14
14
  if (!snapshot || typeof snapshot !== "object" || !(COLLAB_COVERED_KEY in snapshot)) {
@@ -148,10 +148,10 @@ var WorkbookCollabSession = class {
148
148
  */
149
149
  coveredNow() {
150
150
  if (!this.doc) return [];
151
- const covered = this.options.base?.covered();
151
+ const covered2 = this.options.base?.covered();
152
152
  const out = [];
153
153
  for (const op of this.doc.getArray(MUTATIONS_ARRAY_KEY).toArray()) {
154
- if (op.eid && (this.applied.has(op.eid) || covered?.has(op.eid))) out.push(op.eid);
154
+ if (op.eid && (this.applied.has(op.eid) || covered2?.has(op.eid))) out.push(op.eid);
155
155
  }
156
156
  return out;
157
157
  }
@@ -161,11 +161,11 @@ var WorkbookCollabSession = class {
161
161
  * by position — an entry that arrived while the save was in flight is not in the snapshot and stays.
162
162
  * Only the elected saver calls this; peers receive it as a delete (never replayed).
163
163
  */
164
- checkpoint(snapshotId, covered) {
164
+ checkpoint(snapshotId, covered2) {
165
165
  if (!this.doc) return;
166
166
  const yArray = this.doc.getArray(MUTATIONS_ARRAY_KEY);
167
167
  const control = this.doc.getMap(CONTROL_MAP_KEY);
168
- const drop = new Set(covered);
168
+ const drop = new Set(covered2);
169
169
  const signal = { snapshotId, by: this.options.clientId };
170
170
  this.doc.transact(() => {
171
171
  const entries = yArray.toArray();
@@ -289,10 +289,10 @@ var WorkbookCollabSession = class {
289
289
  return;
290
290
  }
291
291
  }
292
- const covered = base?.covered();
292
+ const covered2 = base?.covered();
293
293
  for (const op of entries) {
294
294
  if (op.eid) {
295
- if (this.applied.has(op.eid) || covered?.has(op.eid)) continue;
295
+ if (this.applied.has(op.eid) || covered2?.has(op.eid)) continue;
296
296
  this.applied.add(op.eid);
297
297
  } else {
298
298
  if (this.appliedRefs.has(op)) continue;
@@ -431,13 +431,13 @@ function dropEmptyStyleRetains(op) {
431
431
  e: v.e.map((a) => {
432
432
  const b = a.body;
433
433
  if (a.t !== "r" || !b || a.coverType === 1) return a;
434
- const runs = (b.textRuns ?? []).filter((r) => r.ts && Object.keys(r.ts).length);
434
+ const runs2 = (b.textRuns ?? []).filter((r) => r.ts && Object.keys(r.ts).length);
435
435
  const other = Object.keys(b).filter(
436
436
  (k) => k !== "textRuns" && k !== "dataStream" && !(Array.isArray(b[k]) && b[k].length === 0)
437
437
  );
438
- if (!runs.length && !other.length && !b.dataStream && !a.rangeUpdates?.length) return { t: "r", len: a.len };
439
- if (b.textRuns === void 0 || runs.length === b.textRuns.length) return a;
440
- return { ...a, body: { ...b, textRuns: runs } };
438
+ if (!runs2.length && !other.length && !b.dataStream && !a.rangeUpdates?.length) return { t: "r", len: a.len };
439
+ if (b.textRuns === void 0 || runs2.length === b.textRuns.length) return a;
440
+ return { ...a, body: { ...b, textRuns: runs2 } };
441
441
  })
442
442
  };
443
443
  }
@@ -761,23 +761,23 @@ function transformTextX(xIn, yIn, side, lost = []) {
761
761
  const yIds = valueIds(y);
762
762
  const conflicts = new Set([...valueIds(x)].filter((id) => yIds.has(id)));
763
763
  const X = new It(conflicts.size && !xLeft ? withoutValueRangeMetadata(x, conflicts) : x);
764
- const Y3 = new It(conflicts.size && xLeft ? withoutValueRangeMetadata(y, conflicts) : y);
764
+ const Y4 = new It(conflicts.size && xLeft ? withoutValueRangeMetadata(y, conflicts) : y);
765
765
  const decos = addedDecorations(y).map((d) => ({ ...d, pieces: [] }));
766
766
  const out = [];
767
767
  let inPos = 0;
768
768
  let outPos = 0;
769
- while (X.hasNext() || Y3.hasNext()) {
770
- if (X.peekType() === "i" && (xLeft || Y3.peekType() !== "i")) {
769
+ while (X.hasNext() || Y4.hasNext()) {
770
+ if (X.peekType() === "i" && (xLeft || Y4.peekType() !== "i")) {
771
771
  const a = X.next();
772
- if (Y3.inZone()) {
772
+ if (Y4.inZone()) {
773
773
  lost.push({ rule: "R1", side: "insert", len: a.len, ...a.body?.dataStream !== void 0 ? { text: a.body.dataStream } : {} });
774
774
  continue;
775
775
  }
776
776
  if (a.valueRangeId && conflicts.has(a.valueRangeId) && !xLeft) continue;
777
777
  push(out, a);
778
778
  outPos += a.len;
779
- } else if (Y3.peekType() === "i") {
780
- const b = Y3.next();
779
+ } else if (Y4.peekType() === "i") {
780
+ const b = Y4.next();
781
781
  if (X.inZone()) {
782
782
  push(out, { t: "d", len: b.len, tz: [[0, b.len - 1]] });
783
783
  lost.push({ rule: "R1", side: "delete", len: b.len, ...b.body?.dataStream !== void 0 ? { text: b.body.dataStream } : {} });
@@ -791,9 +791,9 @@ function transformTextX(xIn, yIn, side, lost = []) {
791
791
  }
792
792
  inPos += b.len;
793
793
  } else {
794
- const len = Math.min(X.peekLength(), Y3.peekLength());
794
+ const len = Math.min(X.peekLength(), Y4.peekLength());
795
795
  const a = X.next(len);
796
- const b = Y3.next(len);
796
+ const b = Y4.next(len);
797
797
  if (b.t === "d") continue;
798
798
  if (a.t === "d") {
799
799
  push(out, a);
@@ -888,9 +888,9 @@ function sortDeep(v) {
888
888
  return v;
889
889
  }
890
890
  var sameTs = (a, b) => JSON.stringify(sortDeep(a ?? {})) === JSON.stringify(sortDeep(b ?? {}));
891
- function canonicalRuns(runs) {
891
+ function canonicalRuns(runs2) {
892
892
  const out = [];
893
- for (const r of [...runs ?? []].sort((x, y) => x.st - y.st)) {
893
+ for (const r of [...runs2 ?? []].sort((x, y) => x.st - y.st)) {
894
894
  if (r.ed <= r.st) continue;
895
895
  const ts = sortDeep(r.ts ?? {});
896
896
  if (Object.keys(ts).length === 0) continue;
@@ -1002,25 +1002,25 @@ function rebaseUndoStack(items, remote) {
1002
1002
  let dropped = 0;
1003
1003
  for (let i = items.length - 1; i >= 0; i--) {
1004
1004
  const item = items[i];
1005
- let ok = true;
1005
+ let ok2 = true;
1006
1006
  for (const list of [item.undoMutations, item.redoMutations]) {
1007
1007
  for (const m of list ?? []) {
1008
1008
  if (m.id !== RICH_TEXT_EDITING) continue;
1009
1009
  try {
1010
1010
  if (touchesPageSetup(m.params.actions) && touchesPageSetup(remote)) throw new Error("page setup");
1011
1011
  const r = transformDocsOp(m.params.actions, remote, "left");
1012
- if (isNoopDocsOp(r.op)) ok = false;
1012
+ if (isNoopDocsOp(r.op)) ok2 = false;
1013
1013
  else {
1014
1014
  m.params = { ...m.params, actions: r.op };
1015
1015
  delete m.params.textRanges;
1016
1016
  delete m.params.layoutState;
1017
1017
  }
1018
1018
  } catch {
1019
- ok = false;
1019
+ ok2 = false;
1020
1020
  }
1021
1021
  }
1022
1022
  }
1023
- if (!ok) {
1023
+ if (!ok2) {
1024
1024
  items.splice(i, 1);
1025
1025
  dropped++;
1026
1026
  }
@@ -1550,6 +1550,1902 @@ async function restoreDocumentSnapshot(args, deps = {}) {
1550
1550
  const row = await d.saveRow(args);
1551
1551
  return { via: "saved", snapshotId: row.id };
1552
1552
  }
1553
+
1554
+ // src/univer/collab/sheets-ot/room.ts
1555
+ import { openOpSession as openOpSession2 } from "@ai-matrx/data/realtime/collab";
1556
+
1557
+ // src/collab/sheets/transform/types.ts
1558
+ var isBarrier = (r) => r.barrier === true;
1559
+
1560
+ // src/collab/sheets/transform/registry.ts
1561
+ var covered = (family, ...allow) => ({ kind: "covered", family, allow: ["subUnitId", ...allow] });
1562
+ var never = (reason) => ({ kind: "never-travels", reason });
1563
+ var barrier = (until, reason) => ({ kind: "barrier", until, reason });
1564
+ var FORMULA_RESULT = "formula engine output; every seat computes it (dropped at capture)";
1565
+ var RESOURCE = "ranged resource keyed by id; C5c";
1566
+ var UNIVER_COMMENTS = "Univer's own thread-comment store; our comments anchor elsewhere (design \xA78)";
1567
+ var SHEET_MUTATIONS = {
1568
+ // ── covered (C5a) ────────────────────────────────────────────────────────────────────────────────
1569
+ "sheet.mutation.set-range-values": covered("cell", "cellValue", "refSheets", "derived"),
1570
+ "sheet.mutation.insert-row": covered("structure", "range", "rowInfo"),
1571
+ "sheet.mutation.remove-rows": covered("structure", "range"),
1572
+ "sheet.mutation.insert-col": covered("structure", "range", "colInfo"),
1573
+ "sheet.mutation.remove-col": covered("structure", "range"),
1574
+ "sheet.mutation.move-rows": covered("structure", "sourceRange", "targetRange"),
1575
+ "sheet.mutation.move-columns": covered("structure", "sourceRange", "targetRange"),
1576
+ "sheet.mutation.add-worksheet-merge": covered("merge", "ranges"),
1577
+ "sheet.mutation.remove-worksheet-merge": covered("merge", "ranges"),
1578
+ "sheet.mutation.set-worksheet-row-height": covered("size", "ranges", "rowHeight"),
1579
+ "sheet.mutation.set-worksheet-row-is-auto-height": covered("size", "ranges", "autoHeightInfo"),
1580
+ "sheet.mutation.set-worksheet-row-auto-height": covered("size", "rowsAutoHeightInfo"),
1581
+ "sheet.mutation.set-worksheet-col-width": covered("size", "ranges", "colWidth"),
1582
+ "sheet.mutation.set-worksheet-name": covered("name", "name"),
1583
+ // ── never travels ────────────────────────────────────────────────────────────────────────────────
1584
+ "formula.mutation.set-formula-calculation-start": never(FORMULA_RESULT),
1585
+ "formula.mutation.set-trigger-formula-calculation-start": never(FORMULA_RESULT),
1586
+ "formula.mutation.set-formula-calculation-stop": never(FORMULA_RESULT),
1587
+ "formula.mutation.set-formula-calculation-notification": never(FORMULA_RESULT),
1588
+ "formula.mutation.set-formula-calculation-result": never(FORMULA_RESULT),
1589
+ "formula.mutation.set-array-formula-data": never(FORMULA_RESULT),
1590
+ "formula.mutation.set-formula-data": never(FORMULA_RESULT),
1591
+ "formula.mutation.set-image-formula-data": never(FORMULA_RESULT),
1592
+ "formula.mutation.set-formula-string-batch-calculation": never(FORMULA_RESULT),
1593
+ "formula.mutation.set-formula-string-batch-calculation-result": never(FORMULA_RESULT),
1594
+ "formula.mutation.set-formula-dependency-calculation": never(FORMULA_RESULT),
1595
+ "formula.mutation.set-formula-dependency-calculation-result": never(FORMULA_RESULT),
1596
+ "formula.mutation.set-cell-formula-dependency-calculation": never(FORMULA_RESULT),
1597
+ "formula.mutation.set-cell-formula-dependency-calculation-result": never(FORMULA_RESULT),
1598
+ "formula.mutation.set-query-formula-dependency": never(FORMULA_RESULT),
1599
+ "formula.mutation.set-query-formula-dependency-result": never(FORMULA_RESULT),
1600
+ "formula.mutation.set-query-formula-dependency-all": never(FORMULA_RESULT),
1601
+ "formula.mutation.set-query-formula-dependency-all-result": never(FORMULA_RESULT),
1602
+ "formula.mutation.register-function": never("registers a function body on this seat's engine"),
1603
+ "sheet.mutation.data-validation-formula-mark-dirty": never("dirty mark"),
1604
+ "sheet.mutation.mark-dirty-filter-change": never("dirty mark"),
1605
+ "sheet.mutation.re-calc-filter": never("filter recalculation result"),
1606
+ "sheet.mutation.toggle-note-popup": never("popup state"),
1607
+ "sheet.operation.clear-drawing-transformer": never("drawing selection handles (declared as a mutation)"),
1608
+ "sheet.mutation.copy-worksheet-end": never("end marker of a copy; the copy travels as insert-sheet"),
1609
+ "sheet.mutation.empty": never("no content"),
1610
+ "thread-comment.mutation.add-comment": never(UNIVER_COMMENTS),
1611
+ "thread-comment.mutation.update-comment": never(UNIVER_COMMENTS),
1612
+ "thread-comment.mutation.update-comment-ref": never(UNIVER_COMMENTS),
1613
+ "thread-comment.mutation.resolve-comment": never(UNIVER_COMMENTS),
1614
+ "thread-comment.mutation.delete-comment": never(UNIVER_COMMENTS),
1615
+ // ── barriers: X (no transform yet, design §10) ───────────────────────────────────────────────────
1616
+ "sheet.mutation.reorder-range": barrier("X", "sort: a permutation, not transformed yet"),
1617
+ "sheet.mutation.set-worksheet-row-count": barrier("X", "absolute row count; needs delta semantics"),
1618
+ "sheet.mutation.set-worksheet-column-count": barrier("X", "absolute column count; needs delta semantics"),
1619
+ "sheet.mutation.set-worksheet-order": barrier("X", "absolute sheet order; needs move semantics"),
1620
+ "sheet.mutation.move-range": barrier("X", "cut-paste carries the sender's cell matrices"),
1621
+ "sheet.mutation.insert-sheet": barrier("X", "sheet add: not in C5a"),
1622
+ "sheet.mutation.remove-sheet": barrier("X", "sheet remove: not in C5a"),
1623
+ "sheet.mutation.set-worksheet-hidden": barrier("X", "sheet-level setting: not in C5a"),
1624
+ "sheet.mutation.set-tab-color": barrier("X", "sheet-level setting: not in C5a"),
1625
+ "sheet.mutation.set-workbook-name": barrier("X", "workbook-level setting: not in C5a"),
1626
+ "sheet.mutation.set-worksheet-right-to-left": barrier("X", "sheet-level setting: not in C5a"),
1627
+ "sheet.mutation.toggle-gridlines": barrier("X", "sheet-level setting: not in C5a"),
1628
+ "sheet.mutation.set-gridlines-color": barrier("X", "sheet-level setting: not in C5a"),
1629
+ "sheet.mutation.set-worksheet-default-style": barrier("X", "sheet-level setting: not in C5a"),
1630
+ "sheet.mutation.set-frozen": barrier("X", "absolute frozen indices: not in C5a"),
1631
+ "sheet.mutation.set-row-data": barrier("X", "row properties by index: not in C5a"),
1632
+ "sheet.mutation.set-col-data": barrier("X", "column properties by index: not in C5a"),
1633
+ "sheet.mutation.set-row-hidden": barrier("X", "row visibility: not in C5a"),
1634
+ "sheet.mutation.set-row-visible": barrier("X", "row visibility: not in C5a"),
1635
+ "sheet.mutation.set-col-hidden": barrier("X", "column visibility: not in C5a"),
1636
+ "sheet.mutation.set-col-visible": barrier("X", "column visibility: not in C5a"),
1637
+ "sheet.mutation.set.numfmt": barrier("X", "number formats by range: not in C5a"),
1638
+ "sheet.mutation.remove.numfmt": barrier("X", "number formats by range: not in C5a"),
1639
+ "sheet.mutation.add-range-protection": barrier("X", "permissions: not in C5a"),
1640
+ "sheet.mutation.set-range-protection": barrier("X", "permissions: not in C5a"),
1641
+ "sheet.mutation.delete-range-protection": barrier("X", "permissions: not in C5a"),
1642
+ "sheet.mutation.add-worksheet-protection": barrier("X", "permissions: not in C5a"),
1643
+ "sheet.mutation.set-worksheet-protection": barrier("X", "permissions: not in C5a"),
1644
+ "sheet.mutation.delete-worksheet-protection": barrier("X", "permissions: not in C5a"),
1645
+ "sheet.mutation.set-worksheet-permission-points": barrier("X", "permissions: not in C5a"),
1646
+ // ── formulas (C5b) ───────────────────────────────────────────────────────────────────────────────
1647
+ "formula.mutation.set-defined-name": covered("defname", "id", "name", "formulaOrRefString", "formulaOrRefStringWithPrefix", "comment", "localSheetId", "hidden", "refSheets", "previousName", "derived"),
1648
+ "formula.mutation.remove-defined-name": covered("defname", "id", "name"),
1649
+ "formula.mutation.set-feature-calculation": barrier("X", "a plugin's registered calculation (feature id + dependency ranges); no transform yet"),
1650
+ "formula.mutation.remove-feature-calculation": barrier("X", "a plugin's registered calculation; no transform yet"),
1651
+ "formula.mutation.set-other-formula": barrier("C5c", "formulas owned by conditional formats and data validation travel with their rule"),
1652
+ "formula.mutation.remove-other-formula": barrier("C5c", "formulas owned by conditional formats and data validation travel with their rule"),
1653
+ "formula.mutation.set-super-table": barrier("C5c", "table names in structured references belong to tables (C5c)"),
1654
+ "formula.mutation.remove-super-table": barrier("C5c", "table names in structured references belong to tables (C5c)"),
1655
+ "formula.mutation.set-super-table-option": barrier("C5c", "table names in structured references belong to tables (C5c)"),
1656
+ // ── barriers until C5c (ranged resources) ────────────────────────────────────────────────────────
1657
+ "sheet.mutation.add-conditional-rule": barrier("C5c", RESOURCE),
1658
+ "sheet.mutation.set-conditional-rule": barrier("C5c", RESOURCE),
1659
+ "sheet.mutation.delete-conditional-rule": barrier("C5c", RESOURCE),
1660
+ "sheet.mutation.move-conditional-rule": barrier("C5c", "conditional-format priority (ordered list)"),
1661
+ "data-validation.mutation.addRule": barrier("C5c", RESOURCE),
1662
+ "data-validation.mutation.updateRule": barrier("C5c", RESOURCE),
1663
+ "data-validation.mutation.removeRule": barrier("C5c", RESOURCE),
1664
+ "sheet.mutation.set-filter-range": barrier("C5c", RESOURCE),
1665
+ "sheet.mutation.set-filter-criteria": barrier("C5c", RESOURCE),
1666
+ "sheet.mutation.remove-filter": barrier("C5c", RESOURCE),
1667
+ "sheet.mutation.add-table": barrier("C5c", RESOURCE),
1668
+ "sheet.mutation.delete-table": barrier("C5c", RESOURCE),
1669
+ "sheet.mutation.set-sheet-table": barrier("C5c", RESOURCE),
1670
+ "sheet.mutation.set-table-filter": barrier("C5c", RESOURCE),
1671
+ "sheet.mutation.move-table": barrier("C5c", RESOURCE),
1672
+ "sheets.mutation.add-hyper-link": barrier("C5c", RESOURCE),
1673
+ "sheets.mutation.remove-hyper-link": barrier("C5c", RESOURCE),
1674
+ "sheets.mutation.update-hyper-link": barrier("C5c", RESOURCE),
1675
+ "sheets.mutation.update-hyper-link-ref": barrier("C5c", RESOURCE),
1676
+ "sheets.mutation.update-rich-hyper-link": barrier("C5c", RESOURCE),
1677
+ "sheet.mutation.update-note": barrier("C5c", RESOURCE),
1678
+ "sheet.mutation.remove-note": barrier("C5c", RESOURCE),
1679
+ "sheet.mutation.update-note-position": barrier("C5c", RESOURCE),
1680
+ "sheet.mutation.set-drawing-apply": barrier("C5c", RESOURCE),
1681
+ "sheet.mutation.set-worksheet-background-image": barrier("C5c", RESOURCE),
1682
+ "sheet.mutation.add-range-theme": barrier("C5c", RESOURCE),
1683
+ "sheet.mutation.set-range-theme": barrier("C5c", RESOURCE),
1684
+ "sheet.mutation.remove-range-theme": barrier("C5c", RESOURCE),
1685
+ "sheet.mutation.set-worksheet-range-theme-style": barrier("C5c", RESOURCE),
1686
+ "sheet.mutation.remove-worksheet-range-theme-style": barrier("C5c", RESOURCE),
1687
+ "sheet.mutation.register-worksheet-range-theme-style": barrier("C5c", RESOURCE),
1688
+ "sheet.mutation.unregister-worksheet-range-theme-style": barrier("C5c", RESOURCE)
1689
+ };
1690
+ function allowParams(id, params) {
1691
+ const entry = SHEET_MUTATIONS[id];
1692
+ if (!entry || entry.kind !== "covered") return null;
1693
+ const out = {};
1694
+ for (const f of entry.allow) if (params[f] !== void 0) out[f] = params[f];
1695
+ return out;
1696
+ }
1697
+
1698
+ // src/collab/sheets/transform/transform.ts
1699
+ import { adjustRangeOnMutation } from "@univerjs/sheets";
1700
+
1701
+ // src/collab/sheets/transform/axis.ts
1702
+ function isNoopMove(op) {
1703
+ return op.count <= 0 || op.to >= op.from && op.to <= op.from + op.count;
1704
+ }
1705
+ function movedBlockStart(op) {
1706
+ return op.to > op.from ? op.to - op.count : op.to;
1707
+ }
1708
+ function mapIndex(op, i) {
1709
+ switch (op.kind) {
1710
+ case "insert":
1711
+ return i >= op.at ? i + op.count : i;
1712
+ case "remove":
1713
+ if (i < op.start) return i;
1714
+ if (i < op.start + op.count) return null;
1715
+ return i - op.count;
1716
+ case "move": {
1717
+ if (isNoopMove(op)) return i;
1718
+ const { from, count, to } = op;
1719
+ if (i >= from && i < from + count) return movedBlockStart(op) + (i - from);
1720
+ if (to > from) return i >= from + count && i < to ? i - count : i;
1721
+ return i >= to && i < from ? i + count : i;
1722
+ }
1723
+ }
1724
+ }
1725
+ function runs(indices) {
1726
+ const sorted = [...new Set(indices)].sort((a, b) => a - b);
1727
+ const out = [];
1728
+ for (const i of sorted) {
1729
+ const last = out[out.length - 1];
1730
+ if (last && last.start + last.count === i) last.count++;
1731
+ else out.push({ start: i, count: 1 });
1732
+ }
1733
+ return out;
1734
+ }
1735
+ function mapGapThroughMove(p, mv) {
1736
+ const { from, count, to } = mv;
1737
+ if (p > from && p < from + count) return movedBlockStart(mv) + (p - from);
1738
+ const g = p <= from ? p : p - count;
1739
+ const tg = to <= from ? to : to - count;
1740
+ return g <= tg ? g : g + count;
1741
+ }
1742
+ function transformAxis(x, y, side) {
1743
+ if (y.kind === "move" && isNoopMove(y)) return [x];
1744
+ if (x.kind === "move" && isNoopMove(x)) return [];
1745
+ switch (x.kind) {
1746
+ case "insert": {
1747
+ if (y.kind === "insert") {
1748
+ if (x.at < y.at || x.at === y.at && side === "left") return [x];
1749
+ return [{ ...x, at: x.at + y.count }];
1750
+ }
1751
+ if (y.kind === "remove") {
1752
+ if (x.at <= y.start) return [x];
1753
+ if (x.at >= y.start + y.count) return [{ ...x, at: x.at - y.count }];
1754
+ return [{ ...x, at: y.start }];
1755
+ }
1756
+ return [{ ...x, at: mapGapThroughMove(x.at, y) }];
1757
+ }
1758
+ case "remove": {
1759
+ const kept = [];
1760
+ for (let i = x.start; i < x.start + x.count; i++) {
1761
+ const m = mapIndex(y, i);
1762
+ if (m !== null) kept.push(m);
1763
+ }
1764
+ if (y.kind === "insert" || y.kind === "remove" || y.kind === "move") {
1765
+ return runs(kept).reverse().map((r) => ({ kind: "remove", start: r.start, count: r.count }));
1766
+ }
1767
+ return null;
1768
+ }
1769
+ case "move": {
1770
+ if (y.kind === "insert") {
1771
+ const inside = y.at > x.from && y.at < x.from + x.count;
1772
+ const from = inside || y.at > x.from ? x.from : x.from + y.count;
1773
+ const count = inside ? x.count + y.count : x.count;
1774
+ const to2 = x.to >= y.at ? x.to + y.count : x.to;
1775
+ const out2 = { kind: "move", from, count, to: to2 };
1776
+ return isNoopMove(out2) ? [] : [out2];
1777
+ }
1778
+ if (y.kind === "remove") {
1779
+ const kept = [];
1780
+ for (let i = x.from; i < x.from + x.count; i++) {
1781
+ const m = mapIndex(y, i);
1782
+ if (m !== null) kept.push(m);
1783
+ }
1784
+ if (kept.length === 0) return [];
1785
+ const r2 = runs(kept);
1786
+ if (r2.length !== 1) return null;
1787
+ const to2 = x.to <= y.start ? x.to : x.to >= y.start + y.count ? x.to - y.count : y.start;
1788
+ const out2 = { kind: "move", from: r2[0].start, count: r2[0].count, to: to2 };
1789
+ return isNoopMove(out2) ? [] : [out2];
1790
+ }
1791
+ const overlap = Math.min(x.from + x.count, y.from + y.count) - Math.max(x.from, y.from);
1792
+ if (overlap > 0) {
1793
+ if (x.from !== y.from || x.count !== y.count) return null;
1794
+ if (side === "right") return [];
1795
+ const out2 = { kind: "move", from: movedBlockStart(y), count: x.count, to: mapGapThroughMove(x.to, y) };
1796
+ return isNoopMove(out2) ? [] : [out2];
1797
+ }
1798
+ const mapped = [];
1799
+ for (let i = x.from; i < x.from + x.count; i++) mapped.push(mapIndex(y, i));
1800
+ const r = runs(mapped);
1801
+ if (r.length !== 1) return null;
1802
+ let to;
1803
+ if (x.to > y.from && x.to < y.from + y.count) to = movedBlockStart(y) + (x.to - y.from);
1804
+ else to = mapGapThroughMove(x.to, y) + (x.to === y.to && side === "right" ? y.count : 0);
1805
+ const out = { kind: "move", from: r[0].start, count: r[0].count, to };
1806
+ if (to > out.from && to < out.from + out.count) return null;
1807
+ return isNoopMove(out) ? [] : [out];
1808
+ }
1809
+ }
1810
+ }
1811
+
1812
+ // src/collab/sheets/transform/formula.ts
1813
+ import { Direction, RANGE_TYPE, Rectangle, getIntersectRange } from "@univerjs/core";
1814
+ import { LexerTreeBuilder, deserializeRangeWithSheet, generateStringWithSequence, sequenceNodeType, serializeRangeToRefString } from "@univerjs/engine-formula";
1815
+ import {
1816
+ EffectRefRangId,
1817
+ handleIRemoveCol,
1818
+ handleIRemoveRow,
1819
+ handleInsertCol,
1820
+ handleInsertRow,
1821
+ handleMoveCols,
1822
+ handleMoveRows,
1823
+ runRefRangeMutations
1824
+ } from "@univerjs/sheets";
1825
+ var REF_ERROR = "#REF!";
1826
+ var FULL = 16383 * 64;
1827
+ var lexer = null;
1828
+ var lex = (body) => (lexer ??= new LexerTreeBuilder()).sequenceNodesBuilder(body);
1829
+ var isFormulaText = (f) => typeof f === "string" && f.length > 1 && f.startsWith("=");
1830
+ var IDENT = /^[A-Za-z_\\][A-Za-z0-9_.\\]*$/;
1831
+ var ERROR_TOKEN = /^(?:[^!]+!)?#(?:REF!|NAME\?|VALUE!|DIV\/0!|N\/A|NUM!|NULL!|SPILL!|CALC!)$/i;
1832
+ function parse(text) {
1833
+ const prefix = text.startsWith("=") ? "=" : "";
1834
+ const nodes = lex(text.slice(prefix.length));
1835
+ if (!nodes) return "the formula lexer could not read the text";
1836
+ for (const n of nodes) {
1837
+ if (typeof n === "string") continue;
1838
+ if (n.nodeType === sequenceNodeType.TABLE || n.nodeType === sequenceNodeType.FUNCTION && n.token.includes("[")) return "a structured table reference (tables are C5c)";
1839
+ if (n.nodeType === sequenceNodeType.FUNCTION && !IDENT.test(n.token) && !ERROR_TOKEN.test(n.token))
1840
+ return `the lexer read "${n.token}" as one name (an intersection or a reference it cannot split)`;
1841
+ if (n.nodeType === sequenceNodeType.REFERENCE) {
1842
+ const d = deserializeRangeWithSheet(n.token);
1843
+ if (d.unitId) return "a reference into another workbook";
1844
+ }
1845
+ }
1846
+ return { prefix, nodes };
1847
+ }
1848
+ function targetSheet(sheetName, ctx) {
1849
+ if (!sheetName) return ctx.ownSheet;
1850
+ const id = ctx.refSheets?.[sheetName];
1851
+ if (id === void 0) return void 0;
1852
+ return id ?? "";
1853
+ }
1854
+ function formulaBarrier(text, ctx) {
1855
+ const p = parse(text);
1856
+ if (typeof p === "string") return p;
1857
+ for (const n of p.nodes) {
1858
+ if (typeof n === "string" || n.nodeType !== sequenceNodeType.REFERENCE) continue;
1859
+ const { sheetName } = deserializeRangeWithSheet(n.token);
1860
+ if (targetSheet(sheetName, ctx) === void 0) return `sheet "${sheetName}" is not in refSheets (capture must call annotateRefSheets)`;
1861
+ }
1862
+ return null;
1863
+ }
1864
+ function referencedSheetNames(text) {
1865
+ const p = parse(text);
1866
+ if (typeof p === "string") return [];
1867
+ const out = /* @__PURE__ */ new Set();
1868
+ for (const n of p.nodes) if (typeof n !== "string" && n.nodeType === sequenceNodeType.REFERENCE) {
1869
+ const { sheetName } = deserializeRangeWithSheet(n.token);
1870
+ if (sheetName) out.add(sheetName);
1871
+ }
1872
+ return [...out];
1873
+ }
1874
+ var fullRowsRange = (start, count) => ({ startRow: start, endRow: start + count - 1, startColumn: 0, endColumn: FULL, rangeType: RANGE_TYPE.ROW });
1875
+ var fullColsRange = (start, count) => ({ startRow: 0, endRow: FULL, startColumn: start, endColumn: start + count - 1, rangeType: RANGE_TYPE.COLUMN });
1876
+ var startV = (v) => Number.isNaN(v) || v == null ? -Infinity : v;
1877
+ var endV = (v) => Number.isNaN(v) || v == null ? Infinity : v;
1878
+ function startEnd(r) {
1879
+ return { ...r, startRow: startV(r.startRow), endRow: endV(r.endRow), startColumn: startV(r.startColumn), endColumn: endV(r.endColumn) };
1880
+ }
1881
+ function checkMoveEdge(origin, from) {
1882
+ const startRow = startV(origin.startRow), endRow = endV(origin.endRow), startColumn = startV(origin.startColumn), endColumn = endV(origin.endColumn);
1883
+ const fromStartRow = startV(from.startRow), fromEndRow = endV(from.endRow), fromStartColumn = startV(from.startColumn), fromEndColumn = endV(from.endColumn);
1884
+ const rowsCover = () => origin.rangeType === RANGE_TYPE.COLUMN && from.rangeType === RANGE_TYPE.COLUMN || startRow >= fromStartRow && endRow <= fromEndRow;
1885
+ const columnsCover = () => origin.rangeType === RANGE_TYPE.ROW && from.rangeType === RANGE_TYPE.ROW || startColumn >= fromStartColumn && endColumn <= fromEndColumn;
1886
+ const allCover = () => origin.rangeType === RANGE_TYPE.ALL && from.rangeType === RANGE_TYPE.ALL;
1887
+ if (rowsCover() && columnsCover() || allCover()) return 4;
1888
+ if (columnsCover() && startRow >= fromStartRow && startRow <= fromEndRow && endRow > fromEndRow) return 0;
1889
+ if (columnsCover() && endRow >= fromStartRow && endRow <= fromEndRow && startRow < fromStartRow) return 1;
1890
+ if (rowsCover() && startColumn >= fromStartColumn && startColumn <= fromEndColumn && endColumn > fromEndColumn) return 2;
1891
+ if (rowsCover() && endColumn >= fromStartColumn && endColumn <= fromEndColumn && startColumn < fromStartColumn) return 3;
1892
+ return null;
1893
+ }
1894
+ function getMoveNewRange(moveEdge, result, from, to, origin, remain) {
1895
+ const { startRow, endRow, startColumn, endColumn, rangeType } = startEnd(result);
1896
+ const f = startEnd(from);
1897
+ const fromRangeType = from.rangeType ?? RANGE_TYPE.NORMAL;
1898
+ const t = startEnd(to);
1899
+ const rm = startEnd(remain);
1900
+ const o = startEnd(origin);
1901
+ const originRangeType = origin.rangeType ?? RANGE_TYPE.NORMAL;
1902
+ const newRange = { ...origin };
1903
+ const rowsCover = () => rangeType === RANGE_TYPE.COLUMN && originRangeType === RANGE_TYPE.COLUMN || startColumn >= o.startColumn && endColumn <= o.endColumn;
1904
+ const columnsCover = () => rangeType === RANGE_TYPE.ROW && originRangeType === RANGE_TYPE.ROW || startRow >= o.startRow && endRow <= o.endRow;
1905
+ if (moveEdge === 0) {
1906
+ if (!rowsCover()) return void 0;
1907
+ if (startRow < o.startRow) newRange.startRow = startRow;
1908
+ else if (startRow >= o.endRow) newRange.endRow -= f.endRow + 1 - o.startRow;
1909
+ else return void 0;
1910
+ } else if (moveEdge === 1) {
1911
+ if (!rowsCover()) return void 0;
1912
+ if (endRow > o.endRow) newRange.endRow = endRow;
1913
+ else if (endRow <= o.startRow) newRange.startRow += o.endRow - f.startRow + 1;
1914
+ else return void 0;
1915
+ } else if (moveEdge === 2) {
1916
+ if (!columnsCover()) return void 0;
1917
+ if (startColumn < o.startColumn) newRange.startColumn = startColumn;
1918
+ else if (startColumn >= o.endColumn) newRange.endColumn -= f.endColumn + 1 - o.startColumn;
1919
+ else return void 0;
1920
+ } else if (moveEdge === 3) {
1921
+ if (!columnsCover()) return void 0;
1922
+ if (endColumn > o.endColumn) newRange.endColumn = endColumn;
1923
+ else if (endColumn <= o.startColumn) newRange.startColumn += o.endColumn - f.startColumn + 1;
1924
+ else return void 0;
1925
+ } else if (moveEdge === 4) {
1926
+ Object.assign(newRange, { startRow, startColumn, endRow, endColumn });
1927
+ } else if (f.startColumn <= o.startColumn && f.endColumn >= o.endColumn || fromRangeType === RANGE_TYPE.ROW && originRangeType === RANGE_TYPE.ROW) {
1928
+ const n = f.endRow - f.startRow + 1;
1929
+ if (from.endRow < o.startRow) {
1930
+ if (t.startRow >= o.startRow) newRange.startRow -= n;
1931
+ if (t.startRow >= o.endRow) newRange.endRow -= n;
1932
+ } else if (from.startRow > o.endRow) {
1933
+ if (t.endRow <= o.endRow) newRange.endRow += n;
1934
+ if (t.endRow <= o.startRow) newRange.startRow += n;
1935
+ } else if (from.startRow >= o.startRow && from.endRow <= o.endRow) {
1936
+ if (t.startRow <= o.startRow) newRange.startRow += n;
1937
+ else if (t.startRow >= o.endRow) newRange.endRow -= n;
1938
+ }
1939
+ } else if (f.startRow <= o.startRow && f.endRow >= o.endRow || fromRangeType === RANGE_TYPE.COLUMN && originRangeType === RANGE_TYPE.COLUMN) {
1940
+ const n = f.endColumn - f.startColumn + 1;
1941
+ if (from.endColumn < o.startColumn) {
1942
+ if (t.startColumn >= o.startColumn) newRange.startColumn -= n;
1943
+ if (t.startColumn >= o.endColumn) newRange.endColumn -= n;
1944
+ } else if (from.startColumn > o.endColumn) {
1945
+ if (t.endColumn <= o.endColumn) newRange.endColumn += n;
1946
+ if (t.endColumn <= o.startColumn) newRange.startColumn += n;
1947
+ } else if (from.startColumn >= o.startColumn && from.endColumn <= o.endColumn) {
1948
+ if (t.startColumn <= o.startColumn) newRange.startColumn += n;
1949
+ else if (t.startColumn >= o.endColumn) newRange.endColumn -= n;
1950
+ }
1951
+ } else {
1952
+ Object.assign(newRange, { startRow, startColumn, endRow, endColumn });
1953
+ void rm;
1954
+ }
1955
+ return newRange;
1956
+ }
1957
+ function moveRange(range, axis, op) {
1958
+ const isRow = axis === "row";
1959
+ if (op.kind === "insert") {
1960
+ const r = isRow ? fullRowsRange(op.at, op.count) : fullColsRange(op.at, op.count);
1961
+ const ops2 = isRow ? handleInsertRow({ id: EffectRefRangId.InsertRowCommandId, params: { range: r, unitId: "", subUnitId: "", direction: Direction.DOWN } }, range) : handleInsertCol({ id: EffectRefRangId.InsertColCommandId, params: { range: r, unitId: "", subUnitId: "", direction: Direction.RIGHT } }, range);
1962
+ const res2 = runRefRangeMutations(ops2, range);
1963
+ return res2 == null ? void 0 : { ...range, ...res2 };
1964
+ }
1965
+ if (op.kind === "remove") {
1966
+ const r = isRow ? fullRowsRange(op.start, op.count) : fullColsRange(op.start, op.count);
1967
+ const ops2 = isRow ? handleIRemoveRow({ id: EffectRefRangId.RemoveRowCommandId, params: { range: r } }, range, []) : handleIRemoveCol({ id: EffectRefRangId.RemoveColCommandId, params: { range: r } }, range);
1968
+ const res2 = runRefRangeMutations(ops2, range);
1969
+ return res2 == null ? REF_ERROR : { ...range, ...res2 };
1970
+ }
1971
+ const from = isRow ? fullRowsRange(op.from, op.count) : fullColsRange(op.from, op.count);
1972
+ const to = isRow ? fullRowsRange(op.to, op.count) : fullColsRange(op.to, op.count);
1973
+ const moveEdge = checkMoveEdge(range, from);
1974
+ let remain = getIntersectRange(range, from);
1975
+ if (isRow) {
1976
+ if (remain == null && (from.endRow < range.startRow && to.endRow <= range.startRow || from.startRow > range.endRow && to.startRow > range.endRow)) return void 0;
1977
+ } else if (remain == null && (from.endColumn < range.startColumn && to.endColumn <= range.startColumn || from.startColumn > range.endColumn && to.startColumn > range.endColumn)) return void 0;
1978
+ remain ??= { startRow: range.startRow, endRow: range.endRow, startColumn: range.startColumn, endColumn: range.endColumn, rangeType: RANGE_TYPE.NORMAL };
1979
+ const ops = isRow ? handleMoveRows({ id: EffectRefRangId.MoveRowsCommandId, params: { toRange: to, fromRange: from } }, remain) : handleMoveCols({ id: EffectRefRangId.MoveColsCommandId, params: { toRange: to, fromRange: from } }, remain);
1980
+ const res = runRefRangeMutations(ops, remain);
1981
+ if (res == null) return REF_ERROR;
1982
+ return getMoveNewRange(moveEdge, res, from, to, range, remain);
1983
+ }
1984
+ function rewriteFormula(text, ctx, change) {
1985
+ const p = parse(text);
1986
+ if (typeof p === "string") return p;
1987
+ const nodes = p.nodes.slice();
1988
+ const changedIds = [];
1989
+ for (let i = 0; i < nodes.length; i++) {
1990
+ const n = nodes[i];
1991
+ if (typeof n === "string") continue;
1992
+ if (change.kind === "defined-name") {
1993
+ if ((n.nodeType === sequenceNodeType.DEFINED_NAME || n.nodeType === sequenceNodeType.FUNCTION) && n.token === change.from) {
1994
+ nodes[i] = { ...n, token: change.to ?? REF_ERROR };
1995
+ changedIds.push(i);
1996
+ }
1997
+ continue;
1998
+ }
1999
+ if (n.nodeType !== sequenceNodeType.REFERENCE) continue;
2000
+ const { range, sheetName, unitId } = deserializeRangeWithSheet(n.token);
2001
+ const target = targetSheet(sheetName, ctx);
2002
+ if (target === void 0) return `sheet "${sheetName}" is not in refSheets (capture must call annotateRefSheets)`;
2003
+ if (target !== change.sheet) continue;
2004
+ let token;
2005
+ if (change.kind === "rename") {
2006
+ if (!sheetName) continue;
2007
+ token = serializeRangeToRefString({ range, sheetName: change.name, unitId });
2008
+ } else {
2009
+ const moved = moveRange(Rectangle.moveOffset(range, 0, 0), change.axis, change.op);
2010
+ if (moved === void 0) continue;
2011
+ token = moved === REF_ERROR ? REF_ERROR : serializeRangeToRefString({ range: moved, sheetName: target === ctx.ownSheet && !ctx.keepQualifier ? "" : sheetName, unitId });
2012
+ }
2013
+ nodes[i] = { ...n, token };
2014
+ changedIds.push(i);
2015
+ }
2016
+ if (!changedIds.length) return { text, changed: false };
2017
+ for (let i = 0; i < nodes.length; i++) {
2018
+ const n = nodes[i];
2019
+ if (typeof n === "string" || n.nodeType !== sequenceNodeType.REFERENCE || changedIds.includes(i)) continue;
2020
+ nodes[i] = { ...n, token: serializeRangeToRefString(deserializeRangeWithSheet(n.token)) };
2021
+ }
2022
+ const out = p.prefix + generateStringWithSequence(nodes);
2023
+ return { text: out, changed: out !== text };
2024
+ }
2025
+ function refSheetsAfter(refSheets, change) {
2026
+ if (change.kind !== "rename" || !refSheets) return refSheets;
2027
+ const entries = Object.entries(refSheets);
2028
+ if (!entries.some(([name, id]) => id === change.sheet || name === change.name)) return refSheets;
2029
+ const next = {};
2030
+ for (const [name, id] of entries) if (id !== change.sheet && name !== change.name) next[name] = id;
2031
+ next[change.name] = change.sheet;
2032
+ return next;
2033
+ }
2034
+ function refSheetsFor(texts, sheets) {
2035
+ const byName = new Map(Object.entries(sheets).map(([id, name]) => [name, id]));
2036
+ const out = {};
2037
+ for (const t of texts) for (const name of referencedSheetNames(t)) out[name] = byName.get(name) ?? null;
2038
+ return Object.keys(out).length ? out : void 0;
2039
+ }
2040
+
2041
+ // src/collab/sheets/transform/transform.ts
2042
+ var SHEET_TRANSFORMER_VERSION = "c5b-1";
2043
+ var ID = {
2044
+ values: "sheet.mutation.set-range-values",
2045
+ insertRow: "sheet.mutation.insert-row",
2046
+ removeRows: "sheet.mutation.remove-rows",
2047
+ insertCol: "sheet.mutation.insert-col",
2048
+ removeCol: "sheet.mutation.remove-col",
2049
+ moveRows: "sheet.mutation.move-rows",
2050
+ moveCols: "sheet.mutation.move-columns",
2051
+ addMerge: "sheet.mutation.add-worksheet-merge",
2052
+ removeMerge: "sheet.mutation.remove-worksheet-merge",
2053
+ rowHeight: "sheet.mutation.set-worksheet-row-height",
2054
+ rowIsAuto: "sheet.mutation.set-worksheet-row-is-auto-height",
2055
+ rowAutoHeight: "sheet.mutation.set-worksheet-row-auto-height",
2056
+ colWidth: "sheet.mutation.set-worksheet-col-width",
2057
+ name: "sheet.mutation.set-worksheet-name",
2058
+ setName: "formula.mutation.set-defined-name",
2059
+ removeName: "formula.mutation.remove-defined-name"
2060
+ };
2061
+ var PAIR_BARRIERS = {};
2062
+ var pairKey = (a, b) => a < b ? `${a}|${b}` : `${b}|${a}`;
2063
+ var barrier2 = (reason) => ({ barrier: true, reason });
2064
+ var ok = (op, lost = [], dropped = []) => ({ op, lost, dropped });
2065
+ var flip = (side) => side === "left" ? "right" : "left";
2066
+ var sheetOf = (m) => String(m.params.subUnitId ?? "");
2067
+ function colName(c) {
2068
+ let s = "";
2069
+ for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + (n - 1) % 26) + s;
2070
+ return s;
2071
+ }
2072
+ var cellRef = (sheet, row, col) => `${sheet}!${colName(col)}${row + 1}`;
2073
+ var rangeRef = (sheet, r) => `${sheet}!${colName(r.startColumn)}${r.startRow + 1}:${colName(r.endColumn)}${r.endRow + 1}`;
2074
+ function structuralOf(m) {
2075
+ const p = m.params;
2076
+ switch (m.id) {
2077
+ case ID.insertRow:
2078
+ return { axis: "row", op: { kind: "insert", at: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } };
2079
+ case ID.removeRows:
2080
+ return { axis: "row", op: { kind: "remove", start: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } };
2081
+ case ID.insertCol:
2082
+ return { axis: "col", op: { kind: "insert", at: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } };
2083
+ case ID.removeCol:
2084
+ return { axis: "col", op: { kind: "remove", start: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } };
2085
+ case ID.moveRows:
2086
+ return {
2087
+ axis: "row",
2088
+ op: { kind: "move", from: p.sourceRange.startRow, count: p.sourceRange.endRow - p.sourceRange.startRow + 1, to: p.targetRange.startRow }
2089
+ };
2090
+ case ID.moveCols:
2091
+ return {
2092
+ axis: "col",
2093
+ op: {
2094
+ kind: "move",
2095
+ from: p.sourceRange.startColumn,
2096
+ count: p.sourceRange.endColumn - p.sourceRange.startColumn + 1,
2097
+ to: p.targetRange.startColumn
2098
+ }
2099
+ };
2100
+ default:
2101
+ return null;
2102
+ }
2103
+ }
2104
+ var S = (axis) => axis === "row" ? ["startRow", "endRow"] : ["startColumn", "endColumn"];
2105
+ function buildStructural(template, axis, op) {
2106
+ const [a0, a1] = S(axis);
2107
+ const p = template.params;
2108
+ if (op.kind === "move") {
2109
+ const src = p.sourceRange;
2110
+ const tgt = p.targetRange;
2111
+ return {
2112
+ id: template.id,
2113
+ params: {
2114
+ ...p,
2115
+ sourceRange: { ...src, [a0]: op.from, [a1]: op.from + op.count - 1 },
2116
+ targetRange: { ...tgt, [a0]: op.to, [a1]: op.to + op.count - 1 }
2117
+ }
2118
+ };
2119
+ }
2120
+ const start = op.kind === "insert" ? op.at : op.start;
2121
+ return { id: template.id, params: { ...p, range: { ...p.range, [a0]: start, [a1]: start + op.count - 1 } } };
2122
+ }
2123
+ function univerMutationInfo(axis, op) {
2124
+ const FULL2 = { startRow: 0, endRow: Number.MAX_SAFE_INTEGER, startColumn: 0, endColumn: Number.MAX_SAFE_INTEGER };
2125
+ const start = op.kind === "insert" ? op.at : op.start;
2126
+ const range = axis === "row" ? { ...FULL2, startRow: start, endRow: start + op.count - 1 } : { ...FULL2, startColumn: start, endColumn: start + op.count - 1 };
2127
+ const id = op.kind === "insert" ? axis === "row" ? ID.insertRow : ID.insertCol : axis === "row" ? ID.removeRows : ID.removeCol;
2128
+ return { id, params: { unitId: "", subUnitId: "", range } };
2129
+ }
2130
+ var intersects = (a, b) => a.startRow <= b.endRow && b.startRow <= a.endRow && a.startColumn <= b.endColumn && b.startColumn <= a.endColumn;
2131
+ var isSingleCell = (r) => r.startRow === r.endRow && r.startColumn === r.endColumn;
2132
+ function mergeThrough(s, m) {
2133
+ const [a0, a1] = S(s.axis);
2134
+ const lo = m[a0];
2135
+ const hi = m[a1];
2136
+ const op = s.op;
2137
+ if (op.kind === "insert") {
2138
+ const fixup = lo < op.at && op.at <= hi;
2139
+ return { range: adjustRangeOnMutation(m, univerMutationInfo(s.axis, op)), fixup };
2140
+ }
2141
+ if (op.kind === "remove") {
2142
+ const e = op.start + op.count - 1;
2143
+ if (e < lo || op.start > hi) return { range: adjustRangeOnMutation(m, univerMutationInfo(s.axis, op)), fixup: false };
2144
+ if (op.start <= lo && e >= hi) return { range: null, fixup: true };
2145
+ const r = { ...m };
2146
+ if (op.start >= lo && e <= hi) r[a1] = hi - op.count;
2147
+ else if (op.start < lo) {
2148
+ r[a0] = op.start;
2149
+ r[a1] = hi - op.count;
2150
+ } else r[a1] = op.start - 1;
2151
+ return { range: isSingleCell(r) ? null : r, fixup: true };
2152
+ }
2153
+ const fe = op.from + op.count - 1;
2154
+ if (hi < op.from || lo > fe) {
2155
+ const r = { ...m };
2156
+ if (op.from < lo && op.to > hi) {
2157
+ r[a0] = lo - op.count;
2158
+ r[a1] = hi - op.count;
2159
+ } else if (op.from > hi && op.to <= lo) {
2160
+ r[a0] = lo + op.count;
2161
+ r[a1] = hi + op.count;
2162
+ }
2163
+ return { range: r, fixup: false };
2164
+ }
2165
+ if (lo >= op.from && hi <= fe) {
2166
+ const r = { ...m, [a0]: mapIndex(op, lo), [a1]: mapIndex(op, hi) };
2167
+ return { range: r, fixup: true };
2168
+ }
2169
+ return { range: m, fixup: false };
2170
+ }
2171
+ function exactMergeRemovals(group, merges) {
2172
+ const sim = new Map(Object.entries(merges).map(([k, v]) => [k, v.map((r) => ({ ...r }))]));
2173
+ const out = [];
2174
+ for (const m of group) {
2175
+ const sheet = sheetOf(m);
2176
+ const cur = sim.get(sheet) ?? [];
2177
+ if (m.id === ID.removeMerge) {
2178
+ const hit = cur.filter((q) => mergeRanges(m).some((r) => intersects(r, q)));
2179
+ sim.set(sheet, cur.filter((q) => !hit.includes(q)));
2180
+ if (hit.length) out.push(withRanges(m, hit.map((r) => ({ ...r }))));
2181
+ continue;
2182
+ }
2183
+ if (m.id === ID.addMerge) sim.set(sheet, [...cur, ...mergeRanges(m).map((r) => ({ ...r }))]);
2184
+ const st = structuralOf(m);
2185
+ if (st) sim.set(sheet, cur.map((q) => mergeThrough(st, q).range).filter((q) => q !== null));
2186
+ out.push(m);
2187
+ }
2188
+ return out;
2189
+ }
2190
+ var mergeRanges = (m) => m.params.ranges ?? [];
2191
+ var withRanges = (m, ranges) => ({ id: m.id, params: { ...m.params, ranges } });
2192
+ var mergeMutation = (id, sheet, ranges) => ({ id, params: { subUnitId: sheet, ranges } });
2193
+ var CONTENT_KEYS = ["v", "t", "p", "f", "si", "custom", "ref", "xf", "ft", "fd"];
2194
+ var CONTENT_TOUCH = ["v", "p", "f", "si", "custom", "ref", "xf", "ft", "fd"];
2195
+ var KNOWN_CELL_KEYS = /* @__PURE__ */ new Set([...CONTENT_KEYS, "s"]);
2196
+ function completeCellContent(entry, post) {
2197
+ if (entry === null) return null;
2198
+ if (!CONTENT_TOUCH.some((k) => k in entry)) return entry;
2199
+ const out = {};
2200
+ for (const k of CONTENT_KEYS) out[k] = post && post[k] !== void 0 ? post[k] : null;
2201
+ if (out.v === null) delete out.t;
2202
+ if ("s" in entry) out.s = entry.s;
2203
+ return out;
2204
+ }
2205
+ function cellsOf(m) {
2206
+ return m.params.cellValue ?? {};
2207
+ }
2208
+ function forEachCell(cells, fn) {
2209
+ for (const r of Object.keys(cells)) for (const c of Object.keys(cells[r] ?? {})) fn(Number(r), Number(c), cells[r][c] ?? null);
2210
+ }
2211
+ function cellsMutation(template, cells) {
2212
+ return { id: template.id, params: { ...template.params, cellValue: cells } };
2213
+ }
2214
+ function putCell(cells, r, c, v) {
2215
+ (cells[r] ??= {})[c] = v;
2216
+ }
2217
+ var isEmptyMatrix = (cells) => Object.values(cells).every((row) => Object.keys(row).length === 0);
2218
+ function cellBarrier(m) {
2219
+ if (m.params.isOverrideStyle) return "set-range-values with isOverrideStyle (whole-style replace) is not covered";
2220
+ let why = null;
2221
+ forEachCell(cellsOf(m), (_r, _c, v) => {
2222
+ if (why || v === null) return;
2223
+ for (const k of Object.keys(v)) {
2224
+ if (why) break;
2225
+ if (!KNOWN_CELL_KEYS.has(k)) why = `cell key "${k}" is not covered`;
2226
+ else if (k === "si" && v.si != null) why = "shared formula (si): its text lives in a master cell this op does not carry";
2227
+ else if (k === "f" && isFormulaText(v.f) || k === "ref" && typeof v.ref === "string") why = formulaBarrier(v[k], formulaCtx(m));
2228
+ }
2229
+ if (typeof v.s === "string") why = "a style id travels (style ids are seat-local; capture must send the style object)";
2230
+ if (!why && CONTENT_TOUCH.some((k) => k in v) && !CONTENT_KEYS.every((k) => k in v || k === "t" && v.v == null))
2231
+ why = "cell content is not completed (capture must call completeCellContent)";
2232
+ });
2233
+ return why;
2234
+ }
2235
+ var hasContent = (v) => CONTENT_TOUCH.some((k) => k in v);
2236
+ var contentOf = (v) => {
2237
+ const out = {};
2238
+ for (const k of Object.keys(v)) if (k !== "s") out[k] = v[k];
2239
+ return out;
2240
+ };
2241
+ var richText = (v) => v.p != null;
2242
+ function styleKeys(s) {
2243
+ const out = [];
2244
+ for (const k of Object.keys(s)) {
2245
+ if (k === "bd" && s.bd && typeof s.bd === "object") for (const side of Object.keys(s.bd)) out.push(`bd.${side}`);
2246
+ else out.push(k);
2247
+ }
2248
+ return out;
2249
+ }
2250
+ function withoutStyleKeys(s, drop) {
2251
+ const out = {};
2252
+ for (const k of Object.keys(s)) {
2253
+ if (k === "bd" && s.bd && typeof s.bd === "object") {
2254
+ const bd = {};
2255
+ for (const side of Object.keys(s.bd)) if (!drop.has(`bd.${side}`)) bd[side] = s.bd[side];
2256
+ if (Object.keys(bd).length) out.bd = bd;
2257
+ } else if (!drop.has(k)) out[k] = s[k];
2258
+ }
2259
+ return Object.keys(out).length ? out : null;
2260
+ }
2261
+ function transformCell(X, Y4, side) {
2262
+ if (X === null || Y4 === null) {
2263
+ if (side === "left") return { entries: [X], xLost: false, yLost: true };
2264
+ return X === null ? { entries: [null, Y4], xLost: true, yLost: false } : { entries: [], xLost: true, yLost: false };
2265
+ }
2266
+ if (hasContent(X) && richText(X) && "s" in Y4 || hasContent(Y4) && richText(Y4) && "s" in X)
2267
+ return "rich-text content concurrent with a style change on the same cell is not covered";
2268
+ const out = {};
2269
+ let xLost = false;
2270
+ let yLost = false;
2271
+ if (hasContent(X)) {
2272
+ if (!hasContent(Y4) || side === "left") Object.assign(out, contentOf(X));
2273
+ else xLost = true;
2274
+ if (hasContent(Y4) && side === "left") yLost = true;
2275
+ }
2276
+ const tail = [];
2277
+ if ("s" in X) {
2278
+ const xs = X.s;
2279
+ const ys = "s" in Y4 ? Y4.s : void 0;
2280
+ if (ys === void 0 || side === "left") {
2281
+ if (xs !== void 0) out.s = xs;
2282
+ if (ys !== void 0) yLost = true;
2283
+ } else if (ys === null) {
2284
+ xLost = true;
2285
+ } else if (xs === null) {
2286
+ out.s = null;
2287
+ tail.push({ s: ys });
2288
+ xLost = true;
2289
+ } else {
2290
+ const kept = withoutStyleKeys(xs, new Set(styleKeys(ys)));
2291
+ if (kept) out.s = kept;
2292
+ if (styleKeys(xs).length !== styleKeys(kept ?? {}).length) xLost = true;
2293
+ }
2294
+ }
2295
+ return { entries: Object.keys(out).length ? [out, ...tail] : tail, xLost, yLost };
2296
+ }
2297
+ function transformCellsOverCells(x, y, side) {
2298
+ if (sheetOf(x) !== sheetOf(y)) return ok([x]);
2299
+ const ycells = cellsOf(y);
2300
+ const xd = isDerived(x);
2301
+ const yd = isDerived(y);
2302
+ const eff = derivedSide(x, y, side);
2303
+ const passes = [{}];
2304
+ const lost = [];
2305
+ const dropped = [];
2306
+ let why = null;
2307
+ forEachCell(cellsOf(x), (r, c, X) => {
2308
+ if (why) return;
2309
+ const yRow = ycells[r];
2310
+ if (!yRow || !(String(c) in yRow)) {
2311
+ putCell(passes[0], r, c, X);
2312
+ return;
2313
+ }
2314
+ const res = transformCell(X, yRow[c] ?? null, eff);
2315
+ if (typeof res === "string") {
2316
+ why = res;
2317
+ return;
2318
+ }
2319
+ res.entries.forEach((e, i) => putCell(passes[i] ??= {}, r, c, e));
2320
+ if (res.xLost && !xd) dropped.push(cellRef(sheetOf(x), r, c));
2321
+ if (res.yLost && !yd) lost.push(cellRef(sheetOf(x), r, c));
2322
+ });
2323
+ if (why) return barrier2(why);
2324
+ const op = passes.filter((p) => !isEmptyMatrix(p)).map((p) => cellsMutation(x, p));
2325
+ return ok(op, lost, dropped);
2326
+ }
2327
+ var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived"];
2328
+ var isDerived = (m) => m.params.derived === true;
2329
+ function derivedSide(x, y, side) {
2330
+ const xd = isDerived(x);
2331
+ const yd = isDerived(y);
2332
+ return xd === yd ? side : xd ? "right" : "left";
2333
+ }
2334
+ function forApply(m) {
2335
+ if (!SIDE_CAR_PARAMS.some((k) => k in m.params)) return m;
2336
+ const params = { ...m.params };
2337
+ for (const k of SIDE_CAR_PARAMS) delete params[k];
2338
+ return { id: m.id, params };
2339
+ }
2340
+ var refSheetsOf = (m) => m.params.refSheets;
2341
+ var formulaCtx = (m) => ({ ownSheet: sheetOf(m), refSheets: refSheetsOf(m) });
2342
+ function withRefSheets(params, rs) {
2343
+ const out = { ...params };
2344
+ if (rs) out.refSheets = rs;
2345
+ else delete out.refSheets;
2346
+ return out;
2347
+ }
2348
+ var hasFormulaText = (v) => !!v && (isFormulaText(v.f) || typeof v.ref === "string");
2349
+ function hasFormula(m) {
2350
+ let any = false;
2351
+ forEachCell(cellsOf(m), (_r, _c, v) => {
2352
+ any ||= hasFormulaText(v);
2353
+ });
2354
+ return any;
2355
+ }
2356
+ var setNameWithoutPrevious = (m) => m.id === ID.setName && !("previousName" in m.params);
2357
+ function refChangeOf(m) {
2358
+ const st = structuralOf(m);
2359
+ if (st) return { kind: "axis", sheet: sheetOf(m), axis: st.axis, op: st.op };
2360
+ if (m.id === ID.name) return { kind: "rename", sheet: sheetOf(m), name: String(m.params.name) };
2361
+ if (m.id === ID.removeName) return { kind: "defined-name", from: String(m.params.name), to: null };
2362
+ if (m.id === ID.setName && typeof m.params.previousName === "string" && m.params.previousName !== m.params.name)
2363
+ return { kind: "defined-name", from: m.params.previousName, to: String(m.params.name) };
2364
+ return null;
2365
+ }
2366
+ function rewriteEntry(v, ctx, change) {
2367
+ let entry = v;
2368
+ let changed = false;
2369
+ for (const k of ["f", "ref"]) {
2370
+ const t = v[k];
2371
+ if (k === "f" ? !isFormulaText(t) : typeof t !== "string") continue;
2372
+ const r = rewriteFormula(t, ctx, change);
2373
+ if (typeof r === "string") return r;
2374
+ if (!r.changed) continue;
2375
+ if (k === "ref" && r.text.includes(REF_ERROR)) return "an array formula's range was removed under it";
2376
+ entry = { ...entry, [k]: r.text };
2377
+ changed = true;
2378
+ }
2379
+ return { entry, changed };
2380
+ }
2381
+ function cellThrough(sheet, change, r, c) {
2382
+ if (change.kind !== "axis" || change.sheet !== sheet) return [r, c];
2383
+ const nr = change.axis === "row" ? mapIndex(change.op, r) : r;
2384
+ const nc = change.axis === "col" ? mapIndex(change.op, c) : c;
2385
+ return nr === null || nc === null ? null : [nr, nc];
2386
+ }
2387
+ function cellsOverChange(x, change) {
2388
+ const ctx = formulaCtx(x);
2389
+ const out = {};
2390
+ const dropped = [];
2391
+ let why = null;
2392
+ forEachCell(cellsOf(x), (r, c, v) => {
2393
+ if (why) return;
2394
+ const at = cellThrough(sheetOf(x), change, r, c);
2395
+ if (!at) {
2396
+ dropped.push(cellRef(sheetOf(x), r, c));
2397
+ return;
2398
+ }
2399
+ let e = v;
2400
+ if (hasFormulaText(v)) {
2401
+ const res = rewriteEntry(v, ctx, change);
2402
+ if (typeof res === "string") {
2403
+ why = res;
2404
+ return;
2405
+ }
2406
+ e = res.entry;
2407
+ }
2408
+ putCell(out, at[0], at[1], e);
2409
+ });
2410
+ if (why) return barrier2(why);
2411
+ const params = { ...withRefSheets(x.params, refSheetsAfter(ctx.refSheets, change)), cellValue: out };
2412
+ return ok(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
2413
+ }
2414
+ function rewritesOf(y, change) {
2415
+ const ctx = formulaCtx(y);
2416
+ const out = {};
2417
+ let why = null;
2418
+ forEachCell(cellsOf(y), (r, c, v) => {
2419
+ if (why || !hasFormulaText(v)) return;
2420
+ const at = cellThrough(sheetOf(y), change, r, c);
2421
+ if (!at) return;
2422
+ const res = rewriteEntry(v, ctx, change);
2423
+ if (typeof res === "string") {
2424
+ why = res;
2425
+ return;
2426
+ }
2427
+ if (res.changed) putCell(out, at[0], at[1], contentOf(res.entry));
2428
+ });
2429
+ if (why) return why;
2430
+ if (isEmptyMatrix(out)) return null;
2431
+ return { id: ID.values, params: withRefSheets({ subUnitId: sheetOf(y), cellValue: out, derived: true }, refSheetsAfter(ctx.refSheets, change)) };
2432
+ }
2433
+ var NAME_TEXT_KEYS = ["formulaOrRefString", "formulaOrRefStringWithPrefix"];
2434
+ function definedNameThrough(m, change) {
2435
+ if (change.kind === "defined-name" || m.id !== ID.setName) return { op: m, changed: false };
2436
+ const ctx = { ownSheet: change.sheet, refSheets: refSheetsOf(m), keepQualifier: true };
2437
+ const params = { ...m.params };
2438
+ let changed = false;
2439
+ for (const k of NAME_TEXT_KEYS) {
2440
+ if (typeof params[k] !== "string" || !params[k]) continue;
2441
+ const r = rewriteFormula(params[k], ctx, change);
2442
+ if (typeof r === "string") return r;
2443
+ if (r.changed) {
2444
+ params[k] = r.text;
2445
+ changed = true;
2446
+ }
2447
+ }
2448
+ return { op: { id: m.id, params: withRefSheets(params, refSheetsAfter(ctx.refSheets, change)) }, changed };
2449
+ }
2450
+ function asDerived(m) {
2451
+ return { id: m.id, params: { ...m.params, derived: true } };
2452
+ }
2453
+ function formulaPair(x, y, side) {
2454
+ const fx = familyOf(x.id);
2455
+ const fy = familyOf(y.id);
2456
+ const SET_NAME_BARRIER = "set-defined-name without previousName (capture must record the name it replaces) against formula text";
2457
+ if (fx === "defname" && fy === "defname") {
2458
+ if (String(x.params.id) !== String(y.params.id)) return ok([x]);
2459
+ const eff = derivedSide(x, y, side);
2460
+ if (eff === "left") return ok([x], isDerived(y) ? [] : [`defined name "${String(y.params.name)}"`]);
2461
+ return ok([], [], isDerived(x) ? [] : [`defined name "${String(x.params.name)}"`]);
2462
+ }
2463
+ if (fx === "defname") {
2464
+ if (fy === "cell") {
2465
+ if (setNameWithoutPrevious(x) && hasFormula(y)) return barrier2(SET_NAME_BARRIER);
2466
+ const ch2 = refChangeOf(x);
2467
+ if (!ch2) return ok([x]);
2468
+ const add = rewritesOf(y, ch2);
2469
+ if (typeof add === "string") return barrier2(add);
2470
+ return ok(add ? [x, add] : [x]);
2471
+ }
2472
+ const ch = refChangeOf(y);
2473
+ if (!ch) return ok([x]);
2474
+ const r = definedNameThrough(x, ch);
2475
+ return typeof r === "string" ? barrier2(r) : ok([r.op]);
2476
+ }
2477
+ if (fy === "defname") {
2478
+ if (fx === "cell") {
2479
+ if (setNameWithoutPrevious(y) && hasFormula(x)) return barrier2(SET_NAME_BARRIER);
2480
+ const ch2 = refChangeOf(y);
2481
+ return ch2 ? cellsOverChange(x, ch2) : ok([x]);
2482
+ }
2483
+ const ch = refChangeOf(x);
2484
+ if (!ch) return ok([x]);
2485
+ const r = definedNameThrough(y, ch);
2486
+ if (typeof r === "string") return barrier2(r);
2487
+ return ok(r.changed ? [x, asDerived(r.op)] : [x]);
2488
+ }
2489
+ if (fx === "cell") {
2490
+ const ch = refChangeOf(y);
2491
+ return ch ? cellsOverChange(x, ch) : null;
2492
+ }
2493
+ if (fy === "cell") {
2494
+ const ch = refChangeOf(x);
2495
+ if (!ch) return null;
2496
+ const lost = [];
2497
+ forEachCell(cellsOf(y), (r, c) => {
2498
+ if (!cellThrough(sheetOf(y), ch, r, c)) lost.push(cellRef(sheetOf(y), r, c));
2499
+ });
2500
+ const add = rewritesOf(y, ch);
2501
+ if (typeof add === "string") return barrier2(add);
2502
+ return ok(add ? [x, add] : [x], lost);
2503
+ }
2504
+ return null;
2505
+ }
2506
+ var withPrevious = (m, definedNames) => m.id === ID.setName && !("previousName" in m.params) ? { id: m.id, params: { ...m.params, previousName: definedNames[String(m.params.id)] ?? null } } : m;
2507
+ function annotateFormulas(group, sheets, definedNames) {
2508
+ let changed = false;
2509
+ return group.map((m0) => {
2510
+ const m = changed && (m0.id === ID.values || m0.id === ID.setName) ? asDerived(m0) : m0;
2511
+ if (!changed && refChangeOf(withPrevious(m0, definedNames))) changed = true;
2512
+ if (m.id === ID.values) {
2513
+ const texts = [];
2514
+ forEachCell(cellsOf(m), (_r, _c, v) => {
2515
+ if (v && isFormulaText(v.f)) texts.push(v.f);
2516
+ if (v && typeof v.ref === "string") texts.push(v.ref);
2517
+ });
2518
+ return { id: m.id, params: withRefSheets(m.params, refSheetsFor(texts, sheets)) };
2519
+ }
2520
+ if (m.id === ID.setName) {
2521
+ const texts = NAME_TEXT_KEYS.map((k) => m.params[k]).filter((t) => typeof t === "string");
2522
+ return { id: m.id, params: { ...withRefSheets(m.params, refSheetsFor(texts, sheets)), previousName: withPrevious(m, definedNames).params.previousName } };
2523
+ }
2524
+ return m;
2525
+ });
2526
+ }
2527
+ function sizeOf(m) {
2528
+ const p = m.params;
2529
+ const values = /* @__PURE__ */ new Map();
2530
+ if (m.id === ID.rowAutoHeight) {
2531
+ for (const { row, autoHeight } of p.rowsAutoHeightInfo ?? []) values.set(row, autoHeight);
2532
+ return { axis: "row", attr: "ah", values };
2533
+ }
2534
+ const axis = m.id === ID.colWidth ? "col" : "row";
2535
+ const field = m.id === ID.colWidth ? "colWidth" : m.id === ID.rowHeight ? "rowHeight" : "autoHeightInfo";
2536
+ const value = p[field];
2537
+ const [a0, a1] = S(axis);
2538
+ for (const r of p.ranges ?? [])
2539
+ for (let i = r[a0]; i <= r[a1]; i++) {
2540
+ if (typeof value === "number") values.set(i, value);
2541
+ else if (m.id === ID.rowIsAuto) values.set(i, value?.[i]);
2542
+ else if (value?.[i] != null) values.set(i, value[i]);
2543
+ }
2544
+ return { axis, attr: m.id === ID.colWidth ? "w" : m.id === ID.rowHeight ? "h" : "ia", values };
2545
+ }
2546
+ function buildSize(template, values) {
2547
+ if (values.size === 0) return null;
2548
+ const p = template.params;
2549
+ if (template.id === ID.rowAutoHeight)
2550
+ return { id: template.id, params: { ...p, rowsAutoHeightInfo: [...values].sort((a, b) => a[0] - b[0]).map(([row, autoHeight]) => ({ row, autoHeight })) } };
2551
+ const axis = template.id === ID.colWidth ? "col" : "row";
2552
+ const field = template.id === ID.colWidth ? "colWidth" : template.id === ID.rowHeight ? "rowHeight" : "autoHeightInfo";
2553
+ const [a0, a1] = S(axis);
2554
+ const first = (p.ranges ?? [])[0] ?? { startRow: 0, endRow: 0, startColumn: 0, endColumn: 0 };
2555
+ const ranges = runs(values.keys()).map((r) => ({ ...first, [a0]: r.start, [a1]: r.start + r.count - 1 }));
2556
+ const uniform = typeof p[field] === "number" ? p[field] : void 0;
2557
+ const value = uniform !== void 0 && [...values.values()].every((v) => v === uniform) ? uniform : Object.fromEntries(values);
2558
+ return { id: template.id, params: { ...p, ranges, [field]: value } };
2559
+ }
2560
+ function familyOf(id) {
2561
+ const e = SHEET_MUTATIONS[id];
2562
+ return e && e.kind === "covered" ? e.family : "";
2563
+ }
2564
+ function transformMutation(x, y, side) {
2565
+ for (const m of [x, y]) {
2566
+ const e = SHEET_MUTATIONS[m.id];
2567
+ if (!e) return barrier2(`${m.id} is not in the registry`);
2568
+ if (e.kind !== "covered") return barrier2(`${m.id}: ${e.kind === "barrier" ? `barrier until ${e.until} (${e.reason})` : "never travels"}`);
2569
+ if (m.id === ID.values) {
2570
+ const why = cellBarrier(m);
2571
+ if (why) return barrier2(why);
2572
+ }
2573
+ }
2574
+ const pb = PAIR_BARRIERS[pairKey(x.id, y.id)];
2575
+ if (pb) return barrier2(`${x.id} \xD7 ${y.id}: ${pb.reason}${pb.seed === null ? "" : ` (fuzz seed ${pb.seed})`}`);
2576
+ const fp = formulaPair(x, y, side);
2577
+ if (fp) return fp;
2578
+ if (sheetOf(x) !== sheetOf(y)) return ok([x]);
2579
+ const fx = familyOf(x.id);
2580
+ const fy = familyOf(y.id);
2581
+ const sy = structuralOf(y);
2582
+ const sx = structuralOf(x);
2583
+ if (sx && sy) {
2584
+ if (sx.axis !== sy.axis) return ok([x]);
2585
+ const out = transformAxis(sx.op, sy.op, side);
2586
+ if (!out) return barrier2(`${x.id} over ${y.id}: moved blocks overlap in part, or the block would split`);
2587
+ const dropped = out.length === 0 && sx.op.kind === "move" ? [`${sheetOf(x)}: moved ${sx.axis}s`] : [];
2588
+ return ok(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);
2589
+ }
2590
+ if (sy) {
2591
+ if (fx === "merge") {
2592
+ const kept = [];
2593
+ const dropped = [];
2594
+ for (const r of mergeRanges(x)) {
2595
+ const t = mergeThrough(sy, r).range;
2596
+ if (t) kept.push(t);
2597
+ else dropped.push(rangeRef(sheetOf(x), r));
2598
+ }
2599
+ return ok(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);
2600
+ }
2601
+ if (fx === "size") {
2602
+ const size = sizeOf(x);
2603
+ if (size.axis !== sy.axis) return ok([x]);
2604
+ const next = /* @__PURE__ */ new Map();
2605
+ for (const [i, v] of size.values) {
2606
+ const m = mapIndex(sy.op, i);
2607
+ if (m !== null) next.set(m, v);
2608
+ }
2609
+ const built = buildSize(x, next);
2610
+ return ok(built ? [built] : []);
2611
+ }
2612
+ return ok([x]);
2613
+ }
2614
+ if (sx) {
2615
+ if (fy !== "merge" || y.id !== ID.addMerge) return ok([x]);
2616
+ const remove = [];
2617
+ const add = [];
2618
+ for (const r of mergeRanges(y)) {
2619
+ const t = mergeThrough(sx, r);
2620
+ if (!t.fixup) continue;
2621
+ remove.push(r);
2622
+ if (t.range) add.push(t.range);
2623
+ }
2624
+ const lostMerges = mergeRanges(y).filter((r) => mergeThrough(sx, r).range === null).map((r) => rangeRef(sheetOf(y), r));
2625
+ if (!remove.length) return ok([x], lostMerges);
2626
+ const sheet = sheetOf(x);
2627
+ const pre = sx.op.kind === "insert" ? [] : [mergeMutation(ID.removeMerge, sheet, remove)];
2628
+ const mid = sx.op.kind === "insert" ? [mergeMutation(ID.removeMerge, sheet, remove)] : [];
2629
+ return ok([...pre, x, ...mid, ...add.length ? [mergeMutation(ID.addMerge, sheet, add)] : []], lostMerges);
2630
+ }
2631
+ if (fx === "cell" && fy === "cell") return transformCellsOverCells(x, y, side);
2632
+ if (fx === "merge" && fy === "merge") {
2633
+ const xr = mergeRanges(x);
2634
+ const yr = mergeRanges(y);
2635
+ const hit = (r) => yr.some((q) => intersects(r, q));
2636
+ const sheet = sheetOf(x);
2637
+ if (x.id === ID.addMerge && y.id === ID.addMerge) {
2638
+ if (!xr.some(hit)) return ok([x]);
2639
+ if (side === "left") {
2640
+ const lost = yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q));
2641
+ return ok([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);
2642
+ }
2643
+ const kept = xr.filter((r) => !hit(r));
2644
+ return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
2645
+ }
2646
+ if (x.id === ID.addMerge && y.id === ID.removeMerge) {
2647
+ if (side === "left" || !xr.some(hit)) return ok([x], side === "left" && xr.some(hit) ? yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q)) : []);
2648
+ const kept = xr.filter((r) => !hit(r));
2649
+ return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
2650
+ }
2651
+ if (x.id === ID.removeMerge && y.id === ID.addMerge) {
2652
+ const touched = yr.filter((q) => xr.some((r) => intersects(r, q)));
2653
+ if (!touched.length) return ok([x]);
2654
+ if (side === "left") return ok([x], touched.map((q) => rangeRef(sheet, q)));
2655
+ return ok([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
2656
+ }
2657
+ return ok([x]);
2658
+ }
2659
+ if (fx === "size" && fy === "size") {
2660
+ const a = sizeOf(x);
2661
+ const b = sizeOf(y);
2662
+ if (a.axis !== b.axis || a.attr !== b.attr) return ok([x]);
2663
+ if (side === "left") {
2664
+ const lost = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
2665
+ return ok([x], lost);
2666
+ }
2667
+ const next = new Map([...a.values].filter(([i]) => !b.values.has(i)));
2668
+ const built = buildSize(x, next);
2669
+ const dropped = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
2670
+ return ok(built ? [built] : [], [], dropped);
2671
+ }
2672
+ if (fx === "name" && fy === "name") {
2673
+ if (side === "left") return ok([x], [`${sheetOf(x)}: name "${String(y.params.name)}"`]);
2674
+ return ok([], [], [`${sheetOf(x)}: name "${String(x.params.name)}"`]);
2675
+ }
2676
+ return ok([x]);
2677
+ }
2678
+ var blocked = (p) => !Array.isArray(p);
2679
+ function tSeq(xs, ys, side, acc) {
2680
+ if (xs.length === 0 || ys.length === 0) return [xs, ys];
2681
+ if (xs.length === 1 && ys.length === 1) {
2682
+ const a = transformMutation(xs[0], ys[0], side);
2683
+ if (isBarrier(a)) return a;
2684
+ const b = transformMutation(ys[0], xs[0], flip(side));
2685
+ if (isBarrier(b)) return b;
2686
+ acc.lost.push(...a.lost);
2687
+ acc.dropped.push(...a.dropped);
2688
+ return [a.op, b.op];
2689
+ }
2690
+ if (xs.length > 1) {
2691
+ const first2 = tSeq([xs[0]], ys, side, acc);
2692
+ if (blocked(first2)) return first2;
2693
+ const rest2 = tSeq(xs.slice(1), first2[1], side, acc);
2694
+ if (blocked(rest2)) return rest2;
2695
+ return [[...first2[0], ...rest2[0]], rest2[1]];
2696
+ }
2697
+ const first = tSeq(xs, [ys[0]], side, acc);
2698
+ if (blocked(first)) return first;
2699
+ const rest = tSeq(first[0], ys.slice(1), side, acc);
2700
+ if (blocked(rest)) return rest;
2701
+ return [rest[0], [...first[1], ...rest[1]]];
2702
+ }
2703
+ function transformGroup(x, y, side) {
2704
+ const acc = { lost: [], dropped: [] };
2705
+ const r = tSeq([...x], [...y], side, acc);
2706
+ if (blocked(r)) return r;
2707
+ return { op: r[0], lost: [...new Set(acc.lost)], dropped: [...new Set(acc.dropped)] };
2708
+ }
2709
+
2710
+ // src/univer/collab/sheets-ot/state-hash.ts
2711
+ var SHEET_LOCAL_SHEET_KEYS = ["zoomRatio", "scrollTop", "scrollLeft", "selections", "__collab"];
2712
+ var SHEET_LOCAL_KEYS = ["id", "rev", "__matrxCollabCovered", "__collab"];
2713
+ function sortDeep2(v) {
2714
+ if (Array.isArray(v)) return v.map(sortDeep2);
2715
+ if (v && typeof v === "object") {
2716
+ const out = {};
2717
+ for (const k of Object.keys(v).sort()) {
2718
+ const x = v[k];
2719
+ if (x === void 0 || x === null) continue;
2720
+ if (Array.isArray(x) && x.length === 0) continue;
2721
+ if (x && typeof x === "object" && !Array.isArray(x) && Object.keys(x).length === 0) continue;
2722
+ out[k] = sortDeep2(x);
2723
+ }
2724
+ return out;
2725
+ }
2726
+ return v;
2727
+ }
2728
+ function parsedResource(data) {
2729
+ if (typeof data !== "string") return data;
2730
+ try {
2731
+ return JSON.parse(data);
2732
+ } catch {
2733
+ return data;
2734
+ }
2735
+ }
2736
+ function canonicalSheet(snapshot) {
2737
+ const s = structuredClone(snapshot ?? {});
2738
+ for (const k of SHEET_LOCAL_KEYS) delete s[k];
2739
+ const styles = s.styles ?? {};
2740
+ const deref = (v) => typeof v === "string" && styles[v] ? sortDeep2(styles[v]) : v;
2741
+ delete s.styles;
2742
+ for (const sheet of Object.values(s.sheets ?? {})) {
2743
+ for (const k of SHEET_LOCAL_SHEET_KEYS) delete sheet[k];
2744
+ if (sheet.defaultStyle) sheet.defaultStyle = deref(sheet.defaultStyle);
2745
+ for (const key of ["rowData", "columnData"]) for (const v of Object.values(sheet[key] ?? {})) if (v?.s) v.s = deref(v.s);
2746
+ const cd = sheet.cellData ?? {};
2747
+ for (const row of Object.keys(cd)) {
2748
+ for (const col of Object.keys(cd[row] ?? {})) {
2749
+ const c = cd[row][col];
2750
+ if (c?.s) c.s = deref(c.s);
2751
+ if (c && (c.f || c.si)) {
2752
+ delete c.v;
2753
+ delete c.t;
2754
+ }
2755
+ if (!c || Object.keys(sortDeep2(c)).length === 0) delete cd[row][col];
2756
+ }
2757
+ if (Object.keys(cd[row] ?? {}).length === 0) delete cd[row];
2758
+ }
2759
+ if (Array.isArray(sheet.mergeData))
2760
+ sheet.mergeData = sheet.mergeData.map((m) => JSON.stringify(sortDeep2(m))).sort().map((j) => JSON.parse(j));
2761
+ }
2762
+ if (Array.isArray(s.resources))
2763
+ s.resources = s.resources.map((r) => ({ name: r.name, data: sortDeep2(parsedResource(r.data)) })).filter((r) => r.data != null && r.data !== "" && !(typeof r.data === "object" && Object.keys(r.data).length === 0)).sort((a, b) => String(a.name).localeCompare(String(b.name)));
2764
+ if (Array.isArray(s.definedNames)) s.definedNames = [...s.definedNames].sort((x, y) => String(x.id).localeCompare(String(y.id)));
2765
+ return sortDeep2(s);
2766
+ }
2767
+ var canonicalSheetString = (snapshot) => JSON.stringify(canonicalSheet(snapshot));
2768
+ async function sheetsStateHash(snapshot) {
2769
+ const bytes = new TextEncoder().encode(canonicalSheetString(snapshot));
2770
+ const digest = await globalThis.crypto.subtle.digest("SHA-256", bytes);
2771
+ return Array.from(new Uint8Array(digest), (b) => b.toString(16).padStart(2, "0")).join("");
2772
+ }
2773
+
2774
+ // src/univer/collab/sheets-ot/room.ts
2775
+ var SHEETS_COLLAB_PROTO = 1;
2776
+ var SHEETS_EDIT_GROUP = "sheets.edit";
2777
+ var flip2 = (side) => side === "left" ? "right" : "left";
2778
+ var isNoopSheetOp = (op) => op == null || op.length === 0;
2779
+ function transformSheetOp(x, y, side) {
2780
+ if (isNoopSheetOp(x) || isNoopSheetOp(y)) return { op: isNoopSheetOp(x) ? null : x, lost: [], dropped: [] };
2781
+ const r = transformGroup(x, y, side);
2782
+ if (isBarrier(r)) return r;
2783
+ const back = transformGroup(y, x, flip2(side));
2784
+ const lost = [.../* @__PURE__ */ new Set([...r.lost, ...isBarrier(back) ? [] : back.dropped])];
2785
+ return { op: r.op.length ? r.op : null, lost, dropped: r.dropped };
2786
+ }
2787
+ function encodeSheetOp(op) {
2788
+ return canonicalKeys([{ cmd: SHEETS_EDIT_GROUP, mutations: (op ?? []).map((m) => ({ id: m.id, params: m.params })) }]);
2789
+ }
2790
+ function decodeSheetOp(groups) {
2791
+ const out = [];
2792
+ for (const g of groups) for (const m of g.mutations) out.push({ id: m.id, params: m.params ?? {} });
2793
+ return out.length ? out : null;
2794
+ }
2795
+ function undoStacksOf2(service) {
2796
+ const s = service;
2797
+ if (!s || !(s._undoStacks instanceof Map) || !(s._redoStacks instanceof Map)) return null;
2798
+ return { undo: s._undoStacks, redo: s._redoStacks };
2799
+ }
2800
+ var CONTENT_TOUCH2 = CONTENT_KEYS.filter((k) => k !== "t");
2801
+ function travelingShape(m) {
2802
+ const params = allowParams(m.id, m.params);
2803
+ if (!params) return null;
2804
+ if (m.params.isOverrideStyle) return null;
2805
+ if (m.id === "sheet.mutation.set-range-values") {
2806
+ const cells = structuredClone(params.cellValue ?? {});
2807
+ for (const row of Object.values(cells))
2808
+ for (const [c, v] of Object.entries(row)) {
2809
+ if (!v) continue;
2810
+ if (typeof v.s === "string") return null;
2811
+ if (!CONTENT_TOUCH2.some((k) => k in v)) continue;
2812
+ const full = {};
2813
+ for (const k of CONTENT_KEYS) full[k] = v[k] !== void 0 ? v[k] : null;
2814
+ if (full.v === null) delete full.t;
2815
+ if ("s" in v) full.s = v.s;
2816
+ row[c] = full;
2817
+ }
2818
+ return { id: m.id, params: { ...params, cellValue: cells } };
2819
+ }
2820
+ return { id: m.id, params };
2821
+ }
2822
+ function rebaseSheetUndoStack(items, remote, unitId) {
2823
+ if (isNoopSheetOp(remote)) return 0;
2824
+ let dropped = 0;
2825
+ for (let i = items.length - 1; i >= 0; i--) {
2826
+ const item = items[i];
2827
+ let ok2 = true;
2828
+ for (const key of ["undoMutations", "redoMutations"]) {
2829
+ const list = item[key];
2830
+ if (!ok2 || !list?.length) continue;
2831
+ const isOperation = (id) => !SHEET_MUTATIONS[id] && id.includes(".operation.");
2832
+ const operations = list.filter((m) => isOperation(m.id));
2833
+ const shaped = list.filter((m) => !isOperation(m.id)).map(travelingShape);
2834
+ if (shaped.some((m) => m === null)) {
2835
+ ok2 = false;
2836
+ continue;
2837
+ }
2838
+ if (!shaped.length) continue;
2839
+ try {
2840
+ const r = transformGroup(shaped, remote, "left");
2841
+ if (isBarrier(r) || r.op.length === 0) {
2842
+ ok2 = false;
2843
+ continue;
2844
+ }
2845
+ if (JSON.stringify(r.op) === JSON.stringify(shaped)) continue;
2846
+ item[key] = [...r.op.map((m) => ({ id: m.id, params: { ...forApply(m).params, unitId } })), ...operations];
2847
+ } catch {
2848
+ ok2 = false;
2849
+ }
2850
+ }
2851
+ if (!ok2) {
2852
+ items.splice(i, 1);
2853
+ dropped++;
2854
+ }
2855
+ }
2856
+ return dropped;
2857
+ }
2858
+ function createSheetsOtAdapter(port, hooks = {}) {
2859
+ let queue = [];
2860
+ let draining = false;
2861
+ const applyNow = (op) => {
2862
+ for (const m of op) port.applyRemote(m);
2863
+ let dropped = 0;
2864
+ for (const t of port.undoTargets()) {
2865
+ const stacks = undoStacksOf2(t.service);
2866
+ if (!stacks) continue;
2867
+ for (const map of [stacks.undo, stacks.redo]) {
2868
+ const items = map.get(t.unitId);
2869
+ if (items?.length) dropped += rebaseSheetUndoStack(items, op, t.unitId);
2870
+ }
2871
+ }
2872
+ hooks.onUndoRebased?.(dropped);
2873
+ port.markDirty();
2874
+ };
2875
+ const adapter = {
2876
+ version: SHEET_TRANSFORMER_VERSION,
2877
+ transform: (x, y, side) => transformSheetOp(x, y, side),
2878
+ compose: (a, b) => [...a ?? [], ...b ?? []],
2879
+ isNoop: isNoopSheetOp,
2880
+ encode: encodeSheetOp,
2881
+ decode: decodeSheetOp,
2882
+ apply(op) {
2883
+ if (isNoopSheetOp(op)) return true;
2884
+ if (port.busy() || queue.length) {
2885
+ queue.push(op);
2886
+ if (!draining) {
2887
+ draining = true;
2888
+ port.whenIdle(() => {
2889
+ draining = false;
2890
+ const held = queue;
2891
+ queue = [];
2892
+ for (const q of held) applyNow(q);
2893
+ });
2894
+ }
2895
+ return true;
2896
+ }
2897
+ applyNow(op);
2898
+ return true;
2899
+ },
2900
+ async load(snapshot) {
2901
+ queue = [];
2902
+ const current = port.snapshot();
2903
+ if (!(current && snapshot && canonicalSheetString(current) === canonicalSheetString(snapshot))) port.load(snapshot);
2904
+ for (const t of port.undoTargets()) {
2905
+ const stacks = undoStacksOf2(t.service);
2906
+ stacks?.undo.delete(t.unitId);
2907
+ stacks?.redo.delete(t.unitId);
2908
+ }
2909
+ },
2910
+ snapshot: () => port.snapshot(),
2911
+ async hash() {
2912
+ if (port.busy() || queue.length) {
2913
+ await new Promise((resolve) => {
2914
+ const done = setTimeout(resolve, 5e3);
2915
+ port.whenIdle(() => {
2916
+ clearTimeout(done);
2917
+ setTimeout(resolve, 0);
2918
+ });
2919
+ });
2920
+ }
2921
+ return sheetsStateHash(port.snapshot());
2922
+ },
2923
+ held: () => queue.length,
2924
+ rebaseLocalOverHeld(local) {
2925
+ let op = local;
2926
+ const next = [];
2927
+ for (const q of queue) {
2928
+ const l2 = transformSheetOp(op, q, "left");
2929
+ const q2 = transformSheetOp(q, op, "right");
2930
+ if ("barrier" in l2 || "barrier" in q2) return "barrier";
2931
+ op = l2.op ?? [];
2932
+ if (q2.op?.length) next.push(q2.op);
2933
+ }
2934
+ queue = next;
2935
+ return op;
2936
+ },
2937
+ clearHeld() {
2938
+ queue = [];
2939
+ }
2940
+ };
2941
+ return adapter;
2942
+ }
2943
+ function openSheetsOtRoom(o) {
2944
+ const { port } = o;
2945
+ let session = null;
2946
+ const adapter = createSheetsOtAdapter(port);
2947
+ const notice = (n) => {
2948
+ try {
2949
+ o.onNotice?.(n);
2950
+ } catch (err) {
2951
+ console.warn("[sheets-ot] notice handler failed", err);
2952
+ }
2953
+ };
2954
+ const onLocal = (e) => {
2955
+ if (!session) return;
2956
+ if (e.kind === "not_shared") {
2957
+ notice({ kind: "not_shared", mutationId: e.mutationId });
2958
+ adapter.clearHeld();
2959
+ session.rebuild(`not_shared:${e.mutationId}`);
2960
+ return;
2961
+ }
2962
+ if (!e.mutations.length) return;
2963
+ for (const m of e.mutations) {
2964
+ if (SHEET_MUTATIONS[m.id]?.kind !== "covered") {
2965
+ notice({ kind: "not_shared", mutationId: m.id });
2966
+ adapter.clearHeld();
2967
+ session.rebuild(`not_shared:${m.id}`);
2968
+ return;
2969
+ }
2970
+ }
2971
+ let op = e.mutations;
2972
+ let inverse = e.inverse;
2973
+ if (adapter.held()) {
2974
+ inverse = void 0;
2975
+ const r = adapter.rebaseLocalOverHeld(op);
2976
+ if (r === "barrier") {
2977
+ adapter.clearHeld();
2978
+ session.rebuild("held_barrier");
2979
+ return;
2980
+ }
2981
+ op = r;
2982
+ if (!op.length) return;
2983
+ }
2984
+ if (!session.local(op, { ...inverse !== void 0 ? { inverse } : {}, label: e.label ?? SHEETS_EDIT_GROUP })) notice({ kind: "not_live" });
2985
+ };
2986
+ const unsubLocal = port.onLocal(onLocal);
2987
+ session = openOpSession2({
2988
+ transport: o.transport,
2989
+ adapter,
2990
+ proto: SHEETS_COLLAB_PROTO,
2991
+ clientId: o.clientId,
2992
+ ...o.presence ? { presence: o.presence } : {},
2993
+ onNotice: (n) => notice(n),
2994
+ ...o.onIncident ? { onIncident: o.onIncident } : {},
2995
+ ...o.onStatus ? { onStatus: o.onStatus } : {}
2996
+ });
2997
+ const isSaver = () => {
2998
+ if (!o.presence) return true;
2999
+ return o.presence.peers().every((p) => p.clientId === o.clientId || p.clientId > o.clientId);
3000
+ };
3001
+ return {
3002
+ session,
3003
+ isSaver,
3004
+ async write(reason) {
3005
+ if (!session) return false;
3006
+ if (reason !== "manual" && !isSaver()) return false;
3007
+ const out = await session.save();
3008
+ if (out.saved) return true;
3009
+ if (out.reason === "not_quiet" || out.reason === "changed") setTimeout(() => port.markDirty(), 1500);
3010
+ return false;
3011
+ },
3012
+ async replace(snapshot) {
3013
+ port.load(snapshot);
3014
+ const loaded = port.snapshot();
3015
+ if (!loaded) throw new Error("The workbook is not open in this tab.");
3016
+ const stateHash = await sheetsStateHash(loaded);
3017
+ await o.replace({ snapshot: loaded, stateHash, clientId: o.clientId });
3018
+ },
3019
+ stop() {
3020
+ unsubLocal();
3021
+ session?.close();
3022
+ }
3023
+ };
3024
+ }
3025
+
3026
+ // src/univer/collab/sheets-ot/univer-port.ts
3027
+ var COMMAND = 0;
3028
+ var MUTATION = 2;
3029
+ var VALUES = "sheet.mutation.set-range-values";
3030
+ var ADD_MERGE = "sheet.mutation.add-worksheet-merge";
3031
+ var REMOVE_MERGE = "sheet.mutation.remove-worksheet-merge";
3032
+ var SHEET_NAME = "sheet.mutation.set-worksheet-name";
3033
+ var DEPTH_GUARD = /* @__PURE__ */ Symbol.for("ai-matrx.office.sheets.command-depth-guard");
3034
+ var json = (v) => v === void 0 ? v : JSON.parse(JSON.stringify(v));
3035
+ var flagged = (options) => {
3036
+ const o = options;
3037
+ return !!(o?.onlyLocal || o?.fromCollab);
3038
+ };
3039
+ function univerSheetsOtPort(o) {
3040
+ const cs = o.commandService;
3041
+ const listeners = /* @__PURE__ */ new Set();
3042
+ const idle = [];
3043
+ const pre = /* @__PURE__ */ new WeakMap();
3044
+ const tracker = { stack: [], settle: () => settle() };
3045
+ let group = null;
3046
+ let applying = false;
3047
+ const unitId = () => o.workbook()?.getUnitId() ?? null;
3048
+ const mine = (params) => {
3049
+ const u = unitId();
3050
+ return !!u && !!params && typeof params === "object" && params.unitId === u;
3051
+ };
3052
+ const styleObject = (s) => {
3053
+ if (typeof s !== "string") return s;
3054
+ const found = o.workbook()?.getStyles().get(s);
3055
+ return found ? json(found) : s;
3056
+ };
3057
+ const sheetNames = () => {
3058
+ const out = {};
3059
+ for (const ws of o.workbook()?.getSheets() ?? []) out[ws.getSheetId()] = ws.getName();
3060
+ return out;
3061
+ };
3062
+ const definedNames = () => {
3063
+ const u = unitId();
3064
+ const map = u && o.definedNames?.(u) || {};
3065
+ const out = {};
3066
+ for (const [id, d] of Object.entries(map)) out[id] = String(d?.name ?? "");
3067
+ return out;
3068
+ };
3069
+ const openGroup = (label) => ({ label, sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
3070
+ const emit = (e) => {
3071
+ for (const l of [...listeners]) {
3072
+ try {
3073
+ l(e);
3074
+ } catch (err) {
3075
+ console.warn("[sheets-ot] local change handler failed", err);
3076
+ }
3077
+ }
3078
+ };
3079
+ const flush = () => {
3080
+ const g = group;
3081
+ group = null;
3082
+ if (!g) return;
3083
+ if (g.notShared) emit({ kind: "not_shared", mutationId: g.notShared, label: g.label });
3084
+ else if (g.mutations.length) {
3085
+ const mutations = annotateFormulas(g.mutations, g.sheets, g.names);
3086
+ const known = g.inverses.every((i) => i !== void 0);
3087
+ const inverse = known ? annotateFormulas(g.inverses.slice().reverse().flat(), g.sheets, g.names) : void 0;
3088
+ emit({ kind: "group", mutations, ...inverse !== void 0 ? { inverse } : {}, label: g.label });
3089
+ }
3090
+ };
3091
+ function settle() {
3092
+ if (tracker.stack.length === 0) flush();
3093
+ if (tracker.stack.length === 0 && !group) for (const fn of idle.splice(0)) fn();
3094
+ }
3095
+ const before = cs.beforeCommandExecuted((info, options) => {
3096
+ if (info.type === COMMAND) {
3097
+ if (tracker.stack.length === 0 && !group) group = openGroup(info.id);
3098
+ tracker.stack.push(info.id);
3099
+ return;
3100
+ }
3101
+ if (info.type !== MUTATION || applying || flagged(options) || !mine(info.params)) return;
3102
+ const p = info.params;
3103
+ const ws = o.workbook()?.getSheetBySheetId(String(p.subUnitId ?? ""));
3104
+ if (!ws) return;
3105
+ const record = { merges: json(ws.getMergeData() ?? []) };
3106
+ if (info.id === VALUES) {
3107
+ record.cells = /* @__PURE__ */ new Map();
3108
+ const cells = p.cellValue ?? {};
3109
+ for (const r of Object.keys(cells))
3110
+ for (const c of Object.keys(cells[r] ?? {})) {
3111
+ const raw = ws.getCellRaw(Number(r), Number(c));
3112
+ const copy = raw ? json(raw) : null;
3113
+ if (copy && "s" in copy) copy.s = styleObject(copy.s);
3114
+ record.cells.set(`${r}:${c}`, copy);
3115
+ }
3116
+ }
3117
+ if (info.id === SHEET_NAME) record.name = ws.getName();
3118
+ pre.set(p, record);
3119
+ });
3120
+ const after = cs.onCommandExecuted((info) => {
3121
+ if (info.type !== COMMAND) return;
3122
+ const at = tracker.stack.lastIndexOf(info.id);
3123
+ if (at >= 0) tracker.stack.splice(at, 1);
3124
+ settle();
3125
+ });
3126
+ const guarded = cs;
3127
+ if (!guarded[DEPTH_GUARD] && typeof cs.executeCommand === "function") {
3128
+ const trackers = /* @__PURE__ */ new Set();
3129
+ guarded[DEPTH_GUARD] = trackers;
3130
+ const original = cs.executeCommand.bind(cs);
3131
+ cs.executeCommand = async (id, params, options) => {
3132
+ const depths = new Map([...trackers].map((t) => [t, t.stack.length]));
3133
+ try {
3134
+ return await original(id, params, options);
3135
+ } finally {
3136
+ for (const [t, d] of depths) {
3137
+ if (t.stack.length > d) {
3138
+ t.stack.length = d;
3139
+ t.settle();
3140
+ }
3141
+ }
3142
+ }
3143
+ };
3144
+ }
3145
+ guarded[DEPTH_GUARD]?.add(tracker);
3146
+ const capture = (info) => {
3147
+ const entry = SHEET_MUTATIONS[info.id];
3148
+ if (!entry) {
3149
+ console.warn(`[sheets-ot] ${info.id} is not in the sheet mutation registry; it cannot be shared`);
3150
+ return { m: null, inverse: void 0, notShared: info.id };
3151
+ }
3152
+ if (entry.kind === "never-travels") return { m: null, inverse: void 0 };
3153
+ if (entry.kind === "barrier") return { m: null, inverse: void 0, notShared: info.id };
3154
+ const raw = json(info.params);
3155
+ const before2 = pre.get(info.params) ?? {};
3156
+ const params = allowParams(info.id, raw);
3157
+ if (!params) return { m: null, inverse: void 0, notShared: info.id };
3158
+ const sheet = String(params.subUnitId ?? "");
3159
+ const ws = o.workbook()?.getSheetBySheetId(sheet);
3160
+ if (info.id === VALUES) {
3161
+ const cells = params.cellValue ?? {};
3162
+ const invCells = {};
3163
+ let invKnown = !!before2.cells;
3164
+ for (const r of Object.keys(cells))
3165
+ for (const c of Object.keys(cells[r] ?? {})) {
3166
+ let e = cells[r][c] ?? null;
3167
+ const p = before2.cells?.get(`${r}:${c}`) ?? null;
3168
+ if (e && "s" in e) {
3169
+ e = { ...e, s: styleObject(e.s) };
3170
+ if (raw.isOverrideStyle) {
3171
+ const next = e.s && typeof e.s === "object" ? e.s : {};
3172
+ const prev = p?.s && typeof p.s === "object" ? p.s : {};
3173
+ const merged = { ...next };
3174
+ for (const k of Object.keys(prev)) if (!(k in next)) merged[k] = null;
3175
+ e.s = Object.keys(merged).length ? merged : null;
3176
+ }
3177
+ }
3178
+ const post = ws?.getCellRaw(Number(r), Number(c)) ?? null;
3179
+ const done = completeCellContent(e, post ? json(post) : null);
3180
+ cells[r][c] = done;
3181
+ if (!invKnown) continue;
3182
+ let inv;
3183
+ if (done === null) inv = p ? { ...fullContent(p), ...p.s !== void 0 ? { s: p.s } : {} } : null;
3184
+ else {
3185
+ inv = {};
3186
+ if (CONTENT_KEYS.some((k) => k !== "t" && k in done)) Object.assign(inv, fullContent(p));
3187
+ if ("s" in done) inv.s = p?.s ?? null;
3188
+ }
3189
+ (invCells[r] ??= {})[c] = inv;
3190
+ }
3191
+ return {
3192
+ m: { id: info.id, params: { ...params, cellValue: cells } },
3193
+ inverse: invKnown ? [{ id: VALUES, params: { subUnitId: sheet, cellValue: invCells } }] : void 0
3194
+ };
3195
+ }
3196
+ if (info.id === REMOVE_MERGE) {
3197
+ const exact = exactMergeRemovals([{ id: info.id, params }], { [sheet]: before2.merges ?? ws?.getMergeData() ?? [] });
3198
+ const m2 = exact[0] ?? null;
3199
+ if (!m2) return { m: null, inverse: void 0 };
3200
+ return { m: m2, inverse: [{ id: ADD_MERGE, params: { subUnitId: sheet, ranges: json(m2.params.ranges) } }] };
3201
+ }
3202
+ const m = { id: info.id, params };
3203
+ switch (info.id) {
3204
+ case "sheet.mutation.insert-row":
3205
+ return { m, inverse: [{ id: "sheet.mutation.remove-rows", params: { subUnitId: sheet, range: json(params.range) } }] };
3206
+ case "sheet.mutation.insert-col":
3207
+ return { m, inverse: [{ id: "sheet.mutation.remove-col", params: { subUnitId: sheet, range: json(params.range) } }] };
3208
+ case ADD_MERGE:
3209
+ return { m, inverse: [{ id: REMOVE_MERGE, params: { subUnitId: sheet, ranges: json(params.ranges) } }] };
3210
+ case SHEET_NAME:
3211
+ return { m, inverse: before2.name !== void 0 ? [{ id: SHEET_NAME, params: { subUnitId: sheet, name: before2.name } }] : void 0 };
3212
+ default:
3213
+ return { m, inverse: void 0 };
3214
+ }
3215
+ };
3216
+ const collab = cs.onMutationExecutedForCollab((info, options) => {
3217
+ if (applying || flagged(options) || !mine(info.params)) return;
3218
+ const lone = !group;
3219
+ if (lone) group = openGroup(null);
3220
+ const g = group;
3221
+ if (!g.notShared) {
3222
+ const r = capture(info);
3223
+ if (r.notShared) g.notShared = r.notShared;
3224
+ else if (r.m) {
3225
+ g.mutations.push(r.m);
3226
+ g.inverses.push(r.inverse);
3227
+ }
3228
+ }
3229
+ if (lone && tracker.stack.length === 0) settle();
3230
+ });
3231
+ return {
3232
+ onLocal(listener) {
3233
+ listeners.add(listener);
3234
+ return () => void listeners.delete(listener);
3235
+ },
3236
+ busy: () => tracker.stack.length > 0 || group !== null,
3237
+ whenIdle(fn) {
3238
+ if (tracker.stack.length === 0 && !group) fn();
3239
+ else idle.push(fn);
3240
+ },
3241
+ applyRemote(m) {
3242
+ const u = unitId();
3243
+ if (!u) throw new Error("no workbook is mounted");
3244
+ const a = forApply(m);
3245
+ applying = true;
3246
+ try {
3247
+ const ok2 = cs.syncExecuteCommand(a.id, { ...json(a.params), unitId: u }, { onlyLocal: true, fromCollab: true });
3248
+ if (ok2 === false) throw new Error(`"${m.id}" was refused by the editor`);
3249
+ } finally {
3250
+ applying = false;
3251
+ }
3252
+ },
3253
+ snapshot() {
3254
+ const wb = o.workbook();
3255
+ if (!wb) return null;
3256
+ const saved = o.saveUnit?.(wb.getUnitId()) ?? wb.getSnapshot();
3257
+ return saved ? json(saved) : null;
3258
+ },
3259
+ load(snapshot) {
3260
+ group = null;
3261
+ applying = true;
3262
+ try {
3263
+ o.load(snapshot);
3264
+ } finally {
3265
+ applying = false;
3266
+ }
3267
+ },
3268
+ undoTargets() {
3269
+ const u = unitId();
3270
+ const service = o.undoRedo?.();
3271
+ return u && service ? [{ service, unitId: u }] : [];
3272
+ },
3273
+ markDirty: () => o.markDirty(),
3274
+ dispose() {
3275
+ before.dispose();
3276
+ after.dispose();
3277
+ collab.dispose();
3278
+ guarded[DEPTH_GUARD]?.delete(tracker);
3279
+ listeners.clear();
3280
+ }
3281
+ };
3282
+ }
3283
+ function fullContent(cell) {
3284
+ const out = {};
3285
+ for (const k of CONTENT_KEYS) out[k] = cell && cell[k] !== void 0 ? cell[k] : null;
3286
+ if (out.v === null) delete out.t;
3287
+ return out;
3288
+ }
3289
+
3290
+ // src/sheets/workbook-ot-room.ts
3291
+ import * as Y3 from "yjs";
3292
+ import { Awareness as Awareness3 } from "y-protocols/awareness";
3293
+ import {
3294
+ awarenessOpPresence as awarenessOpPresence2,
3295
+ collabReplace as collabReplace3,
3296
+ collabRoomExists as collabRoomExists3,
3297
+ SupabaseYjsProvider as SupabaseYjsProvider2,
3298
+ supabaseOpTransport as supabaseOpTransport2
3299
+ } from "@ai-matrx/data/realtime/collab";
3300
+
3301
+ // src/sheets/ports.ts
3302
+ var SLOT2 = /* @__PURE__ */ Symbol.for("ai-matrx.office.sheets-host");
3303
+ var slot2 = () => {
3304
+ const g = globalThis;
3305
+ return g[SLOT2] ??= {};
3306
+ };
3307
+ function getSheetsHost() {
3308
+ const ports = slot2().ports;
3309
+ if (!ports) throw new Error("@ai-matrx/office/sheets: configureSheetsHost(ports) was not called before the workbook service ran.");
3310
+ return ports;
3311
+ }
3312
+
3313
+ // src/sheets/workbook-service.ts
3314
+ import { requireOrganizationContext as requireOrganizationContext2 } from "@ai-matrx/api";
3315
+ import { getClaimsUser as getClaimsUser2 } from "@ai-matrx/auth";
3316
+ import { tryWriteOne as tryWriteOne2, writeOneRow as writeOneRow2 } from "@ai-matrx/data/db";
3317
+ var db3 = () => getSheetsHost().getSupabase();
3318
+ async function getLatestSnapshot(workbookId) {
3319
+ const { data, error } = await db3().schema("workbench").from("udt_workbook_snapshots").select("*").eq("workbook_id", workbookId).order("created_at", { ascending: false }).limit(1).maybeSingle();
3320
+ if (error) return { success: false, error: error.message };
3321
+ return { success: true, data: data ?? null };
3322
+ }
3323
+ async function saveSnapshot(args) {
3324
+ const { data: userData } = await getClaimsUser2(db3());
3325
+ const { data: workbook, error: workbookError } = await db3().schema("workbench").from("udt_workbooks").select("organization_id").eq("id", args.workbookId).single();
3326
+ if (workbookError) return { success: false, error: workbookError.message };
3327
+ const { data, error } = await db3().schema("workbench").from("udt_workbook_snapshots").insert({
3328
+ organization_id: workbook.organization_id,
3329
+ workbook_id: args.workbookId,
3330
+ snapshot: args.snapshot,
3331
+ label: args.label ?? null,
3332
+ origin: args.origin ?? "autosave",
3333
+ created_by: userData?.user?.id ?? null
3334
+ }).select("*").single();
3335
+ if (error) return { success: false, error: error.message };
3336
+ await db3().schema("workbench").from("udt_workbooks").update({ updated_at: (/* @__PURE__ */ new Date()).toISOString() }).eq("id", args.workbookId);
3337
+ return { success: true, data };
3338
+ }
3339
+
3340
+ // src/sheets/workbook-ot-room.ts
3341
+ var db4 = () => getSheetsHost().getSupabase();
3342
+ async function loadSnapshotRow2(workbookId, ref) {
3343
+ if (ref === "none") {
3344
+ const res = await getLatestSnapshot(workbookId);
3345
+ if (!res.success) throw new Error(res.error);
3346
+ return res.data?.snapshot ?? null;
3347
+ }
3348
+ const { data, error } = await getSheetsHost().getSupabase().schema("workbench").from("udt_workbook_snapshots").select("snapshot").eq("id", ref).maybeSingle();
3349
+ if (error) throw new Error(error.message);
3350
+ if (!data) throw new Error(`The saved version ${ref} of this workbook is missing.`);
3351
+ return data.snapshot ?? null;
3352
+ }
3353
+ async function workbookUsesOrderedRoom(workbookId, knob, isNewWorkbook) {
3354
+ try {
3355
+ if (await collabRoomExists3(db4(), workbookId)) return true;
3356
+ } catch (err) {
3357
+ console.warn("[workbook] could not ask whether this workbook has a co-editing room; opening the relay room", err);
3358
+ return false;
3359
+ }
3360
+ if (knob === "all") return true;
3361
+ if (knob === "new") return isNewWorkbook();
3362
+ return false;
3363
+ }
3364
+ function pickColor3(uid) {
3365
+ const palette = ["#ef4444", "#f59e0b", "#10b981", "#3b82f6", "#8b5cf6", "#ec4899", "#14b8a6", "#f97316"];
3366
+ let h = 2166136261;
3367
+ for (let i = 0; i < uid.length; i++) {
3368
+ h ^= uid.charCodeAt(i);
3369
+ h = Math.imul(h, 16777619);
3370
+ }
3371
+ return palette[Math.abs(h) % palette.length] ?? "#ec4899";
3372
+ }
3373
+ async function startWorkbookOtRoom(port, o) {
3374
+ const latest = await getLatestSnapshot(o.workbookId);
3375
+ if (!latest.success) throw new Error(latest.error);
3376
+ if (!latest.data) {
3377
+ const mounted = port.snapshot();
3378
+ if (mounted) {
3379
+ const saved = await saveSnapshot({ workbookId: o.workbookId, snapshot: mounted, origin: "autosave" });
3380
+ if (!saved.success) throw new Error(saved.error);
3381
+ }
3382
+ }
3383
+ const doc = new Y3.Doc();
3384
+ const awareness = new Awareness3(doc);
3385
+ awareness.setLocalState({
3386
+ uid: o.uid,
3387
+ clientId: o.clientId,
3388
+ name: o.displayName ?? o.uid.slice(0, 8),
3389
+ color: pickColor3(o.uid),
3390
+ sheetId: null,
3391
+ row: null,
3392
+ col: null,
3393
+ ts: Date.now()
3394
+ });
3395
+ const publishAwareness = () => o.onAwareness?.(new Map(awareness.getStates()));
3396
+ awareness.on("change", publishAwareness);
3397
+ const provider = new SupabaseYjsProvider2({
3398
+ workbookId: o.workbookId,
3399
+ clientId: o.clientId,
3400
+ doc,
3401
+ awareness,
3402
+ ...o.readAntiEntropyIntervalMs ? { readAntiEntropyIntervalMs: o.readAntiEntropyIntervalMs } : {}
3403
+ });
3404
+ await provider.connect();
3405
+ publishAwareness();
3406
+ const client = db4();
3407
+ const room = openSheetsOtRoom({
3408
+ port,
3409
+ clientId: o.clientId,
3410
+ presence: awarenessOpPresence2(awareness),
3411
+ transport: supabaseOpTransport2({
3412
+ client,
3413
+ roomId: o.workbookId,
3414
+ kind: "univer_sheet",
3415
+ store: {
3416
+ loadSnapshot: (ref) => loadSnapshotRow2(o.workbookId, ref),
3417
+ async writeSnapshot(snapshot) {
3418
+ const res = await saveSnapshot({ workbookId: o.workbookId, snapshot, origin: "autosave" });
3419
+ if (!res.success) throw new Error(res.error);
3420
+ return res.data.id;
3421
+ }
3422
+ }
3423
+ }),
3424
+ replace: ({ snapshot, stateHash, clientId }) => collabReplace3(client, { roomId: o.workbookId, snapshot, stateHash, origin: "restore", clientId }),
3425
+ ...o.onNotice ? { onNotice: o.onNotice } : {},
3426
+ ...o.onIncident ? { onIncident: o.onIncident } : {},
3427
+ ...o.onStatus ? { onStatus: o.onStatus } : {}
3428
+ });
3429
+ await room.session.ready;
3430
+ return {
3431
+ session: room.session,
3432
+ isSaver: () => room.isSaver(),
3433
+ write: (reason) => room.write(reason),
3434
+ replace: (snapshot) => room.replace(snapshot),
3435
+ setCursor(c) {
3436
+ const current = awareness.getLocalState() ?? {};
3437
+ awareness.setLocalState({ ...current, sheetId: c.sheetId, row: c.row, col: c.col, ts: Date.now() });
3438
+ },
3439
+ stop() {
3440
+ room.stop();
3441
+ port.dispose?.();
3442
+ awareness.off("change", publishAwareness);
3443
+ provider.disconnect();
3444
+ awareness.destroy();
3445
+ doc.destroy();
3446
+ }
3447
+ };
3448
+ }
1553
3449
  export {
1554
3450
  COLLAB_COVERED_KEY,
1555
3451
  DOCS_COLLAB_PROTO,
@@ -1557,29 +3453,43 @@ export {
1557
3453
  DOC_LOCAL_KEYS,
1558
3454
  RICH_TEXT_EDITING,
1559
3455
  SENDER_VIEW_PARAMS,
3456
+ SHEETS_COLLAB_PROTO,
3457
+ SHEETS_EDIT_GROUP,
1560
3458
  WorkbookCollabSession,
1561
3459
  applyDocsOp,
1562
3460
  canonicalDocsSnapshot,
1563
3461
  canonicalDocsString,
1564
3462
  canonicalKeys,
3463
+ canonicalSheet,
3464
+ canonicalSheetString,
1565
3465
  composeDocsOps,
3466
+ createSheetsOtAdapter,
3467
+ decodeSheetOp,
1566
3468
  docsStateHash,
1567
3469
  documentOtFactory,
1568
3470
  documentUsesOrderedRoom,
1569
3471
  dropEmptyStyleRetains,
3472
+ encodeSheetOp,
1570
3473
  invertDocsOp,
1571
3474
  isCellEditorScratch,
1572
3475
  isNoopDocsOp,
1573
3476
  normalizeDocsOp,
1574
3477
  openDocsOtRoom,
3478
+ openSheetsOtRoom,
3479
+ rebaseSheetUndoStack,
1575
3480
  rebaseUndoStack,
1576
3481
  restoreDocumentSnapshot,
3482
+ sheetsStateHash,
1577
3483
  stampCovered,
1578
3484
  stampDeterministicIds,
3485
+ startWorkbookOtRoom,
1579
3486
  stripSenderView,
1580
3487
  takeCovered,
1581
3488
  transformDocsOp,
3489
+ transformSheetOp,
1582
3490
  transformTextX,
1583
- undoStacksOf
3491
+ undoStacksOf,
3492
+ univerSheetsOtPort,
3493
+ workbookUsesOrderedRoom
1584
3494
  };
1585
3495
  //# sourceMappingURL=univer-collab.js.map