@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.
@@ -60,6 +60,7 @@ __export(collab_exports, {
60
60
  isNoopDocsOp: () => isNoopDocsOp,
61
61
  moveSelectionsThrough: () => moveSelectionsThrough,
62
62
  normalizeDocsOp: () => normalizeDocsOp,
63
+ offlineTextOfGroups: () => offlineTextOfGroups,
63
64
  openDocsOtRoom: () => openDocsOtRoom,
64
65
  openSheetsOtRoom: () => openSheetsOtRoom,
65
66
  rebaseSheetUndoStack: () => rebaseSheetUndoStack,
@@ -1193,25 +1194,25 @@ function rebaseUndoStack(items, remote) {
1193
1194
  let dropped = 0;
1194
1195
  for (let i = items.length - 1; i >= 0; i--) {
1195
1196
  const item = items[i];
1196
- let ok2 = true;
1197
+ let ok3 = true;
1197
1198
  for (const list of [item.undoMutations, item.redoMutations]) {
1198
1199
  for (const m of list ?? []) {
1199
1200
  if (m.id !== RICH_TEXT_EDITING) continue;
1200
1201
  try {
1201
1202
  if (touchesPageSetup(m.params.actions) && touchesPageSetup(remote)) throw new Error("page setup");
1202
1203
  const r = transformDocsOp(m.params.actions, remote, "left");
1203
- if (isNoopDocsOp(r.op)) ok2 = false;
1204
+ if (isNoopDocsOp(r.op)) ok3 = false;
1204
1205
  else {
1205
1206
  m.params = { ...m.params, actions: r.op };
1206
1207
  delete m.params.textRanges;
1207
1208
  delete m.params.layoutState;
1208
1209
  }
1209
1210
  } catch {
1210
- ok2 = false;
1211
+ ok3 = false;
1211
1212
  }
1212
1213
  }
1213
1214
  }
1214
- if (!ok2) {
1215
+ if (!ok3) {
1215
1216
  items.splice(i, 1);
1216
1217
  dropped++;
1217
1218
  }
@@ -1370,7 +1371,9 @@ function openDocsOtRoom(o) {
1370
1371
  ...o.presence ? { presence: o.presence } : {},
1371
1372
  onNotice: (n) => notice(n),
1372
1373
  ...o.onIncident ? { onIncident: o.onIncident } : {},
1373
- ...o.onStatus ? { onStatus: o.onStatus } : {}
1374
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
1375
+ ...o.offline ? { offline: o.offline } : {},
1376
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
1374
1377
  });
1375
1378
  const isSaver = () => {
1376
1379
  if (!o.presence) return true;
@@ -1638,7 +1641,9 @@ function documentOtFactory(o) {
1638
1641
  replace: ({ snapshot, stateHash, clientId }) => (0, import_collab3.collabReplace)(client, { roomId: o.documentId, snapshot, stateHash, origin: "restore", clientId }),
1639
1642
  ...o.onNotice ? { onNotice: o.onNotice } : {},
1640
1643
  ...o.onIncident ? { onIncident: o.onIncident } : {},
1641
- ...o.onStatus ? { onStatus: o.onStatus } : {}
1644
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
1645
+ offline: (0, import_collab3.browserOfflineOptions)(`${o.documentId}:${o.uid}`),
1646
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
1642
1647
  });
1643
1648
  await room.session.ready;
1644
1649
  let lastKey = "";
@@ -1766,6 +1771,8 @@ var SHEET_MUTATIONS = {
1766
1771
  "sheet.mutation.insert-sheet": covered("sheet", "index", "sheet"),
1767
1772
  "sheet.mutation.remove-sheet": covered("sheet", "sheetIndex", "sheetsLeft"),
1768
1773
  "sheet.mutation.set-worksheet-order": covered("sheet", "fromOrder", "toOrder"),
1774
+ // ── covered (C9): our own cell comment anchors (comment-anchor-transform.ts; not emitted by Univer) ──────
1775
+ "matrx.mutation.set-comment-anchor": covered("anchor", "anchorId", "cell"),
1769
1776
  "sheet.mutation.reorder-range": covered("sort", "range", "order"),
1770
1777
  // ── never travels ────────────────────────────────────────────────────────────────────────────────
1771
1778
  "formula.mutation.set-formula-calculation-start": never(FORMULA_RESULT),
@@ -2208,6 +2215,74 @@ function refSheetsFor(texts, sheets) {
2208
2215
  return Object.keys(out).length ? out : void 0;
2209
2216
  }
2210
2217
 
2218
+ // src/collab/sheets/comment-anchor-transform.ts
2219
+ var SET_SHEET_COMMENT_ANCHOR = "matrx.mutation.set-comment-anchor";
2220
+ var REMOVE_SHEET = "sheet.mutation.remove-sheet";
2221
+ function structuralAxisOp(id, params) {
2222
+ const p = params;
2223
+ switch (id) {
2224
+ case "sheet.mutation.insert-row":
2225
+ return p.range ? { axis: "row", op: { kind: "insert", at: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } } : null;
2226
+ case "sheet.mutation.remove-rows":
2227
+ return p.range ? { axis: "row", op: { kind: "remove", start: p.range.startRow, count: p.range.endRow - p.range.startRow + 1 } } : null;
2228
+ case "sheet.mutation.insert-col":
2229
+ return p.range ? { axis: "col", op: { kind: "insert", at: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } } : null;
2230
+ case "sheet.mutation.remove-col":
2231
+ return p.range ? { axis: "col", op: { kind: "remove", start: p.range.startColumn, count: p.range.endColumn - p.range.startColumn + 1 } } : null;
2232
+ case "sheet.mutation.move-rows":
2233
+ 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;
2234
+ case "sheet.mutation.move-columns":
2235
+ return p.sourceRange && p.targetRange ? {
2236
+ axis: "col",
2237
+ op: { kind: "move", from: p.sourceRange.startColumn, count: p.sourceRange.endColumn - p.sourceRange.startColumn + 1, to: p.targetRange.startColumn }
2238
+ } : null;
2239
+ default:
2240
+ return null;
2241
+ }
2242
+ }
2243
+ function moveSheetAnchorCell(cell, sheet, id, params) {
2244
+ if (String(params.subUnitId ?? "") !== sheet) return cell;
2245
+ if (id === REMOVE_SHEET) return null;
2246
+ const s = structuralAxisOp(id, params);
2247
+ if (!s) return cell;
2248
+ if (s.axis === "row") {
2249
+ const row = mapIndex(s.op, cell.row);
2250
+ return row === null ? null : row === cell.row ? cell : { row, col: cell.col };
2251
+ }
2252
+ const col = mapIndex(s.op, cell.col);
2253
+ return col === null ? null : col === cell.col ? cell : { row: cell.row, col };
2254
+ }
2255
+ function colName(c) {
2256
+ let s = "";
2257
+ for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + (n - 1) % 26) + s;
2258
+ return s;
2259
+ }
2260
+ var sheetCellName = (cell) => `${colName(cell.col)}${cell.row + 1}`;
2261
+ function cellOf(m) {
2262
+ const c = m.params.cell;
2263
+ return c && typeof c.row === "number" && typeof c.col === "number" ? c : null;
2264
+ }
2265
+ var ok = (op, lost = [], dropped = []) => ({ op, lost, dropped });
2266
+ var label = (m) => {
2267
+ const c = cellOf(m);
2268
+ return `${String(m.params.subUnitId ?? "")}!${c ? sheetCellName(c) : "?"} comment`;
2269
+ };
2270
+ function transformCommentAnchor(x, y, side) {
2271
+ const xa = x.id === SET_SHEET_COMMENT_ANCHOR;
2272
+ const ya = y.id === SET_SHEET_COMMENT_ANCHOR;
2273
+ if (!xa && !ya) return null;
2274
+ if (!xa) return ok([x]);
2275
+ if (ya) {
2276
+ if (x.params.anchorId !== y.params.anchorId || x.params.subUnitId !== y.params.subUnitId) return ok([x]);
2277
+ return side === "left" ? ok([x], [label(y)]) : ok([], [], [label(x)]);
2278
+ }
2279
+ const cell = cellOf(x);
2280
+ if (!cell) return ok([x]);
2281
+ const moved = moveSheetAnchorCell(cell, String(x.params.subUnitId ?? ""), y.id, y.params);
2282
+ if (!moved) return ok([], [], [label(x)]);
2283
+ return ok([moved === cell ? x : { id: x.id, params: { ...x.params, cell: moved } }]);
2284
+ }
2285
+
2211
2286
  // src/collab/sheets/transform/transform.ts
2212
2287
  var SHEET_TRANSFORMER_VERSION = "c5c-1";
2213
2288
  var ID = {
@@ -2239,16 +2314,16 @@ var ID = {
2239
2314
  var PAIR_BARRIERS = {};
2240
2315
  var pairKey = (a, b) => a < b ? `${a}|${b}` : `${b}|${a}`;
2241
2316
  var barrier2 = (reason) => ({ barrier: true, reason });
2242
- var ok = (op, lost = [], dropped = []) => ({ op, lost, dropped });
2317
+ var ok2 = (op, lost = [], dropped = []) => ({ op, lost, dropped });
2243
2318
  var flip = (side) => side === "left" ? "right" : "left";
2244
2319
  var sheetOf = (m) => String(m.params.subUnitId ?? "");
2245
- function colName(c) {
2320
+ function colName2(c) {
2246
2321
  let s = "";
2247
2322
  for (let n = c + 1; n > 0; n = Math.floor((n - 1) / 26)) s = String.fromCharCode(65 + (n - 1) % 26) + s;
2248
2323
  return s;
2249
2324
  }
2250
- var cellRef = (sheet, row, col) => `${sheet}!${colName(col)}${row + 1}`;
2251
- var rangeRef = (sheet, r) => `${sheet}!${colName(r.startColumn)}${r.startRow + 1}:${colName(r.endColumn)}${r.endRow + 1}`;
2325
+ var cellRef = (sheet, row, col) => `${sheet}!${colName2(col)}${row + 1}`;
2326
+ var rangeRef = (sheet, r) => `${sheet}!${colName2(r.startColumn)}${r.startRow + 1}:${colName2(r.endColumn)}${r.endRow + 1}`;
2252
2327
  function structuralOf(m) {
2253
2328
  const p = m.params;
2254
2329
  switch (m.id) {
@@ -2503,9 +2578,9 @@ function transformCell(X, Y4, side) {
2503
2578
  return { entries: Object.keys(out).length ? [out, ...tail] : tail, xLost, yLost };
2504
2579
  }
2505
2580
  function transformCellsOverCells(x, y, side) {
2506
- if (sheetOf(x) !== sheetOf(y)) return ok([x]);
2581
+ if (sheetOf(x) !== sheetOf(y)) return ok2([x]);
2507
2582
  const ycells = cellsOf(y);
2508
- if (!cellsOverlap(cellsOf(x), ycells)) return ok([x]);
2583
+ if (!cellsOverlap(cellsOf(x), ycells)) return ok2([x]);
2509
2584
  const xd = isDerived(x);
2510
2585
  const yd = isDerived(y);
2511
2586
  const eff = derivedSide(x, y, side);
@@ -2531,7 +2606,7 @@ function transformCellsOverCells(x, y, side) {
2531
2606
  });
2532
2607
  if (why) return barrier2(why);
2533
2608
  const op = passes.filter((p) => !isEmptyMatrix(p)).map((p) => cellsMutation(x, p));
2534
- return ok(op, lost, dropped);
2609
+ return ok2(op, lost, dropped);
2535
2610
  }
2536
2611
  var SIDE_CAR_PARAMS = ["refSheets", "previousName", "derived", "sheetIndex", "sheetsLeft"];
2537
2612
  var isDerived = (m) => m.params.derived === true;
@@ -2602,7 +2677,7 @@ function cellThrough(sheet, change, r, c) {
2602
2677
  return nr === null || nc === null ? null : [nr, nc];
2603
2678
  }
2604
2679
  function cellsOverChange(x, change) {
2605
- if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok([x]);
2680
+ if (!hasFormula(x) && (change.kind !== "axis" || change.sheet !== sheetOf(x))) return ok2([x]);
2606
2681
  const ctx = formulaCtx(x);
2607
2682
  const out = {};
2608
2683
  const dropped = [];
@@ -2631,9 +2706,9 @@ function cellsOverChange(x, change) {
2631
2706
  });
2632
2707
  if (why) return barrier2(why);
2633
2708
  const rsAfter = refSheetsAfter(ctx.refSheets, change);
2634
- if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok([x]);
2709
+ if (!changed && JSON.stringify(rsAfter ?? null) === JSON.stringify(ctx.refSheets ?? null)) return ok2([x]);
2635
2710
  const params = { ...withRefSheets(x.params, rsAfter), cellValue: out };
2636
- return ok(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
2711
+ return ok2(isEmptyMatrix(out) ? [] : [{ id: x.id, params }], [], dropped);
2637
2712
  }
2638
2713
  function rewritesOf(y, change) {
2639
2714
  if (!hasFormula(y)) return null;
@@ -2680,36 +2755,36 @@ function formulaPair(x, y, side) {
2680
2755
  const fy = familyOf(y.id);
2681
2756
  const SET_NAME_BARRIER = "set-defined-name without previousName (capture must record the name it replaces) against formula text";
2682
2757
  if (fx === "defname" && fy === "defname") {
2683
- if (String(x.params.id) !== String(y.params.id)) return ok([x]);
2758
+ if (String(x.params.id) !== String(y.params.id)) return ok2([x]);
2684
2759
  const eff = derivedSide(x, y, side);
2685
- if (eff === "left") return ok([x], isDerived(y) ? [] : [`defined name "${String(y.params.name)}"`]);
2686
- return ok([], [], isDerived(x) ? [] : [`defined name "${String(x.params.name)}"`]);
2760
+ if (eff === "left") return ok2([x], isDerived(y) ? [] : [`defined name "${String(y.params.name)}"`]);
2761
+ return ok2([], [], isDerived(x) ? [] : [`defined name "${String(x.params.name)}"`]);
2687
2762
  }
2688
2763
  if (fx === "defname") {
2689
2764
  if (fy === "cell") {
2690
2765
  if (setNameWithoutPrevious(x) && hasFormula(y)) return barrier2(SET_NAME_BARRIER);
2691
2766
  const ch2 = refChangeOf(x);
2692
- if (!ch2) return ok([x]);
2767
+ if (!ch2) return ok2([x]);
2693
2768
  const add = rewritesOf(y, ch2);
2694
2769
  if (typeof add === "string") return barrier2(add);
2695
- return ok(add ? [x, add] : [x]);
2770
+ return ok2(add ? [x, add] : [x]);
2696
2771
  }
2697
2772
  const ch = refChangeOf(y);
2698
- if (!ch) return ok([x]);
2773
+ if (!ch) return ok2([x]);
2699
2774
  const r = definedNameThrough(x, ch);
2700
- return typeof r === "string" ? barrier2(r) : ok([r.op]);
2775
+ return typeof r === "string" ? barrier2(r) : ok2([r.op]);
2701
2776
  }
2702
2777
  if (fy === "defname") {
2703
2778
  if (fx === "cell") {
2704
2779
  if (setNameWithoutPrevious(y) && hasFormula(x)) return barrier2(SET_NAME_BARRIER);
2705
2780
  const ch2 = refChangeOf(y);
2706
- return ch2 ? cellsOverChange(x, ch2) : ok([x]);
2781
+ return ch2 ? cellsOverChange(x, ch2) : ok2([x]);
2707
2782
  }
2708
2783
  const ch = refChangeOf(x);
2709
- if (!ch) return ok([x]);
2784
+ if (!ch) return ok2([x]);
2710
2785
  const r = definedNameThrough(y, ch);
2711
2786
  if (typeof r === "string") return barrier2(r);
2712
- return ok(r.changed ? [x, asDerived(r.op)] : [x]);
2787
+ return ok2(r.changed ? [x, asDerived(r.op)] : [x]);
2713
2788
  }
2714
2789
  if (fx === "cell") {
2715
2790
  const ch = refChangeOf(y);
@@ -2724,7 +2799,7 @@ function formulaPair(x, y, side) {
2724
2799
  });
2725
2800
  const add = rewritesOf(y, ch);
2726
2801
  if (typeof add === "string") return barrier2(add);
2727
- return ok(add ? [x, add] : [x], lost);
2802
+ return ok2(add ? [x, add] : [x], lost);
2728
2803
  }
2729
2804
  return null;
2730
2805
  }
@@ -2872,20 +2947,20 @@ function numfmtPair(x, y, side, sx, sy) {
2872
2947
  const nx = isNumfmt(x);
2873
2948
  const ny = isNumfmt(y);
2874
2949
  if (!nx && !ny) return null;
2875
- if (nx && sy) return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
2876
- if (ny && sx) return ok([x]);
2950
+ if (nx && sy) return ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsThrough(sy, p.ranges) }))));
2951
+ if (ny && sx) return ok2([x]);
2877
2952
  if (nx && ny) {
2878
- if (side === "left") return ok([x]);
2953
+ if (side === "left") return ok2([x]);
2879
2954
  const ys = nfParts(y).flatMap((p) => p.ranges);
2880
- return ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
2955
+ return ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) }))));
2881
2956
  }
