@ai-matrx/office 0.8.26 → 0.8.27
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 +29 -0
- package/dist/collab-sheets-transform.cjs +215 -14
- package/dist/collab-sheets-transform.cjs.map +1 -1
- package/dist/collab-sheets-transform.d.cts +7 -2
- package/dist/collab-sheets-transform.d.ts +7 -2
- package/dist/collab-sheets-transform.js +215 -14
- package/dist/collab-sheets-transform.js.map +1 -1
- package/dist/docs.cjs +35 -1
- package/dist/docs.cjs.map +1 -1
- package/dist/docs.d.cts +16 -2
- package/dist/docs.d.ts +16 -2
- package/dist/docs.js +34 -0
- package/dist/docs.js.map +1 -1
- package/dist/sheets-comment-anchors.cjs +44 -3
- package/dist/sheets-comment-anchors.cjs.map +1 -1
- package/dist/sheets-comment-anchors.js +42 -1
- package/dist/sheets-comment-anchors.js.map +1 -1
- package/dist/univer-collab.cjs +315 -37
- package/dist/univer-collab.cjs.map +1 -1
- package/dist/univer-collab.d.cts +9 -5
- package/dist/univer-collab.d.ts +9 -5
- package/dist/univer-collab.js +300 -18
- package/dist/univer-collab.js.map +1 -1
- package/package.json +2 -2
|
@@ -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" | "sort" | "anchor";
|
|
48
|
+
type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort" | "anchor" | "cf" | "dv" | "filter";
|
|
49
49
|
interface CoveredEntry {
|
|
50
50
|
readonly kind: "covered";
|
|
51
51
|
readonly family: SheetFamily;
|
|
@@ -103,7 +103,7 @@ declare function mapIndex(op: AxisOp, i: number): number | null;
|
|
|
103
103
|
*/
|
|
104
104
|
declare function transformAxis(x: AxisOp, y: AxisOp, side: Side): AxisOp[] | null;
|
|
105
105
|
|
|
106
|
-
declare const SHEET_TRANSFORMER_VERSION = "
|
|
106
|
+
declare const SHEET_TRANSFORMER_VERSION = "c5d-1";
|
|
107
107
|
/**
|
|
108
108
|
* Pairs the fuzz proved divergent (or that have no transform yet), as unordered mutation-id pairs, with the
|
|
109
109
|
* failing seed. Each returns a Barrier until it has its own correct transform under a new proto.
|
|
@@ -208,6 +208,11 @@ type RefChange = {
|
|
|
208
208
|
readonly kind: "rename";
|
|
209
209
|
readonly sheet: string;
|
|
210
210
|
readonly name: string;
|
|
211
|
+
}
|
|
212
|
+
/** C5d: the sheet was removed; every reference that names it becomes #REF! (Excel's rule). */
|
|
213
|
+
| {
|
|
214
|
+
readonly kind: "remove-sheet";
|
|
215
|
+
readonly sheet: string;
|
|
211
216
|
} | {
|
|
212
217
|
readonly kind: "defined-name";
|
|
213
218
|
readonly from: string;
|
|
@@ -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" | "sort" | "anchor";
|
|
48
|
+
type SheetFamily = "cell" | "structure" | "merge" | "size" | "name" | "defname" | "numfmt" | "count" | "sheet" | "sort" | "anchor" | "cf" | "dv" | "filter";
|
|
49
49
|
interface CoveredEntry {
|
|
50
50
|
readonly kind: "covered";
|
|
51
51
|
readonly family: SheetFamily;
|
|
@@ -103,7 +103,7 @@ declare function mapIndex(op: AxisOp, i: number): number | null;
|
|
|
103
103
|
*/
|
|
104
104
|
declare function transformAxis(x: AxisOp, y: AxisOp, side: Side): AxisOp[] | null;
|
|
105
105
|
|
|
106
|
-
declare const SHEET_TRANSFORMER_VERSION = "
|
|
106
|
+
declare const SHEET_TRANSFORMER_VERSION = "c5d-1";
|
|
107
107
|
/**
|
|
108
108
|
* Pairs the fuzz proved divergent (or that have no transform yet), as unordered mutation-id pairs, with the
|
|
109
109
|
* failing seed. Each returns a Barrier until it has its own correct transform under a new proto.
|
|
@@ -208,6 +208,11 @@ type RefChange = {
|
|
|
208
208
|
readonly kind: "rename";
|
|
209
209
|
readonly sheet: string;
|
|
210
210
|
readonly name: string;
|
|
211
|
+
}
|
|
212
|
+
/** C5d: the sheet was removed; every reference that names it becomes #REF! (Excel's rule). */
|
|
213
|
+
| {
|
|
214
|
+
readonly kind: "remove-sheet";
|
|
215
|
+
readonly sheet: string;
|
|
211
216
|
} | {
|
|
212
217
|
readonly kind: "defined-name";
|
|
213
218
|
readonly from: string;
|
|
@@ -101,16 +101,17 @@ var SHEET_MUTATIONS = {
|
|
|
101
101
|
"formula.mutation.remove-super-table": barrier("C5c", "table names in structured references belong to tables (C5c)"),
|
|
102
102
|
"formula.mutation.set-super-table-option": barrier("C5c", "table names in structured references belong to tables (C5c)"),
|
|
103
103
|
// ── barriers until C5c (ranged resources) ────────────────────────────────────────────────────────
|
|
104
|
-
|
|
105
|
-
"sheet.mutation.
|
|
106
|
-
"sheet.mutation.
|
|
104
|
+
// ── covered (C5d): ranged resources, transformed by ranged-resources.ts ──
|
|
105
|
+
"sheet.mutation.add-conditional-rule": covered("cf", "rule", "derived"),
|
|
106
|
+
"sheet.mutation.set-conditional-rule": covered("cf", "cfId", "rule", "derived"),
|
|
107
|
+
"sheet.mutation.delete-conditional-rule": covered("cf", "cfId", "derived"),
|
|
107
108
|
"sheet.mutation.move-conditional-rule": barrier("C5c", "conditional-format priority (ordered list)"),
|
|
108
|
-
"data-validation.mutation.addRule":
|
|
109
|
-
"data-validation.mutation.updateRule":
|
|
110
|
-
"data-validation.mutation.removeRule":
|
|
111
|
-
"sheet.mutation.set-filter-range":
|
|
112
|
-
"sheet.mutation.set-filter-criteria":
|
|
113
|
-
"sheet.mutation.remove-filter":
|
|
109
|
+
"data-validation.mutation.addRule": covered("dv", "rule", "index", "source", "derived"),
|
|
110
|
+
"data-validation.mutation.updateRule": covered("dv", "ruleId", "payload", "source", "derived"),
|
|
111
|
+
"data-validation.mutation.removeRule": covered("dv", "ruleId", "source", "derived"),
|
|
112
|
+
"sheet.mutation.set-filter-range": covered("filter", "range", "derived"),
|
|
113
|
+
"sheet.mutation.set-filter-criteria": covered("filter", "col", "criteria", "reCalc", "derived"),
|
|
114
|
+
"sheet.mutation.remove-filter": covered("filter", "derived"),
|
|
114
115
|
"sheet.mutation.add-table": barrier("C5c", RESOURCE),
|
|
115
116
|
"sheet.mutation.delete-table": barrier("C5c", RESOURCE),
|
|
116
117
|
"sheet.mutation.set-sheet-table": barrier("C5c", RESOURCE),
|
|
@@ -452,6 +453,9 @@ function rewriteFormula(text, ctx, change) {
|
|
|
452
453
|
if (change.kind === "rename") {
|
|
453
454
|
if (!sheetName) continue;
|
|
454
455
|
token = serializeRangeToRefString({ range, sheetName: change.name, unitId });
|
|
456
|
+
} else if (change.kind === "remove-sheet") {
|
|
457
|
+
if (!sheetName) continue;
|
|
458
|
+
token = REF_ERROR;
|
|
455
459
|
} else {
|
|
456
460
|
const moved = moveRange(Rectangle.moveOffset(range, 0, 0), change.axis, change.op);
|
|
457
461
|
if (moved === void 0) continue;
|
|
@@ -470,6 +474,10 @@ function rewriteFormula(text, ctx, change) {
|
|
|
470
474
|
return { text: out, changed: out !== text };
|
|
471
475
|
}
|
|
472
476
|
function refSheetsAfter(refSheets, change) {
|
|
477
|
+
if (change.kind === "remove-sheet" && refSheets) {
|
|
478
|
+
if (!Object.values(refSheets).includes(change.sheet)) return refSheets;
|
|
479
|
+
return Object.fromEntries(Object.entries(refSheets).map(([n, id]) => [n, id === change.sheet ? null : id]));
|
|
480
|
+
}
|
|
473
481
|
if (change.kind !== "rename" || !refSheets) return refSheets;
|
|
474
482
|
const entries = Object.entries(refSheets);
|
|
475
483
|
if (!entries.some(([name, id]) => id === change.sheet || name === change.name)) return refSheets;
|
|
@@ -553,8 +561,111 @@ function transformCommentAnchor(x, y, side) {
|
|
|
553
561
|
return ok([moved === cell ? x : { id: x.id, params: { ...x.params, cell: moved } }]);
|
|
554
562
|
}
|
|
555
563
|
|
|
564
|
+
// src/collab/sheets/transform/ranged-resources.ts
|
|
565
|
+
var specs = /* @__PURE__ */ new Map();
|
|
566
|
+
var byId = /* @__PURE__ */ new Map();
|
|
567
|
+
function registerRangedResource(spec) {
|
|
568
|
+
specs.set(spec.family, spec);
|
|
569
|
+
for (const id of Object.keys(spec.ids)) byId.set(id, spec);
|
|
570
|
+
}
|
|
571
|
+
var rangedSpecOf = (id) => byId.get(id);
|
|
572
|
+
var cfRule = (m) => m.params.rule ?? {};
|
|
573
|
+
var CF_FORMULA = (r) => {
|
|
574
|
+
const rule = r.rule ?? {};
|
|
575
|
+
if (rule.type === "highlightCell" && rule.subType === "formula") return true;
|
|
576
|
+
return JSON.stringify(rule).includes('"type":"formula"');
|
|
577
|
+
};
|
|
578
|
+
registerRangedResource({
|
|
579
|
+
family: "cf",
|
|
580
|
+
ids: { "sheet.mutation.add-conditional-rule": "add", "sheet.mutation.set-conditional-rule": "set", "sheet.mutation.delete-conditional-rule": "remove" },
|
|
581
|
+
keys: (m) => [String(m.id === "sheet.mutation.add-conditional-rule" ? cfRule(m).cfId : m.params.cfId)],
|
|
582
|
+
rects: (m) => cfRule(m).ranges ?? null,
|
|
583
|
+
withRects: (m, rects) => ({ id: m.id, params: { ...m.params, rule: { ...cfRule(m), ranges: rects } } }),
|
|
584
|
+
setFor: (m, rects) => ({
|
|
585
|
+
id: "sheet.mutation.set-conditional-rule",
|
|
586
|
+
params: { subUnitId: m.params.subUnitId, cfId: cfRule(m).cfId ?? m.params.cfId, rule: { ...cfRule(m), ranges: rects }, derived: true }
|
|
587
|
+
}),
|
|
588
|
+
removeOf: (sheet, key) => ({ id: "sheet.mutation.delete-conditional-rule", params: { subUnitId: sheet, cfId: key, derived: true } }),
|
|
589
|
+
hasFormula: (m) => CF_FORMULA(cfRule(m)),
|
|
590
|
+
orderedAdds: true
|
|
591
|
+
});
|
|
592
|
+
var DV = { add: "data-validation.mutation.addRule", update: "data-validation.mutation.updateRule", remove: "data-validation.mutation.removeRule" };
|
|
593
|
+
var DV_RANGE = 1;
|
|
594
|
+
var DV_FACETS = { 0: "setting", 1: "range", 2: "options", 3: "all" };
|
|
595
|
+
var dvPayload = (m) => m.params.payload ?? {};
|
|
596
|
+
var dvFormula = (o) => !!o && [o.formula1, o.formula2].some((f) => typeof f === "string" && f.trim().startsWith("="));
|
|
597
|
+
registerRangedResource({
|
|
598
|
+
family: "dv",
|
|
599
|
+
ids: { [DV.add]: "add", [DV.update]: "set", [DV.remove]: "remove" },
|
|
600
|
+
keys: (m) => {
|
|
601
|
+
if (m.id === DV.add) return [String((m.params.rule ?? {}).uid)];
|
|
602
|
+
const id = m.params.ruleId;
|
|
603
|
+
return Array.isArray(id) ? id.map(String) : [String(id)];
|
|
604
|
+
},
|
|
605
|
+
facet: (m) => m.id === DV.update ? DV_FACETS[Number(dvPayload(m).type)] ?? "all" : "all",
|
|
606
|
+
rects: (m) => {
|
|
607
|
+
if (m.id === DV.add) return m.params.rule?.ranges ?? null;
|
|
608
|
+
if (m.id === DV.update && dvPayload(m).type === DV_RANGE) return dvPayload(m).payload ?? null;
|
|
609
|
+
if (m.id === DV.update && dvPayload(m).type === 3) return (dvPayload(m).payload ?? {}).ranges ?? null;
|
|
610
|
+
return null;
|
|
611
|
+
},
|
|
612
|
+
withRects: (m, rects) => {
|
|
613
|
+
if (m.id === DV.add) return { id: m.id, params: { ...m.params, rule: { ...m.params.rule, ranges: rects } } };
|
|
614
|
+
const p = dvPayload(m);
|
|
615
|
+
return { id: m.id, params: { ...m.params, payload: p.type === DV_RANGE ? { ...p, payload: rects } : { ...p, payload: { ...p.payload, ranges: rects } } } };
|
|
616
|
+
},
|
|
617
|
+
setFor: (m, rects) => ({
|
|
618
|
+
id: DV.update,
|
|
619
|
+
params: { subUnitId: m.params.subUnitId, ruleId: m.id === DV.add ? (m.params.rule ?? {}).uid : m.params.ruleId, payload: { type: DV_RANGE, payload: rects }, derived: true }
|
|
620
|
+
}),
|
|
621
|
+
removeOf: (sheet, key) => ({ id: DV.remove, params: { subUnitId: sheet, ruleId: key, derived: true } }),
|
|
622
|
+
withoutKeys: (m, keys) => {
|
|
623
|
+
const left = (Array.isArray(m.params.ruleId) ? m.params.ruleId : [m.params.ruleId]).filter((k) => !keys.includes(String(k)));
|
|
624
|
+
return left.length ? { id: m.id, params: { ...m.params, ruleId: Array.isArray(m.params.ruleId) ? left : left[0] } } : null;
|
|
625
|
+
},
|
|
626
|
+
hasFormula: (m) => {
|
|
627
|
+
if (m.id === DV.add) return dvFormula(m.params.rule);
|
|
628
|
+
const p = dvPayload(m);
|
|
629
|
+
return p.type === 0 || p.type === 3 ? dvFormula(p.payload) : false;
|
|
630
|
+
},
|
|
631
|
+
orderedAdds: true,
|
|
632
|
+
// an ALL update (the ref-range handler restates the whole rule) losing to a setting/options change keeps its ranges
|
|
633
|
+
narrow: (m, lost) => {
|
|
634
|
+
if (m.id !== DV.update || dvPayload(m).type !== 3 || lost === "range") return null;
|
|
635
|
+
const ranges = (dvPayload(m).payload ?? {}).ranges;
|
|
636
|
+
return Array.isArray(ranges) ? { id: m.id, params: { ...m.params, payload: { type: DV_RANGE, payload: ranges } } } : null;
|
|
637
|
+
}
|
|
638
|
+
});
|
|
639
|
+
var FILTER = { range: "sheet.mutation.set-filter-range", criteria: "sheet.mutation.set-filter-criteria", remove: "sheet.mutation.remove-filter" };
|
|
640
|
+
var hull = (rects) => ({
|
|
641
|
+
startRow: Math.min(...rects.map((r) => r.startRow)),
|
|
642
|
+
endRow: Math.max(...rects.map((r) => r.endRow)),
|
|
643
|
+
startColumn: Math.min(...rects.map((r) => r.startColumn)),
|
|
644
|
+
endColumn: Math.max(...rects.map((r) => r.endColumn))
|
|
645
|
+
});
|
|
646
|
+
var filterWith = (m, rects) => m.id === FILTER.range ? { id: m.id, params: { ...m.params, range: hull(rects) } } : { id: m.id, params: { ...m.params, col: rects[0].startColumn } };
|
|
647
|
+
var colRect = (col) => ({ startRow: 0, endRow: 1e9, startColumn: col, endColumn: col });
|
|
648
|
+
registerRangedResource({
|
|
649
|
+
family: "filter",
|
|
650
|
+
ids: { [FILTER.range]: "set", [FILTER.criteria]: "set", [FILTER.remove]: "remove" },
|
|
651
|
+
keys: () => ["filter"],
|
|
652
|
+
facet: (m) => m.id === FILTER.criteria ? `col:${String(m.params.col)}` : "range",
|
|
653
|
+
rects: (m) => m.id === FILTER.range ? [m.params.range] : m.id === FILTER.criteria ? [colRect(Number(m.params.col))] : null,
|
|
654
|
+
withRects: (m, rects) => filterWith(m, rects),
|
|
655
|
+
setFor: (m, rects) => {
|
|
656
|
+
const f = filterWith(m, rects);
|
|
657
|
+
return { id: f.id, params: { ...f.params, derived: true } };
|
|
658
|
+
},
|
|
659
|
+
removeOf: (sheet) => ({ id: FILTER.remove, params: { subUnitId: sheet, derived: true } }),
|
|
660
|
+
/** a criteria column that was removed takes only its criteria with it, never the filter */
|
|
661
|
+
emptyDrops: (m) => m.id === FILTER.criteria,
|
|
662
|
+
// a column move can carry a criteria column out of the filter's range (the model refuses it): not yet
|
|
663
|
+
// where a criteria column lands depends on how the filter's own range moved (Univer's rule at its edges): not yet
|
|
664
|
+
barrierOver: (m, axis) => m.id === FILTER.criteria && axis === "col" ? "filter: a column's criteria against a column insert, remove or move" : null
|
|
665
|
+
});
|
|
666
|
+
|
|
556
667
|
// src/collab/sheets/transform/transform.ts
|
|
557
|
-
var SHEET_TRANSFORMER_VERSION = "
|
|
668
|
+
var SHEET_TRANSFORMER_VERSION = "c5d-1";
|
|
558
669
|
var ID = {
|
|
559
670
|
values: "sheet.mutation.set-range-values",
|
|
560
671
|
insertRow: "sheet.mutation.insert-row",
|
|
@@ -1329,19 +1440,44 @@ function sheetPair(x, y, side) {
|
|
|
1329
1440
|
if (ys) {
|
|
1330
1441
|
if (y.id !== ID.removeSheet) return ok2([x]);
|
|
1331
1442
|
const gone2 = sheetOf(y);
|
|
1332
|
-
if (namesSheet(x, gone2)) return barrier2("a formula names a sheet removed at the same time");
|
|
1333
1443
|
if (sheetOf(x) === gone2 && x.id !== ID.setName && x.id !== ID.removeName)
|
|
1334
1444
|
return ok2([], [], isDerived(x) ? [] : [`${gone2}: the sheet was removed`]);
|
|
1445
|
+
if (namesSheet(x, gone2)) {
|
|
1446
|
+
const ch = { kind: "remove-sheet", sheet: gone2 };
|
|
1447
|
+
if (x.id === ID.values) return cellsOverChange(x, ch);
|
|
1448
|
+
const r = definedNameThrough(x, ch);
|
|
1449
|
+
return typeof r === "string" ? barrier2(r) : ok2([r.op]);
|
|
1450
|
+
}
|
|
1335
1451
|
return ok2([x]);
|
|
1336
1452
|
}
|
|
1337
1453
|
if (x.id !== ID.removeSheet) return ok2([x]);
|
|
1338
1454
|
const gone = sheetOf(x);
|
|
1339
|
-
|
|
1340
|
-
|
|
1455
|
+
const ry = rangedSpecOf(y.id);
|
|
1456
|
+
if (ry && sheetOf(y) === gone && ry.ids[y.id] !== "remove")
|
|
1457
|
+
return ok2([...ry.keys(y).map((k) => ({ id: ry.removeOf(gone, k).id, params: { ...ry.removeOf(gone, k).params } })), x]);
|
|
1458
|
+
const lost = sheetOf(y) === gone && !isDerived(y) && y.id !== ID.setName && y.id !== ID.removeName ? [`${gone}: the sheet was removed`] : [];
|
|
1459
|
+
if (sheetOf(y) !== gone && namesSheet(y, gone)) {
|
|
1460
|
+
const ch = { kind: "remove-sheet", sheet: gone };
|
|
1461
|
+
if (y.id === ID.values) {
|
|
1462
|
+
const add = rewritesOf(y, ch);
|
|
1463
|
+
if (typeof add === "string") return barrier2(add);
|
|
1464
|
+
return ok2(add ? [x, add] : [x], lost);
|
|
1465
|
+
}
|
|
1466
|
+
const r = definedNameThrough(y, ch);
|
|
1467
|
+
if (typeof r === "string") return barrier2(r);
|
|
1468
|
+
return ok2(r.changed ? [x, asDerived(r.op)] : [x], lost);
|
|
1469
|
+
}
|
|
1470
|
+
return ok2([x], lost);
|
|
1341
1471
|
}
|
|
1342
1472
|
function annotateSheetOps(group, sheetOrder) {
|
|
1473
|
+
return cleanupsBeforeSheetRemoval(annotateSheetOpsInOrder(group, sheetOrder));
|
|
1474
|
+
}
|
|
1475
|
+
function annotateSheetOpsInOrder(group, sheetOrder) {
|
|
1343
1476
|
const order = [...sheetOrder];
|
|
1344
|
-
|
|
1477
|
+
let structural = false;
|
|
1478
|
+
return group.map((m0) => {
|
|
1479
|
+
if (structuralOf(m0)) structural = true;
|
|
1480
|
+
const m = structural && rangedSpecOf(m0.id) && !isDerived(m0) ? { id: m0.id, params: { ...m0.params, derived: true } } : m0;
|
|
1345
1481
|
if (m.id === ID.insertSheet) {
|
|
1346
1482
|
const index = typeof m.params.index === "number" ? Math.min(m.params.index, order.length) : order.length;
|
|
1347
1483
|
order.splice(index, 0, sheetIdOf(m));
|
|
@@ -1360,6 +1496,16 @@ function annotateSheetOps(group, sheetOrder) {
|
|
|
1360
1496
|
return m;
|
|
1361
1497
|
});
|
|
1362
1498
|
}
|
|
1499
|
+
function cleanupsBeforeSheetRemoval(group) {
|
|
1500
|
+
const at = group.findIndex((m) => m.id === ID.removeSheet);
|
|
1501
|
+
if (at < 0) return group;
|
|
1502
|
+
const gone = sheetOf(group[at]);
|
|
1503
|
+
const moved = group.filter((m, k2) => k2 > at && rangedSpecOf(m.id) && sheetOf(m) === gone);
|
|
1504
|
+
if (!moved.length) return group;
|
|
1505
|
+
const rest = group.filter((m) => !moved.includes(m));
|
|
1506
|
+
const k = rest.indexOf(group[at]);
|
|
1507
|
+
return [...rest.slice(0, k), ...moved, ...rest.slice(k)];
|
|
1508
|
+
}
|
|
1363
1509
|
function inlineSheetStyles(sheet, styleOf) {
|
|
1364
1510
|
const out = JSON.parse(JSON.stringify(sheet));
|
|
1365
1511
|
const fix = (o) => {
|
|
@@ -1489,6 +1635,59 @@ function sortPair(x, y, sx, sy) {
|
|
|
1489
1635
|
}
|
|
1490
1636
|
return ok2([x]);
|
|
1491
1637
|
}
|
|
1638
|
+
function rangedPair(x, y, side, sx, sy) {
|
|
1639
|
+
const px = rangedSpecOf(x.id);
|
|
1640
|
+
const py = rangedSpecOf(y.id);
|
|
1641
|
+
if (!px && !py) return null;
|
|
1642
|
+
const told = (m, what) => isDerived(m) ? [] : [`${sheetOf(m)}: ${what}`];
|
|
1643
|
+
if (px && sy) {
|
|
1644
|
+
const role = px.ids[x.id];
|
|
1645
|
+
const rects = role === "remove" ? null : px.rects(x);
|
|
1646
|
+
if (!rects) return ok2([x]);
|
|
1647
|
+
const why = px.barrierOver?.(x, sy.axis, sy.op.kind);
|
|
1648
|
+
if (why) return barrier2(why);
|
|
1649
|
+
if (px.hasFormula?.(x)) return barrier2(`${px.family}: a rule with formula text against a row or column change (its formulas do not move yet)`);
|
|
1650
|
+
const moved = rectsThrough(sy, rects);
|
|
1651
|
+
if (moved.length) return ok2([px.withRects(x, moved)]);
|
|
1652
|
+
if (role === "add" || px.emptyDrops?.(x)) return ok2([], [], told(x, `${px.family} ${px.keys(x).join(",")}: its cells were removed`));
|
|
1653
|
+
return ok2(px.keys(x).map((k) => px.removeOf(sheetOf(x), k)), [], told(x, `${px.family} ${px.keys(x).join(",")}: its cells were removed`));
|
|
1654
|
+
}
|
|
1655
|
+
if (py && sx) {
|
|
1656
|
+
const role = py.ids[y.id];
|
|
1657
|
+
const rects = role === "remove" ? null : py.rects(y);
|
|
1658
|
+
if (!rects) return ok2([x]);
|
|
1659
|
+
const why = py.barrierOver?.(y, sx.axis, sx.op.kind);
|
|
1660
|
+
if (why) return barrier2(why);
|
|
1661
|
+
if (py.hasFormula?.(y)) return barrier2(`${py.family}: a rule with formula text against a row or column change (its formulas do not move yet)`);
|
|
1662
|
+
const moved = rectsThrough(sx, rects);
|
|
1663
|
+
if (!moved.length && py.emptyDrops?.(y)) return ok2([x], told(y, `${py.family} ${py.keys(y).join(",")}: its cells were removed`));
|
|
1664
|
+
return ok2([x, ...moved.length ? [py.setFor(y, moved)] : py.keys(y).map((k) => py.removeOf(sheetOf(y), k))], moved.length ? [] : told(y, `${py.family} ${py.keys(y).join(",")}: its cells were removed`));
|
|
1665
|
+
}
|
|
1666
|
+
if (!px || !py || px !== py) return ok2([x]);
|
|
1667
|
+
const rx = px.ids[x.id];
|
|
1668
|
+
const ry = py.ids[y.id];
|
|
1669
|
+
const ky = py.keys(y);
|
|
1670
|
+
const common = px.keys(x).filter((k) => ky.includes(k));
|
|
1671
|
+
if (!common.length) {
|
|
1672
|
+
if (rx === "add" && ry === "add" && px.orderedAdds) return barrier2(`${px.family}: two added to one sheet at once (their order is state)`);
|
|
1673
|
+
return ok2([x]);
|
|
1674
|
+
}
|
|
1675
|
+
if (rx === "remove") {
|
|
1676
|
+
if (ry !== "remove") return ok2([x]);
|
|
1677
|
+
const rest = px.withoutKeys ? px.withoutKeys(x, common) : null;
|
|
1678
|
+
return ok2(rest ? [rest] : []);
|
|
1679
|
+
}
|
|
1680
|
+
if (ry === "remove") return ok2([], [], told(x, `${px.family} ${common.join(",")}: removed at the same time`));
|
|
1681
|
+
const fx = px.facet?.(x) ?? "all";
|
|
1682
|
+
const fy = py.facet?.(y) ?? "all";
|
|
1683
|
+
if (fx !== fy && fx !== "all" && fy !== "all") return ok2([x]);
|
|
1684
|
+
const dx = isDerived(x);
|
|
1685
|
+
const dy = isDerived(y);
|
|
1686
|
+
const xWins = dx !== dy ? !dx : side === "left";
|
|
1687
|
+
if (xWins) return ok2([x], told(y, `${py.family} ${common.join(",")}`));
|
|
1688
|
+
const narrowed = fx === "all" && fy !== "all" ? px.narrow?.(x, fy) : null;
|
|
1689
|
+
return ok2(narrowed ? [narrowed] : [], [], told(x, `${px.family} ${common.join(",")}`));
|
|
1690
|
+
}
|
|
1492
1691
|
function familyOf(id) {
|
|
1493
1692
|
const e = SHEET_MUTATIONS[id];
|
|
1494
1693
|
return e && e.kind === "covered" ? e.family : "";
|
|
@@ -1516,6 +1715,8 @@ function transformMutation(x, y, side) {
|
|
|
1516
1715
|
const fy = familyOf(y.id);
|
|
1517
1716
|
const sy = structuralOf(y);
|
|
1518
1717
|
const sx = structuralOf(x);
|
|
1718
|
+
const rp = rangedPair(x, y, side, sx, sy);
|
|
1719
|
+
if (rp) return rp;
|
|
1519
1720
|
const sortp = sortPair(x, y, sx, sy);
|
|
1520
1721
|
if (sortp) return sortp;
|
|
1521
1722
|
const cp = countPair(x, y, sy);
|