@ai-matrx/office 0.8.19 → 0.8.21

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.
@@ -119,6 +119,7 @@ var WorkbookCollabSession = class {
119
119
  muted = 0;
120
120
  started = false;
121
121
  disposed = false;
122
+ stopColor = null;
122
123
  /** Room entries this seat holds in its content: applied from a peer, or made here. */
123
124
  applied = /* @__PURE__ */ new Set();
124
125
  /** Entries without an id (a peer on an older build) are applied once, by identity. */
@@ -140,12 +141,12 @@ var WorkbookCollabSession = class {
140
141
  uid: this.options.uid,
141
142
  clientId: this.options.clientId,
142
143
  name: this.options.uid.slice(0, 8),
143
- color: pickColor(this.options.uid),
144
144
  sheetId: null,
145
145
  row: null,
146
146
  col: null,
147
147
  ts: Date.now()
148
148
  });
149
+ this.stopColor = (0, import_collab.claimCollaboratorColor)(this.awareness, { uid: this.options.uid, clientId: this.options.clientId });
149
150
  this.provider = this.options.makeProvider({
150
151
  workbookId: this.options.workbookId,
151
152
  clientId: this.options.clientId,
@@ -206,6 +207,8 @@ var WorkbookCollabSession = class {
206
207
  this.awareness.off("change", this.awarenessObserver);
207
208
  this.awarenessObserver = null;
208
209
  }
210
+ this.stopColor?.();
211
+ this.stopColor = null;
209
212
  this.provider?.disconnect();
210
213
  this.provider = null;
211
214
  if (this.awareness) {
@@ -412,32 +415,6 @@ function stripSenderView(params) {
412
415
  function isCellEditorScratch(info) {
413
416
  return typeof info.id === "string" && info.id.startsWith("doc.mutation.");
414
417
  }
415
- var CURSOR_PALETTE = [
416
- "#3b82f6",
417
- // blue
418
- "#10b981",
419
- // emerald
420
- "#f59e0b",
421
- // amber
422
- "#ef4444",
423
- // red
424
- "#8b5cf6",
425
- // violet
426
- "#06b6d4",
427
- // cyan
428
- "#ec4899",
429
- // pink
430
- "#84cc16"
431
- // lime
432
- ];
433
- function pickColor(uid) {
434
- let h = 2166136261;
435
- for (let i = 0; i < uid.length; i++) {
436
- h ^= uid.charCodeAt(i);
437
- h = Math.imul(h, 16777619);
438
- }
439
- return CURSOR_PALETTE[Math.abs(h) % CURSOR_PALETTE.length] ?? "#ec4899";
440
- }
441
418
 
442
419
  // src/univer/collab/docs-ot/transform.ts
443
420
  var import_core = require("@univerjs/core");
@@ -1781,6 +1758,14 @@ var SHEET_MUTATIONS = {
1781
1758
  "sheet.mutation.set-worksheet-row-auto-height": covered("size", "rowsAutoHeightInfo"),
1782
1759
  "sheet.mutation.set-worksheet-col-width": covered("size", "ranges", "colWidth"),
1783
1760
  "sheet.mutation.set-worksheet-name": covered("name", "name"),
1761
+ // ── covered (C5c) ────────────────────────────────────────────────────────────────────────────────
1762
+ "sheet.mutation.set.numfmt": covered("numfmt", "values", "refMap"),
1763
+ "sheet.mutation.remove.numfmt": covered("numfmt", "ranges"),
1764
+ "sheet.mutation.set-worksheet-row-count": covered("count", "rowCount"),
1765
+ "sheet.mutation.set-worksheet-column-count": covered("count", "columnCount"),
1766
+ "sheet.mutation.insert-sheet": covered("sheet", "index", "sheet"),
1767
+ "sheet.mutation.remove-sheet": covered("sheet", "sheetIndex", "sheetsLeft"),
1768
+ "sheet.mutation.set-worksheet-order": covered("sheet", "fromOrder", "toOrder"),
1784
1769
  // ── never travels ────────────────────────────────────────────────────────────────────────────────
1785
1770
  "formula.mutation.set-formula-calculation-start": never(FORMULA_RESULT),
1786
1771
  "formula.mutation.set-trigger-formula-calculation-start": never(FORMULA_RESULT),
@@ -1815,12 +1800,7 @@ var SHEET_MUTATIONS = {
1815
1800
  "thread-comment.mutation.delete-comment": never(UNIVER_COMMENTS),
1816
1801
  // ── barriers: X (no transform yet, design §10) ───────────────────────────────────────────────────
1817
1802
  "sheet.mutation.reorder-range": barrier("X", "sort: a permutation, not transformed yet"),
1818
- "sheet.mutation.set-worksheet-row-count": barrier("X", "absolute row count; needs delta semantics"),
1819
- "sheet.mutation.set-worksheet-column-count": barrier("X", "absolute column count; needs delta semantics"),
1820
- "sheet.mutation.set-worksheet-order": barrier("X", "absolute sheet order; needs move semantics"),
1821
1803
  "sheet.mutation.move-range": barrier("X", "cut-paste carries the sender's cell matrices"),
1822
- "sheet.mutation.insert-sheet": barrier("X", "sheet add: not in C5a"),
1823
- "sheet.mutation.remove-sheet": barrier("X", "sheet remove: not in C5a"),
1824
1804
  "sheet.mutation.set-worksheet-hidden": barrier("X", "sheet-level setting: not in C5a"),
1825
1805
  "sheet.mutation.set-tab-color": barrier("X", "sheet-level setting: not in C5a"),
1826
1806
  "sheet.mutation.set-workbook-name": barrier("X", "workbook-level setting: not in C5a"),
@@ -1835,8 +1815,6 @@ var SHEET_MUTATIONS = {
1835
1815
  "sheet.mutation.set-row-visible": barrier("X", "row visibility: not in C5a"),
1836
1816
  "sheet.mutation.set-col-hidden": barrier("X", "column visibility: not in C5a"),
1837
1817
  "sheet.mutation.set-col-visible": barrier("X", "column visibility: not in C5a"),
1838
- "sheet.mutation.set.numfmt": barrier("X", "number formats by range: not in C5a"),
1839
- "sheet.mutation.remove.numfmt": barrier("X", "number formats by range: not in C5a"),
1840
1818
  "sheet.mutation.add-range-protection": barrier("X", "permissions: not in C5a"),
1841
1819
  "sheet.mutation.set-range-protection": barrier("X", "permissions: not in C5a"),
1842
1820
  "sheet.mutation.delete-range-protection": barrier("X", "permissions: not in C5a"),
@@ -2231,7 +2209,7 @@ function refSheetsFor(texts, sheets) {
2231
2209
  }
2232
2210
 
2233
2211
  // src/collab/sheets/transform/transform.ts
2234
- var SHEET_TRANSFORMER_VERSION = "c5b-1";
2212
+ var SHEET_TRANSFORMER_VERSION = "c5c-1";
2235
2213
  var ID = {
2236
2214
  values: "sheet.mutation.set-range-values",
2237
2215
  insertRow: "sheet.mutation.insert-row",
@@ -2248,7 +2226,14 @@ var ID = {
2248
2226
  colWidth: "sheet.mutation.set-worksheet-col-width",
2249
2227
  name: "sheet.mutation.set-worksheet-name",
2250
2228
  setName: "formula.mutation.set-defined-name",
2251
- removeName: "formula.mutation.remove-defined-name"
2229
+ removeName: "formula.mutation.remove-defined-name",
2230
+ setNumfmt: "sheet.mutation.set.numfmt",
2231
+ removeNumfmt: "sheet.mutation.remove.numfmt",
2232
+ rowCount: "sheet.mutation.set-worksheet-row-count",
2233
+ colCount: "sheet.mutation.set-worksheet-column-count",
2234
+ insertSheet: "sheet.mutation.insert-sheet",
2235
+ removeSheet: "sheet.mutation.remove-sheet",
2236
+ sheetOrder: "sheet.mutation.set-worksheet-order"
2252
2237
  };
2253
2238
  var PAIR_BARRIERS = {};
2254
2239
  var pairKey = (a, b) => a < b ? `${a}|${b}` : `${b}|${a}`;
@@ -2360,6 +2345,20 @@ function mergeThrough(s, m) {
2360
2345
  }
2361
2346
  return { range: m, fixup: false };
2362
2347
  }
2348
+ function mergeFixupsOwed(m, mergesBefore) {
2349
+ const st = structuralOf(m);
2350
+ if (!st) return null;
2351
+ const remove = [];
2352
+ const add = [];
2353
+ for (const q of mergesBefore) {
2354
+ const t = mergeThrough(st, q);
2355
+ if (!t.fixup) continue;
2356
+ remove.push({ startRow: q.startRow, endRow: q.endRow, startColumn: q.startColumn, endColumn: q.endColumn, ...q.rangeType !== void 0 ? { rangeType: q.rangeType } : {} });
2357
+ if (t.range) add.push({ ...t.range });
2358
+ }
2359
+ return remove.length ? { remove, add } : null;
2360
+ }
2361
+ var isStructuralMutation = (m) => structuralOf(m) !== null;
2363
2362
  function exactMergeRemovals(group, merges) {
2364
2363
  const sim = new Map(Object.entries(merges).map(([k, v]) => [k, v.map((r) => ({ ...r }))]));
2365
2364
  const out = [];
@@ -2406,8 +2405,24 @@ function cellsMutation(template, cells) {
2406
2405
  function putCell(cells, r, c, v) {
2407
2406
  (cells[r] ??= {})[c] = v;
2408
2407
  }
2408
+ function cellsOverlap(a, b) {
2409
+ for (const r of Object.keys(a)) {
2410
+ const br = b[r];
2411
+ if (!br) continue;
2412
+ for (const c of Object.keys(a[r] ?? {})) if (c in br) return true;
2413
+ }
2414
+ return false;
2415
+ }
2409
2416
  var isEmptyMatrix = (cells) => Object.values(cells).every((row) => Object.keys(row).length === 0);
2417
+ var cellBarrierCache = /* @__PURE__ */ new WeakMap();
2410
2418
  function cellBarrier(m) {
2419
+ const hit = cellBarrierCache.get(m);
2420
+ if (hit !== void 0) return hit;
2421
+ const why = cellBarrierOf(m);
2422
+ cellBarrierCache.set(m, why);
2423
+ return why;
2424
+ }
2425
+ function cellBarrierOf(m) {
2411
2426
  if (m.params.isOverrideStyle) return "set-range-values with isOverrideStyle (whole-style replace) is not covered";
2412
2427
  let why = null;
2413
2428
  forEachCell(cellsOf(m), (_r, _c, v) => {
@@ -2489,6 +2504,7 @@ function transformCell(X, Y4, side) {
2489
2504
  function transformCellsOverCells(x, y, side) {
2490
2505
  if (sheetOf(x) !== sheetOf(y)) return ok([x]);
2491
2506
  const ycells = cellsOf(y);
2507
+ if (!cellsOverlap(cellsOf(x), ycells)) return ok([x]);
2492
2508
  const xd = isDerived(x);
2493
2509
  const yd = isDerived(y);
2494
2510
  const eff = derivedSide(x, y, side);
@@ -2516,7 +2532,7 @@ function transformCellsOverCells(x, y, side) {
2516
2532
  const op = passes.filter((p) => !isEmptyMatrix(p)).map((p) => cellsMutation(x, p));
2517
2533
  return ok(op, lost, dropped);
2518
2534
  }
2519
- var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived"];
2535
+ var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived", "sheetIndex", "sheetsLeft"];
2520
2536
  var isDerived = (m) => m.params.derived === true;
2521
2537
  function derivedSide(x, y, side) {
2522
2538
  const xd = isDerived(x);
@@ -2538,7 +2554,15 @@ function withRefSheets(params, rs) {
2538
2554
  return out;
2539
2555
  }
2540
2556
  var hasFormulaText = (v) => !!v && (isFormulaText(v.f) || typeof v.ref === "string");
2557
+ var hasFormulaCache = /* @__PURE__ */ new WeakMap();
2541
2558
  function hasFormula(m) {
2559
+ const hit = hasFormulaCache.get(m);
2560
+ if (hit !== void 0) return hit;
2561
+ const any = hasFormulaOf(m);
2562
+ hasFormulaCache.set(m, any);
2563
+ return any;
2564
+ }
2565
+ function hasFormulaOf(m) {
2542
2566
  let any = false;
2543
2567
  forEachCell(cellsOf(m), (_r, _c, v) => {
2544
2568
  any ||= hasFormulaText(v);
@@ -2577,15 +2601,18 @@ function cellThrough(sheet, change, r, c) {
2577
2601
  return nr === null || nc === null ? null : [nr, nc];
2578
2602
  }
2579
2603
  function cellsOverChange(x, change) {
2604
+ if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok([x]);
2580
2605
  const ctx = formulaCtx(x);
2581
2606
  const out = {};
2582
2607
  const dropped = [];
2583
2608
  let why = null;
2609
+ let changed = false;
2584
2610
  forEachCell(cellsOf(x), (r, c, v) => {
2585
2611
  if (why) return;
2586
2612
  const at = cellThrough(sheetOf(x), change, r, c);
2587
2613
  if (!at) {
2588
2614
  dropped.push(cellRef(sheetOf(x), r, c));
2615
+ changed = true;
2589
2616
  return;
2590
2617
  }
2591
2618
  let e = v;
@@ -2596,14 +2623,19 @@ function cellsOverChange(x, change) {
2596
2623
  return;
2597
2624
  }
2598
2625
  e = res.entry;
2626
+ if (res.changed) changed = true;
2599
2627
  }
2628
+ if (at[0] !== r || at[1] !== c) changed = true;
2600
2629
  putCell(out, at[0], at[1], e);
2601
2630
  });
2602
2631
  if (why) return barrier2(why);
2603
- const params = { ...withRefSheets(x.params, refSheetsAfter(ctx.refSheets, change)), cellValue: out };
2632
+ const rsAfter = refSheetsAfter(ctx.refSheets, change);
2633
+ if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok([x]);
2634
+ const params = { ...withRefSheets(x.params, rsAfter), cellValue: out };
2604
2635
  return ok(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
2605
2636
  }
2606
2637
  function rewritesOf(y, change) {
2638
+ if (!hasFormula(y)) return null;
2607
2639
  const ctx = formulaCtx(y);
2608
2640
  const out = {};
2609
2641
  let why = null;
@@ -2749,6 +2781,255 @@ function buildSize(template, values) {
2749
2781
  const value = uniform !== void 0 && [...values.values()].every((v) => v === uniform) ? uniform : Object.fromEntries(values);
2750
2782
  return { id: template.id, params: { ...p, ranges, [field]: value } };
2751
2783
  }
2784
+ var isNumfmt = (m) => m.id === ID.setNumfmt || m.id === ID.removeNumfmt;
2785
+ function nfParts(m) {
2786
+ if (m.id === ID.removeNumfmt) return [{ key: null, ranges: (m.params.ranges ?? []).map((r) => ({ ...r })) }];
2787
+ const values = m.params.values ?? {};
2788
+ return Object.keys(values).map((k) => ({ key: k, ranges: (values[k]?.ranges ?? []).map((r) => ({ ...r })) }));
2789
+ }
2790
+ function nfBuild(m, parts) {
2791
+ const keep = parts.filter((p) => p.ranges.length);
2792
+ if (!keep.length) return [];
2793
+ if (m.id === ID.removeNumfmt) return [{ id: m.id, params: { ...m.params, ranges: keep[0].ranges } }];
2794
+ const values = {};
2795
+ const refMap = {};
2796
+ const srcValues = m.params.values ?? {};
2797
+ const srcRef = m.params.refMap ?? {};
2798
+ for (const p of keep) {
2799
+ values[p.key] = { ...srcValues[p.key], ranges: p.ranges };
2800
+ refMap[p.key] = srcRef[p.key];
2801
+ }
2802
+ return [{ id: m.id, params: { ...m.params, values, refMap } }];
2803
+ }
2804
+ function nfValueAt(m, row, col) {
2805
+ for (const p of nfParts(m))
2806
+ if (p.ranges.some((r) => r.startRow <= row && row <= r.endRow && r.startColumn <= col && col <= r.endColumn)) {
2807
+ if (p.key === null) return null;
2808
+ const ref = (m.params.refMap ?? {})[p.key];
2809
+ return { pattern: ref?.pattern };
2810
+ }
2811
+ return void 0;
2812
+ }
2813
+ function spanThrough(op, lo, hi) {
2814
+ const pieces = [];
2815
+ if (op.kind === "insert") pieces.push([0, op.at - 1, 0], [op.at, Infinity, op.count]);
2816
+ else if (op.kind === "remove") pieces.push([0, op.start - 1, 0], [op.start + op.count, Infinity, -op.count]);
2817
+ else if (op.count <= 0 || op.to >= op.from && op.to <= op.from + op.count) pieces.push([0, Infinity, 0]);
2818
+ else if (op.to > op.from) {
2819
+ const n = op.count;
2820
+ pieces.push([0, op.from - 1, 0], [op.from, op.from + n - 1, op.to - n - op.from], [op.from + n, op.to - 1, -n], [op.to, Infinity, 0]);
2821
+ } else {
2822
+ const n = op.count;
2823
+ pieces.push([0, op.to - 1, 0], [op.to, op.from - 1, n], [op.from, op.from + n - 1, op.to - op.from], [op.from + n, Infinity, 0]);
2824
+ }
2825
+ const out = [];
2826
+ for (const [a, b, d] of pieces) {
2827
+ const x0 = Math.max(a, lo);
2828
+ const x1 = Math.min(b, hi);
2829
+ if (x0 <= x1) out.push([x0 + d, x1 + d]);
2830
+ }
2831
+ out.sort((p, q) => p[0] - q[0]);
2832
+ const merged = [];
2833
+ for (const p of out) {
2834
+ const last = merged[merged.length - 1];
2835
+ if (last && last[1] + 1 >= p[0]) last[1] = Math.max(last[1], p[1]);
2836
+ else merged.push([p[0], p[1]]);
2837
+ }
2838
+ return merged;
2839
+ }
2840
+ function rectsThrough(st, rects) {
2841
+ const [a0, a1] = S(st.axis);
2842
+ const out = [];
2843
+ for (const r of rects) for (const [lo, hi] of spanThrough(st.op, r[a0], r[a1])) out.push({ ...r, [a0]: lo, [a1]: hi });
2844
+ return out;
2845
+ }
2846
+ function rectMinus(a, b) {
2847
+ if (a.startRow > b.endRow || b.startRow > a.endRow || a.startColumn > b.endColumn || b.startColumn > a.endColumn) return [a];
2848
+ const out = [];
2849
+ if (a.startRow < b.startRow) out.push({ ...a, endRow: b.startRow - 1 });
2850
+ if (a.endRow > b.endRow) out.push({ ...a, startRow: b.endRow + 1 });
2851
+ const r0 = Math.max(a.startRow, b.startRow);
2852
+ const r1 = Math.min(a.endRow, b.endRow);
2853
+ if (a.startColumn < b.startColumn) out.push({ ...a, startRow: r0, endRow: r1, endColumn: b.startColumn - 1 });
2854
+ if (a.endColumn > b.endColumn) out.push({ ...a, startRow: r0, endRow: r1, startColumn: b.endColumn + 1 });
2855
+ return out;
2856
+ }
2857
+ function rectsMinus(as, bs) {
2858
+ let cur = as;
2859
+ for (const b of bs) cur = cur.flatMap((a) => rectMinus(a, b));
2860
+ return cur;
2861
+ }
2862
+ function nWrites(m) {
2863
+ const out = [];
2864
+ forEachCell(cellsOf(m), (r, c, v) => {
2865
+ if (v === null || v.s === null || v.s && typeof v.s === "object" && "n" in v.s)
2866
+ out.push({ startRow: r, endRow: r, startColumn: c, endColumn: c });
2867
+ });
2868
+ return out;
2869
+ }
2870
+ function numfmtPair(x, y, side, sx, sy) {
2871
+ const nx = isNumfmt(x);
2872
+ const ny = isNumfmt(y);
2873
+ if (!nx && !ny) return null;
2874
+ if (nx && sy) return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
2875
+ if (ny && sx) return ok([x]);
2876
+ if (nx && ny) {
2877
+ if (side === "left") return ok([x]);
2878
+ const ys = nfParts(y).flatMap((p) => p.ranges);
2879
+ return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
2880
+ }
2881
+ if (nx && y.id === ID.values) {
2882
+ if (side === "left") return ok([x]);
2883
+ const ys = nWrites(y);
2884
+ return ys.length ? ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok([x]);
2885
+ }
2886
+ if (ny && x.id === ID.values) {
2887
+ if (side === "left") return ok([x]);
2888
+ const out = {};
2889
+ const tail = {};
2890
+ let touched = false;
2891
+ forEachCell(cellsOf(x), (r, c, v) => {
2892
+ const n = nfValueAt(y, r, c);
2893
+ if (n === void 0) return putCell(out, r, c, v);
2894
+ if (v === null || v.s === null) {
2895
+ putCell(out, r, c, v);
2896
+ if (n) {
2897
+ putCell(tail, r, c, { s: { n } });
2898
+ touched = true;
2899
+ }
2900
+ return;
2901
+ }
2902
+ if (v.s && typeof v.s === "object" && "n" in v.s) {
2903
+ const { n: _drop, ...rest } = v.s;
2904
+ const e = { ...v };
2905
+ if (Object.keys(rest).length) e.s = rest;
2906
+ else delete e.s;
2907
+ touched = true;
2908
+ if (Object.keys(e).length) putCell(out, r, c, e);
2909
+ return;
2910
+ }
2911
+ putCell(out, r, c, v);
2912
+ });
2913
+ if (!touched) return ok([x]);
2914
+ const ops = [];
2915
+ if (!isEmptyMatrix(out)) ops.push(cellsMutation(x, out));
2916
+ if (!isEmptyMatrix(tail)) ops.push({ id: ID.values, params: { subUnitId: sheetOf(x), cellValue: tail } });
2917
+ return ok(ops);
2918
+ }
2919
+ return ok([x]);
2920
+ }
2921
+ var isCount = (m) => m.id === ID.rowCount || m.id === ID.colCount;
2922
+ var countAxis = (m) => m.id === ID.rowCount ? "row" : "col";
2923
+ var countKey = (m) => m.id === ID.rowCount ? "rowCount" : "columnCount";
2924
+ function countPair(x, y, sy) {
2925
+ if (!isCount(x)) return isCount(y) ? ok([x]) : null;
2926
+ const k = countKey(x);
2927
+ const v = Number(x.params[k]);
2928
+ if (sy) {
2929
+ if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok([x]);
2930
+ const d = sy.op.kind === "insert" ? sy.op.count : -sy.op.count;
2931
+ return ok([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
2932
+ }
2933
+ if (isCount(y) && y.id === x.id) {
2934
+ const w = Number(y.params[k]);
2935
+ return ok([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
2936
+ }
2937
+ return ok([x]);
2938
+ }
2939
+ var isSheetOp = (m) => m.id === ID.insertSheet || m.id === ID.removeSheet || m.id === ID.sheetOrder;
2940
+ var sheetIdOf = (m) => m.id === ID.insertSheet ? String(m.params.sheet?.id ?? "") : sheetOf(m);
2941
+ function sheetAxisOf(m) {
2942
+ const p = m.params;
2943
+ if (m.id === ID.insertSheet) return typeof p.index === "number" ? { kind: "insert", at: p.index, count: 1 } : null;
2944
+ if (m.id === ID.removeSheet) return typeof p.sheetIndex === "number" ? { kind: "remove", start: p.sheetIndex, count: 1 } : null;
2945
+ if (m.id === ID.sheetOrder) {
2946
+ const f = Number(p.fromOrder);
2947
+ const t = Number(p.toOrder);
2948
+ return { kind: "move", from: f, count: 1, to: t > f ? t + 1 : t };
2949
+ }
2950
+ return null;
2951
+ }
2952
+ function buildSheetOp(template, op) {
2953
+ if (op.kind === "insert") return { id: template.id, params: { ...template.params, index: op.at } };
2954
+ if (op.kind === "remove") return { id: template.id, params: { ...template.params, sheetIndex: op.start } };
2955
+ return { id: template.id, params: { ...template.params, fromOrder: op.from, toOrder: op.to > op.from ? op.to - 1 : op.to } };
2956
+ }
2957
+ function namesSheet(m, id) {
2958
+ const rs = refSheetsOf(m);
2959
+ return !!rs && Object.values(rs).includes(id) && (m.id === ID.setName || hasFormula(m));
2960
+ }
2961
+ function sheetPair(x, y, side) {
2962
+ const xs = isSheetOp(x);
2963
+ const ys = isSheetOp(y);
2964
+ if (!xs && !ys) return null;
2965
+ if (xs && ys) {
2966
+ const a = sheetAxisOf(x);
2967
+ const b = sheetAxisOf(y);
2968
+ if (!a || !b) return barrier2("a sheet add or remove without its index (capture must call annotateSheetOps)");
2969
+ if (x.id === ID.insertSheet && y.id === ID.insertSheet && sheetIdOf(x) === sheetIdOf(y)) {
2970
+ return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok([]) : barrier2("the same sheet id added twice with different content");
2971
+ }
2972
+ if (x.id === ID.removeSheet && typeof x.params.sheetsLeft === "number" && sheetIdOf(x) !== sheetIdOf(y) && (y.id === ID.removeSheet || y.id === ID.insertSheet)) {
2973
+ const left = x.params.sheetsLeft + (y.id === ID.insertSheet ? 1 : -1);
2974
+ if (left < 1) return barrier2("concurrent sheet removes would leave the workbook without a sheet");
2975
+ const out2 = transformAxis(a, b, side);
2976
+ if (!out2) return barrier2("sheet order: no transform");
2977
+ return ok(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
2978
+ }
2979
+ const out = transformAxis(a, b, side);
2980
+ if (!out) return barrier2("sheet order: no transform");
2981
+ return ok(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
2982
+ }
2983
+ if (ys) {
2984
+ if (y.id !== ID.removeSheet) return ok([x]);
2985
+ const gone2 = sheetOf(y);
2986
+ if (namesSheet(x, gone2)) return barrier2("a formula names a sheet removed at the same time");
2987
+ if (sheetOf(x) === gone2 && x.id !== ID.setName && x.id !== ID.removeName)
2988
+ return ok([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
2989
+ return ok([x]);
2990
+ }
2991
+ if (x.id !== ID.removeSheet) return ok([x]);
2992
+ const gone = sheetOf(x);
2993
+ if (namesSheet(y, gone)) return barrier2("a formula names a sheet removed at the same time");
2994
+ return ok([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
2995
+ }
2996
+ function annotateSheetOps(group, sheetOrder) {
2997
+ const order = [...sheetOrder];
2998
+ return group.map((m) => {
2999
+ if (m.id === ID.insertSheet) {
3000
+ const index = typeof m.params.index === "number" ? Math.min(m.params.index, order.length) : order.length;
3001
+ order.splice(index, 0, sheetIdOf(m));
3002
+ return index === m.params.index ? m : { id: m.id, params: { ...m.params, index } };
3003
+ }
3004
+ if (m.id === ID.removeSheet) {
3005
+ const i = order.indexOf(sheetOf(m));
3006
+ if (i >= 0) order.splice(i, 1);
3007
+ return i >= 0 ? { id: m.id, params: { ...m.params, sheetIndex: i, sheetsLeft: order.length } } : m;
3008
+ }
3009
+ if (m.id === ID.sheetOrder) {
3010
+ const f = Number(m.params.fromOrder);
3011
+ const [id] = order.splice(f, 1);
3012
+ order.splice(Number(m.params.toOrder), 0, id ?? sheetOf(m));
3013
+ }
3014
+ return m;
3015
+ });
3016
+ }
3017
+ function inlineSheetStyles(sheet, styleOf) {
3018
+ const out = JSON.parse(JSON.stringify(sheet));
3019
+ const fix = (o) => {
3020
+ if (o && typeof o.s === "string") {
3021
+ const st = styleOf(o.s);
3022
+ if (st) o.s = JSON.parse(JSON.stringify(st));
3023
+ }
3024
+ };
3025
+ for (const row of Object.values(out.cellData ?? {})) for (const cell of Object.values(row ?? {})) fix(cell);
3026
+ for (const key of ["rowData", "columnData"]) for (const v of Object.values(out[key] ?? {})) fix(v);
3027
+ if (typeof out.defaultStyle === "string") {
3028
+ const st = styleOf(out.defaultStyle);
3029
+ if (st) out.defaultStyle = JSON.parse(JSON.stringify(st));
3030
+ }
3031
+ return out;
3032
+ }
2752
3033
  function familyOf(id) {
2753
3034
  const e = SHEET_MUTATIONS[id];
2754
3035
  return e && e.kind === "covered" ? e.family : "";
@@ -2765,6 +3046,8 @@ function transformMutation(x, y, side) {
2765
3046
  }
2766
3047
  const pb = PAIR_BARRIERS[pairKey(x.id, y.id)];
2767
3048
  if (pb) return barrier2(`${x.id} \xD7 ${y.id}: ${pb.reason}${pb.seed === null ? "" : ` (fuzz seed ${pb.seed})`}`);
3049
+ const sp = sheetPair(x, y, side);
3050
+ if (sp) return sp;
2768
3051
  const fp = formulaPair(x, y, side);
2769
3052
  if (fp) return fp;
2770
3053
  if (sheetOf(x) !== sheetOf(y)) return ok([x]);
@@ -2772,6 +3055,10 @@ function transformMutation(x, y, side) {
2772
3055
  const fy = familyOf(y.id);
2773
3056
  const sy = structuralOf(y);
2774
3057
  const sx = structuralOf(x);
3058
+ const cp = countPair(x, y, sy);
3059
+ if (cp) return cp;
3060
+ const np = numfmtPair(x, y, side, sx, sy);
3061
+ if (np) return np;
2775
3062
  if (sx && sy) {
2776
3063
  if (sx.axis !== sy.axis) return ok([x]);
2777
3064
  const out = transformAxis(sx.op, sy.op, side);
@@ -2879,22 +3166,45 @@ function tSeq(xs, ys, side, acc) {
2879
3166
  acc.dropped.push(...a.dropped);
2880
3167
  return [a.op, b.op];
2881
3168
  }
3169
+ const outX = [];
3170
+ let curY = ys;
3171
+ for (const x of xs) {
3172
+ let curX = [x];
3173
+ const nextY = [];
3174
+ for (const y of curY) {
3175
+ if (curX.length === 0) {
3176
+ nextY.push(y);
3177
+ continue;
3178
+ }
3179
+ const r = tSeq(curX, [y], side, acc);
3180
+ if (blocked(r)) return r;
3181
+ curX = r[0];
3182
+ for (const m of r[1]) nextY.push(m);
3183
+ }
3184
+ for (const m of curX) outX.push(m);
3185
+ curY = nextY;
3186
+ }
3187
+ return [outX, curY];
3188
+ }
3189
+ function tSeqOld(xs, ys, side, acc) {
3190
+ if (xs.length === 0 || ys.length === 0) return [xs, ys];
3191
+ if (xs.length === 1 && ys.length === 1) return tSeq(xs, ys, side, acc);
2882
3192
  if (xs.length > 1) {
2883
- const first2 = tSeq([xs[0]], ys, side, acc);
3193
+ const first2 = tSeqOld([xs[0]], ys, side, acc);
2884
3194
  if (blocked(first2)) return first2;
2885
- const rest2 = tSeq(xs.slice(1), first2[1], side, acc);
3195
+ const rest2 = tSeqOld(xs.slice(1), first2[1], side, acc);
2886
3196
  if (blocked(rest2)) return rest2;
2887
3197
  return [[...first2[0], ...rest2[0]], rest2[1]];
2888
3198
  }
2889
- const first = tSeq(xs, [ys[0]], side, acc);
3199
+ const first = tSeqOld(xs, [ys[0]], side, acc);
2890
3200
  if (blocked(first)) return first;
2891
- const rest = tSeq(first[0], ys.slice(1), side, acc);
3201
+ const rest = tSeqOld(first[0], ys.slice(1), side, acc);
2892
3202
  if (blocked(rest)) return rest;
2893
3203
  return [rest[0], [...first[1], ...rest[1]]];
2894
3204
  }
2895
3205
  function transformGroup(x, y, side) {
2896
3206
  const acc = { lost: [], dropped: [] };
2897
- const r = tSeq([...x], [...y], side, acc);
3207
+ const r = (process.env.OLD_TSEQ ? tSeqOld : tSeq)([...x], [...y], side, acc);
2898
3208
  if (blocked(r)) return r;
2899
3209
  return { op: r[0], lost: [...new Set(acc.lost)], dropped: [...new Set(acc.dropped)] };
2900
3210
  }
@@ -2964,7 +3274,7 @@ async function sheetsStateHash(snapshot) {
2964
3274
  }
2965
3275
 
2966
3276
  // src/univer/collab/sheets-ot/room.ts
2967
- var SHEETS_COLLAB_PROTO = 1;
3277
+ var SHEETS_COLLAB_PROTO = 2;
2968
3278
  var SHEETS_EDIT_GROUP = "sheets.edit";
2969
3279
  var flip2 = (side) => side === "left" ? "right" : "left";
2970
3280
  var isNoopSheetOp = (op) => op == null || op.length === 0;
@@ -3011,6 +3321,11 @@ function travelingShape(m) {
3011
3321
  }
3012
3322
  return { id: m.id, params };
3013
3323
  }
3324
+ var shapedLists = /* @__PURE__ */ new WeakMap();
3325
+ function cachedShape(list) {
3326
+ const hit = shapedLists.get(list);
3327
+ return hit && hit.src.length === list.length && hit.src.every((m, i) => m === list[i]) ? hit.shaped : null;
3328
+ }
3014
3329
  function rebaseSheetUndoStack(items, remote, unitId) {
3015
3330
  if (isNoopSheetOp(remote)) return 0;
3016
3331
  let dropped = 0;
@@ -3022,7 +3337,11 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3022
3337
  if (!ok2 || !list?.length) continue;
3023
3338
  const isOperation = (id) => !SHEET_MUTATIONS[id] && id.includes(".operation.");
3024
3339
  const operations = list.filter((m) => isOperation(m.id));
3025
- const shaped = list.filter((m) => !isOperation(m.id)).map(travelingShape);
3340
+ let shaped = cachedShape(list);
3341
+ if (!shaped) {
3342
+ shaped = list.filter((m) => !isOperation(m.id)).map(travelingShape);
3343
+ shapedLists.set(list, { src: list.slice(), shaped });
3344
+ }
3026
3345
  if (shaped.some((m) => m === null)) {
3027
3346
  ok2 = false;
3028
3347
  continue;
@@ -3034,8 +3353,10 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3034
3353
  ok2 = false;
3035
3354
  continue;
3036
3355
  }
3037
- if (JSON.stringify(r.op) === JSON.stringify(shaped)) continue;
3038
- item[key] = [...r.op.map((m) => ({ id: m.id, params: { ...forApply(m).params, unitId } })), ...operations];
3356
+ if (r.op.length === shaped.length && r.op.every((m, i2) => m === shaped[i2])) continue;
3357
+ const next = [...r.op.map((m) => ({ id: m.id, params: { ...forApply(m).params, unitId } })), ...operations];
3358
+ shapedLists.set(next, { src: next.slice(), shaped: r.op });
3359
+ item[key] = next;
3039
3360
  } catch {
3040
3361
  ok2 = false;
3041
3362
  }
@@ -3110,7 +3431,7 @@ function createSheetsOtAdapter(port, hooks = {}) {
3110
3431
  });
3111
3432
  });
3112
3433
  }
3113
- return sheetsStateHash(port.snapshot());
3434
+ return (hooks.stateHash ?? sheetsStateHash)(port.snapshot());
3114
3435
  },
3115
3436
  held: () => queue.length,
3116
3437
  rebaseLocalOverHeld(local) {
@@ -3222,6 +3543,8 @@ var VALUES = "sheet.mutation.set-range-values";
3222
3543
  var ADD_MERGE = "sheet.mutation.add-worksheet-merge";
3223
3544
  var REMOVE_MERGE = "sheet.mutation.remove-worksheet-merge";
3224
3545
  var SHEET_NAME = "sheet.mutation.set-worksheet-name";
3546
+ var INSERT_SHEET = "sheet.mutation.insert-sheet";
3547
+ var RESHAPE = /* @__PURE__ */ new Set(["sheet.mutation.set-worksheet-row-count", "sheet.mutation.set-worksheet-column-count", "sheet.mutation.remove-sheet", INSERT_SHEET]);
3225
3548
  var DEPTH_GUARD = /* @__PURE__ */ Symbol.for("ai-matrx.office.sheets.command-depth-guard");
3226
3549
  var json = (v) => v === void 0 ? v : JSON.parse(JSON.stringify(v));
3227
3550
  var flagged = (options) => {
@@ -3258,7 +3581,8 @@ function univerSheetsOtPort(o) {
3258
3581
  for (const [id, d] of Object.entries(map)) out[id] = String(d?.name ?? "");
3259
3582
  return out;
3260
3583
  };
3261
- const openGroup = (label) => ({ label, sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
3584
+ const sheetOrder = () => (o.workbook()?.getSheets() ?? []).map((ws) => ws.getSheetId());
3585
+ const openGroup = (label) => ({ label, order: sheetOrder(), sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
3262
3586
  const emit = (e) => {
3263
3587
  for (const l of [...listeners]) {
3264
3588
  try {
@@ -3274,7 +3598,8 @@ function univerSheetsOtPort(o) {
3274
3598
  if (!g) return;
3275
3599
  if (g.notShared) emit({ kind: "not_shared", mutationId: g.notShared, label: g.label });
3276
3600
  else if (g.mutations.length) {
3277
- const mutations = annotateFormulas(g.mutations, g.sheets, g.names);
3601
+ const mutations = annotateSheetOps(annotateFormulas(g.mutations, g.sheets, g.names), g.order);
3602
+ if (mutations.some((m) => isStructuralMutation(m) || RESHAPE.has(m.id))) clampSelection();
3278
3603
  const known = g.inverses.every((i) => i !== void 0);
3279
3604
  const inverse = known ? annotateFormulas(g.inverses.slice().reverse().flat(), g.sheets, g.names) : void 0;
3280
3605
  emit({ kind: "group", mutations, ...inverse !== void 0 ? { inverse } : {}, label: g.label });
@@ -3308,7 +3633,27 @@ function univerSheetsOtPort(o) {
3308
3633
  }
3309
3634
  if (info.id === SHEET_NAME) record.name = ws.getName();
3310
3635
  pre.set(p, record);
3636
+ const owed = isStructuralMutation({ id: info.id, params: p }) ? mergeFixupsOwed({ id: info.id, params: p }, record.merges ?? []) : null;
3637
+ if (owed) {
3638
+ runOwn(REMOVE_MERGE, String(p.subUnitId), owed.remove, ADD_MERGE);
3639
+ if (owed.add.length) record.addAfter = owed.add;
3640
+ }
3311
3641
  });
3642
+ const runOwn = (id, sheet, ranges, inverseId) => {
3643
+ const u = unitId();
3644
+ if (!u) return;
3645
+ applying = true;
3646
+ try {
3647
+ cs.syncExecuteCommand(id, { unitId: u, subUnitId: sheet, ranges: json(ranges) }, { onlyLocal: true });
3648
+ } finally {
3649
+ applying = false;
3650
+ }
3651
+ if (!group) group = openGroup(null);
3652
+ if (!group.notShared) {
3653
+ group.mutations.push({ id, params: { subUnitId: sheet, ranges: json(ranges) } });
3654
+ group.inverses.push([{ id: inverseId, params: { subUnitId: sheet, ranges: json(ranges) } }]);
3655
+ }
3656
+ };
3312
3657
  const after = cs.onCommandExecuted((info) => {
3313
3658
  if (info.type !== COMMAND) return;
3314
3659
  const at = tracker.stack.lastIndexOf(info.id);
@@ -3406,6 +3751,8 @@ function univerSheetsOtPort(o) {
3406
3751
  if (!m2) return { m: null, inverse: void 0 };
3407
3752
  return { m: m2, inverse: [{ id: ADD_MERGE, params: { subUnitId: sheet, ranges: json(m2.params.ranges) } }] };
3408
3753
  }
3754
+ if (info.id === INSERT_SHEET && params.sheet && typeof params.sheet === "object")
3755
+ params.sheet = inlineSheetStyles(params.sheet, (id) => o.workbook()?.getStyles().get(id));
3409
3756
  const m = { id: info.id, params };
3410
3757
  switch (info.id) {
3411
3758
  case "sheet.mutation.insert-row":
@@ -3422,8 +3769,7 @@ function univerSheetsOtPort(o) {
3422
3769
  };
3423
3770
  const collab = cs.onMutationExecutedForCollab((info, options) => {
3424
3771
  if (applying || flagged(options) || !mine(info.params)) return;
3425
- const lone = !group;
3426
- if (lone) group = openGroup(null);
3772
+ if (!group) group = openGroup(null);
3427
3773
  const g = group;
3428
3774
  if (!g.notShared) {
3429
3775
  const r = capture(info);
@@ -3433,11 +3779,29 @@ function univerSheetsOtPort(o) {
3433
3779
  g.inverses.push(r.inverse);
3434
3780
  }
3435
3781
  }
3436
- if (lone && tracker.stack.length === 0) settle();
3782
+ const owedAdd = pre.get(info.params)?.addAfter;
3783
+ if (owedAdd?.length) runOwn(ADD_MERGE, String(info.params.subUnitId ?? ""), owedAdd, REMOVE_MERGE);
3784
+ if (tracker.stack.length === 0) settle();
3437
3785
  });
3786
+ const clampSelection = () => {
3787
+ const sel = o.selections;
3788
+ if (!sel) return;
3789
+ try {
3790
+ const sheet = sel.sheetId();
3791
+ const ws = sheet ? o.workbook()?.getSheetBySheetId(sheet) : null;
3792
+ const current = sel.get();
3793
+ if (!ws || !current?.length) return;
3794
+ const rows = ws.getMaxRows?.() ?? Number.MAX_SAFE_INTEGER;
3795
+ const cols = ws.getMaxColumns?.() ?? Number.MAX_SAFE_INTEGER;
3796
+ const next = moveSelectionsThrough(json(current), { id: "", params: {} }, rows, cols);
3797
+ if (JSON.stringify(next) !== JSON.stringify(current)) sel.set(next);
3798
+ } catch (err) {
3799
+ console.warn("[sheets-ot] could not keep this seat's selection inside the sheet after its own row or column change", err);
3800
+ }
3801
+ };
3438
3802
  const followSelection = (m) => {
3439
3803
  const sel = o.selections;
3440
- if (!sel || !axisOpOf(m)) return;
3804
+ if (!sel || !axisOpOf(m) && !RESHAPE.has(m.id)) return;
3441
3805
  try {
3442
3806
  const sheet = String(m.params.subUnitId ?? "");
3443
3807
  if (sel.sheetId() !== sheet) return;
@@ -3643,15 +4007,6 @@ async function workbookUsesOrderedRoom(workbookId, knob, isNewWorkbook) {
3643
4007
  if (knob === "new") return isNewWorkbook();
3644
4008
  return false;
3645
4009
  }
3646
- function pickColor2(uid) {
3647
- const palette = ["#ef4444", "#f59e0b", "#10b981", "#3b82f6", "#8b5cf6", "#ec4899", "#14b8a6", "#f97316"];
3648
- let h = 2166136261;
3649
- for (let i = 0; i < uid.length; i++) {
3650
- h ^= uid.charCodeAt(i);
3651
- h = Math.imul(h, 16777619);
3652
- }
3653
- return palette[Math.abs(h) % palette.length] ?? "#ec4899";
3654
- }
3655
4010
  async function startWorkbookOtRoom(port, o) {
3656
4011
  const latest = await getLatestSnapshot(o.workbookId);
3657
4012
  if (!latest.success) throw new Error(latest.error);
@@ -3668,12 +4023,12 @@ async function startWorkbookOtRoom(port, o) {
3668
4023
  uid: o.uid,
3669
4024
  clientId: o.clientId,
3670
4025
  name: o.displayName ?? o.uid.slice(0, 8),
3671
- color: pickColor2(o.uid),
3672
4026
  sheetId: null,
3673
4027
  row: null,
3674
4028
  col: null,
3675
4029
  ts: Date.now()
3676
4030
  });
4031
+ const stopColor = (0, import_collab6.claimCollaboratorColor)(awareness, { uid: o.uid, clientId: o.clientId });
3677
4032
  const publishAwareness = () => o.onAwareness?.(new Map(awareness.getStates()));
3678
4033
  awareness.on("change", publishAwareness);
3679
4034
  const provider = new import_collab6.SupabaseYjsProvider({
@@ -3719,6 +4074,7 @@ async function startWorkbookOtRoom(port, o) {
3719
4074
  awareness.setLocalState({ ...current, sheetId: c.sheetId, row: c.row, col: c.col, ts: Date.now() });
3720
4075
  },
3721
4076
  stop() {
4077
+ stopColor();
3722
4078
  room.stop();
3723
4079
  port.dispose?.();
3724
4080
  awareness.off("change", publishAwareness);