2882
2957
  if (nx && y.id === ID.values) {
2883
- if (side === "left") return ok([x]);
2958
+ if (side === "left") return ok2([x]);
2884
2959
  const ys = nWrites(y);
2885
- return ys.length ? ok(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok([x]);
2960
+ return ys.length ? ok2(nfBuild(x, nfParts(x).map((p) => ({ ...p, ranges: rectsMinus(p.ranges, ys) })))) : ok2([x]);
2886
2961
  }
2887
2962
  if (ny && x.id === ID.values) {
2888
- if (side === "left") return ok([x]);
2963
+ if (side === "left") return ok2([x]);
2889
2964
  const out = {};
2890
2965
  const tail = {};
2891
2966
  let touched = false;
@@ -2911,31 +2986,31 @@ function numfmtPair(x, y, side, sx, sy) {
2911
2986
  }
2912
2987
  putCell(out, r, c, v);
2913
2988
  });
2914
- if (!touched) return ok([x]);
2989
+ if (!touched) return ok2([x]);
2915
2990
  const ops = [];
2916
2991
  if (!isEmptyMatrix(out)) ops.push(cellsMutation(x, out));
2917
2992
  if (!isEmptyMatrix(tail)) ops.push({ id: ID.values, params: { subUnitId: sheetOf(x), cellValue: tail } });
