attaform 0.31.0 → 0.31.1
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/abstract.d.mts +5 -5
- package/dist/abstract.mjs +4 -4
- package/dist/dev/abstract.mjs +4 -4
- package/dist/dev/chunks/devtools.mjs +1 -1
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +15 -2
- package/dist/dev/index.mjs +5 -5
- package/dist/dev/runtime/plugins/attaform.mjs +1 -1
- package/dist/dev/shared/{attaform-dev.zlvDr0WB.mjs → attaform-dev.04aupFBW.mjs} +3 -2
- package/dist/dev/shared/{attaform-dev.y9x9Vp9F.mjs → attaform-dev.3uTCYwy8.mjs} +572 -135
- package/dist/dev/shared/{attaform-dev.DJ3nsWw6.mjs → attaform-dev.BpVGFSFa.mjs} +18 -9
- package/dist/dev/shared/{attaform-dev.B1q-x9R9.mjs → attaform-dev.Bu6wgrA5.mjs} +1 -1
- package/dist/dev/shared/{attaform-dev.k5X47GMD.mjs → attaform-dev.Cbx0AiQF.mjs} +3 -2
- package/dist/dev/shared/attaform-dev.CwYTWyPX.mjs +120 -0
- package/dist/dev/shared/{attaform-dev.DlaT4xGd.mjs → attaform-dev.D7lKyM_7.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.CtyqGia7.mjs → attaform-dev.OceE0X3v.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.Caibt7sb.mjs → attaform-dev.PTGM9KE1.mjs} +6 -6
- package/dist/{shared/attaform.8mfKZCwH.mjs → dev/shared/attaform-dev.n6n00owJ.mjs} +49 -128
- package/dist/dev/zod-v3.mjs +6 -6
- package/dist/dev/zod-v4.mjs +6 -6
- package/dist/dev/zod.mjs +5 -5
- package/dist/directive.d.mts +2 -2
- package/dist/directive.mjs +1 -1
- package/dist/history.d.mts +1 -1
- package/dist/history.mjs +15 -2
- package/dist/index.d.mts +16 -55
- package/dist/index.mjs +5 -5
- package/dist/runtime/plugins/attaform.mjs +1 -1
- package/dist/shared/{attaform.BWUn8Kjy.mjs → attaform.B5b-HmhH.mjs} +18 -9
- package/dist/shared/{attaform.CRVe8s82.d.mts → attaform.B9PYKlhB.d.mts} +43 -19
- package/dist/shared/{attaform.DxKQsqFZ.mjs → attaform.BPMOl562.mjs} +3 -2
- package/dist/{dev/shared/attaform-dev.CZz4GYZ6.mjs → shared/attaform.BPSqtU7a.mjs} +44 -156
- package/dist/shared/{attaform.CdZIEf7_.mjs → attaform.BhtAZysa.mjs} +3 -2
- package/dist/shared/{attaform.DAo0QBmS.d.mts → attaform.CYlF4P6X.d.mts} +31 -10
- package/dist/shared/{attaform.C4shmwyJ.mjs → attaform.CdA9bfRv.mjs} +1 -1
- package/dist/shared/{attaform.DNPJPOO7.mjs → attaform.DAf4ehIe.mjs} +569 -134
- package/dist/shared/{attaform.D9RqPgGu.d.mts → attaform.DZOynI6c.d.mts} +1 -1
- package/dist/shared/{attaform.L011tHgJ.mjs → attaform.KEfNRDot.mjs} +4 -4
- package/dist/shared/attaform._1Zp3mDG.mjs +96 -0
- package/dist/shared/{attaform.DZnrDrNb.d.mts → attaform.i13OEHJF.d.mts} +60 -7
- package/dist/shared/{attaform.DL2nl_QR.mjs → attaform.j9xI_ObC.mjs} +6 -6
- package/dist/shared/{attaform.LUPC-2Qg.mjs → attaform.u6jfHoed.mjs} +4 -4
- package/dist/zod-v3.d.mts +4 -4
- package/dist/zod-v3.mjs +6 -6
- package/dist/zod-v4.d.mts +15 -11
- package/dist/zod-v4.mjs +6 -6
- package/dist/zod.d.mts +4 -4
- package/dist/zod.mjs +5 -5
- package/package.json +2 -1
- package/skills/attaform/SKILL.md +1 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { computed, readonly, toRaw, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, reactive, shallowReactive, shallowRef, toValue, watch, triggerRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, effectScope, onBeforeMount, onBeforeUpdate, onMounted, nextTick } from 'vue';
|
|
2
|
-
import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform.
|
|
3
|
-
import { c as armDomBinding, r as recordInheritedModifiers, w as withInheritedModifiers } from './attaform.
|
|
2
|
+
import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform.CdA9bfRv.mjs';
|
|
3
|
+
import { c as armDomBinding, r as recordInheritedModifiers, w as withInheritedModifiers } from './attaform.BPMOl562.mjs';
|
|
4
4
|
import { R as REGISTER_OWNER_MARKER, b as V_REGISTER_MARKER } from './attaform.KvlEedlF.mjs';
|
|
5
|
-
import { A as ANONYMOUS_FORM_KEY_PREFIX,
|
|
6
|
-
import { i as isPathPrefix,
|
|
5
|
+
import { A as ANONYMOUS_FORM_KEY_PREFIX, d as diffAndApply, i as isBarePatch, p as pickDefined, s as structuralSnapshot, n as normalizeNumericOption, a as DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS, b as isDescendable, c as applyChangedKeys, R as RESERVED_KEY_PREFIX, e as DEFAULT_MAX_RECURSION_DEPTH, f as ANONYMOUS_WIZARD_KEY_PREFIX } from './attaform.BPSqtU7a.mjs';
|
|
6
|
+
import { e as canonicalizePath, i as isPathPrefix, f as pathsEqual, k as keyForSegments, m as mapSegmentKeys, b as ROOT_PATH_KEY, s as segmentsForPathKey, S as SubmitErrorHandlerError, t as toError, j as groupErrorsByKey, n as normalizeErrorInput, h as SET_MEMBER_SEGMENT, R as ROOT_PATH, l as normalizeErrorInputs, a as InvalidUseFormConfigError, d as ReservedFormKeyError } from './attaform.BhtAZysa.mjs';
|
|
7
|
+
import { i as isShadowedKey, e as safeOwnHas, a as safeOwnRead, f as consumerHas, g as spreadConsumerRecord, h as copyConsumerArray, r as readConsumerIndex, s as safeAssign, c as consumerKeys, b as readConsumerProp, d as callConsumerFn, j as consumerSymbolKeys } from './attaform._1Zp3mDG.mjs';
|
|
7
8
|
|
|
8
9
|
const AttaformErrorCode = {
|
|
9
10
|
/** A required field is in the blank set: no value was supplied. */
|
|
@@ -142,7 +143,7 @@ function hashStableString(input, seed = 0) {
|
|
|
142
143
|
const ANON_STEM = "atta";
|
|
143
144
|
function readableFormKeyStem(formKey) {
|
|
144
145
|
if (formKey === "" || formKey.startsWith(ANONYMOUS_FORM_KEY_PREFIX)) return ANON_STEM;
|
|
145
|
-
const sanitized = formKey.replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|(
|
|
146
|
+
const sanitized = formKey.replace(/[^A-Za-z0-9_-]+/g, "-").replace(/^-+|([^-])-+$/g, "$1");
|
|
146
147
|
return sanitized === "" ? ANON_STEM : sanitized;
|
|
147
148
|
}
|
|
148
149
|
function fieldIdToken(formInstanceId, pathKey) {
|
|
@@ -646,6 +647,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
646
647
|
let asyncPending = false;
|
|
647
648
|
const submissionAttempts = state.submissionAttempts.value;
|
|
648
649
|
const blurredLeafSegments = [];
|
|
650
|
+
const errorsByKey = errorBucketsAt(state, segments, key);
|
|
649
651
|
const descendantLeaves = [];
|
|
650
652
|
visitActiveLeafPaths(value, segments, (leafSegments) => {
|
|
651
653
|
const { key: leafKey } = keyForSegments(leafSegments);
|
|
@@ -655,6 +657,8 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
655
657
|
});
|
|
656
658
|
for (const { key: leafKey, segments: leafSeg } of descendantLeaves) {
|
|
657
659
|
const leafRecord = state.fields.get(leafKey);
|
|
660
|
+
const leafErrors = errorsByKey.get(leafKey);
|
|
661
|
+
if (leafErrors !== void 0) leafErrors.walked = true;
|
|
658
662
|
if (!state.isPristineAtPathByKey(leafKey, leafSeg)) {
|
|
659
663
|
pristine = false;
|
|
660
664
|
dirty = true;
|
|
@@ -689,22 +693,28 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
689
693
|
if (updatedAt === null || ts > updatedAt) updatedAt = ts;
|
|
690
694
|
}
|
|
691
695
|
}
|
|
692
|
-
if (!dirty && state.
|
|
696
|
+
if (!dirty && !(Array.isArray(value) || isPlainRecord(value)) && !state.isPristineAtPathByKey(key, segments)) {
|
|
693
697
|
pristine = false;
|
|
694
698
|
dirty = true;
|
|
695
699
|
}
|
|
696
|
-
if (!dirty && state.
|
|
700
|
+
if (!dirty && state.hasStructuralChangeUnder(segments, key)) {
|
|
697
701
|
pristine = false;
|
|
698
702
|
dirty = true;
|
|
699
703
|
}
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
704
|
+
if (!dirty && state.hasRemovedSubtreeUnder(segments, key)) {
|
|
705
|
+
pristine = false;
|
|
706
|
+
dirty = true;
|
|
707
|
+
}
|
|
708
|
+
const errorBuckets = sortErrorBuckets(errorsByKey);
|
|
709
|
+
const errors = flattenErrorBuckets(errorBuckets);
|
|
710
|
+
const revealedDescendantError = errors.length > 0 && descendantErrorRevealed(
|
|
711
|
+
state,
|
|
712
|
+
segments,
|
|
713
|
+
errorBuckets,
|
|
714
|
+
submissionAttempts,
|
|
715
|
+
blurredAfterInteraction,
|
|
716
|
+
blurredLeafSegments
|
|
717
|
+
);
|
|
708
718
|
if (!asyncPending && state.pathHasAsyncValidationByKey(key, segments)) asyncPending = true;
|
|
709
719
|
if ((state.fieldValidationCounts.get(key) ?? 0) > 0) {
|
|
710
720
|
validating = true;
|
|
@@ -726,6 +736,8 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
726
736
|
if (ownRecord.interacted === true) interacted = true;
|
|
727
737
|
if (ownRecord.blurredAfterInteraction === true) blurredAfterInteraction = true;
|
|
728
738
|
if (ownRecord.connected === true) connected = true;
|
|
739
|
+
const ts = ownRecord.updatedAt;
|
|
740
|
+
if (ts !== null && (updatedAt === null || ts > updatedAt)) updatedAt = ts;
|
|
729
741
|
}
|
|
730
742
|
const ownTransformError = state.transformErrors.get(key) ?? null;
|
|
731
743
|
const gated = asyncPending && !state.firstValidationDone.value;
|
|
@@ -817,9 +829,41 @@ function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingS
|
|
|
817
829
|
firstOwnError
|
|
818
830
|
};
|
|
819
831
|
}
|
|
832
|
+
function descendantErrorRevealed(state, segments, buckets, submissionAttempts, blurredAfterInteraction, blurredLeafSegments) {
|
|
833
|
+
for (const bucket of buckets) {
|
|
834
|
+
let ownHistory;
|
|
835
|
+
for (const e of bucket.errors) {
|
|
836
|
+
const ePath = e.path;
|
|
837
|
+
if (pathsEqual(ePath, segments)) continue;
|
|
838
|
+
if (submissionAttempts > 0) return true;
|
|
839
|
+
if (ePath.length === 1 && ePath[0] === "") {
|
|
840
|
+
if (blurredAfterInteraction) return true;
|
|
841
|
+
continue;
|
|
842
|
+
}
|
|
843
|
+
for (const leaf of blurredLeafSegments) if (isPathPrefix(ePath, leaf)) return true;
|
|
844
|
+
if (bucket.walked) continue;
|
|
845
|
+
ownHistory ?? (ownHistory = state.fields.get(bucket.key)?.blurredAfterInteraction === true);
|
|
846
|
+
if (ownHistory) return true;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
return false;
|
|
850
|
+
}
|
|
820
851
|
function aggregateErrorsAt(state, prefix, prefixKey) {
|
|
852
|
+
return flattenErrorBuckets(sortErrorBuckets(errorBucketsAt(state, prefix, prefixKey)));
|
|
853
|
+
}
|
|
854
|
+
const NO_ERROR_BUCKETS = /* @__PURE__ */ new Map();
|
|
855
|
+
function sortErrorBuckets(buckets) {
|
|
856
|
+
if (buckets.size <= 1) return [...buckets.values()];
|
|
857
|
+
return [...buckets.values()].sort((a, b) => a.ordinal - b.ordinal);
|
|
858
|
+
}
|
|
859
|
+
function flattenErrorBuckets(buckets) {
|
|
860
|
+
if (buckets.length === 0) return [];
|
|
861
|
+
if (buckets.length === 1) return buckets[0]?.errors ?? [];
|
|
862
|
+
return buckets.flatMap((bucket) => bucket.errors);
|
|
863
|
+
}
|
|
864
|
+
function errorBucketsAt(state, prefix, prefixKey) {
|
|
821
865
|
const candidates = state.errorWindowAt(prefix, prefixKey);
|
|
822
|
-
if (candidates.length === 0) return
|
|
866
|
+
if (candidates.length === 0) return NO_ERROR_BUCKETS;
|
|
823
867
|
const formValue = state.form.value;
|
|
824
868
|
const cells = state.errorCells();
|
|
825
869
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -832,19 +876,16 @@ function aggregateErrorsAt(state, prefix, prefixKey) {
|
|
|
832
876
|
const userList = cell?.user;
|
|
833
877
|
const total = (schemaList?.length ?? 0) + (blankList?.length ?? 0) + (userList?.length ?? 0);
|
|
834
878
|
if (total === 0) continue;
|
|
835
|
-
|
|
836
|
-
let bucket = buckets.get(ordinal);
|
|
879
|
+
let bucket = buckets.get(key);
|
|
837
880
|
if (bucket === void 0) {
|
|
838
|
-
bucket = [];
|
|
839
|
-
buckets.set(
|
|
881
|
+
bucket = { key, ordinal: state.ensurePathOrdinal(key), errors: [], walked: false };
|
|
882
|
+
buckets.set(key, bucket);
|
|
840
883
|
}
|
|
841
|
-
if (schemaList !== void 0) bucket.push(...schemaList);
|
|
842
|
-
if (blankList !== void 0) bucket.push(...blankList);
|
|
843
|
-
if (userList !== void 0) bucket.push(...userList);
|
|
884
|
+
if (schemaList !== void 0) bucket.errors.push(...schemaList);
|
|
885
|
+
if (blankList !== void 0) bucket.errors.push(...blankList);
|
|
886
|
+
if (userList !== void 0) bucket.errors.push(...userList);
|
|
844
887
|
}
|
|
845
|
-
|
|
846
|
-
if (buckets.size === 1) return [...buckets.values()][0];
|
|
847
|
-
return [...buckets.entries()].sort(([a], [b]) => a - b).flatMap(([, errs]) => errs);
|
|
888
|
+
return buckets;
|
|
848
889
|
}
|
|
849
890
|
const EMPTY_ELEMENTS = Object.freeze([]);
|
|
850
891
|
|
|
@@ -876,7 +917,7 @@ function liveContainerHasKey(state, segments, key) {
|
|
|
876
917
|
return Number.isInteger(index) && index >= 0 && String(index) === key && value.has(index);
|
|
877
918
|
}
|
|
878
919
|
if (value instanceof Set) return false;
|
|
879
|
-
return
|
|
920
|
+
return safeOwnHas(value, key);
|
|
880
921
|
}
|
|
881
922
|
function isArrayPath(state, segments) {
|
|
882
923
|
if (segments.length === 0) return false;
|
|
@@ -1534,7 +1575,7 @@ function deleteKeysAtIndices(keys, del, arrayPath, indices) {
|
|
|
1534
1575
|
del(hit.key);
|
|
1535
1576
|
}
|
|
1536
1577
|
}
|
|
1537
|
-
function createArrayIdentity(getArrayLength) {
|
|
1578
|
+
function createArrayIdentity(getArrayLength, onChange) {
|
|
1538
1579
|
const tokens = /* @__PURE__ */ new Map();
|
|
1539
1580
|
const baselines = /* @__PURE__ */ new Map();
|
|
1540
1581
|
let counter = 0;
|
|
@@ -1546,7 +1587,13 @@ function createArrayIdentity(getArrayLength) {
|
|
|
1546
1587
|
ids = [];
|
|
1547
1588
|
tokens.set(arrayKey, ids);
|
|
1548
1589
|
}
|
|
1549
|
-
|
|
1590
|
+
if (ids.length < expectedLen) {
|
|
1591
|
+
const baseline = baselines.get(arrayKey);
|
|
1592
|
+
while (ids.length < expectedLen) {
|
|
1593
|
+
const anchored = baseline?.[ids.length];
|
|
1594
|
+
ids.push(anchored !== void 0 && !ids.includes(anchored) ? anchored : allocate());
|
|
1595
|
+
}
|
|
1596
|
+
}
|
|
1550
1597
|
if (ids.length > expectedLen) ids.length = expectedLen;
|
|
1551
1598
|
if (firstTrack) baselines.set(arrayKey, [...ids]);
|
|
1552
1599
|
return ids;
|
|
@@ -1572,15 +1619,39 @@ function createArrayIdentity(getArrayLength) {
|
|
|
1572
1619
|
const arrayKey = canonicalizePath(arraySegs).key;
|
|
1573
1620
|
const ids = ensure(arrayKey, remap.oldLen);
|
|
1574
1621
|
tokens.set(arrayKey, permuteList(ids, remap, allocate));
|
|
1622
|
+
onChange([arraySegs]);
|
|
1575
1623
|
},
|
|
1576
1624
|
applyRemap(arrayPath, remap) {
|
|
1577
1625
|
if (remap.moved.size === 0 && remap.vacated.size === 0 && remap.fresh.size === 0) return;
|
|
1578
|
-
|
|
1626
|
+
const moved = [];
|
|
1627
|
+
for (const hit of collectKeysAtIndices(tokens.keys(), arrayPath, remapAffects(remap))) {
|
|
1628
|
+
moved.push(hit.segments);
|
|
1629
|
+
}
|
|
1630
|
+
migrateMapSubtree(tokens, arrayPath, remap, (value, segments) => {
|
|
1631
|
+
moved.push(segments);
|
|
1632
|
+
return value;
|
|
1633
|
+
});
|
|
1579
1634
|
migrateMapSubtree(baselines, arrayPath, remap, (value) => value);
|
|
1635
|
+
if (moved.length > 0) onChange(moved);
|
|
1580
1636
|
},
|
|
1581
1637
|
realign(arraySegs) {
|
|
1582
1638
|
ensure(canonicalizePath(arraySegs).key, getArrayLength(arraySegs));
|
|
1583
1639
|
},
|
|
1640
|
+
realignContaining(paths) {
|
|
1641
|
+
if (tokens.size === 0 || paths.length === 0) return;
|
|
1642
|
+
const resized = [];
|
|
1643
|
+
for (const [arrayKey, ids] of tokens) {
|
|
1644
|
+
const segs = segmentsForPathKey(arrayKey);
|
|
1645
|
+
if (segs === null || !paths.some((path) => isPathPrefix(segs, path) || isPathPrefix(path, segs))) {
|
|
1646
|
+
continue;
|
|
1647
|
+
}
|
|
1648
|
+
const len = getArrayLength(segs);
|
|
1649
|
+
if (ids.length === len) continue;
|
|
1650
|
+
ensure(arrayKey, len);
|
|
1651
|
+
resized.push(segs);
|
|
1652
|
+
}
|
|
1653
|
+
if (resized.length > 0) onChange(resized);
|
|
1654
|
+
},
|
|
1584
1655
|
hasStructuralChangeUnder(prefix) {
|
|
1585
1656
|
for (const arrayKey of tokens.keys()) {
|
|
1586
1657
|
if (orderPristineForKey(arrayKey)) continue;
|
|
@@ -1591,15 +1662,39 @@ function createArrayIdentity(getArrayLength) {
|
|
|
1591
1662
|
return false;
|
|
1592
1663
|
},
|
|
1593
1664
|
rebaselineAll() {
|
|
1665
|
+
const rebased = [];
|
|
1594
1666
|
for (const arrayKey of [...tokens.keys()]) {
|
|
1595
1667
|
const segs = segmentsForPathKey(arrayKey);
|
|
1596
1668
|
if (segs === null) continue;
|
|
1597
1669
|
const ids = ensure(arrayKey, getArrayLength(segs));
|
|
1598
1670
|
baselines.set(arrayKey, [...ids]);
|
|
1671
|
+
rebased.push(segs);
|
|
1599
1672
|
}
|
|
1673
|
+
if (rebased.length > 0) onChange(rebased);
|
|
1674
|
+
},
|
|
1675
|
+
snapshot() {
|
|
1676
|
+
return { tokens: copyLists(tokens), baselines: copyLists(baselines) };
|
|
1677
|
+
},
|
|
1678
|
+
restore(orders) {
|
|
1679
|
+
const keys = /* @__PURE__ */ new Set([...tokens.keys(), ...orders.tokens.keys()]);
|
|
1680
|
+
tokens.clear();
|
|
1681
|
+
for (const [key, ids] of orders.tokens) tokens.set(key, [...ids]);
|
|
1682
|
+
baselines.clear();
|
|
1683
|
+
for (const [key, ids] of orders.baselines) baselines.set(key, [...ids]);
|
|
1684
|
+
const restored = [];
|
|
1685
|
+
for (const key of keys) {
|
|
1686
|
+
const segs = segmentsForPathKey(key);
|
|
1687
|
+
if (segs !== null) restored.push(segs);
|
|
1688
|
+
}
|
|
1689
|
+
if (restored.length > 0) onChange(restored);
|
|
1600
1690
|
}
|
|
1601
1691
|
};
|
|
1602
1692
|
}
|
|
1693
|
+
function copyLists(lists) {
|
|
1694
|
+
const out = /* @__PURE__ */ new Map();
|
|
1695
|
+
for (const [key, ids] of lists) out.set(key, [...ids]);
|
|
1696
|
+
return out;
|
|
1697
|
+
}
|
|
1603
1698
|
function createVariantMemory() {
|
|
1604
1699
|
const memory = /* @__PURE__ */ new Map();
|
|
1605
1700
|
return {
|
|
@@ -1666,6 +1761,8 @@ function createArrayBookkeeping(deps) {
|
|
|
1666
1761
|
blankPaths,
|
|
1667
1762
|
originalBlankPaths,
|
|
1668
1763
|
authoredPaths,
|
|
1764
|
+
removedPaths,
|
|
1765
|
+
notifyStructure,
|
|
1669
1766
|
fieldValidationCounts,
|
|
1670
1767
|
fieldValidatingSince,
|
|
1671
1768
|
fieldValidationState,
|
|
@@ -1673,10 +1770,35 @@ function createArrayBookkeeping(deps) {
|
|
|
1673
1770
|
arrayIdentity,
|
|
1674
1771
|
variantMemory,
|
|
1675
1772
|
touchFieldRecord,
|
|
1773
|
+
stampContainers,
|
|
1774
|
+
stampBareContainers,
|
|
1775
|
+
foldInteractionHistory,
|
|
1676
1776
|
decFieldValidation
|
|
1677
1777
|
} = deps;
|
|
1678
1778
|
function migrateElementState(arrayPath, remap) {
|
|
1679
1779
|
if (remap.moved.size === 0 && remap.vacated.size === 0) return;
|
|
1780
|
+
migrateSetSubtree(originalBlankPaths, arrayPath, remap);
|
|
1781
|
+
migrateSetSubtree(authoredPaths, arrayPath, remap);
|
|
1782
|
+
const removedMoved = [];
|
|
1783
|
+
for (const hit of collectKeysAtIndices(removedPaths.keys(), arrayPath, remapAffects(remap))) {
|
|
1784
|
+
removedMoved.push(hit.segments);
|
|
1785
|
+
}
|
|
1786
|
+
migrateMapSubtree(removedPaths, arrayPath, remap, (_, segments) => {
|
|
1787
|
+
removedMoved.push(segments);
|
|
1788
|
+
return segments;
|
|
1789
|
+
});
|
|
1790
|
+
if (remap.vacated.size > 0) {
|
|
1791
|
+
const released = [];
|
|
1792
|
+
for (const { key } of collectKeysAtIndices(
|
|
1793
|
+
fields.keys(),
|
|
1794
|
+
arrayPath,
|
|
1795
|
+
(index) => remap.vacated.has(index)
|
|
1796
|
+
)) {
|
|
1797
|
+
const record = fields.get(key);
|
|
1798
|
+
if (record !== void 0) released.push(record);
|
|
1799
|
+
}
|
|
1800
|
+
foldInteractionHistory(arrayPath, released);
|
|
1801
|
+
}
|
|
1680
1802
|
migrateMapSubtree(fields, arrayPath, remap, (record, segments) => ({
|
|
1681
1803
|
...record,
|
|
1682
1804
|
path: segments
|
|
@@ -1690,21 +1812,37 @@ function createArrayBookkeeping(deps) {
|
|
|
1690
1812
|
value: record.value
|
|
1691
1813
|
}));
|
|
1692
1814
|
migrateSetSubtree(blankPaths, arrayPath, remap);
|
|
1693
|
-
migrateSetSubtree(originalBlankPaths, arrayPath, remap);
|
|
1694
|
-
migrateSetSubtree(authoredPaths, arrayPath, remap);
|
|
1695
1815
|
migrateMapSubtree(fieldValidatingSince, arrayPath, remap, (since) => since);
|
|
1696
1816
|
migrateMapSubtree(fieldValidationCounts, arrayPath, remap, (count) => count);
|
|
1817
|
+
migrateMapSubtree(fieldValidationState, arrayPath, remap, (entry, segments) => {
|
|
1818
|
+
entry.key = keyForSegments(segments).key;
|
|
1819
|
+
entry.path = segments;
|
|
1820
|
+
return entry;
|
|
1821
|
+
});
|
|
1697
1822
|
arrayIdentity.applyRemap(arrayPath, remap);
|
|
1823
|
+
if (removedMoved.length > 0) notifyStructure(removedMoved);
|
|
1698
1824
|
}
|
|
1699
|
-
function seedFreshElement(arrayPath, freshIndex) {
|
|
1825
|
+
function seedFreshElement(arrayPath, freshIndex, now) {
|
|
1700
1826
|
const elementPath = [...arrayPath, freshIndex];
|
|
1701
|
-
const
|
|
1827
|
+
const patches = [];
|
|
1702
1828
|
diffAndApply(void 0, getAtPath(form.value, elementPath), elementPath, (patch) => {
|
|
1829
|
+
patches.push(patch);
|
|
1830
|
+
});
|
|
1831
|
+
const bare = [];
|
|
1832
|
+
patches.forEach((patch, index) => {
|
|
1703
1833
|
if (patch.kind !== "added") return;
|
|
1704
|
-
|
|
1834
|
+
if (isBarePatch(patch)) {
|
|
1835
|
+
bare.push(index);
|
|
1836
|
+
return;
|
|
1837
|
+
}
|
|
1838
|
+
const { key, segments } = canonicalizePath(patch.path);
|
|
1705
1839
|
if (!originals.has(key)) originals.set(key, { segments: patch.path, value: void 0 });
|
|
1706
|
-
touchFieldRecord(key,
|
|
1840
|
+
touchFieldRecord(key, segments, { updatedAt: now });
|
|
1707
1841
|
});
|
|
1842
|
+
if (bare.length > 0) stampBareContainers(patches, bare, now);
|
|
1843
|
+
else if (patches.length === 0 && hasAtPath(form.value, elementPath)) {
|
|
1844
|
+
stampContainers([elementPath], now);
|
|
1845
|
+
}
|
|
1708
1846
|
}
|
|
1709
1847
|
function abortValidationAtVacatedIndices(arrayPath, remap) {
|
|
1710
1848
|
if (remap.vacated.size === 0) return;
|
|
@@ -1718,21 +1856,22 @@ function createArrayBookkeeping(deps) {
|
|
|
1718
1856
|
if (entry === void 0) continue;
|
|
1719
1857
|
if (entry.timer !== null) {
|
|
1720
1858
|
clearTimeout(entry.timer);
|
|
1721
|
-
} else if (!entry.settled) {
|
|
1859
|
+
} else if (!entry.settled && !entry.released) {
|
|
1722
1860
|
activeValidations.value = Math.max(0, activeValidations.value - 1);
|
|
1723
1861
|
decFieldValidation(hit.key);
|
|
1862
|
+
entry.released = true;
|
|
1724
1863
|
}
|
|
1725
1864
|
entry.aborted = true;
|
|
1726
1865
|
fieldValidationState.delete(hit.key);
|
|
1727
1866
|
}
|
|
1728
1867
|
}
|
|
1729
1868
|
return {
|
|
1730
|
-
applyStructuralOp(arrayPath, remap) {
|
|
1869
|
+
applyStructuralOp(arrayPath, remap, now) {
|
|
1870
|
+
abortValidationAtVacatedIndices(arrayPath, remap);
|
|
1731
1871
|
migrateElementState(arrayPath, remap);
|
|
1732
|
-
for (const freshIndex of remap.fresh) seedFreshElement(arrayPath, freshIndex);
|
|
1872
|
+
for (const freshIndex of remap.fresh) seedFreshElement(arrayPath, freshIndex, now);
|
|
1733
1873
|
const changed = changedIndices(remap);
|
|
1734
1874
|
evictSchemaVerdictsAtIndices(errorCells(), arrayPath, changed);
|
|
1735
|
-
abortValidationAtVacatedIndices(arrayPath, remap);
|
|
1736
1875
|
variantMemory.dropAtIndices(arrayPath, changed);
|
|
1737
1876
|
arrayIdentity.applyOp(arrayPath, remap);
|
|
1738
1877
|
}
|
|
@@ -2461,12 +2600,12 @@ function isPrimitiveOrEmpty(value) {
|
|
|
2461
2600
|
return t === "string" || t === "number" || t === "boolean" || t === "bigint";
|
|
2462
2601
|
}
|
|
2463
2602
|
function isSlimNumericPrimitive(value) {
|
|
2464
|
-
return value === 0 || value ===
|
|
2603
|
+
return value === 0 || typeof value === "bigint" && !value;
|
|
2465
2604
|
}
|
|
2466
2605
|
function blankForKind(slimDefault) {
|
|
2467
2606
|
if (typeof slimDefault === "string") return "";
|
|
2468
2607
|
if (typeof slimDefault === "number") return 0;
|
|
2469
|
-
if (typeof slimDefault === "bigint") return
|
|
2608
|
+
if (typeof slimDefault === "bigint") return typeof BigInt === "function" ? BigInt(0) : void 0;
|
|
2470
2609
|
if (typeof slimDefault === "boolean") return false;
|
|
2471
2610
|
if (slimDefault === null) return null;
|
|
2472
2611
|
return void 0;
|
|
@@ -2835,7 +2974,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2835
2974
|
};
|
|
2836
2975
|
const metaTarget = buildMetaProxy(META_KEYS, (key) => {
|
|
2837
2976
|
if (key === "errorCount") return metaErrors.value.length;
|
|
2838
|
-
if (
|
|
2977
|
+
if (safeOwnHas(metaOwn, key)) return metaOwn[key];
|
|
2839
2978
|
return rootFieldState.value[key];
|
|
2840
2979
|
});
|
|
2841
2980
|
const formMeta = readonly(reactive(metaTarget));
|
|
@@ -2850,8 +2989,8 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2850
2989
|
);
|
|
2851
2990
|
state.reset(walked.cleanedValues);
|
|
2852
2991
|
for (const pathKey of walked.paths) {
|
|
2853
|
-
state.blankPaths.add(pathKey);
|
|
2854
2992
|
state.originalBlankPaths.add(pathKey);
|
|
2993
|
+
state.blankPaths.add(pathKey);
|
|
2855
2994
|
}
|
|
2856
2995
|
}
|
|
2857
2996
|
};
|
|
@@ -3304,16 +3443,15 @@ function appendHydrationFailedEntry(st, error) {
|
|
|
3304
3443
|
return entry;
|
|
3305
3444
|
}
|
|
3306
3445
|
|
|
3307
|
-
const isContainer = (value) => Array.isArray(value) || isPlainRecord(value);
|
|
3308
3446
|
function isHydratedFieldRecord(value) {
|
|
3309
3447
|
if (typeof value !== "object" || value === null) return false;
|
|
3310
3448
|
const r = value;
|
|
3311
3449
|
return Array.isArray(r.path) && (typeof r.updatedAt === "string" || r.updatedAt === null) && typeof r.connected === "boolean" && (typeof r.focused === "boolean" || r.focused === null) && (typeof r.blurred === "boolean" || r.blurred === null) && typeof r.touched === "boolean" && typeof r.interacted === "boolean" && typeof r.blurredAfterInteraction === "boolean";
|
|
3312
3450
|
}
|
|
3313
|
-
function withClearedHistoryFlags(record,
|
|
3451
|
+
function withClearedHistoryFlags(record, updatedAt) {
|
|
3314
3452
|
return {
|
|
3315
3453
|
path: record.path,
|
|
3316
|
-
updatedAt
|
|
3454
|
+
updatedAt,
|
|
3317
3455
|
connected: record.connected,
|
|
3318
3456
|
focused: record.focused,
|
|
3319
3457
|
blurred: record.blurred,
|
|
@@ -3428,14 +3566,27 @@ function initialFirstValidationGate(schema) {
|
|
|
3428
3566
|
return schema.needsAsyncValidation?.() !== true;
|
|
3429
3567
|
}
|
|
3430
3568
|
function seedOriginalsFromBaseline(st, baseline) {
|
|
3431
|
-
|
|
3569
|
+
const seeded = /* @__PURE__ */ new Map();
|
|
3432
3570
|
diffAndApply({}, baseline, [], (patch) => {
|
|
3433
|
-
if (patch.kind
|
|
3434
|
-
st.originals.set(canonicalizePath(patch.path).key, {
|
|
3435
|
-
segments: patch.path,
|
|
3436
|
-
value: patch.newValue
|
|
3437
|
-
});
|
|
3571
|
+
if (patch.kind === "added") seedBaseline(seeded, canonicalizePath(patch.path).key, patch);
|
|
3438
3572
|
});
|
|
3573
|
+
replaceOriginals(st, seeded);
|
|
3574
|
+
}
|
|
3575
|
+
function replaceOriginals(st, next) {
|
|
3576
|
+
for (const [key, entry] of next) st.originals.set(key, entry);
|
|
3577
|
+
for (const key of [...toRaw(st.originals).keys()]) {
|
|
3578
|
+
if (!next.has(key)) st.originals.delete(key);
|
|
3579
|
+
}
|
|
3580
|
+
}
|
|
3581
|
+
function seedBaseline(originals, key, patch) {
|
|
3582
|
+
const value = patch.newValue;
|
|
3583
|
+
if (!isDescendable(value)) {
|
|
3584
|
+
originals.set(key, { segments: patch.path, value });
|
|
3585
|
+
return false;
|
|
3586
|
+
}
|
|
3587
|
+
if (!(value instanceof Map))
|
|
3588
|
+
originals.set(key, { segments: patch.path, value: Array.isArray(value) ? [] : {} });
|
|
3589
|
+
return true;
|
|
3439
3590
|
}
|
|
3440
3591
|
function queueInitialAsyncValidation(st) {
|
|
3441
3592
|
if (!st.ssr && st.schema.needsAsyncValidation?.() === true) {
|
|
@@ -3597,8 +3748,18 @@ function settleTransforms(st, path) {
|
|
|
3597
3748
|
st.transformWaiters.push({ key, resolve });
|
|
3598
3749
|
});
|
|
3599
3750
|
}
|
|
3751
|
+
function writeInstant(st) {
|
|
3752
|
+
const clock = (/* @__PURE__ */ new Date()).toISOString();
|
|
3753
|
+
if (clock > st.latestStamp) return clock;
|
|
3754
|
+
const after = new Date(new Date(st.latestStamp).getTime() + 1);
|
|
3755
|
+
return Number.isFinite(after.getTime()) ? after.toISOString() : clock;
|
|
3756
|
+
}
|
|
3757
|
+
function noteStamp(st, stamp) {
|
|
3758
|
+
if (stamp !== null && stamp > st.latestStamp) st.latestStamp = stamp;
|
|
3759
|
+
}
|
|
3600
3760
|
function touchFieldRecord(st, pathKey, path, patch) {
|
|
3601
3761
|
const current = st.fields.get(pathKey);
|
|
3762
|
+
if (patch.updatedAt !== void 0) noteStamp(st, patch.updatedAt);
|
|
3602
3763
|
st.fields.set(pathKey, {
|
|
3603
3764
|
path,
|
|
3604
3765
|
updatedAt: patch.updatedAt ?? current?.updatedAt ?? null,
|
|
@@ -3617,19 +3778,188 @@ function touchFieldRecord(st, pathKey, path, patch) {
|
|
|
3617
3778
|
blurredAfterInteraction: patch.blurredAfterInteraction ?? current?.blurredAfterInteraction ?? false
|
|
3618
3779
|
});
|
|
3619
3780
|
}
|
|
3620
|
-
function
|
|
3621
|
-
|
|
3781
|
+
function stampContainers(st, containers, now) {
|
|
3782
|
+
eachAncestorOnce(containers, (key, segments) => raiseStamp(st, key, segments, now));
|
|
3783
|
+
}
|
|
3784
|
+
function raiseStamp(st, key, segments, stamp) {
|
|
3785
|
+
if ((st.fields.get(key)?.updatedAt ?? "") < stamp) {
|
|
3786
|
+
touchFieldRecord(st, key, segments, { updatedAt: stamp });
|
|
3787
|
+
}
|
|
3788
|
+
}
|
|
3789
|
+
function holdRemovedStamps(st, patches, next) {
|
|
3790
|
+
const held = /* @__PURE__ */ new Map();
|
|
3791
|
+
const hold = (path, depth, leaf) => noteHold(st, held, next, path, depth, leaf);
|
|
3622
3792
|
for (const patch of patches) {
|
|
3623
|
-
|
|
3624
|
-
|
|
3793
|
+
if (patch.kind === "added") continue;
|
|
3794
|
+
const { oldValue, path } = patch;
|
|
3795
|
+
if (Array.isArray(oldValue) || isPlainRecord(oldValue)) {
|
|
3796
|
+
if (patch.kind === "changed") {
|
|
3797
|
+
visitActiveLeafPaths(oldValue, path, (leaf) => hold(path, path.length, leaf));
|
|
3798
|
+
}
|
|
3799
|
+
} else if (patch.kind === "removed" ? !hasAtPath(next, path) : Array.isArray(patch.newValue) || isPlainRecord(patch.newValue)) {
|
|
3800
|
+
hold(path, path.length - 1, path);
|
|
3801
|
+
}
|
|
3802
|
+
}
|
|
3803
|
+
applyHolds(st, held);
|
|
3804
|
+
}
|
|
3805
|
+
function noteHold(st, held, next, path, depth, leaf) {
|
|
3806
|
+
const { key: leafKey } = keyForSegments(leaf);
|
|
3807
|
+
const stamp = toRaw(st.originals).has(leafKey) ? toRaw(st.fields).get(leafKey)?.updatedAt : null;
|
|
3808
|
+
if (stamp === null || stamp === void 0) return;
|
|
3809
|
+
let kept = false;
|
|
3810
|
+
for (let at = depth; at >= 0; at--) {
|
|
3811
|
+
const segments = path.slice(0, at);
|
|
3812
|
+
if (!kept && !hasAtPath(next, segments)) continue;
|
|
3813
|
+
kept = true;
|
|
3814
|
+
const { key } = keyForSegments(segments);
|
|
3815
|
+
const current = held.get(key);
|
|
3816
|
+
if (current === void 0) held.set(key, { segments, stamp });
|
|
3817
|
+
else if (stamp > current.stamp) current.stamp = stamp;
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
function applyHolds(st, held) {
|
|
3821
|
+
for (const [key, { segments, stamp }] of held) raiseStamp(st, key, segments, stamp);
|
|
3822
|
+
}
|
|
3823
|
+
function stampBareContainers(st, patches, bare, now) {
|
|
3824
|
+
for (const index of bare) {
|
|
3825
|
+
const path = patches[index]?.path ?? [];
|
|
3826
|
+
for (let depth = path.length; depth >= 0; depth--) {
|
|
3827
|
+
const container = path.slice(0, depth);
|
|
3828
|
+
if (depth < path.length && reachedBesides(patches, index, container)) break;
|
|
3829
|
+
const { key, segments } = keyForSegments(container);
|
|
3830
|
+
raiseStamp(st, key, segments, now);
|
|
3831
|
+
}
|
|
3832
|
+
}
|
|
3833
|
+
}
|
|
3834
|
+
function reachedBesides(patches, index, container) {
|
|
3835
|
+
for (const step of [-1, 1]) {
|
|
3836
|
+
for (let i = index + step; ; i += step) {
|
|
3837
|
+
const patch = patches[i];
|
|
3838
|
+
if (patch === void 0 || !isPathPrefix(container, patch.path)) break;
|
|
3839
|
+
if (!isBarePatch(patch)) return true;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
return false;
|
|
3843
|
+
}
|
|
3844
|
+
function eachAncestorOnce(paths, visit) {
|
|
3845
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3846
|
+
for (const path of paths) {
|
|
3847
|
+
for (let depth = path.length; depth >= 0; depth--) {
|
|
3848
|
+
const { key, segments } = keyForSegments(path.slice(0, depth));
|
|
3849
|
+
if (seen.has(key)) break;
|
|
3850
|
+
seen.add(key);
|
|
3851
|
+
visit(key, segments);
|
|
3852
|
+
}
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
function foldInteractionHistory(st, path, released) {
|
|
3856
|
+
let touched = false;
|
|
3857
|
+
let interacted = false;
|
|
3858
|
+
let blurredAfterInteraction = false;
|
|
3859
|
+
for (const record of released) {
|
|
3860
|
+
touched || (touched = record.touched);
|
|
3861
|
+
interacted || (interacted = record.interacted);
|
|
3862
|
+
blurredAfterInteraction || (blurredAfterInteraction = record.blurredAfterInteraction);
|
|
3863
|
+
}
|
|
3864
|
+
if (!touched && !interacted && !blurredAfterInteraction) return;
|
|
3865
|
+
for (let depth = path.length; depth >= 0; depth--) {
|
|
3866
|
+
const { key, segments } = keyForSegments(path.slice(0, depth));
|
|
3867
|
+
const current = st.fields.get(key);
|
|
3868
|
+
touchFieldRecord(st, key, segments, {
|
|
3869
|
+
touched: touched || current?.touched === true,
|
|
3870
|
+
interacted: interacted || current?.interacted === true,
|
|
3871
|
+
blurredAfterInteraction: blurredAfterInteraction || current?.blurredAfterInteraction === true
|
|
3872
|
+
});
|
|
3873
|
+
}
|
|
3874
|
+
}
|
|
3875
|
+
function releaseRemovedRecords(st, segments, raw) {
|
|
3876
|
+
const released = [];
|
|
3877
|
+
let depth = segments.length;
|
|
3878
|
+
do {
|
|
3879
|
+
const { key } = keyForSegments(segments.slice(0, depth));
|
|
3880
|
+
abortValidationAt(st, key);
|
|
3881
|
+
const record = st.fields.get(key);
|
|
3882
|
+
if (record !== void 0) {
|
|
3883
|
+
released.push(record);
|
|
3884
|
+
if (record.connected) st.fields.set(key, withClearedHistoryFlags(record, null));
|
|
3885
|
+
else st.fields.delete(key);
|
|
3886
|
+
}
|
|
3887
|
+
depth--;
|
|
3888
|
+
} while (depth > 0 && !hasAtPath(raw, segments.slice(0, depth)));
|
|
3889
|
+
const present = segments.slice(0, depth);
|
|
3890
|
+
foldInteractionHistory(st, present, released);
|
|
3891
|
+
return present;
|
|
3892
|
+
}
|
|
3893
|
+
function noteRemovedBaseline(st, key, segments, notify) {
|
|
3894
|
+
if (st.originals.get(key)?.value === void 0) return;
|
|
3895
|
+
st.removedPaths.set(key, segments);
|
|
3896
|
+
notify.push(segments);
|
|
3897
|
+
}
|
|
3898
|
+
function trackForSweep(st, path, key) {
|
|
3899
|
+
st.pathSweep.track(path, key);
|
|
3900
|
+
for (let i = 1; i < path.length; i++) {
|
|
3901
|
+
const ancestor = path.slice(0, i);
|
|
3902
|
+
st.pathSweep.track(ancestor, canonicalizePath(ancestor).key);
|
|
3903
|
+
}
|
|
3904
|
+
}
|
|
3905
|
+
function commitWritePatches(st, patches, meta, structuralOp, now) {
|
|
3906
|
+
const arrayOpPath = structuralOp?.path;
|
|
3907
|
+
const reshaped = [];
|
|
3908
|
+
const removed = [];
|
|
3909
|
+
const resizing = [];
|
|
3910
|
+
const raw = toRaw(st.form.value);
|
|
3911
|
+
const bareAt = [];
|
|
3912
|
+
for (const [index, patch] of patches.entries()) {
|
|
3913
|
+
const { key, segments } = canonicalizePath(patch.path);
|
|
3914
|
+
const bare = isBarePatch(patch);
|
|
3915
|
+
if (!bare && !st.originals.has(key)) {
|
|
3625
3916
|
st.originals.set(key, { segments: patch.path, value: void 0 });
|
|
3626
3917
|
}
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3918
|
+
const positional = arrayOpPath !== void 0 && segments.length > arrayOpPath.length && isPathPrefix(arrayOpPath, segments);
|
|
3919
|
+
if (structuralOp === null && (patch.kind !== "changed" || typeof patch.oldValue === "object" || typeof patch.newValue === "object")) {
|
|
3920
|
+
resizing.push(segments);
|
|
3921
|
+
}
|
|
3922
|
+
if (!positional) {
|
|
3923
|
+
if (patch.kind === "removed" && !hasAtPath(raw, segments)) {
|
|
3924
|
+
reshaped.push(releaseRemovedRecords(st, segments, raw));
|
|
3925
|
+
noteRemovedBaseline(st, key, segments, removed);
|
|
3926
|
+
} else {
|
|
3927
|
+
touchFieldRecord(st, key, segments, { updatedAt: now });
|
|
3928
|
+
if (bare) bareAt.push(index);
|
|
3929
|
+
if (patch.kind === "changed" && typeof patch.oldValue === "object" && patch.oldValue !== null) {
|
|
3930
|
+
diffAndApply(patch.oldValue, void 0, segments, (gone) => {
|
|
3931
|
+
if (!hasAtPath(raw, gone.path)) {
|
|
3932
|
+
reshaped.push(releaseRemovedRecords(st, gone.path, raw));
|
|
3933
|
+
const goneAt = canonicalizePath(gone.path);
|
|
3934
|
+
noteRemovedBaseline(st, goneAt.key, goneAt.segments, removed);
|
|
3935
|
+
}
|
|
3936
|
+
});
|
|
3937
|
+
}
|
|
3938
|
+
if (patch.kind === "changed" && isDescendable(patch.newValue)) {
|
|
3939
|
+
diffAndApply(void 0, patch.newValue, segments, (fresh) => {
|
|
3940
|
+
const at = canonicalizePath(fresh.path);
|
|
3941
|
+
trackForSweep(st, fresh.path, at.key);
|
|
3942
|
+
if (fresh.kind === "added" && isDescendable(fresh.newValue)) {
|
|
3943
|
+
reshaped.push(at.segments);
|
|
3944
|
+
return;
|
|
3945
|
+
}
|
|
3946
|
+
if (!st.originals.has(at.key)) {
|
|
3947
|
+
st.originals.set(at.key, { segments: fresh.path, value: void 0 });
|
|
3948
|
+
}
|
|
3949
|
+
touchFieldRecord(st, at.key, at.segments, { updatedAt: now });
|
|
3950
|
+
});
|
|
3951
|
+
}
|
|
3952
|
+
}
|
|
3632
3953
|
}
|
|
3954
|
+
trackForSweep(st, patch.path, key);
|
|
3955
|
+
}
|
|
3956
|
+
if (arrayOpPath !== void 0 && patches.length > 0) reshaped.push(arrayOpPath);
|
|
3957
|
+
if (reshaped.length > 0) stampContainers(st, reshaped, now);
|
|
3958
|
+
if (bareAt.length > 0) stampBareContainers(st, patches, bareAt, now);
|
|
3959
|
+
if (removed.length > 0) pulseStructure(st.structureSignal, removed);
|
|
3960
|
+
if (resizing.length > 0) st.arrayIdentity.realignContaining(resizing);
|
|
3961
|
+
if (structuralOp !== null) {
|
|
3962
|
+
st.arrayBookkeeping.applyStructuralOp(structuralOp.path, structuralOp.remap, now);
|
|
3633
3963
|
}
|
|
3634
3964
|
for (const listener of st.formChangeListeners) {
|
|
3635
3965
|
try {
|
|
@@ -3639,33 +3969,39 @@ function commitWritePatches(st, patches, meta) {
|
|
|
3639
3969
|
}
|
|
3640
3970
|
}
|
|
3641
3971
|
}
|
|
3642
|
-
function applyFormReplacementWithPath(st, next, meta,
|
|
3972
|
+
function applyFormReplacementWithPath(st, next, meta, structuralOp, now) {
|
|
3643
3973
|
const prev = st.form.value;
|
|
3644
3974
|
if (Object.is(prev, next)) return;
|
|
3645
3975
|
const patches = [];
|
|
3646
3976
|
diffAndApply(prev, next, [], (patch) => {
|
|
3647
3977
|
patches.push(patch);
|
|
3648
3978
|
});
|
|
3649
|
-
|
|
3979
|
+
holdRemovedStamps(st, patches, next);
|
|
3980
|
+
const reconciled = callConsumerFn(
|
|
3981
|
+
() => applyChangedKeys(prev, next, structuralOp?.path ?? null, [], patches),
|
|
3982
|
+
null);
|
|
3983
|
+
if (reconciled === null) return;
|
|
3984
|
+
if (!reconciled) {
|
|
3650
3985
|
st.form.value = next;
|
|
3651
3986
|
} else if (patches.some(
|
|
3652
3987
|
(p) => p.path.length > 0 && typeof p.path[0] === "string" && isShadowedKey(p.path[0])
|
|
3653
3988
|
)) {
|
|
3654
3989
|
triggerRef(st.form);
|
|
3655
3990
|
}
|
|
3656
|
-
commitWritePatches(st, patches, meta);
|
|
3991
|
+
commitWritePatches(st, patches, meta, structuralOp, now);
|
|
3657
3992
|
}
|
|
3658
3993
|
function applyFormReplacement(st, next, meta) {
|
|
3659
|
-
applyFormReplacementWithPath(st, next, meta, null);
|
|
3994
|
+
applyFormReplacementWithPath(st, next, meta, null, writeInstant(st));
|
|
3660
3995
|
}
|
|
3661
|
-
function applyTargetedWrite(st, path, completedValue, meta) {
|
|
3996
|
+
function applyTargetedWrite(st, path, completedValue, meta, structuralOp, now) {
|
|
3662
3997
|
const result = tryInPlaceLeafWrite(st.form.value, path, completedValue);
|
|
3663
3998
|
if (!result.applied) {
|
|
3664
3999
|
applyFormReplacementWithPath(
|
|
3665
4000
|
st,
|
|
3666
4001
|
setAtPathWithSchemaFill(st.form.value, st.schema, path, completedValue),
|
|
3667
4002
|
meta,
|
|
3668
|
-
|
|
4003
|
+
structuralOp,
|
|
4004
|
+
now
|
|
3669
4005
|
);
|
|
3670
4006
|
return;
|
|
3671
4007
|
}
|
|
@@ -3673,9 +4009,9 @@ function applyTargetedWrite(st, path, completedValue, meta) {
|
|
|
3673
4009
|
diffAndApply(result.old, completedValue, path, (patch) => {
|
|
3674
4010
|
patches.push(patch);
|
|
3675
4011
|
});
|
|
3676
|
-
commitWritePatches(st, patches, meta);
|
|
4012
|
+
commitWritePatches(st, patches, meta, null, now);
|
|
3677
4013
|
}
|
|
3678
|
-
function setValueAtPath(st, path, value, meta) {
|
|
4014
|
+
function setValueAtPath(st, path, value, meta, writeStamp) {
|
|
3679
4015
|
if (st.effectiveDisabled.value) {
|
|
3680
4016
|
return false;
|
|
3681
4017
|
}
|
|
@@ -3748,7 +4084,8 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3748
4084
|
value,
|
|
3749
4085
|
variantDefault,
|
|
3750
4086
|
void 0,
|
|
3751
|
-
meta
|
|
4087
|
+
meta,
|
|
4088
|
+
writeStamp
|
|
3752
4089
|
);
|
|
3753
4090
|
}
|
|
3754
4091
|
return reshapeUnionVariant(
|
|
@@ -3758,7 +4095,8 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3758
4095
|
value,
|
|
3759
4096
|
{ [last]: value },
|
|
3760
4097
|
void 0,
|
|
3761
|
-
meta
|
|
4098
|
+
meta,
|
|
4099
|
+
writeStamp
|
|
3762
4100
|
);
|
|
3763
4101
|
}
|
|
3764
4102
|
}
|
|
@@ -3782,7 +4120,8 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3782
4120
|
discValue,
|
|
3783
4121
|
variantDefault,
|
|
3784
4122
|
valueRecord,
|
|
3785
|
-
meta
|
|
4123
|
+
meta,
|
|
4124
|
+
writeStamp
|
|
3786
4125
|
);
|
|
3787
4126
|
}
|
|
3788
4127
|
return reshapeUnionVariant(
|
|
@@ -3792,10 +4131,20 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3792
4131
|
discValue,
|
|
3793
4132
|
{ [discKey]: discValue },
|
|
3794
4133
|
void 0,
|
|
3795
|
-
meta
|
|
4134
|
+
meta,
|
|
4135
|
+
writeStamp
|
|
3796
4136
|
);
|
|
3797
4137
|
}
|
|
3798
|
-
return reshapeUnionVariant(
|
|
4138
|
+
return reshapeUnionVariant(
|
|
4139
|
+
st,
|
|
4140
|
+
path,
|
|
4141
|
+
oldDiscValue,
|
|
4142
|
+
void 0,
|
|
4143
|
+
{},
|
|
4144
|
+
void 0,
|
|
4145
|
+
meta,
|
|
4146
|
+
writeStamp
|
|
4147
|
+
);
|
|
3799
4148
|
}
|
|
3800
4149
|
}
|
|
3801
4150
|
}
|
|
@@ -3845,16 +4194,17 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3845
4194
|
if (arrayOpRemap === null && Array.isArray(value) && Array.isArray(currentValue)) {
|
|
3846
4195
|
st.arrayIdentity.realign(path);
|
|
3847
4196
|
}
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
st
|
|
3851
|
-
|
|
4197
|
+
const now = writeStamp ?? writeInstant(st);
|
|
4198
|
+
applyTargetedWrite(
|
|
4199
|
+
st,
|
|
4200
|
+
path,
|
|
4201
|
+
completedValue,
|
|
4202
|
+
meta,
|
|
4203
|
+
arrayOpRemap !== null ? { path, remap: arrayOpRemap } : null,
|
|
4204
|
+
now
|
|
4205
|
+
);
|
|
4206
|
+
if (arrayOpRemap === null && Array.isArray(value) && Array.isArray(currentValue)) {
|
|
3852
4207
|
st.variantMemory.clearUnderPath(path);
|
|
3853
|
-
st.arrayIdentity.realign(path);
|
|
3854
|
-
} else if (isContainer(currentValue) && !isContainer(value)) {
|
|
3855
|
-
if (subtreeHadRealBaseline(st, path, currentValue)) {
|
|
3856
|
-
st.removedSubtrees.add(pathKey);
|
|
3857
|
-
}
|
|
3858
4208
|
}
|
|
3859
4209
|
const effectiveModeAfterWrite = meta?.instance?.validateOn ?? st.fieldValidationMode;
|
|
3860
4210
|
if (effectiveModeAfterWrite === "change") {
|
|
@@ -3862,7 +4212,7 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3862
4212
|
}
|
|
3863
4213
|
return true;
|
|
3864
4214
|
}
|
|
3865
|
-
function reshapeUnionVariant(st, parentPath, oldDiscValue, newDiscValue, variantDefault, consumerOverrides, meta) {
|
|
4215
|
+
function reshapeUnionVariant(st, parentPath, oldDiscValue, newDiscValue, variantDefault, consumerOverrides, meta, writeStamp) {
|
|
3866
4216
|
const sameDisc = Object.is(oldDiscValue, newDiscValue);
|
|
3867
4217
|
const parentKey = canonicalizePath(parentPath).key;
|
|
3868
4218
|
let baseline = variantDefault;
|
|
@@ -3928,7 +4278,7 @@ function reshapeUnionVariant(st, parentPath, oldDiscValue, newDiscValue, variant
|
|
|
3928
4278
|
appliedSync = true;
|
|
3929
4279
|
}
|
|
3930
4280
|
}
|
|
3931
|
-
|
|
4281
|
+
applyFormReplacementWithPath(st, nextForm, meta, null, writeStamp ?? writeInstant(st));
|
|
3932
4282
|
for (const k of newBlankPaths) st.blankPaths.add(k);
|
|
3933
4283
|
if (reshapeMode === "change" && !appliedSync) {
|
|
3934
4284
|
scheduleFieldValidation(st, parentPath, false, meta?.instance);
|
|
@@ -3949,7 +4299,9 @@ function scheduleFieldValidation(st, path, immediate, instance) {
|
|
|
3949
4299
|
aborted: false,
|
|
3950
4300
|
timer: null,
|
|
3951
4301
|
settled: false,
|
|
3952
|
-
released: false
|
|
4302
|
+
released: false,
|
|
4303
|
+
key,
|
|
4304
|
+
path
|
|
3953
4305
|
};
|
|
3954
4306
|
st.fieldValidationState.set(key, fresh);
|
|
3955
4307
|
const myEpoch = ++st.scheduleEpoch;
|
|
@@ -3960,19 +4312,20 @@ function scheduleFieldValidation(st, path, immediate, instance) {
|
|
|
3960
4312
|
try {
|
|
3961
4313
|
st.activeValidations.value += 1;
|
|
3962
4314
|
activeIncremented = true;
|
|
3963
|
-
incFieldValidation(st, key);
|
|
4315
|
+
incFieldValidation(st, fresh.key);
|
|
3964
4316
|
} catch (err) {
|
|
3965
4317
|
if (activeIncremented) {
|
|
3966
4318
|
st.activeValidations.value = Math.max(0, st.activeValidations.value - 1);
|
|
3967
4319
|
}
|
|
3968
4320
|
throw err;
|
|
3969
4321
|
}
|
|
3970
|
-
const
|
|
3971
|
-
const
|
|
3972
|
-
const dataAtScope = subtreeScope ? getAtPath(st.form.value,
|
|
3973
|
-
|
|
3974
|
-
void Promise.resolve().then(() => st.schema.validateAtPath(dataAtScope, scopePath)).then((response) => {
|
|
4322
|
+
const startPath = fresh.path;
|
|
4323
|
+
const subtreeScope = startPath.length > 0 && st.schema.hasContainerOrRootRefine?.() === false;
|
|
4324
|
+
const dataAtScope = subtreeScope ? getAtPath(st.form.value, startPath) : st.form.value;
|
|
4325
|
+
void Promise.resolve().then(() => st.schema.validateAtPath(dataAtScope, subtreeScope ? startPath : void 0)).then((response) => {
|
|
3975
4326
|
if (fresh.aborted) return;
|
|
4327
|
+
const scopePath = subtreeScope ? fresh.path : void 0;
|
|
4328
|
+
const scopeKey = subtreeScope ? fresh.key : ROOT_PATH_KEY;
|
|
3976
4329
|
if (myEpoch <= st.lastCommittedEpoch) return;
|
|
3977
4330
|
st.lastCommittedEpoch = myEpoch;
|
|
3978
4331
|
if (effectiveMode === "blur") {
|
|
@@ -3983,14 +4336,14 @@ function scheduleFieldValidation(st, path, immediate, instance) {
|
|
|
3983
4336
|
const filtered = filterAuthoredErrors(st, errors);
|
|
3984
4337
|
const restamped = subtreeScope ? filtered.map((err) => ({
|
|
3985
4338
|
...err,
|
|
3986
|
-
path: [...
|
|
4339
|
+
path: [...scopePath ?? [], ...err.path]
|
|
3987
4340
|
})) : filtered;
|
|
3988
4341
|
applySchemaErrorsForSubtree(st, scopePath ?? [], restamped);
|
|
3989
4342
|
}).catch(() => {
|
|
3990
4343
|
}).finally(() => {
|
|
3991
4344
|
if (!fresh.released) {
|
|
3992
4345
|
st.activeValidations.value = Math.max(0, st.activeValidations.value - 1);
|
|
3993
|
-
decFieldValidation(st, key);
|
|
4346
|
+
decFieldValidation(st, fresh.key);
|
|
3994
4347
|
}
|
|
3995
4348
|
fresh.settled = true;
|
|
3996
4349
|
});
|
|
@@ -4029,6 +4382,19 @@ function cancelFieldValidationUnder(st, prefix) {
|
|
|
4029
4382
|
st.fieldValidationState.delete(key);
|
|
4030
4383
|
}
|
|
4031
4384
|
}
|
|
4385
|
+
function abortValidationAt(st, key) {
|
|
4386
|
+
const entry = st.fieldValidationState.get(key);
|
|
4387
|
+
if (entry === void 0) return;
|
|
4388
|
+
if (entry.timer !== null) {
|
|
4389
|
+
clearTimeout(entry.timer);
|
|
4390
|
+
} else if (!entry.settled && !entry.released) {
|
|
4391
|
+
st.activeValidations.value = Math.max(0, st.activeValidations.value - 1);
|
|
4392
|
+
decFieldValidation(st, key);
|
|
4393
|
+
entry.released = true;
|
|
4394
|
+
}
|
|
4395
|
+
entry.aborted = true;
|
|
4396
|
+
st.fieldValidationState.delete(key);
|
|
4397
|
+
}
|
|
4032
4398
|
function onFormChange(st, listener) {
|
|
4033
4399
|
st.formChangeListeners.add(listener);
|
|
4034
4400
|
return () => {
|
|
@@ -4156,6 +4522,36 @@ function restoreErrorCells(st, entries) {
|
|
|
4156
4522
|
st.errorCells().set(key, { schema: [...cell.schema], user: [...cell.user] });
|
|
4157
4523
|
}
|
|
4158
4524
|
}
|
|
4525
|
+
function captureStructure(st) {
|
|
4526
|
+
return {
|
|
4527
|
+
identity: st.arrayIdentity.snapshot(),
|
|
4528
|
+
originals: [...toRaw(st.originals)],
|
|
4529
|
+
originalBlank: [...st.originalBlankPaths],
|
|
4530
|
+
removed: [...st.removedPaths]
|
|
4531
|
+
};
|
|
4532
|
+
}
|
|
4533
|
+
function restoreStructure(st, snapshot) {
|
|
4534
|
+
const originals = new Map(snapshot.originals);
|
|
4535
|
+
const raw = toRaw(st.form.value);
|
|
4536
|
+
const held = /* @__PURE__ */ new Map();
|
|
4537
|
+
for (const [key, { segments }] of toRaw(st.originals)) {
|
|
4538
|
+
if (!originals.has(key) && hasAtPath(raw, segments)) {
|
|
4539
|
+
noteHold(st, held, raw, segments, segments.length - 1, segments);
|
|
4540
|
+
}
|
|
4541
|
+
}
|
|
4542
|
+
applyHolds(st, held);
|
|
4543
|
+
st.arrayIdentity.restore(snapshot.identity);
|
|
4544
|
+
replaceOriginals(st, originals);
|
|
4545
|
+
st.originalBlankPaths.clear();
|
|
4546
|
+
for (const key of snapshot.originalBlank) st.originalBlankPaths.add(key);
|
|
4547
|
+
const pulsed = [...st.removedPaths.values()];
|
|
4548
|
+
st.removedPaths.clear();
|
|
4549
|
+
for (const [key, segments] of snapshot.removed) {
|
|
4550
|
+
st.removedPaths.set(key, segments);
|
|
4551
|
+
pulsed.push(segments);
|
|
4552
|
+
}
|
|
4553
|
+
if (pulsed.length > 0) pulseStructure(st.structureSignal, pulsed);
|
|
4554
|
+
}
|
|
4159
4555
|
function getErrorsForPath(st, path) {
|
|
4160
4556
|
const { key } = canonicalizePath(path);
|
|
4161
4557
|
const cell = st.errorCells().get(key);
|
|
@@ -4180,6 +4576,7 @@ function noteDomConnected(st, path) {
|
|
|
4180
4576
|
}
|
|
4181
4577
|
function noteDomDisconnected(st, path) {
|
|
4182
4578
|
const { key } = canonicalizePath(path);
|
|
4579
|
+
if (!st.fields.has(key)) return;
|
|
4183
4580
|
touchFieldRecord(st, key, path, { connected: false, focused: null, blurred: null });
|
|
4184
4581
|
}
|
|
4185
4582
|
function markConnectedOptimistically(st, path) {
|
|
@@ -4242,7 +4639,7 @@ function markInteracted(st, path) {
|
|
|
4242
4639
|
function touchAtPath(st, segments) {
|
|
4243
4640
|
const formValue = st.form.value;
|
|
4244
4641
|
for (const [leafKey, entry] of st.originals) {
|
|
4245
|
-
if (!isPathPrefix(segments, entry.segments)) continue;
|
|
4642
|
+
if (!isPathPrefix(segments, entry.segments) || isDescendable(entry.value)) continue;
|
|
4246
4643
|
if (!hasAtPath(formValue, entry.segments)) continue;
|
|
4247
4644
|
const current = st.fields.get(leafKey);
|
|
4248
4645
|
if (current?.touched === true) continue;
|
|
@@ -4254,7 +4651,7 @@ function interactAtPath(st, segments) {
|
|
|
4254
4651
|
const formValue = st.form.value;
|
|
4255
4652
|
let interactedAny = false;
|
|
4256
4653
|
for (const [leafKey, entry] of st.originals) {
|
|
4257
|
-
if (!isPathPrefix(segments, entry.segments)) continue;
|
|
4654
|
+
if (!isPathPrefix(segments, entry.segments) || isDescendable(entry.value)) continue;
|
|
4258
4655
|
if (!hasAtPath(formValue, entry.segments)) continue;
|
|
4259
4656
|
interactedAny = true;
|
|
4260
4657
|
const current = st.fields.get(leafKey);
|
|
@@ -4330,15 +4727,20 @@ function reset(st, nextDefaultValues) {
|
|
|
4330
4727
|
st.schema.getDefaultValues({ useDefaultSchemaValues: true })
|
|
4331
4728
|
);
|
|
4332
4729
|
rebuildAuthoredPaths(st, resetSource, next);
|
|
4333
|
-
applyFormReplacement(st, next);
|
|
4334
|
-
st.arrayIdentity.rebaselineAll();
|
|
4335
|
-
st.removedSubtrees.clear();
|
|
4336
|
-
seedOriginalsFromBaseline(st, next);
|
|
4337
4730
|
if (nextDefaultValues !== void 0) {
|
|
4338
4731
|
const mentioned = /* @__PURE__ */ new Set();
|
|
4339
4732
|
walkAuthoredFromConstraints(nextDefaultValues, [], mentioned);
|
|
4340
4733
|
for (const key of mentioned) st.originalBlankPaths.delete(key);
|
|
4341
4734
|
}
|
|
4735
|
+
const now = writeInstant(st);
|
|
4736
|
+
applyFormReplacementWithPath(st, next, void 0, null, now);
|
|
4737
|
+
st.arrayIdentity.rebaselineAll();
|
|
4738
|
+
if (st.removedPaths.size > 0) {
|
|
4739
|
+
const cleared = [...st.removedPaths.values()];
|
|
4740
|
+
st.removedPaths.clear();
|
|
4741
|
+
pulseStructure(st.structureSignal, cleared);
|
|
4742
|
+
}
|
|
4743
|
+
seedOriginalsFromBaseline(st, next);
|
|
4342
4744
|
st.blankPaths.clear();
|
|
4343
4745
|
for (const key of st.originalBlankPaths) {
|
|
4344
4746
|
st.blankPaths.add(key);
|
|
@@ -4347,7 +4749,7 @@ function reset(st, nextDefaultValues) {
|
|
|
4347
4749
|
replaceErrorChannel(st, "schema", st.schema.validateSync(next));
|
|
4348
4750
|
st.firstValidationDone.value = initialFirstValidationGate(st.schema);
|
|
4349
4751
|
queueInitialAsyncValidation(st);
|
|
4350
|
-
|
|
4752
|
+
noteStamp(st, now);
|
|
4351
4753
|
for (const [pathKey, record] of st.fields) {
|
|
4352
4754
|
st.fields.set(pathKey, withClearedHistoryFlags(record, now));
|
|
4353
4755
|
}
|
|
@@ -4376,6 +4778,7 @@ function reset(st, nextDefaultValues) {
|
|
|
4376
4778
|
}
|
|
4377
4779
|
function resetField(st, path) {
|
|
4378
4780
|
const { key: targetKey, segments: targetSegments } = canonicalizePath(path);
|
|
4781
|
+
const now = writeInstant(st);
|
|
4379
4782
|
st.variantMemory.clearUnderPath(targetSegments);
|
|
4380
4783
|
cancelFieldValidationUnder(st, targetSegments);
|
|
4381
4784
|
cancelTransformsUnder(st, targetSegments);
|
|
@@ -4384,9 +4787,21 @@ function resetField(st, path) {
|
|
|
4384
4787
|
if (segs === null) continue;
|
|
4385
4788
|
if (isPathPrefix(targetSegments, segs)) st.pathSnapshots.delete(snapKey);
|
|
4386
4789
|
}
|
|
4790
|
+
const cleared = [];
|
|
4791
|
+
for (const [fieldKey, record] of Array.from(st.fields.entries())) {
|
|
4792
|
+
if (!isPathPrefix(targetSegments, record.path)) continue;
|
|
4793
|
+
st.fields.set(fieldKey, withClearedHistoryFlags(record, record.updatedAt));
|
|
4794
|
+
cleared.push(fieldKey);
|
|
4795
|
+
}
|
|
4387
4796
|
const leafEntry = st.originals.get(targetKey);
|
|
4388
4797
|
if (leafEntry !== void 0) {
|
|
4389
|
-
const wrote = setValueAtPath(
|
|
4798
|
+
const wrote = setValueAtPath(
|
|
4799
|
+
st,
|
|
4800
|
+
targetSegments,
|
|
4801
|
+
structuralSnapshot(leafEntry.value),
|
|
4802
|
+
void 0,
|
|
4803
|
+
now
|
|
4804
|
+
);
|
|
4390
4805
|
if (!wrote) {
|
|
4391
4806
|
console.error(
|
|
4392
4807
|
`[attaform] AF11 attaform.dev/e/af11 '${targetKey}'`
|
|
@@ -4404,10 +4819,10 @@ function resetField(st, path) {
|
|
|
4404
4819
|
if (subtree === void 0) {
|
|
4405
4820
|
subtree = typeof relative[0] === "number" ? [] : {};
|
|
4406
4821
|
}
|
|
4407
|
-
subtree = setAtPath(subtree, relative, entry.value);
|
|
4822
|
+
subtree = setAtPath(subtree, relative, structuralSnapshot(entry.value));
|
|
4408
4823
|
}
|
|
4409
4824
|
if (anyMatch) {
|
|
4410
|
-
const wroteSubtree = setValueAtPath(st, targetSegments, subtree);
|
|
4825
|
+
const wroteSubtree = setValueAtPath(st, targetSegments, subtree, void 0, now);
|
|
4411
4826
|
if (!wroteSubtree) {
|
|
4412
4827
|
console.error(
|
|
4413
4828
|
`[attaform] AF12 attaform.dev/e/af12 '${targetKey}'`
|
|
@@ -4416,8 +4831,14 @@ function resetField(st, path) {
|
|
|
4416
4831
|
}
|
|
4417
4832
|
}
|
|
4418
4833
|
deleteErrorCellsUnderPrefix(st, targetSegments);
|
|
4419
|
-
|
|
4420
|
-
|
|
4834
|
+
const raw = toRaw(st.form.value);
|
|
4835
|
+
for (const fieldKey of cleared) {
|
|
4836
|
+
const record = st.fields.get(fieldKey);
|
|
4837
|
+
if (record === void 0 || !hasAtPath(raw, record.path)) continue;
|
|
4838
|
+
raiseStamp(st, fieldKey, record.path, now);
|
|
4839
|
+
}
|
|
4840
|
+
if (cleared.length > 0 && hasAtPath(raw, targetSegments)) {
|
|
4841
|
+
stampContainers(st, [targetSegments], now);
|
|
4421
4842
|
}
|
|
4422
4843
|
}
|
|
4423
4844
|
function deleteErrorCellsUnderPrefix(st, prefix) {
|
|
@@ -4430,36 +4851,35 @@ function deleteErrorCellsUnderPrefix(st, prefix) {
|
|
|
4430
4851
|
}
|
|
4431
4852
|
}
|
|
4432
4853
|
}
|
|
4433
|
-
function clearFieldRecordFlags(st, pathKey) {
|
|
4434
|
-
const record = st.fields.get(pathKey);
|
|
4435
|
-
if (record === void 0) return;
|
|
4436
|
-
st.fields.set(pathKey, withClearedHistoryFlags(record, (/* @__PURE__ */ new Date()).toISOString()));
|
|
4437
|
-
}
|
|
4438
4854
|
function isPristineAtPathByKey(st, key, segments) {
|
|
4439
4855
|
if (st.blankPaths.has(key) !== st.originalBlankPaths.has(key)) return false;
|
|
4440
4856
|
const entry = st.originals.get(key);
|
|
4441
4857
|
if (entry === void 0) return true;
|
|
4442
4858
|
return Object.is(getAtPath(st.form.value, segments), entry.value);
|
|
4443
4859
|
}
|
|
4444
|
-
function hasStructuralChangeUnder(st, path) {
|
|
4860
|
+
function hasStructuralChangeUnder(st, path, key) {
|
|
4861
|
+
subscribeStructure(st.structureSignal, key);
|
|
4445
4862
|
return st.arrayIdentity.hasStructuralChangeUnder(path);
|
|
4446
4863
|
}
|
|
4447
|
-
function
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4864
|
+
function pulseStructure(signal, paths) {
|
|
4865
|
+
const keys = signal.keys;
|
|
4866
|
+
if (keys === null) return;
|
|
4867
|
+
eachAncestorOnce(paths, (key) => {
|
|
4868
|
+
keys.add(key);
|
|
4869
|
+
keys.delete(key);
|
|
4453
4870
|
});
|
|
4454
|
-
return had;
|
|
4455
4871
|
}
|
|
4456
|
-
function
|
|
4457
|
-
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4872
|
+
function subscribeStructure(signal, key) {
|
|
4873
|
+
signal.keys ?? (signal.keys = shallowReactive(/* @__PURE__ */ new Set()));
|
|
4874
|
+
void signal.keys.has(key);
|
|
4875
|
+
}
|
|
4876
|
+
function hasRemovedSubtreeUnder(st, prefix, key) {
|
|
4877
|
+
subscribeStructure(st.structureSignal, key);
|
|
4878
|
+
if (st.removedPaths.size === 0) return false;
|
|
4879
|
+
const raw = toRaw(st.form.value);
|
|
4880
|
+
for (const segments of st.removedPaths.values()) {
|
|
4461
4881
|
if (!isPathPrefix(prefix, segments)) continue;
|
|
4462
|
-
if (
|
|
4882
|
+
if (hasAtPath(raw, segments)) continue;
|
|
4463
4883
|
return true;
|
|
4464
4884
|
}
|
|
4465
4885
|
return false;
|
|
@@ -4495,10 +4915,14 @@ function createFormStore(options) {
|
|
|
4495
4915
|
warn: true
|
|
4496
4916
|
}) : initialData;
|
|
4497
4917
|
const form = ref(stubbedInitialData);
|
|
4498
|
-
const
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4918
|
+
const structureSignal = { keys: null };
|
|
4919
|
+
const arrayIdentity = createArrayIdentity(
|
|
4920
|
+
(arraySegs) => {
|
|
4921
|
+
const v = getAtPath(toRaw(form.value), arraySegs);
|
|
4922
|
+
return Array.isArray(v) ? v.length : 0;
|
|
4923
|
+
},
|
|
4924
|
+
(arrayPaths) => pulseStructure(structureSignal, arrayPaths)
|
|
4925
|
+
);
|
|
4502
4926
|
const fields = shallowReactive(/* @__PURE__ */ new Map());
|
|
4503
4927
|
const domBinding = shallowRef(null);
|
|
4504
4928
|
const errorStore = createErrorCells(
|
|
@@ -4507,7 +4931,7 @@ function createFormStore(options) {
|
|
|
4507
4931
|
);
|
|
4508
4932
|
const errorCells = () => errorStore(true);
|
|
4509
4933
|
const originals = shallowReactive(/* @__PURE__ */ new Map());
|
|
4510
|
-
const
|
|
4934
|
+
const removedPaths = /* @__PURE__ */ new Map();
|
|
4511
4935
|
const blankPaths = reactive(/* @__PURE__ */ new Set());
|
|
4512
4936
|
const originalBlankPaths = /* @__PURE__ */ new Set();
|
|
4513
4937
|
const seededBlankPaths = hydration !== void 0 ? (hydration.blankPaths ?? []).map((dotted) => canonicalizePath(dotted).key) : options.initialBlankPaths ?? [];
|
|
@@ -4608,6 +5032,8 @@ function createFormStore(options) {
|
|
|
4608
5032
|
blankPaths,
|
|
4609
5033
|
originalBlankPaths,
|
|
4610
5034
|
authoredPaths,
|
|
5035
|
+
removedPaths,
|
|
5036
|
+
notifyStructure: (paths) => pulseStructure(structureSignal, paths),
|
|
4611
5037
|
fieldValidationCounts,
|
|
4612
5038
|
fieldValidatingSince,
|
|
4613
5039
|
fieldValidationState,
|
|
@@ -4615,6 +5041,9 @@ function createFormStore(options) {
|
|
|
4615
5041
|
arrayIdentity,
|
|
4616
5042
|
variantMemory,
|
|
4617
5043
|
touchFieldRecord: (pathKey, path, patch) => touchFieldRecord(st, pathKey, path, patch),
|
|
5044
|
+
stampContainers: (containers, now) => stampContainers(st, containers, now),
|
|
5045
|
+
stampBareContainers: (patches, bare, now) => stampBareContainers(st, patches, bare, now),
|
|
5046
|
+
foldInteractionHistory: (path, released) => foldInteractionHistory(st, path, released),
|
|
4618
5047
|
decFieldValidation: (key) => decFieldValidation(st, key)
|
|
4619
5048
|
});
|
|
4620
5049
|
const bind = (fn) => (...args) => fn(st, ...args);
|
|
@@ -4678,7 +5107,8 @@ function createFormStore(options) {
|
|
|
4678
5107
|
cleanupHooks,
|
|
4679
5108
|
authoredPaths,
|
|
4680
5109
|
arrayIdentity,
|
|
4681
|
-
|
|
5110
|
+
removedPaths,
|
|
5111
|
+
structureSignal,
|
|
4682
5112
|
variantMemory,
|
|
4683
5113
|
pathOrdinals,
|
|
4684
5114
|
pathSnapshots,
|
|
@@ -4688,6 +5118,7 @@ function createFormStore(options) {
|
|
|
4688
5118
|
arrayBookkeeping,
|
|
4689
5119
|
skipErrorSeed: () => errorStore(false),
|
|
4690
5120
|
nextOrdinal: 0,
|
|
5121
|
+
latestStamp: "",
|
|
4691
5122
|
scheduleEpoch: 0,
|
|
4692
5123
|
lastCommittedEpoch: 0,
|
|
4693
5124
|
transformTokenSeq: 0,
|
|
@@ -4725,6 +5156,8 @@ function createFormStore(options) {
|
|
|
4725
5156
|
),
|
|
4726
5157
|
clearUserErrors: (path) => clearErrorChannel(st, "user", path),
|
|
4727
5158
|
restoreErrorCells: bind(restoreErrorCells),
|
|
5159
|
+
captureStructure: bind(captureStructure),
|
|
5160
|
+
restoreStructure: bind(restoreStructure),
|
|
4728
5161
|
getErrorsForPath: bind(getErrorsForPath),
|
|
4729
5162
|
ensurePathOrdinal: bind(ensurePathOrdinal),
|
|
4730
5163
|
noteDomConnected: bind(noteDomConnected),
|
|
@@ -4758,7 +5191,7 @@ function createFormStore(options) {
|
|
|
4758
5191
|
diffAndApply({}, schemaInitialData, [], (patch) => {
|
|
4759
5192
|
if (patch.kind !== "added") return;
|
|
4760
5193
|
const { key } = canonicalizePath(patch.path);
|
|
4761
|
-
originals
|
|
5194
|
+
if (seedBaseline(originals, key, patch)) return;
|
|
4762
5195
|
ensurePathOrdinal(st, key);
|
|
4763
5196
|
if (hydration === void 0) {
|
|
4764
5197
|
fields.set(key, {
|
|
@@ -4773,12 +5206,14 @@ function createFormStore(options) {
|
|
|
4773
5206
|
});
|
|
4774
5207
|
}
|
|
4775
5208
|
});
|
|
5209
|
+
if (fields.size > 0) noteStamp(st, initStamp);
|
|
4776
5210
|
if (hydration !== void 0) {
|
|
4777
5211
|
for (const [rawKey, record] of hydration.fields) {
|
|
4778
5212
|
if (typeof rawKey !== "string" || !isHydratedFieldRecord(record)) {
|
|
4779
5213
|
continue;
|
|
4780
5214
|
}
|
|
4781
5215
|
fields.set(rawKey, record);
|
|
5216
|
+
noteStamp(st, record.updatedAt);
|
|
4782
5217
|
}
|
|
4783
5218
|
for (const [rawKey, errs] of hydration.schemaErrors) {
|
|
4784
5219
|
if (typeof rawKey !== "string" || !isHydratedValidationErrorArray(errs)) {
|
|
@@ -5282,7 +5717,7 @@ function buildWizardStatusesProxy(statuses) {
|
|
|
5282
5717
|
// resolves to `undefined` (consistent with property-access).
|
|
5283
5718
|
resolveCall: (arg) => statuses[String(arg)]?.value,
|
|
5284
5719
|
ownKeys: () => Object.keys(statuses),
|
|
5285
|
-
hasKey: (key) =>
|
|
5720
|
+
hasKey: (key) => safeOwnHas(statuses, key)
|
|
5286
5721
|
});
|
|
5287
5722
|
}
|
|
5288
5723
|
|