@fuaran-ui/ops 0.1.0 → 0.3.0
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/README.md +2 -2
- package/dist/index.cjs +109 -137
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -2
- package/dist/index.d.ts +0 -2
- package/dist/index.js +110 -138
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Canonical-JSON codec (encoder + structural decoder) and tree-op apply engine for
|
|
4
4
|
the Fuaran UI wire format — a conformant **TypeScript host** of the
|
|
5
5
|
language-neutral contract specified in
|
|
6
|
-
[`fuaran/docs/WIRE_FORMAT.md`](../../../fuaran/docs/WIRE_FORMAT.md), sibling to the
|
|
6
|
+
[`fuaran-dotnet/docs/WIRE_FORMAT.md`](../../../fuaran-dotnet/docs/WIRE_FORMAT.md), sibling to the
|
|
7
7
|
F# host. Built on the typed shapes from
|
|
8
8
|
[`@fuaran-ui/schema`](../schema/) (a peer dependency).
|
|
9
9
|
|
|
@@ -73,7 +73,7 @@ of the erased payloads is the host's responsibility.
|
|
|
73
73
|
## Conformance is the stability contract
|
|
74
74
|
|
|
75
75
|
Per the wire-format **forward-coupling rule**
|
|
76
|
-
([`WIRE_FORMAT.md` §11](../../../fuaran/docs/WIRE_FORMAT.md)), adding a `NodeKind` / `Spec`
|
|
76
|
+
([`WIRE_FORMAT.md` §11](../../../fuaran-dotnet/docs/WIRE_FORMAT.md)), adding a `NodeKind` / `Spec`
|
|
77
77
|
/ `TreeOp` / `Binding` / `Action` case updates the F# encoder + decoder + the corpus
|
|
78
78
|
**and** this TS codec + `@fuaran-ui/schema` in the same commit. Byte-equality against the
|
|
79
79
|
corpus — not just API non-breakage — is the contract.
|
package/dist/index.cjs
CHANGED
|
@@ -362,8 +362,10 @@ var flushTrigger = (t) => {
|
|
|
362
362
|
};
|
|
363
363
|
var binding = (b, staticEnc = objValue) => {
|
|
364
364
|
switch (b.kind) {
|
|
365
|
-
case "Static":
|
|
366
|
-
|
|
365
|
+
case "Static": {
|
|
366
|
+
const valueFields = b.value === null || b.value === void 0 ? [] : [["value", staticEnc(b.value)]];
|
|
367
|
+
return caseObj("Static", valueFields);
|
|
368
|
+
}
|
|
367
369
|
case "Query": {
|
|
368
370
|
const dependsOnFields = b.dependsOn !== void 0 && b.dependsOn.length > 0 ? [["dependsOn", jArray(b.dependsOn.map((s) => str(s)))]] : [];
|
|
369
371
|
return caseObj("Query", [...dependsOnFields, ["name", str(b.name)]]);
|
|
@@ -377,11 +379,10 @@ var binding = (b, staticEnc = objValue) => {
|
|
|
377
379
|
const fieldField = b.field !== void 0 ? [["field", str(b.field)]] : [];
|
|
378
380
|
return caseObj("Selection", [...defaultField, ...fieldField, ["nodeId", str(b.nodeId)]]);
|
|
379
381
|
}
|
|
380
|
-
case "State":
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
]);
|
|
382
|
+
case "State": {
|
|
383
|
+
const defaultFields = b.defaultValue === null || b.defaultValue === void 0 ? [] : [["defaultValue", staticEnc(b.defaultValue)]];
|
|
384
|
+
return caseObj("State", [...defaultFields, ["key", str(b.key)]]);
|
|
385
|
+
}
|
|
385
386
|
case "Computed":
|
|
386
387
|
return caseObj("Computed", [["fn", CLOSURE]]);
|
|
387
388
|
case "I18n": {
|
|
@@ -936,6 +937,25 @@ var formFieldKind = (autoBind, k) => {
|
|
|
936
937
|
if (k.constraints.step !== void 0) fields.push(["step", num(k.constraints.step)]);
|
|
937
938
|
return caseObj("Date", fields);
|
|
938
939
|
}
|
|
940
|
+
case "DateRange": {
|
|
941
|
+
const staticPair = (p) => jObject([
|
|
942
|
+
["from", str(p[0])],
|
|
943
|
+
["to", str(p[1])]
|
|
944
|
+
]);
|
|
945
|
+
const fields = [
|
|
946
|
+
...handlerField("onChange", k.onChange),
|
|
947
|
+
...valueField(
|
|
948
|
+
k.value,
|
|
949
|
+
schema.controlValueDefaults.dateRange,
|
|
950
|
+
(v) => v.kind === "Static" ? staticPair(v.value) : binding(v, staticPair)
|
|
951
|
+
),
|
|
952
|
+
["variant", str(k.variant)]
|
|
953
|
+
];
|
|
954
|
+
if (k.constraints.min !== void 0) fields.push(["min", str(k.constraints.min)]);
|
|
955
|
+
if (k.constraints.max !== void 0) fields.push(["max", str(k.constraints.max)]);
|
|
956
|
+
if (k.constraints.step !== void 0) fields.push(["step", num(k.constraints.step)]);
|
|
957
|
+
return caseObj("DateRange", fields);
|
|
958
|
+
}
|
|
939
959
|
default:
|
|
940
960
|
return assertNever(k);
|
|
941
961
|
}
|
|
@@ -1517,15 +1537,13 @@ var treeOp = (op) => {
|
|
|
1517
1537
|
case "InsertChild":
|
|
1518
1538
|
return caseObj("InsertChild", [
|
|
1519
1539
|
["child", node(op.child)],
|
|
1520
|
-
["parentId", str(op.parentId)]
|
|
1521
|
-
["position", num(op.position)]
|
|
1540
|
+
["parentId", str(op.parentId)]
|
|
1522
1541
|
]);
|
|
1523
1542
|
case "RemoveNode":
|
|
1524
1543
|
return caseObj("RemoveNode", [["target", str(op.target)]]);
|
|
1525
1544
|
case "MoveNode":
|
|
1526
1545
|
return caseObj("MoveNode", [
|
|
1527
1546
|
["newParentId", str(op.newParentId)],
|
|
1528
|
-
["newPosition", num(op.newPosition)],
|
|
1529
1547
|
["target", str(op.target)]
|
|
1530
1548
|
]);
|
|
1531
1549
|
case "ReorderChildren":
|
|
@@ -4034,9 +4052,8 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
|
|
|
4034
4052
|
if (!d.ok) return d;
|
|
4035
4053
|
switch (d.value) {
|
|
4036
4054
|
case "Static": {
|
|
4037
|
-
const
|
|
4038
|
-
|
|
4039
|
-
const parsed = parseStatic(`${path}.value`, v.value);
|
|
4055
|
+
const raw = f.get("value") ?? { kind: "JNull" };
|
|
4056
|
+
const parsed = parseStatic(`${path}.value`, raw);
|
|
4040
4057
|
return parsed.ok ? ok({ kind: "Static", value: parsed.value }) : parsed;
|
|
4041
4058
|
}
|
|
4042
4059
|
case "Query": {
|
|
@@ -4113,7 +4130,7 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
|
|
|
4113
4130
|
case "State": {
|
|
4114
4131
|
const key = reqField(path, f, "key", "state key string", requireString);
|
|
4115
4132
|
if (!key.ok) return key;
|
|
4116
|
-
const dv = fieldAliased(f, "defaultValue", ["initialValue", "default"]);
|
|
4133
|
+
const dv = fieldAliased(f, "defaultValue", ["initialValue", "default"]) ?? { kind: "JNull" };
|
|
4117
4134
|
let defaultValue = placeholder;
|
|
4118
4135
|
if (dv !== void 0) {
|
|
4119
4136
|
const parsed = parseStatic(`${path}.defaultValue`, dv);
|
|
@@ -4341,6 +4358,41 @@ var decodeBindingFloatPair = (p, j) => {
|
|
|
4341
4358
|
}
|
|
4342
4359
|
return decodeBinding(p, j, parseStaticFloatPair, [0, 0]);
|
|
4343
4360
|
};
|
|
4361
|
+
var parseStaticStringPair = (p, v) => {
|
|
4362
|
+
const ordered = (a, b) => a > b ? makeError(
|
|
4363
|
+
"WRONG_TYPE",
|
|
4364
|
+
p,
|
|
4365
|
+
`date-range start '${a}' is after end '${b}' \u2014 a DateRange pair is ordered (from <= to); ISO-8601 strings of one variant compare lexicographically, so swap the two values`,
|
|
4366
|
+
'ordered ISO-8601 pair ({"from": <iso>, "to": <iso>} with from <= to)'
|
|
4367
|
+
) : ok([a, b]);
|
|
4368
|
+
if (v.kind === "JObject") {
|
|
4369
|
+
const from = v.fields.get("from");
|
|
4370
|
+
const to = v.fields.get("to");
|
|
4371
|
+
if (from !== void 0 && to !== void 0) {
|
|
4372
|
+
const a = requireString(`${p}.from`, from);
|
|
4373
|
+
if (!a.ok) return a;
|
|
4374
|
+
const b = requireString(`${p}.to`, to);
|
|
4375
|
+
if (!b.ok) return b;
|
|
4376
|
+
return ordered(a.value, b.value);
|
|
4377
|
+
}
|
|
4378
|
+
return wrongType(p, "object with from and to ISO-8601 strings");
|
|
4379
|
+
}
|
|
4380
|
+
if (v.kind === "JArray" && v.items.length === 2) {
|
|
4381
|
+
const a = requireString(`${p}[0]`, v.items[0]);
|
|
4382
|
+
if (!a.ok) return a;
|
|
4383
|
+
const b = requireString(`${p}[1]`, v.items[1]);
|
|
4384
|
+
if (!b.ok) return b;
|
|
4385
|
+
return ordered(a.value, b.value);
|
|
4386
|
+
}
|
|
4387
|
+
return wrongType(p, "date-range pair ({from, to} object or [from, to] array)");
|
|
4388
|
+
};
|
|
4389
|
+
var decodeBindingStringPair = (p, j) => {
|
|
4390
|
+
if (j.kind === "JObject" && j.fields.get("$type") === void 0 && j.fields.get("from") !== void 0 && j.fields.get("to") !== void 0) {
|
|
4391
|
+
const parsed = parseStaticStringPair(p, j);
|
|
4392
|
+
return parsed.ok ? ok({ kind: "Static", value: parsed.value }) : parsed;
|
|
4393
|
+
}
|
|
4394
|
+
return decodeBinding(p, j, parseStaticStringPair, ["", ""]);
|
|
4395
|
+
};
|
|
4344
4396
|
var parseStaticStringList = (p, v) => {
|
|
4345
4397
|
if (v.kind === "JNull") return ok([]);
|
|
4346
4398
|
if (v.kind === "JString" && v.value === OPAQUE2) return ok([OPAQUE2]);
|
|
@@ -5188,6 +5240,7 @@ var decodeDisplayKind = (path, j) => {
|
|
|
5188
5240
|
);
|
|
5189
5241
|
}
|
|
5190
5242
|
};
|
|
5243
|
+
var WRONG_FORM_FIELD_KIND_HINT = schema.FORM_FIELD_KIND_NAMES.join(" | ");
|
|
5191
5244
|
var decodeFormFieldKind = (autoBind, path, j) => {
|
|
5192
5245
|
const fo = requireObject(path, j);
|
|
5193
5246
|
if (!fo.ok) return fo;
|
|
@@ -5337,12 +5390,35 @@ var decodeFormFieldKind = (autoBind, path, j) => {
|
|
|
5337
5390
|
}
|
|
5338
5391
|
});
|
|
5339
5392
|
}
|
|
5340
|
-
|
|
5341
|
-
|
|
5342
|
-
|
|
5343
|
-
|
|
5344
|
-
"
|
|
5393
|
+
case "DateRange": {
|
|
5394
|
+
const value = valueOr(
|
|
5395
|
+
decodeBindingStringPair,
|
|
5396
|
+
schema.controlValueDefaults.dateRange,
|
|
5397
|
+
"Binding<[from, to]> ISO-8601 pair value"
|
|
5345
5398
|
);
|
|
5399
|
+
if (!value.ok) return value;
|
|
5400
|
+
const variant = reqField(path, f, "variant", "DateVariant", decodeDateVariant);
|
|
5401
|
+
if (!variant.ok) return variant;
|
|
5402
|
+
const min = optField(path, f, "min", requireString);
|
|
5403
|
+
if (!min.ok) return min;
|
|
5404
|
+
const max = optField(path, f, "max", requireString);
|
|
5405
|
+
if (!max.ok) return max;
|
|
5406
|
+
const step = optField(path, f, "step", requireFloat);
|
|
5407
|
+
if (!step.ok) return step;
|
|
5408
|
+
return ok({
|
|
5409
|
+
kind: "DateRange",
|
|
5410
|
+
value: value.value,
|
|
5411
|
+
...onChangeField,
|
|
5412
|
+
variant: variant.value,
|
|
5413
|
+
constraints: {
|
|
5414
|
+
...min.value !== void 0 ? { min: min.value } : {},
|
|
5415
|
+
...max.value !== void 0 ? { max: max.value } : {},
|
|
5416
|
+
...step.value !== void 0 ? { step: step.value } : {}
|
|
5417
|
+
}
|
|
5418
|
+
});
|
|
5419
|
+
}
|
|
5420
|
+
default:
|
|
5421
|
+
return unknownDuCase(path, d.value, WRONG_FORM_FIELD_KIND_HINT);
|
|
5346
5422
|
}
|
|
5347
5423
|
};
|
|
5348
5424
|
var decodeFormField = (path, j) => {
|
|
@@ -5828,23 +5904,6 @@ var decodeVisKind = (path, j) => {
|
|
|
5828
5904
|
const r = decodeChartSpec(path, j);
|
|
5829
5905
|
return r.ok ? ok({ kind: "Chart", spec: r.value }) : r;
|
|
5830
5906
|
}
|
|
5831
|
-
// Phase 393 — legacy decode-upgrade: a `Table` tag folds into a read-only `Grid`
|
|
5832
|
-
// (the `staticRows` mode). Accepted on read but NEVER re-encodes as `Table` (the
|
|
5833
|
-
// encoder has no `Table` arm), riding the Phase 390 retired-kind seam.
|
|
5834
|
-
case "Table": {
|
|
5835
|
-
const r = decodeStaticRows(path, j);
|
|
5836
|
-
return r.ok ? ok({
|
|
5837
|
-
kind: "Grid",
|
|
5838
|
-
spec: {
|
|
5839
|
-
// An opaque Static source re-encodes to {"$type":"Static","value":"<opaque>"} —
|
|
5840
|
-
// byte-identical to the F# static grid's `Binding.Static Seq.empty`.
|
|
5841
|
-
source: { kind: "Static", value: OPAQUE2 },
|
|
5842
|
-
columns: [],
|
|
5843
|
-
editable: false,
|
|
5844
|
-
staticRows: r.value
|
|
5845
|
-
}
|
|
5846
|
-
}) : r;
|
|
5847
|
-
}
|
|
5848
5907
|
case "Map": {
|
|
5849
5908
|
const r = decodeMapSpec(path, j);
|
|
5850
5909
|
return r.ok ? ok({ kind: "Map", spec: r.value }) : r;
|
|
@@ -5936,64 +5995,6 @@ var decodeBox = (path, j) => {
|
|
|
5936
5995
|
role: role.value
|
|
5937
5996
|
});
|
|
5938
5997
|
};
|
|
5939
|
-
var decodeLegacyDashboard = (path, j) => {
|
|
5940
|
-
const fo = requireObject(path, j);
|
|
5941
|
-
if (!fo.ok) return fo;
|
|
5942
|
-
const children = decodeChildren(path, fo.value);
|
|
5943
|
-
if (!children.ok) return children;
|
|
5944
|
-
return ok({ children: children.value, layout: { kind: "Auto" }, role: "Dashboard" });
|
|
5945
|
-
};
|
|
5946
|
-
var decodeLegacyStack = (path, j) => {
|
|
5947
|
-
const fo = requireObject(path, j);
|
|
5948
|
-
if (!fo.ok) return fo;
|
|
5949
|
-
const f = fo.value;
|
|
5950
|
-
const children = decodeChildren(path, f);
|
|
5951
|
-
if (!children.ok) return children;
|
|
5952
|
-
const orientation = reqField(path, f, "orientation", "Orientation", decodeOrientation);
|
|
5953
|
-
if (!orientation.ok) return orientation;
|
|
5954
|
-
const wrap = reqField(path, f, "wrap", "wrap bool", requireBool);
|
|
5955
|
-
if (!wrap.ok) return wrap;
|
|
5956
|
-
return ok({
|
|
5957
|
-
children: children.value,
|
|
5958
|
-
layout: { kind: "Flex", direction: orientation.value, wrap: wrap.value },
|
|
5959
|
-
role: "Group"
|
|
5960
|
-
});
|
|
5961
|
-
};
|
|
5962
|
-
var decodeLegacyGridLayout = (path, j) => {
|
|
5963
|
-
const fo = requireObject(path, j);
|
|
5964
|
-
if (!fo.ok) return fo;
|
|
5965
|
-
const f = fo.value;
|
|
5966
|
-
const children = decodeChildren(path, f);
|
|
5967
|
-
if (!children.ok) return children;
|
|
5968
|
-
const cols = reqFieldAliased(path, f, "cols", ["columns"], "cols integer", requireInt);
|
|
5969
|
-
if (!cols.ok) return cols;
|
|
5970
|
-
const templateColumns = optField(path, f, "templateColumns", requireString);
|
|
5971
|
-
if (!templateColumns.ok) return templateColumns;
|
|
5972
|
-
return ok({
|
|
5973
|
-
children: children.value,
|
|
5974
|
-
layout: {
|
|
5975
|
-
kind: "Grid",
|
|
5976
|
-
cols: cols.value,
|
|
5977
|
-
...templateColumns.value !== void 0 ? { templateColumns: templateColumns.value } : {}
|
|
5978
|
-
},
|
|
5979
|
-
role: "Group"
|
|
5980
|
-
});
|
|
5981
|
-
};
|
|
5982
|
-
var decodeLegacyCard = (path, j) => {
|
|
5983
|
-
const fo = requireObject(path, j);
|
|
5984
|
-
if (!fo.ok) return fo;
|
|
5985
|
-
const f = fo.value;
|
|
5986
|
-
const children = decodeChildren(path, f);
|
|
5987
|
-
if (!children.ok) return children;
|
|
5988
|
-
const heading = optFieldAliased(path, f, "heading", ["title"], decodeTextSource);
|
|
5989
|
-
if (!heading.ok) return heading;
|
|
5990
|
-
return ok({
|
|
5991
|
-
children: children.value,
|
|
5992
|
-
...heading.value !== void 0 ? { heading: heading.value } : {},
|
|
5993
|
-
layout: { kind: "Flex", direction: "Vertical", wrap: false },
|
|
5994
|
-
role: "Card"
|
|
5995
|
-
});
|
|
5996
|
-
};
|
|
5997
5998
|
var decodeSplitPanelSpec = (path, j) => {
|
|
5998
5999
|
const fo = requireObject(path, j);
|
|
5999
6000
|
if (!fo.ok) return fo;
|
|
@@ -6183,22 +6184,6 @@ var decodeLayoutKind = (path, j) => {
|
|
|
6183
6184
|
const r = decodeBox(path, j);
|
|
6184
6185
|
return r.ok ? ok({ kind: "Box", spec: r.value }) : r;
|
|
6185
6186
|
}
|
|
6186
|
-
case "Dashboard": {
|
|
6187
|
-
const r = decodeLegacyDashboard(path, j);
|
|
6188
|
-
return r.ok ? ok({ kind: "Box", spec: r.value }) : r;
|
|
6189
|
-
}
|
|
6190
|
-
case "Stack": {
|
|
6191
|
-
const r = decodeLegacyStack(path, j);
|
|
6192
|
-
return r.ok ? ok({ kind: "Box", spec: r.value }) : r;
|
|
6193
|
-
}
|
|
6194
|
-
case "GridLayout": {
|
|
6195
|
-
const r = decodeLegacyGridLayout(path, j);
|
|
6196
|
-
return r.ok ? ok({ kind: "Box", spec: r.value }) : r;
|
|
6197
|
-
}
|
|
6198
|
-
case "Card": {
|
|
6199
|
-
const r = decodeLegacyCard(path, j);
|
|
6200
|
-
return r.ok ? ok({ kind: "Box", spec: r.value }) : r;
|
|
6201
|
-
}
|
|
6202
6187
|
case "SplitPanel": {
|
|
6203
6188
|
const r = decodeSplitPanelSpec(path, j);
|
|
6204
6189
|
return r.ok ? ok({ kind: "SplitPanel", spec: r.value }) : r;
|
|
@@ -6231,7 +6216,7 @@ var decodeLayoutKind = (path, j) => {
|
|
|
6231
6216
|
return unknownDuCase(
|
|
6232
6217
|
path,
|
|
6233
6218
|
d.value,
|
|
6234
|
-
"Box |
|
|
6219
|
+
"Box | SplitPanel | Tabs | Stepper | SummaryList | Disclosure | Modal | ScrollArea"
|
|
6235
6220
|
);
|
|
6236
6221
|
}
|
|
6237
6222
|
};
|
|
@@ -6395,6 +6380,13 @@ var decodeEffectClass = (path, j) => {
|
|
|
6395
6380
|
);
|
|
6396
6381
|
return ok({ hostEffect: host.value, determinism: det.value });
|
|
6397
6382
|
};
|
|
6383
|
+
var WRONG_NODE_KIND_HINT = (() => {
|
|
6384
|
+
const primitives = schema.NODE_KIND_GROUPS.filter((g) => g.label !== "Structural").map(
|
|
6385
|
+
(g) => `${"AEIOU".includes(g.label[0]) ? "an" : "a"} ${g.label} primitive (${g.kinds.join(" | ")})`
|
|
6386
|
+
).join(", ");
|
|
6387
|
+
const structural = schema.NODE_KIND_GROUPS.find((g) => g.label === "Structural")?.kinds ?? [];
|
|
6388
|
+
return `${primitives}, or ${structural.join(" | ")}`;
|
|
6389
|
+
})();
|
|
6398
6390
|
var decodeNodeKind = (path, j) => {
|
|
6399
6391
|
const fo = requireObject(path, j);
|
|
6400
6392
|
if (!fo.ok) return fo;
|
|
@@ -6407,12 +6399,8 @@ var decodeNodeKind = (path, j) => {
|
|
|
6407
6399
|
// each primitive to its inner decoder and recover the category here. These
|
|
6408
6400
|
// name-sets MUST stay in sync with the four inner decoders + the encoder.
|
|
6409
6401
|
case "Box":
|
|
6410
|
-
case "Dashboard":
|
|
6411
|
-
case "Stack":
|
|
6412
|
-
case "GridLayout":
|
|
6413
6402
|
case "SplitPanel":
|
|
6414
6403
|
case "Tabs":
|
|
6415
|
-
case "Card":
|
|
6416
6404
|
case "Stepper":
|
|
6417
6405
|
case "SummaryList":
|
|
6418
6406
|
case "Disclosure":
|
|
@@ -6451,7 +6439,6 @@ var decodeNodeKind = (path, j) => {
|
|
|
6451
6439
|
}
|
|
6452
6440
|
case "DataGrid":
|
|
6453
6441
|
case "Chart":
|
|
6454
|
-
case "Table":
|
|
6455
6442
|
case "Map": {
|
|
6456
6443
|
const k = decodeVisKind(path, j);
|
|
6457
6444
|
return k.ok ? ok({ kind: "Visualisation", visualisation: k.value }) : k;
|
|
@@ -6654,7 +6641,7 @@ var decodeNodeKind = (path, j) => {
|
|
|
6654
6641
|
"WRONG_NODE_KIND",
|
|
6655
6642
|
`${path}.$type`,
|
|
6656
6643
|
`unknown NodeKind discriminator '${d.value}'`,
|
|
6657
|
-
|
|
6644
|
+
WRONG_NODE_KIND_HINT
|
|
6658
6645
|
);
|
|
6659
6646
|
}
|
|
6660
6647
|
};
|
|
@@ -6825,13 +6812,10 @@ var decodeTreeOpAst = (path, j) => {
|
|
|
6825
6812
|
case "InsertChild": {
|
|
6826
6813
|
const parentJ = reqField(path, f, "parentId", "parent NodeId", requireString);
|
|
6827
6814
|
if (!parentJ.ok) return parentJ;
|
|
6828
|
-
const position = reqField(path, f, "position", "position integer", requireInt);
|
|
6829
|
-
if (!position.ok) return position;
|
|
6830
6815
|
const child = reqField(path, f, "child", "child Node object", decodeNodeAst);
|
|
6831
6816
|
return child.ok ? ok({
|
|
6832
6817
|
kind: "InsertChild",
|
|
6833
6818
|
parentId: parentJ.value,
|
|
6834
|
-
position: position.value,
|
|
6835
6819
|
child: child.value
|
|
6836
6820
|
}) : child;
|
|
6837
6821
|
}
|
|
@@ -6843,14 +6827,11 @@ var decodeTreeOpAst = (path, j) => {
|
|
|
6843
6827
|
const t = target();
|
|
6844
6828
|
if (!t.ok) return t;
|
|
6845
6829
|
const newParent = reqField(path, f, "newParentId", "new parent NodeId", requireString);
|
|
6846
|
-
|
|
6847
|
-
const newPosition = reqField(path, f, "newPosition", "new position integer", requireInt);
|
|
6848
|
-
return newPosition.ok ? ok({
|
|
6830
|
+
return newParent.ok ? ok({
|
|
6849
6831
|
kind: "MoveNode",
|
|
6850
6832
|
target: t.value,
|
|
6851
|
-
newParentId: newParent.value
|
|
6852
|
-
|
|
6853
|
-
}) : newPosition;
|
|
6833
|
+
newParentId: newParent.value
|
|
6834
|
+
}) : newParent;
|
|
6854
6835
|
}
|
|
6855
6836
|
case "ReorderChildren": {
|
|
6856
6837
|
const parentJ = reqField(path, f, "parentId", "parent NodeId", requireString);
|
|
@@ -7858,11 +7839,6 @@ var applyOne = (op, root, telem) => {
|
|
|
7858
7839
|
"ChildlessKind",
|
|
7859
7840
|
`Node '${op.parentId}' (kind=${parent.kind.kind}) has no children field \u2014 only Layout kinds accept structural child ops.`
|
|
7860
7841
|
);
|
|
7861
|
-
if (op.position < 0 || op.position > children.length)
|
|
7862
|
-
return fail2(
|
|
7863
|
-
"PositionOutOfRange",
|
|
7864
|
-
`Position ${op.position} is out of range for parent '${op.parentId}' (valid: 0..${children.length}).`
|
|
7865
|
-
);
|
|
7866
7842
|
const existing = new Set(allNodeIds(root));
|
|
7867
7843
|
const duplicate = allNodeIds(op.child).find((id) => existing.has(id));
|
|
7868
7844
|
if (duplicate !== void 0)
|
|
@@ -7870,11 +7846,7 @@ var applyOne = (op, root, telem) => {
|
|
|
7870
7846
|
"DuplicateNodeId",
|
|
7871
7847
|
`NodeId '${duplicate}' is already present in the tree; ids must be unique.`
|
|
7872
7848
|
);
|
|
7873
|
-
const newChildren = [
|
|
7874
|
-
...children.slice(0, op.position),
|
|
7875
|
-
op.child,
|
|
7876
|
-
...children.slice(op.position)
|
|
7877
|
-
];
|
|
7849
|
+
const newChildren = [...children, op.child];
|
|
7878
7850
|
const newTree = mapNode(op.parentId, (n) => withLayoutChildren(n, newChildren), root);
|
|
7879
7851
|
if (newTree === void 0)
|
|
7880
7852
|
return fail2("ParentNotFound", `Parent node '${op.parentId}' not found in tree.`);
|
|
@@ -7922,7 +7894,7 @@ var applyOne = (op, root, telem) => {
|
|
|
7922
7894
|
const afterRemove = applyOne({ kind: "RemoveNode", target: op.target }, root, []);
|
|
7923
7895
|
if (!afterRemove.ok) return afterRemove;
|
|
7924
7896
|
const inserted = applyOne(
|
|
7925
|
-
{ kind: "InsertChild", parentId: op.newParentId,
|
|
7897
|
+
{ kind: "InsertChild", parentId: op.newParentId, child: moving },
|
|
7926
7898
|
afterRemove.value,
|
|
7927
7899
|
[]
|
|
7928
7900
|
);
|