@ai-matrx/office 0.8.16 → 0.8.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,10 +1,36 @@
1
1
  # Changelog
2
2
 
3
- ## 0.8.16
3
+ ## 0.8.17
4
4
 
5
5
  UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
6
6
  Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/office/src`.
7
7
 
8
+ ## 0.8.16
9
+
10
+ SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
11
+ so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
12
+ Diff: `git diff 50c68fc222 f8e2208b71 -- apps/shared/office/src`
13
+
14
+ Changed shipped source files (2):
15
+ - `apps/shared/office/src/docs/remote-carets.ts`
16
+ - `apps/shared/office/src/univer/collab/sheets-ot/univer-port.ts`
17
+
18
+ ## 0.8.15
19
+
20
+ SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
21
+ so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
22
+ Diff: `git diff 6d605b00d1 50c68fc222 -- apps/shared/office/src`
23
+
24
+ Changed shipped source files (8):
25
+ - `apps/shared/office/src/collab/sheets/transform/fuzz/seats.ts`
26
+ - `apps/shared/office/src/collab/sheets/transform/fuzz/state-hash.ts`
27
+ - `apps/shared/office/src/sheets/workbook-ot-room.ts`
28
+ - `apps/shared/office/src/univer/collab/index.ts`
29
+ - `apps/shared/office/src/univer/collab/sheets-ot/index.ts`
30
+ - `apps/shared/office/src/univer/collab/sheets-ot/room.ts`
31
+ - `apps/shared/office/src/univer/collab/sheets-ot/state-hash.ts`
32
+ - `apps/shared/office/src/univer/collab/sheets-ot/univer-port.ts`
33
+
8
34
  ## 0.8.14
9
35
 
10
36
  - **`/collab/sheets-transform` covers formulas (C5b; still inert, no consumer).** A formula typed on one seat now has its references rewritten by a concurrent row/column insert, removal or move and by a concurrent sheet rename, in both commit orders, exactly as Univer's own `@univerjs/sheets-formula` interceptor rewrites them: A1 references, ranges, absolute and mixed markers, whole rows and columns, cross-sheet references, references into a removed range (`#REF!`), array formulas (`ref` range moves; dynamic arrays are plain formulas). Defined names (`formula.mutation.set-defined-name` / `remove-defined-name`) are covered: their ranges follow structural edits and renames, a renamed name is renamed inside concurrent formulas, a removed one becomes `#REF!`. A rewrite a structural op carries for formulas that already existed (`derived`) never outranks a person's concurrent write to the same cell or name. Shared formulas (`si`) stay barriers (the failing case is in `sheet-formula-hard-cases.test.ts`). Rewrites match real sheets-formula 1.0.4 on 476 oracle cases (`fixtures/sheets-formula-oracle.json`, made by `spikes/c5b-probe/oracle.mjs`). Pairwise TP1 fuzz: 20 families (210 pairs) at 4,000 seeds each, both orders, 0 divergences, 0 throws. New exports: `annotateFormulas`, `forApply`, `SIDE_CAR_PARAMS`, `rewriteFormula`, `formulaBarrier`, `isFormulaText`, `refSheetsFor`, `refSheetsAfter`, `REF_ERROR` and the `RefChange`/`RefSheets`/`FormulaCtx` types. `CONTENT_KEYS` gains `ref`, `xf`, `ft`, `fd`; `SHEET_TRANSFORMER_VERSION` is `c5b-1`. `@univerjs/engine-formula` moves from devDependencies to dependencies (the lexer runs in shipped code). Consumer action: none (nothing imports this section yet). For C6: capture must call `annotateFormulas` on each group (sheet id → name, defined-name id → name, read before the command) and apply through `forApply`; the canonical sheet hash must sort the defined-names resource by id.