2918
- return ok(ops);
2993
+ return ok2(ops);
2919
2994
  }
2920
- return ok([x]);
2995
+ return ok2([x]);
2921
2996
  }
2922
2997
  var isCount = (m) => m.id === ID.rowCount || m.id === ID.colCount;
2923
2998
  var countAxis = (m) => m.id === ID.rowCount ? "row" : "col";
2924
2999
  var countKey = (m) => m.id === ID.rowCount ? "rowCount" : "columnCount";
2925
3000
  function countPair(x, y, sy) {
2926
- if (!isCount(x)) return isCount(y) ? ok([x]) : null;
3001
+ if (!isCount(x)) return isCount(y) ? ok2([x]) : null;
2927
3002
  const k = countKey(x);
2928
3003
  const v = Number(x.params[k]);
2929
3004
  if (sy) {
2930
- if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok([x]);
3005
+ if (sy.axis !== countAxis(x) || sy.op.kind === "move") return ok2([x]);
2931
3006
  const d = sy.op.kind === "insert" ? sy.op.count : -sy.op.count;
2932
- return ok([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
3007
+ return ok2([{ id: x.id, params: { ...x.params, [k]: Math.max(1, v + d) } }]);
2933
3008
  }
2934
3009
  if (isCount(y) && y.id === x.id) {
2935
3010
  const w = Number(y.params[k]);
2936
- return ok([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
3011
+ return ok2([w > v ? { id: x.id, params: { ...x.params, [k]: w } } : x]);
2937
3012
  }
2938
- return ok([x]);
3013
+ return ok2([x]);
2939
3014
  }
2940
3015
  var isSheetOp = (m) => m.id === ID.insertSheet || m.id === ID.removeSheet || m.id === ID.sheetOrder;
2941
3016
  var sheetIdOf = (m) => m.id === ID.insertSheet ? String(m.params.sheet?.id ?? "") : sheetOf(m);
@@ -2968,31 +3043,31 @@ function sheetPair(x, y, side) {
2968
3043
  const b = sheetAxisOf(y);
2969
3044
  if (!a || !b) return barrier2("a sheet add or remove without its index (capture must call annotateSheetOps)");
2970
3045
  if (x.id === ID.insertSheet && y.id === ID.insertSheet && sheetIdOf(x) === sheetIdOf(y)) {
2971
- return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok([]) : barrier2("the same sheet id added twice with different content");
3046
+ return JSON.stringify(x.params) === JSON.stringify(y.params) ? ok2([]) : barrier2("the same sheet id added twice with different content");
2972
3047
  }
2973
3048
  if (x.id === ID.removeSheet && typeof x.params.sheetsLeft === "number" && sheetIdOf(x) !== sheetIdOf(y) && (y.id === ID.removeSheet || y.id === ID.insertSheet)) {
2974
3049
  const left = x.params.sheetsLeft + (y.id === ID.insertSheet ? 1 : -1);
2975
3050
  if (left < 1) return barrier2("concurrent sheet removes would leave the workbook without a sheet");
2976
3051
  const out2 = transformAxis(a, b, side);
2977
3052
  if (!out2) return barrier2("sheet order: no transform");
2978
- return ok(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
3053
+ return ok2(out2.map((o) => buildSheetOp({ id: x.id, params: { ...x.params, sheetsLeft: left } }, o)));
2979
3054
  }
2980
3055
  const out = transformAxis(a, b, side);
2981
3056
  if (!out) return barrier2("sheet order: no transform");
2982
- return ok(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
3057
+ return ok2(out.map((o) => buildSheetOp(x, o)), [], out.length === 0 && x.id === ID.sheetOrder ? [`${sheetIdOf(x)}: sheet order`] : []);
2983
3058
  }
2984
3059
  if (ys) {
2985
- if (y.id !== ID.removeSheet) return ok([x]);
3060
+ if (y.id !== ID.removeSheet) return ok2([x]);
2986
3061
  const gone2 = sheetOf(y);
2987
3062
  if (namesSheet(x, gone2)) return barrier2("a formula names a sheet removed at the same time");
2988
3063
  if (sheetOf(x) === gone2 && x.id !== ID.setName && x.id !== ID.removeName)
2989
- return ok([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
2990
- return ok([x]);
3064
+ return ok2([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
3065
+ return ok2([x]);
2991
3066
  }
2992
- if (x.id !== ID.removeSheet) return ok([x]);
3067
+ if (x.id !== ID.removeSheet) return ok2([x]);
2993
3068
  const gone = sheetOf(x);
2994
3069
  if (namesSheet(y, gone)) return barrier2("a formula names a sheet removed at the same time");
2995
- return ok([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
3070
+ return ok2([x], sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : []);
2996
3071
  }
2997
3072
  function annotateSheetOps(group, sheetOrder) {
2998
3073
  const order = [...sheetOrder];
@@ -3090,22 +3165,22 @@ function sortPair(x, y, sx, sy) {
3090
3165
  const a = sortOf(x).range;
3091
3166
  const b = sortOf(y).range;
3092
3167
  const overlap = a.startRow <= b.endRow && b.startRow <= a.endRow && a.startColumn <= b.endColumn && b.startColumn <= a.endColumn;
3093
- return overlap ? barrier2("two sorts of overlapping ranges at once") : ok([x]);
3168
+ return overlap ? barrier2("two sorts of overlapping ranges at once") : ok2([x]);
3094
3169
  }
3095
3170
  if (xs) {
3096
3171
  if (sy) {
3097
3172
  const t = sortThrough(sortOf(x), sy);
3098
- return t ? ok(buildSort(x, t)) : barrier2("a row or column move through a sorted range");
3173
+ return t ? ok2(buildSort(x, t)) : barrier2("a row or column move through a sorted range");
3099
3174
  }
3100
- return ok([x]);
3175
+ return ok2([x]);
3101
3176
  }
3102
3177
  const o = sortOf(y);
3103
3178
  const Q = sortQ(o);
3104
3179
  const moved = (r) => r >= o.range.startRow && r <= o.range.endRow && Q.has(r);
3105
3180
  if (sx) {
3106
- if (sx.axis === "col") return sx.op.kind === "move" && !sortThrough(o, sx) ? barrier2("a column move through a sorted range") : ok([x]);
3107
- if (sx.op.kind === "insert") return ok([x]);
3108
- if (sx.op.kind === "move") return sortThrough(o, sx) ? ok([x]) : barrier2("a row move through a sorted range");
3181
+ if (sx.axis === "col") return sx.op.kind === "move" && !sortThrough(o, sx) ? barrier2("a column move through a sorted range") : ok2([x]);
3182
+ if (sx.op.kind === "insert") return ok2([x]);
3183
+ if (sx.op.kind === "move") return sortThrough(o, sx) ? ok2([x]) : barrier2("a row move through a sorted range");
3109
3184
  const rows = [];
3110
3185
  let partial = false;
3111
3186
  for (let i = sx.op.start; i < sx.op.start + sx.op.count; i++) {
@@ -3113,7 +3188,7 @@ function sortPair(x, y, sx, sy) {
3113
3188
  rows.push(Q.get(i) ?? i);
3114
3189
  }
3115
3190
  if (partial) return barrier2("a row remove against a concurrent sort of those rows");
3116
- return ok([x]);
3191
+ return ok2([x]);
3117
3192
  }
3118
3193
  if (x.id === ID.values) {
3119
3194
  const out = {};
@@ -3124,7 +3199,7 @@ function sortPair(x, y, sx, sy) {
3124
3199
  changed = true;
3125
3200
  } else putCell(out, r, c, v);
3126
3201
  });
3127
- return changed ? ok([cellsMutation(x, out)]) : ok([x]);
3202
+ return changed ? ok2([cellsMutation(x, out)]) : ok2([x]);
3128
3203
  }
3129
3204
  if (isNumfmt(x)) {
3130
3205
  const parts = nfParts(x).map((p) => {
@@ -3140,9 +3215,9 @@ function sortPair(x, y, sx, sy) {
3140
3215
  }
3141
3216
  return { ...p, ranges };
3142
3217
  });
3143
- return ok(nfBuild(x, parts));
3218
+ return ok2(nfBuild(x, parts));
3144
3219
  }
3145
- return ok([x]);
3220
+ return ok2([x]);
3146
3221
  }
3147
3222
  function familyOf(id) {
3148
3223
  const e = SHEET_MUTATIONS[id];
@@ -3158,13 +3233,15 @@ function transformMutation(x, y, side) {
3158
3233
  if (why) return barrier2(why);
3159
3234
  }
3160
3235
  }
3236
+ const ca = transformCommentAnchor(x, y, side);
3237
+ if (ca) return ca;
3161
3238
  const pb = PAIR_BARRIERS[pairKey(x.id, y.id)];
3162
3239
  if (pb) return barrier2(`${x.id} \xD7 ${y.id}: ${pb.reason}${pb.seed === null ? "" : ` (fuzz seed ${pb.seed})`}`);
3163
3240
  const sp = sheetPair(x, y, side);
3164
3241
  if (sp) return sp;
3165
3242
  const fp = formulaPair(x, y, side);
3166
3243
  if (fp) return fp;
3167
- if (sheetOf(x) !== sheetOf(y)) return ok([x]);
3244
+ if (sheetOf(x) !== sheetOf(y)) return ok2([x]);
3168
3245
  const fx = familyOf(x.id);
3169
3246
  const fy = familyOf(y.id);
3170
3247
  const sy = structuralOf(y);
@@ -3176,11 +3253,11 @@ function transformMutation(x, y, side) {
3176
3253
  const np = numfmtPair(x, y, side, sx, sy);
3177
3254
  if (np) return np;
3178
3255
  if (sx && sy) {
3179
- if (sx.axis !== sy.axis) return ok([x]);
3256
+ if (sx.axis !== sy.axis) return ok2([x]);
3180
3257
  const out = transformAxis(sx.op, sy.op, side);
3181
3258
  if (!out) return barrier2(`${x.id} over ${y.id}: moved blocks overlap in part, or the block would split`);
3182
3259
  const dropped = out.length === 0 && sx.op.kind === "move" ? [`${sheetOf(x)}: moved ${sx.axis}s`] : [];
3183
- return ok(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);
3260
+ return ok2(out.map((o) => buildStructural(x, sx.axis, o)), [], dropped);
3184
3261
  }
3185
3262
  if (sy) {
3186
3263
  if (fx === "merge") {
@@ -3191,23 +3268,23 @@ function transformMutation(x, y, side) {
3191
3268
  if (t) kept.push(t);
3192
3269
  else dropped.push(rangeRef(sheetOf(x), r));
3193
3270
  }
3194
- return ok(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);
3271
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], x.id === ID.addMerge ? dropped : []);
3195
3272
  }
3196
3273
  if (fx === "size") {
3197
3274
  const size = sizeOf(x);
3198
- if (size.axis !== sy.axis) return ok([x]);
3275
+ if (size.axis !== sy.axis) return ok2([x]);
3199
3276
  const next = /* @__PURE__ */ new Map();
3200
3277
  for (const [i, v] of size.values) {
3201
3278
  const m = mapIndex(sy.op, i);
3202
3279
  if (m !== null) next.set(m, v);
3203
3280
  }
3204
3281
  const built = buildSize(x, next);
3205
- return ok(built ? [built] : []);
3282
+ return ok2(built ? [built] : []);
3206
3283
  }
3207
- return ok([x]);
3284
+ return ok2([x]);
3208
3285
  }
3209
3286
  if (sx) {
3210
- if (fy !== "merge" || y.id !== ID.addMerge) return ok([x]);
3287
+ if (fy !== "merge" || y.id !== ID.addMerge) return ok2([x]);
3211
3288
  const remove = [];
3212
3289
  const add = [];
3213
3290
  for (const r of mergeRanges(y)) {
@@ -3217,11 +3294,11 @@ function transformMutation(x, y, side) {
3217
3294
  if (t.range) add.push(t.range);
3218
3295
  }
3219
3296
  const lostMerges = mergeRanges(y).filter((r) => mergeThrough(sx, r).range === null).map((r) => rangeRef(sheetOf(y), r));
3220
- if (!remove.length) return ok([x], lostMerges);
3297
+ if (!remove.length) return ok2([x], lostMerges);
3221
3298
  const sheet = sheetOf(x);
3222
3299
  const pre = sx.op.kind === "insert" ? [] : [mergeMutation(ID.removeMerge, sheet, remove)];
3223
3300
  const mid = sx.op.kind === "insert" ? [mergeMutation(ID.removeMerge, sheet, remove)] : [];
3224
- return ok([...pre, x, ...mid, ...add.length ? [mergeMutation(ID.addMerge, sheet, add)] : []], lostMerges);
3301
+ return ok2([...pre, x, ...mid, ...add.length ? [mergeMutation(ID.addMerge, sheet, add)] : []], lostMerges);
3225
3302
  }
3226
3303
  if (fx === "cell" && fy === "cell") return transformCellsOverCells(x, y, side);
3227
3304
  if (fx === "merge" && fy === "merge") {
@@ -3230,45 +3307,45 @@ function transformMutation(x, y, side) {
3230
3307
  const hit = (r) => yr.some((q) => intersects(r, q));
3231
3308
  const sheet = sheetOf(x);
3232
3309
  if (x.id === ID.addMerge && y.id === ID.addMerge) {
3233
- if (!xr.some(hit)) return ok([x]);
3310
+ if (!xr.some(hit)) return ok2([x]);
3234
3311
  if (side === "left") {
3235
3312
  const lost = yr.filter((q) => xr.some((r) => intersects(r, q))).map((q) => rangeRef(sheet, q));
3236
- return ok([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);
3313
+ return ok2([mergeMutation(ID.removeMerge, sheet, xr.filter(hit)), x], lost);
3237
3314
  }
3238
3315
  const kept = xr.filter((r) => !hit(r));
3239
- return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3316
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3240
3317
  }
3241
3318
  if (x.id === ID.addMerge && y.id === ID.removeMerge) {
3242
- 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)) : []);
3319
+ 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)) : []);
3243
3320
  const kept = xr.filter((r) => !hit(r));
3244
- return ok(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3321
+ return ok2(kept.length ? [withRanges(x, kept)] : [], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3245
3322
  }
3246
3323
  if (x.id === ID.removeMerge && y.id === ID.addMerge) {
3247
3324
  const touched = yr.filter((q) => xr.some((r) => intersects(r, q)));
3248
- if (!touched.length) return ok([x]);
3249
- if (side === "left") return ok([x], touched.map((q) => rangeRef(sheet, q)));
3250
- return ok([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3325
+ if (!touched.length) return ok2([x]);
3326
+ if (side === "left") return ok2([x], touched.map((q) => rangeRef(sheet, q)));
3327
+ return ok2([x, mergeMutation(ID.addMerge, sheet, touched)], [], xr.filter(hit).map((r) => rangeRef(sheet, r)));
3251
3328
  }
3252
- return ok([x]);
3329
+ return ok2([x]);
3253
3330
  }
3254
3331
  if (fx === "size" && fy === "size") {
3255
3332
  const a = sizeOf(x);
3256
3333
  const b = sizeOf(y);
3257
- if (a.axis !== b.axis || a.attr !== b.attr) return ok([x]);
3334
+ if (a.axis !== b.axis || a.attr !== b.attr) return ok2([x]);
3258
3335
  if (side === "left") {
3259
3336
  const lost = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
3260
- return ok([x], lost);
3337
+ return ok2([x], lost);
3261
3338
  }
3262
3339
  const next = new Map([...a.values].filter(([i]) => !b.values.has(i)));
3263
3340
  const built = buildSize(x, next);
3264
3341
  const dropped = [...a.values.keys()].filter((i) => b.values.has(i)).map((i) => `${sheetOf(x)}: ${a.axis} ${i + 1} ${a.attr}`);
3265
- return ok(built ? [built] : [], [], dropped);
3342
+ return ok2(built ? [built] : [], [], dropped);
3266
3343
  }
3267
3344
  if (fx === "name" && fy === "name") {
3268
- if (side === "left") return ok([x], [`${sheetOf(x)}: name "${String(y.params.name)}"`]);
3269
- return ok([], [], [`${sheetOf(x)}: name "${String(x.params.name)}"`]);
3345
+ if (side === "left") return ok2([x], [`${sheetOf(x)}: name "${String(y.params.name)}"`]);
3346
+ return ok2([], [], [`${sheetOf(x)}: name "${String(x.params.name)}"`]);
3270
3347
  }
3271
- return ok([x]);
3348
+ return ok2([x]);
3272
3349
  }
3273
3350
  var blocked = (p) => !Array.isArray(p);
3274
3351
  function tSeq(xs, ys, side, acc) {
@@ -3447,10 +3524,10 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3447
3524
  let dropped = 0;
3448
3525
  for (let i = items.length - 1; i >= 0; i--) {
3449
3526
  const item = items[i];
3450
- let ok2 = true;
3527
+ let ok3 = true;
3451
3528
  for (const key of ["undoMutations", "redoMutations"]) {
3452
3529
  const list = item[key];
3453
- if (!ok2 || !list?.length) continue;
3530
+ if (!ok3 || !list?.length) continue;
3454
3531
  const isOperation = (id) => !SHEET_MUTATIONS[id] && id.includes(".operation.");
3455
3532
  const operations = list.filter((m) => isOperation(m.id));
3456
3533
  let shaped = cachedShape(list);
@@ -3459,14 +3536,14 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3459
3536
  shapedLists.set(list, { src: list.slice(), shaped });
3460
3537
  }
3461
3538
  if (shaped.some((m) => m === null)) {
3462
- ok2 = false;
3539
+ ok3 = false;
3463
3540
  continue;
3464
3541
  }
3465
3542
  if (!shaped.length) continue;
3466
3543
  try {
3467
3544
  const r = transformGroup(shaped, remote, "left");
3468
3545
  if (isBarrier(r) || r.op.length === 0) {
3469
- ok2 = false;
3546
+ ok3 = false;
3470
3547
  continue;
3471
3548
  }
3472
3549
  if (r.op.length === shaped.length && r.op.every((m, i2) => m === shaped[i2])) continue;
@@ -3474,10 +3551,10 @@ function rebaseSheetUndoStack(items, remote, unitId) {
3474
3551
  shapedLists.set(next, { src: next.slice(), shaped: r.op });
3475
3552
  item[key] = next;
3476
3553
  } catch {
3477
- ok2 = false;
3554
+ ok3 = false;
3478
3555
  }
3479
3556
  }
3480
- if (!ok2) {
3557
+ if (!ok3) {
3481
3558
  items.splice(i, 1);
3482
3559
  dropped++;
3483
3560
  }
@@ -3621,7 +3698,9 @@ function openSheetsOtRoom(o) {
3621
3698
  ...o.presence ? { presence: o.presence } : {},
3622
3699
  onNotice: (n) => notice(n),
3623
3700
  ...o.onIncident ? { onIncident: o.onIncident } : {},
3624
- ...o.onStatus ? { onStatus: o.onStatus } : {}
3701
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
3702
+ ...o.offline ? { offline: o.offline } : {},
3703
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
3625
3704
  });
3626
3705
  const isSaver = () => {
3627
3706
  if (!o.presence) return true;
@@ -3652,6 +3731,65 @@ function openSheetsOtRoom(o) {
3652
3731
  };
3653
3732
  }
3654
3733
 
3734
+ // src/univer/collab/sheets-ot/plugin-teardown.ts
3735
+ var perSheetList = (data) => Object.entries(data).flatMap(([sheet, list]) => Array.isArray(list) ? [[sheet, list.filter((x) => !!x && typeof x === "object")]] : []);
3736
+ var PLUGIN_TEARDOWNS = [
3737
+ {
3738
+ resource: "SHEET_CONDITIONAL_FORMATTING_PLUGIN",
3739
+ removals: (unitId, data) => perSheetList(data).flatMap(
3740
+ ([subUnitId, rules]) => rules.filter((r) => typeof r.cfId === "string").map((r) => ({ id: "sheet.mutation.delete-conditional-rule", params: { unitId, subUnitId, cfId: r.cfId } }))
3741
+ )
3742
+ },
3743
+ {
3744
+ resource: "SHEET_DATA_VALIDATION_PLUGIN",
3745
+ removals: (unitId, data) => perSheetList(data).flatMap(([subUnitId, rules]) => {
3746
+ const ids = rules.map((r) => r.uid).filter((u) => typeof u === "string");
3747
+ return ids.length ? [{ id: "data-validation.mutation.removeRule", params: { unitId, subUnitId, ruleId: ids, source: "command" } }] : [];
3748
+ })
3749
+ },
3750
+ {
3751
+ resource: "SHEET_NOTE_PLUGIN",
3752
+ removals: (unitId, data) => Object.entries(data).flatMap(
3753
+ ([sheetId, rows]) => Object.entries(rows ?? {}).flatMap(
3754
+ ([row, cols]) => Object.entries(cols ?? {}).map(([col, note]) => ({
3755
+ id: "sheet.mutation.remove-note",
3756
+ params: { unitId, sheetId, row: Number(row), col: Number(col), ...note && typeof note.id === "string" ? { noteId: note.id } : {}, silent: true }
3757
+ }))
3758
+ )
3759
+ )
3760
+ }
3761
+ ];
3762
+ function resourcesOf(saved) {
3763
+ const out = /* @__PURE__ */ new Map();
3764
+ const list = saved?.resources;
3765
+ for (const r of Array.isArray(list) ? list : []) {
3766
+ if (!r?.name) continue;
3767
+ try {
3768
+ const data = typeof r.data === "string" ? r.data ? JSON.parse(r.data) : null : r.data;
3769
+ if (data && typeof data === "object") out.set(r.name, data);
3770
+ } catch {
3771
+ }
3772
+ }
3773
+ return out;
3774
+ }
3775
+ function releaseUnitPluginState(cs, unitId, saved) {
3776
+ const resources = resourcesOf(saved);
3777
+ let ran = 0;
3778
+ for (const t of PLUGIN_TEARDOWNS) {
3779
+ const data = resources.get(t.resource);
3780
+ if (!data) continue;
3781
+ for (const m of t.removals(unitId, data)) {
3782
+ try {
3783
+ cs.syncExecuteCommand(m.id, m.params, { onlyLocal: true });
3784
+ ran++;
3785
+ } catch (err) {
3786
+ console.warn(`[sheets-ot] could not release ${t.resource} state before a reload`, err);
3787
+ }
3788
+ }
3789
+ }
3790
+ return ran;
3791
+ }
3792
+
3655
3793
  // src/univer/collab/sheets-ot/univer-port.ts
3656
3794
  var COMMAND = 0;
3657
3795
  var MUTATION = 2;
@@ -3698,7 +3836,7 @@ function univerSheetsOtPort(o) {
3698
3836
  return out;
3699
3837
  };
3700
3838
  const sheetOrder = () => (o.workbook()?.getSheets() ?? []).map((ws) => ws.getSheetId());
3701
- const openGroup = (label) => ({ label, order: sheetOrder(), sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
3839
+ const openGroup = (label2) => ({ label: label2, order: sheetOrder(), sheets: sheetNames(), names: definedNames(), mutations: [], inverses: [], notShared: null });
3702
3840
  const emit = (e) => {
3703
3841
  for (const l of [...listeners]) {
3704
3842
  try {
@@ -3954,8 +4092,8 @@ function univerSheetsOtPort(o) {
3954
4092
  const a = forApply(m);
3955
4093
  applying = true;
3956
4094
  try {
3957
- const ok2 = cs.syncExecuteCommand(a.id, { ...json(a.params), unitId: u }, { fromCollab: true });
3958
- if (ok2 === false) throw new Error(`"${m.id}" was refused by the editor`);
4095
+ const ok3 = cs.syncExecuteCommand(a.id, { ...json(a.params), unitId: u }, { fromCollab: true });
4096
+ if (ok3 === false) throw new Error(`"${m.id}" was refused by the editor`);
3959
4097
  } finally {
3960
4098
  applying = false;
3961
4099
  }
@@ -3971,6 +4109,8 @@ function univerSheetsOtPort(o) {
3971
4109
  group = null;
3972
4110
  applying = true;
3973
4111
  try {
4112
+ const u = unitId();
4113
+ if (u) releaseUnitPluginState(cs, u, o.saveUnit?.(u) ?? null);
3974
4114
  o.load(snapshot);
3975
4115
  } finally {
3976
4116
  applying = false;
@@ -4060,6 +4200,53 @@ function moveSelectionsThrough(selections, m, maxRows, maxCols) {
4060
4200
  return selections.map((s) => ({ ...s, range: box(s.range, s.range.rangeType), ...s.primary ? { primary: box(s.primary) } : {} }));
4061
4201
  }
4062
4202
 
4203
+ // src/univer/collab/offline-text.ts
4204
+ var colName3 = (c) => {
4205
+ let n = c;
4206
+ let s = "";
4207
+ do {
4208
+ s = String.fromCharCode(65 + n % 26) + s;
4209
+ n = Math.floor(n / 26) - 1;
4210
+ } while (n >= 0);
4211
+ return s;
4212
+ };
4213
+ function collectDocText(v, out) {
4214
+ if (Array.isArray(v)) {
4215
+ for (const x of v) collectDocText(x, out);
4216
+ return;
4217
+ }
4218
+ if (!v || typeof v !== "object") return;
4219
+ const o = v;
4220
+ if (typeof o.dataStream === "string" && o.dataStream.length) out.push(o.dataStream);
4221
+ for (const k of Object.keys(o)) if (k !== "dataStream") collectDocText(o[k], out);
4222
+ }
4223
+ function collectCells(cellValue, out) {
4224
+ if (!cellValue || typeof cellValue !== "object") return;
4225
+ for (const [r, cols] of Object.entries(cellValue)) {
4226
+ if (!cols || typeof cols !== "object") continue;
4227
+ for (const [c, cell] of Object.entries(cols)) {
4228
+ const x = cell;
4229
+ const val = x?.f ?? x?.v;
4230
+ if (val !== void 0 && val !== null && val !== "") out.push(`${colName3(Number(c))}${Number(r) + 1}: ${String(val)}`);
4231
+ }
4232
+ }
4233
+ }
4234
+ function offlineTextOfGroups(buffers) {
4235
+ const docs = [];
4236
+ const cells = [];
4237
+ for (const groups of buffers) {
4238
+ for (const g of groups) {
4239
+ for (const m of g.mutations) {
4240
+ const p = m.params;
4241
+ if (p && "cellValue" in p) collectCells(p.cellValue, cells);
4242
+ else collectDocText(p, docs);
4243
+ }
4244
+ }
4245
+ }
4246
+ const text = docs.join("").replace(/\r/g, "\n").replace(/\u0000/g, "");
4247
+ return [text, cells.join("\n")].filter((s) => s.length > 0).join("\n");
4248
+ }
4249
+
4063
4250
  // src/sheets/workbook-ot-room.ts
4064
4251
  var Y3 = __toESM(require("yjs"), 1);
4065
4252
  var import_awareness3 = require("y-protocols/awareness");
@@ -4162,6 +4349,7 @@ async function startWorkbookOtRoom(port, o) {
4162
4349
  await provider.connect();
4163
4350
  publishAwareness();
4164
4351
  const client = db4();
4352
+ const offline = (0, import_collab6.browserOfflineOptions)(`${o.workbookId}:${o.uid}`);
4165
4353
  const room = openSheetsOtRoom({
4166
4354
  port,
4167
4355
  clientId: o.clientId,
@@ -4182,7 +4370,9 @@ async function startWorkbookOtRoom(port, o) {
4182
4370
  replace: ({ snapshot, stateHash, clientId }) => (0, import_collab6.collabReplace)(client, { roomId: o.workbookId, snapshot, stateHash, origin: "restore", clientId }),
4183
4371
  ...o.onNotice ? { onNotice: o.onNotice } : {},
4184
4372
  ...o.onIncident ? { onIncident: o.onIncident } : {},
4185
- ...o.onStatus ? { onStatus: o.onStatus } : {}
4373
+ ...o.onStatus ? { onStatus: o.onStatus } : {},
4374
+ ...offline ? { offline } : {},
4375
+ ...o.onOffline ? { onOffline: o.onOffline } : {}
4186
4376
  });
4187
4377
  await room.session.ready;
4188
4378
  return {