@ai-matrx/office 0.8.21 → 0.8.22

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.
@@ -45,7 +45,7 @@ interface SheetRange {
45
45
  * column width, worksheet name. C5b: formula text in cells (`f`, array `ref`) and defined names. Shared
46
46
  * formulas (`si`) stay barriers (see transform.ts cellBarrier); ranged resources are C5c.
47
47
  */
48
- type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet";
48
+ type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort";
49
49
  interface CoveredEntry {
50
50
  readonly kind: "covered";
51
51
  readonly family: SheetFamily;
@@ -45,7 +45,7 @@ interface SheetRange {
45
45
  * column width, worksheet name. C5b: formula text in cells (`f`, array `ref`) and defined names. Shared
46
46
  * formulas (`si`) stay barriers (see transform.ts cellBarrier); ranged resources are C5c.
47
47
  */
48
- type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet";
48
+ type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort";
49
49
  interface CoveredEntry {
50
50
  readonly kind: "covered";
51
51
  readonly family: SheetFamily;
@@ -32,6 +32,7 @@ var SHEET_MUTATIONS = {
32
32
  "sheet.mutation.insert-sheet": covered("sheet", "index", "sheet"),
33
33
  "sheet.mutation.remove-sheet": covered("sheet", "sheetIndex", "sheetsLeft"),
34
34
  "sheet.mutation.set-worksheet-order": covered("sheet", "fromOrder", "toOrder"),
35
+ "sheet.mutation.reorder-range": covered("sort", "range", "order"),
35
36
  // ── never travels ────────────────────────────────────────────────────────────────────────────────
36
37
  "formula.mutation.set-formula-calculation-start": never(FORMULA_RESULT),
37
38
  "formula.mutation.set-trigger-formula-calculation-start": never(FORMULA_RESULT),
@@ -65,7 +66,6 @@ var SHEET_MUTATIONS = {
65
66
  "thread-comment.mutation.resolve-comment": never(UNIVER_COMMENTS),
66
67
  "thread-comment.mutation.delete-comment": never(UNIVER_COMMENTS),
67
68
  // ── barriers: X (no transform yet, design §10) ───────────────────────────────────────────────────
68
- "sheet.mutation.reorder-range": barrier("X", "sort: a permutation, not transformed yet"),
69
69
  "sheet.mutation.move-range": barrier("X", "cut-paste carries the sender's cell matrices"),
70
70
  "sheet.mutation.set-worksheet-hidden": barrier("X", "sheet-level setting: not in C5a"),
71
71
  "sheet.mutation.set-tab-color": barrier("X", "sheet-level setting: not in C5a"),
@@ -508,7 +508,8 @@ var ID = {
508
508
  colCount: "sheet.mutation.set-worksheet-column-count",
509
509
  insertSheet: "sheet.mutation.insert-sheet",
510
510
  removeSheet: "sheet.mutation.remove-sheet",
511
- sheetOrder: "sheet.mutation.set-worksheet-order"
511
+ sheetOrder: "sheet.mutation.set-worksheet-order",
512
+ sort: "sheet.mutation.reorder-range"
512
513
  };
513
514
  var PAIR_BARRIERS = {};
514
515
  var pairKey = (a, b) => a < b ? `${a}|${b}` : `${b}|${a}`;
@@ -1305,6 +1306,119 @@ function inlineSheetStyles(sheet, styleOf) {
1305
1306
  }
1306
1307
  return out;
1307
1308
  }
1309
+ var isSort = (m) => m.id === ID.sort;
1310
+ function sortOf(m) {
1311
+ const P = /* @__PURE__ */ new Map();
1312
+ for (const [t, src] of Object.entries(m.params.order ?? {})) P.set(Number(t), Number(src));
1313
+ return { range: { ...m.params.range }, P };
1314
+ }
1315
+ var sortQ = (o) => new Map([...o.P].map(([t, s0]) => [s0, t]));
1316
+ function buildSort(template, o) {
1317
+ const order = {};
1318
+ for (const [t, s0] of [...o.P].sort((a, b) => a[0] - b[0])) if (t !== s0) order[t] = s0;
1319
+ if (!Object.keys(order).length || o.range.startRow > o.range.endRow || o.range.startColumn > o.range.endColumn) return [];
1320
+ return [{ id: template.id, params: { ...template.params, range: o.range, order } }];
1321
+ }
1322
+ var inSortCols = (o, c) => c >= o.range.startColumn && c <= o.range.endColumn;
1323
+ function sortThrough(o, st) {
1324
+ const r = o.range;
1325
+ if (st.axis === "col") {
1326
+ if (st.op.kind === "move") {
1327
+ const { from, count, to } = st.op;
1328
+ const touches = !(from + count - 1 < r.startColumn || from > r.endColumn) || to > r.startColumn && to <= r.endColumn;
1329
+ if (touches) return null;
1330
+ const spans3 = spanThrough(st.op, r.startColumn, r.endColumn);
1331
+ return spans3.length === 1 ? { range: { ...r, startColumn: spans3[0][0], endColumn: spans3[0][1] }, P: o.P } : null;
1332
+ }
1333
+ const spans2 = spanThrough(st.op, r.startColumn, r.endColumn);
1334
+ if (!spans2.length) return { range: { ...r, startColumn: 1, endColumn: 0 }, P: /* @__PURE__ */ new Map() };
1335
+ return { range: { ...r, startColumn: spans2[0][0], endColumn: spans2[spans2.length - 1][1] }, P: o.P };
1336
+ }
1337
+ const op = st.op;
1338
+ if (op.kind === "move") {
1339
+ const touches = !(op.from + op.count - 1 < r.startRow || op.from > r.endRow) || op.to > r.startRow && op.to <= r.endRow;
1340
+ if (touches) return null;
1341
+ }
1342
+ if (op.kind === "insert" || op.kind === "move") {
1343
+ const P2 = /* @__PURE__ */ new Map();
1344
+ for (const [t, s0] of o.P) P2.set(mapIndex(op, t), mapIndex(op, s0));
1345
+ const spans2 = spanThrough(op, r.startRow, r.endRow);
1346
+ return { range: { ...r, startRow: spans2[0][0], endRow: spans2[spans2.length - 1][1] }, P: P2 };
1347
+ }
1348
+ const removed = (i) => i >= op.start && i < op.start + op.count;
1349
+ const Q = sortQ(o);
1350
+ const goneTargets = [];
1351
+ for (let i = op.start; i < op.start + op.count; i++) goneTargets.push(Q.get(i) ?? i);
1352
+ goneTargets.sort((a, b) => a - b);
1353
+ const compact = (t) => t - goneTargets.filter((g) => g < t).length;
1354
+ const P = /* @__PURE__ */ new Map();
1355
+ for (const [t, s0] of o.P) if (!removed(s0)) P.set(compact(t), mapIndex(op, s0));
1356
+ const spans = spanThrough(op, r.startRow, r.endRow);
1357
+ if (!spans.length) return { range: { ...r, startRow: 1, endRow: 0 }, P: /* @__PURE__ */ new Map() };
1358
+ return { range: { ...r, startRow: spans[0][0], endRow: spans[spans.length - 1][1] }, P };
1359
+ }
1360
+ function sortPair(x, y, sx, sy) {
1361
+ const xs = isSort(x);
1362
+ const ys = isSort(y);
1363
+ if (!xs && !ys) return null;
1364
+ if (xs && ys) {
1365
+ const a = sortOf(x).range;
1366
+ const b = sortOf(y).range;
1367
+ const overlap = a.startRow <= b.endRow && b.startRow <= a.endRow && a.startColumn <= b.endColumn && b.startColumn <= a.endColumn;
1368
+ return overlap ? barrier2("two sorts of overlapping ranges at once") : ok([x]);
1369
+ }
1370
+ if (xs) {
1371
+ if (sy) {
1372
+ const t = sortThrough(sortOf(x), sy);
1373
+ return t ? ok(buildSort(x, t)) : barrier2("a row or column move through a sorted range");
1374
+ }
1375
+ return ok([x]);
1376
+ }
1377
+ const o = sortOf(y);
1378
+ const Q = sortQ(o);
1379
+ const moved = (r) => r >= o.range.startRow && r <= o.range.endRow && Q.has(r);
1380
+ if (sx) {
1381
+ if (sx.axis === "col") return sx.op.kind === "move" && !sortThrough(o, sx) ? barrier2("a column move through a sorted range") : ok([x]);
1382
+ if (sx.op.kind === "insert") return ok([x]);
1383
+ if (sx.op.kind === "move") return sortThrough(o, sx) ? ok([x]) : barrier2("a row move through a sorted range");
1384
+ const rows = [];
1385
+ let partial = false;
1386
+ for (let i = sx.op.start; i < sx.op.start + sx.op.count; i++) {
1387
+ if (moved(i)) partial = true;
1388
+ rows.push(Q.get(i) ?? i);
1389
+ }
1390
+ if (partial) return barrier2("a row remove against a concurrent sort of those rows");
1391
+ return ok([x]);
1392
+ }
1393
+ if (x.id === ID.values) {
1394
+ const out = {};
1395
+ let changed = false;
1396
+ forEachCell(cellsOf(x), (r, c, v) => {
1397
+ if (inSortCols(o, c) && moved(r)) {
1398
+ putCell(out, Q.get(r), c, v);
1399
+ changed = true;
1400
+ } else putCell(out, r, c, v);
1401
+ });
1402
+ return changed ? ok([cellsMutation(x, out)]) : ok([x]);
1403
+ }
1404
+ if (isNumfmt(x)) {
1405
+ const parts = nfParts(x).map((p) => {
1406
+ const ranges = [];
1407
+ for (const rc of p.ranges) {
1408
+ const inner = { ...rc, startRow: Math.max(rc.startRow, o.range.startRow), endRow: Math.min(rc.endRow, o.range.endRow), startColumn: Math.max(rc.startColumn, o.range.startColumn), endColumn: Math.min(rc.endColumn, o.range.endColumn) };
1409
+ if (inner.startRow > inner.endRow || inner.startColumn > inner.endColumn) {
1410
+ ranges.push(rc);
1411
+ continue;
1412
+ }
1413
+ ranges.push(...rectMinus(rc, inner));
1414
+ for (let r = inner.startRow; r <= inner.endRow; r++) ranges.push({ ...inner, startRow: Q.get(r) ?? r, endRow: Q.get(r) ?? r });
1415
+ }
1416
+ return { ...p, ranges };
1417
+ });
1418
+ return ok(nfBuild(x, parts));
1419
+ }
1420
+ return ok([x]);
1421
+ }
1308
1422
  function familyOf(id) {
1309
1423
  const e = SHEET_MUTATIONS[id];
1310
1424
  return e && e.kind === "covered" ? e.family : "";
@@ -1330,6 +1444,8 @@ function transformMutation(x, y, side) {
1330
1444
  const fy = familyOf(y.id);
1331
1445
  const sy = structuralOf(y);
1332
1446
  const sx = structuralOf(x);
1447
+ const sortp = sortPair(x, y, sx, sy);
1448
+ if (sortp) return sortp;
1333
1449
  const cp = countPair(x, y, sy);
1334
1450
  if (cp) return cp;
1335
1451
  const np = numfmtPair(x, y, side, sx, sy);