@ai-matrx/office 0.8.22 → 0.8.24

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.
@@ -1113,25 +1113,25 @@ function rebaseUndoStack(items, remote) {
1113
1113
  let dropped = 0;
1114
1114
  for (let i = items.length - 1; i >= 0; i--) {
1115
1115
  const item = items[i];
1116
- let ok2 = true;
1116
+ let ok3 = true;
1117
1117
  for (const list of [item.undoMutations, item.redoMutations]) {
1118
1118
  for (const m of list ?? []) {
1119
1119
  if (m.id !== RICH_TEXT_EDITING) continue;
1120
1120
  try {
1121
1121
  if (touchesPageSetup(m.params.actions) && touchesPageSetup(remote)) throw new Error("page setup");
1122
1122
  const r = transformDocsOp(m.params.actions, remote, "left");
1123
- if (isNoopDocsOp(r.op)) ok2 = false;
1123
+ if (isNoopDocsOp(r.op)) ok3 = false;
1124
1124
  else {
1125
1125
  m.params = { ...m.params, actions: r.op };
1126
1126
  delete m.params.textRanges;
1127
1127
  delete m.params.layoutState;
1128
1128
  }
1129
1129
  } catch {
1130
- ok2 = false;
1130
+ ok3 = false;
1131
1131
  }
1132
1132
  }
1133
1133
  }
1134
- if (!ok2) {
1134
+ if (!ok3) {
1135
1135
  items.splice(i, 1);
1136
1136
  dropped++;
1137
1137
  }
@@ -1290,7 +1290,9 @@ function openDocsOtRoom(o) {
1290
1290
  ...o.presence ? { presence: o.presence } : {},
1291
1291
  onNotice: (n) => notice(n),
1292
1292
  ...o.onIncident ? { onIncident: o.onIncident } : {},
1293
- ...o.onStatus ? { onStatus: o.onStatus } : {}
1293
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
1294
+ ...o.offline ? { offline: o.offline } : {},
1295
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
1294
1296
  });
1295
1297
  const isSaver = () => {
1296
1298
  if (!o.presence) return true;
@@ -1328,6 +1330,7 @@ import * as Y2 from "yjs";
1328
1330
  import { Awareness as Awareness2 } from "y-protocols/awareness";
1329
1331
  import {
1330
1332
  awarenessOpPresence,
1333
+ browserOfflineOptions,
1331
1334
  claimCollaboratorColor as claimCollaboratorColor2,
1332
1335
  collabReplace,
1333
1336
  collabRoomExists,
@@ -1565,7 +1568,9 @@ function documentOtFactory(o) {
1565
1568
  replace: ({ snapshot, stateHash, clientId }) => collabReplace(client, { roomId: o.documentId, snapshot, stateHash, origin: "restore", clientId }),
1566
1569
  ...o.onNotice ? { onNotice: o.onNotice } : {},
1567
1570
  ...o.onIncident ? { onIncident: o.onIncident } : {},
1568
- ...o.onStatus ? { onStatus: o.onStatus } : {}
1571
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
1572
+ offline: browserOfflineOptions(`${o.documentId}:${o.uid}`),
1573
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
1569
1574
  });
1570
1575
  await room.session.ready;
1571
1576
  let lastKey = "";
@@ -1693,6 +1698,8 @@ var SHEET_MUTATIONS = {
1693
1698
  "sheet.mutation.insert-sheet": covered("sheet", "index", "sheet"),
1694
1699
  "sheet.mutation.remove-sheet": covered("sheet", "sheetIndex", "sheetsLeft"),
1695
1700
  "sheet.mutation.set-worksheet-order": covered("sheet", "fromOrder", "toOrder"),
1701
+ // ── covered (C9): our own cell comment anchors (comment-anchor-transform.ts; not emitted by Univer) ──────
1702
+ "matrx.mutation.set-comment-anchor": covered("anchor", "anchorId", "cell"),
1696
1703
  "sheet.mutation.reorder-range": covered("sort", "range", "order"),
1697
1704
  // ── never travels ────────────────────────────────────────────────────────────────────────────────
1698
1705
  "formula.mutation.set-formula-calculation-start": never(FORMULA_RESULT),
@@ -2144,6 +2151,74 @@ function refSheetsFor(texts, sheets) {
2144
2151
  return Object.keys(out).length ? out : void 0;
2145
2152
  }
2146
2153
 
2154
+ // src/collab/sheets/comment-anchor-transform.ts
2155
+ var SET_SHEET_COMMENT_ANCHOR = "matrx.mutation.set-comment-anchor";
2156
+ var REMOVE_SHEET = "sheet.mutation.remove-sheet";
2157
+ function structuralAxisOp(id, params) {
2158
+ const p = params;
2159
+ switch (id) {
2160
+ case "sheet.mutation.insert-row":
2161
+ return p.range ? { axis: "row", op: { kind: "insert", at: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } } : null;
2162
+ case "sheet.mutation.remove-rows":
2163
+ return p.range ? { axis: "row", op: { kind: "remove", start: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } } : null;
2164
+ case "sheet.mutation.insert-col":
2165
+ return p.range ? { axis: "col", op: { kind: "insert", at: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } } : null;
2166
+ case "sheet.mutation.remove-col":
2167
+ return p.range ? { axis: "col", op: { kind: "remove", start: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } } : null;
2168
+ case "sheet.mutation.move-rows":
2169
+ return p.sourceRange && p.targetRange ? { axis: "row", op: { kind: "move", from: p.sourceRange.startRow, count: p.sourceRange.endRow - p.sourceRange.startRow + 1, to: p.targetRange.startRow } } : null;
2170
+ case "sheet.mutation.move-columns":
2171
+ return p.sourceRange && p.targetRange ? {
2172
+ axis: "col",
2173
+ op: { kind: "move", from: p.sourceRange.startColumn, count: p.sourceRange.endColumn - p.sourceRange.startColumn + 1, to: p.targetRange.startColumn }
2174
+ } : null;
2175
+ default:
2176
+ return null;
2177
+ }
2178
+ }
2179
+ function moveSheetAnchorCell(cell, sheet, id, params) {
2180
+ if (String(params.subUnitId ?? "") !== sheet) return cell;
2181
+ if (id === REMOVE_SHEET) return null;
2182
+ const s = structuralAxisOp(id, params);
2183
+ if (!s) return cell;
2184
+ if (s.axis === "row") {
2185
+ const row = mapIndex(s.op, cell.row);
2186
+ return row === null ? null : row === cell.row ? cell : { row, col: cell.col };
2187
+ }
2188
+ const col = mapIndex(s.op, cell.col);
2189
+ return col === null ? null : col === cell.col ? cell : { row: cell.row, col };
2190
+ }
2191
+ function colName(c) {
2192
+ let s = "";
2193
+ for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + (n - 1) % 26) + s;
2194
+ return s;
2195
+ }
2196
+ var sheetCellName = (cell) => `${colName(cell.col)}${cell.row + 1}`;
2197
+ function cellOf(m) {
2198
+ const c = m.params.cell;
2199
+ return c && typeof c.row === "number" && typeof c.col === "number" ? c : null;
2200
+ }
2201
+ var ok = (op, lost = [], dropped = []) => ({ op, lost, dropped });
2202
+ var label = (m) => {
2203
+ const c = cellOf(m);
2204
+ return `${String(m.params.subUnitId ?? "")}!${c ? sheetCellName(c) : "?"} comment`;
2205
+ };
2206
+ function transformCommentAnchor(x, y, side) {
2207
+ const xa = x.id === SET_SHEET_COMMENT_ANCHOR;
2208
+ const ya = y.id === SET_SHEET_COMMENT_ANCHOR;
2209
+ if (!xa && !ya) return null;
2210
+ if (!xa) return ok([x]);
2211
+ if (ya) {
2212
+ if (x.params.anchorId !== y.params.anchorId || x.params.subUnitId !== y.params.subUnitId) return ok([x]);
2213
+ return side === "left" ? ok([x], [label(y)]) : ok([], [], [label(x)]);
2214
+ }
2215
+ const cell = cellOf(x);
2216
+ if (!cell) return ok([x]);
2217
+ const moved = moveSheetAnchorCell(cell, String(x.params.subUnitId ?? ""), y.id, y.params);
2218
+ if (!moved) return ok([], [], [label(x)]);
2219
+ return ok([moved === cell ? x : { id: x.id, params: { ...x.params, cell: moved } }]);
2220
+ }
2221
+
2147
2222
  // src/collab/sheets/transform/transform.ts
2148
2223
  var SHEET_TRANSFORMER_VERSION = "c5c-1";
2149
2224
  var ID = {
@@ -2175,16 +2250,16 @@ var ID = {
2175
2250
  var PAIR_BARRIERS = {};
2176
2251
  var pairKey = (a, b) => a < b ? `${a}|${b}` : `${b}|${a}`;
2177
2252
  var barrier2 = (reason) => ({ barrier: true, reason });
2178
- var ok = (op, lost = [], dropped = []) => ({ op, lost, dropped });
2253
+ var ok2 = (op, lost = [], dropped = []) => ({ op, lost, dropped });
2179
2254
  var flip = (side) => side === "left" ? "right" : "left";
2180
2255
  var sheetOf = (m) => String(m.params.subUnitId ?? "");
2181
- function colName(c) {
2256
+ function colName2(c) {
2182
2257
  let s = "";
2183
2258
  for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + (n - 1) % 26) + s;
2184
2259
  return s;
2185
2260
  }
2186
- var cellRef = (sheet, row, col) => `${sheet}!${colName(col)}${row + 1}`;
2187
- var rangeRef = (sheet, r) => `${sheet}!${colName(r.startColumn)}${r.startRow + 1}:${colName(r.endColumn)}${r.endRow + 1}`;
2261
+ var cellRef = (sheet, row, col) => `${sheet}!${colName2(col)}${row + 1}`;
2262
+ var rangeRef = (sheet, r) => `${sheet}!${colName2(r.startColumn)}${r.startRow + 1}:${colName2(r.endColumn)}${r.endRow + 1}`;
2188
2263
  function structuralOf(m) {
2189
2264
  const p = m.params;
2190
2265
  switch (m.id) {
@@ -2439,9 +2514,9 @@ function transformCell(X, Y4, side) {
2439
2514
  return { entries: Object.keys(out).length ? [out, ...tail] : tail, xLost, yLost };
2440
2515
  }
2441
2516
  function transformCellsOverCells(x, y, side) {
2442
- if (sheetOf(x) !== sheetOf(y)) return ok([x]);
2517
+ if (sheetOf(x) !== sheetOf(y)) return ok2([x]);
2443
2518
  const ycells = cellsOf(y);
2444
- if (!cellsOverlap(cellsOf(x), ycells)) return ok([x]);
2519
+ if (!cellsOverlap(cellsOf(x), ycells)) return ok2([x]);
2445
2520
  const xd = isDerived(x);
2446
2521
  const yd = isDerived(y);
2447
2522
  const eff = derivedSide(x, y, side);
@@ -2467,7 +2542,7 @@ function transformCellsOverCells(x, y, side) {
2467
2542
  });
2468
2543
  if (why) return barrier2(why);
2469
2544
  const op = passes.filter((p) => !isEmptyMatrix(p)).map((p) => cellsMutation(x, p));
2470
- return ok(op, lost, dropped);
2545
+ return ok2(op, lost, dropped);
2471
2546
  }
2472
2547
  var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived", "sheetIndex", "sheetsLeft"];
2473
2548
  var isDerived = (m) => m.params.derived === true;
@@ -2538,7 +2613,7 @@ function cellThrough(sheet, change, r, c) {
2538
2613
  return nr === null || nc === null ? null : [nr, nc];
2539
2614
  }
2540
2615
  function cellsOverChange(x, change) {
2541
- if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok([x]);
2616
+ if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok2([x]);
2542
2617
  const ctx = formulaCtx(x);
2543
2618
  const out = {};
2544
2619
  const dropped = [];
@@ -2567,9 +2642,9 @@ function cellsOverChange(x, change) {
2567
2642
  });
2568
2643
  if (why) return barrier2(why);
2569
2644
  const rsAfter = refSheetsAfter(ctx.refSheets, change);
2570
- if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok([x]);
2645
+ if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok2([x]);
2571
2646
  const params = { ...withRefSheets(x.params, rsAfter), cellValue: out };
2572
- return ok(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
2647
+ return ok2(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
2573
2648
  }
2574
2649
  function rewritesOf(y, change) {
2575
2650
  if (!hasFormula(y)) return null;
@@ -2616,36 +2691,36 @@ function formulaPair(x, y, side) {
2616
2691
  const fy = familyOf(y.id);
2617
2692
  const SET_NAME_BARRIER = "set-defined-name without previousName (capture must record the name it replaces) against formula text";
2618
2693
  if (fx === "defname" && fy === "defname") {
2619
- if (String(x.params.id) !== String(y.params.id)) return ok([x]);
2694
+ if (String(x.params.id) !== String(y.params.id)) return ok2([x]);
2620
2695
  const eff = derivedSide(x, y, side);
2621
- if (eff === "left") return ok([x], isDerived(y) ? [] : [`defined name "${String(y.params.name)}"`]);
2622
- return ok([], [], isDerived(x) ? [] : [`defined name "${String(x.params.name)}"`]);
2696
+ if (eff === "left") return ok2([x], isDerived(y) ? [] : [`defined name "${String(y.params.name)}"`]);
2697
+ return ok2([], [], isDerived(x) ? [] : [`defined name "${String(x.params.name)}"`]);
2623
2698
  }
2624
2699
  if (fx === "defname") {
2625
2700
  if (fy === "cell") {
2626
2701
  if (setNameWithoutPrevious(x) && hasFormula(y)) return barrier2(SET_NAME_BARRIER);
2627
2702
  const ch2 = refChangeOf(x);
2628
- if (!ch2) return ok([x]);
2703
+ if (!ch2) return ok2([x]);
2629
2704
  const add = rewritesOf(y, ch2);
2630
2705
  if (typeof add === "string") return barrier2(add);
2631
- return ok(add ? [x, add] : [x]);
2706
+ return ok2(add ? [x, add] : [x]);
2632
2707
  }
2633
2708
  const ch = refChangeOf(y);
2634
- if (!ch) return ok([x]);
2709
+ if (!ch) return ok2([x]);
2635
2710
  const r = definedNameThrough(x, ch);
2636
- return typeof r === "string" ? barrier2(r) : ok([r.op]);
2711
+ return typeof r === "string" ? barrier2(r) : ok2([r.op]);
2637
2712
  }
2638
2713
  if (fy === "defname") {
2639
2714
  if (fx === "cell") {
2640
2715
  if (setNameWithoutPrevious(y) && hasFormula(x)) return barrier2(SET_NAME_BARRIER);
2641
2716
  const ch2 = refChangeOf(y);
2642
- return ch2 ? cellsOverChange(x, ch2) : ok([x]);
2717
+ return ch2 ? cellsOverChange(x, ch2) : ok2([x]);
2643
2718
  }
2644
2719
  const ch = refChangeOf(x);
2645
- if (!ch) return ok([x]);
2720
+ if (!ch) return ok2([x]);
2646
2721
  const r = definedNameThrough(y, ch);
2647
2722
  if (typeof r === "string") return barrier2(r);
2648
- return ok(r.changed ? [x, asDerived(r.op)] : [x]);
2723
+ return ok2(r.changed ? [x, asDerived(r.op)] : [x]);
2649
2724
  }
2650
2725
  if (fx === "cell") {
2651
2726
  const ch = refChangeOf(y);
@@ -2660,7 +2735,7 @@ function formulaPair(x, y, side) {
2660
2735
  });
2661
2736
  const add = rewritesOf(y, ch);
2662
2737
  if (typeof add === "string") return barrier2(add);
2663
- return ok(add ? [x, add] : [x], lost);
2738
+ return ok2(add ? [x, add] : [x], lost);
2664
2739
  }
2665
2740
  return null;
2666
2741
  }
@@ -2808,20 +2883,20 @@ function numfmtPair(x, y, side, sx, sy) {
2808
2883
  const nx = isNumfmt(x);
2809
2884
  const ny = isNumfmt(y);
2810
2885
  if (!nx && !ny) return null;
2811
- if (nx && sy) return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
2812
- if (ny && sx) return ok([x]);
2886
+ if (nx && sy) return ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
2887
+ if (ny && sx) return ok2([x]);
2813
2888
  if (nx && ny) {
2814
- if (side === "left") return ok([x]);
2889
+ if (side === "left") return ok2([x]);
2815
2890
  const ys = nfParts(y).flatMap((p) => p.ranges);
2816
- return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
2891
+ return ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
2817
2892
  }
2818
2893
  if (nx && y.id === ID.values) {
2819
- if (side === "left") return ok([x]);
2894
+ if (side === "left") return ok2([x]);
2820
2895
  const ys = nWrites(y);
2821
- return ys.length ? ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok([x]);
2896
+ return ys.length ? ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok2([x]);
2822
2897
  }
2823
2898
  if (ny && x.id === ID.values) {
2824
- if (side === "left") return ok([x]);
2899
+ if (side === "left") return ok2([x]);
2825
2900
  const out = {};
2826
2901
  const tail = {};
2827
2902
  let touched = false;
@@ -2847,31 +2922,31 @@ function numfmtPair(x, y, side, sx, sy) {
2847
2922
  }
2848
2923
  putCell(out, r, c, v);
2849
2924
  });
2850
- if (!touched) return ok([x]);
2925
+ if (!touched) return ok2([x]);
2851
2926
  const ops = [];
2852
2927
  if (!isEmptyMatrix(out)) ops.push(cellsMutation(x, out));
2853
2928
  if (!isEmptyMatrix(tail)) ops.push({ id: ID.values, params: { subUnitId: sheetOf(x), cellValue: tail } });
2854
- return ok(ops);
2929
+ return ok2(ops);
2855
2930
  }
2856
- return ok([x]);
2931
+ return ok2([x]);
2857
2932
  }
2858
2933
  var isCount = (m) => m.id === ID.rowCount || m.id === ID.colCount;
2859
2934
  var countAxis = (m) => m.id === ID.rowCount ? "row" : "col";
2860
2935
  var countKey = (m) => m.id === ID.rowCount ? "rowCount" : "columnCount";
2861
2936
  function countPair(x, y, sy) {
2862
- if (!isCount(x)) return isCount(y) ? ok([x]) : null;
2937
+ if (!isCount(x)) return isCount(y) ? ok2([x]) : null;
2863
2938
  const k = countKey(x);
2864
2939
  const v = Number(x.params[k]);
2865
2940
  if (sy) {
2866
- if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok([x]);
2941
+ if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok2([x]);
2867
2942
  const d = sy.op.kind === "insert" ? sy.op.count : -sy.op.count;
2868
- return ok([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
2943
+ return ok2([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
2869
2944
  }
2870
2945
  if (isCount(y) && y.id === x.id) {
2871
2946
  const w = Number(y.params[k]);
2872
- return ok([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
2947
+ return ok2([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
2873
2948
  }
2874
- return ok([x]);
2949
+ return ok2([x]);
2875
2950
  }
2876
2951
  var isSheetOp = (m) => m.id === ID.insertSheet || m.id === ID.removeSheet || m.id === ID.sheetOrder;
2877
2952
  var sheetIdOf = (m) => m.id === ID.insertSheet ? String(m.params.sheet?.id ?? "") : sheetOf(m);
@@ -2904,31 +2979,31 @@ function sheetPair(x, y, side) {
2904
2979
  const b = sheetAxisOf(y);
2905
2980
  if (!a || !b) return barrier2("a sheet add or remove without its index (capture must call annotateSheetOps)");
2906
2981
  if (x.id === ID.insertSheet && y.id === ID.insertSheet && sheetIdOf(x) === sheetIdOf(y)) {
2907
- return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok([]) : barrier2("the same sheet id added twice with different content");
2982
+ return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok2([]) : barrier2("the same sheet id added twice with different content");
2908
2983
  }
2909
2984
  if (x.id === ID.removeSheet && typeof x.params.sheetsLeft === "number" && sheetIdOf(x) !== sheetIdOf(y) && (y.id === ID.removeSheet || y.id === ID.insertSheet)) {
2910
2985
  const left = x.params.sheetsLeft + (y.id === ID.insertSheet ? 1 : -1);
2911
2986
  if (left < 1) return barrier2("concurrent sheet removes would leave the workbook without a sheet");
2912
2987
  const out2 = transformAxis(a, b, side);
2913
2988
  if (!out2) return barrier2("sheet order: no transform");
2914
- return ok(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
2989
+ return ok2(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
2915
2990
  }
2916
2991
  const out = transformAxis(a, b, side);
2917
2992
  if (!out) return barrier2("sheet order: no transform");
2918
- return ok(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
2993
+ return ok2(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
2919
2994
  }
2920
2995
  if (ys) {
2921
- if (y.id !== ID.removeSheet) return ok([x]);
2996
+ if (y.id !== ID.removeSheet) return ok2([x]);
2922
2997
  const gone2 = sheetOf(y);
2923
2998
  if (namesSheet(x, gone2)) return barrier2("a formula names a sheet removed at the same time");
2924
2999
  if (sheetOf(x) === gone2 && x.id !== ID.setName && x.id !== ID.removeName)
2925
- return ok([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
2926
- return ok([x]);
3000
+ return ok2([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
3001
+ return ok2([x]);
2927
3002
  }
2928
- if (x.id !== ID.removeSheet) return ok([x]);
3003
+ if (x.id !== ID.removeSheet) return ok2([x]);
2929
3004
  const gone = sheetOf(x);
2930
3005
  if (namesSheet(y, gone)) return barrier2("a formula names a sheet removed at the same time");
2931
- return ok([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
3006
+ return ok2([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
2932
3007
  }
2933
3008
  function annotateSheetOps(group, sheetOrder) {
2934
3009
  const order = [...sheetOrder];
@@ -3026,22 +3101,22 @@ function sortPair(x, y, sx, sy) {
3026
3101
  const a = sortOf(x).range;
3027
3102
  const b = sortOf(y).range;
3028
3103
  const overlap = a.startRow <= b.endRow && b.startRow <= a.endRow && a.startColumn <= b.endColumn && b.startColumn <= a.endColumn;
3029
- return overlap ? barrier2("two sorts of overlapping ranges at once") : ok([x]);
3104
+ return overlap ? barrier2("two sorts of overlapping ranges at once") : ok2([x]);
3030
3105
  }
3031
3106
  if (xs) {
3032
3107
  if (sy) {
3033
3108
  const t = sortThrough(sortOf(x), sy);
3034
- return t ? ok(buildSort(x, t)) : barrier2("a row or column move through a sorted range");
3109
+ return t ? ok2(buildSort(x, t)) : barrier2("a row or column move through a sorted range");
3035
3110
  }
3036
- return ok([x]);
3111
+ return ok2([x]);
3037
3112
  }
3038
3113
  const o = sortOf(y);
3039
3114
  const Q = sortQ(o);
3040
3115
  const moved = (r) => r >= o.range.startRow && r <= o.range.endRow && Q.has(r);
3041
3116
  if (sx) {
3042
- if (sx.axis === "col") return sx.op.kind === "move" && !sortThrough(o, sx) ? barrier2("a column move through a sorted range") : ok([x]);
3043
- if (sx.op.kind === "insert") return ok([x]);
3044
- if (sx.op.kind === "move") return sortThrough(o, sx) ? ok([x]) : barrier2("a row move through a sorted range");
3117
+ if (sx.axis === "col") return sx.op.kind === "move" && !sortThrough(o, sx) ? barrier2("a column move through a sorted range") : ok2([x]);
3118
+ if (sx.op.kind === "insert") return ok2([x]);
3119
+ if (sx.op.kind === "move") return sortThrough(o, sx) ? ok2([x]) : barrier2("a row move through a sorted range");
3045
3120
  const rows = [];
3046
3121
  let partial = false;
3047
3122
  for (let i = sx.op.start; i < sx.op.start + sx.op.count; i++) {
@@ -3049,7 +3124,7 @@ function sortPair(x, y, sx, sy) {
3049
3124
  rows.push(Q.get(i) ?? i);
3050
3125
  }
3051
3126
  if (partial) return barrier2("a row remove against a concurrent sort of those rows");
3052
- return ok([x]);
3127
+ return ok2([x]);
3053
3128
  }
3054
3129
  if (x.id === ID.values) {
3055
3130
  const out = {};
@@ -3060,7 +3135,7 @@ function sortPair(x, y, sx, sy) {
3060
3135
  changed = true;
3061
3136
  } else putCell(out, r, c, v);
3062
3137
  });
3063
- return changed ? ok([cellsMutation(x, out)]) : ok([x]);
3138
+ return changed ? ok2([cellsMutation(x, out)]) : ok2([x]);
3064
3139
  }
3065
3140
  if (isNumfmt(x)) {
3066
3141
  const parts = nfParts(x).map((p) => {
@@ -3076,9 +3151,9 @@ function sortPair(x, y, sx, sy) {
3076
3151
  }
3077
3152
  return { ...p, ranges };
3078
3153
  });
3079
- return ok(nfBuild(x, parts));
3154
+ return ok2(nfBuild(x, parts));
3080
3155
  }
3081
- return ok([x]);
3156
+ return ok2([x]);
3082
3157
  }
3083
3158
  function familyOf(id) {
3084
3159
  const e = SHEET_MUTATIONS[id];
@@ -3094,13 +3169,15 @@ function transformMutation(x, y, side) {
3094
3169
  if (why) return barrier2(why);
3095
3170
  }
3096
3171
  }
3172
+ const ca = transformCommentAnchor(x, y, side);
3173
+ if (ca) return ca;
3097
3174
  const pb = PAIR_BARRIERS[pairKey(x.id, y.id)];
3098
3175
  if (pb) return barrier2(`${x.id} \xD7 ${y.id}: ${pb.reason}${pb.seed === null ? "" : ` (fuzz seed ${pb.seed})`}`);
3099
3176
  const sp = sheetPair(x, y, side);
3100
3177
  if (sp) return sp;
3101
3178
  const fp = formulaPair(x, y, side);
3102
3179
  if (fp) return fp;
3103
- if (sheetOf(x) !== sheetOf(y)) return ok([x]);
3180
+ if (sheetOf(x) !== sheetOf(y)) return ok2([x]);
3104
3181
  const fx = familyOf(x.id);
3105
3182
  const fy = familyOf(y.id);
3106
3183
  const sy = structuralOf(y);
@@ -3112,11 +3189,11 @@ function transformMutation(x, y, side) {
3112
3189
  const np = numfmtPair(x, y, side, sx, sy);
3113
3190
  if (np) return np;
3114
3191
  if (sx && sy) {
3115
- if (sx.axis !== sy.axis) return ok([x]);
3192
+ if (sx.axis !== sy.axis) return ok2([x]);
3116
3193
  const out = transformAxis(sx.op, sy.op, side);
3117
3194
  if (!out) return barrier2(`${x.id} over ${y.id}: moved blocks overlap in part, or the block would split`);
3118
3195
  const dropped = out.length === 0 && sx.op.kind === "move" ? [`${sheetOf(x)}: moved ${sx.axis}s`] : [];
3119
- return ok(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);
3196
+ return ok2(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);
3120
3197
  }
3121
3198
  if (sy) {
3122
3199
  if (fx === "merge") {
@@ -3127,23 +3204,23 @@ function transformMutation(x, y, side) {
3127
3204
  if (t) kept.push(t);
3128
3205
  else dropped.push(rangeRef(sheetOf(x), r));
3129
3206
  }
3130
- return ok(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);
3207
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);
3131
3208
  }
3132
3209
  if (fx === "size") {
3133
3210
  const size = sizeOf(x);
3134
- if (size.axis !== sy.axis) return ok([x]);
3211
+ if (size.axis !== sy.axis) return ok2([x]);
3135
3212
  const next = /* @__PURE__ */ new Map();
3136
3213
  for (const [i, v] of size.values) {
3137
3214
  const m = mapIndex(sy.op, i);
3138
3215
  if (m !== null) next.set(m, v);
3139
3216
  }
3140
3217
  const built = buildSize(x, next);
3141
- return ok(built ? [built] : []);
3218
+ return ok2(built ? [built] : []);
3142
3219
  }
3143
- return ok([x]);
3220
+ return ok2([x]);
3144
3221
  }
3145
3222
  if (sx) {
3146
- if (fy !== "merge" || y.id !== ID.addMerge) return ok([x]);
3223
+ if (fy !== "merge" || y.id !== ID.addMerge) return ok2([x]);
3147
3224
  const remove = [];
3148
3225
  const add = [];
3149
3226
  for (const r of mergeRanges(y)) {
@@ -3153,11 +3230,11 @@ function transformMutation(x, y, side) {
3153
3230
  if (t.range) add.push(t.range);
3154
3231
  }
3155
3232
  const lostMerges = mergeRanges(y).filter((r) => mergeThrough(sx, r).range === null).map((r) => rangeRef(sheetOf(y), r));
3156
- if (!remove.length) return ok([x], lostMerges);
3233
+ if (!remove.length) return ok2([x], lostMerges);
3157
3234
  const sheet = sheetOf(x);
3158
3235
  const pre = sx.op.kind === "insert" ? [] : [mergeMutation(ID.removeMerge, sheet, remove)];
3159
3236
  const mid = sx.op.kind === "insert" ? [mergeMutation(ID.removeMerge, sheet, remove)] : [];
3160
- return ok([...pre, x, ...mid, ...add.length ? [mergeMutation(ID.addMerge, sheet, add)] : []], lostMerges);
3237
+ return ok2([...pre, x, ...mid, ...add.length ? [mergeMutation(ID.addMerge, sheet, add)] : []], lostMerges);
3161
3238
  }
3162
3239
  if (fx === "cell" && fy === "cell") return transformCellsOverCells(x, y, side);
3163
3240
  if (fx === "merge" && fy === "merge") {
@@ -3166,45 +3243,45 @@ function transformMutation(x, y, side) {
3166
3243
  const hit = (r) => yr.some((q) => intersects(r, q));
3167
3244
  const sheet = sheetOf(x);
3168
3245
  if (x.id === ID.addMerge && y.id === ID.addMerge) {
3169
- if (!xr.some(hit)) return ok([x]);
3246
+ if (!xr.some(hit)) return ok2([x]);
3170
3247
  if (side === "left") {
3171
3248
  const lost = yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q));
3172
- return ok([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);
3249
+ return ok2([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);
3173
3250
  }
3174
3251
  const kept = xr.filter((r) => !hit(r));
3175
- return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3252
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3176
3253
  }
3177
3254
  if (x.id === ID.addMerge && y.id === ID.removeMerge) {
3178
- 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)) : []);
3255
+ if (side === "left" || !xr.some(hit)) return ok2([x], side === "left" && xr.some(hit) ? yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q)) : []);
3179
3256
  const kept = xr.filter((r) => !hit(r));
3180
- return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3257
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3181
3258
  }
3182
3259
  if (x.id === ID.removeMerge && y.id === ID.addMerge) {
3183
3260
  const touched = yr.filter((q) => xr.some((r) => intersects(r, q)));
3184
- if (!touched.length) return ok([x]);
3185
- if (side === "left") return ok([x], touched.map((q) => rangeRef(sheet, q)));
3186
- return ok([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3261
+ if (!touched.length) return ok2([x]);
3262
+ if (side === "left") return ok2([x], touched.map((q) => rangeRef(sheet, q)));
3263
+ return ok2([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3187
3264
  }
3188
- return ok([x]);
3265
+ return ok2([x]);
3189
3266
  }
3190
3267
  if (fx === "size" && fy === "size") {
3191
3268
  const a = sizeOf(x);
3192
3269
  const b = sizeOf(y);
3193
- if (a.axis !== b.axis || a.attr !== b.attr) return ok([x]);
3270
+ if (a.axis !== b.axis || a.attr !== b.attr) return ok2([x]);
3194
3271
  if (side === "left") {
3195
3272
  const lost = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
3196
- return ok([x], lost);
3273
+ return ok2([x], lost);
3197
3274
  }
3198
3275
  const next = new Map([...a.values].filter(([i]) => !b.values.has(i)));
3199
3276
  const built = buildSize(x, next);
3200
3277
  const dropped = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
3201
- return ok(built ? [built] : [], [], dropped);
3278
+ return ok2(built ? [built] : [], [], dropped);
3202
3279
  }
3203
3280
  if (fx === "name" && fy === "name") {
3204
- if (side === "left") return ok([x], [`${sheetOf(x)}: name "${String(y.params.name)}"`]);
3205
- return ok([], [], [`${sheetOf(x)}: name "${String(x.params.name)}"`]);
3281
+ if (side === "left") return ok2([x], [`${sheetOf(x)}: name "${String(y.params.name)}"`]);
3282
+ return ok2([], [], [`${sheetOf(x)}: name "${String(x.params.name)}"`]);
3206
3283
  }
3207
- return ok([x]);
3284
+ return ok2([x]);
3208
3285
  }
3209
3286
  var blocked = (p) => !Array.isArray(p);
3210
3287
  function tSeq(xs, ys, side, acc) {
@@ -3383,10 +3460,10 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3383
3460
  let dropped = 0;
3384
3461
  for (let i = items.length - 1; i >= 0; i--) {
3385
3462
  const item = items[i];
3386
- let ok2 = true;
3463
+ let ok3 = true;
3387
3464
  for (const key of ["undoMutations", "redoMutations"]) {
3388
3465
  const list = item[key];
3389
- if (!ok2 || !list?.length) continue;
3466
+ if (!ok3 || !list?.length) continue;
3390
3467
  const isOperation = (id) => !SHEET_MUTATIONS[id] && id.includes(".operation.");
3391
3468
  const operations = list.filter((m) => isOperation(m.id));
3392
3469
  let shaped = cachedShape(list);
@@ -3395,14 +3472,14 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3395
3472
  shapedLists.set(list, { src: list.slice(), shaped });
3396
3473
  }
3397
3474
  if (shaped.some((m) => m === null)) {
3398
- ok2 = false;
3475
+ ok3 = false;
3399
3476
  continue;
3400
3477
  }
3401
3478
  if (!shaped.length) continue;
3402
3479
  try {
3403
3480
  const r = transformGroup(shaped, remote, "left");
3404
3481
  if (isBarrier(r) || r.op.length === 0) {
3405
- ok2 = false;
3482
+ ok3 = false;
3406
3483
  continue;
3407
3484
  }
3408
3485
  if (r.op.length === shaped.length && r.op.every((m, i2) => m === shaped[i2])) continue;
@@ -3410,10 +3487,10 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3410
3487
  shapedLists.set(next, { src: next.slice(), shaped: r.op });
3411
3488
  item[key] = next;
3412
3489
  } catch {
3413
- ok2 = false;
3490
+ ok3 = false;
3414
3491
  }
3415
3492
  }
3416
- if (!ok2) {
3493
+ if (!ok3) {
3417
3494
  items.splice(i, 1);
3418
3495
  dropped++;
3419
3496
  }
@@ -3557,7 +3634,9 @@ function openSheetsOtRoom(o) {
3557
3634
  ...o.presence ? { presence: o.presence } : {},
3558
3635
  onNotice: (n) => notice(n),
3559
3636
  ...o.onIncident ? { onIncident: o.onIncident } : {},
3560
- ...o.onStatus ? { onStatus: o.onStatus } : {}
3637
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
3638
+ ...o.offline ? { offline: o.offline } : {},
3639
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
3561
3640
  });
3562
3641
  const isSaver = () => {
3563
3642
  if (!o.presence) return true;
@@ -3588,6 +3667,65 @@ function openSheetsOtRoom(o) {
3588
3667
  };
3589
3668
  }
3590
3669
 
3670
+ // src/univer/collab/sheets-ot/plugin-teardown.ts
3671
+ var perSheetList = (data) => Object.entries(data).flatMap(([sheet, list]) => Array.isArray(list) ? [[sheet, list.filter((x) => !!x && typeof x === "object")]] : []);
3672
+ var PLUGIN_TEARDOWNS = [
3673
+ {
3674
+ resource: "SHEET_CONDITIONAL_FORMATTING_PLUGIN",
3675
+ removals: (unitId, data) => perSheetList(data).flatMap(
3676
+ ([subUnitId, rules]) => rules.filter((r) => typeof r.cfId === "string").map((r) => ({ id: "sheet.mutation.delete-conditional-rule", params: { unitId, subUnitId, cfId: r.cfId } }))
3677
+ )
3678
+ },
3679
+ {
3680
+ resource: "SHEET_DATA_VALIDATION_PLUGIN",
3681
+ removals: (unitId, data) => perSheetList(data).flatMap(([subUnitId, rules]) => {
3682
+ const ids = rules.map((r) => r.uid).filter((u) => typeof u === "string");
3683
+ return ids.length ? [{ id: "data-validation.mutation.removeRule", params: { unitId, subUnitId, ruleId: ids, source: "command" } }] : [];
3684
+ })
3685
+ },
3686
+ {
3687
+ resource: "SHEET_NOTE_PLUGIN",
3688
+ removals: (unitId, data) => Object.entries(data).flatMap(
3689
+ ([sheetId, rows]) => Object.entries(rows ?? {}).flatMap(
3690
+ ([row, cols]) => Object.entries(cols ?? {}).map(([col, note]) => ({
3691
+ id: "sheet.mutation.remove-note",
3692
+ params: { unitId, sheetId, row: Number(row), col: Number(col), ...note && typeof note.id === "string" ? { noteId: note.id } : {}, silent: true }
3693
+ }))
3694
+ )
3695
+ )
3696
+ }
3697
+ ];
3698
+ function resourcesOf(saved) {
3699
+ const out = /* @__PURE__ */ new Map();
3700
+ const list = saved?.resources;
3701
+ for (const r of Array.isArray(list) ? list : []) {
3702
+ if (!r?.name) continue;
3703
+ try {
3704
+ const data = typeof r.data === "string" ? r.data ? JSON.parse(r.data) : null : r.data;
3705
+ if (data && typeof data === "object") out.set(r.name, data);
3706
+ } catch {
3707
+ }
3708
+ }
3709
+ return out;
3710
+ }
3711
+ function releaseUnitPluginState(cs, unitId, saved) {
3712
+ const resources = resourcesOf(saved);
3713
+ let ran = 0;
3714
+ for (const t of PLUGIN_TEARDOWNS) {
3715
+ const data = resources.get(t.resource);
3716
+ if (!data) continue;
3717
+ for (const m of t.removals(unitId, data)) {
3718
+ try {
3719
+ cs.syncExecuteCommand(m.id, m.params, { onlyLocal: true });
3720
+ ran++;
3721
+ } catch (err) {
3722
+ console.warn(`[sheets-ot] could not release ${t.resource} state before a reload`, err);
3723
+ }
3724
+ }
3725
+ }
3726
+ return ran;
3727
+ }
3728
+
3591
3729
  // src/univer/collab/sheets-ot/univer-port.ts
3592
3730
  var COMMAND = 0;
3593
3731
  var MUTATION = 2;
@@ -3634,7 +3772,7 @@ function univerSheetsOtPort(o) {
3634
3772
  return out;
3635
3773
  };
3636
3774
  const sheetOrder = () => (o.workbook()?.getSheets() ?? []).map((ws) => ws.getSheetId());
3637
- const openGroup = (label) => ({ label, order: sheetOrder(), sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
3775
+ const openGroup = (label2) => ({ label: label2, order: sheetOrder(), sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
3638
3776
  const emit = (e) => {
3639
3777
  for (const l of [...listeners]) {
3640
3778
  try {
@@ -3890,8 +4028,8 @@ function univerSheetsOtPort(o) {
3890
4028
  const a = forApply(m);
3891
4029
  applying = true;
3892
4030
  try {
3893
- const ok2 = cs.syncExecuteCommand(a.id, { ...json(a.params), unitId: u }, { fromCollab: true });
3894
- if (ok2 === false) throw new Error(`"${m.id}" was refused by the editor`);
4031
+ const ok3 = cs.syncExecuteCommand(a.id, { ...json(a.params), unitId: u }, { fromCollab: true });
4032
+ if (ok3 === false) throw new Error(`"${m.id}" was refused by the editor`);
3895
4033
  } finally {
3896
4034
  applying = false;
3897
4035
  }
@@ -3907,6 +4045,8 @@ function univerSheetsOtPort(o) {
3907
4045
  group = null;
3908
4046
  applying = true;
3909
4047
  try {
4048
+ const u = unitId();
4049
+ if (u) releaseUnitPluginState(cs, u, o.saveUnit?.(u) ?? null);
3910
4050
  o.load(snapshot);
3911
4051
  } finally {
3912
4052
  applying = false;
@@ -3996,11 +4136,59 @@ function moveSelectionsThrough(selections, m, maxRows, maxCols) {
3996
4136
  return selections.map((s) => ({ ...s, range: box(s.range, s.range.rangeType), ...s.primary ? { primary: box(s.primary) } : {} }));
3997
4137
  }
3998
4138
 
4139
+ // src/univer/collab/offline-text.ts
4140
+ var colName3 = (c) => {
4141
+ let n = c;
4142
+ let s = "";
4143
+ do {
4144
+ s = String.fromCharCode(65 + n % 26) + s;
4145
+ n = Math.floor(n / 26) - 1;
4146
+ } while (n >= 0);
4147
+ return s;
4148
+ };
4149
+ function collectDocText(v, out) {
4150
+ if (Array.isArray(v)) {
4151
+ for (const x of v) collectDocText(x, out);
4152
+ return;
4153
+ }
4154
+ if (!v || typeof v !== "object") return;
4155
+ const o = v;
4156
+ if (typeof o.dataStream === "string" && o.dataStream.length) out.push(o.dataStream);
4157
+ for (const k of Object.keys(o)) if (k !== "dataStream") collectDocText(o[k], out);
4158
+ }
4159
+ function collectCells(cellValue, out) {
4160
+ if (!cellValue || typeof cellValue !== "object") return;
4161
+ for (const [r, cols] of Object.entries(cellValue)) {
4162
+ if (!cols || typeof cols !== "object") continue;
4163
+ for (const [c, cell] of Object.entries(cols)) {
4164
+ const x = cell;
4165
+ const val = x?.f ?? x?.v;
4166
+ if (val !== void 0 && val !== null && val !== "") out.push(`${colName3(Number(c))}${Number(r) + 1}: ${String(val)}`);
4167
+ }
4168
+ }
4169
+ }
4170
+ function offlineTextOfGroups(buffers) {
4171
+ const docs = [];
4172
+ const cells = [];
4173
+ for (const groups of buffers) {
4174
+ for (const g of groups) {
4175
+ for (const m of g.mutations) {
4176
+ const p = m.params;
4177
+ if (p && "cellValue" in p) collectCells(p.cellValue, cells);
4178
+ else collectDocText(p, docs);
4179
+ }
4180
+ }
4181
+ }
4182
+ const text = docs.join("").replace(/\r/g, "\n").replace(/\u0000/g, "");
4183
+ return [text, cells.join("\n")].filter((s) => s.length > 0).join("\n");
4184
+ }
4185
+
3999
4186
  // src/sheets/workbook-ot-room.ts
4000
4187
  import * as Y3 from "yjs";
4001
4188
  import { Awareness as Awareness3 } from "y-protocols/awareness";
4002
4189
  import {
4003
4190
  awarenessOpPresence as awarenessOpPresence2,
4191
+ browserOfflineOptions as browserOfflineOptions2,
4004
4192
  claimCollaboratorColor as claimCollaboratorColor3,
4005
4193
  collabReplace as collabReplace3,
4006
4194
  collabRoomExists as collabRoomExists3,
@@ -4105,6 +4293,7 @@ async function startWorkbookOtRoom(port, o) {
4105
4293
  await provider.connect();
4106
4294
  publishAwareness();
4107
4295
  const client = db4();
4296
+ const offline = browserOfflineOptions2(`${o.workbookId}:${o.uid}`);
4108
4297
  const room = openSheetsOtRoom({
4109
4298
  port,
4110
4299
  clientId: o.clientId,
@@ -4125,7 +4314,9 @@ async function startWorkbookOtRoom(port, o) {
4125
4314
  replace: ({ snapshot, stateHash, clientId }) => collabReplace3(client, { roomId: o.workbookId, snapshot, stateHash, origin: "restore", clientId }),
4126
4315
  ...o.onNotice ? { onNotice: o.onNotice } : {},
4127
4316
  ...o.onIncident ? { onIncident: o.onIncident } : {},
4128
- ...o.onStatus ? { onStatus: o.onStatus } : {}
4317
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
4318
+ ...offline ? { offline } : {},
4319
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
4129
4320
  });
4130
4321
  await room.session.ready;
4131
4322
  return {
@@ -4178,6 +4369,7 @@ export {
4178
4369
  isNoopDocsOp,
4179
4370
  moveSelectionsThrough,
4180
4371
  normalizeDocsOp,
4372
+ offlineTextOfGroups,
4181
4373
  openDocsOtRoom,
4182
4374
  openSheetsOtRoom,
4183
4375
  rebaseSheetUndoStack,