@@ -17,6 +43,8 @@ Check the package's gitHead on npm against this version's gitHead: `git diff <pr
17
43
 
18
44
  ### Unreleased
19
45
 
46
+ - **Sheets co-editing on the ordered log (C6).** `@ai-matrx/office/univer/collab` adds the Sheets room: `openSheetsOtRoom` (the C2 session over the C5a/C5b group transform, saves at a quiet point with a matching hash, restore through `collab_replace`, undo items rebased over every remote op), `univerSheetsOtPort` (capture: onlyLocal/fromCollab filtered, grouped by outermost command with a try/finally depth guard on both execute paths, params allowlist, completeCellContent, exact merge removals, style objects never ids, whole-style overrides restated as merges, annotateFormulas, inverses from the applied params against a pre-state copy; a barrier or unknown id is `not_shared` and rolls the seat back), `sheetsStateHash` / `canonicalSheet` (merges as a set, defined names by id; the transform fuzz now hashes through it), and `startWorkbookOtRoom` / `workbookUsesOrderedRoom` (the `udt_workbook_snapshots` store, the C1 doors, presence). A remote row/column insert, remove or move carries this seat's selection along and never leaves it past the sheet's edge (the port's `selections` option; a stale whole-row selection after a peer's column delete crashed the editor in the live run). Flip is per room exactly like Docs. Consumer action: matrx-frontend's WorkbookEditor opens it when the workbook's room exists or `collab.ot_rooms` says so (shipped with this release); every other consumer: none.
47
+
20
48
  - **`Workbook` and `DocumentRow` carry `test_expires_at` / `test_run_id`** — the `workbench.udt_workbooks` / `udt_documents` rows gained these test-fixture columns; the hand-written types now match the generated row again (matrx-frontend `features/data-tables/office-types-agree.ts`). Consumer action: none (a literal building one of these rows must add the two fields, `null` for real records).
21
49
 
22
50
  ## 0.8.13
@@ -57,6 +57,7 @@ __export(collab_exports, {
57
57
  invertDocsOp: () => invertDocsOp,
58
58
  isCellEditorScratch: () => isCellEditorScratch,
59
59
  isNoopDocsOp: () => isNoopDocsOp,
60
+ moveSelectionsThrough: () => moveSelectionsThrough,
60
61
  normalizeDocsOp: () => normalizeDocsOp,
61
62
  openDocsOtRoom: () => openDocsOtRoom,
62
63
  openSheetsOtRoom: () => openSheetsOtRoom,
@@ -3303,12 +3304,30 @@ function univerSheetsOtPort(o) {
3303
3304
  }
3304
3305
  if (lone && tracker.stack.length === 0) settle();
3305
3306
  });
3307
+ const followSelection = (m) => {
3308
+ const sel = o.selections;
3309
+ if (!sel || !axisOpOf(m)) return;
3310
+ try {
3311
+ const sheet = String(m.params.subUnitId ?? "");
3312
+ if (sel.sheetId() !== sheet) return;
3313
+ const ws = o.workbook()?.getSheetBySheetId(sheet);
3314
+ const current = sel.get();
3315
+ if (!ws || !current?.length) return;
3316
+ const rows = ws.getMaxRows?.() ?? Number.MAX_SAFE_INTEGER;
3317
+ const cols = ws.getMaxColumns?.() ?? Number.MAX_SAFE_INTEGER;
3318
+ sel.set(moveSelectionsThrough(json(current), m, rows, cols));
3319
+ } catch (err) {
3320
+ console.warn("[sheets-ot] could not move this seat's selection past a collaborator's row or column change", err);
3321
+ }
3322
+ };
3306
3323
  return {
3307
3324
  onLocal(listener) {
3308
3325
  listeners.add(listener);
3309
3326
  return () => void listeners.delete(listener);
3310
3327
  },
3311
3328
  busy: () => tracker.stack.length > 0 || group !== null,
3329
+ /** The outermost commands still running here (why the port is busy), for logs. */
3330
+ running: () => [...tracker.stack, ...group && tracker.stack.length === 0 ? ["(group)"] : []],
3312
3331
  whenIdle(fn) {
3313
3332
  if (tracker.stack.length === 0 && !group) fn();
3314
3333
  else idle.push(fn);
@@ -3324,6 +3343,7 @@ function univerSheetsOtPort(o) {
3324
3343
  } finally {
3325
3344
  applying = false;
3326
3345
  }
3346
+ followSelection(m);
3327
3347
  },
3328
3348
  snapshot() {
3329
3349
  const wb = o.workbook();
@@ -3361,6 +3381,68 @@ function fullContent(cell) {
3361
3381
  if (out.v === null) delete out.t;
3362
3382
  return out;
3363
3383
  }
3384
+ function axisOpOf(m) {
3385
+ const p = m.params;
3386
+ const span = (r, axis) => axis === "row" ? [r.startRow, r.endRow - r.startRow + 1] : [r.startColumn, r.endColumn - r.startColumn + 1];
3387
+ switch (m.id) {
3388
+ case "sheet.mutation.insert-row": {
3389
+ const [at, count] = span(p.range, "row");
3390
+ return { axis: "row", op: { kind: "insert", at, count } };
3391
+ }
3392
+ case "sheet.mutation.insert-col": {
3393
+ const [at, count] = span(p.range, "col");
3394
+ return { axis: "col", op: { kind: "insert", at, count } };
3395
+ }
3396
+ case "sheet.mutation.remove-rows": {
3397
+ const [start, count] = span(p.range, "row");
3398
+ return { axis: "row", op: { kind: "remove", start, count } };
3399
+ }
3400
+ case "sheet.mutation.remove-col": {
3401
+ const [start, count] = span(p.range, "col");
3402
+ return { axis: "col", op: { kind: "remove", start, count } };
3403
+ }
3404
+ case "sheet.mutation.move-rows": {
3405
+ const [from, count] = span(p.sourceRange, "row");
3406
+ return { axis: "row", op: { kind: "move", from, count, to: p.targetRange.startRow } };
3407
+ }
3408
+ case "sheet.mutation.move-columns": {
3409
+ const [from, count] = span(p.sourceRange, "col");
3410
+ return { axis: "col", op: { kind: "move", from, count, to: p.targetRange.startColumn } };
3411
+ }
3412
+ default:
3413
+ return null;
3414
+ }
3415
+ }
3416
+ function moveSelectionsThrough(selections, m, maxRows, maxCols) {
3417
+ const a = axisOpOf(m);
3418
+ const clamp = (v, max) => Math.max(0, Math.min(v, Math.max(0, max - 1)));
3419
+ const through = (i, axis) => {
3420
+ if (typeof i !== "number") return i;
3421
+ let next = i;
3422
+ if (a && a.axis === axis) {
3423
+ const mapped = mapIndex(a.op, i);
3424
+ next = mapped ?? (a.op.kind === "remove" ? a.op.start : i);
3425
+ }
3426
+ return clamp(next, axis === "row" ? maxRows : maxCols);
3427
+ };
3428
+ const box = (r, rangeType) => {
3429
+ const out = { ...r };
3430
+ for (const k of ["startRow", "endRow", "actualRow"]) if (k in out) out[k] = through(out[k], "row");
3431
+ for (const k of ["startColumn", "endColumn", "actualColumn"]) if (k in out) out[k] = through(out[k], "col");
3432
+ if (typeof out.startRow === "number" && typeof out.endRow === "number" && out.endRow < out.startRow) out.endRow = out.startRow;
3433
+ if (typeof out.startColumn === "number" && typeof out.endColumn === "number" && out.endColumn < out.startColumn) out.endColumn = out.startColumn;
3434
+ if (rangeType === 1 || rangeType === 3) {
3435
+ out.startColumn = 0;
3436
+ out.endColumn = Math.max(0, maxCols - 1);
3437
+ }
3438
+ if (rangeType === 2 || rangeType === 3) {
3439
+ out.startRow = 0;
3440
+ out.endRow = Math.max(0, maxRows - 1);
3441
+ }
3442
+ return out;
3443
+ };
3444
+ return selections.map((s) => ({ ...s, range: box(s.range, s.range.rangeType), ...s.primary ? { primary: box(s.primary) } : {} }));
3445
+ }
3364
3446
 
3365
3447
  // src/sheets/workbook-ot-room.ts
3366
3448
  var Y3 = __toESM(require("yjs"), 1);