attaform 0.21.2 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/dev-key-collision-warnings.cjs +1 -1
- package/dist/chunks/dev-key-collision-warnings.mjs +1 -1
- package/dist/chunks/devtools.cjs +1 -1
- package/dist/chunks/devtools.mjs +1 -1
- package/dist/chunks/fingerprint2.cjs +1 -1
- package/dist/chunks/fingerprint2.mjs +1 -1
- package/dist/chunks/indexeddb.cjs +1 -1
- package/dist/chunks/indexeddb.mjs +1 -1
- package/dist/chunks/local-storage.cjs +1 -1
- package/dist/chunks/local-storage.mjs +1 -1
- package/dist/chunks/multi-tab-sync.cjs +2 -2
- package/dist/chunks/multi-tab-sync.mjs +2 -2
- package/dist/chunks/session-storage.cjs +1 -1
- package/dist/chunks/session-storage.mjs +1 -1
- package/dist/chunks/wire-persistence.cjs +2 -2
- package/dist/chunks/wire-persistence.mjs +2 -2
- package/dist/index.cjs +3 -3
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.mjs +5 -5
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/{attaform.B5LNzqQh.cjs → attaform.01iKS_lz.cjs} +18 -5
- package/dist/shared/{attaform.DP-u7_tk.mjs.map → attaform.01iKS_lz.cjs.map} +1 -1
- package/dist/shared/{attaform.C41gjp-a.mjs → attaform.6xE0Lcfd.mjs} +2 -2
- package/dist/shared/{attaform.C41gjp-a.mjs.map → attaform.6xE0Lcfd.mjs.map} +1 -1
- package/dist/shared/{attaform.BBDIKtKY.cjs → attaform.AyujQoHp.cjs} +4 -4
- package/dist/shared/{attaform.BBDIKtKY.cjs.map → attaform.AyujQoHp.cjs.map} +1 -1
- package/dist/shared/{attaform.BGf_J22U.d.ts → attaform.BGwNZ9GV.d.cts} +10 -2
- package/dist/shared/{attaform.DP-u7_tk.mjs → attaform.BKFwekY2.mjs} +16 -6
- package/dist/shared/{attaform.B5LNzqQh.cjs.map → attaform.BKFwekY2.mjs.map} +1 -1
- package/dist/shared/{attaform.CcnF1AKJ.cjs → attaform.C-RtnCJM.cjs} +116 -47
- package/dist/shared/attaform.C-RtnCJM.cjs.map +1 -0
- package/dist/shared/{attaform.BkjJfMvJ.d.cts → attaform.CCCeEPwa.d.mts} +10 -2
- package/dist/shared/{attaform.BwLp9KM7.cjs → attaform.CRzpFCjV.cjs} +2 -2
- package/dist/shared/{attaform.BwLp9KM7.cjs.map → attaform.CRzpFCjV.cjs.map} +1 -1
- package/dist/shared/{attaform.D2ZuIOCf.cjs → attaform.CjMcwV7W.cjs} +557 -126
- package/dist/shared/attaform.CjMcwV7W.cjs.map +1 -0
- package/dist/shared/{attaform.CTheKoTc.mjs → attaform.CsB-iKbU.mjs} +557 -126
- package/dist/shared/attaform.CsB-iKbU.mjs.map +1 -0
- package/dist/shared/{attaform.BCcrLApm.d.mts → attaform.D4XYaasQ.d.ts} +10 -2
- package/dist/shared/{attaform.D6GYGshL.mjs → attaform.DCjgGir_.mjs} +3 -3
- package/dist/shared/{attaform.D6GYGshL.mjs.map → attaform.DCjgGir_.mjs.map} +1 -1
- package/dist/shared/{attaform.BVeLgfEh.mjs → attaform.DNuiFCXG.mjs} +4 -4
- package/dist/shared/{attaform.BVeLgfEh.mjs.map → attaform.DNuiFCXG.mjs.map} +1 -1
- package/dist/shared/{attaform.BYgioWLF.d.ts → attaform.DUMWQefY.d.ts} +1 -1
- package/dist/shared/{attaform.CrD73S4m.mjs → attaform.DgCfLqay.mjs} +116 -47
- package/dist/shared/attaform.DgCfLqay.mjs.map +1 -0
- package/dist/shared/{attaform.ory-3WhV.d.ts → attaform.DvUH4a3o.d.cts} +181 -6
- package/dist/shared/{attaform.ory-3WhV.d.cts → attaform.DvUH4a3o.d.mts} +181 -6
- package/dist/shared/{attaform.ory-3WhV.d.mts → attaform.DvUH4a3o.d.ts} +181 -6
- package/dist/shared/{attaform.BoY6RZUl.d.cts → attaform.FN0vaQAg.d.mts} +1 -1
- package/dist/shared/{attaform.BwrowMp2.cjs → attaform.Q3eAD2wD.cjs} +3 -3
- package/dist/shared/{attaform.BwrowMp2.cjs.map → attaform.Q3eAD2wD.cjs.map} +1 -1
- package/dist/shared/{attaform.CnEl--PF.d.mts → attaform.aekT7mMx.d.cts} +1 -1
- package/dist/zod-v3.cjs +2 -2
- package/dist/zod-v3.d.cts +3 -3
- package/dist/zod-v3.d.mts +3 -3
- package/dist/zod-v3.d.ts +3 -3
- package/dist/zod-v3.mjs +2 -2
- package/dist/zod-v4.cjs +2 -2
- package/dist/zod-v4.d.cts +4 -4
- package/dist/zod-v4.d.mts +4 -4
- package/dist/zod-v4.d.ts +4 -4
- package/dist/zod-v4.mjs +2 -2
- package/dist/zod.cjs +5 -5
- package/dist/zod.d.cts +5 -5
- package/dist/zod.d.mts +5 -5
- package/dist/zod.d.ts +5 -5
- package/dist/zod.mjs +5 -5
- package/package.json +2 -2
- package/dist/shared/attaform.CTheKoTc.mjs.map +0 -1
- package/dist/shared/attaform.CcnF1AKJ.cjs.map +0 -1
- package/dist/shared/attaform.CrD73S4m.mjs.map +0 -1
- package/dist/shared/attaform.D2ZuIOCf.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const vue = require('vue');
|
|
4
|
-
const paths = require('./attaform.
|
|
4
|
+
const paths = require('./attaform.01iKS_lz.cjs');
|
|
5
5
|
|
|
6
6
|
function safeAssign(target, key, value) {
|
|
7
7
|
if (key === "__proto__") {
|
|
@@ -36,7 +36,7 @@ function descendStep(value, segment) {
|
|
|
36
36
|
if (typeof value !== "object") return NOT_FOUND;
|
|
37
37
|
if (Array.isArray(value)) {
|
|
38
38
|
if (typeof segment !== "number") return NOT_FOUND;
|
|
39
|
-
if (segment
|
|
39
|
+
if (!(segment in value)) return NOT_FOUND;
|
|
40
40
|
return value[segment];
|
|
41
41
|
}
|
|
42
42
|
const record = value;
|
|
@@ -71,7 +71,7 @@ function hasAtPath(root, path) {
|
|
|
71
71
|
if (current === null || current === void 0) return false;
|
|
72
72
|
if (typeof current !== "object") return false;
|
|
73
73
|
if (Array.isArray(current)) {
|
|
74
|
-
return typeof last === "number" && last
|
|
74
|
+
return typeof last === "number" && last in current;
|
|
75
75
|
}
|
|
76
76
|
const key = typeof last === "number" ? String(last) : last;
|
|
77
77
|
if (isShadowedKey(key)) return safeOwnHas(current, key);
|
|
@@ -100,6 +100,31 @@ function setAtPathOffset(root, path, value, offset) {
|
|
|
100
100
|
safeAssign(rec, head, setAtPathOffset(safeOwnRead(rec, head), path, value, nextOffset));
|
|
101
101
|
return rec;
|
|
102
102
|
}
|
|
103
|
+
const NO_IN_PLACE = { applied: false };
|
|
104
|
+
function tryInPlaceLeafWrite(root, path, value) {
|
|
105
|
+
if (path.length === 0) return NO_IN_PLACE;
|
|
106
|
+
let node = root;
|
|
107
|
+
for (let i = 0; i < path.length; i++) {
|
|
108
|
+
const seg = path[i];
|
|
109
|
+
if (Array.isArray(node)) {
|
|
110
|
+
if (typeof seg !== "number" || seg < 0 || seg >= node.length) return NO_IN_PLACE;
|
|
111
|
+
} else if (isPlainRecord(node)) {
|
|
112
|
+
if (typeof seg !== "string" || isShadowedKey(seg) || !(seg in node)) return NO_IN_PLACE;
|
|
113
|
+
} else {
|
|
114
|
+
return NO_IN_PLACE;
|
|
115
|
+
}
|
|
116
|
+
const container = node;
|
|
117
|
+
if (i < path.length - 1) {
|
|
118
|
+
node = container[seg];
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
const old = container[seg];
|
|
122
|
+
if (isPlainRecord(old) || Array.isArray(old)) return NO_IN_PLACE;
|
|
123
|
+
container[seg] = value;
|
|
124
|
+
return { applied: true, old };
|
|
125
|
+
}
|
|
126
|
+
return NO_IN_PLACE;
|
|
127
|
+
}
|
|
103
128
|
function deleteAtPath(root, path) {
|
|
104
129
|
return deleteAtPathOffset(root, path, 0);
|
|
105
130
|
}
|
|
@@ -403,7 +428,7 @@ function diffObjectsLockstep(oldRec, newRec, prefix, visit) {
|
|
|
403
428
|
diffAndApply(oldRec[k], newRec[k], appendSegment(prefix, k), visit);
|
|
404
429
|
}
|
|
405
430
|
}
|
|
406
|
-
function applyChangedKeys(target, source) {
|
|
431
|
+
function applyChangedKeys(target, source, arrayOpPath, currentPath) {
|
|
407
432
|
if (!isDescendable(target) || !isDescendable(source)) return false;
|
|
408
433
|
const targetIsArray = Array.isArray(target);
|
|
409
434
|
const sourceIsArray = Array.isArray(source);
|
|
@@ -421,11 +446,27 @@ function applyChangedKeys(target, source) {
|
|
|
421
446
|
if (targetIsArray) {
|
|
422
447
|
const t = target;
|
|
423
448
|
const s = source;
|
|
424
|
-
if (
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
449
|
+
if (arrayOpPath === null || paths.pathsEqual(currentPath, arrayOpPath)) {
|
|
450
|
+
if (t.length > s.length) t.length = s.length;
|
|
451
|
+
for (const idx of changedFirstSegments) {
|
|
452
|
+
if (typeof idx === "symbol") continue;
|
|
453
|
+
const i = typeof idx === "number" ? idx : Number(idx);
|
|
454
|
+
if (i >= s.length) continue;
|
|
455
|
+
t[i] = s[i];
|
|
456
|
+
}
|
|
457
|
+
} else {
|
|
458
|
+
for (const idx of changedFirstSegments) {
|
|
459
|
+
if (typeof idx === "symbol") continue;
|
|
460
|
+
const i = typeof idx === "number" ? idx : Number(idx);
|
|
461
|
+
if (i >= s.length) continue;
|
|
462
|
+
const childPath = appendSegment(currentPath, i);
|
|
463
|
+
const curEl = t[i];
|
|
464
|
+
const nextEl = s[i];
|
|
465
|
+
if (paths.isPathPrefix(childPath, arrayOpPath) && isDescendable(curEl) && isDescendable(nextEl) && applyChangedKeys(curEl, nextEl, arrayOpPath, childPath)) {
|
|
466
|
+
continue;
|
|
467
|
+
}
|
|
468
|
+
t[i] = nextEl;
|
|
469
|
+
}
|
|
429
470
|
}
|
|
430
471
|
} else {
|
|
431
472
|
const t = target;
|
|
@@ -437,7 +478,14 @@ function applyChangedKeys(target, source) {
|
|
|
437
478
|
for (const k of changedFirstSegments) {
|
|
438
479
|
if (typeof k === "symbol") continue;
|
|
439
480
|
const key = String(k);
|
|
440
|
-
|
|
481
|
+
const nextVal = safeOwnRead(s, key);
|
|
482
|
+
if (arrayOpPath !== null) {
|
|
483
|
+
const curVal = safeOwnRead(t, key);
|
|
484
|
+
if (isDescendable(curVal) && isDescendable(nextVal) && applyChangedKeys(curVal, nextVal, arrayOpPath, appendSegment(currentPath, key))) {
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
safeAssign(t, key, nextVal);
|
|
441
489
|
}
|
|
442
490
|
}
|
|
443
491
|
return true;
|
|
@@ -549,6 +597,50 @@ function resolveGetDisplayState(config) {
|
|
|
549
597
|
return config ?? defaultDisplayState;
|
|
550
598
|
}
|
|
551
599
|
|
|
600
|
+
const AttaformErrorCode = {
|
|
601
|
+
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
602
|
+
NoValueSupplied: "atta:no-value-supplied",
|
|
603
|
+
/** The schema adapter's `validateAtPath` threw synchronously. */
|
|
604
|
+
AdapterThrew: "atta:adapter-threw",
|
|
605
|
+
/**
|
|
606
|
+
* User code inside a `z.preprocess`, `.refine`, or `.transform`
|
|
607
|
+
* threw (sync or async). The adapter caught the throw and surfaced
|
|
608
|
+
* it as a `ValidationError` at the field path so the form's normal
|
|
609
|
+
* error pipeline handles it instead of leaking as an unhandled
|
|
610
|
+
* rejection or routing through `submitError`.
|
|
611
|
+
*/
|
|
612
|
+
ValidatorThrew: "atta:validator-threw",
|
|
613
|
+
/**
|
|
614
|
+
* A function-form `defaultValues` factory threw or its promise
|
|
615
|
+
* rejected. The runtime captures the raw error on `form.hydrateError`
|
|
616
|
+
* and ALSO surfaces a form-level `ValidationError` (path `[]`) so
|
|
617
|
+
* the standard error pipeline carries the signal. Critical for the
|
|
618
|
+
* SSR round-trip: `hydrateError` itself does not ride the wire
|
|
619
|
+
* payload, but `schemaErrors` does, so the client sees the failure
|
|
620
|
+
* after rehydration without an extra channel.
|
|
621
|
+
*/
|
|
622
|
+
HydrationFailed: "atta:hydration-failed",
|
|
623
|
+
/** The supplied path didn't resolve to any node in the schema. */
|
|
624
|
+
PathNotFound: "atta:path-not-found",
|
|
625
|
+
/**
|
|
626
|
+
* A walked form's `activate()` (async `defaultValues` factory) threw
|
|
627
|
+
* during `wizard.handleSubmit`'s path walk. Surfaced as a synthetic
|
|
628
|
+
* `ValidationError` at the form-level path (`[]`) so the wizard's
|
|
629
|
+
* aggregate error pipeline can carry the failure alongside ordinary
|
|
630
|
+
* validation errors. The raw factory error remains on
|
|
631
|
+
* `form.hydrateError` for retry UX.
|
|
632
|
+
*/
|
|
633
|
+
ActivationFailed: "atta:activation-failed"
|
|
634
|
+
};
|
|
635
|
+
function makeBlankRequiredError(segments, formKey) {
|
|
636
|
+
return {
|
|
637
|
+
message: "No value supplied",
|
|
638
|
+
path: [...segments],
|
|
639
|
+
formKey,
|
|
640
|
+
code: AttaformErrorCode.NoValueSupplied
|
|
641
|
+
};
|
|
642
|
+
}
|
|
643
|
+
|
|
552
644
|
const DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS = 0;
|
|
553
645
|
const DEFAULT_PERSISTENCE_DEBOUNCE_MS = 300;
|
|
554
646
|
const DEFAULT_HISTORY_MAX_SNAPSHOTS = 128;
|
|
@@ -662,7 +754,7 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
662
754
|
const original = state.originals.get(key)?.value;
|
|
663
755
|
const pristine = state.isPristineAtPath(segments);
|
|
664
756
|
const schemaForKey = state.schemaErrors.get(key);
|
|
665
|
-
const blankForKey = state.
|
|
757
|
+
const blankForKey = state.blankPaths.has(key) && state.schema.isRequiredAtPath(segments) ? [makeBlankRequiredError(segments, state.formKey)] : void 0;
|
|
666
758
|
const userForKey = state.userErrors.get(key);
|
|
667
759
|
const errors = [];
|
|
668
760
|
if (schemaForKey !== void 0) errors.push(...schemaForKey);
|
|
@@ -726,9 +818,32 @@ function buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBa
|
|
|
726
818
|
getDisplayState
|
|
727
819
|
);
|
|
728
820
|
}
|
|
821
|
+
function visitActiveLeafPaths(value, base, visit) {
|
|
822
|
+
if (Array.isArray(value)) {
|
|
823
|
+
for (let i = 0; i < value.length; i++) {
|
|
824
|
+
const child = value[i];
|
|
825
|
+
if (Array.isArray(child) || isPlainRecord(child)) {
|
|
826
|
+
visitActiveLeafPaths(child, [...base, i], visit);
|
|
827
|
+
} else {
|
|
828
|
+
visit([...base, i]);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
return;
|
|
832
|
+
}
|
|
833
|
+
if (isPlainRecord(value)) {
|
|
834
|
+
for (const k of Object.keys(value)) {
|
|
835
|
+
const child = value[k];
|
|
836
|
+
if (Array.isArray(child) || isPlainRecord(child)) {
|
|
837
|
+
visitActiveLeafPaths(child, [...base, k], visit);
|
|
838
|
+
} else {
|
|
839
|
+
visit([...base, k]);
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
}
|
|
729
844
|
function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
730
845
|
const formValue = state.form.value;
|
|
731
|
-
const value =
|
|
846
|
+
const value = getAtPath(formValue, segments);
|
|
732
847
|
const original = state.originals.get(key)?.value;
|
|
733
848
|
let pristine = true;
|
|
734
849
|
let blank = true;
|
|
@@ -747,12 +862,16 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
747
862
|
let asyncPending = false;
|
|
748
863
|
const submissionAttempts = state.submissionAttempts.value;
|
|
749
864
|
const blurredLeafSegments = [];
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
865
|
+
const descendantLeaves = [];
|
|
866
|
+
visitActiveLeafPaths(value, segments, (leafSegments) => {
|
|
867
|
+
const { key: leafKey } = paths.keyForSegments(leafSegments);
|
|
868
|
+
const entry = state.originals.get(leafKey);
|
|
869
|
+
if (entry === void 0) return;
|
|
870
|
+
descendantLeaves.push({ key: leafKey, segments: entry.segments });
|
|
871
|
+
});
|
|
872
|
+
for (const { key: leafKey, segments: leafSeg } of descendantLeaves) {
|
|
754
873
|
const leafRecord = state.fields.get(leafKey);
|
|
755
|
-
if (!state.isPristineAtPathByKey(leafKey,
|
|
874
|
+
if (!state.isPristineAtPathByKey(leafKey, leafSeg)) {
|
|
756
875
|
pristine = false;
|
|
757
876
|
dirty = true;
|
|
758
877
|
}
|
|
@@ -763,7 +882,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
763
882
|
if (leafRecord?.interacted === true) interacted = true;
|
|
764
883
|
if (leafRecord?.blurredAfterInteraction === true) {
|
|
765
884
|
blurredAfterInteraction = true;
|
|
766
|
-
blurredLeafSegments.push(
|
|
885
|
+
blurredLeafSegments.push(leafSeg);
|
|
767
886
|
}
|
|
768
887
|
if (leafRecord?.connected === true) connected = true;
|
|
769
888
|
if ((state.fieldValidationCounts.get(leafKey) ?? 0) > 0) {
|
|
@@ -780,7 +899,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
780
899
|
if (leafGateOpen && since !== void 0 && (transformingSince === null || since < transformingSince))
|
|
781
900
|
transformingSince = since;
|
|
782
901
|
}
|
|
783
|
-
if (state.pathHasAsyncValidationByKey(leafKey,
|
|
902
|
+
if (state.pathHasAsyncValidationByKey(leafKey, leafSeg)) asyncPending = true;
|
|
784
903
|
const ts = leafRecord?.updatedAt;
|
|
785
904
|
if (ts !== void 0 && ts !== null) {
|
|
786
905
|
if (updatedAt === null || ts > updatedAt) updatedAt = ts;
|
|
@@ -1407,7 +1526,7 @@ function buildFieldArrayApi(state) {
|
|
|
1407
1526
|
append(path, value) {
|
|
1408
1527
|
const next = readArray(path);
|
|
1409
1528
|
next.push(value);
|
|
1410
|
-
return writeArray(path, next);
|
|
1529
|
+
return writeArray(path, next, { kind: "insert", index: next.length - 1 });
|
|
1411
1530
|
},
|
|
1412
1531
|
prepend(path, value) {
|
|
1413
1532
|
const next = readArray(path);
|
|
@@ -1735,42 +1854,6 @@ function mergeObjectKeys(target, source, path, schema) {
|
|
|
1735
1854
|
return out;
|
|
1736
1855
|
}
|
|
1737
1856
|
|
|
1738
|
-
const AttaformErrorCode = {
|
|
1739
|
-
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
1740
|
-
NoValueSupplied: "atta:no-value-supplied",
|
|
1741
|
-
/** The schema adapter's `validateAtPath` threw synchronously. */
|
|
1742
|
-
AdapterThrew: "atta:adapter-threw",
|
|
1743
|
-
/**
|
|
1744
|
-
* User code inside a `z.preprocess`, `.refine`, or `.transform`
|
|
1745
|
-
* threw (sync or async). The adapter caught the throw and surfaced
|
|
1746
|
-
* it as a `ValidationError` at the field path so the form's normal
|
|
1747
|
-
* error pipeline handles it instead of leaking as an unhandled
|
|
1748
|
-
* rejection or routing through `submitError`.
|
|
1749
|
-
*/
|
|
1750
|
-
ValidatorThrew: "atta:validator-threw",
|
|
1751
|
-
/**
|
|
1752
|
-
* A function-form `defaultValues` factory threw or its promise
|
|
1753
|
-
* rejected. The runtime captures the raw error on `form.hydrateError`
|
|
1754
|
-
* and ALSO surfaces a form-level `ValidationError` (path `[]`) so
|
|
1755
|
-
* the standard error pipeline carries the signal. Critical for the
|
|
1756
|
-
* SSR round-trip: `hydrateError` itself does not ride the wire
|
|
1757
|
-
* payload, but `schemaErrors` does, so the client sees the failure
|
|
1758
|
-
* after rehydration without an extra channel.
|
|
1759
|
-
*/
|
|
1760
|
-
HydrationFailed: "atta:hydration-failed",
|
|
1761
|
-
/** The supplied path didn't resolve to any node in the schema. */
|
|
1762
|
-
PathNotFound: "atta:path-not-found",
|
|
1763
|
-
/**
|
|
1764
|
-
* A walked form's `activate()` (async `defaultValues` factory) threw
|
|
1765
|
-
* during `wizard.handleSubmit`'s path walk. Surfaced as a synthetic
|
|
1766
|
-
* `ValidationError` at the form-level path (`[]`) so the wizard's
|
|
1767
|
-
* aggregate error pipeline can carry the failure alongside ordinary
|
|
1768
|
-
* validation errors. The raw factory error remains on
|
|
1769
|
-
* `form.hydrateError` for retry UX.
|
|
1770
|
-
*/
|
|
1771
|
-
ActivationFailed: "atta:activation-failed"
|
|
1772
|
-
};
|
|
1773
|
-
|
|
1774
1857
|
const warnedNoScopeStores = paths.__DEV__ ? /* @__PURE__ */ new WeakSet() : null;
|
|
1775
1858
|
function buildProcessForm(state, formInstanceId, options = {}) {
|
|
1776
1859
|
const invalidPolicy = options.onInvalidSubmit ?? "focus-first-error";
|
|
@@ -2796,19 +2879,116 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2796
2879
|
}
|
|
2797
2880
|
};
|
|
2798
2881
|
const getFormMetaBase = () => {
|
|
2799
|
-
|
|
2882
|
+
let rollup;
|
|
2883
|
+
const rootBase = () => rollup ?? (rollup = buildContainerFieldStateBase(
|
|
2800
2884
|
state,
|
|
2801
2885
|
paths.ROOT_PATH,
|
|
2802
2886
|
paths.ROOT_PATH_KEY,
|
|
2803
2887
|
formInstanceId
|
|
2804
|
-
);
|
|
2888
|
+
).base);
|
|
2805
2889
|
return {
|
|
2806
|
-
|
|
2890
|
+
// Rollup-derived (FieldStateBase) — the whole rollup builds once, on the
|
|
2891
|
+
// first access of any of these.
|
|
2892
|
+
get value() {
|
|
2893
|
+
return rootBase().value;
|
|
2894
|
+
},
|
|
2895
|
+
get original() {
|
|
2896
|
+
return rootBase().original;
|
|
2897
|
+
},
|
|
2898
|
+
get pristine() {
|
|
2899
|
+
return rootBase().pristine;
|
|
2900
|
+
},
|
|
2901
|
+
get dirty() {
|
|
2902
|
+
return rootBase().dirty;
|
|
2903
|
+
},
|
|
2904
|
+
get focused() {
|
|
2905
|
+
return rootBase().focused;
|
|
2906
|
+
},
|
|
2907
|
+
get blurred() {
|
|
2908
|
+
return rootBase().blurred;
|
|
2909
|
+
},
|
|
2910
|
+
get touched() {
|
|
2911
|
+
return rootBase().touched;
|
|
2912
|
+
},
|
|
2913
|
+
get interacted() {
|
|
2914
|
+
return rootBase().interacted;
|
|
2915
|
+
},
|
|
2916
|
+
get blurredAfterInteraction() {
|
|
2917
|
+
return rootBase().blurredAfterInteraction;
|
|
2918
|
+
},
|
|
2919
|
+
get connected() {
|
|
2920
|
+
return rootBase().connected;
|
|
2921
|
+
},
|
|
2922
|
+
get element() {
|
|
2923
|
+
return rootBase().element;
|
|
2924
|
+
},
|
|
2925
|
+
get elements() {
|
|
2926
|
+
return rootBase().elements;
|
|
2927
|
+
},
|
|
2928
|
+
get updatedAt() {
|
|
2929
|
+
return rootBase().updatedAt;
|
|
2930
|
+
},
|
|
2931
|
+
get errors() {
|
|
2932
|
+
return rootBase().errors;
|
|
2933
|
+
},
|
|
2934
|
+
get validating() {
|
|
2935
|
+
return rootBase().validating;
|
|
2936
|
+
},
|
|
2937
|
+
get valid() {
|
|
2938
|
+
return rootBase().valid;
|
|
2939
|
+
},
|
|
2940
|
+
get transforming() {
|
|
2941
|
+
return rootBase().transforming;
|
|
2942
|
+
},
|
|
2943
|
+
get busy() {
|
|
2944
|
+
return rootBase().busy;
|
|
2945
|
+
},
|
|
2946
|
+
get transformError() {
|
|
2947
|
+
return rootBase().transformError;
|
|
2948
|
+
},
|
|
2949
|
+
get path() {
|
|
2950
|
+
return rootBase().path;
|
|
2951
|
+
},
|
|
2952
|
+
get id() {
|
|
2953
|
+
return rootBase().id;
|
|
2954
|
+
},
|
|
2955
|
+
get aria() {
|
|
2956
|
+
return rootBase().aria;
|
|
2957
|
+
},
|
|
2958
|
+
get key() {
|
|
2959
|
+
return rootBase().key;
|
|
2960
|
+
},
|
|
2961
|
+
get blank() {
|
|
2962
|
+
return rootBase().blank;
|
|
2963
|
+
},
|
|
2964
|
+
get label() {
|
|
2965
|
+
return rootBase().label;
|
|
2966
|
+
},
|
|
2967
|
+
get description() {
|
|
2968
|
+
return rootBase().description;
|
|
2969
|
+
},
|
|
2970
|
+
get placeholder() {
|
|
2971
|
+
return rootBase().placeholder;
|
|
2972
|
+
},
|
|
2973
|
+
get meta() {
|
|
2974
|
+
return rootBase().meta;
|
|
2975
|
+
},
|
|
2976
|
+
get errorCount() {
|
|
2977
|
+
return rootBase().errors.length;
|
|
2978
|
+
},
|
|
2979
|
+
// Form-level scalars — EAGER reads, tracked on every field-state eval.
|
|
2980
|
+
// They are O(1) refs that never change on a keystroke, so tracking them
|
|
2981
|
+
// per field costs nothing on the hot path. Kept eager (NOT lazy like the
|
|
2982
|
+
// rollup) because behaviors beyond the predicate's own output depend on
|
|
2983
|
+
// every field re-evaluating when they flip — most notably, the display
|
|
2984
|
+
// engine is cleared on submit (revealing held spinners), and that
|
|
2985
|
+
// imperative reset only becomes visible if `submitting` is a tracked dep
|
|
2986
|
+
// of each field. Matches the pre-bust dependency set for these scalars
|
|
2987
|
+
// exactly.
|
|
2807
2988
|
submitting: state.submitting.value,
|
|
2808
2989
|
submissionAttempts: state.submissionAttempts.value,
|
|
2809
2990
|
departAttempts: state.departAttempts.value,
|
|
2810
2991
|
submitError: state.submitError.value,
|
|
2811
|
-
errorCount: rootBase.errors.length,
|
|
2812
2992
|
submitted: state.submitted.value,
|
|
2813
2993
|
instanceId: formInstanceId
|
|
2814
2994
|
};
|
|
@@ -2843,14 +3023,19 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2843
3023
|
const segments = paths.canonicalizePath(pathInput).segments;
|
|
2844
3024
|
return vue.computed(() => getAtPath(state.form.value, segments));
|
|
2845
3025
|
}
|
|
2846
|
-
function setValueImpl(pathOrValue, maybeValue) {
|
|
2847
|
-
|
|
3026
|
+
function setValueImpl(pathOrValue, maybeValue, maybeOptions) {
|
|
3027
|
+
const argc = arguments.length;
|
|
3028
|
+
const isPathForm = argc >= 2 && (typeof pathOrValue === "string" || Array.isArray(pathOrValue));
|
|
3029
|
+
const options2 = isPathForm ? maybeOptions : argc >= 2 ? maybeValue : void 0;
|
|
3030
|
+
const silent = options2?.silent === true;
|
|
3031
|
+
const writeMeta = (extra) => withInstanceMeta(silent ? { ...extra, silent: true } : extra);
|
|
3032
|
+
if (!isPathForm) {
|
|
2848
3033
|
const next = typeof pathOrValue === "function" ? pathOrValue(structuralSnapshot(state.form.value)) : pathOrValue;
|
|
2849
3034
|
const walked2 = walkUnsetSentinels(
|
|
2850
3035
|
next,
|
|
2851
3036
|
state.schema
|
|
2852
3037
|
);
|
|
2853
|
-
const ok2 = state.setValueAtPath([], walked2.cleanedValues,
|
|
3038
|
+
const ok2 = state.setValueAtPath([], walked2.cleanedValues, writeMeta());
|
|
2854
3039
|
if (!ok2) return false;
|
|
2855
3040
|
reMarkBlanksAfterSubstitution(walked2.paths);
|
|
2856
3041
|
return true;
|
|
@@ -2864,7 +3049,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2864
3049
|
if (parentDU?.discriminatorKey === last) {
|
|
2865
3050
|
const slimDefault = state.schema.getEmptyValueAtPath(segments);
|
|
2866
3051
|
const blank = blankForKind(slimDefault);
|
|
2867
|
-
return state.setValueAtPath(segments, blank,
|
|
3052
|
+
return state.setValueAtPath(segments, blank, writeMeta({ blank: true }));
|
|
2868
3053
|
}
|
|
2869
3054
|
}
|
|
2870
3055
|
const blankPaths = [];
|
|
@@ -2875,9 +3060,9 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2875
3060
|
);
|
|
2876
3061
|
const segmentsKey = paths.canonicalizePath(segments).key;
|
|
2877
3062
|
if (blankPaths.length === 1 && blankPaths[0] === segmentsKey) {
|
|
2878
|
-
return state.setValueAtPath(segments, expanded,
|
|
3063
|
+
return state.setValueAtPath(segments, expanded, writeMeta({ blank: true }));
|
|
2879
3064
|
}
|
|
2880
|
-
const ok2 = state.setValueAtPath(segments, expanded,
|
|
3065
|
+
const ok2 = state.setValueAtPath(segments, expanded, writeMeta());
|
|
2881
3066
|
if (!ok2) return false;
|
|
2882
3067
|
for (const pathKey of blankPaths) {
|
|
2883
3068
|
const blankSegments = paths.segmentsForPathKey(pathKey);
|
|
@@ -2885,7 +3070,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2885
3070
|
state.setValueAtPath(
|
|
2886
3071
|
blankSegments,
|
|
2887
3072
|
state.getValueAtPath(blankSegments),
|
|
2888
|
-
|
|
3073
|
+
writeMeta({ blank: true })
|
|
2889
3074
|
);
|
|
2890
3075
|
}
|
|
2891
3076
|
return true;
|
|
@@ -2905,7 +3090,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2905
3090
|
segments,
|
|
2906
3091
|
state.schema
|
|
2907
3092
|
);
|
|
2908
|
-
const ok = state.setValueAtPath(segments, walked.cleanedValues,
|
|
3093
|
+
const ok = state.setValueAtPath(segments, walked.cleanedValues, writeMeta());
|
|
2909
3094
|
if (!ok) return false;
|
|
2910
3095
|
reMarkBlanksAfterSubstitution(walked.paths);
|
|
2911
3096
|
return true;
|
|
@@ -3276,7 +3461,19 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
3276
3461
|
}
|
|
3277
3462
|
return Object.freeze(out);
|
|
3278
3463
|
}
|
|
3279
|
-
|
|
3464
|
+
const formHandle = {
|
|
3465
|
+
current: void 0
|
|
3466
|
+
};
|
|
3467
|
+
function onChangeImpl(a, b, c) {
|
|
3468
|
+
const sourced = typeof b === "function";
|
|
3469
|
+
const source = sourced ? a : void 0;
|
|
3470
|
+
const handler = sourced ? b : a;
|
|
3471
|
+
const options2 = sourced ? c : b;
|
|
3472
|
+
const stop = state.registerOnChange(source, handler, options2, () => formHandle.current);
|
|
3473
|
+
if (vue.getCurrentScope() !== void 0) vue.onScopeDispose(stop);
|
|
3474
|
+
return stop;
|
|
3475
|
+
}
|
|
3476
|
+
const api = {
|
|
3280
3477
|
handleSubmit: gated(handleSubmit),
|
|
3281
3478
|
// Callable readonly Proxies (`values`, `fields`, `errors`) and the
|
|
3282
3479
|
// reactive containers (`meta`, `history`, `blankPaths`) are exposed
|
|
@@ -3363,8 +3560,11 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
3363
3560
|
get blankPaths() {
|
|
3364
3561
|
void state.activate();
|
|
3365
3562
|
return blankPathsView;
|
|
3366
|
-
}
|
|
3563
|
+
},
|
|
3564
|
+
onChange: onChangeImpl
|
|
3367
3565
|
};
|
|
3566
|
+
formHandle.current = api;
|
|
3567
|
+
return api;
|
|
3368
3568
|
}
|
|
3369
3569
|
|
|
3370
3570
|
const IDLE = Object.freeze({ display: "idle" });
|
|
@@ -3791,6 +3991,7 @@ function createArrayBookkeeping(deps) {
|
|
|
3791
3991
|
originals,
|
|
3792
3992
|
blankPaths,
|
|
3793
3993
|
originalBlankPaths,
|
|
3994
|
+
authoredPaths,
|
|
3794
3995
|
fieldValidationCounts,
|
|
3795
3996
|
fieldValidatingSince,
|
|
3796
3997
|
fieldValidationState,
|
|
@@ -3818,6 +4019,7 @@ function createArrayBookkeeping(deps) {
|
|
|
3818
4019
|
}));
|
|
3819
4020
|
migrateSetSubtree(blankPaths, arrayPath, remap);
|
|
3820
4021
|
migrateSetSubtree(originalBlankPaths, arrayPath, remap);
|
|
4022
|
+
migrateSetSubtree(authoredPaths, arrayPath, remap);
|
|
3821
4023
|
migrateMapSubtree(fieldValidatingSince, arrayPath, remap, (since) => since);
|
|
3822
4024
|
migrateMapSubtree(fieldValidationCounts, arrayPath, remap, (count) => count);
|
|
3823
4025
|
arrayIdentity.applyRemap(arrayPath, remap);
|
|
@@ -3861,7 +4063,7 @@ function createArrayBookkeeping(deps) {
|
|
|
3861
4063
|
activeValidations.value = Math.max(0, activeValidations.value - 1);
|
|
3862
4064
|
decFieldValidation(key);
|
|
3863
4065
|
}
|
|
3864
|
-
entry.
|
|
4066
|
+
entry.aborted = true;
|
|
3865
4067
|
fieldValidationState.delete(key);
|
|
3866
4068
|
}
|
|
3867
4069
|
}
|
|
@@ -3873,6 +4075,170 @@ function createArrayBookkeeping(deps) {
|
|
|
3873
4075
|
};
|
|
3874
4076
|
}
|
|
3875
4077
|
|
|
4078
|
+
const NOOP_STOP = () => {
|
|
4079
|
+
};
|
|
4080
|
+
function isThenable(value) {
|
|
4081
|
+
return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
4082
|
+
}
|
|
4083
|
+
function isSuppressed(meta) {
|
|
4084
|
+
return meta?.hydration === true || meta?.crossTab === true || meta?.silent === true;
|
|
4085
|
+
}
|
|
4086
|
+
function canonicalizeSourceList(raw) {
|
|
4087
|
+
const list = typeof raw === "string" ? [raw] : raw;
|
|
4088
|
+
const out = [];
|
|
4089
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4090
|
+
for (const entry of list) {
|
|
4091
|
+
const { segments, key } = paths.canonicalizePath(entry);
|
|
4092
|
+
if (seen.has(key)) continue;
|
|
4093
|
+
seen.add(key);
|
|
4094
|
+
out.push({ segments, key, dotted: paths.segmentsToDotted(segments) });
|
|
4095
|
+
}
|
|
4096
|
+
return out;
|
|
4097
|
+
}
|
|
4098
|
+
function makeResolver(source) {
|
|
4099
|
+
if (source === void 0) {
|
|
4100
|
+
const root = [{ segments: paths.ROOT_PATH, key: paths.ROOT_PATH_KEY, dotted: "" }];
|
|
4101
|
+
return () => root;
|
|
4102
|
+
}
|
|
4103
|
+
if (typeof source !== "function" && !vue.isRef(source)) {
|
|
4104
|
+
const fixed = canonicalizeSourceList(source);
|
|
4105
|
+
return () => fixed;
|
|
4106
|
+
}
|
|
4107
|
+
return () => canonicalizeSourceList(vue.toValue(source));
|
|
4108
|
+
}
|
|
4109
|
+
function createOnChangeRegistry(deps) {
|
|
4110
|
+
const handlers = /* @__PURE__ */ new Set();
|
|
4111
|
+
function isCurrent(reg, key, token) {
|
|
4112
|
+
return reg.runs.get(key)?.token === token;
|
|
4113
|
+
}
|
|
4114
|
+
function routeError(reg, error, source, changed, value, previous, attempt, token) {
|
|
4115
|
+
if (reg.onError === void 0) {
|
|
4116
|
+
if (paths.__DEV__) {
|
|
4117
|
+
console.error(
|
|
4118
|
+
`[attaform] onChange handler threw for path '${source.dotted}' \u2014 error swallowed. Pass { onError } to handle it. Original error:`,
|
|
4119
|
+
error
|
|
4120
|
+
);
|
|
4121
|
+
}
|
|
4122
|
+
return;
|
|
4123
|
+
}
|
|
4124
|
+
const retry = () => {
|
|
4125
|
+
if (!isCurrent(reg, source.key, token)) return;
|
|
4126
|
+
runHandler(reg, source, changed, value, previous, attempt + 1);
|
|
4127
|
+
};
|
|
4128
|
+
const errCtx = {
|
|
4129
|
+
path: source.dotted,
|
|
4130
|
+
value,
|
|
4131
|
+
attempt,
|
|
4132
|
+
retry,
|
|
4133
|
+
form: reg.getForm()
|
|
4134
|
+
};
|
|
4135
|
+
try {
|
|
4136
|
+
reg.onError(error, errCtx);
|
|
4137
|
+
} catch (err) {
|
|
4138
|
+
if (paths.__DEV__) console.error("[attaform] onChange onError threw:", err);
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
function runHandler(reg, source, changed, value, previous, attempt) {
|
|
4142
|
+
const prior = reg.runs.get(source.key);
|
|
4143
|
+
if (prior) prior.controller.abort();
|
|
4144
|
+
const controller = new AbortController();
|
|
4145
|
+
const token = ++reg.seq;
|
|
4146
|
+
reg.runs.set(source.key, { token, controller });
|
|
4147
|
+
const ctx = {
|
|
4148
|
+
path: source.dotted,
|
|
4149
|
+
previous,
|
|
4150
|
+
signal: controller.signal,
|
|
4151
|
+
attempt,
|
|
4152
|
+
form: reg.getForm(),
|
|
4153
|
+
changed
|
|
4154
|
+
};
|
|
4155
|
+
let result;
|
|
4156
|
+
try {
|
|
4157
|
+
result = reg.handler(value, ctx);
|
|
4158
|
+
} catch (error) {
|
|
4159
|
+
routeError(reg, error, source, changed, value, previous, attempt, token);
|
|
4160
|
+
return;
|
|
4161
|
+
}
|
|
4162
|
+
if (isThenable(result)) {
|
|
4163
|
+
result.then(void 0, (error) => {
|
|
4164
|
+
if (isCurrent(reg, source.key, token)) {
|
|
4165
|
+
routeError(reg, error, source, changed, value, previous, attempt, token);
|
|
4166
|
+
}
|
|
4167
|
+
});
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
function dispatch(patches, meta) {
|
|
4171
|
+
if (handlers.size === 0 || isSuppressed(meta)) return;
|
|
4172
|
+
for (const reg of handlers) {
|
|
4173
|
+
let sources;
|
|
4174
|
+
try {
|
|
4175
|
+
sources = reg.resolve();
|
|
4176
|
+
} catch (error) {
|
|
4177
|
+
if (paths.__DEV__) console.error("[attaform] onChange source getter threw:", error);
|
|
4178
|
+
continue;
|
|
4179
|
+
}
|
|
4180
|
+
for (const source of sources) {
|
|
4181
|
+
let changed;
|
|
4182
|
+
for (const patch of patches) {
|
|
4183
|
+
if (paths.isPathPrefix(source.segments, patch.path) || paths.isPathPrefix(patch.path, source.segments)) {
|
|
4184
|
+
(changed ?? (changed = [])).push(paths.segmentsToDotted(patch.path));
|
|
4185
|
+
}
|
|
4186
|
+
}
|
|
4187
|
+
if (changed === void 0) continue;
|
|
4188
|
+
const value = deps.getValueAtPath(source.segments);
|
|
4189
|
+
const previous = reg.previous.has(source.key) ? reg.previous.get(source.key) : value;
|
|
4190
|
+
reg.previous.set(source.key, value);
|
|
4191
|
+
runHandler(reg, source, changed, value, previous, 0);
|
|
4192
|
+
}
|
|
4193
|
+
}
|
|
4194
|
+
}
|
|
4195
|
+
function register(source, handler, options, getForm) {
|
|
4196
|
+
if (deps.ssr) return NOOP_STOP;
|
|
4197
|
+
const reg = {
|
|
4198
|
+
handler,
|
|
4199
|
+
onError: options?.onError,
|
|
4200
|
+
getForm,
|
|
4201
|
+
resolve: makeResolver(source),
|
|
4202
|
+
previous: /* @__PURE__ */ new Map(),
|
|
4203
|
+
runs: /* @__PURE__ */ new Map(),
|
|
4204
|
+
seq: 0
|
|
4205
|
+
};
|
|
4206
|
+
try {
|
|
4207
|
+
for (const { key, segments } of reg.resolve()) {
|
|
4208
|
+
reg.previous.set(key, deps.getValueAtPath(segments));
|
|
4209
|
+
}
|
|
4210
|
+
} catch (error) {
|
|
4211
|
+
if (paths.__DEV__) console.error("[attaform] onChange source getter threw at registration:", error);
|
|
4212
|
+
}
|
|
4213
|
+
handlers.add(reg);
|
|
4214
|
+
let stopped = false;
|
|
4215
|
+
return () => {
|
|
4216
|
+
if (stopped) return;
|
|
4217
|
+
stopped = true;
|
|
4218
|
+
handlers.delete(reg);
|
|
4219
|
+
for (const run of reg.runs.values()) run.controller.abort();
|
|
4220
|
+
reg.runs.clear();
|
|
4221
|
+
reg.previous.clear();
|
|
4222
|
+
};
|
|
4223
|
+
}
|
|
4224
|
+
function dispose() {
|
|
4225
|
+
for (const reg of handlers) {
|
|
4226
|
+
for (const run of reg.runs.values()) run.controller.abort();
|
|
4227
|
+
reg.runs.clear();
|
|
4228
|
+
reg.previous.clear();
|
|
4229
|
+
}
|
|
4230
|
+
handlers.clear();
|
|
4231
|
+
}
|
|
4232
|
+
return {
|
|
4233
|
+
get active() {
|
|
4234
|
+
return handlers.size > 0;
|
|
4235
|
+
},
|
|
4236
|
+
register,
|
|
4237
|
+
dispatch,
|
|
4238
|
+
dispose
|
|
4239
|
+
};
|
|
4240
|
+
}
|
|
4241
|
+
|
|
3876
4242
|
function isHydratedFieldRecord(value) {
|
|
3877
4243
|
if (typeof value !== "object" || value === null) return false;
|
|
3878
4244
|
const r = value;
|
|
@@ -3957,6 +4323,17 @@ function walkAuthoredFromConstraints(value, prefix, out) {
|
|
|
3957
4323
|
}
|
|
3958
4324
|
}
|
|
3959
4325
|
}
|
|
4326
|
+
function freshElementIndices(op) {
|
|
4327
|
+
switch (op.kind) {
|
|
4328
|
+
case "insert":
|
|
4329
|
+
case "replace-at":
|
|
4330
|
+
return [op.index];
|
|
4331
|
+
case "remove":
|
|
4332
|
+
case "swap":
|
|
4333
|
+
case "move":
|
|
4334
|
+
return [];
|
|
4335
|
+
}
|
|
4336
|
+
}
|
|
3960
4337
|
function walkAuthoredFromSchemaDiff(withDefaults, withoutDefaults, prefix, out) {
|
|
3961
4338
|
if (isPlainRecord(withDefaults) && isPlainRecord(withoutDefaults)) {
|
|
3962
4339
|
const left = withDefaults;
|
|
@@ -3995,6 +4372,7 @@ function createFormStore(options) {
|
|
|
3995
4372
|
const formChangeListeners = /* @__PURE__ */ new Set();
|
|
3996
4373
|
const submitSuccessListeners = /* @__PURE__ */ new Set();
|
|
3997
4374
|
const resetListeners = /* @__PURE__ */ new Set();
|
|
4375
|
+
const onChangeRegistry = createOnChangeRegistry({ getValueAtPath, ssr });
|
|
3998
4376
|
const persistOptIns = paths.createPersistOptInRegistry();
|
|
3999
4377
|
const noSyncPaths = /* @__PURE__ */ new Set();
|
|
4000
4378
|
const noSyncPathCounts = /* @__PURE__ */ new Map();
|
|
@@ -4033,11 +4411,8 @@ function createFormStore(options) {
|
|
|
4033
4411
|
if (constraints !== void 0) {
|
|
4034
4412
|
walkAuthoredFromConstraints(constraints, [], authoredPaths);
|
|
4035
4413
|
}
|
|
4036
|
-
const
|
|
4037
|
-
|
|
4038
|
-
strict
|
|
4039
|
-
});
|
|
4040
|
-
walkAuthoredFromSchemaDiff(schemaWithDefaultsData, slimResponse.data, [], authoredPaths);
|
|
4414
|
+
const slimBaseline = schema.getEmptyValueAtPath([]);
|
|
4415
|
+
walkAuthoredFromSchemaDiff(schemaWithDefaultsData, slimBaseline, [], authoredPaths);
|
|
4041
4416
|
}
|
|
4042
4417
|
rebuildAuthoredPaths(defaultValues, schemaInitialData);
|
|
4043
4418
|
function filterAuthoredErrors(errors) {
|
|
@@ -4056,7 +4431,7 @@ function createFormStore(options) {
|
|
|
4056
4431
|
});
|
|
4057
4432
|
const form = vue.ref(stubbedInitialData);
|
|
4058
4433
|
const arrayIdentity = createArrayIdentity((arraySegs) => {
|
|
4059
|
-
const v = getAtPath(form.value, arraySegs);
|
|
4434
|
+
const v = getAtPath(vue.toRaw(form.value), arraySegs);
|
|
4060
4435
|
return Array.isArray(v) ? v.length : 0;
|
|
4061
4436
|
});
|
|
4062
4437
|
function arrayElementKey(path) {
|
|
@@ -4099,14 +4474,7 @@ function createFormStore(options) {
|
|
|
4099
4474
|
const segments = paths.segmentsForPathKey(pathKey);
|
|
4100
4475
|
if (segments === null) continue;
|
|
4101
4476
|
if (!schema.isRequiredAtPath(segments)) continue;
|
|
4102
|
-
result.set(pathKey, [
|
|
4103
|
-
{
|
|
4104
|
-
message: "No value supplied",
|
|
4105
|
-
path: [...segments],
|
|
4106
|
-
formKey,
|
|
4107
|
-
code: AttaformErrorCode.NoValueSupplied
|
|
4108
|
-
}
|
|
4109
|
-
]);
|
|
4477
|
+
result.set(pathKey, [makeBlankRequiredError(segments, formKey)]);
|
|
4110
4478
|
}
|
|
4111
4479
|
return result;
|
|
4112
4480
|
});
|
|
@@ -4346,6 +4714,7 @@ function createFormStore(options) {
|
|
|
4346
4714
|
originals,
|
|
4347
4715
|
blankPaths,
|
|
4348
4716
|
originalBlankPaths,
|
|
4717
|
+
authoredPaths,
|
|
4349
4718
|
fieldValidationCounts,
|
|
4350
4719
|
fieldValidatingSince,
|
|
4351
4720
|
fieldValidationState,
|
|
@@ -4355,17 +4724,8 @@ function createFormStore(options) {
|
|
|
4355
4724
|
touchFieldRecord,
|
|
4356
4725
|
decFieldValidation
|
|
4357
4726
|
});
|
|
4358
|
-
function
|
|
4359
|
-
const prev = form.value;
|
|
4360
|
-
if (Object.is(prev, next)) return;
|
|
4727
|
+
function commitWritePatches(patches, meta) {
|
|
4361
4728
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4362
|
-
const patches = [];
|
|
4363
|
-
diffAndApply(prev, next, [], (patch) => {
|
|
4364
|
-
patches.push(patch);
|
|
4365
|
-
});
|
|
4366
|
-
if (!applyChangedKeys(prev, next)) {
|
|
4367
|
-
form.value = next;
|
|
4368
|
-
}
|
|
4369
4729
|
for (const patch of patches) {
|
|
4370
4730
|
const { key } = paths.canonicalizePath(patch.path);
|
|
4371
4731
|
if (patch.kind === "added" && !originals.has(key)) {
|
|
@@ -4380,10 +4740,63 @@ function createFormStore(options) {
|
|
|
4380
4740
|
console.error("[attaform] onFormChange threw:", err);
|
|
4381
4741
|
}
|
|
4382
4742
|
}
|
|
4743
|
+
if (onChangeRegistry.active) onChangeRegistry.dispatch(patches, meta);
|
|
4744
|
+
}
|
|
4745
|
+
function applyFormReplacementWithPath(next, meta, arrayOpPath) {
|
|
4746
|
+
const prev = form.value;
|
|
4747
|
+
if (Object.is(prev, next)) return;
|
|
4748
|
+
const patches = [];
|
|
4749
|
+
diffAndApply(prev, next, [], (patch) => {
|
|
4750
|
+
patches.push(patch);
|
|
4751
|
+
});
|
|
4752
|
+
if (!applyChangedKeys(prev, next, arrayOpPath, [])) {
|
|
4753
|
+
form.value = next;
|
|
4754
|
+
} else if (patches.some(
|
|
4755
|
+
(p) => p.path.length > 0 && typeof p.path[0] === "string" && isShadowedKey(p.path[0])
|
|
4756
|
+
)) {
|
|
4757
|
+
vue.triggerRef(form);
|
|
4758
|
+
}
|
|
4759
|
+
commitWritePatches(patches, meta);
|
|
4760
|
+
}
|
|
4761
|
+
function applyFormReplacement(next, meta) {
|
|
4762
|
+
applyFormReplacementWithPath(next, meta, null);
|
|
4763
|
+
}
|
|
4764
|
+
function applyTargetedWrite(path, completedValue, meta) {
|
|
4765
|
+
const result = tryInPlaceLeafWrite(form.value, path, completedValue);
|
|
4766
|
+
if (!result.applied) {
|
|
4767
|
+
applyFormReplacementWithPath(
|
|
4768
|
+
setAtPathWithSchemaFill(form.value, schema, path, completedValue),
|
|
4769
|
+
meta,
|
|
4770
|
+
meta?.arrayOp !== void 0 ? path : null
|
|
4771
|
+
);
|
|
4772
|
+
return;
|
|
4773
|
+
}
|
|
4774
|
+
const patches = [];
|
|
4775
|
+
diffAndApply(result.old, completedValue, path, (patch) => {
|
|
4776
|
+
patches.push(patch);
|
|
4777
|
+
});
|
|
4778
|
+
commitWritePatches(patches, meta);
|
|
4383
4779
|
}
|
|
4384
4780
|
function setValueAtPath(path, value, meta) {
|
|
4385
|
-
|
|
4386
|
-
|
|
4781
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4782
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4783
|
+
value[idx] = stripSymbolsDeep(value[idx]);
|
|
4784
|
+
}
|
|
4785
|
+
} else {
|
|
4786
|
+
value = stripSymbolsDeep(value);
|
|
4787
|
+
}
|
|
4788
|
+
let slimOk = true;
|
|
4789
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4790
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4791
|
+
if (!isSlimPrimitiveValid(schema, form, [...path, idx], value[idx])) {
|
|
4792
|
+
slimOk = false;
|
|
4793
|
+
break;
|
|
4794
|
+
}
|
|
4795
|
+
}
|
|
4796
|
+
} else {
|
|
4797
|
+
slimOk = isSlimPrimitiveValid(schema, form, path, value);
|
|
4798
|
+
}
|
|
4799
|
+
if (!slimOk) {
|
|
4387
4800
|
return false;
|
|
4388
4801
|
}
|
|
4389
4802
|
if (path.length >= 2) {
|
|
@@ -4476,22 +4889,37 @@ function createFormStore(options) {
|
|
|
4476
4889
|
}
|
|
4477
4890
|
}
|
|
4478
4891
|
}
|
|
4892
|
+
const currentValue = getAtPath(form.value, path);
|
|
4479
4893
|
const pathKey = paths.canonicalizePath(path).key;
|
|
4480
4894
|
if (meta?.blank === true) {
|
|
4481
4895
|
blankPaths.add(pathKey);
|
|
4482
4896
|
} else {
|
|
4483
4897
|
if (blankPaths.has(pathKey)) blankPaths.delete(pathKey);
|
|
4484
|
-
if (meta?.arrayOp === void 0) {
|
|
4898
|
+
if (meta?.arrayOp === void 0 && (isPlainRecord(currentValue) || Array.isArray(currentValue))) {
|
|
4485
4899
|
for (const existingKey of [...blankPaths]) {
|
|
4486
4900
|
if (isPathKeyUnder(existingKey, path)) blankPaths.delete(existingKey);
|
|
4487
4901
|
}
|
|
4488
4902
|
}
|
|
4489
4903
|
}
|
|
4490
4904
|
const wasAuthoredBefore = authoredPaths.has(pathKey);
|
|
4491
|
-
|
|
4905
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4906
|
+
if (path.length > 0) authoredPaths.add(pathKey);
|
|
4907
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4908
|
+
walkAuthoredFromConstraints(value[idx], [...path, idx], authoredPaths);
|
|
4909
|
+
}
|
|
4910
|
+
} else {
|
|
4911
|
+
walkAuthoredFromConstraints(value, path, authoredPaths);
|
|
4912
|
+
}
|
|
4492
4913
|
const newlyAuthored = !wasAuthoredBefore && authoredPaths.has(pathKey);
|
|
4493
|
-
|
|
4494
|
-
|
|
4914
|
+
let completedValue;
|
|
4915
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4916
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4917
|
+
value[idx] = mergeStructural(schema, [...path, idx], value[idx]);
|
|
4918
|
+
}
|
|
4919
|
+
completedValue = value;
|
|
4920
|
+
} else {
|
|
4921
|
+
completedValue = mergeStructural(schema, path, value);
|
|
4922
|
+
}
|
|
4495
4923
|
if (Object.is(currentValue, completedValue)) {
|
|
4496
4924
|
if (newlyAuthored && schema.isPreprocessOrCoerceLeaf(path)) {
|
|
4497
4925
|
const modeForAuthoringTransition = meta?.instance?.validateOn ?? fieldValidationMode;
|
|
@@ -4505,8 +4933,7 @@ function createFormStore(options) {
|
|
|
4505
4933
|
return true;
|
|
4506
4934
|
}
|
|
4507
4935
|
const oldArrayLength = Array.isArray(currentValue) ? currentValue.length : 0;
|
|
4508
|
-
|
|
4509
|
-
applyFormReplacement(nextForm, meta);
|
|
4936
|
+
applyTargetedWrite(path, completedValue, meta);
|
|
4510
4937
|
if (meta?.arrayOp !== void 0) {
|
|
4511
4938
|
const remap = remapForOp(meta.arrayOp, oldArrayLength);
|
|
4512
4939
|
arrayBookkeeping.migrateElementState(path, remap);
|
|
@@ -4589,7 +5016,7 @@ function createFormStore(options) {
|
|
|
4589
5016
|
const prevValidation = fieldValidationState.get(parentKey2);
|
|
4590
5017
|
if (prevValidation !== void 0) {
|
|
4591
5018
|
if (prevValidation.timer !== null) clearTimeout(prevValidation.timer);
|
|
4592
|
-
prevValidation.
|
|
5019
|
+
prevValidation.aborted = true;
|
|
4593
5020
|
fieldValidationState.delete(parentKey2);
|
|
4594
5021
|
}
|
|
4595
5022
|
appliedSync = true;
|
|
@@ -4613,15 +5040,19 @@ function createFormStore(options) {
|
|
|
4613
5040
|
const prev = fieldValidationState.get(key);
|
|
4614
5041
|
if (prev !== void 0) {
|
|
4615
5042
|
if (prev.timer !== null) clearTimeout(prev.timer);
|
|
4616
|
-
prev.
|
|
5043
|
+
prev.aborted = true;
|
|
4617
5044
|
}
|
|
4618
|
-
const
|
|
4619
|
-
|
|
5045
|
+
const fresh = {
|
|
5046
|
+
aborted: false,
|
|
5047
|
+
timer: null,
|
|
5048
|
+
settled: false,
|
|
5049
|
+
released: false
|
|
5050
|
+
};
|
|
4620
5051
|
fieldValidationState.set(key, fresh);
|
|
4621
5052
|
const myEpoch = ++scheduleEpoch;
|
|
4622
5053
|
const run = () => {
|
|
4623
5054
|
fresh.timer = null;
|
|
4624
|
-
if (
|
|
5055
|
+
if (fresh.aborted) return;
|
|
4625
5056
|
let activeIncremented = false;
|
|
4626
5057
|
try {
|
|
4627
5058
|
activeValidations.value += 1;
|
|
@@ -4638,7 +5069,7 @@ function createFormStore(options) {
|
|
|
4638
5069
|
const dataAtScope = subtreeScope ? getAtPath(form.value, path) : form.value;
|
|
4639
5070
|
const scopeKey = subtreeScope ? paths.canonicalizePath(path).key : paths.ROOT_PATH_KEY;
|
|
4640
5071
|
void Promise.resolve().then(() => schema.validateAtPath(dataAtScope, scopePath)).then((response) => {
|
|
4641
|
-
if (
|
|
5072
|
+
if (fresh.aborted) return;
|
|
4642
5073
|
if (myEpoch <= lastCommittedEpoch) return;
|
|
4643
5074
|
lastCommittedEpoch = myEpoch;
|
|
4644
5075
|
if (effectiveMode === "blur") {
|
|
@@ -4675,7 +5106,7 @@ function createFormStore(options) {
|
|
|
4675
5106
|
activeValidations.value = Math.max(0, activeValidations.value - 1);
|
|
4676
5107
|
decFieldValidation(pkey);
|
|
4677
5108
|
}
|
|
4678
|
-
entry.
|
|
5109
|
+
entry.aborted = true;
|
|
4679
5110
|
}
|
|
4680
5111
|
fieldValidationState.clear();
|
|
4681
5112
|
}
|
|
@@ -4691,7 +5122,7 @@ function createFormStore(options) {
|
|
|
4691
5122
|
decFieldValidation(key);
|
|
4692
5123
|
entry.released = true;
|
|
4693
5124
|
}
|
|
4694
|
-
entry.
|
|
5125
|
+
entry.aborted = true;
|
|
4695
5126
|
fieldValidationState.delete(key);
|
|
4696
5127
|
}
|
|
4697
5128
|
}
|
|
@@ -4750,6 +5181,7 @@ function createFormStore(options) {
|
|
|
4750
5181
|
formChangeListeners.clear();
|
|
4751
5182
|
submitSuccessListeners.clear();
|
|
4752
5183
|
resetListeners.clear();
|
|
5184
|
+
onChangeRegistry.dispose();
|
|
4753
5185
|
persistOptIns.clear();
|
|
4754
5186
|
noSyncPaths.clear();
|
|
4755
5187
|
noSyncPathCounts.clear();
|
|
@@ -5055,7 +5487,7 @@ function createFormStore(options) {
|
|
|
5055
5487
|
});
|
|
5056
5488
|
const next = resetResponse.data;
|
|
5057
5489
|
rebuildAuthoredPaths(resetSource, next);
|
|
5058
|
-
applyFormReplacement(next);
|
|
5490
|
+
applyFormReplacement(next, { silent: true });
|
|
5059
5491
|
arrayIdentity.rebaselineAll();
|
|
5060
5492
|
originals.clear();
|
|
5061
5493
|
diffAndApply({}, next, [], (patch) => {
|
|
@@ -5301,6 +5733,7 @@ function createFormStore(options) {
|
|
|
5301
5733
|
settleTransforms,
|
|
5302
5734
|
scheduleFieldValidation,
|
|
5303
5735
|
onFormChange,
|
|
5736
|
+
registerOnChange: onChangeRegistry.register,
|
|
5304
5737
|
onSubmitSuccess,
|
|
5305
5738
|
onReset,
|
|
5306
5739
|
emitSubmitSuccess,
|
|
@@ -5330,19 +5763,12 @@ function captureErrorEntries(map) {
|
|
|
5330
5763
|
for (const [k, v] of map) out.push([k, [...v]]);
|
|
5331
5764
|
return out;
|
|
5332
5765
|
}
|
|
5333
|
-
function pathsEqual(a, b) {
|
|
5334
|
-
if (a.length !== b.length) return false;
|
|
5335
|
-
for (let j = 0; j < a.length; j++) {
|
|
5336
|
-
if (a[j] !== b[j]) return false;
|
|
5337
|
-
}
|
|
5338
|
-
return true;
|
|
5339
|
-
}
|
|
5340
5766
|
function errorFieldsEqual(av, bvi) {
|
|
5341
5767
|
if (av === bvi) return true;
|
|
5342
5768
|
if (av.message !== bvi.message) return false;
|
|
5343
5769
|
if (av.code !== bvi.code) return false;
|
|
5344
5770
|
if (av.formKey !== bvi.formKey) return false;
|
|
5345
|
-
return av.path === bvi.path || pathsEqual(av.path, bvi.path);
|
|
5771
|
+
return av.path === bvi.path || paths.pathsEqual(av.path, bvi.path);
|
|
5346
5772
|
}
|
|
5347
5773
|
function errorsEqual(a, b) {
|
|
5348
5774
|
if (a.length !== b.length) return false;
|
|
@@ -5721,11 +6147,16 @@ function useAbstractForm(configuration, options) {
|
|
|
5721
6147
|
if (merged.autoAria !== void 0) {
|
|
5722
6148
|
apiOptions.autoAria = merged.autoAria;
|
|
5723
6149
|
}
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
6150
|
+
const api = buildFormApi(state, formInstanceId, apiOptions);
|
|
6151
|
+
const onChangeConfig = configuration.onChange;
|
|
6152
|
+
if (onChangeConfig !== void 0) {
|
|
6153
|
+
const handler = typeof onChangeConfig === "function" ? onChangeConfig : onChangeConfig.handler;
|
|
6154
|
+
const onError = typeof onChangeConfig === "function" ? void 0 : onChangeConfig.onError;
|
|
6155
|
+
const options2 = onError === void 0 ? void 0 : { onError };
|
|
6156
|
+
const stop = state.registerOnChange(void 0, handler, options2, () => api);
|
|
6157
|
+
if (vue.getCurrentScope() !== void 0) vue.onScopeDispose(stop);
|
|
6158
|
+
}
|
|
6159
|
+
return api;
|
|
5729
6160
|
}
|
|
5730
6161
|
function mergeWithDefaults(defaults, configuration) {
|
|
5731
6162
|
const strict = configuration.strict ?? defaults.strict;
|
|
@@ -7123,4 +7554,4 @@ exports.unset = unset;
|
|
|
7123
7554
|
exports.useAbstractForm = useAbstractForm;
|
|
7124
7555
|
exports.useRegister = useRegister;
|
|
7125
7556
|
exports.useWizard = useWizard;
|
|
7126
|
-
//# sourceMappingURL=attaform.
|
|
7557
|
+
//# sourceMappingURL=attaform.CjMcwV7W.cjs.map
|