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,5 +1,5 @@
|
|
|
1
|
-
import { computed, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, readonly, toRaw, reactive, watch, markRaw, shallowRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, onBeforeMount, onBeforeUpdate, onMounted, effectScope, nextTick } from 'vue';
|
|
2
|
-
import { _ as __DEV__, a as canonicalizePath, s as segmentsForPathKey,
|
|
1
|
+
import { computed, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, readonly, toRaw, reactive, isRef, toValue, watch, markRaw, triggerRef, shallowRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, onBeforeMount, onBeforeUpdate, onMounted, effectScope, nextTick } from 'vue';
|
|
2
|
+
import { q as pathsEqual, l as isPathPrefix, _ as __DEV__, a as canonicalizePath, s as segmentsForPathKey, F as FORM_ERRORS_PATH_KEY, r as keyForSegments, S as SubmitErrorHandlerError, t as toError, A as AnonPersistError, w as INTERACTIVE_TAG_NAMES, x as getOrAssignElementId, R as ROOT_PATH, y as allowSensitivePersist, z as FORM_ERRORS_PATH, e as ROOT_PATH_KEY, B as segmentsToDotted, C as coerceToPathKey, E as isSensitivePath, G as createPersistOptInRegistry, d as InvalidUseFormConfigError, H as ensureAttaformInstalled, u as useRegistry, J as kFormContext, K as kFormInstanceId, h as ReservedFormKeyError, L as createIsSensitivePath, M as REGISTER_OWNER_MARKER, V as V_REGISTER_MARKER, k as kAttaformWizardActiveStepResolver, N as kAttaformAncestorWizard } from './attaform.BKFwekY2.mjs';
|
|
3
3
|
|
|
4
4
|
function safeAssign(target, key, value) {
|
|
5
5
|
if (key === "__proto__") {
|
|
@@ -34,7 +34,7 @@ function descendStep(value, segment) {
|
|
|
34
34
|
if (typeof value !== "object") return NOT_FOUND;
|
|
35
35
|
if (Array.isArray(value)) {
|
|
36
36
|
if (typeof segment !== "number") return NOT_FOUND;
|
|
37
|
-
if (segment
|
|
37
|
+
if (!(segment in value)) return NOT_FOUND;
|
|
38
38
|
return value[segment];
|
|
39
39
|
}
|
|
40
40
|
const record = value;
|
|
@@ -69,7 +69,7 @@ function hasAtPath(root, path) {
|
|
|
69
69
|
if (current === null || current === void 0) return false;
|
|
70
70
|
if (typeof current !== "object") return false;
|
|
71
71
|
if (Array.isArray(current)) {
|
|
72
|
-
return typeof last === "number" && last
|
|
72
|
+
return typeof last === "number" && last in current;
|
|
73
73
|
}
|
|
74
74
|
const key = typeof last === "number" ? String(last) : last;
|
|
75
75
|
if (isShadowedKey(key)) return safeOwnHas(current, key);
|
|
@@ -98,6 +98,31 @@ function setAtPathOffset(root, path, value, offset) {
|
|
|
98
98
|
safeAssign(rec, head, setAtPathOffset(safeOwnRead(rec, head), path, value, nextOffset));
|
|
99
99
|
return rec;
|
|
100
100
|
}
|
|
101
|
+
const NO_IN_PLACE = { applied: false };
|
|
102
|
+
function tryInPlaceLeafWrite(root, path, value) {
|
|
103
|
+
if (path.length === 0) return NO_IN_PLACE;
|
|
104
|
+
let node = root;
|
|
105
|
+
for (let i = 0; i < path.length; i++) {
|
|
106
|
+
const seg = path[i];
|
|
107
|
+
if (Array.isArray(node)) {
|
|
108
|
+
if (typeof seg !== "number" || seg < 0 || seg >= node.length) return NO_IN_PLACE;
|
|
109
|
+
} else if (isPlainRecord(node)) {
|
|
110
|
+
if (typeof seg !== "string" || isShadowedKey(seg) || !(seg in node)) return NO_IN_PLACE;
|
|
111
|
+
} else {
|
|
112
|
+
return NO_IN_PLACE;
|
|
113
|
+
}
|
|
114
|
+
const container = node;
|
|
115
|
+
if (i < path.length - 1) {
|
|
116
|
+
node = container[seg];
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const old = container[seg];
|
|
120
|
+
if (isPlainRecord(old) || Array.isArray(old)) return NO_IN_PLACE;
|
|
121
|
+
container[seg] = value;
|
|
122
|
+
return { applied: true, old };
|
|
123
|
+
}
|
|
124
|
+
return NO_IN_PLACE;
|
|
125
|
+
}
|
|
101
126
|
function deleteAtPath(root, path) {
|
|
102
127
|
return deleteAtPathOffset(root, path, 0);
|
|
103
128
|
}
|
|
@@ -401,7 +426,7 @@ function diffObjectsLockstep(oldRec, newRec, prefix, visit) {
|
|
|
401
426
|
diffAndApply(oldRec[k], newRec[k], appendSegment(prefix, k), visit);
|
|
402
427
|
}
|
|
403
428
|
}
|
|
404
|
-
function applyChangedKeys(target, source) {
|
|
429
|
+
function applyChangedKeys(target, source, arrayOpPath, currentPath) {
|
|
405
430
|
if (!isDescendable(target) || !isDescendable(source)) return false;
|
|
406
431
|
const targetIsArray = Array.isArray(target);
|
|
407
432
|
const sourceIsArray = Array.isArray(source);
|
|
@@ -419,11 +444,27 @@ function applyChangedKeys(target, source) {
|
|
|
419
444
|
if (targetIsArray) {
|
|
420
445
|
const t = target;
|
|
421
446
|
const s = source;
|
|
422
|
-
if (
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
447
|
+
if (arrayOpPath === null || pathsEqual(currentPath, arrayOpPath)) {
|
|
448
|
+
if (t.length > s.length) t.length = s.length;
|
|
449
|
+
for (const idx of changedFirstSegments) {
|
|
450
|
+
if (typeof idx === "symbol") continue;
|
|
451
|
+
const i = typeof idx === "number" ? idx : Number(idx);
|
|
452
|
+
if (i >= s.length) continue;
|
|
453
|
+
t[i] = s[i];
|
|
454
|
+
}
|
|
455
|
+
} else {
|
|
456
|
+
for (const idx of changedFirstSegments) {
|
|
457
|
+
if (typeof idx === "symbol") continue;
|
|
458
|
+
const i = typeof idx === "number" ? idx : Number(idx);
|
|
459
|
+
if (i >= s.length) continue;
|
|
460
|
+
const childPath = appendSegment(currentPath, i);
|
|
461
|
+
const curEl = t[i];
|
|
462
|
+
const nextEl = s[i];
|
|
463
|
+
if (isPathPrefix(childPath, arrayOpPath) && isDescendable(curEl) && isDescendable(nextEl) && applyChangedKeys(curEl, nextEl, arrayOpPath, childPath)) {
|
|
464
|
+
continue;
|
|
465
|
+
}
|
|
466
|
+
t[i] = nextEl;
|
|
467
|
+
}
|
|
427
468
|
}
|
|
428
469
|
} else {
|
|
429
470
|
const t = target;
|
|
@@ -435,7 +476,14 @@ function applyChangedKeys(target, source) {
|
|
|
435
476
|
for (const k of changedFirstSegments) {
|
|
436
477
|
if (typeof k === "symbol") continue;
|
|
437
478
|
const key = String(k);
|
|
438
|
-
|
|
479
|
+
const nextVal = safeOwnRead(s, key);
|
|
480
|
+
if (arrayOpPath !== null) {
|
|
481
|
+
const curVal = safeOwnRead(t, key);
|
|
482
|
+
if (isDescendable(curVal) && isDescendable(nextVal) && applyChangedKeys(curVal, nextVal, arrayOpPath, appendSegment(currentPath, key))) {
|
|
483
|
+
continue;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
safeAssign(t, key, nextVal);
|
|
439
487
|
}
|
|
440
488
|
}
|
|
441
489
|
return true;
|
|
@@ -547,6 +595,50 @@ function resolveGetDisplayState(config) {
|
|
|
547
595
|
return config ?? defaultDisplayState;
|
|
548
596
|
}
|
|
549
597
|
|
|
598
|
+
const AttaformErrorCode = {
|
|
599
|
+
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
600
|
+
NoValueSupplied: "atta:no-value-supplied",
|
|
601
|
+
/** The schema adapter's `validateAtPath` threw synchronously. */
|
|
602
|
+
AdapterThrew: "atta:adapter-threw",
|
|
603
|
+
/**
|
|
604
|
+
* User code inside a `z.preprocess`, `.refine`, or `.transform`
|
|
605
|
+
* threw (sync or async). The adapter caught the throw and surfaced
|
|
606
|
+
* it as a `ValidationError` at the field path so the form's normal
|
|
607
|
+
* error pipeline handles it instead of leaking as an unhandled
|
|
608
|
+
* rejection or routing through `submitError`.
|
|
609
|
+
*/
|
|
610
|
+
ValidatorThrew: "atta:validator-threw",
|
|
611
|
+
/**
|
|
612
|
+
* A function-form `defaultValues` factory threw or its promise
|
|
613
|
+
* rejected. The runtime captures the raw error on `form.hydrateError`
|
|
614
|
+
* and ALSO surfaces a form-level `ValidationError` (path `[]`) so
|
|
615
|
+
* the standard error pipeline carries the signal. Critical for the
|
|
616
|
+
* SSR round-trip: `hydrateError` itself does not ride the wire
|
|
617
|
+
* payload, but `schemaErrors` does, so the client sees the failure
|
|
618
|
+
* after rehydration without an extra channel.
|
|
619
|
+
*/
|
|
620
|
+
HydrationFailed: "atta:hydration-failed",
|
|
621
|
+
/** The supplied path didn't resolve to any node in the schema. */
|
|
622
|
+
PathNotFound: "atta:path-not-found",
|
|
623
|
+
/**
|
|
624
|
+
* A walked form's `activate()` (async `defaultValues` factory) threw
|
|
625
|
+
* during `wizard.handleSubmit`'s path walk. Surfaced as a synthetic
|
|
626
|
+
* `ValidationError` at the form-level path (`[]`) so the wizard's
|
|
627
|
+
* aggregate error pipeline can carry the failure alongside ordinary
|
|
628
|
+
* validation errors. The raw factory error remains on
|
|
629
|
+
* `form.hydrateError` for retry UX.
|
|
630
|
+
*/
|
|
631
|
+
ActivationFailed: "atta:activation-failed"
|
|
632
|
+
};
|
|
633
|
+
function makeBlankRequiredError(segments, formKey) {
|
|
634
|
+
return {
|
|
635
|
+
message: "No value supplied",
|
|
636
|
+
path: [...segments],
|
|
637
|
+
formKey,
|
|
638
|
+
code: AttaformErrorCode.NoValueSupplied
|
|
639
|
+
};
|
|
640
|
+
}
|
|
641
|
+
|
|
550
642
|
const DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS = 0;
|
|
551
643
|
const DEFAULT_PERSISTENCE_DEBOUNCE_MS = 300;
|
|
552
644
|
const DEFAULT_HISTORY_MAX_SNAPSHOTS = 128;
|
|
@@ -660,7 +752,7 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
660
752
|
const original = state.originals.get(key)?.value;
|
|
661
753
|
const pristine = state.isPristineAtPath(segments);
|
|
662
754
|
const schemaForKey = state.schemaErrors.get(key);
|
|
663
|
-
const blankForKey = state.
|
|
755
|
+
const blankForKey = state.blankPaths.has(key) && state.schema.isRequiredAtPath(segments) ? [makeBlankRequiredError(segments, state.formKey)] : void 0;
|
|
664
756
|
const userForKey = state.userErrors.get(key);
|
|
665
757
|
const errors = [];
|
|
666
758
|
if (schemaForKey !== void 0) errors.push(...schemaForKey);
|
|
@@ -724,9 +816,32 @@ function buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBa
|
|
|
724
816
|
getDisplayState
|
|
725
817
|
);
|
|
726
818
|
}
|
|
819
|
+
function visitActiveLeafPaths(value, base, visit) {
|
|
820
|
+
if (Array.isArray(value)) {
|
|
821
|
+
for (let i = 0; i < value.length; i++) {
|
|
822
|
+
const child = value[i];
|
|
823
|
+
if (Array.isArray(child) || isPlainRecord(child)) {
|
|
824
|
+
visitActiveLeafPaths(child, [...base, i], visit);
|
|
825
|
+
} else {
|
|
826
|
+
visit([...base, i]);
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return;
|
|
830
|
+
}
|
|
831
|
+
if (isPlainRecord(value)) {
|
|
832
|
+
for (const k of Object.keys(value)) {
|
|
833
|
+
const child = value[k];
|
|
834
|
+
if (Array.isArray(child) || isPlainRecord(child)) {
|
|
835
|
+
visitActiveLeafPaths(child, [...base, k], visit);
|
|
836
|
+
} else {
|
|
837
|
+
visit([...base, k]);
|
|
838
|
+
}
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
}
|
|
727
842
|
function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
728
843
|
const formValue = state.form.value;
|
|
729
|
-
const value =
|
|
844
|
+
const value = getAtPath(formValue, segments);
|
|
730
845
|
const original = state.originals.get(key)?.value;
|
|
731
846
|
let pristine = true;
|
|
732
847
|
let blank = true;
|
|
@@ -745,12 +860,16 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
745
860
|
let asyncPending = false;
|
|
746
861
|
const submissionAttempts = state.submissionAttempts.value;
|
|
747
862
|
const blurredLeafSegments = [];
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
863
|
+
const descendantLeaves = [];
|
|
864
|
+
visitActiveLeafPaths(value, segments, (leafSegments) => {
|
|
865
|
+
const { key: leafKey } = keyForSegments(leafSegments);
|
|
866
|
+
const entry = state.originals.get(leafKey);
|
|
867
|
+
if (entry === void 0) return;
|
|
868
|
+
descendantLeaves.push({ key: leafKey, segments: entry.segments });
|
|
869
|
+
});
|
|
870
|
+
for (const { key: leafKey, segments: leafSeg } of descendantLeaves) {
|
|
752
871
|
const leafRecord = state.fields.get(leafKey);
|
|
753
|
-
if (!state.isPristineAtPathByKey(leafKey,
|
|
872
|
+
if (!state.isPristineAtPathByKey(leafKey, leafSeg)) {
|
|
754
873
|
pristine = false;
|
|
755
874
|
dirty = true;
|
|
756
875
|
}
|
|
@@ -761,7 +880,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
761
880
|
if (leafRecord?.interacted === true) interacted = true;
|
|
762
881
|
if (leafRecord?.blurredAfterInteraction === true) {
|
|
763
882
|
blurredAfterInteraction = true;
|
|
764
|
-
blurredLeafSegments.push(
|
|
883
|
+
blurredLeafSegments.push(leafSeg);
|
|
765
884
|
}
|
|
766
885
|
if (leafRecord?.connected === true) connected = true;
|
|
767
886
|
if ((state.fieldValidationCounts.get(leafKey) ?? 0) > 0) {
|
|
@@ -778,7 +897,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
778
897
|
if (leafGateOpen && since !== void 0 && (transformingSince === null || since < transformingSince))
|
|
779
898
|
transformingSince = since;
|
|
780
899
|
}
|
|
781
|
-
if (state.pathHasAsyncValidationByKey(leafKey,
|
|
900
|
+
if (state.pathHasAsyncValidationByKey(leafKey, leafSeg)) asyncPending = true;
|
|
782
901
|
const ts = leafRecord?.updatedAt;
|
|
783
902
|
if (ts !== void 0 && ts !== null) {
|
|
784
903
|
if (updatedAt === null || ts > updatedAt) updatedAt = ts;
|
|
@@ -1405,7 +1524,7 @@ function buildFieldArrayApi(state) {
|
|
|
1405
1524
|
append(path, value) {
|
|
1406
1525
|
const next = readArray(path);
|
|
1407
1526
|
next.push(value);
|
|
1408
|
-
return writeArray(path, next);
|
|
1527
|
+
return writeArray(path, next, { kind: "insert", index: next.length - 1 });
|
|
1409
1528
|
},
|
|
1410
1529
|
prepend(path, value) {
|
|
1411
1530
|
const next = readArray(path);
|
|
@@ -1733,42 +1852,6 @@ function mergeObjectKeys(target, source, path, schema) {
|
|
|
1733
1852
|
return out;
|
|
1734
1853
|
}
|
|
1735
1854
|
|
|
1736
|
-
const AttaformErrorCode = {
|
|
1737
|
-
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
1738
|
-
NoValueSupplied: "atta:no-value-supplied",
|
|
1739
|
-
/** The schema adapter's `validateAtPath` threw synchronously. */
|
|
1740
|
-
AdapterThrew: "atta:adapter-threw",
|
|
1741
|
-
/**
|
|
1742
|
-
* User code inside a `z.preprocess`, `.refine`, or `.transform`
|
|
1743
|
-
* threw (sync or async). The adapter caught the throw and surfaced
|
|
1744
|
-
* it as a `ValidationError` at the field path so the form's normal
|
|
1745
|
-
* error pipeline handles it instead of leaking as an unhandled
|
|
1746
|
-
* rejection or routing through `submitError`.
|
|
1747
|
-
*/
|
|
1748
|
-
ValidatorThrew: "atta:validator-threw",
|
|
1749
|
-
/**
|
|
1750
|
-
* A function-form `defaultValues` factory threw or its promise
|
|
1751
|
-
* rejected. The runtime captures the raw error on `form.hydrateError`
|
|
1752
|
-
* and ALSO surfaces a form-level `ValidationError` (path `[]`) so
|
|
1753
|
-
* the standard error pipeline carries the signal. Critical for the
|
|
1754
|
-
* SSR round-trip: `hydrateError` itself does not ride the wire
|
|
1755
|
-
* payload, but `schemaErrors` does, so the client sees the failure
|
|
1756
|
-
* after rehydration without an extra channel.
|
|
1757
|
-
*/
|
|
1758
|
-
HydrationFailed: "atta:hydration-failed",
|
|
1759
|
-
/** The supplied path didn't resolve to any node in the schema. */
|
|
1760
|
-
PathNotFound: "atta:path-not-found",
|
|
1761
|
-
/**
|
|
1762
|
-
* A walked form's `activate()` (async `defaultValues` factory) threw
|
|
1763
|
-
* during `wizard.handleSubmit`'s path walk. Surfaced as a synthetic
|
|
1764
|
-
* `ValidationError` at the form-level path (`[]`) so the wizard's
|
|
1765
|
-
* aggregate error pipeline can carry the failure alongside ordinary
|
|
1766
|
-
* validation errors. The raw factory error remains on
|
|
1767
|
-
* `form.hydrateError` for retry UX.
|
|
1768
|
-
*/
|
|
1769
|
-
ActivationFailed: "atta:activation-failed"
|
|
1770
|
-
};
|
|
1771
|
-
|
|
1772
1855
|
const warnedNoScopeStores = __DEV__ ? /* @__PURE__ */ new WeakSet() : null;
|
|
1773
1856
|
function buildProcessForm(state, formInstanceId, options = {}) {
|
|
1774
1857
|
const invalidPolicy = options.onInvalidSubmit ?? "focus-first-error";
|
|
@@ -2794,19 +2877,116 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2794
2877
|
}
|
|
2795
2878
|
};
|
|
2796
2879
|
const getFormMetaBase = () => {
|
|
2797
|
-
|
|
2880
|
+
let rollup;
|
|
2881
|
+
const rootBase = () => rollup ?? (rollup = buildContainerFieldStateBase(
|
|
2798
2882
|
state,
|
|
2799
2883
|
ROOT_PATH,
|
|
2800
2884
|
ROOT_PATH_KEY,
|
|
2801
2885
|
formInstanceId
|
|
2802
|
-
);
|
|
2886
|
+
).base);
|
|
2803
2887
|
return {
|
|
2804
|
-
|
|
2888
|
+
// Rollup-derived (FieldStateBase) — the whole rollup builds once, on the
|
|
2889
|
+
// first access of any of these.
|
|
2890
|
+
get value() {
|
|
2891
|
+
return rootBase().value;
|
|
2892
|
+
},
|
|
2893
|
+
get original() {
|
|
2894
|
+
return rootBase().original;
|
|
2895
|
+
},
|
|
2896
|
+
get pristine() {
|
|
2897
|
+
return rootBase().pristine;
|
|
2898
|
+
},
|
|
2899
|
+
get dirty() {
|
|
2900
|
+
return rootBase().dirty;
|
|
2901
|
+
},
|
|
2902
|
+
get focused() {
|
|
2903
|
+
return rootBase().focused;
|
|
2904
|
+
},
|
|
2905
|
+
get blurred() {
|
|
2906
|
+
return rootBase().blurred;
|
|
2907
|
+
},
|
|
2908
|
+
get touched() {
|
|
2909
|
+
return rootBase().touched;
|
|
2910
|
+
},
|
|
2911
|
+
get interacted() {
|
|
2912
|
+
return rootBase().interacted;
|
|
2913
|
+
},
|
|
2914
|
+
get blurredAfterInteraction() {
|
|
2915
|
+
return rootBase().blurredAfterInteraction;
|
|
2916
|
+
},
|
|
2917
|
+
get connected() {
|
|
2918
|
+
return rootBase().connected;
|
|
2919
|
+
},
|
|
2920
|
+
get element() {
|
|
2921
|
+
return rootBase().element;
|
|
2922
|
+
},
|
|
2923
|
+
get elements() {
|
|
2924
|
+
return rootBase().elements;
|
|
2925
|
+
},
|
|
2926
|
+
get updatedAt() {
|
|
2927
|
+
return rootBase().updatedAt;
|
|
2928
|
+
},
|
|
2929
|
+
get errors() {
|
|
2930
|
+
return rootBase().errors;
|
|
2931
|
+
},
|
|
2932
|
+
get validating() {
|
|
2933
|
+
return rootBase().validating;
|
|
2934
|
+
},
|
|
2935
|
+
get valid() {
|
|
2936
|
+
return rootBase().valid;
|
|
2937
|
+
},
|
|
2938
|
+
get transforming() {
|
|
2939
|
+
return rootBase().transforming;
|
|
2940
|
+
},
|
|
2941
|
+
get busy() {
|
|
2942
|
+
return rootBase().busy;
|
|
2943
|
+
},
|
|
2944
|
+
get transformError() {
|
|
2945
|
+
return rootBase().transformError;
|
|
2946
|
+
},
|
|
2947
|
+
get path() {
|
|
2948
|
+
return rootBase().path;
|
|
2949
|
+
},
|
|
2950
|
+
get id() {
|
|
2951
|
+
return rootBase().id;
|
|
2952
|
+
},
|
|
2953
|
+
get aria() {
|
|
2954
|
+
return rootBase().aria;
|
|
2955
|
+
},
|
|
2956
|
+
get key() {
|
|
2957
|
+
return rootBase().key;
|
|
2958
|
+
},
|
|
2959
|
+
get blank() {
|
|
2960
|
+
return rootBase().blank;
|
|
2961
|
+
},
|
|
2962
|
+
get label() {
|
|
2963
|
+
return rootBase().label;
|
|
2964
|
+
},
|
|
2965
|
+
get description() {
|
|
2966
|
+
return rootBase().description;
|
|
2967
|
+
},
|
|
2968
|
+
get placeholder() {
|
|
2969
|
+
return rootBase().placeholder;
|
|
2970
|
+
},
|
|
2971
|
+
get meta() {
|
|
2972
|
+
return rootBase().meta;
|
|
2973
|
+
},
|
|
2974
|
+
get errorCount() {
|
|
2975
|
+
return rootBase().errors.length;
|
|
2976
|
+
},
|
|
2977
|
+
// Form-level scalars — EAGER reads, tracked on every field-state eval.
|
|
2978
|
+
// They are O(1) refs that never change on a keystroke, so tracking them
|
|
2979
|
+
// per field costs nothing on the hot path. Kept eager (NOT lazy like the
|
|
2980
|
+
// rollup) because behaviors beyond the predicate's own output depend on
|
|
2981
|
+
// every field re-evaluating when they flip — most notably, the display
|
|
2982
|
+
// engine is cleared on submit (revealing held spinners), and that
|
|
2983
|
+
// imperative reset only becomes visible if `submitting` is a tracked dep
|
|
2984
|
+
// of each field. Matches the pre-bust dependency set for these scalars
|
|
2985
|
+
// exactly.
|
|
2805
2986
|
submitting: state.submitting.value,
|
|
2806
2987
|
submissionAttempts: state.submissionAttempts.value,
|
|
2807
2988
|
departAttempts: state.departAttempts.value,
|
|
2808
2989
|
submitError: state.submitError.value,
|
|
2809
|
-
errorCount: rootBase.errors.length,
|
|
2810
2990
|
submitted: state.submitted.value,
|
|
2811
2991
|
instanceId: formInstanceId
|
|
2812
2992
|
};
|
|
@@ -2841,14 +3021,19 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2841
3021
|
const segments = canonicalizePath(pathInput).segments;
|
|
2842
3022
|
return computed(() => getAtPath(state.form.value, segments));
|
|
2843
3023
|
}
|
|
2844
|
-
function setValueImpl(pathOrValue, maybeValue) {
|
|
2845
|
-
|
|
3024
|
+
function setValueImpl(pathOrValue, maybeValue, maybeOptions) {
|
|
3025
|
+
const argc = arguments.length;
|
|
3026
|
+
const isPathForm = argc >= 2 && (typeof pathOrValue === "string" || Array.isArray(pathOrValue));
|
|
3027
|
+
const options2 = isPathForm ? maybeOptions : argc >= 2 ? maybeValue : void 0;
|
|
3028
|
+
const silent = options2?.silent === true;
|
|
3029
|
+
const writeMeta = (extra) => withInstanceMeta(silent ? { ...extra, silent: true } : extra);
|
|
3030
|
+
if (!isPathForm) {
|
|
2846
3031
|
const next = typeof pathOrValue === "function" ? pathOrValue(structuralSnapshot(state.form.value)) : pathOrValue;
|
|
2847
3032
|
const walked2 = walkUnsetSentinels(
|
|
2848
3033
|
next,
|
|
2849
3034
|
state.schema
|
|
2850
3035
|
);
|
|
2851
|
-
const ok2 = state.setValueAtPath([], walked2.cleanedValues,
|
|
3036
|
+
const ok2 = state.setValueAtPath([], walked2.cleanedValues, writeMeta());
|
|
2852
3037
|
if (!ok2) return false;
|
|
2853
3038
|
reMarkBlanksAfterSubstitution(walked2.paths);
|
|
2854
3039
|
return true;
|
|
@@ -2862,7 +3047,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2862
3047
|
if (parentDU?.discriminatorKey === last) {
|
|
2863
3048
|
const slimDefault = state.schema.getEmptyValueAtPath(segments);
|
|
2864
3049
|
const blank = blankForKind(slimDefault);
|
|
2865
|
-
return state.setValueAtPath(segments, blank,
|
|
3050
|
+
return state.setValueAtPath(segments, blank, writeMeta({ blank: true }));
|
|
2866
3051
|
}
|
|
2867
3052
|
}
|
|
2868
3053
|
const blankPaths = [];
|
|
@@ -2873,9 +3058,9 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2873
3058
|
);
|
|
2874
3059
|
const segmentsKey = canonicalizePath(segments).key;
|
|
2875
3060
|
if (blankPaths.length === 1 && blankPaths[0] === segmentsKey) {
|
|
2876
|
-
return state.setValueAtPath(segments, expanded,
|
|
3061
|
+
return state.setValueAtPath(segments, expanded, writeMeta({ blank: true }));
|
|
2877
3062
|
}
|
|
2878
|
-
const ok2 = state.setValueAtPath(segments, expanded,
|
|
3063
|
+
const ok2 = state.setValueAtPath(segments, expanded, writeMeta());
|
|
2879
3064
|
if (!ok2) return false;
|
|
2880
3065
|
for (const pathKey of blankPaths) {
|
|
2881
3066
|
const blankSegments = segmentsForPathKey(pathKey);
|
|
@@ -2883,7 +3068,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2883
3068
|
state.setValueAtPath(
|
|
2884
3069
|
blankSegments,
|
|
2885
3070
|
state.getValueAtPath(blankSegments),
|
|
2886
|
-
|
|
3071
|
+
writeMeta({ blank: true })
|
|
2887
3072
|
);
|
|
2888
3073
|
}
|
|
2889
3074
|
return true;
|
|
@@ -2903,7 +3088,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2903
3088
|
segments,
|
|
2904
3089
|
state.schema
|
|
2905
3090
|
);
|
|
2906
|
-
const ok = state.setValueAtPath(segments, walked.cleanedValues,
|
|
3091
|
+
const ok = state.setValueAtPath(segments, walked.cleanedValues, writeMeta());
|
|
2907
3092
|
if (!ok) return false;
|
|
2908
3093
|
reMarkBlanksAfterSubstitution(walked.paths);
|
|
2909
3094
|
return true;
|
|
@@ -3274,7 +3459,19 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
3274
3459
|
}
|
|
3275
3460
|
return Object.freeze(out);
|
|
3276
3461
|
}
|
|
3277
|
-
|
|
3462
|
+
const formHandle = {
|
|
3463
|
+
current: void 0
|
|
3464
|
+
};
|
|
3465
|
+
function onChangeImpl(a, b, c) {
|
|
3466
|
+
const sourced = typeof b === "function";
|
|
3467
|
+
const source = sourced ? a : void 0;
|
|
3468
|
+
const handler = sourced ? b : a;
|
|
3469
|
+
const options2 = sourced ? c : b;
|
|
3470
|
+
const stop = state.registerOnChange(source, handler, options2, () => formHandle.current);
|
|
3471
|
+
if (getCurrentScope() !== void 0) onScopeDispose(stop);
|
|
3472
|
+
return stop;
|
|
3473
|
+
}
|
|
3474
|
+
const api = {
|
|
3278
3475
|
handleSubmit: gated(handleSubmit),
|
|
3279
3476
|
// Callable readonly Proxies (`values`, `fields`, `errors`) and the
|
|
3280
3477
|
// reactive containers (`meta`, `history`, `blankPaths`) are exposed
|
|
@@ -3361,8 +3558,11 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
3361
3558
|
get blankPaths() {
|
|
3362
3559
|
void state.activate();
|
|
3363
3560
|
return blankPathsView;
|
|
3364
|
-
}
|
|
3561
|
+
},
|
|
3562
|
+
onChange: onChangeImpl
|
|
3365
3563
|
};
|
|
3564
|
+
formHandle.current = api;
|
|
3565
|
+
return api;
|
|
3366
3566
|
}
|
|
3367
3567
|
|
|
3368
3568
|
const IDLE = Object.freeze({ display: "idle" });
|
|
@@ -3789,6 +3989,7 @@ function createArrayBookkeeping(deps) {
|
|
|
3789
3989
|
originals,
|
|
3790
3990
|
blankPaths,
|
|
3791
3991
|
originalBlankPaths,
|
|
3992
|
+
authoredPaths,
|
|
3792
3993
|
fieldValidationCounts,
|
|
3793
3994
|
fieldValidatingSince,
|
|
3794
3995
|
fieldValidationState,
|
|
@@ -3816,6 +4017,7 @@ function createArrayBookkeeping(deps) {
|
|
|
3816
4017
|
}));
|
|
3817
4018
|
migrateSetSubtree(blankPaths, arrayPath, remap);
|
|
3818
4019
|
migrateSetSubtree(originalBlankPaths, arrayPath, remap);
|
|
4020
|
+
migrateSetSubtree(authoredPaths, arrayPath, remap);
|
|
3819
4021
|
migrateMapSubtree(fieldValidatingSince, arrayPath, remap, (since) => since);
|
|
3820
4022
|
migrateMapSubtree(fieldValidationCounts, arrayPath, remap, (count) => count);
|
|
3821
4023
|
arrayIdentity.applyRemap(arrayPath, remap);
|
|
@@ -3859,7 +4061,7 @@ function createArrayBookkeeping(deps) {
|
|
|
3859
4061
|
activeValidations.value = Math.max(0, activeValidations.value - 1);
|
|
3860
4062
|
decFieldValidation(key);
|
|
3861
4063
|
}
|
|
3862
|
-
entry.
|
|
4064
|
+
entry.aborted = true;
|
|
3863
4065
|
fieldValidationState.delete(key);
|
|
3864
4066
|
}
|
|
3865
4067
|
}
|
|
@@ -3871,6 +4073,170 @@ function createArrayBookkeeping(deps) {
|
|
|
3871
4073
|
};
|
|
3872
4074
|
}
|
|
3873
4075
|
|
|
4076
|
+
const NOOP_STOP = () => {
|
|
4077
|
+
};
|
|
4078
|
+
function isThenable(value) {
|
|
4079
|
+
return value !== null && (typeof value === "object" || typeof value === "function") && typeof value.then === "function";
|
|
4080
|
+
}
|
|
4081
|
+
function isSuppressed(meta) {
|
|
4082
|
+
return meta?.hydration === true || meta?.crossTab === true || meta?.silent === true;
|
|
4083
|
+
}
|
|
4084
|
+
function canonicalizeSourceList(raw) {
|
|
4085
|
+
const list = typeof raw === "string" ? [raw] : raw;
|
|
4086
|
+
const out = [];
|
|
4087
|
+
const seen = /* @__PURE__ */ new Set();
|
|
4088
|
+
for (const entry of list) {
|
|
4089
|
+
const { segments, key } = canonicalizePath(entry);
|
|
4090
|
+
if (seen.has(key)) continue;
|
|
4091
|
+
seen.add(key);
|
|
4092
|
+
out.push({ segments, key, dotted: segmentsToDotted(segments) });
|
|
4093
|
+
}
|
|
4094
|
+
return out;
|
|
4095
|
+
}
|
|
4096
|
+
function makeResolver(source) {
|
|
4097
|
+
if (source === void 0) {
|
|
4098
|
+
const root = [{ segments: ROOT_PATH, key: ROOT_PATH_KEY, dotted: "" }];
|
|
4099
|
+
return () => root;
|
|
4100
|
+
}
|
|
4101
|
+
if (typeof source !== "function" && !isRef(source)) {
|
|
4102
|
+
const fixed = canonicalizeSourceList(source);
|
|
4103
|
+
return () => fixed;
|
|
4104
|
+
}
|
|
4105
|
+
return () => canonicalizeSourceList(toValue(source));
|
|
4106
|
+
}
|
|
4107
|
+
function createOnChangeRegistry(deps) {
|
|
4108
|
+
const handlers = /* @__PURE__ */ new Set();
|
|
4109
|
+
function isCurrent(reg, key, token) {
|
|
4110
|
+
return reg.runs.get(key)?.token === token;
|
|
4111
|
+
}
|
|
4112
|
+
function routeError(reg, error, source, changed, value, previous, attempt, token) {
|
|
4113
|
+
if (reg.onError === void 0) {
|
|
4114
|
+
if (__DEV__) {
|
|
4115
|
+
console.error(
|
|
4116
|
+
`[attaform] onChange handler threw for path '${source.dotted}' \u2014 error swallowed. Pass { onError } to handle it. Original error:`,
|
|
4117
|
+
error
|
|
4118
|
+
);
|
|
4119
|
+
}
|
|
4120
|
+
return;
|
|
4121
|
+
}
|
|
4122
|
+
const retry = () => {
|
|
4123
|
+
if (!isCurrent(reg, source.key, token)) return;
|
|
4124
|
+
runHandler(reg, source, changed, value, previous, attempt + 1);
|
|
4125
|
+
};
|
|
4126
|
+
const errCtx = {
|
|
4127
|
+
path: source.dotted,
|
|
4128
|
+
value,
|
|
4129
|
+
attempt,
|
|
4130
|
+
retry,
|
|
4131
|
+
form: reg.getForm()
|
|
4132
|
+
};
|
|
4133
|
+
try {
|
|
4134
|
+
reg.onError(error, errCtx);
|
|
4135
|
+
} catch (err) {
|
|
4136
|
+
if (__DEV__) console.error("[attaform] onChange onError threw:", err);
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
function runHandler(reg, source, changed, value, previous, attempt) {
|
|
4140
|
+
const prior = reg.runs.get(source.key);
|
|
4141
|
+
if (prior) prior.controller.abort();
|
|
4142
|
+
const controller = new AbortController();
|
|
4143
|
+
const token = ++reg.seq;
|
|
4144
|
+
reg.runs.set(source.key, { token, controller });
|
|
4145
|
+
const ctx = {
|
|
4146
|
+
path: source.dotted,
|
|
4147
|
+
previous,
|
|
4148
|
+
signal: controller.signal,
|
|
4149
|
+
attempt,
|
|
4150
|
+
form: reg.getForm(),
|
|
4151
|
+
changed
|
|
4152
|
+
};
|
|
4153
|
+
let result;
|
|
4154
|
+
try {
|
|
4155
|
+
result = reg.handler(value, ctx);
|
|
4156
|
+
} catch (error) {
|
|
4157
|
+
routeError(reg, error, source, changed, value, previous, attempt, token);
|
|
4158
|
+
return;
|
|
4159
|
+
}
|
|
4160
|
+
if (isThenable(result)) {
|
|
4161
|
+
result.then(void 0, (error) => {
|
|
4162
|
+
if (isCurrent(reg, source.key, token)) {
|
|
4163
|
+
routeError(reg, error, source, changed, value, previous, attempt, token);
|
|
4164
|
+
}
|
|
4165
|
+
});
|
|
4166
|
+
}
|
|
4167
|
+
}
|
|
4168
|
+
function dispatch(patches, meta) {
|
|
4169
|
+
if (handlers.size === 0 || isSuppressed(meta)) return;
|
|
4170
|
+
for (const reg of handlers) {
|
|
4171
|
+
let sources;
|
|
4172
|
+
try {
|
|
4173
|
+
sources = reg.resolve();
|
|
4174
|
+
} catch (error) {
|
|
4175
|
+
if (__DEV__) console.error("[attaform] onChange source getter threw:", error);
|
|
4176
|
+
continue;
|
|
4177
|
+
}
|
|
4178
|
+
for (const source of sources) {
|
|
4179
|
+
let changed;
|
|
4180
|
+
for (const patch of patches) {
|
|
4181
|
+
if (isPathPrefix(source.segments, patch.path) || isPathPrefix(patch.path, source.segments)) {
|
|
4182
|
+
(changed ?? (changed = [])).push(segmentsToDotted(patch.path));
|
|
4183
|
+
}
|
|
4184
|
+
}
|
|
4185
|
+
if (changed === void 0) continue;
|
|
4186
|
+
const value = deps.getValueAtPath(source.segments);
|
|
4187
|
+
const previous = reg.previous.has(source.key) ? reg.previous.get(source.key) : value;
|
|
4188
|
+
reg.previous.set(source.key, value);
|
|
4189
|
+
runHandler(reg, source, changed, value, previous, 0);
|
|
4190
|
+
}
|
|
4191
|
+
}
|
|
4192
|
+
}
|
|
4193
|
+
function register(source, handler, options, getForm) {
|
|
4194
|
+
if (deps.ssr) return NOOP_STOP;
|
|
4195
|
+
const reg = {
|
|
4196
|
+
handler,
|
|
4197
|
+
onError: options?.onError,
|
|
4198
|
+
getForm,
|
|
4199
|
+
resolve: makeResolver(source),
|
|
4200
|
+
previous: /* @__PURE__ */ new Map(),
|
|
4201
|
+
runs: /* @__PURE__ */ new Map(),
|
|
4202
|
+
seq: 0
|
|
4203
|
+
};
|
|
4204
|
+
try {
|
|
4205
|
+
for (const { key, segments } of reg.resolve()) {
|
|
4206
|
+
reg.previous.set(key, deps.getValueAtPath(segments));
|
|
4207
|
+
}
|
|
4208
|
+
} catch (error) {
|
|
4209
|
+
if (__DEV__) console.error("[attaform] onChange source getter threw at registration:", error);
|
|
4210
|
+
}
|
|
4211
|
+
handlers.add(reg);
|
|
4212
|
+
let stopped = false;
|
|
4213
|
+
return () => {
|
|
4214
|
+
if (stopped) return;
|
|
4215
|
+
stopped = true;
|
|
4216
|
+
handlers.delete(reg);
|
|
4217
|
+
for (const run of reg.runs.values()) run.controller.abort();
|
|
4218
|
+
reg.runs.clear();
|
|
4219
|
+
reg.previous.clear();
|
|
4220
|
+
};
|
|
4221
|
+
}
|
|
4222
|
+
function dispose() {
|
|
4223
|
+
for (const reg of handlers) {
|
|
4224
|
+
for (const run of reg.runs.values()) run.controller.abort();
|
|
4225
|
+
reg.runs.clear();
|
|
4226
|
+
reg.previous.clear();
|
|
4227
|
+
}
|
|
4228
|
+
handlers.clear();
|
|
4229
|
+
}
|
|
4230
|
+
return {
|
|
4231
|
+
get active() {
|
|
4232
|
+
return handlers.size > 0;
|
|
4233
|
+
},
|
|
4234
|
+
register,
|
|
4235
|
+
dispatch,
|
|
4236
|
+
dispose
|
|
4237
|
+
};
|
|
4238
|
+
}
|
|
4239
|
+
|
|
3874
4240
|
function isHydratedFieldRecord(value) {
|
|
3875
4241
|
if (typeof value !== "object" || value === null) return false;
|
|
3876
4242
|
const r = value;
|
|
@@ -3955,6 +4321,17 @@ function walkAuthoredFromConstraints(value, prefix, out) {
|
|
|
3955
4321
|
}
|
|
3956
4322
|
}
|
|
3957
4323
|
}
|
|
4324
|
+
function freshElementIndices(op) {
|
|
4325
|
+
switch (op.kind) {
|
|
4326
|
+
case "insert":
|
|
4327
|
+
case "replace-at":
|
|
4328
|
+
return [op.index];
|
|
4329
|
+
case "remove":
|
|
4330
|
+
case "swap":
|
|
4331
|
+
case "move":
|
|
4332
|
+
return [];
|
|
4333
|
+
}
|
|
4334
|
+
}
|
|
3958
4335
|
function walkAuthoredFromSchemaDiff(withDefaults, withoutDefaults, prefix, out) {
|
|
3959
4336
|
if (isPlainRecord(withDefaults) && isPlainRecord(withoutDefaults)) {
|
|
3960
4337
|
const left = withDefaults;
|
|
@@ -3993,6 +4370,7 @@ function createFormStore(options) {
|
|
|
3993
4370
|
const formChangeListeners = /* @__PURE__ */ new Set();
|
|
3994
4371
|
const submitSuccessListeners = /* @__PURE__ */ new Set();
|
|
3995
4372
|
const resetListeners = /* @__PURE__ */ new Set();
|
|
4373
|
+
const onChangeRegistry = createOnChangeRegistry({ getValueAtPath, ssr });
|
|
3996
4374
|
const persistOptIns = createPersistOptInRegistry();
|
|
3997
4375
|
const noSyncPaths = /* @__PURE__ */ new Set();
|
|
3998
4376
|
const noSyncPathCounts = /* @__PURE__ */ new Map();
|
|
@@ -4031,11 +4409,8 @@ function createFormStore(options) {
|
|
|
4031
4409
|
if (constraints !== void 0) {
|
|
4032
4410
|
walkAuthoredFromConstraints(constraints, [], authoredPaths);
|
|
4033
4411
|
}
|
|
4034
|
-
const
|
|
4035
|
-
|
|
4036
|
-
strict
|
|
4037
|
-
});
|
|
4038
|
-
walkAuthoredFromSchemaDiff(schemaWithDefaultsData, slimResponse.data, [], authoredPaths);
|
|
4412
|
+
const slimBaseline = schema.getEmptyValueAtPath([]);
|
|
4413
|
+
walkAuthoredFromSchemaDiff(schemaWithDefaultsData, slimBaseline, [], authoredPaths);
|
|
4039
4414
|
}
|
|
4040
4415
|
rebuildAuthoredPaths(defaultValues, schemaInitialData);
|
|
4041
4416
|
function filterAuthoredErrors(errors) {
|
|
@@ -4054,7 +4429,7 @@ function createFormStore(options) {
|
|
|
4054
4429
|
});
|
|
4055
4430
|
const form = ref(stubbedInitialData);
|
|
4056
4431
|
const arrayIdentity = createArrayIdentity((arraySegs) => {
|
|
4057
|
-
const v = getAtPath(form.value, arraySegs);
|
|
4432
|
+
const v = getAtPath(toRaw(form.value), arraySegs);
|
|
4058
4433
|
return Array.isArray(v) ? v.length : 0;
|
|
4059
4434
|
});
|
|
4060
4435
|
function arrayElementKey(path) {
|
|
@@ -4097,14 +4472,7 @@ function createFormStore(options) {
|
|
|
4097
4472
|
const segments = segmentsForPathKey(pathKey);
|
|
4098
4473
|
if (segments === null) continue;
|
|
4099
4474
|
if (!schema.isRequiredAtPath(segments)) continue;
|
|
4100
|
-
result.set(pathKey, [
|
|
4101
|
-
{
|
|
4102
|
-
message: "No value supplied",
|
|
4103
|
-
path: [...segments],
|
|
4104
|
-
formKey,
|
|
4105
|
-
code: AttaformErrorCode.NoValueSupplied
|
|
4106
|
-
}
|
|
4107
|
-
]);
|
|
4475
|
+
result.set(pathKey, [makeBlankRequiredError(segments, formKey)]);
|
|
4108
4476
|
}
|
|
4109
4477
|
return result;
|
|
4110
4478
|
});
|
|
@@ -4344,6 +4712,7 @@ function createFormStore(options) {
|
|
|
4344
4712
|
originals,
|
|
4345
4713
|
blankPaths,
|
|
4346
4714
|
originalBlankPaths,
|
|
4715
|
+
authoredPaths,
|
|
4347
4716
|
fieldValidationCounts,
|
|
4348
4717
|
fieldValidatingSince,
|
|
4349
4718
|
fieldValidationState,
|
|
@@ -4353,17 +4722,8 @@ function createFormStore(options) {
|
|
|
4353
4722
|
touchFieldRecord,
|
|
4354
4723
|
decFieldValidation
|
|
4355
4724
|
});
|
|
4356
|
-
function
|
|
4357
|
-
const prev = form.value;
|
|
4358
|
-
if (Object.is(prev, next)) return;
|
|
4725
|
+
function commitWritePatches(patches, meta) {
|
|
4359
4726
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4360
|
-
const patches = [];
|
|
4361
|
-
diffAndApply(prev, next, [], (patch) => {
|
|
4362
|
-
patches.push(patch);
|
|
4363
|
-
});
|
|
4364
|
-
if (!applyChangedKeys(prev, next)) {
|
|
4365
|
-
form.value = next;
|
|
4366
|
-
}
|
|
4367
4727
|
for (const patch of patches) {
|
|
4368
4728
|
const { key } = canonicalizePath(patch.path);
|
|
4369
4729
|
if (patch.kind === "added" && !originals.has(key)) {
|
|
@@ -4378,10 +4738,63 @@ function createFormStore(options) {
|
|
|
4378
4738
|
console.error("[attaform] onFormChange threw:", err);
|
|
4379
4739
|
}
|
|
4380
4740
|
}
|
|
4741
|
+
if (onChangeRegistry.active) onChangeRegistry.dispatch(patches, meta);
|
|
4742
|
+
}
|
|
4743
|
+
function applyFormReplacementWithPath(next, meta, arrayOpPath) {
|
|
4744
|
+
const prev = form.value;
|
|
4745
|
+
if (Object.is(prev, next)) return;
|
|
4746
|
+
const patches = [];
|
|
4747
|
+
diffAndApply(prev, next, [], (patch) => {
|
|
4748
|
+
patches.push(patch);
|
|
4749
|
+
});
|
|
4750
|
+
if (!applyChangedKeys(prev, next, arrayOpPath, [])) {
|
|
4751
|
+
form.value = next;
|
|
4752
|
+
} else if (patches.some(
|
|
4753
|
+
(p) => p.path.length > 0 && typeof p.path[0] === "string" && isShadowedKey(p.path[0])
|
|
4754
|
+
)) {
|
|
4755
|
+
triggerRef(form);
|
|
4756
|
+
}
|
|
4757
|
+
commitWritePatches(patches, meta);
|
|
4758
|
+
}
|
|
4759
|
+
function applyFormReplacement(next, meta) {
|
|
4760
|
+
applyFormReplacementWithPath(next, meta, null);
|
|
4761
|
+
}
|
|
4762
|
+
function applyTargetedWrite(path, completedValue, meta) {
|
|
4763
|
+
const result = tryInPlaceLeafWrite(form.value, path, completedValue);
|
|
4764
|
+
if (!result.applied) {
|
|
4765
|
+
applyFormReplacementWithPath(
|
|
4766
|
+
setAtPathWithSchemaFill(form.value, schema, path, completedValue),
|
|
4767
|
+
meta,
|
|
4768
|
+
meta?.arrayOp !== void 0 ? path : null
|
|
4769
|
+
);
|
|
4770
|
+
return;
|
|
4771
|
+
}
|
|
4772
|
+
const patches = [];
|
|
4773
|
+
diffAndApply(result.old, completedValue, path, (patch) => {
|
|
4774
|
+
patches.push(patch);
|
|
4775
|
+
});
|
|
4776
|
+
commitWritePatches(patches, meta);
|
|
4381
4777
|
}
|
|
4382
4778
|
function setValueAtPath(path, value, meta) {
|
|
4383
|
-
|
|
4384
|
-
|
|
4779
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4780
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4781
|
+
value[idx] = stripSymbolsDeep(value[idx]);
|
|
4782
|
+
}
|
|
4783
|
+
} else {
|
|
4784
|
+
value = stripSymbolsDeep(value);
|
|
4785
|
+
}
|
|
4786
|
+
let slimOk = true;
|
|
4787
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4788
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4789
|
+
if (!isSlimPrimitiveValid(schema, form, [...path, idx], value[idx])) {
|
|
4790
|
+
slimOk = false;
|
|
4791
|
+
break;
|
|
4792
|
+
}
|
|
4793
|
+
}
|
|
4794
|
+
} else {
|
|
4795
|
+
slimOk = isSlimPrimitiveValid(schema, form, path, value);
|
|
4796
|
+
}
|
|
4797
|
+
if (!slimOk) {
|
|
4385
4798
|
return false;
|
|
4386
4799
|
}
|
|
4387
4800
|
if (path.length >= 2) {
|
|
@@ -4474,22 +4887,37 @@ function createFormStore(options) {
|
|
|
4474
4887
|
}
|
|
4475
4888
|
}
|
|
4476
4889
|
}
|
|
4890
|
+
const currentValue = getAtPath(form.value, path);
|
|
4477
4891
|
const pathKey = canonicalizePath(path).key;
|
|
4478
4892
|
if (meta?.blank === true) {
|
|
4479
4893
|
blankPaths.add(pathKey);
|
|
4480
4894
|
} else {
|
|
4481
4895
|
if (blankPaths.has(pathKey)) blankPaths.delete(pathKey);
|
|
4482
|
-
if (meta?.arrayOp === void 0) {
|
|
4896
|
+
if (meta?.arrayOp === void 0 && (isPlainRecord(currentValue) || Array.isArray(currentValue))) {
|
|
4483
4897
|
for (const existingKey of [...blankPaths]) {
|
|
4484
4898
|
if (isPathKeyUnder(existingKey, path)) blankPaths.delete(existingKey);
|
|
4485
4899
|
}
|
|
4486
4900
|
}
|
|
4487
4901
|
}
|
|
4488
4902
|
const wasAuthoredBefore = authoredPaths.has(pathKey);
|
|
4489
|
-
|
|
4903
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4904
|
+
if (path.length > 0) authoredPaths.add(pathKey);
|
|
4905
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4906
|
+
walkAuthoredFromConstraints(value[idx], [...path, idx], authoredPaths);
|
|
4907
|
+
}
|
|
4908
|
+
} else {
|
|
4909
|
+
walkAuthoredFromConstraints(value, path, authoredPaths);
|
|
4910
|
+
}
|
|
4490
4911
|
const newlyAuthored = !wasAuthoredBefore && authoredPaths.has(pathKey);
|
|
4491
|
-
|
|
4492
|
-
|
|
4912
|
+
let completedValue;
|
|
4913
|
+
if (meta?.arrayOp !== void 0 && Array.isArray(value)) {
|
|
4914
|
+
for (const idx of freshElementIndices(meta.arrayOp)) {
|
|
4915
|
+
value[idx] = mergeStructural(schema, [...path, idx], value[idx]);
|
|
4916
|
+
}
|
|
4917
|
+
completedValue = value;
|
|
4918
|
+
} else {
|
|
4919
|
+
completedValue = mergeStructural(schema, path, value);
|
|
4920
|
+
}
|
|
4493
4921
|
if (Object.is(currentValue, completedValue)) {
|
|
4494
4922
|
if (newlyAuthored && schema.isPreprocessOrCoerceLeaf(path)) {
|
|
4495
4923
|
const modeForAuthoringTransition = meta?.instance?.validateOn ?? fieldValidationMode;
|
|
@@ -4503,8 +4931,7 @@ function createFormStore(options) {
|
|
|
4503
4931
|
return true;
|
|
4504
4932
|
}
|
|
4505
4933
|
const oldArrayLength = Array.isArray(currentValue) ? currentValue.length : 0;
|
|
4506
|
-
|
|
4507
|
-
applyFormReplacement(nextForm, meta);
|
|
4934
|
+
applyTargetedWrite(path, completedValue, meta);
|
|
4508
4935
|
if (meta?.arrayOp !== void 0) {
|
|
4509
4936
|
const remap = remapForOp(meta.arrayOp, oldArrayLength);
|
|
4510
4937
|
arrayBookkeeping.migrateElementState(path, remap);
|
|
@@ -4587,7 +5014,7 @@ function createFormStore(options) {
|
|
|
4587
5014
|
const prevValidation = fieldValidationState.get(parentKey2);
|
|
4588
5015
|
if (prevValidation !== void 0) {
|
|
4589
5016
|
if (prevValidation.timer !== null) clearTimeout(prevValidation.timer);
|
|
4590
|
-
prevValidation.
|
|
5017
|
+
prevValidation.aborted = true;
|
|
4591
5018
|
fieldValidationState.delete(parentKey2);
|
|
4592
5019
|
}
|
|
4593
5020
|
appliedSync = true;
|
|
@@ -4611,15 +5038,19 @@ function createFormStore(options) {
|
|
|
4611
5038
|
const prev = fieldValidationState.get(key);
|
|
4612
5039
|
if (prev !== void 0) {
|
|
4613
5040
|
if (prev.timer !== null) clearTimeout(prev.timer);
|
|
4614
|
-
prev.
|
|
5041
|
+
prev.aborted = true;
|
|
4615
5042
|
}
|
|
4616
|
-
const
|
|
4617
|
-
|
|
5043
|
+
const fresh = {
|
|
5044
|
+
aborted: false,
|
|
5045
|
+
timer: null,
|
|
5046
|
+
settled: false,
|
|
5047
|
+
released: false
|
|
5048
|
+
};
|
|
4618
5049
|
fieldValidationState.set(key, fresh);
|
|
4619
5050
|
const myEpoch = ++scheduleEpoch;
|
|
4620
5051
|
const run = () => {
|
|
4621
5052
|
fresh.timer = null;
|
|
4622
|
-
if (
|
|
5053
|
+
if (fresh.aborted) return;
|
|
4623
5054
|
let activeIncremented = false;
|
|
4624
5055
|
try {
|
|
4625
5056
|
activeValidations.value += 1;
|
|
@@ -4636,7 +5067,7 @@ function createFormStore(options) {
|
|
|
4636
5067
|
const dataAtScope = subtreeScope ? getAtPath(form.value, path) : form.value;
|
|
4637
5068
|
const scopeKey = subtreeScope ? canonicalizePath(path).key : ROOT_PATH_KEY;
|
|
4638
5069
|
void Promise.resolve().then(() => schema.validateAtPath(dataAtScope, scopePath)).then((response) => {
|
|
4639
|
-
if (
|
|
5070
|
+
if (fresh.aborted) return;
|
|
4640
5071
|
if (myEpoch <= lastCommittedEpoch) return;
|
|
4641
5072
|
lastCommittedEpoch = myEpoch;
|
|
4642
5073
|
if (effectiveMode === "blur") {
|
|
@@ -4673,7 +5104,7 @@ function createFormStore(options) {
|
|
|
4673
5104
|
activeValidations.value = Math.max(0, activeValidations.value - 1);
|
|
4674
5105
|
decFieldValidation(pkey);
|
|
4675
5106
|
}
|
|
4676
|
-
entry.
|
|
5107
|
+
entry.aborted = true;
|
|
4677
5108
|
}
|
|
4678
5109
|
fieldValidationState.clear();
|
|
4679
5110
|
}
|
|
@@ -4689,7 +5120,7 @@ function createFormStore(options) {
|
|
|
4689
5120
|
decFieldValidation(key);
|
|
4690
5121
|
entry.released = true;
|
|
4691
5122
|
}
|
|
4692
|
-
entry.
|
|
5123
|
+
entry.aborted = true;
|
|
4693
5124
|
fieldValidationState.delete(key);
|
|
4694
5125
|
}
|
|
4695
5126
|
}
|
|
@@ -4748,6 +5179,7 @@ function createFormStore(options) {
|
|
|
4748
5179
|
formChangeListeners.clear();
|
|
4749
5180
|
submitSuccessListeners.clear();
|
|
4750
5181
|
resetListeners.clear();
|
|
5182
|
+
onChangeRegistry.dispose();
|
|
4751
5183
|
persistOptIns.clear();
|
|
4752
5184
|
noSyncPaths.clear();
|
|
4753
5185
|
noSyncPathCounts.clear();
|
|
@@ -5053,7 +5485,7 @@ function createFormStore(options) {
|
|
|
5053
5485
|
});
|
|
5054
5486
|
const next = resetResponse.data;
|
|
5055
5487
|
rebuildAuthoredPaths(resetSource, next);
|
|
5056
|
-
applyFormReplacement(next);
|
|
5488
|
+
applyFormReplacement(next, { silent: true });
|
|
5057
5489
|
arrayIdentity.rebaselineAll();
|
|
5058
5490
|
originals.clear();
|
|
5059
5491
|
diffAndApply({}, next, [], (patch) => {
|
|
@@ -5299,6 +5731,7 @@ function createFormStore(options) {
|
|
|
5299
5731
|
settleTransforms,
|
|
5300
5732
|
scheduleFieldValidation,
|
|
5301
5733
|
onFormChange,
|
|
5734
|
+
registerOnChange: onChangeRegistry.register,
|
|
5302
5735
|
onSubmitSuccess,
|
|
5303
5736
|
onReset,
|
|
5304
5737
|
emitSubmitSuccess,
|
|
@@ -5328,13 +5761,6 @@ function captureErrorEntries(map) {
|
|
|
5328
5761
|
for (const [k, v] of map) out.push([k, [...v]]);
|
|
5329
5762
|
return out;
|
|
5330
5763
|
}
|
|
5331
|
-
function pathsEqual(a, b) {
|
|
5332
|
-
if (a.length !== b.length) return false;
|
|
5333
|
-
for (let j = 0; j < a.length; j++) {
|
|
5334
|
-
if (a[j] !== b[j]) return false;
|
|
5335
|
-
}
|
|
5336
|
-
return true;
|
|
5337
|
-
}
|
|
5338
5764
|
function errorFieldsEqual(av, bvi) {
|
|
5339
5765
|
if (av === bvi) return true;
|
|
5340
5766
|
if (av.message !== bvi.message) return false;
|
|
@@ -5719,11 +6145,16 @@ function useAbstractForm(configuration, options) {
|
|
|
5719
6145
|
if (merged.autoAria !== void 0) {
|
|
5720
6146
|
apiOptions.autoAria = merged.autoAria;
|
|
5721
6147
|
}
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
6148
|
+
const api = buildFormApi(state, formInstanceId, apiOptions);
|
|
6149
|
+
const onChangeConfig = configuration.onChange;
|
|
6150
|
+
if (onChangeConfig !== void 0) {
|
|
6151
|
+
const handler = typeof onChangeConfig === "function" ? onChangeConfig : onChangeConfig.handler;
|
|
6152
|
+
const onError = typeof onChangeConfig === "function" ? void 0 : onChangeConfig.onError;
|
|
6153
|
+
const options2 = onError === void 0 ? void 0 : { onError };
|
|
6154
|
+
const stop = state.registerOnChange(void 0, handler, options2, () => api);
|
|
6155
|
+
if (getCurrentScope() !== void 0) onScopeDispose(stop);
|
|
6156
|
+
}
|
|
6157
|
+
return api;
|
|
5727
6158
|
}
|
|
5728
6159
|
function mergeWithDefaults(defaults, configuration) {
|
|
5729
6160
|
const strict = configuration.strict ?? defaults.strict;
|
|
@@ -7090,4 +7521,4 @@ function warnIfAmbientWizardProviderHadDuplicates() {
|
|
|
7090
7521
|
}
|
|
7091
7522
|
|
|
7092
7523
|
export { AttaformErrorCode as A, deleteAtPath as B, safeOwnRead as C, DEFAULT_TIMINGS as D, humanize as E, PERSISTENCE_MODULE_KEY as P, injectWizard as a, isUnset as b, useRegister as c, useWizard as d, isPlainRecord as e, safeAssign as f, diffAndApply as g, slimKindOf as h, injectForm as i, applyPatchesForward as j, normalizeNumericOption as k, lazy as l, defaultCoercionRules as m, normalizePersistConfig as n, defaultDisplayState as o, defineCoercion as p, makeDefaultDisplayState as q, useAbstractForm as r, structuralSnapshot as s, getAtPath as t, unset as u, setAtPath as v, resolveStorageKeyBase as w, DEFAULT_PERSISTENCE_DEBOUNCE_MS as x, cleanupOrphanKeys as y, mergeSparseHydration as z };
|
|
7093
|
-
//# sourceMappingURL=attaform.
|
|
7524
|
+
//# sourceMappingURL=attaform.CsB-iKbU.mjs.map
|