@atscript/ui 0.1.103 → 0.1.104
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 +3 -3
package/dist/index.mjs
CHANGED
|
@@ -29,7 +29,7 @@ const UI_FORM_SUFFIX_ICON = "ui.form.suffix.icon";
|
|
|
29
29
|
const UI_TABLE_WIDTH = "ui.table.width";
|
|
30
30
|
const UI_TABLE_COMPONENT = "ui.table.component";
|
|
31
31
|
const UI_TABLE_SELECT_WITH = "ui.table.selectWith";
|
|
32
|
-
const
|
|
32
|
+
const UI_TABLE_EXCLUDE = "ui.table.exclude";
|
|
33
33
|
const UI_TABLE_ATTR = "ui.table.attr";
|
|
34
34
|
const UI_TABLE_CLASSES = "ui.table.classes";
|
|
35
35
|
const UI_TABLE_STYLES = "ui.table.styles";
|
|
@@ -810,6 +810,35 @@ function setByPath(obj, path, value) {
|
|
|
810
810
|
}
|
|
811
811
|
current[last] = value;
|
|
812
812
|
}
|
|
813
|
+
/**
|
|
814
|
+
* Deletes the own key at a dot-separated path (form-data wrapper aware — derefs
|
|
815
|
+
* `obj.value` first). Walks to the parent WITHOUT vivifying intermediate nodes:
|
|
816
|
+
* if any ancestor is missing, the call is a no-op (nothing to delete).
|
|
817
|
+
*
|
|
818
|
+
* Unlike `setByPath(obj, path, undefined)`, this leaves NO own key behind — the
|
|
819
|
+
* leaf reads as absent (`'k' in parent === false`), which keeps `deepEqual`
|
|
820
|
+
* structural comparisons in sync (a present `undefined` own-key and an absent
|
|
821
|
+
* key are NOT structurally equal under the own-key walk). Used by
|
|
822
|
+
* {@link applyFormChanges} to apply a clear-to-`undefined` change as a delete.
|
|
823
|
+
*
|
|
824
|
+
* Empty path clears the root domain value (`obj.value = undefined`).
|
|
825
|
+
*/
|
|
826
|
+
function deleteByPath(obj, path) {
|
|
827
|
+
if (!path) {
|
|
828
|
+
obj.value = void 0;
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
const keys = path.split(".");
|
|
832
|
+
const last = keys.pop();
|
|
833
|
+
if (last === void 0) return;
|
|
834
|
+
let current = obj.value;
|
|
835
|
+
for (const key of keys) {
|
|
836
|
+
if (current === null || current === void 0 || typeof current !== "object") return;
|
|
837
|
+
current = current[key];
|
|
838
|
+
}
|
|
839
|
+
if (current === null || current === void 0 || typeof current !== "object") return;
|
|
840
|
+
delete current[last];
|
|
841
|
+
}
|
|
813
842
|
function parseStaticDefault(raw, prop) {
|
|
814
843
|
if (typeof raw !== "string") return raw;
|
|
815
844
|
if (prop.type.kind === "" && prop.type.designType === "string") return raw;
|
|
@@ -883,8 +912,11 @@ function detectUnionVariant(value, variants) {
|
|
|
883
912
|
const disc = getVariantsDiscriminator(variants);
|
|
884
913
|
if (disc && value !== null && typeof value === "object") {
|
|
885
914
|
const tag = value[disc.propertyName];
|
|
886
|
-
const
|
|
887
|
-
if (
|
|
915
|
+
const key = String(tag);
|
|
916
|
+
if (Object.prototype.hasOwnProperty.call(disc.indexMapping, key)) {
|
|
917
|
+
const idx = disc.indexMapping[key];
|
|
918
|
+
if (idx !== void 0) return idx;
|
|
919
|
+
}
|
|
888
920
|
}
|
|
889
921
|
for (let i = 0; i < variants.length; i++) try {
|
|
890
922
|
if (getVariantValidator(variants[i]).validate(value, true)) return i;
|
|
@@ -892,6 +924,35 @@ function detectUnionVariant(value, variants) {
|
|
|
892
924
|
return 0;
|
|
893
925
|
}
|
|
894
926
|
//#endregion
|
|
927
|
+
//#region src/form/clone.ts
|
|
928
|
+
/**
|
|
929
|
+
* Structural deep clone of plain JSON-ish data (objects / arrays / primitives /
|
|
930
|
+
* `Date`). Walks OWN-ENUMERABLE keys only (matches the own-key discipline in
|
|
931
|
+
* `diff.ts` — never copies an accidental prototype) and copies leaves by value.
|
|
932
|
+
*
|
|
933
|
+
* `structuredClone` is deliberately NOT used: it throws on functions and on Vue
|
|
934
|
+
* reactive proxies. The optional `unwrap` hook lets a framework caller
|
|
935
|
+
* de-proxy each value first (vue-form passes `toRaw`); the core omits it.
|
|
936
|
+
*
|
|
937
|
+
* The SINGLE deep-clone primitive for the form engine — used by
|
|
938
|
+
* `applyFormChanges`, `buildFormRebase`, and vue-form's baseline snapshot. Do
|
|
939
|
+
* not reimplement structural cloning elsewhere.
|
|
940
|
+
*/
|
|
941
|
+
function deepClone(value, unwrap) {
|
|
942
|
+
const v = unwrap ? unwrap(value) : value;
|
|
943
|
+
if (v === null || typeof v !== "object") return v;
|
|
944
|
+
if (v instanceof Date) return new Date(v.getTime());
|
|
945
|
+
if (Array.isArray(v)) {
|
|
946
|
+
const out = [];
|
|
947
|
+
for (let i = 0; i < v.length; i++) out.push(deepClone(v[i], unwrap));
|
|
948
|
+
return out;
|
|
949
|
+
}
|
|
950
|
+
const src = v;
|
|
951
|
+
const out = {};
|
|
952
|
+
for (const k of Object.keys(src)) out[k] = deepClone(src[k], unwrap);
|
|
953
|
+
return out;
|
|
954
|
+
}
|
|
955
|
+
//#endregion
|
|
895
956
|
//#region src/form/validate.ts
|
|
896
957
|
let defaultValidatorPlugins = [];
|
|
897
958
|
/** Replace the default validator plugins applied to every form/field validator. */
|
|
@@ -1350,6 +1411,10 @@ function stableKey(v) {
|
|
|
1350
1411
|
* Structural deep equality (order-sensitive for arrays). `NaN` equals `NaN`
|
|
1351
1412
|
* (revert-aware for NaN scalars) while `0` / `-0` stay equal (matches DB
|
|
1352
1413
|
* intent — `===` treats them equal, only NaN is special-cased).
|
|
1414
|
+
*
|
|
1415
|
+
* The single comparator shared across the form engine: diff, conflict
|
|
1416
|
+
* detection ({@link buildFormRebase}), and apply all route through this — never
|
|
1417
|
+
* reimplement equality elsewhere.
|
|
1353
1418
|
*/
|
|
1354
1419
|
function deepEqual(a, b) {
|
|
1355
1420
|
if (a === b) return true;
|
|
@@ -1376,6 +1441,228 @@ function deepEqual(a, b) {
|
|
|
1376
1441
|
return true;
|
|
1377
1442
|
}
|
|
1378
1443
|
//#endregion
|
|
1444
|
+
//#region src/form/dirty.ts
|
|
1445
|
+
/**
|
|
1446
|
+
* True when the field at dot-path `path` is dirty given a {@link FormFieldChange}
|
|
1447
|
+
* list (as produced by {@link buildFormDiff}).
|
|
1448
|
+
*
|
|
1449
|
+
* The change list is leaf-grained for scalars/objects but WHOLE-ARRAY for arrays,
|
|
1450
|
+
* so a field at `path` is dirty iff some change path equals `path` OR starts with
|
|
1451
|
+
* `path + "."`:
|
|
1452
|
+
*
|
|
1453
|
+
* - scalar / leaf field (incl. nested `address.city`) → exact match.
|
|
1454
|
+
* - object / section container → no entry at its own path, only its leaves →
|
|
1455
|
+
* matched by the PREFIX branch.
|
|
1456
|
+
* - whole-array field → one entry at the array root → exact match.
|
|
1457
|
+
* - a field rendered for an array-ITEM leaf (e.g. `items.0.qty`) → NOT detectable:
|
|
1458
|
+
* the array diff emits a single whole-array change at the array root, never
|
|
1459
|
+
* per-item leaf paths, so this correctly returns false (the array container
|
|
1460
|
+
* lights up instead). This is a known, documented limitation.
|
|
1461
|
+
*
|
|
1462
|
+
* The prefix uses `path + "."` so field `item` never matches a change at `items`
|
|
1463
|
+
* (no false positives).
|
|
1464
|
+
*
|
|
1465
|
+
* Empty `path` `''` is the wrapped form root — every change is nested under it,
|
|
1466
|
+
* so it is considered dirty iff there are ANY changes.
|
|
1467
|
+
*/
|
|
1468
|
+
function isPathDirty(changes, path) {
|
|
1469
|
+
if (path === "") return changes.length > 0;
|
|
1470
|
+
const prefix = `${path}.`;
|
|
1471
|
+
for (const change of changes) if (change.path === path || change.path.startsWith(prefix)) return true;
|
|
1472
|
+
return false;
|
|
1473
|
+
}
|
|
1474
|
+
/**
|
|
1475
|
+
* Precomputes the set of ALL dirty paths from a {@link FormFieldChange} list so
|
|
1476
|
+
* that membership is an O(1) `Set.has(path)` instead of {@link isPathDirty}'s
|
|
1477
|
+
* per-call O(changes) prefix scan. Callers that probe many fields against the
|
|
1478
|
+
* same change list (e.g. a form rendering one field per leaf) build this once
|
|
1479
|
+
* and query it per field.
|
|
1480
|
+
*
|
|
1481
|
+
* For each change path `C` it adds `C` AND every dot-prefix ancestor of `C`
|
|
1482
|
+
* (so `'address.city'` adds both `'address.city'` and `'address'`), matching
|
|
1483
|
+
* `isPathDirty`'s "exact OR `path + '.'` prefix" predicate — an ancestor
|
|
1484
|
+
* container is dirty exactly when some change is nested under it. The wrapped
|
|
1485
|
+
* root `''` is added iff there are ANY changes, mirroring `isPathDirty('')`.
|
|
1486
|
+
*
|
|
1487
|
+
* INVARIANT (locked, tested): for EVERY path `P`,
|
|
1488
|
+
* `collectDirtyPaths(changes).has(P) === isPathDirty(changes, P)`. This is a
|
|
1489
|
+
* precompute of the SAME predicate, not a second one — keep them in lockstep.
|
|
1490
|
+
*/
|
|
1491
|
+
function collectDirtyPaths(changes) {
|
|
1492
|
+
const dirty = /* @__PURE__ */ new Set();
|
|
1493
|
+
if (changes.length === 0) return dirty;
|
|
1494
|
+
dirty.add("");
|
|
1495
|
+
for (const change of changes) {
|
|
1496
|
+
const path = change.path;
|
|
1497
|
+
dirty.add(path);
|
|
1498
|
+
let dot = path.indexOf(".");
|
|
1499
|
+
while (dot !== -1) {
|
|
1500
|
+
dirty.add(path.slice(0, dot));
|
|
1501
|
+
dot = path.indexOf(".", dot + 1);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
return dirty;
|
|
1505
|
+
}
|
|
1506
|
+
//#endregion
|
|
1507
|
+
//#region src/form/apply.ts
|
|
1508
|
+
/**
|
|
1509
|
+
* Applies a {@link FormFieldChange} list onto a WRAPPED form-data container
|
|
1510
|
+
* (`{ value: domainData }`), mutating it in place and returning the same
|
|
1511
|
+
* reference. The inverse direction of {@link buildFormDiff}: where the diff
|
|
1512
|
+
* READS `(baseline, current)` into changes, this WRITES changes onto data.
|
|
1513
|
+
*
|
|
1514
|
+
* IMPORTANT: pass a CLONE, never the live fetched row — every write mutates
|
|
1515
|
+
* `data` directly. Callers that need the original intact should
|
|
1516
|
+
* `deepClone(data)` first (see {@link deepClone}).
|
|
1517
|
+
*
|
|
1518
|
+
* Per-change semantics (the single place the apply rules live, so
|
|
1519
|
+
* {@link buildFormRebase} stays consistent):
|
|
1520
|
+
*
|
|
1521
|
+
* - `kind: 'set'`:
|
|
1522
|
+
* - `change.after === undefined` → DELETE the own key at `change.path` (walk
|
|
1523
|
+
* to parent, `delete`). A cleared field must read as ABSENT, not as a
|
|
1524
|
+
* present `undefined` own-key — otherwise a re-diff sees a structural
|
|
1525
|
+
* mismatch where the form intends "no value". `setByPath(…, undefined)`
|
|
1526
|
+
* leaves an own key behind, so we use {@link deleteByPath} instead.
|
|
1527
|
+
* - otherwise → `setByPath(data, change.path, change.after)`.
|
|
1528
|
+
* - `kind: 'array'`: whole-array set via `setByPath(data, change.path,
|
|
1529
|
+
* change.after)` (LOCKED Option A — no per-element merge; the diff already
|
|
1530
|
+
* carried the full after-array).
|
|
1531
|
+
*
|
|
1532
|
+
* The `def` is currently unused by the apply walk (paths fully describe the
|
|
1533
|
+
* write target) but is part of the signature for parity with
|
|
1534
|
+
* `buildFormDiff`/`buildFormRebase`, so the rebase engine threads one `def`
|
|
1535
|
+
* uniformly through diff + apply.
|
|
1536
|
+
*/
|
|
1537
|
+
function applyFormChanges(_def, data, changes) {
|
|
1538
|
+
for (const change of changes) if (change.kind === "set" && change.after === void 0) deleteByPath(data, change.path);
|
|
1539
|
+
else setByPath(data, change.path, change.after);
|
|
1540
|
+
return data;
|
|
1541
|
+
}
|
|
1542
|
+
//#endregion
|
|
1543
|
+
//#region src/form/rebase.ts
|
|
1544
|
+
/**
|
|
1545
|
+
* Pure 3-way rebase for a change-tracked form. Given the current baseline `B0`,
|
|
1546
|
+
* the live form `C`, and a fresh upstream `U`, produces the form rewritten as
|
|
1547
|
+
* `U` + the local diff (`C` vs `B0`) reapplied on top:
|
|
1548
|
+
*
|
|
1549
|
+
* - Fields the user never touched adopt upstream's value.
|
|
1550
|
+
* - Local edits survive (reapplied onto the upstream clone).
|
|
1551
|
+
* - Fields changed on BOTH sides to different values are conflicts, resolved by
|
|
1552
|
+
* `opts.conflict` (`'ours'` keeps local, `'theirs'` takes upstream).
|
|
1553
|
+
*
|
|
1554
|
+
* All inputs are WRAPPED form-data containers (`{ value: domainData }`). The
|
|
1555
|
+
* result `next` is a fresh container; no input is mutated.
|
|
1556
|
+
*
|
|
1557
|
+
* `diffOptions` are forwarded to BOTH internal `buildFormDiff` passes so the
|
|
1558
|
+
* same field exclusions apply (notably the `@db.column.version` column and the
|
|
1559
|
+
* `$cas` policy) on the local and upstream sides — keep them identical to the
|
|
1560
|
+
* options the caller uses for its own change tracking.
|
|
1561
|
+
*/
|
|
1562
|
+
function buildFormRebase(def, baseline, current, upstream, opts, diffOptions) {
|
|
1563
|
+
const conflictMode = opts?.conflict ?? "ours";
|
|
1564
|
+
const local = buildFormDiff(def, baseline, current, diffOptions).changes;
|
|
1565
|
+
const upstreamChanges = buildFormDiff(def, baseline, upstream, diffOptions).changes;
|
|
1566
|
+
const upstreamByPath = /* @__PURE__ */ new Map();
|
|
1567
|
+
for (const uc of upstreamChanges) upstreamByPath.set(uc.path, uc);
|
|
1568
|
+
const next = deepClone(upstream);
|
|
1569
|
+
const conflicts = [];
|
|
1570
|
+
for (const lc of local) {
|
|
1571
|
+
const clearedAncestor = findClearedAncestor(lc.path, baseline, upstream);
|
|
1572
|
+
if (clearedAncestor !== void 0) {
|
|
1573
|
+
conflicts.push(clearedAncestor);
|
|
1574
|
+
if (conflictMode === "ours") setByPath(next, clearedAncestor, deepClone(getByPath(current, clearedAncestor)));
|
|
1575
|
+
continue;
|
|
1576
|
+
}
|
|
1577
|
+
const uc = upstreamByPath.get(lc.path);
|
|
1578
|
+
if (uc !== void 0) {
|
|
1579
|
+
if (deepEqual(lc.after, uc.after)) continue;
|
|
1580
|
+
conflicts.push(lc.path);
|
|
1581
|
+
if (conflictMode === "ours") reapply(def, next, lc);
|
|
1582
|
+
continue;
|
|
1583
|
+
}
|
|
1584
|
+
reapply(def, next, lc);
|
|
1585
|
+
}
|
|
1586
|
+
const reapplied = buildFormDiff(def, upstream, deepClone(next), diffOptions).changes;
|
|
1587
|
+
return {
|
|
1588
|
+
next,
|
|
1589
|
+
conflicts: [...new Set(conflicts)],
|
|
1590
|
+
reapplied
|
|
1591
|
+
};
|
|
1592
|
+
}
|
|
1593
|
+
/**
|
|
1594
|
+
* Reapplies a single local change onto `next`, DEEP-CLONING its `after` value
|
|
1595
|
+
* first. `lc.after` is a LIVE reference into `current` (buildFormDiff holds live
|
|
1596
|
+
* refs), so for a `kind:'array'` or whole-object/union `set` change a raw apply
|
|
1597
|
+
* would make `next.value`'s node `===` `current.value`'s node — violating the
|
|
1598
|
+
* `FormRebaseResult.next` contract ("never aliases any input container"). The
|
|
1599
|
+
* ancestor-clear branch already deep-clones before writing; this keeps the two
|
|
1600
|
+
* leaf-reapply sites consistent.
|
|
1601
|
+
*/
|
|
1602
|
+
function reapply(def, next, lc) {
|
|
1603
|
+
applyFormChanges(def, next, [{
|
|
1604
|
+
...lc,
|
|
1605
|
+
after: deepClone(lc.after)
|
|
1606
|
+
}]);
|
|
1607
|
+
}
|
|
1608
|
+
/**
|
|
1609
|
+
* Returns the SHALLOWEST strict ancestor of `leafPath` that was an object/array
|
|
1610
|
+
* in `baseline` but is `null`/`undefined` in `upstream` (upstream cleared the
|
|
1611
|
+
* subtree), or `undefined` when no ancestor was cleared. The leaf path itself is
|
|
1612
|
+
* never considered an ancestor.
|
|
1613
|
+
*/
|
|
1614
|
+
function findClearedAncestor(leafPath, baseline, upstream) {
|
|
1615
|
+
if (!leafPath.includes(".")) return void 0;
|
|
1616
|
+
const segs = leafPath.split(".");
|
|
1617
|
+
let acc = "";
|
|
1618
|
+
for (let i = 0; i < segs.length - 1; i++) {
|
|
1619
|
+
acc = acc ? `${acc}.${segs[i]}` : segs[i];
|
|
1620
|
+
const base = getByPath(baseline, acc);
|
|
1621
|
+
if (typeof base !== "object" || base === null) continue;
|
|
1622
|
+
const up = getByPath(upstream, acc);
|
|
1623
|
+
if (up === null || up === void 0) return acc;
|
|
1624
|
+
}
|
|
1625
|
+
}
|
|
1626
|
+
//#endregion
|
|
1627
|
+
//#region src/form/union-detect.ts
|
|
1628
|
+
/**
|
|
1629
|
+
* True when ANY union field in the form resolves to a DIFFERENT discriminated
|
|
1630
|
+
* variant between two wrapped data containers. A variant picker typically
|
|
1631
|
+
* detects its variant index once at setup and keys the variant subtree on it,
|
|
1632
|
+
* so a rebase that lands a different variant (via conflict OR an upstream-only
|
|
1633
|
+
* switch) needs a remount to re-detect. This walks union + nested-object fields
|
|
1634
|
+
* and compares `detectUnionVariant` at each union path.
|
|
1635
|
+
*
|
|
1636
|
+
* Scope note (pragmatic): walks standalone + nested-OBJECT union fields. Unions
|
|
1637
|
+
* nested INSIDE array items are not walked — an array renderer that keeps a
|
|
1638
|
+
* stable per-item key across in-place value mutations would not remount an
|
|
1639
|
+
* existing row's picker on an upstream-driven variant flip, but that collision
|
|
1640
|
+
* (a 3-way rebase landing a different union variant inside an unchanged array
|
|
1641
|
+
* row) is a rare edge. TODO: extend to array-item unions if a real consumer
|
|
1642
|
+
* hits a stuck picker inside an array row.
|
|
1643
|
+
*/
|
|
1644
|
+
function unionVariantChanged(def, before, after) {
|
|
1645
|
+
return walkUnionFields(def.fields, "", before, after);
|
|
1646
|
+
}
|
|
1647
|
+
function walkUnionFields(fields, prefix, before, after) {
|
|
1648
|
+
for (const field of fields) {
|
|
1649
|
+
if (field.phantom) continue;
|
|
1650
|
+
const fullPath = field.path ? prefix ? `${prefix}.${field.path}` : field.path : prefix;
|
|
1651
|
+
if (isUnionField(field)) {
|
|
1652
|
+
const variants = field.unionVariants;
|
|
1653
|
+
if (variants.length > 1) {
|
|
1654
|
+
if (detectUnionVariant(getByPath(before, fullPath), variants) !== detectUnionVariant(getByPath(after, fullPath), variants)) return true;
|
|
1655
|
+
}
|
|
1656
|
+
continue;
|
|
1657
|
+
}
|
|
1658
|
+
if (isObjectField(field)) {
|
|
1659
|
+
const objectDef = field.objectDef;
|
|
1660
|
+
if (walkUnionFields(objectDef.fields, fullPath, before, after)) return true;
|
|
1661
|
+
}
|
|
1662
|
+
}
|
|
1663
|
+
return false;
|
|
1664
|
+
}
|
|
1665
|
+
//#endregion
|
|
1379
1666
|
//#region src/form/error-utils.ts
|
|
1380
1667
|
/**
|
|
1381
1668
|
* Framework-agnostic helpers for working with form-error maps keyed by
|
|
@@ -1860,6 +2147,7 @@ function createTableDef(meta, preDeserializedType) {
|
|
|
1860
2147
|
const kind = prop.type.kind;
|
|
1861
2148
|
if (path.includes(".") || kind === "object" || kind === "array") continue;
|
|
1862
2149
|
}
|
|
2150
|
+
if (getFieldMeta(prop, "ui.table.exclude") !== void 0) continue;
|
|
1863
2151
|
const fieldMeta = meta.fields[path];
|
|
1864
2152
|
const options = extractLiteralOptions(prop);
|
|
1865
2153
|
const valueHelpInfo = extractValueHelp(prop);
|
|
@@ -1876,7 +2164,6 @@ function createTableDef(meta, preDeserializedType) {
|
|
|
1876
2164
|
sortable: fieldMeta?.sortable ?? false,
|
|
1877
2165
|
filterable: fieldMeta?.filterable ?? false,
|
|
1878
2166
|
nullable: prop.optional === true,
|
|
1879
|
-
visible: getFieldMeta(prop, UI_TABLE_HIDDEN) === void 0,
|
|
1880
2167
|
width: getFieldMeta(prop, UI_TABLE_WIDTH),
|
|
1881
2168
|
maxLen: maxLengthMeta?.length,
|
|
1882
2169
|
order: getFieldMeta(prop, "ui.table.order") ?? Infinity,
|
|
@@ -1892,6 +2179,7 @@ function createTableDef(meta, preDeserializedType) {
|
|
|
1892
2179
|
type,
|
|
1893
2180
|
columns,
|
|
1894
2181
|
flatMap,
|
|
2182
|
+
fetchableFields: new Set(Object.keys(meta.fields)),
|
|
1895
2183
|
primaryKeys: meta.primaryKeys,
|
|
1896
2184
|
preferredId: meta.preferredId ?? meta.primaryKeys,
|
|
1897
2185
|
versionColumn: meta.versionColumn,
|
|
@@ -1965,10 +2253,6 @@ function str(value) {
|
|
|
1965
2253
|
}
|
|
1966
2254
|
//#endregion
|
|
1967
2255
|
//#region src/table/column-resolver.ts
|
|
1968
|
-
/** Get visible columns only, already sorted by order. */
|
|
1969
|
-
function getVisibleColumns(def) {
|
|
1970
|
-
return def.columns.filter((c) => c.visible);
|
|
1971
|
-
}
|
|
1972
2256
|
/** Get sortable columns. */
|
|
1973
2257
|
function getSortableColumns(def) {
|
|
1974
2258
|
return def.columns.filter((c) => c.sortable);
|
|
@@ -1982,4 +2266,4 @@ function getColumn(def, path) {
|
|
|
1982
2266
|
return def.columns.find((c) => c.path === path);
|
|
1983
2267
|
}
|
|
1984
2268
|
//#endregion
|
|
1985
|
-
export { DB_AMOUNT_CURRENCY, DB_AMOUNT_CURRENCY_REF, DB_COLUMN_PRECISION, DB_HTTP_PATH, DB_REL_FK, DB_UNIT, DB_UNIT_REF, DEFAULT_COL_SPAN, DEFAULT_ROW_SPAN, EXPECT_MAX_LENGTH, META_DEFAULT, META_DESCRIPTION, META_ID, META_LABEL, META_READONLY, META_REQUIRED, META_SENSITIVE, StaticFieldResolver, UI_DICT_ATTR, UI_DICT_DESCR, UI_DICT_FILTERABLE, UI_DICT_LABEL, UI_DICT_SEARCHABLE, UI_DICT_SORTABLE, UI_FORM_ACTION, UI_FORM_ATTR, UI_FORM_AUTOCOMPLETE, UI_FORM_CLASSES, UI_FORM_COMPONENT, UI_FORM_DISABLED, UI_FORM_FN_ATTR, UI_FORM_FN_CLASSES, UI_FORM_FN_DESCRIPTION, UI_FORM_FN_DISABLED, UI_FORM_FN_HIDDEN, UI_FORM_FN_HINT, UI_FORM_FN_LABEL, UI_FORM_FN_OPTIONS, UI_FORM_FN_PLACEHOLDER, UI_FORM_FN_PREFIX, UI_FORM_FN_READONLY, UI_FORM_FN_STYLES, UI_FORM_FN_SUBMIT_DISABLED, UI_FORM_FN_SUBMIT_TEXT, UI_FORM_FN_TITLE, UI_FORM_FN_VALUE, UI_FORM_GRID_COL_SPAN, UI_FORM_GRID_ROW_SPAN, UI_FORM_HIDDEN, UI_FORM_HINT, UI_FORM_LABEL_SINGULAR, UI_FORM_OPTIONS, UI_FORM_ORDER, UI_FORM_PLACEHOLDER, UI_FORM_PREFIX, UI_FORM_PREFIX_ICON, UI_FORM_PREFIX_REF, UI_FORM_STYLES, UI_FORM_SUBMIT_TEXT, UI_FORM_SUFFIX, UI_FORM_SUFFIX_ICON, UI_FORM_SUFFIX_REF, UI_FORM_TYPE, UI_FORM_VALIDATE, UI_TABLE_ATTR, UI_TABLE_CLASSES, UI_TABLE_COMPONENT, UI_TABLE_FN_ATTR, UI_TABLE_FN_CLASSES, UI_TABLE_FN_PREFIX, UI_TABLE_FN_STYLES,
|
|
2269
|
+
export { DB_AMOUNT_CURRENCY, DB_AMOUNT_CURRENCY_REF, DB_COLUMN_PRECISION, DB_HTTP_PATH, DB_REL_FK, DB_UNIT, DB_UNIT_REF, DEFAULT_COL_SPAN, DEFAULT_ROW_SPAN, EXPECT_MAX_LENGTH, META_DEFAULT, META_DESCRIPTION, META_ID, META_LABEL, META_READONLY, META_REQUIRED, META_SENSITIVE, StaticFieldResolver, UI_DICT_ATTR, UI_DICT_DESCR, UI_DICT_FILTERABLE, UI_DICT_LABEL, UI_DICT_SEARCHABLE, UI_DICT_SORTABLE, UI_FORM_ACTION, UI_FORM_ATTR, UI_FORM_AUTOCOMPLETE, UI_FORM_CLASSES, UI_FORM_COMPONENT, UI_FORM_DISABLED, UI_FORM_FN_ATTR, UI_FORM_FN_CLASSES, UI_FORM_FN_DESCRIPTION, UI_FORM_FN_DISABLED, UI_FORM_FN_HIDDEN, UI_FORM_FN_HINT, UI_FORM_FN_LABEL, UI_FORM_FN_OPTIONS, UI_FORM_FN_PLACEHOLDER, UI_FORM_FN_PREFIX, UI_FORM_FN_READONLY, UI_FORM_FN_STYLES, UI_FORM_FN_SUBMIT_DISABLED, UI_FORM_FN_SUBMIT_TEXT, UI_FORM_FN_TITLE, UI_FORM_FN_VALUE, UI_FORM_GRID_COL_SPAN, UI_FORM_GRID_ROW_SPAN, UI_FORM_HIDDEN, UI_FORM_HINT, UI_FORM_LABEL_SINGULAR, UI_FORM_OPTIONS, UI_FORM_ORDER, UI_FORM_PLACEHOLDER, UI_FORM_PREFIX, UI_FORM_PREFIX_ICON, UI_FORM_PREFIX_REF, UI_FORM_STYLES, UI_FORM_SUBMIT_TEXT, UI_FORM_SUFFIX, UI_FORM_SUFFIX_ICON, UI_FORM_SUFFIX_REF, UI_FORM_TYPE, UI_FORM_VALIDATE, UI_TABLE_ATTR, UI_TABLE_CLASSES, UI_TABLE_COMPONENT, UI_TABLE_EXCLUDE, UI_TABLE_FN_ATTR, UI_TABLE_FN_CLASSES, UI_TABLE_FN_PREFIX, UI_TABLE_FN_STYLES, UI_TABLE_ORDER, UI_TABLE_SELECT_WITH, UI_TABLE_STYLES, UI_TABLE_TYPE, UI_TABLE_WIDTH, UI_TYPE, ValueHelpClient, WF_ACTION_WITH_DATA, applyFormChanges, asArray, buildDescendantErrorCounts, buildFormDiff, buildFormRebase, buildGridClasses, buildUnionVariants, collectDirtyPaths, createFieldValidator, createFormData, createFormDef, createFormValueResolver, createTableDef, deepClone, deepEqual, defaultResolver, deleteByPath, detectUnionVariant, enforceScale, extractLiteralOptions, extractMeasurement, extractValueHelp, formatDecimalForDisplay, getByPath, getColumn, getCurrencyDecimals, getCurrencyDisplayParts, getDecimalSeparator, getDeclaredFormActions, getDefaultClientFactory, getDefaultValidatorPlugins, getFieldMeta, getFilterableColumns, getFormValidator, getMetaEntry, getResolver, getSortableColumns, getThousandsSeparator, groupInteger, hasComputedAnnotations, isArrayField, isObjectField, isPathDirty, isPureLiteralUnion, isTupleField, isUnionField, iteratePathAncestors, joinDecimalString, mergeErrorMaps, optKey, optLabel, parseColSpan, parseDecimalInput, parseRowSpan, parseStaticAttrs, parseStaticOptions, resetDefaultClientFactory, resetMetaCache, resetValueHelpCache, resolveAttrs, resolveFieldProp, resolveFormProp, resolveGridSpec, resolveOptions, resolveSingularLabel, resolveStatic, resolveValueHelp, setByPath, setDefaultClientFactory, setDefaultValidatorPlugins, setResolver, splitDecimalString, str, unionVariantChanged, valueHelpDictPaths };
|
package/dist/plugin.cjs
CHANGED
|
@@ -344,8 +344,8 @@ const uiAnnotations = { ui: {
|
|
|
344
344
|
description: "Component name from the table components registry"
|
|
345
345
|
}
|
|
346
346
|
}),
|
|
347
|
-
|
|
348
|
-
description: "
|
|
347
|
+
exclude: new _atscript_core.AnnotationSpec({
|
|
348
|
+
description: "Completely removes this field from the table — not displayable, filterable, or sortable, and not shown in the config dialog. The field stays in the type and remains a valid `@ui.table.selectWith` target so its data can still be fetched for custom cells.",
|
|
349
349
|
nodeType: ["prop", "type"]
|
|
350
350
|
}),
|
|
351
351
|
attr: new _atscript_core.AnnotationSpec({
|
package/dist/plugin.mjs
CHANGED
|
@@ -344,8 +344,8 @@ const uiAnnotations = { ui: {
|
|
|
344
344
|
description: "Component name from the table components registry"
|
|
345
345
|
}
|
|
346
346
|
}),
|
|
347
|
-
|
|
348
|
-
description: "
|
|
347
|
+
exclude: new AnnotationSpec({
|
|
348
|
+
description: "Completely removes this field from the table — not displayable, filterable, or sortable, and not shown in the config dialog. The field stays in the type and remains a valid `@ui.table.selectWith` target so its data can still be fetched for custom cells.",
|
|
349
349
|
nodeType: ["prop", "type"]
|
|
350
350
|
}),
|
|
351
351
|
attr: new AnnotationSpec({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atscript/ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.104",
|
|
4
4
|
"description": "Framework-agnostic runtime for form and table definitions from atscript annotated types",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"annotations",
|
|
@@ -47,11 +47,11 @@
|
|
|
47
47
|
"access": "public"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@atscript/db-client": "^0.1.
|
|
50
|
+
"@atscript/db-client": "^0.1.108"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@atscript/core": "^0.1.77",
|
|
54
|
-
"@atscript/db": "^0.1.
|
|
54
|
+
"@atscript/db": "^0.1.108",
|
|
55
55
|
"@atscript/typescript": "^0.1.77",
|
|
56
56
|
"unplugin-atscript": "^0.1.77",
|
|
57
57
|
"vitest": "npm:@voidzero-dev/vite-plus-test@0.1.14"
|