@atscript/ui 0.1.103 → 0.1.105
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/dist/index.cjs +301 -10
- package/dist/index.d.cts +205 -6
- package/dist/index.d.mts +205 -6
- package/dist/index.mjs +293 -9
- package/dist/plugin.cjs +2 -2
- package/dist/plugin.mjs +2 -2
- package/package.json +8 -8
package/dist/index.cjs
CHANGED
|
@@ -30,7 +30,7 @@ const UI_FORM_SUFFIX_ICON = "ui.form.suffix.icon";
|
|
|
30
30
|
const UI_TABLE_WIDTH = "ui.table.width";
|
|
31
31
|
const UI_TABLE_COMPONENT = "ui.table.component";
|
|
32
32
|
const UI_TABLE_SELECT_WITH = "ui.table.selectWith";
|
|
33
|
-
const
|
|
33
|
+
const UI_TABLE_EXCLUDE = "ui.table.exclude";
|
|
34
34
|
const UI_TABLE_ATTR = "ui.table.attr";
|
|
35
35
|
const UI_TABLE_CLASSES = "ui.table.classes";
|
|
36
36
|
const UI_TABLE_STYLES = "ui.table.styles";
|
|
@@ -811,6 +811,35 @@ function setByPath(obj, path, value) {
|
|
|
811
811
|
}
|
|
812
812
|
current[last] = value;
|
|
813
813
|
}
|
|
814
|
+
/**
|
|
815
|
+
* Deletes the own key at a dot-separated path (form-data wrapper aware — derefs
|
|
816
|
+
* `obj.value` first). Walks to the parent WITHOUT vivifying intermediate nodes:
|
|
817
|
+
* if any ancestor is missing, the call is a no-op (nothing to delete).
|
|
818
|
+
*
|
|
819
|
+
* Unlike `setByPath(obj, path, undefined)`, this leaves NO own key behind — the
|
|
820
|
+
* leaf reads as absent (`'k' in parent === false`), which keeps `deepEqual`
|
|
821
|
+
* structural comparisons in sync (a present `undefined` own-key and an absent
|
|
822
|
+
* key are NOT structurally equal under the own-key walk). Used by
|
|
823
|
+
* {@link applyFormChanges} to apply a clear-to-`undefined` change as a delete.
|
|
824
|
+
*
|
|
825
|
+
* Empty path clears the root domain value (`obj.value = undefined`).
|
|
826
|
+
*/
|
|
827
|
+
function deleteByPath(obj, path) {
|
|
828
|
+
if (!path) {
|
|
829
|
+
obj.value = void 0;
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
const keys = path.split(".");
|
|
833
|
+
const last = keys.pop();
|
|
834
|
+
if (last === void 0) return;
|
|
835
|
+
let current = obj.value;
|
|
836
|
+
for (const key of keys) {
|
|
837
|
+
if (current === null || current === void 0 || typeof current !== "object") return;
|
|
838
|
+
current = current[key];
|
|
839
|
+
}
|
|
840
|
+
if (current === null || current === void 0 || typeof current !== "object") return;
|
|
841
|
+
delete current[last];
|
|
842
|
+
}
|
|
814
843
|
function parseStaticDefault(raw, prop) {
|
|
815
844
|
if (typeof raw !== "string") return raw;
|
|
816
845
|
if (prop.type.kind === "" && prop.type.designType === "string") return raw;
|
|
@@ -884,8 +913,11 @@ function detectUnionVariant(value, variants) {
|
|
|
884
913
|
const disc = getVariantsDiscriminator(variants);
|
|
885
914
|
if (disc && value !== null && typeof value === "object") {
|
|
886
915
|
const tag = value[disc.propertyName];
|
|
887
|
-
const
|
|
888
|
-
if (
|
|
916
|
+
const key = String(tag);
|
|
917
|
+
if (Object.prototype.hasOwnProperty.call(disc.indexMapping, key)) {
|
|
918
|
+
const idx = disc.indexMapping[key];
|
|
919
|
+
if (idx !== void 0) return idx;
|
|
920
|
+
}
|
|
889
921
|
}
|
|
890
922
|
for (let i = 0; i < variants.length; i++) try {
|
|
891
923
|
if (getVariantValidator(variants[i]).validate(value, true)) return i;
|
|
@@ -893,6 +925,35 @@ function detectUnionVariant(value, variants) {
|
|
|
893
925
|
return 0;
|
|
894
926
|
}
|
|
895
927
|
//#endregion
|
|
928
|
+
//#region src/form/clone.ts
|
|
929
|
+
/**
|
|
930
|
+
* Structural deep clone of plain JSON-ish data (objects / arrays / primitives /
|
|
931
|
+
* `Date`). Walks OWN-ENUMERABLE keys only (matches the own-key discipline in
|
|
932
|
+
* `diff.ts` — never copies an accidental prototype) and copies leaves by value.
|
|
933
|
+
*
|
|
934
|
+
* `structuredClone` is deliberately NOT used: it throws on functions and on Vue
|
|
935
|
+
* reactive proxies. The optional `unwrap` hook lets a framework caller
|
|
936
|
+
* de-proxy each value first (vue-form passes `toRaw`); the core omits it.
|
|
937
|
+
*
|
|
938
|
+
* The SINGLE deep-clone primitive for the form engine — used by
|
|
939
|
+
* `applyFormChanges`, `buildFormRebase`, and vue-form's baseline snapshot. Do
|
|
940
|
+
* not reimplement structural cloning elsewhere.
|
|
941
|
+
*/
|
|
942
|
+
function deepClone(value, unwrap) {
|
|
943
|
+
const v = unwrap ? unwrap(value) : value;
|
|
944
|
+
if (v === null || typeof v !== "object") return v;
|
|
945
|
+
if (v instanceof Date) return new Date(v.getTime());
|
|
946
|
+
if (Array.isArray(v)) {
|
|
947
|
+
const out = [];
|
|
948
|
+
for (let i = 0; i < v.length; i++) out.push(deepClone(v[i], unwrap));
|
|
949
|
+
return out;
|
|
950
|
+
}
|
|
951
|
+
const src = v;
|
|
952
|
+
const out = {};
|
|
953
|
+
for (const k of Object.keys(src)) out[k] = deepClone(src[k], unwrap);
|
|
954
|
+
return out;
|
|
955
|
+
}
|
|
956
|
+
//#endregion
|
|
896
957
|
//#region src/form/validate.ts
|
|
897
958
|
let defaultValidatorPlugins = [];
|
|
898
959
|
/** Replace the default validator plugins applied to every form/field validator. */
|
|
@@ -1351,6 +1412,10 @@ function stableKey(v) {
|
|
|
1351
1412
|
* Structural deep equality (order-sensitive for arrays). `NaN` equals `NaN`
|
|
1352
1413
|
* (revert-aware for NaN scalars) while `0` / `-0` stay equal (matches DB
|
|
1353
1414
|
* intent — `===` treats them equal, only NaN is special-cased).
|
|
1415
|
+
*
|
|
1416
|
+
* The single comparator shared across the form engine: diff, conflict
|
|
1417
|
+
* detection ({@link buildFormRebase}), and apply all route through this — never
|
|
1418
|
+
* reimplement equality elsewhere.
|
|
1354
1419
|
*/
|
|
1355
1420
|
function deepEqual(a, b) {
|
|
1356
1421
|
if (a === b) return true;
|
|
@@ -1377,6 +1442,228 @@ function deepEqual(a, b) {
|
|
|
1377
1442
|
return true;
|
|
1378
1443
|
}
|
|
1379
1444
|
//#endregion
|
|
1445
|
+
//#region src/form/dirty.ts
|
|
1446
|
+
/**
|
|
1447
|
+
* True when the field at dot-path `path` is dirty given a {@link FormFieldChange}
|
|
1448
|
+
* list (as produced by {@link buildFormDiff}).
|
|
1449
|
+
*
|
|
1450
|
+
* The change list is leaf-grained for scalars/objects but WHOLE-ARRAY for arrays,
|
|
1451
|
+
* so a field at `path` is dirty iff some change path equals `path` OR starts with
|
|
1452
|
+
* `path + "."`:
|
|
1453
|
+
*
|
|
1454
|
+
* - scalar / leaf field (incl. nested `address.city`) → exact match.
|
|
1455
|
+
* - object / section container → no entry at its own path, only its leaves →
|
|
1456
|
+
* matched by the PREFIX branch.
|
|
1457
|
+
* - whole-array field → one entry at the array root → exact match.
|
|
1458
|
+
* - a field rendered for an array-ITEM leaf (e.g. `items.0.qty`) → NOT detectable:
|
|
1459
|
+
* the array diff emits a single whole-array change at the array root, never
|
|
1460
|
+
* per-item leaf paths, so this correctly returns false (the array container
|
|
1461
|
+
* lights up instead). This is a known, documented limitation.
|
|
1462
|
+
*
|
|
1463
|
+
* The prefix uses `path + "."` so field `item` never matches a change at `items`
|
|
1464
|
+
* (no false positives).
|
|
1465
|
+
*
|
|
1466
|
+
* Empty `path` `''` is the wrapped form root — every change is nested under it,
|
|
1467
|
+
* so it is considered dirty iff there are ANY changes.
|
|
1468
|
+
*/
|
|
1469
|
+
function isPathDirty(changes, path) {
|
|
1470
|
+
if (path === "") return changes.length > 0;
|
|
1471
|
+
const prefix = `${path}.`;
|
|
1472
|
+
for (const change of changes) if (change.path === path || change.path.startsWith(prefix)) return true;
|
|
1473
|
+
return false;
|
|
1474
|
+
}
|
|
1475
|
+
/**
|
|
1476
|
+
* Precomputes the set of ALL dirty paths from a {@link FormFieldChange} list so
|
|
1477
|
+
* that membership is an O(1) `Set.has(path)` instead of {@link isPathDirty}'s
|
|
1478
|
+
* per-call O(changes) prefix scan. Callers that probe many fields against the
|
|
1479
|
+
* same change list (e.g. a form rendering one field per leaf) build this once
|
|
1480
|
+
* and query it per field.
|
|
1481
|
+
*
|
|
1482
|
+
* For each change path `C` it adds `C` AND every dot-prefix ancestor of `C`
|
|
1483
|
+
* (so `'address.city'` adds both `'address.city'` and `'address'`), matching
|
|
1484
|
+
* `isPathDirty`'s "exact OR `path + '.'` prefix" predicate — an ancestor
|
|
1485
|
+
* container is dirty exactly when some change is nested under it. The wrapped
|
|
1486
|
+
* root `''` is added iff there are ANY changes, mirroring `isPathDirty('')`.
|
|
1487
|
+
*
|
|
1488
|
+
* INVARIANT (locked, tested): for EVERY path `P`,
|
|
1489
|
+
* `collectDirtyPaths(changes).has(P) === isPathDirty(changes, P)`. This is a
|
|
1490
|
+
* precompute of the SAME predicate, not a second one — keep them in lockstep.
|
|
1491
|
+
*/
|
|
1492
|
+
function collectDirtyPaths(changes) {
|
|
1493
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
1494
|
+
if (changes.length === 0) return dirty;
|
|
1495
|
+
dirty.add("");
|
|
1496
|
+
for (const change of changes) {
|
|
1497
|
+
const path = change.path;
|
|
1498
|
+
dirty.add(path);
|
|
1499
|
+
let dot = path.indexOf(".");
|
|
1500
|
+
while (dot !== -1) {
|
|
1501
|
+
dirty.add(path.slice(0, dot));
|
|
1502
|
+
dot = path.indexOf(".", dot + 1);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
return dirty;
|
|
1506
|
+
}
|
|
1507
|
+
//#endregion
|
|
1508
|
+
//#region src/form/apply.ts
|
|
1509
|
+
/**
|
|
1510
|
+
* Applies a {@link FormFieldChange} list onto a WRAPPED form-data container
|
|
1511
|
+
* (`{ value: domainData }`), mutating it in place and returning the same
|
|
1512
|
+
* reference. The inverse direction of {@link buildFormDiff}: where the diff
|
|
1513
|
+
* READS `(baseline, current)` into changes, this WRITES changes onto data.
|
|
1514
|
+
*
|
|
1515
|
+
* IMPORTANT: pass a CLONE, never the live fetched row — every write mutates
|
|
1516
|
+
* `data` directly. Callers that need the original intact should
|
|
1517
|
+
* `deepClone(data)` first (see {@link deepClone}).
|
|
1518
|
+
*
|
|
1519
|
+
* Per-change semantics (the single place the apply rules live, so
|
|
1520
|
+
* {@link buildFormRebase} stays consistent):
|
|
1521
|
+
*
|
|
1522
|
+
* - `kind: 'set'`:
|
|
1523
|
+
* - `change.after === undefined` → DELETE the own key at `change.path` (walk
|
|
1524
|
+
* to parent, `delete`). A cleared field must read as ABSENT, not as a
|
|
1525
|
+
* present `undefined` own-key — otherwise a re-diff sees a structural
|
|
1526
|
+
* mismatch where the form intends "no value". `setByPath(…, undefined)`
|
|
1527
|
+
* leaves an own key behind, so we use {@link deleteByPath} instead.
|
|
1528
|
+
* - otherwise → `setByPath(data, change.path, change.after)`.
|
|
1529
|
+
* - `kind: 'array'`: whole-array set via `setByPath(data, change.path,
|
|
1530
|
+
* change.after)` (LOCKED Option A — no per-element merge; the diff already
|
|
1531
|
+
* carried the full after-array).
|
|
1532
|
+
*
|
|
1533
|
+
* The `def` is currently unused by the apply walk (paths fully describe the
|
|
1534
|
+
* write target) but is part of the signature for parity with
|
|
1535
|
+
* `buildFormDiff`/`buildFormRebase`, so the rebase engine threads one `def`
|
|
1536
|
+
* uniformly through diff + apply.
|
|
1537
|
+
*/
|
|
1538
|
+
function applyFormChanges(_def, data, changes) {
|
|
1539
|
+
for (const change of changes) if (change.kind === "set" && change.after === void 0) deleteByPath(data, change.path);
|
|
1540
|
+
else setByPath(data, change.path, change.after);
|
|
1541
|
+
return data;
|
|
1542
|
+
}
|
|
1543
|
+
//#endregion
|
|
1544
|
+
//#region src/form/rebase.ts
|
|
1545
|
+
/**
|
|
1546
|
+
* Pure 3-way rebase for a change-tracked form. Given the current baseline `B0`,
|
|
1547
|
+
* the live form `C`, and a fresh upstream `U`, produces the form rewritten as
|
|
1548
|
+
* `U` + the local diff (`C` vs `B0`) reapplied on top:
|
|
1549
|
+
*
|
|
1550
|
+
* - Fields the user never touched adopt upstream's value.
|
|
1551
|
+
* - Local edits survive (reapplied onto the upstream clone).
|
|
1552
|
+
* - Fields changed on BOTH sides to different values are conflicts, resolved by
|
|
1553
|
+
* `opts.conflict` (`'ours'` keeps local, `'theirs'` takes upstream).
|
|
1554
|
+
*
|
|
1555
|
+
* All inputs are WRAPPED form-data containers (`{ value: domainData }`). The
|
|
1556
|
+
* result `next` is a fresh container; no input is mutated.
|
|
1557
|
+
*
|
|
1558
|
+
* `diffOptions` are forwarded to BOTH internal `buildFormDiff` passes so the
|
|
1559
|
+
* same field exclusions apply (notably the `@db.column.version` column and the
|
|
1560
|
+
* `$cas` policy) on the local and upstream sides — keep them identical to the
|
|
1561
|
+
* options the caller uses for its own change tracking.
|
|
1562
|
+
*/
|
|
1563
|
+
function buildFormRebase(def, baseline, current, upstream, opts, diffOptions) {
|
|
1564
|
+
const conflictMode = opts?.conflict ?? "ours";
|
|
1565
|
+
const local = buildFormDiff(def, baseline, current, diffOptions).changes;
|
|
1566
|
+
const upstreamChanges = buildFormDiff(def, baseline, upstream, diffOptions).changes;
|
|
1567
|
+
const upstreamByPath = /* @__PURE__ */ new Map();
|
|
1568
|
+
for (const uc of upstreamChanges) upstreamByPath.set(uc.path, uc);
|
|
1569
|
+
const next = deepClone(upstream);
|
|
1570
|
+
const conflicts = [];
|
|
1571
|
+
for (const lc of local) {
|
|
1572
|
+
const clearedAncestor = findClearedAncestor(lc.path, baseline, upstream);
|
|
1573
|
+
if (clearedAncestor !== void 0) {
|
|
1574
|
+
conflicts.push(clearedAncestor);
|
|
1575
|
+
if (conflictMode === "ours") setByPath(next, clearedAncestor, deepClone(getByPath(current, clearedAncestor)));
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
const uc = upstreamByPath.get(lc.path);
|
|
1579
|
+
if (uc !== void 0) {
|
|
1580
|
+
if (deepEqual(lc.after, uc.after)) continue;
|
|
1581
|
+
conflicts.push(lc.path);
|
|
1582
|
+
if (conflictMode === "ours") reapply(def, next, lc);
|
|
1583
|
+
continue;
|
|
1584
|
+
}
|
|
1585
|
+
reapply(def, next, lc);
|
|
1586
|
+
}
|
|
1587
|
+
const reapplied = buildFormDiff(def, upstream, deepClone(next), diffOptions).changes;
|
|
1588
|
+
return {
|
|
1589
|
+
next,
|
|
1590
|
+
conflicts: [...new Set(conflicts)],
|
|
1591
|
+
reapplied
|
|
1592
|
+
};
|
|
1593
|
+
}
|
|
1594
|
+
/**
|
|
1595
|
+
* Reapplies a single local change onto `next`, DEEP-CLONING its `after` value
|
|
1596
|
+
* first. `lc.after` is a LIVE reference into `current` (buildFormDiff holds live
|
|
1597
|
+
* refs), so for a `kind:'array'` or whole-object/union `set` change a raw apply
|
|
1598
|
+
* would make `next.value`'s node `===` `current.value`'s node — violating the
|
|
1599
|
+
* `FormRebaseResult.next` contract ("never aliases any input container"). The
|
|
1600
|
+
* ancestor-clear branch already deep-clones before writing; this keeps the two
|
|
1601
|
+
* leaf-reapply sites consistent.
|
|
1602
|
+
*/
|
|
1603
|
+
function reapply(def, next, lc) {
|
|
1604
|
+
applyFormChanges(def, next, [{
|
|
1605
|
+
...lc,
|
|
1606
|
+
after: deepClone(lc.after)
|
|
1607
|
+
}]);
|
|
1608
|
+
}
|
|
1609
|
+
/**
|
|
1610
|
+
* Returns the SHALLOWEST strict ancestor of `leafPath` that was an object/array
|
|
1611
|
+
* in `baseline` but is `null`/`undefined` in `upstream` (upstream cleared the
|
|
1612
|
+
* subtree), or `undefined` when no ancestor was cleared. The leaf path itself is
|
|
1613
|
+
* never considered an ancestor.
|
|
1614
|
+
*/
|
|
1615
|
+
function findClearedAncestor(leafPath, baseline, upstream) {
|
|
1616
|
+
if (!leafPath.includes(".")) return void 0;
|
|
1617
|
+
const segs = leafPath.split(".");
|
|
1618
|
+
let acc = "";
|
|
1619
|
+
for (let i = 0; i < segs.length - 1; i++) {
|
|
1620
|
+
acc = acc ? `${acc}.${segs[i]}` : segs[i];
|
|
1621
|
+
const base = getByPath(baseline, acc);
|
|
1622
|
+
if (typeof base !== "object" || base === null) continue;
|
|
1623
|
+
const up = getByPath(upstream, acc);
|
|
1624
|
+
if (up === null || up === void 0) return acc;
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1627
|
+
//#endregion
|
|
1628
|
+
//#region src/form/union-detect.ts
|
|
1629
|
+
/**
|
|
1630
|
+
* True when ANY union field in the form resolves to a DIFFERENT discriminated
|
|
1631
|
+
* variant between two wrapped data containers. A variant picker typically
|
|
1632
|
+
* detects its variant index once at setup and keys the variant subtree on it,
|
|
1633
|
+
* so a rebase that lands a different variant (via conflict OR an upstream-only
|
|
1634
|
+
* switch) needs a remount to re-detect. This walks union + nested-object fields
|
|
1635
|
+
* and compares `detectUnionVariant` at each union path.
|
|
1636
|
+
*
|
|
1637
|
+
* Scope note (pragmatic): walks standalone + nested-OBJECT union fields. Unions
|
|
1638
|
+
* nested INSIDE array items are not walked — an array renderer that keeps a
|
|
1639
|
+
* stable per-item key across in-place value mutations would not remount an
|
|
1640
|
+
* existing row's picker on an upstream-driven variant flip, but that collision
|
|
1641
|
+
* (a 3-way rebase landing a different union variant inside an unchanged array
|
|
1642
|
+
* row) is a rare edge. TODO: extend to array-item unions if a real consumer
|
|
1643
|
+
* hits a stuck picker inside an array row.
|
|
1644
|
+
*/
|
|
1645
|
+
function unionVariantChanged(def, before, after) {
|
|
1646
|
+
return walkUnionFields(def.fields, "", before, after);
|
|
1647
|
+
}
|
|
1648
|
+
function walkUnionFields(fields, prefix, before, after) {
|
|
1649
|
+
for (const field of fields) {
|
|
1650
|
+
if (field.phantom) continue;
|
|
1651
|
+
const fullPath = field.path ? prefix ? `${prefix}.${field.path}` : field.path : prefix;
|
|
1652
|
+
if (isUnionField(field)) {
|
|
1653
|
+
const variants = field.unionVariants;
|
|
1654
|
+
if (variants.length > 1) {
|
|
1655
|
+
if (detectUnionVariant(getByPath(before, fullPath), variants) !== detectUnionVariant(getByPath(after, fullPath), variants)) return true;
|
|
1656
|
+
}
|
|
1657
|
+
continue;
|
|
1658
|
+
}
|
|
1659
|
+
if (isObjectField(field)) {
|
|
1660
|
+
const objectDef = field.objectDef;
|
|
1661
|
+
if (walkUnionFields(objectDef.fields, fullPath, before, after)) return true;
|
|
1662
|
+
}
|
|
1663
|
+
}
|
|
1664
|
+
return false;
|
|
1665
|
+
}
|
|
1666
|
+
//#endregion
|
|
1380
1667
|
//#region src/form/error-utils.ts
|
|
1381
1668
|
/**
|
|
1382
1669
|
* Framework-agnostic helpers for working with form-error maps keyed by
|
|
@@ -1861,6 +2148,7 @@ function createTableDef(meta, preDeserializedType) {
|
|
|
1861
2148
|
const kind = prop.type.kind;
|
|
1862
2149
|
if (path.includes(".") || kind === "object" || kind === "array") continue;
|
|
1863
2150
|
}
|
|
2151
|
+
if (getFieldMeta(prop, "ui.table.exclude") !== void 0) continue;
|
|
1864
2152
|
const fieldMeta = meta.fields[path];
|
|
1865
2153
|
const options = extractLiteralOptions(prop);
|
|
1866
2154
|
const valueHelpInfo = extractValueHelp(prop);
|
|
@@ -1877,7 +2165,6 @@ function createTableDef(meta, preDeserializedType) {
|
|
|
1877
2165
|
sortable: fieldMeta?.sortable ?? false,
|
|
1878
2166
|
filterable: fieldMeta?.filterable ?? false,
|
|
1879
2167
|
nullable: prop.optional === true,
|
|
1880
|
-
visible: getFieldMeta(prop, UI_TABLE_HIDDEN) === void 0,
|
|
1881
2168
|
width: getFieldMeta(prop, UI_TABLE_WIDTH),
|
|
1882
2169
|
maxLen: maxLengthMeta?.length,
|
|
1883
2170
|
order: getFieldMeta(prop, "ui.table.order") ?? Infinity,
|
|
@@ -1893,6 +2180,7 @@ function createTableDef(meta, preDeserializedType) {
|
|
|
1893
2180
|
type,
|
|
1894
2181
|
columns,
|
|
1895
2182
|
flatMap,
|
|
2183
|
+
fetchableFields: new Set(Object.keys(meta.fields)),
|
|
1896
2184
|
primaryKeys: meta.primaryKeys,
|
|
1897
2185
|
preferredId: meta.preferredId ?? meta.primaryKeys,
|
|
1898
2186
|
versionColumn: meta.versionColumn,
|
|
@@ -1966,10 +2254,6 @@ function str(value) {
|
|
|
1966
2254
|
}
|
|
1967
2255
|
//#endregion
|
|
1968
2256
|
//#region src/table/column-resolver.ts
|
|
1969
|
-
/** Get visible columns only, already sorted by order. */
|
|
1970
|
-
function getVisibleColumns(def) {
|
|
1971
|
-
return def.columns.filter((c) => c.visible);
|
|
1972
|
-
}
|
|
1973
2257
|
/** Get sortable columns. */
|
|
1974
2258
|
function getSortableColumns(def) {
|
|
1975
2259
|
return def.columns.filter((c) => c.sortable);
|
|
@@ -2050,11 +2334,11 @@ exports.UI_FORM_VALIDATE = UI_FORM_VALIDATE;
|
|
|
2050
2334
|
exports.UI_TABLE_ATTR = UI_TABLE_ATTR;
|
|
2051
2335
|
exports.UI_TABLE_CLASSES = UI_TABLE_CLASSES;
|
|
2052
2336
|
exports.UI_TABLE_COMPONENT = UI_TABLE_COMPONENT;
|
|
2337
|
+
exports.UI_TABLE_EXCLUDE = UI_TABLE_EXCLUDE;
|
|
2053
2338
|
exports.UI_TABLE_FN_ATTR = UI_TABLE_FN_ATTR;
|
|
2054
2339
|
exports.UI_TABLE_FN_CLASSES = UI_TABLE_FN_CLASSES;
|
|
2055
2340
|
exports.UI_TABLE_FN_PREFIX = UI_TABLE_FN_PREFIX;
|
|
2056
2341
|
exports.UI_TABLE_FN_STYLES = UI_TABLE_FN_STYLES;
|
|
2057
|
-
exports.UI_TABLE_HIDDEN = UI_TABLE_HIDDEN;
|
|
2058
2342
|
exports.UI_TABLE_ORDER = UI_TABLE_ORDER;
|
|
2059
2343
|
exports.UI_TABLE_SELECT_WITH = UI_TABLE_SELECT_WITH;
|
|
2060
2344
|
exports.UI_TABLE_STYLES = UI_TABLE_STYLES;
|
|
@@ -2063,17 +2347,23 @@ exports.UI_TABLE_WIDTH = UI_TABLE_WIDTH;
|
|
|
2063
2347
|
exports.UI_TYPE = UI_TYPE;
|
|
2064
2348
|
exports.ValueHelpClient = ValueHelpClient;
|
|
2065
2349
|
exports.WF_ACTION_WITH_DATA = WF_ACTION_WITH_DATA;
|
|
2350
|
+
exports.applyFormChanges = applyFormChanges;
|
|
2066
2351
|
exports.asArray = asArray;
|
|
2067
2352
|
exports.buildDescendantErrorCounts = buildDescendantErrorCounts;
|
|
2068
2353
|
exports.buildFormDiff = buildFormDiff;
|
|
2354
|
+
exports.buildFormRebase = buildFormRebase;
|
|
2069
2355
|
exports.buildGridClasses = buildGridClasses;
|
|
2070
2356
|
exports.buildUnionVariants = buildUnionVariants;
|
|
2357
|
+
exports.collectDirtyPaths = collectDirtyPaths;
|
|
2071
2358
|
exports.createFieldValidator = createFieldValidator;
|
|
2072
2359
|
exports.createFormData = createFormData;
|
|
2073
2360
|
exports.createFormDef = createFormDef;
|
|
2074
2361
|
exports.createFormValueResolver = createFormValueResolver;
|
|
2075
2362
|
exports.createTableDef = createTableDef;
|
|
2363
|
+
exports.deepClone = deepClone;
|
|
2364
|
+
exports.deepEqual = deepEqual;
|
|
2076
2365
|
exports.defaultResolver = defaultResolver;
|
|
2366
|
+
exports.deleteByPath = deleteByPath;
|
|
2077
2367
|
exports.detectUnionVariant = detectUnionVariant;
|
|
2078
2368
|
exports.enforceScale = enforceScale;
|
|
2079
2369
|
exports.extractLiteralOptions = extractLiteralOptions;
|
|
@@ -2095,11 +2385,11 @@ exports.getMetaEntry = getMetaEntry;
|
|
|
2095
2385
|
exports.getResolver = getResolver;
|
|
2096
2386
|
exports.getSortableColumns = getSortableColumns;
|
|
2097
2387
|
exports.getThousandsSeparator = getThousandsSeparator;
|
|
2098
|
-
exports.getVisibleColumns = getVisibleColumns;
|
|
2099
2388
|
exports.groupInteger = groupInteger;
|
|
2100
2389
|
exports.hasComputedAnnotations = hasComputedAnnotations;
|
|
2101
2390
|
exports.isArrayField = isArrayField;
|
|
2102
2391
|
exports.isObjectField = isObjectField;
|
|
2392
|
+
exports.isPathDirty = isPathDirty;
|
|
2103
2393
|
exports.isPureLiteralUnion = isPureLiteralUnion;
|
|
2104
2394
|
exports.isTupleField = isTupleField;
|
|
2105
2395
|
exports.isUnionField = isUnionField;
|
|
@@ -2130,4 +2420,5 @@ exports.setDefaultValidatorPlugins = setDefaultValidatorPlugins;
|
|
|
2130
2420
|
exports.setResolver = setResolver;
|
|
2131
2421
|
exports.splitDecimalString = splitDecimalString;
|
|
2132
2422
|
exports.str = str;
|
|
2423
|
+
exports.unionVariantChanged = unionVariantChanged;
|
|
2133
2424
|
exports.valueHelpDictPaths = valueHelpDictPaths;
|