attaform 0.29.0 → 0.30.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/abstract.d.mts +5 -5
- package/dist/abstract.mjs +4 -4
- package/dist/dev/abstract.mjs +4 -4
- package/dist/dev/chunks/dev-key-collision-warnings.mjs +47 -8
- package/dist/dev/chunks/devtools.mjs +1 -1
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +1 -2
- package/dist/dev/index.mjs +5 -5
- package/dist/dev/runtime/plugins/attaform.mjs +3 -3
- package/dist/dev/shared/{attaform-dev.BO-71R54.mjs → attaform-dev.BK6Ge2qR.mjs} +34 -188
- package/dist/dev/shared/{attaform-dev.A-TpJW0B.mjs → attaform-dev.BQc5QV3Y.mjs} +1 -19
- package/dist/dev/shared/{attaform-dev.DrzObAZo.mjs → attaform-dev.BcNtyOmf.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.ButTkwHd.mjs → attaform-dev.BcYT6tFh.mjs} +7 -8
- package/dist/dev/shared/{attaform-dev.BgM6FdtA.mjs → attaform-dev.BisFstxh.mjs} +91 -59
- package/dist/dev/shared/{attaform-dev.DHuydLAC.mjs → attaform-dev.CQ2rJiAX.mjs} +560 -631
- package/dist/dev/shared/{attaform-dev.D8aoKb89.mjs → attaform-dev.D6CLvaQT.mjs} +8 -8
- package/dist/dev/shared/{attaform-dev.q6UutkCx.mjs → attaform-dev.DTrHonpc.mjs} +69 -120
- package/dist/dev/shared/{attaform-dev.DD5m2W51.mjs → attaform-dev.DUZckyV8.mjs} +1 -3
- package/dist/dev/zod-v3.mjs +6 -6
- package/dist/dev/zod-v4.mjs +6 -6
- package/dist/dev/zod.mjs +5 -5
- package/dist/directive.d.mts +2 -2
- package/dist/directive.mjs +1 -1
- package/dist/history.d.mts +1 -1
- package/dist/history.mjs +1 -2
- package/dist/index.d.mts +6 -6
- package/dist/index.mjs +5 -5
- package/dist/nuxt.d.mts +2 -11
- package/dist/nuxt.mjs +0 -1
- package/dist/runtime/plugins/attaform.mjs +3 -3
- package/dist/shared/{attaform.DffRL5pP.mjs → attaform.B3resMQ1.mjs} +8 -8
- package/dist/shared/{attaform.Cvao8bW5.mjs → attaform.BRDDQeHV.mjs} +6 -6
- package/dist/shared/{attaform.C2MVyuxC.mjs → attaform.BXneBxEj.mjs} +34 -188
- package/dist/shared/{attaform.BndjUUYX.mjs → attaform.ByWP6kSx.mjs} +4 -4
- package/dist/shared/{attaform.D1fnTifF.mjs → attaform.CJ8DpRGj.mjs} +69 -120
- package/dist/shared/{attaform.B0dKL8ST.mjs → attaform.CUfrMK7t.mjs} +91 -59
- package/dist/shared/{attaform.CZYt_5N_.mjs → attaform.CdZIEf7_.mjs} +1 -19
- package/dist/shared/{attaform.axHXVQO7.d.mts → attaform.Clz0ArIi.d.mts} +1 -1
- package/dist/shared/{attaform.CZMAYwSK.mjs → attaform.DNJOWjQw.mjs} +559 -588
- package/dist/shared/{attaform.CIWLMY-R.d.mts → attaform.Rc9u4Vfw.d.mts} +1 -1
- package/dist/shared/{attaform.DDtqHYv1.d.mts → attaform.UGyOK83T.d.mts} +115 -214
- package/dist/shared/{attaform.D0x-qSXm.mjs → attaform.WiGdIqgx.mjs} +1 -3
- package/dist/shared/{attaform.CsoeRi3P.d.mts → attaform.bKLzMU0o.d.mts} +99 -493
- package/dist/vite.mjs +5 -0
- package/dist/zod-v3.d.mts +4 -4
- package/dist/zod-v3.mjs +6 -6
- package/dist/zod-v4.d.mts +9 -9
- package/dist/zod-v4.mjs +6 -6
- package/dist/zod.d.mts +4 -4
- package/dist/zod.mjs +5 -5
- package/package.json +3 -2
- package/skills/attaform/SKILL.md +1 -1
- package/skills/attaform/references/custom-components.md +1 -1
- package/dist/chunks/fingerprint.mjs +0 -183
- package/dist/chunks/fingerprint2.mjs +0 -159
- package/dist/dev/chunks/fingerprint.mjs +0 -183
- package/dist/dev/chunks/fingerprint2.mjs +0 -159
- package/dist/dev/shared/attaform-dev.BxfsuwBR.mjs +0 -44
- package/dist/shared/attaform.BxfsuwBR.mjs +0 -44
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { computed, readonly, toRaw, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, reactive, shallowRef, toValue, watch, triggerRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, onBeforeMount, onBeforeUpdate, onMounted, effectScope, nextTick } from 'vue';
|
|
2
|
-
import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform.
|
|
3
|
-
import { c as armDomBinding } from './attaform.
|
|
1
|
+
import { computed, readonly, toRaw, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, reactive, shallowReactive, shallowRef, toValue, watch, triggerRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, onBeforeMount, onBeforeUpdate, onMounted, effectScope, nextTick } from 'vue';
|
|
2
|
+
import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform.WiGdIqgx.mjs';
|
|
3
|
+
import { c as armDomBinding } from './attaform.B3resMQ1.mjs';
|
|
4
4
|
import { R as REGISTER_OWNER_MARKER, b as V_REGISTER_MARKER } from './attaform.KvlEedlF.mjs';
|
|
5
|
-
import { A as ANONYMOUS_FORM_KEY_PREFIX,
|
|
6
|
-
import { i as isPathPrefix, e as canonicalizePath,
|
|
5
|
+
import { A as ANONYMOUS_FORM_KEY_PREFIX, i as isShadowedKey, d as safeOwnHas, a as safeOwnRead, e as consumerHas, f as spreadConsumerRecord, g as copyConsumerArray, r as readConsumerIndex, b as safeAssign, h as consumerKeys, j as readConsumerProp, k as diffAndApply, p as pickDefined, s as structuralSnapshot, n as normalizeNumericOption, l as DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS, m as consumerSymbolKeys, o as applyChangedKeys, R as RESERVED_KEY_PREFIX, q as DEFAULT_MAX_RECURSION_DEPTH, t as ANONYMOUS_WIZARD_KEY_PREFIX } from './attaform.BRDDQeHV.mjs';
|
|
6
|
+
import { i as isPathPrefix, e as canonicalizePath, k as keyForSegments, m as mapSegmentKeys, b as ROOT_PATH_KEY, s as segmentsForPathKey, S as SubmitErrorHandlerError, t as toError, j as groupErrorsByKey, n as normalizeErrorInput, h as SET_MEMBER_SEGMENT, R as ROOT_PATH, l as normalizeErrorInputs, a as InvalidUseFormConfigError, d as ReservedFormKeyError } from './attaform.CdZIEf7_.mjs';
|
|
7
7
|
|
|
8
8
|
const AttaformErrorCode = {
|
|
9
9
|
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
@@ -78,11 +78,6 @@ function makeBlankRequiredError(segments) {
|
|
|
78
78
|
}
|
|
79
79
|
const NO_ERRORS = Object.freeze([]);
|
|
80
80
|
|
|
81
|
-
function crossCopyState(key, create) {
|
|
82
|
-
const carrier = globalThis;
|
|
83
|
-
return carrier[key] ?? (carrier[key] = create());
|
|
84
|
-
}
|
|
85
|
-
|
|
86
81
|
function isGateOpen(field, formMeta) {
|
|
87
82
|
return formMeta.submissionAttempts > 0 || field.blurredAfterInteraction === true;
|
|
88
83
|
}
|
|
@@ -104,45 +99,32 @@ function earliestNonNull(a, b) {
|
|
|
104
99
|
return a < b ? a : b;
|
|
105
100
|
}
|
|
106
101
|
const DEFAULT_TIMINGS = { showDelay: 120, minVisible: 120 };
|
|
102
|
+
const { showDelay, minVisible } = DEFAULT_TIMINGS;
|
|
107
103
|
const FOCUS_OUT_GRACE = 16;
|
|
108
|
-
const
|
|
109
|
-
|
|
110
|
-
()
|
|
111
|
-
);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
if (!isGateOpen(field, formMeta)) return { display: verdict };
|
|
122
|
-
const inFlightSince = earliestNonNull(validatingSince, transformingSince);
|
|
123
|
-
if (inFlightSince === null) {
|
|
124
|
-
if (prev.display === "pending") {
|
|
125
|
-
const shownAt = prev.pendingShownAt ?? now;
|
|
126
|
-
if (now < shownAt + minVisible)
|
|
127
|
-
return { display: "pending", pendingShownAt: shownAt, reviewAt: shownAt + minVisible };
|
|
128
|
-
}
|
|
129
|
-
return { display: verdict };
|
|
130
|
-
}
|
|
131
|
-
if (prev.display === "pending")
|
|
132
|
-
return { display: "pending", pendingShownAt: prev.pendingShownAt ?? now };
|
|
133
|
-
const window = field.focused === false ? Math.min(showDelay, FOCUS_OUT_GRACE) : showDelay;
|
|
134
|
-
if (now - inFlightSince < window) {
|
|
135
|
-
return { display: prev.display, reviewAt: inFlightSince + window };
|
|
104
|
+
const defaultDisplayState = (prev, { field, formMeta, validatingSince, transformingSince, now }) => {
|
|
105
|
+
const verdict = computeVerdict(field, formMeta);
|
|
106
|
+
if (!isGateOpen(field, formMeta)) return { display: verdict };
|
|
107
|
+
const inFlightSince = earliestNonNull(validatingSince, transformingSince);
|
|
108
|
+
if (inFlightSince === null) {
|
|
109
|
+
if (prev.display === "pending") {
|
|
110
|
+
const shownAt = prev.pendingShownAt ?? now;
|
|
111
|
+
if (now < shownAt + minVisible)
|
|
112
|
+
return {
|
|
113
|
+
display: "pending",
|
|
114
|
+
pendingShownAt: shownAt,
|
|
115
|
+
reviewAt: shownAt + minVisible
|
|
116
|
+
};
|
|
136
117
|
}
|
|
137
|
-
return { display:
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
118
|
+
return { display: verdict };
|
|
119
|
+
}
|
|
120
|
+
if (prev.display === "pending")
|
|
121
|
+
return { display: "pending", pendingShownAt: prev.pendingShownAt ?? now };
|
|
122
|
+
const window = field.focused === false ? Math.min(showDelay, FOCUS_OUT_GRACE) : showDelay;
|
|
123
|
+
if (now - inFlightSince < window) {
|
|
124
|
+
return { display: prev.display, reviewAt: inFlightSince + window };
|
|
125
|
+
}
|
|
126
|
+
return { display: "pending", pendingShownAt: now, reviewAt: now + minVisible };
|
|
127
|
+
};
|
|
146
128
|
|
|
147
129
|
function hashStableString(input, seed = 0) {
|
|
148
130
|
let h1 = 3735928559 ^ seed;
|
|
@@ -230,16 +212,27 @@ function descendStep(value, segment) {
|
|
|
230
212
|
}
|
|
231
213
|
function getAtPath(root, path) {
|
|
232
214
|
if (path.length === 0) return root;
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
215
|
+
try {
|
|
216
|
+
let current = root;
|
|
217
|
+
for (const segment of path) {
|
|
218
|
+
const next = descendStep(current, segment);
|
|
219
|
+
if (next === NOT_FOUND) return void 0;
|
|
220
|
+
current = next;
|
|
221
|
+
}
|
|
222
|
+
return current;
|
|
223
|
+
} catch {
|
|
224
|
+
return void 0;
|
|
238
225
|
}
|
|
239
|
-
return current;
|
|
240
226
|
}
|
|
241
227
|
function hasAtPath(root, path) {
|
|
242
228
|
if (path.length === 0) return true;
|
|
229
|
+
try {
|
|
230
|
+
return hasAtPathUnguarded(root, path);
|
|
231
|
+
} catch {
|
|
232
|
+
return false;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function hasAtPathUnguarded(root, path) {
|
|
243
236
|
let current = root;
|
|
244
237
|
for (let i = 0; i < path.length - 1; i++) {
|
|
245
238
|
const segment = path[i];
|
|
@@ -266,29 +259,15 @@ function isPlainRecord(value) {
|
|
|
266
259
|
const proto = Object.getPrototypeOf(value);
|
|
267
260
|
return proto === null || proto === Object.prototype;
|
|
268
261
|
}
|
|
262
|
+
const NO_SCHEMA_DEFAULTS = /* @__PURE__ */ new Set();
|
|
263
|
+
const NO_SCHEMA_FILL = {
|
|
264
|
+
getDefaultAtPath: () => void 0,
|
|
265
|
+
arrayShapeAtPath: () => null,
|
|
266
|
+
getSlimPrimitiveTypesAtPath: () => NO_SCHEMA_DEFAULTS,
|
|
267
|
+
entryKeyKindAtPath: () => void 0
|
|
268
|
+
};
|
|
269
269
|
function setAtPath(root, path, value) {
|
|
270
|
-
return
|
|
271
|
-
}
|
|
272
|
-
function setAtPathOffset(root, path, value, offset) {
|
|
273
|
-
if (offset >= path.length) return value;
|
|
274
|
-
const head = path[offset];
|
|
275
|
-
const nextOffset = offset + 1;
|
|
276
|
-
if (root instanceof Map) {
|
|
277
|
-
const next = new Map(root);
|
|
278
|
-
const key = mapKeyForSegment(root, head);
|
|
279
|
-
next.set(key, setAtPathOffset(root.get(key), path, value, nextOffset));
|
|
280
|
-
return next;
|
|
281
|
-
}
|
|
282
|
-
if (!isRebuildableContainer(root, head)) return root;
|
|
283
|
-
if (typeof head === "number") {
|
|
284
|
-
const arr = Array.isArray(root) ? [...root] : [];
|
|
285
|
-
while (arr.length <= head) arr.push(void 0);
|
|
286
|
-
arr[head] = setAtPathOffset(arr[head], path, value, nextOffset);
|
|
287
|
-
return arr;
|
|
288
|
-
}
|
|
289
|
-
const rec = isPlainRecord(root) ? { ...root } : {};
|
|
290
|
-
safeAssign(rec, head, setAtPathOffset(safeOwnRead(rec, head), path, value, nextOffset));
|
|
291
|
-
return rec;
|
|
270
|
+
return setAtPathWithSchemaFill(root, NO_SCHEMA_FILL, path, value);
|
|
292
271
|
}
|
|
293
272
|
const NO_IN_PLACE = { applied: false };
|
|
294
273
|
function tryInPlaceLeafWrite(root, path, value) {
|
|
@@ -494,10 +473,10 @@ function setAtPathWithSchemaFillImpl(root, schema, fullPath, value, startIdx) {
|
|
|
494
473
|
}
|
|
495
474
|
const rec = isPlainRecord(root) ? { ...root } : {};
|
|
496
475
|
if (isLeafStep) {
|
|
497
|
-
rec
|
|
476
|
+
safeAssign(rec, head, value);
|
|
498
477
|
return rec;
|
|
499
478
|
}
|
|
500
|
-
const existing = rec
|
|
479
|
+
const existing = safeOwnRead(rec, head);
|
|
501
480
|
let childRoot;
|
|
502
481
|
if (existing === void 0 || existing !== null && typeof existing !== "object") {
|
|
503
482
|
const intermPath = [...fullPath.slice(0, startIdx + 1)];
|
|
@@ -506,7 +485,11 @@ function setAtPathWithSchemaFillImpl(root, schema, fullPath, value, startIdx) {
|
|
|
506
485
|
} else {
|
|
507
486
|
childRoot = existing;
|
|
508
487
|
}
|
|
509
|
-
|
|
488
|
+
safeAssign(
|
|
489
|
+
rec,
|
|
490
|
+
head,
|
|
491
|
+
setAtPathWithSchemaFillImpl(childRoot, schema, fullPath, value, startIdx + 1)
|
|
492
|
+
);
|
|
510
493
|
return rec;
|
|
511
494
|
}
|
|
512
495
|
|
|
@@ -523,16 +506,15 @@ function isUnderStubAncestor(state, segments) {
|
|
|
523
506
|
}
|
|
524
507
|
return false;
|
|
525
508
|
}
|
|
526
|
-
function buildFieldStateAccessor(state, formInstanceId, getFormMetaBase, sweep
|
|
509
|
+
function buildFieldStateAccessor(state, formInstanceId, getFormMetaBase, sweep) {
|
|
527
510
|
const cache = /* @__PURE__ */ new Map();
|
|
528
|
-
const predicate = options?.getDisplayState;
|
|
529
511
|
sweep.onEvict((key) => cache.delete(key));
|
|
530
512
|
return function getFieldState(pathInput) {
|
|
531
513
|
const { segments, key } = canonicalizePath(pathInput);
|
|
532
514
|
const cached = cache.get(key);
|
|
533
515
|
if (cached !== void 0) return cached;
|
|
534
516
|
const c = computed(
|
|
535
|
-
() => state.schema.isLeafAtPath(segments) ? buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBase
|
|
517
|
+
() => state.schema.isLeafAtPath(segments) ? buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBase) : buildContainerFieldState(state, segments, key, formInstanceId, getFormMetaBase)
|
|
536
518
|
);
|
|
537
519
|
cache.set(key, c);
|
|
538
520
|
sweep.track(segments, key);
|
|
@@ -549,7 +531,7 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
549
531
|
const record = state.fields.get(key);
|
|
550
532
|
const value = state.getValueAtPath(segments);
|
|
551
533
|
const original = state.originals.get(key)?.value;
|
|
552
|
-
const pristine = state.
|
|
534
|
+
const pristine = state.isPristineAtPathByKey(key, segments);
|
|
553
535
|
const cell = state.errorCells.get(key);
|
|
554
536
|
const schemaForKey = cell !== void 0 && cell.schema.length > 0 ? cell.schema : void 0;
|
|
555
537
|
const blankForKey = state.blankPaths.has(key) && state.schema.isRequiredAtPath(segments) ? [makeBlankRequiredError(segments)] : void 0;
|
|
@@ -561,7 +543,7 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
561
543
|
const validating = (state.fieldValidationCounts.get(key) ?? 0) > 0;
|
|
562
544
|
const transforming = (state.fieldTransformCounts.get(key) ?? 0) > 0;
|
|
563
545
|
const transformError = state.transformErrors.get(key) ?? null;
|
|
564
|
-
const gated = state.
|
|
546
|
+
const gated = state.pathHasAsyncValidationByKey(key, segments) && !state.firstValidationDone.value;
|
|
565
547
|
const isOrphan = segments.length > 0 && !hasAtPath(state.form.value, segments) && isUnderStubAncestor(state, segments);
|
|
566
548
|
const valid = !gated && errors.length === 0 && !validating && !isOrphan;
|
|
567
549
|
const elementRecord = state.domBinding.value?.elements.get(key);
|
|
@@ -604,7 +586,7 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
604
586
|
meta: resolved.meta
|
|
605
587
|
};
|
|
606
588
|
}
|
|
607
|
-
function buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBase
|
|
589
|
+
function buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBase) {
|
|
608
590
|
const base = buildLeafFieldStateBase(state, segments, key, formInstanceId);
|
|
609
591
|
const validatingSince = state.fieldValidatingSince.get(key) ?? null;
|
|
610
592
|
const transformingSince = state.fieldTransformingSince.get(key) ?? null;
|
|
@@ -617,9 +599,8 @@ function buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBa
|
|
|
617
599
|
transformingSince,
|
|
618
600
|
false,
|
|
619
601
|
// revealedDescendantError: leaves have no descendants
|
|
620
|
-
false
|
|
602
|
+
false
|
|
621
603
|
// isRoot: a leaf is never the form root
|
|
622
|
-
getDisplayState
|
|
623
604
|
);
|
|
624
605
|
}
|
|
625
606
|
function visitActiveLeafPaths(value, base, visit) {
|
|
@@ -717,7 +698,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
717
698
|
pristine = false;
|
|
718
699
|
dirty = true;
|
|
719
700
|
}
|
|
720
|
-
const errors = aggregateErrorsAt(state, segments);
|
|
701
|
+
const errors = aggregateErrorsAt(state, segments, key);
|
|
721
702
|
const revealedDescendantError = errors.length > 0 && errors.some((e) => {
|
|
722
703
|
const ePath = e.path;
|
|
723
704
|
if (ePath.length === segments.length && ePath.every((s, i) => s === segments[i])) return false;
|
|
@@ -725,7 +706,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
725
706
|
if (ePath.length === 1 && ePath[0] === "") return blurredAfterInteraction;
|
|
726
707
|
return blurredLeafSegments.some((s) => isPathPrefix(ePath, s));
|
|
727
708
|
});
|
|
728
|
-
if (!asyncPending && state.
|
|
709
|
+
if (!asyncPending && state.pathHasAsyncValidationByKey(key, segments)) asyncPending = true;
|
|
729
710
|
if ((state.fieldValidationCounts.get(key) ?? 0) > 0) {
|
|
730
711
|
validating = true;
|
|
731
712
|
const since = state.fieldValidatingSince.get(key);
|
|
@@ -796,7 +777,7 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
796
777
|
revealedDescendantError
|
|
797
778
|
};
|
|
798
779
|
}
|
|
799
|
-
function buildContainerFieldState(state, segments, key, formInstanceId, getFormMetaBase
|
|
780
|
+
function buildContainerFieldState(state, segments, key, formInstanceId, getFormMetaBase) {
|
|
800
781
|
const { base, validatingSince, transformingSince, revealedDescendantError } = buildContainerFieldStateBase(state, segments, key, formInstanceId);
|
|
801
782
|
return decorateWithDerivedProps(
|
|
802
783
|
base,
|
|
@@ -806,14 +787,12 @@ function buildContainerFieldState(state, segments, key, formInstanceId, getFormM
|
|
|
806
787
|
validatingSince,
|
|
807
788
|
transformingSince,
|
|
808
789
|
revealedDescendantError,
|
|
809
|
-
segments.length === 0
|
|
810
|
-
getDisplayState
|
|
790
|
+
segments.length === 0
|
|
811
791
|
);
|
|
812
792
|
}
|
|
813
|
-
function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingSince, transformingSince, revealedDescendantError, isRoot
|
|
793
|
+
function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingSince, transformingSince, revealedDescendantError, isRoot) {
|
|
814
794
|
const firstError = base.errors[0];
|
|
815
795
|
const firstOwnError = base.ownErrors[0];
|
|
816
|
-
const predicate = getDisplayState ?? state.getDisplayState;
|
|
817
796
|
const formMeta = getFormMetaBase();
|
|
818
797
|
const ctx = {
|
|
819
798
|
field: base,
|
|
@@ -824,16 +803,9 @@ function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingS
|
|
|
824
803
|
// flight) so the reducer returns the plain verdict and hydration matches.
|
|
825
804
|
now: state.ssr ? 0 : Date.now()
|
|
826
805
|
};
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
machine = state.displayEngine.resolve(key, ctx, predicate);
|
|
831
|
-
} catch (err) {
|
|
832
|
-
machine = state.displayEngine.resolve(key, ctx, defaultDisplayState);
|
|
833
|
-
rollupApplies = true;
|
|
834
|
-
}
|
|
835
|
-
const submitValidating = rollupApplies && isRoot && state.submitting.value && state.activeValidations.value > 0;
|
|
836
|
-
const resolvedDisplayState = machine.display === "pending" || submitValidating ? "pending" : rollupApplies && revealedDescendantError ? "error" : machine.display;
|
|
806
|
+
const machine = state.displayEngine.resolve(key, ctx, defaultDisplayState);
|
|
807
|
+
const submitValidating = isRoot && state.submitting.value && state.activeValidations.value > 0;
|
|
808
|
+
const resolvedDisplayState = machine.display === "pending" || submitValidating ? "pending" : revealedDescendantError ? "error" : machine.display;
|
|
837
809
|
const displayState = base.disabled === true ? "idle" : resolvedDisplayState;
|
|
838
810
|
return {
|
|
839
811
|
...base,
|
|
@@ -846,26 +818,33 @@ function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingS
|
|
|
846
818
|
firstOwnError
|
|
847
819
|
};
|
|
848
820
|
}
|
|
849
|
-
function aggregateErrorsAt(state, prefix) {
|
|
821
|
+
function aggregateErrorsAt(state, prefix, prefixKey) {
|
|
822
|
+
const candidates = state.errorWindowAt(prefix, prefixKey);
|
|
823
|
+
if (candidates.length === 0) return [];
|
|
850
824
|
const formValue = state.form.value;
|
|
825
|
+
const cells = state.errorCells;
|
|
851
826
|
const buckets = /* @__PURE__ */ new Map();
|
|
852
|
-
const
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
827
|
+
for (const { key, segments } of candidates) {
|
|
828
|
+
if (!isPathPrefix(prefix, segments)) continue;
|
|
829
|
+
if (segments.length > 0 && !hasAtPath(formValue, segments)) continue;
|
|
830
|
+
const cell = cells.get(key);
|
|
831
|
+
const blankList = state.blankPaths.has(key) && state.schema.isRequiredAtPath(segments) ? [makeBlankRequiredError(segments)] : void 0;
|
|
832
|
+
const schemaList = cell?.schema;
|
|
833
|
+
const userList = cell?.user;
|
|
834
|
+
const total = (schemaList?.length ?? 0) + (blankList?.length ?? 0) + (userList?.length ?? 0);
|
|
835
|
+
if (total === 0) continue;
|
|
836
|
+
const ordinal = state.ensurePathOrdinal(key);
|
|
837
|
+
let bucket = buckets.get(ordinal);
|
|
838
|
+
if (bucket === void 0) {
|
|
839
|
+
bucket = [];
|
|
840
|
+
buckets.set(ordinal, bucket);
|
|
841
|
+
}
|
|
842
|
+
if (schemaList !== void 0) bucket.push(...schemaList);
|
|
843
|
+
if (blankList !== void 0) bucket.push(...blankList);
|
|
844
|
+
if (userList !== void 0) bucket.push(...userList);
|
|
845
|
+
}
|
|
868
846
|
if (buckets.size === 0) return [];
|
|
847
|
+
if (buckets.size === 1) return [...buckets.values()][0];
|
|
869
848
|
return [...buckets.entries()].sort(([a], [b]) => a - b).flatMap(([, errs]) => errs);
|
|
870
849
|
}
|
|
871
850
|
const EMPTY_ELEMENTS = Object.freeze([]);
|
|
@@ -957,7 +936,7 @@ function buildTree(spec) {
|
|
|
957
936
|
existsCache.delete(key);
|
|
958
937
|
});
|
|
959
938
|
function schemaHasPath(segs) {
|
|
960
|
-
const cacheKey =
|
|
939
|
+
const cacheKey = keyForSegments(segs).key;
|
|
961
940
|
const cached = existsCache.get(cacheKey);
|
|
962
941
|
if (cached !== void 0) return cached;
|
|
963
942
|
const result = spec.schema.getSlimPrimitiveTypesAtPath(segs).size > 0;
|
|
@@ -972,7 +951,7 @@ function buildTree(spec) {
|
|
|
972
951
|
}
|
|
973
952
|
function containerAt(segments) {
|
|
974
953
|
const isArrayLike = spec.isArrayAt(segments);
|
|
975
|
-
const pathKey =
|
|
954
|
+
const pathKey = keyForSegments(segments).key;
|
|
976
955
|
const cacheKey = `${pathKey}+${isArrayLike ? "A" : "O"}`;
|
|
977
956
|
const existing = containerCache.get(cacheKey);
|
|
978
957
|
if (existing !== void 0) return existing;
|
|
@@ -1072,7 +1051,7 @@ function buildErrorsSurface(state, sweep) {
|
|
|
1072
1051
|
const treeCache = /* @__PURE__ */ new Map();
|
|
1073
1052
|
sweep.onEvict((key) => treeCache.delete(key));
|
|
1074
1053
|
const materialize = (segments) => {
|
|
1075
|
-
const cacheKey =
|
|
1054
|
+
const cacheKey = keyForSegments(segments).key;
|
|
1076
1055
|
let tree = treeCache.get(cacheKey);
|
|
1077
1056
|
if (tree === void 0) {
|
|
1078
1057
|
const frozen = [...segments];
|
|
@@ -1084,28 +1063,21 @@ function buildErrorsSurface(state, sweep) {
|
|
|
1084
1063
|
};
|
|
1085
1064
|
const resolveLeaf = (path) => {
|
|
1086
1065
|
const isContainerSelfAccess = path.length > 1 && path[path.length - 1] === "";
|
|
1087
|
-
const collectAtKey = (key2, active2, into) => {
|
|
1088
|
-
const cell = state.errorCells.get(key2);
|
|
1089
|
-
if (active2) {
|
|
1090
|
-
const b = state.derivedBlankErrors.value.get(key2);
|
|
1091
|
-
if (cell !== void 0) into.push(...cell.schema);
|
|
1092
|
-
if (b !== void 0) into.push(...b);
|
|
1093
|
-
}
|
|
1094
|
-
if (cell !== void 0) into.push(...cell.user);
|
|
1095
|
-
};
|
|
1096
1066
|
const merged = [];
|
|
1097
1067
|
if (isContainerSelfAccess) {
|
|
1098
1068
|
const containerPath = path.slice(0, -1);
|
|
1099
|
-
const
|
|
1100
|
-
const
|
|
1069
|
+
const container = canonicalizePath(containerPath);
|
|
1070
|
+
const literal = canonicalizePath(path);
|
|
1101
1071
|
const active2 = hasAtPath(state.form.value, containerPath);
|
|
1102
|
-
|
|
1103
|
-
if (
|
|
1072
|
+
collectErrorsAt(state, container.key, container.segments, active2, merged);
|
|
1073
|
+
if (literal.key !== container.key) {
|
|
1074
|
+
collectErrorsAt(state, literal.key, literal.segments, active2, merged);
|
|
1075
|
+
}
|
|
1104
1076
|
return merged;
|
|
1105
1077
|
}
|
|
1106
|
-
const { key } = canonicalizePath(path);
|
|
1078
|
+
const { key, segments } = canonicalizePath(path);
|
|
1107
1079
|
const active = hasAtPath(state.form.value, path);
|
|
1108
|
-
|
|
1080
|
+
collectErrorsAt(state, key, segments, active, merged);
|
|
1109
1081
|
return merged;
|
|
1110
1082
|
};
|
|
1111
1083
|
return buildTree({
|
|
@@ -1123,65 +1095,80 @@ function buildErrorsSurface(state, sweep) {
|
|
|
1123
1095
|
// `errors()` / `errors([])` / `errors(path)` are all the subtree
|
|
1124
1096
|
// aggregate — the same helper `meta.errors` reads, so the surfaces
|
|
1125
1097
|
// never drift.
|
|
1126
|
-
call: (path) => aggregateErrorsAt(state, path),
|
|
1098
|
+
call: (path) => aggregateErrorsAt(state, path, keyForSegments(path).key),
|
|
1127
1099
|
surface: "form.errors",
|
|
1128
1100
|
sweep
|
|
1129
1101
|
});
|
|
1130
1102
|
}
|
|
1103
|
+
function collectErrorsAt(state, key, segments, active, into) {
|
|
1104
|
+
const cell = state.errorCells.get(key);
|
|
1105
|
+
if (active) {
|
|
1106
|
+
if (cell !== void 0) into.push(...cell.schema);
|
|
1107
|
+
if (state.blankPaths.has(key) && state.schema.isRequiredAtPath(segments)) {
|
|
1108
|
+
into.push(makeBlankRequiredError(segments));
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
if (cell !== void 0) into.push(...cell.user);
|
|
1112
|
+
}
|
|
1131
1113
|
function errorAwareContainerKeys(state, segments) {
|
|
1132
1114
|
const keys = new Set(liveKeysAtPath(state, segments));
|
|
1133
1115
|
const formValue = state.form.value;
|
|
1134
|
-
const
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1116
|
+
const errors = [];
|
|
1117
|
+
const found = [];
|
|
1118
|
+
for (const { key, segments: decoded } of state.errorWindowAt(
|
|
1119
|
+
segments,
|
|
1120
|
+
keyForSegments(segments).key
|
|
1121
|
+
)) {
|
|
1122
|
+
if (decoded.length <= segments.length) continue;
|
|
1123
|
+
if (!isPathPrefix(segments, decoded)) continue;
|
|
1124
|
+
errors.length = 0;
|
|
1125
|
+
collectErrorsAt(state, key, decoded, hasAtPath(formValue, decoded), errors);
|
|
1126
|
+
if (errors.length === 0) continue;
|
|
1127
|
+
const nextSeg = decoded[segments.length];
|
|
1128
|
+
found.push({
|
|
1129
|
+
childKey: typeof nextSeg === "number" ? String(nextSeg) : nextSeg,
|
|
1130
|
+
ordinal: state.ensurePathOrdinal(key)
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
found.sort((a, b) => a.ordinal - b.ordinal);
|
|
1134
|
+
for (const { childKey } of found) keys.add(childKey);
|
|
1149
1135
|
return [...keys];
|
|
1150
1136
|
}
|
|
1151
1137
|
function materializeErrors(state, containerSegments) {
|
|
1152
|
-
const
|
|
1138
|
+
const formValue = state.form.value;
|
|
1139
|
+
const liveContainer = getAtPath(formValue, containerSegments);
|
|
1153
1140
|
const tree = Array.isArray(liveContainer) ? [] : {};
|
|
1154
|
-
const
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
for (let i = 0; i < containerSegments.length; i++) {
|
|
1165
|
-
if (fullPath[i] !== containerSegments[i]) continue entries;
|
|
1166
|
-
}
|
|
1167
|
-
if (applyActivePathFilter && !hasAtPath(state.form.value, fullPath)) continue;
|
|
1168
|
-
const relativePath = fullPath.slice(containerSegments.length);
|
|
1169
|
-
let placePath;
|
|
1170
|
-
if (relativePath.length === 0) {
|
|
1171
|
-
placePath = [""];
|
|
1172
|
-
} else if (state.schema.isLeafAtPath(fullPath)) {
|
|
1173
|
-
placePath = relativePath;
|
|
1174
|
-
} else if (state.schema.getSlimPrimitiveTypesAtPath(fullPath).size > 0) {
|
|
1175
|
-
placePath = [...relativePath, ""];
|
|
1176
|
-
} else {
|
|
1177
|
-
placePath = relativePath;
|
|
1178
|
-
}
|
|
1179
|
-
placeAt(tree, placePath, errors);
|
|
1141
|
+
const placements = [];
|
|
1142
|
+
for (const { key, segments: fullPath } of state.errorWindowAt(
|
|
1143
|
+
containerSegments,
|
|
1144
|
+
keyForSegments(containerSegments).key
|
|
1145
|
+
)) {
|
|
1146
|
+
const isRoot = fullPath.length === 0;
|
|
1147
|
+
if (isRoot) {
|
|
1148
|
+
if (containerSegments.length !== 0) continue;
|
|
1149
|
+
} else if (!isPathPrefix(containerSegments, fullPath)) {
|
|
1150
|
+
continue;
|
|
1180
1151
|
}
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1152
|
+
const errors = [];
|
|
1153
|
+
collectErrorsAt(state, key, fullPath, isRoot || hasAtPath(formValue, fullPath), errors);
|
|
1154
|
+
if (errors.length === 0) continue;
|
|
1155
|
+
const relativePath = fullPath.slice(containerSegments.length);
|
|
1156
|
+
let placePath;
|
|
1157
|
+
if (isRoot) {
|
|
1158
|
+
placePath = [ROOT_PATH_KEY];
|
|
1159
|
+
} else if (relativePath.length === 0) {
|
|
1160
|
+
placePath = [""];
|
|
1161
|
+
} else if (state.schema.isLeafAtPath(fullPath)) {
|
|
1162
|
+
placePath = relativePath;
|
|
1163
|
+
} else if (state.schema.getSlimPrimitiveTypesAtPath(fullPath).size > 0) {
|
|
1164
|
+
placePath = [...relativePath, ""];
|
|
1165
|
+
} else {
|
|
1166
|
+
placePath = relativePath;
|
|
1167
|
+
}
|
|
1168
|
+
placements.push({ placePath, errors, ordinal: state.ensurePathOrdinal(key) });
|
|
1169
|
+
}
|
|
1170
|
+
placements.sort((a, b) => a.ordinal - b.ordinal);
|
|
1171
|
+
for (const { placePath, errors } of placements) placeAt(tree, placePath, errors);
|
|
1185
1172
|
return tree;
|
|
1186
1173
|
}
|
|
1187
1174
|
function placeAt(tree, path, errors) {
|
|
@@ -1254,7 +1241,7 @@ function buildFieldsSurface(state, getFieldStateAt, sweep) {
|
|
|
1254
1241
|
const viewCache = /* @__PURE__ */ new Map();
|
|
1255
1242
|
sweep.onEvict((key) => viewCache.delete(key));
|
|
1256
1243
|
function viewAt(segments) {
|
|
1257
|
-
const cacheKey =
|
|
1244
|
+
const cacheKey = keyForSegments(segments).key;
|
|
1258
1245
|
const existing = viewCache.get(cacheKey);
|
|
1259
1246
|
if (existing !== void 0) return existing;
|
|
1260
1247
|
const { toString, valueOf, toJSON, toPrimitive } = makeReadonlyCoercion(
|
|
@@ -1816,45 +1803,6 @@ function buildFieldArrayApi(state) {
|
|
|
1816
1803
|
};
|
|
1817
1804
|
}
|
|
1818
1805
|
|
|
1819
|
-
const SWEEP_SLICE = 8;
|
|
1820
|
-
function createDynamicPathSweep(state) {
|
|
1821
|
-
const dynamicKeys = /* @__PURE__ */ new Set();
|
|
1822
|
-
const evictors = [];
|
|
1823
|
-
const isDynamicPath = (segments) => {
|
|
1824
|
-
for (let i = 0; i < segments.length; i++) {
|
|
1825
|
-
if (typeof segments[i] === "number") return true;
|
|
1826
|
-
if (!state.schema.isFixedObjectAtPath(segments.slice(0, i))) return true;
|
|
1827
|
-
}
|
|
1828
|
-
return false;
|
|
1829
|
-
};
|
|
1830
|
-
let sweepCursor = null;
|
|
1831
|
-
state.onFormChange((next) => {
|
|
1832
|
-
if (dynamicKeys.size === 0) return;
|
|
1833
|
-
const raw = toRaw(next);
|
|
1834
|
-
for (let i = 0; i < SWEEP_SLICE; i++) {
|
|
1835
|
-
sweepCursor ?? (sweepCursor = dynamicKeys.values());
|
|
1836
|
-
const step = sweepCursor.next();
|
|
1837
|
-
if (step.done === true) {
|
|
1838
|
-
sweepCursor = null;
|
|
1839
|
-
break;
|
|
1840
|
-
}
|
|
1841
|
-
const segments = segmentsForPathKey(step.value);
|
|
1842
|
-
if (segments !== null && hasAtPath(raw, segments)) continue;
|
|
1843
|
-
dynamicKeys.delete(step.value);
|
|
1844
|
-
for (const evict of evictors) evict(step.value);
|
|
1845
|
-
}
|
|
1846
|
-
});
|
|
1847
|
-
return {
|
|
1848
|
-
track(segments, key) {
|
|
1849
|
-
if (dynamicKeys.has(key)) return;
|
|
1850
|
-
if (isDynamicPath(segments)) dynamicKeys.add(key);
|
|
1851
|
-
},
|
|
1852
|
-
onEvict(evict) {
|
|
1853
|
-
evictors.push(evict);
|
|
1854
|
-
}
|
|
1855
|
-
};
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
1806
|
function isErrorInputLike(value) {
|
|
1859
1807
|
if (value instanceof Error) return true;
|
|
1860
1808
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -1881,8 +1829,8 @@ function deriveSubmitErrors(err) {
|
|
|
1881
1829
|
messageless: true
|
|
1882
1830
|
};
|
|
1883
1831
|
}
|
|
1884
|
-
function buildProcessForm(state,
|
|
1885
|
-
const
|
|
1832
|
+
function buildProcessForm(state, options = {}) {
|
|
1833
|
+
const applyInvalidSubmit = options.applyInvalidSubmit;
|
|
1886
1834
|
function validate(pathInput) {
|
|
1887
1835
|
const result = ref({
|
|
1888
1836
|
pending: true,
|
|
@@ -1975,7 +1923,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
1975
1923
|
};
|
|
1976
1924
|
}
|
|
1977
1925
|
async function runRefinementValidation(data, path) {
|
|
1978
|
-
return await state.schema.validateAtPath(data, path);
|
|
1926
|
+
return stampFormKey(await state.schema.validateAtPath(data, path), state.formKey);
|
|
1979
1927
|
}
|
|
1980
1928
|
function composeWithDerivedBlank(refinement, scope) {
|
|
1981
1929
|
const blankErrors = collectScopedBlankErrors(state, scope);
|
|
@@ -2021,7 +1969,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
2021
1969
|
}
|
|
2022
1970
|
}
|
|
2023
1971
|
if (generationStillValid) {
|
|
2024
|
-
|
|
1972
|
+
applyInvalidSubmit?.();
|
|
2025
1973
|
}
|
|
2026
1974
|
if (onError !== void 0) {
|
|
2027
1975
|
try {
|
|
@@ -2038,7 +1986,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
2038
1986
|
await onSubmit(merged.data);
|
|
2039
1987
|
if (hasUserErrorEntries(state)) {
|
|
2040
1988
|
if (state.submissionGeneration.value === genAtEntry) {
|
|
2041
|
-
|
|
1989
|
+
applyInvalidSubmit?.();
|
|
2042
1990
|
}
|
|
2043
1991
|
return;
|
|
2044
1992
|
}
|
|
@@ -2056,7 +2004,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
2056
2004
|
if (segments === null) continue;
|
|
2057
2005
|
state.setUserErrorsForPath([...segments], bucket);
|
|
2058
2006
|
}
|
|
2059
|
-
|
|
2007
|
+
applyInvalidSubmit?.();
|
|
2060
2008
|
}
|
|
2061
2009
|
}
|
|
2062
2010
|
} finally {
|
|
@@ -2071,6 +2019,10 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
2071
2019
|
};
|
|
2072
2020
|
return { validate, parse, handleSubmit };
|
|
2073
2021
|
}
|
|
2022
|
+
function stampFormKey(verdict, formKey) {
|
|
2023
|
+
if (verdict.success) return { ...verdict, formKey };
|
|
2024
|
+
return verdict.data === void 0 ? { data: void 0, errors: verdict.errors, success: false, formKey } : { data: verdict.data, errors: verdict.errors, success: false, formKey };
|
|
2025
|
+
}
|
|
2074
2026
|
function toSegments(pathInput) {
|
|
2075
2027
|
return canonicalizePath(pathInput).segments;
|
|
2076
2028
|
}
|
|
@@ -2104,21 +2056,6 @@ function collectScopedBlankErrors(state, scope) {
|
|
|
2104
2056
|
}
|
|
2105
2057
|
return errors;
|
|
2106
2058
|
}
|
|
2107
|
-
function applyInvalidSubmitPolicy(state, formInstanceId, policy) {
|
|
2108
|
-
if (policy === "none") return;
|
|
2109
|
-
const target = state.domBinding.value?.getFirstErrorElement(formInstanceId) ?? null;
|
|
2110
|
-
if (target === null) return;
|
|
2111
|
-
if (policy === "scroll-to-first-error") {
|
|
2112
|
-
target.element.scrollIntoView();
|
|
2113
|
-
return;
|
|
2114
|
-
}
|
|
2115
|
-
if (policy === "focus-first-error") {
|
|
2116
|
-
target.element.focus({ focusVisible: true });
|
|
2117
|
-
return;
|
|
2118
|
-
}
|
|
2119
|
-
target.element.scrollIntoView();
|
|
2120
|
-
target.element.focus({ preventScroll: true, focusVisible: true });
|
|
2121
|
-
}
|
|
2122
2059
|
|
|
2123
2060
|
function slimKindOf(value) {
|
|
2124
2061
|
if (value === null) return "null";
|
|
@@ -2182,51 +2119,9 @@ function walk(schema, store, path, value) {
|
|
|
2182
2119
|
return true;
|
|
2183
2120
|
}
|
|
2184
2121
|
|
|
2185
|
-
function defineCoercion(entry) {
|
|
2186
|
-
return entry;
|
|
2187
|
-
}
|
|
2188
2122
|
const IDENTITY = (v) => v;
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
defineCoercion({
|
|
2192
|
-
input: "string",
|
|
2193
|
-
output: "number",
|
|
2194
|
-
transform: (s) => {
|
|
2195
|
-
const trimmed = s.trim();
|
|
2196
|
-
if (trimmed === "") return { coerced: false };
|
|
2197
|
-
const n = Number(trimmed);
|
|
2198
|
-
if (!Number.isFinite(n)) return { coerced: false };
|
|
2199
|
-
return { coerced: true, value: n };
|
|
2200
|
-
}
|
|
2201
|
-
}),
|
|
2202
|
-
defineCoercion({
|
|
2203
|
-
input: "string",
|
|
2204
|
-
output: "boolean",
|
|
2205
|
-
transform: (s) => {
|
|
2206
|
-
const normalized = s.trim().toLowerCase();
|
|
2207
|
-
if (normalized === "true") return { coerced: true, value: true };
|
|
2208
|
-
if (normalized === "false") return { coerced: true, value: false };
|
|
2209
|
-
return { coerced: false };
|
|
2210
|
-
}
|
|
2211
|
-
})
|
|
2212
|
-
];
|
|
2213
|
-
function resolveCoercionIndex(config) {
|
|
2214
|
-
if (config === false) return EMPTY_INDEX;
|
|
2215
|
-
const rules = config === void 0 || config === true ? defaultCoercionRules : config;
|
|
2216
|
-
return indexRules(rules);
|
|
2217
|
-
}
|
|
2218
|
-
function indexRules(rules) {
|
|
2219
|
-
const idx = /* @__PURE__ */ new Map();
|
|
2220
|
-
for (const entry of rules) {
|
|
2221
|
-
const candidate = entry;
|
|
2222
|
-
if (candidate === null || typeof candidate !== "object" || typeof candidate.transform !== "function") {
|
|
2223
|
-
continue;
|
|
2224
|
-
}
|
|
2225
|
-
const key = `${entry.input}->${entry.output}`;
|
|
2226
|
-
if (idx.has(key) && false) ;
|
|
2227
|
-
idx.set(key, entry);
|
|
2228
|
-
}
|
|
2229
|
-
return idx;
|
|
2123
|
+
function resolveCoerceEnabled(config) {
|
|
2124
|
+
return config !== false;
|
|
2230
2125
|
}
|
|
2231
2126
|
function memberSlimTypes(schema, segments, accepted) {
|
|
2232
2127
|
if (accepted.has("array")) return schema.getSlimPrimitiveTypesAtPath([...segments, 0]);
|
|
@@ -2235,89 +2130,83 @@ function memberSlimTypes(schema, segments, accepted) {
|
|
|
2235
2130
|
}
|
|
2236
2131
|
return void 0;
|
|
2237
2132
|
}
|
|
2238
|
-
function buildCoerceFn(schema, segments,
|
|
2239
|
-
if (
|
|
2240
|
-
if (index.size === 0) return IDENTITY;
|
|
2133
|
+
function buildCoerceFn(schema, segments, enabled) {
|
|
2134
|
+
if (!enabled) return IDENTITY;
|
|
2241
2135
|
const accepted = schema.getSlimPrimitiveTypesAtPath(segments);
|
|
2242
2136
|
const elementAccepted = memberSlimTypes(schema, segments, accepted);
|
|
2243
|
-
return (value) => coerceValue(value, accepted, elementAccepted
|
|
2137
|
+
return (value) => coerceValue(value, accepted, elementAccepted);
|
|
2244
2138
|
}
|
|
2245
|
-
function buildElementCoerceFn(schema, segments,
|
|
2246
|
-
if (
|
|
2247
|
-
if (index.size === 0) return void 0;
|
|
2139
|
+
function buildElementCoerceFn(schema, segments, enabled) {
|
|
2140
|
+
if (!enabled) return void 0;
|
|
2248
2141
|
const accepted = schema.getSlimPrimitiveTypesAtPath(segments);
|
|
2249
2142
|
const elementAccepted = memberSlimTypes(schema, segments, accepted);
|
|
2250
2143
|
if (elementAccepted === void 0) return void 0;
|
|
2251
|
-
return (value) => coerceScalar(value, elementAccepted
|
|
2144
|
+
return (value) => coerceScalar(value, elementAccepted);
|
|
2252
2145
|
}
|
|
2253
2146
|
function pickScalarTarget(accepted) {
|
|
2254
2147
|
if (accepted.has("string")) return null;
|
|
2255
2148
|
if (accepted.has("number")) return "number";
|
|
2256
2149
|
if (accepted.has("boolean")) return "boolean";
|
|
2257
|
-
if (accepted.has("bigint")) return "bigint";
|
|
2258
2150
|
return null;
|
|
2259
2151
|
}
|
|
2260
|
-
function
|
|
2152
|
+
function toNumber(source) {
|
|
2153
|
+
const trimmed = source.trim();
|
|
2154
|
+
if (trimmed === "") return source;
|
|
2155
|
+
const n = Number(trimmed);
|
|
2156
|
+
return Number.isFinite(n) ? n : source;
|
|
2157
|
+
}
|
|
2158
|
+
function toBoolean(source) {
|
|
2159
|
+
const normalized = source.trim().toLowerCase();
|
|
2160
|
+
if (normalized === "true") return true;
|
|
2161
|
+
if (normalized === "false") return false;
|
|
2162
|
+
return source;
|
|
2163
|
+
}
|
|
2164
|
+
function coerceScalar(value, accepted) {
|
|
2261
2165
|
if (accepted.size === 0) return value;
|
|
2262
2166
|
const sourceKind = slimKindOf(value);
|
|
2263
2167
|
if (accepted.has(sourceKind)) return value;
|
|
2168
|
+
if (sourceKind !== "string") return value;
|
|
2264
2169
|
const target = pickScalarTarget(accepted);
|
|
2265
|
-
if (target ===
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
let result;
|
|
2269
|
-
try {
|
|
2270
|
-
result = entry.transform(value);
|
|
2271
|
-
} catch (err) {
|
|
2272
|
-
return value;
|
|
2273
|
-
}
|
|
2274
|
-
if (!result.coerced) return value;
|
|
2275
|
-
const returnedKind = slimKindOf(result.value);
|
|
2276
|
-
if (returnedKind !== entry.output) {
|
|
2277
|
-
return value;
|
|
2278
|
-
}
|
|
2279
|
-
if (entry.output === "number" && !Number.isFinite(result.value)) {
|
|
2280
|
-
return value;
|
|
2281
|
-
}
|
|
2282
|
-
return result.value;
|
|
2170
|
+
if (target === "number") return toNumber(value);
|
|
2171
|
+
if (target === "boolean") return toBoolean(value);
|
|
2172
|
+
return value;
|
|
2283
2173
|
}
|
|
2284
|
-
function coerceArrayMembers(arr, elementAccepted
|
|
2174
|
+
function coerceArrayMembers(arr, elementAccepted) {
|
|
2285
2175
|
let changed = false;
|
|
2286
2176
|
const out = [];
|
|
2287
2177
|
for (const el of arr) {
|
|
2288
|
-
const next = coerceScalar(el, elementAccepted
|
|
2178
|
+
const next = coerceScalar(el, elementAccepted);
|
|
2289
2179
|
if (next !== el) changed = true;
|
|
2290
2180
|
out.push(next);
|
|
2291
2181
|
}
|
|
2292
2182
|
return changed ? out : arr;
|
|
2293
2183
|
}
|
|
2294
|
-
function coerceSetMembers(set, elementAccepted
|
|
2184
|
+
function coerceSetMembers(set, elementAccepted) {
|
|
2295
2185
|
let changed = false;
|
|
2296
2186
|
const out = [];
|
|
2297
2187
|
for (const el of set) {
|
|
2298
|
-
const next = coerceScalar(el, elementAccepted
|
|
2188
|
+
const next = coerceScalar(el, elementAccepted);
|
|
2299
2189
|
if (next !== el) changed = true;
|
|
2300
2190
|
out.push(next);
|
|
2301
2191
|
}
|
|
2302
2192
|
return changed ? new Set(out) : set;
|
|
2303
2193
|
}
|
|
2304
|
-
function coerceValue(value, accepted, elementAccepted
|
|
2194
|
+
function coerceValue(value, accepted, elementAccepted) {
|
|
2305
2195
|
if (Array.isArray(value)) {
|
|
2306
2196
|
if (!accepted.has("array") || elementAccepted === void 0) return value;
|
|
2307
|
-
return coerceArrayMembers(value, elementAccepted
|
|
2197
|
+
return coerceArrayMembers(value, elementAccepted);
|
|
2308
2198
|
}
|
|
2309
2199
|
if (value instanceof Set) {
|
|
2310
2200
|
if (!accepted.has("set") || elementAccepted === void 0) return value;
|
|
2311
|
-
return coerceSetMembers(value, elementAccepted
|
|
2201
|
+
return coerceSetMembers(value, elementAccepted);
|
|
2312
2202
|
}
|
|
2313
|
-
return coerceScalar(value, accepted
|
|
2203
|
+
return coerceScalar(value, accepted);
|
|
2314
2204
|
}
|
|
2315
2205
|
|
|
2316
2206
|
const EMPTY_TRANSFORMS = Object.freeze([]);
|
|
2317
2207
|
function buildRegister(state, formInstanceId, instanceConfig) {
|
|
2318
|
-
const
|
|
2208
|
+
const coerceEnabled = instanceConfig?.coerce !== void 0 ? resolveCoerceEnabled(instanceConfig.coerce) : state.coerceEnabled;
|
|
2319
2209
|
const instanceMeta = instanceConfig?.instanceMeta;
|
|
2320
|
-
const formAutoAria = instanceConfig?.autoAria ?? true;
|
|
2321
2210
|
const getDisplayStateAt = instanceConfig?.getDisplayStateAt;
|
|
2322
2211
|
const withInstanceMeta = (meta) => {
|
|
2323
2212
|
if (instanceMeta === void 0) return meta;
|
|
@@ -2357,16 +2246,15 @@ function buildRegister(state, formInstanceId, instanceConfig) {
|
|
|
2357
2246
|
const coerce = buildCoerceFn(
|
|
2358
2247
|
state.schema,
|
|
2359
2248
|
segments,
|
|
2360
|
-
|
|
2249
|
+
coerceEnabled
|
|
2361
2250
|
);
|
|
2362
2251
|
const coerceElement = buildElementCoerceFn(
|
|
2363
2252
|
state.schema,
|
|
2364
2253
|
segments,
|
|
2365
|
-
|
|
2254
|
+
coerceEnabled
|
|
2366
2255
|
);
|
|
2367
2256
|
const { aria } = computeFieldIdentity(formInstanceId, state.formKey, pathKey);
|
|
2368
2257
|
const isRequired = state.schema.isRequiredAtPath(segments);
|
|
2369
|
-
const ariaEnabled = options?.autoAria ?? formAutoAria;
|
|
2370
2258
|
const ariaDisplayState = getDisplayStateAt !== void 0 ? computed(() => getDisplayStateAt(segments)) : void 0;
|
|
2371
2259
|
const markBlank = () => state.setValueAtPath(segments, slimDefault, withInstanceMeta({ blank: true }));
|
|
2372
2260
|
const internalRv = {
|
|
@@ -2468,7 +2356,6 @@ function buildRegister(state, formInstanceId, instanceConfig) {
|
|
|
2468
2356
|
// --- Aria (internal; consumed by the directive) ---
|
|
2469
2357
|
aria,
|
|
2470
2358
|
isRequired,
|
|
2471
|
-
ariaEnabled,
|
|
2472
2359
|
...ariaDisplayState !== void 0 ? { ariaDisplayState } : {}
|
|
2473
2360
|
};
|
|
2474
2361
|
return shallowReadonly(internalRv);
|
|
@@ -2632,11 +2519,50 @@ const DERIVED_DISPLAY_KEYS = /* @__PURE__ */ new Set([
|
|
|
2632
2519
|
"firstError",
|
|
2633
2520
|
"firstOwnError"
|
|
2634
2521
|
]);
|
|
2635
|
-
const
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2522
|
+
const META_KEYS = [
|
|
2523
|
+
...FIELD_STATE_KEYS,
|
|
2524
|
+
"submitting",
|
|
2525
|
+
"submissionAttempts",
|
|
2526
|
+
"departAttempts",
|
|
2527
|
+
"submitError",
|
|
2528
|
+
"submitted",
|
|
2529
|
+
"instanceId",
|
|
2530
|
+
"errorCount"
|
|
2531
|
+
];
|
|
2532
|
+
const BASE_META_KEYS = META_KEYS.filter((k) => !DERIVED_DISPLAY_KEYS.has(k));
|
|
2533
|
+
let INERT_HISTORY;
|
|
2534
|
+
function inertHistory() {
|
|
2535
|
+
INERT_HISTORY ?? (INERT_HISTORY = readonly({
|
|
2536
|
+
undo: () => false,
|
|
2537
|
+
redo: () => false,
|
|
2538
|
+
clear: () => {
|
|
2539
|
+
},
|
|
2540
|
+
canUndo: false,
|
|
2541
|
+
canRedo: false,
|
|
2542
|
+
size: 0
|
|
2543
|
+
}));
|
|
2544
|
+
return INERT_HISTORY;
|
|
2545
|
+
}
|
|
2546
|
+
const denyWrite = () => false;
|
|
2547
|
+
function buildMetaProxy(keys, read) {
|
|
2548
|
+
const target = {};
|
|
2549
|
+
const owns = new Set(keys);
|
|
2550
|
+
return new Proxy(target, {
|
|
2551
|
+
get: (_, key) => owns.has(key) ? read(key) : Reflect.get(target, key),
|
|
2552
|
+
has: (_, key) => owns.has(key) || Reflect.has(target, key),
|
|
2553
|
+
// Safe to hand back the same array every time: the spec copies a
|
|
2554
|
+
// trap's key list before using it.
|
|
2555
|
+
ownKeys: () => keys,
|
|
2556
|
+
getOwnPropertyDescriptor(_, key) {
|
|
2557
|
+
if (!owns.has(key)) return Reflect.getOwnPropertyDescriptor(target, key);
|
|
2558
|
+
return { configurable: true, enumerable: true, value: read(key), writable: false };
|
|
2559
|
+
},
|
|
2560
|
+
// A getter with no setter throws on assignment under strict mode,
|
|
2561
|
+
// which every module here is. `false` keeps that.
|
|
2562
|
+
set: denyWrite,
|
|
2563
|
+
deleteProperty: denyWrite,
|
|
2564
|
+
defineProperty: denyWrite
|
|
2565
|
+
});
|
|
2640
2566
|
}
|
|
2641
2567
|
function buildFormApi(state, formInstanceId, options = {}) {
|
|
2642
2568
|
const instanceBag = pickDefined({
|
|
@@ -2663,32 +2589,26 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2663
2589
|
const rootBaseComputed = computed(
|
|
2664
2590
|
() => buildContainerFieldStateBase(state, ROOT_PATH, ROOT_PATH_KEY, formInstanceId).base
|
|
2665
2591
|
);
|
|
2666
|
-
const metaBase = {
|
|
2667
|
-
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2592
|
+
const metaBase = buildMetaProxy(BASE_META_KEYS, (key) => {
|
|
2593
|
+
switch (key) {
|
|
2594
|
+
case "instanceId":
|
|
2595
|
+
return formInstanceId;
|
|
2596
|
+
case "errorCount":
|
|
2597
|
+
return rootBaseComputed.value.errors.length;
|
|
2598
|
+
case "submitting":
|
|
2599
|
+
return state.submitting.value;
|
|
2600
|
+
case "submissionAttempts":
|
|
2601
|
+
return state.submissionAttempts.value;
|
|
2602
|
+
case "departAttempts":
|
|
2603
|
+
return state.departAttempts.value;
|
|
2604
|
+
case "submitError":
|
|
2605
|
+
return state.submitError.value;
|
|
2606
|
+
case "submitted":
|
|
2607
|
+
return state.submitted.value;
|
|
2608
|
+
default:
|
|
2609
|
+
return rootBaseComputed.value[key];
|
|
2682
2610
|
}
|
|
2683
|
-
};
|
|
2684
|
-
for (const k of BASE_MIRROR_KEYS) {
|
|
2685
|
-
defineGetter(
|
|
2686
|
-
metaBase,
|
|
2687
|
-
k,
|
|
2688
|
-
() => rootBaseComputed.value[k]
|
|
2689
|
-
);
|
|
2690
|
-
}
|
|
2691
|
-
defineGetter(metaBase, "errorCount", () => rootBaseComputed.value.errors.length);
|
|
2611
|
+
});
|
|
2692
2612
|
const getFormMetaBase = () => {
|
|
2693
2613
|
void state.submitting.value;
|
|
2694
2614
|
void state.submissionAttempts.value;
|
|
@@ -2697,28 +2617,41 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2697
2617
|
void state.submitted.value;
|
|
2698
2618
|
return metaBase;
|
|
2699
2619
|
};
|
|
2700
|
-
const
|
|
2701
|
-
const pathSweep = createDynamicPathSweep(state);
|
|
2620
|
+
const pathSweep = state.pathSweep;
|
|
2702
2621
|
const getRootFieldStateAt = buildFieldStateAccessor(
|
|
2703
2622
|
state,
|
|
2704
2623
|
formInstanceId,
|
|
2705
2624
|
getFormMetaBase,
|
|
2706
|
-
pathSweep
|
|
2707
|
-
fieldStateAccessorOptions
|
|
2625
|
+
pathSweep
|
|
2708
2626
|
);
|
|
2709
2627
|
const getDisplayStateAt = (segments) => getRootFieldStateAt(segments).value.displayState;
|
|
2710
2628
|
const registerConfig = {
|
|
2711
|
-
...pickDefined({ instanceMeta, coerce: options.coerce
|
|
2629
|
+
...pickDefined({ instanceMeta, coerce: options.coerce }),
|
|
2712
2630
|
getDisplayStateAt
|
|
2713
2631
|
};
|
|
2714
2632
|
const register = buildRegister(state, formInstanceId, registerConfig);
|
|
2715
|
-
const
|
|
2716
|
-
|
|
2633
|
+
const focusFirstError = (options2) => {
|
|
2634
|
+
const target = state.domBinding.value?.getFirstErrorElement(formInstanceId) ?? null;
|
|
2635
|
+
if (target === null) return false;
|
|
2636
|
+
target.element.focus({ focusVisible: true, ...options2 });
|
|
2637
|
+
return true;
|
|
2638
|
+
};
|
|
2639
|
+
const scrollToFirstError = (options2) => {
|
|
2640
|
+
const target = state.domBinding.value?.getFirstErrorElement(formInstanceId) ?? null;
|
|
2641
|
+
if (target === null) return false;
|
|
2642
|
+
target.element.scrollIntoView(options2);
|
|
2643
|
+
return true;
|
|
2644
|
+
};
|
|
2645
|
+
const applyInvalidSubmitPolicyPublic = () => {
|
|
2646
|
+
if (options.focusOnInvalidSubmit !== false) focusFirstError();
|
|
2647
|
+
};
|
|
2717
2648
|
const {
|
|
2718
2649
|
validate: validateBuilt,
|
|
2719
2650
|
parse: parseBuilt,
|
|
2720
2651
|
handleSubmit
|
|
2721
|
-
} = buildProcessForm(state,
|
|
2652
|
+
} = buildProcessForm(state, {
|
|
2653
|
+
applyInvalidSubmit: applyInvalidSubmitPolicyPublic
|
|
2654
|
+
});
|
|
2722
2655
|
const validate = (pathInput) => validateBuilt(pathInput);
|
|
2723
2656
|
const parse = (arg1, arg2) => {
|
|
2724
2657
|
const isPathArg = typeof arg1 === "string" || Array.isArray(arg1);
|
|
@@ -2846,22 +2779,21 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2846
2779
|
() => state.firstValidationDone.value && state.errorCells.size === 0 && state.derivedBlankErrors.value.size === 0 && !validating.value
|
|
2847
2780
|
);
|
|
2848
2781
|
const history = options.history;
|
|
2849
|
-
const formHistory = readonly(
|
|
2782
|
+
const formHistory = history === void 0 ? inertHistory() : readonly(
|
|
2850
2783
|
reactive({
|
|
2851
|
-
undo: history
|
|
2852
|
-
redo: history
|
|
2853
|
-
clear: history
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
size: history?.historySize ?? computed(() => 0)
|
|
2784
|
+
undo: history.undo,
|
|
2785
|
+
redo: history.redo,
|
|
2786
|
+
clear: history.clear,
|
|
2787
|
+
canUndo: history.canUndo,
|
|
2788
|
+
canRedo: history.canRedo,
|
|
2789
|
+
size: history.historySize
|
|
2858
2790
|
})
|
|
2859
2791
|
);
|
|
2860
2792
|
const metaErrors = computed(
|
|
2861
|
-
() => aggregateErrorsAt(state, [])
|
|
2793
|
+
() => aggregateErrorsAt(state, [], ROOT_PATH_KEY)
|
|
2862
2794
|
);
|
|
2863
2795
|
const rootFieldState = getRootFieldStateAt([]);
|
|
2864
|
-
const
|
|
2796
|
+
const metaOwn = {
|
|
2865
2797
|
// Whole-form work signals compose the LIFECYCLE counters with the
|
|
2866
2798
|
// per-leaf rollup: a submit-time validate shows up as
|
|
2867
2799
|
// activeValidations, per-field debounced validators as
|
|
@@ -2890,14 +2822,11 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2890
2822
|
// identifier).
|
|
2891
2823
|
instanceId: formInstanceId
|
|
2892
2824
|
};
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
);
|
|
2899
|
-
}
|
|
2900
|
-
defineGetter(metaTarget, "errorCount", () => metaErrors.value.length);
|
|
2825
|
+
const metaTarget = buildMetaProxy(META_KEYS, (key) => {
|
|
2826
|
+
if (key === "errorCount") return metaErrors.value.length;
|
|
2827
|
+
if (Object.hasOwn(metaOwn, key)) return metaOwn[key];
|
|
2828
|
+
return rootFieldState.value[key];
|
|
2829
|
+
});
|
|
2901
2830
|
const formMeta = readonly(reactive(metaTarget));
|
|
2902
2831
|
const reset = (nextDefaultValues) => {
|
|
2903
2832
|
if (nextDefaultValues === void 0) {
|
|
@@ -2937,21 +2866,6 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2937
2866
|
} catch {
|
|
2938
2867
|
}
|
|
2939
2868
|
}
|
|
2940
|
-
const focusFirstError = (options2) => {
|
|
2941
|
-
const target = state.domBinding.value?.getFirstErrorElement(formInstanceId) ?? null;
|
|
2942
|
-
if (target === null) return false;
|
|
2943
|
-
target.element.focus({ focusVisible: true, ...options2 });
|
|
2944
|
-
return true;
|
|
2945
|
-
};
|
|
2946
|
-
const scrollToFirstError = (options2) => {
|
|
2947
|
-
const target = state.domBinding.value?.getFirstErrorElement(formInstanceId) ?? null;
|
|
2948
|
-
if (target === null) return false;
|
|
2949
|
-
target.element.scrollIntoView(options2);
|
|
2950
|
-
return true;
|
|
2951
|
-
};
|
|
2952
|
-
const applyInvalidSubmitPolicyPublic = (policy) => {
|
|
2953
|
-
applyInvalidSubmitPolicy(state, formInstanceId, policy ?? defaultInvalidSubmitPolicy);
|
|
2954
|
-
};
|
|
2955
2869
|
const fieldArrays = buildFieldArrayApi(state);
|
|
2956
2870
|
const blankPathsView = computed(() => {
|
|
2957
2871
|
const keys = /* @__PURE__ */ new Set();
|
|
@@ -3099,6 +3013,45 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
3099
3013
|
return api;
|
|
3100
3014
|
}
|
|
3101
3015
|
|
|
3016
|
+
const SWEEP_SLICE = 8;
|
|
3017
|
+
function createDynamicPathSweep(deps) {
|
|
3018
|
+
const dynamicKeys = /* @__PURE__ */ new Set();
|
|
3019
|
+
const evictors = [];
|
|
3020
|
+
const isDynamicPath = (segments) => {
|
|
3021
|
+
for (let i = 0; i < segments.length; i++) {
|
|
3022
|
+
if (typeof segments[i] === "number") return true;
|
|
3023
|
+
if (!deps.isFixedObjectAtPath(segments.slice(0, i))) return true;
|
|
3024
|
+
}
|
|
3025
|
+
return false;
|
|
3026
|
+
};
|
|
3027
|
+
let sweepCursor = null;
|
|
3028
|
+
deps.onFormChange((next) => {
|
|
3029
|
+
if (dynamicKeys.size === 0) return;
|
|
3030
|
+
const raw = toRaw(next);
|
|
3031
|
+
for (let i = 0; i < SWEEP_SLICE; i++) {
|
|
3032
|
+
sweepCursor ?? (sweepCursor = dynamicKeys.values());
|
|
3033
|
+
const step = sweepCursor.next();
|
|
3034
|
+
if (step.done === true) {
|
|
3035
|
+
sweepCursor = null;
|
|
3036
|
+
break;
|
|
3037
|
+
}
|
|
3038
|
+
const segments = segmentsForPathKey(step.value);
|
|
3039
|
+
if (segments !== null && hasAtPath(raw, segments)) continue;
|
|
3040
|
+
dynamicKeys.delete(step.value);
|
|
3041
|
+
for (const evict of evictors) evict(step.value);
|
|
3042
|
+
}
|
|
3043
|
+
});
|
|
3044
|
+
return {
|
|
3045
|
+
track(segments, key) {
|
|
3046
|
+
if (dynamicKeys.has(key)) return;
|
|
3047
|
+
if (isDynamicPath(segments)) dynamicKeys.add(key);
|
|
3048
|
+
},
|
|
3049
|
+
onEvict(evict) {
|
|
3050
|
+
evictors.push(evict);
|
|
3051
|
+
}
|
|
3052
|
+
};
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3102
3055
|
const IDLE = Object.freeze({ display: "idle" });
|
|
3103
3056
|
const MAX_DELAY = 2147483647;
|
|
3104
3057
|
const PENDING_LIVENESS_MS = 250;
|
|
@@ -3187,6 +3140,58 @@ function createDisplayEngine(ssr) {
|
|
|
3187
3140
|
return engine;
|
|
3188
3141
|
}
|
|
3189
3142
|
|
|
3143
|
+
function buildErrorPathIndex(cells, blank) {
|
|
3144
|
+
const keys = /* @__PURE__ */ new Set();
|
|
3145
|
+
for (const [key, cell] of cells) {
|
|
3146
|
+
if (cell.schema.length > 0 || cell.user.length > 0) keys.add(key);
|
|
3147
|
+
}
|
|
3148
|
+
for (const [key, list] of blank) {
|
|
3149
|
+
if (list.length > 0) keys.add(key);
|
|
3150
|
+
}
|
|
3151
|
+
if (keys.size === 0) return EMPTY_INDEX;
|
|
3152
|
+
const entries = [];
|
|
3153
|
+
for (const key of keys) {
|
|
3154
|
+
const segments = segmentsForPathKey(key);
|
|
3155
|
+
if (segments !== null) entries.push({ key, segments });
|
|
3156
|
+
}
|
|
3157
|
+
entries.sort(compareByKey);
|
|
3158
|
+
return entries;
|
|
3159
|
+
}
|
|
3160
|
+
const EMPTY_INDEX = Object.freeze([]);
|
|
3161
|
+
function compareByKey(a, b) {
|
|
3162
|
+
return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;
|
|
3163
|
+
}
|
|
3164
|
+
function windowUnder(index, prefix) {
|
|
3165
|
+
if (prefix.length === 0 || index.length === 0) return index;
|
|
3166
|
+
const prefixKey = keyForSegments(prefix).key;
|
|
3167
|
+
const marker = `${prefixKey.slice(0, -1)},`;
|
|
3168
|
+
const start = lowerBound(index, marker);
|
|
3169
|
+
if (start >= index.length) return EMPTY_INDEX;
|
|
3170
|
+
let end = start;
|
|
3171
|
+
for (; end < index.length; end += 1) {
|
|
3172
|
+
const entry = index[end];
|
|
3173
|
+
if (entry === void 0 || entry.key > prefixKey) break;
|
|
3174
|
+
}
|
|
3175
|
+
return start === 0 && end === index.length ? index : index.slice(start, end);
|
|
3176
|
+
}
|
|
3177
|
+
function isSameWindow(a, b) {
|
|
3178
|
+
if (a.length !== b.length) return false;
|
|
3179
|
+
for (let i = 0; i < a.length; i += 1) {
|
|
3180
|
+
if (a[i]?.key !== b[i]?.key) return false;
|
|
3181
|
+
}
|
|
3182
|
+
return true;
|
|
3183
|
+
}
|
|
3184
|
+
function lowerBound(index, target) {
|
|
3185
|
+
let lo = 0;
|
|
3186
|
+
let hi = index.length;
|
|
3187
|
+
while (lo < hi) {
|
|
3188
|
+
const mid = lo + hi >>> 1;
|
|
3189
|
+
if ((index[mid]?.key ?? target) < target) lo = mid + 1;
|
|
3190
|
+
else hi = mid;
|
|
3191
|
+
}
|
|
3192
|
+
return lo;
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3190
3195
|
function mergeSparseHydration(schemaDefaults, sparse, schema) {
|
|
3191
3196
|
return mergeDeep(schemaDefaults, sparse, [], schema);
|
|
3192
3197
|
}
|
|
@@ -3397,16 +3402,15 @@ function walkAuthoredFromSchemaDiff(withDefaults, withoutDefaults, prefix, out)
|
|
|
3397
3402
|
out.add(canonicalizePath(prefix).key);
|
|
3398
3403
|
}
|
|
3399
3404
|
}
|
|
3400
|
-
function computeBaselineResponse(schema,
|
|
3405
|
+
function computeBaselineResponse(schema, source) {
|
|
3401
3406
|
const completed = source === void 0 ? void 0 : mergeStructural(schema, [], source);
|
|
3402
3407
|
return schema.getDefaultValues({
|
|
3403
3408
|
useDefaultSchemaValues: true,
|
|
3404
|
-
constraints: completed
|
|
3405
|
-
strict
|
|
3409
|
+
constraints: completed
|
|
3406
3410
|
});
|
|
3407
3411
|
}
|
|
3408
|
-
function initialFirstValidationGate(schema
|
|
3409
|
-
return
|
|
3412
|
+
function initialFirstValidationGate(schema) {
|
|
3413
|
+
return schema.needsAsyncValidation?.() !== true;
|
|
3410
3414
|
}
|
|
3411
3415
|
function seedOriginalsFromBaseline(st, baseline, ensureOrdinals) {
|
|
3412
3416
|
st.originals.clear();
|
|
@@ -3418,7 +3422,7 @@ function seedOriginalsFromBaseline(st, baseline, ensureOrdinals) {
|
|
|
3418
3422
|
});
|
|
3419
3423
|
}
|
|
3420
3424
|
function queueInitialAsyncValidation(st) {
|
|
3421
|
-
if (!st.ssr && st.
|
|
3425
|
+
if (!st.ssr && st.schema.needsAsyncValidation?.() === true) {
|
|
3422
3426
|
queueMicrotask(() => scheduleFieldValidation(
|
|
3423
3427
|
st,
|
|
3424
3428
|
[],
|
|
@@ -3460,10 +3464,6 @@ function ensurePathOrdinal(st, key) {
|
|
|
3460
3464
|
}
|
|
3461
3465
|
return ordinal;
|
|
3462
3466
|
}
|
|
3463
|
-
function pathHasAsyncValidation(st, path) {
|
|
3464
|
-
const { key } = canonicalizePath(path);
|
|
3465
|
-
return pathHasAsyncValidationByKey(st, key, path);
|
|
3466
|
-
}
|
|
3467
3467
|
function pathHasAsyncValidationByKey(st, key, segments) {
|
|
3468
3468
|
const cached = st.pathAsyncCache.get(key);
|
|
3469
3469
|
if (cached !== void 0) return cached;
|
|
@@ -3606,10 +3606,15 @@ function commitWritePatches(st, patches, meta) {
|
|
|
3606
3606
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
3607
3607
|
for (const patch of patches) {
|
|
3608
3608
|
const { key } = canonicalizePath(patch.path);
|
|
3609
|
-
if (
|
|
3609
|
+
if (!st.originals.has(key)) {
|
|
3610
3610
|
st.originals.set(key, { segments: patch.path, value: void 0 });
|
|
3611
3611
|
}
|
|
3612
3612
|
touchFieldRecord(st, key, patch.path, { updatedAt: now });
|
|
3613
|
+
st.pathSweep.track(patch.path, key);
|
|
3614
|
+
for (let i = 1; i < patch.path.length; i++) {
|
|
3615
|
+
const ancestor = patch.path.slice(0, i);
|
|
3616
|
+
st.pathSweep.track(ancestor, canonicalizePath(ancestor).key);
|
|
3617
|
+
}
|
|
3613
3618
|
}
|
|
3614
3619
|
for (const listener of st.formChangeListeners) {
|
|
3615
3620
|
try {
|
|
@@ -3814,10 +3819,7 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3814
3819
|
if (newlyAuthored && st.schema.isPreprocessOrCoerceLeaf(path)) {
|
|
3815
3820
|
const modeForAuthoringTransition = meta?.instance?.validateOn ?? st.fieldValidationMode;
|
|
3816
3821
|
if (modeForAuthoringTransition === "change") {
|
|
3817
|
-
scheduleFieldValidation(st, path, false,
|
|
3818
|
-
...meta?.instance?.validateOn !== void 0 ? { mode: meta.instance.validateOn } : {},
|
|
3819
|
-
...meta?.instance?.debounceMs !== void 0 ? { debounceMs: meta.instance.debounceMs } : {}
|
|
3820
|
-
});
|
|
3822
|
+
scheduleFieldValidation(st, path, false, meta?.instance);
|
|
3821
3823
|
}
|
|
3822
3824
|
}
|
|
3823
3825
|
return true;
|
|
@@ -3833,15 +3835,12 @@ function setValueAtPath(st, path, value, meta) {
|
|
|
3833
3835
|
st.arrayIdentity.realign(path);
|
|
3834
3836
|
} else if (isContainer(currentValue) && !isContainer(value)) {
|
|
3835
3837
|
if (subtreeHadRealBaseline(st, path, currentValue)) {
|
|
3836
|
-
st.removedSubtrees.add(
|
|
3838
|
+
st.removedSubtrees.add(pathKey);
|
|
3837
3839
|
}
|
|
3838
3840
|
}
|
|
3839
3841
|
const effectiveModeAfterWrite = meta?.instance?.validateOn ?? st.fieldValidationMode;
|
|
3840
3842
|
if (effectiveModeAfterWrite === "change") {
|
|
3841
|
-
scheduleFieldValidation(st, path, false,
|
|
3842
|
-
...meta?.instance?.validateOn !== void 0 ? { mode: meta.instance.validateOn } : {},
|
|
3843
|
-
...meta?.instance?.debounceMs !== void 0 ? { debounceMs: meta.instance.debounceMs } : {}
|
|
3844
|
-
});
|
|
3843
|
+
scheduleFieldValidation(st, path, false, meta?.instance);
|
|
3845
3844
|
}
|
|
3846
3845
|
return true;
|
|
3847
3846
|
}
|
|
@@ -3902,12 +3901,11 @@ function reshapeUnionVariant(st, parentPath, oldDiscValue, newDiscValue, variant
|
|
|
3902
3901
|
path: [...parentPath, ...err.path]
|
|
3903
3902
|
}));
|
|
3904
3903
|
applySchemaErrorsForSubtree(st, parentPath, reStamped);
|
|
3905
|
-
const
|
|
3906
|
-
const prevValidation = st.fieldValidationState.get(parentKey2);
|
|
3904
|
+
const prevValidation = st.fieldValidationState.get(parentKey);
|
|
3907
3905
|
if (prevValidation !== void 0) {
|
|
3908
3906
|
if (prevValidation.timer !== null) clearTimeout(prevValidation.timer);
|
|
3909
3907
|
prevValidation.aborted = true;
|
|
3910
|
-
st.fieldValidationState.delete(
|
|
3908
|
+
st.fieldValidationState.delete(parentKey);
|
|
3911
3909
|
}
|
|
3912
3910
|
appliedSync = true;
|
|
3913
3911
|
}
|
|
@@ -3915,17 +3913,14 @@ function reshapeUnionVariant(st, parentPath, oldDiscValue, newDiscValue, variant
|
|
|
3915
3913
|
applyFormReplacement(st, nextForm, meta);
|
|
3916
3914
|
for (const k of newBlankPaths) st.blankPaths.add(k);
|
|
3917
3915
|
if (reshapeMode === "change" && !appliedSync) {
|
|
3918
|
-
scheduleFieldValidation(st, parentPath, false,
|
|
3919
|
-
...meta?.instance?.validateOn !== void 0 ? { mode: meta.instance.validateOn } : {},
|
|
3920
|
-
...meta?.instance?.debounceMs !== void 0 ? { debounceMs: meta.instance.debounceMs } : {}
|
|
3921
|
-
});
|
|
3916
|
+
scheduleFieldValidation(st, parentPath, false, meta?.instance);
|
|
3922
3917
|
}
|
|
3923
3918
|
return true;
|
|
3924
3919
|
}
|
|
3925
|
-
function scheduleFieldValidation(st, path, immediate,
|
|
3926
|
-
const effectiveMode =
|
|
3920
|
+
function scheduleFieldValidation(st, path, immediate, instance) {
|
|
3921
|
+
const effectiveMode = instance?.validateOn ?? st.fieldValidationMode;
|
|
3927
3922
|
if (effectiveMode === "submit") return;
|
|
3928
|
-
const effectiveDebounce =
|
|
3923
|
+
const effectiveDebounce = instance?.debounceMs ?? st.fieldValidationDebounceMs;
|
|
3929
3924
|
const { key } = canonicalizePath(path);
|
|
3930
3925
|
const prev = st.fieldValidationState.get(key);
|
|
3931
3926
|
if (prev !== void 0) {
|
|
@@ -4199,10 +4194,7 @@ function markFocused(st, path, focused, meta) {
|
|
|
4199
4194
|
});
|
|
4200
4195
|
}
|
|
4201
4196
|
if (changed) {
|
|
4202
|
-
scheduleFieldValidation(st, path, true,
|
|
4203
|
-
...meta?.instance?.validateOn !== void 0 ? { mode: meta.instance.validateOn } : {},
|
|
4204
|
-
...meta?.instance?.debounceMs !== void 0 ? { debounceMs: meta.instance.debounceMs } : {}
|
|
4205
|
-
});
|
|
4197
|
+
scheduleFieldValidation(st, path, true, meta?.instance);
|
|
4206
4198
|
}
|
|
4207
4199
|
}
|
|
4208
4200
|
}
|
|
@@ -4214,10 +4206,9 @@ function markInteracted(st, path) {
|
|
|
4214
4206
|
}
|
|
4215
4207
|
function touchAtPath(st, segments) {
|
|
4216
4208
|
const formValue = st.form.value;
|
|
4217
|
-
for (const [, entry] of st.originals) {
|
|
4209
|
+
for (const [leafKey, entry] of st.originals) {
|
|
4218
4210
|
if (!isPathPrefix(segments, entry.segments)) continue;
|
|
4219
4211
|
if (!hasAtPath(formValue, entry.segments)) continue;
|
|
4220
|
-
const leafKey = canonicalizePath(entry.segments).key;
|
|
4221
4212
|
const current = st.fields.get(leafKey);
|
|
4222
4213
|
if (current?.touched === true) continue;
|
|
4223
4214
|
touchFieldRecord(st, leafKey, entry.segments, { touched: true });
|
|
@@ -4227,11 +4218,10 @@ function interactAtPath(st, segments) {
|
|
|
4227
4218
|
if (st.effectiveDisabled.value) return false;
|
|
4228
4219
|
const formValue = st.form.value;
|
|
4229
4220
|
let interactedAny = false;
|
|
4230
|
-
for (const [, entry] of st.originals) {
|
|
4221
|
+
for (const [leafKey, entry] of st.originals) {
|
|
4231
4222
|
if (!isPathPrefix(segments, entry.segments)) continue;
|
|
4232
4223
|
if (!hasAtPath(formValue, entry.segments)) continue;
|
|
4233
4224
|
interactedAny = true;
|
|
4234
|
-
const leafKey = canonicalizePath(entry.segments).key;
|
|
4235
4225
|
const current = st.fields.get(leafKey);
|
|
4236
4226
|
if (current?.touched === true && current.interacted === true && current.blurredAfterInteraction === true) {
|
|
4237
4227
|
continue;
|
|
@@ -4283,11 +4273,7 @@ function adoptResolvedDefaults(st, value) {
|
|
|
4283
4273
|
st.schema
|
|
4284
4274
|
)
|
|
4285
4275
|
);
|
|
4286
|
-
seedOriginalsFromBaseline(
|
|
4287
|
-
st,
|
|
4288
|
-
computeBaselineResponse(st.schema, st.strict, st.defaultValues).data,
|
|
4289
|
-
false
|
|
4290
|
-
);
|
|
4276
|
+
seedOriginalsFromBaseline(st, computeBaselineResponse(st.schema, st.defaultValues).data, false);
|
|
4291
4277
|
}
|
|
4292
4278
|
function reset(st, nextDefaultValues) {
|
|
4293
4279
|
const resetSource = nextDefaultValues === void 0 ? st.defaultValues : mergeSparseHydration(
|
|
@@ -4296,7 +4282,7 @@ function reset(st, nextDefaultValues) {
|
|
|
4296
4282
|
st.schema
|
|
4297
4283
|
);
|
|
4298
4284
|
st.defaultValues = structuralSnapshot(resetSource);
|
|
4299
|
-
const resetResponse = computeBaselineResponse(st.schema,
|
|
4285
|
+
const resetResponse = computeBaselineResponse(st.schema, resetSource);
|
|
4300
4286
|
const next = resetResponse.data;
|
|
4301
4287
|
rebuildAuthoredPaths(st, resetSource, next);
|
|
4302
4288
|
applyFormReplacement(st, next);
|
|
@@ -4313,16 +4299,14 @@ function reset(st, nextDefaultValues) {
|
|
|
4313
4299
|
st.blankPaths.add(key);
|
|
4314
4300
|
}
|
|
4315
4301
|
st.errorCells.clear();
|
|
4316
|
-
if (
|
|
4302
|
+
if (!resetResponse.success) {
|
|
4317
4303
|
replaceErrorChannel(st, "schema", resetResponse.errors);
|
|
4318
4304
|
}
|
|
4319
|
-
|
|
4320
|
-
|
|
4321
|
-
|
|
4322
|
-
applySchemaErrorsForSubtree(st, [], syncResult.errors);
|
|
4323
|
-
}
|
|
4305
|
+
const syncResult = st.schema.validateAtPath(st.form.value, void 0, { sync: true });
|
|
4306
|
+
if (!(syncResult instanceof Promise) && !syncResult.success) {
|
|
4307
|
+
applySchemaErrorsForSubtree(st, [], syncResult.errors);
|
|
4324
4308
|
}
|
|
4325
|
-
st.firstValidationDone.value = initialFirstValidationGate(st.schema
|
|
4309
|
+
st.firstValidationDone.value = initialFirstValidationGate(st.schema);
|
|
4326
4310
|
queueInitialAsyncValidation(st);
|
|
4327
4311
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
4328
4312
|
for (const [pathKey, record] of st.fields) {
|
|
@@ -4412,10 +4396,6 @@ function clearFieldRecordFlags(st, pathKey) {
|
|
|
4412
4396
|
if (record === void 0) return;
|
|
4413
4397
|
st.fields.set(pathKey, withClearedHistoryFlags(record, (/* @__PURE__ */ new Date()).toISOString()));
|
|
4414
4398
|
}
|
|
4415
|
-
function isPristineAtPath(st, path) {
|
|
4416
|
-
const { key, segments } = canonicalizePath(path);
|
|
4417
|
-
return isPristineAtPathByKey(st, key, segments);
|
|
4418
|
-
}
|
|
4419
4399
|
function isPristineAtPathByKey(st, key, segments) {
|
|
4420
4400
|
if (st.blankPaths.has(key) !== st.originalBlankPaths.has(key)) return false;
|
|
4421
4401
|
const entry = st.originals.get(key);
|
|
@@ -4449,12 +4429,8 @@ function getFieldRecord(st, path) {
|
|
|
4449
4429
|
const { key } = canonicalizePath(path);
|
|
4450
4430
|
return st.fields.get(key);
|
|
4451
4431
|
}
|
|
4452
|
-
function getOriginalAtPath(st, path) {
|
|
4453
|
-
const { key } = canonicalizePath(path);
|
|
4454
|
-
return st.originals.get(key)?.value;
|
|
4455
|
-
}
|
|
4456
4432
|
function createFormStore(options) {
|
|
4457
|
-
const { formKey, schema, defaultValues,
|
|
4433
|
+
const { formKey, schema, defaultValues, hydration } = options;
|
|
4458
4434
|
const ssr = options.ssr === true;
|
|
4459
4435
|
const ssrPrefetch = options.ssrPrefetch;
|
|
4460
4436
|
const rememberVariants = options.rememberVariants !== false;
|
|
@@ -4462,22 +4438,16 @@ function createFormStore(options) {
|
|
|
4462
4438
|
const fieldValidationDebounceMs = normalizeNumericOption({
|
|
4463
4439
|
value: options.debounceMs ?? DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS,
|
|
4464
4440
|
source: "useForm.debounceMs",
|
|
4465
|
-
allowInfinity: false,
|
|
4466
4441
|
min: 0,
|
|
4467
4442
|
defaultValue: DEFAULT_FIELD_VALIDATION_DEBOUNCE_MS
|
|
4468
4443
|
});
|
|
4469
|
-
const
|
|
4470
|
-
const resolvedGetDisplayState = resolveGetDisplayState(options.getDisplayState);
|
|
4444
|
+
const coerceEnabled = resolveCoerceEnabled(options.coerce);
|
|
4471
4445
|
const cleanupHooks = [];
|
|
4472
4446
|
const modules = /* @__PURE__ */ new Map();
|
|
4473
4447
|
const fieldValidatingSince = reactive(/* @__PURE__ */ new Map());
|
|
4474
4448
|
const displayEngine = createDisplayEngine(ssr);
|
|
4475
4449
|
cleanupHooks.push(() => displayEngine.dispose());
|
|
4476
|
-
const schemaResponse = computeBaselineResponse(
|
|
4477
|
-
schema,
|
|
4478
|
-
strict,
|
|
4479
|
-
defaultValues
|
|
4480
|
-
);
|
|
4450
|
+
const schemaResponse = computeBaselineResponse(schema, defaultValues);
|
|
4481
4451
|
const schemaInitialData = schemaResponse.data;
|
|
4482
4452
|
const authoredPaths = /* @__PURE__ */ new Set();
|
|
4483
4453
|
const initialData = hydration !== void 0 ? hydration.form : structuralSnapshot(schemaInitialData);
|
|
@@ -4490,16 +4460,15 @@ function createFormStore(options) {
|
|
|
4490
4460
|
const v = getAtPath(toRaw(form.value), arraySegs);
|
|
4491
4461
|
return Array.isArray(v) ? v.length : 0;
|
|
4492
4462
|
});
|
|
4493
|
-
const fields =
|
|
4463
|
+
const fields = shallowReactive(/* @__PURE__ */ new Map());
|
|
4494
4464
|
const domBinding = shallowRef(null);
|
|
4495
|
-
const errorCells =
|
|
4496
|
-
const originals =
|
|
4465
|
+
const errorCells = shallowReactive(/* @__PURE__ */ new Map());
|
|
4466
|
+
const originals = shallowReactive(/* @__PURE__ */ new Map());
|
|
4497
4467
|
const removedSubtrees = /* @__PURE__ */ new Set();
|
|
4498
|
-
const initialTransientList = hydration?.blankPaths ?? options.initialBlankPaths ?? [];
|
|
4499
4468
|
const blankPaths = reactive(/* @__PURE__ */ new Set());
|
|
4500
4469
|
const originalBlankPaths = /* @__PURE__ */ new Set();
|
|
4501
|
-
|
|
4502
|
-
|
|
4470
|
+
const seededBlankPaths = hydration !== void 0 ? (hydration.blankPaths ?? []).map((dotted) => canonicalizePath(dotted).key) : options.initialBlankPaths ?? [];
|
|
4471
|
+
for (const key of seededBlankPaths) {
|
|
4503
4472
|
blankPaths.add(key);
|
|
4504
4473
|
originalBlankPaths.add(key);
|
|
4505
4474
|
}
|
|
@@ -4516,6 +4485,9 @@ function createFormStore(options) {
|
|
|
4516
4485
|
}
|
|
4517
4486
|
return result;
|
|
4518
4487
|
});
|
|
4488
|
+
const errorPathIndex = computed(
|
|
4489
|
+
() => buildErrorPathIndex(errorCells, derivedBlankErrors.value)
|
|
4490
|
+
);
|
|
4519
4491
|
const submitting = ref(false);
|
|
4520
4492
|
const activeSubmissions = ref(0);
|
|
4521
4493
|
const submissionAttempts = ref(0);
|
|
@@ -4540,7 +4512,7 @@ function createFormStore(options) {
|
|
|
4540
4512
|
const defaultsResolved = ref(false);
|
|
4541
4513
|
const activated = ref(false);
|
|
4542
4514
|
const activationPromise = ref(void 0);
|
|
4543
|
-
const firstValidationDone = ref(initialFirstValidationGate(schema
|
|
4515
|
+
const firstValidationDone = ref(initialFirstValidationGate(schema));
|
|
4544
4516
|
watch(activeValidations, (now, prev) => {
|
|
4545
4517
|
if (prev > 0 && now === 0) {
|
|
4546
4518
|
firstValidationDone.value = true;
|
|
@@ -4558,6 +4530,33 @@ function createFormStore(options) {
|
|
|
4558
4530
|
const activeTransforms = ref(0);
|
|
4559
4531
|
const transformRuns = /* @__PURE__ */ new Map();
|
|
4560
4532
|
const transformWaiters = [];
|
|
4533
|
+
const errorWindows = /* @__PURE__ */ new Map();
|
|
4534
|
+
const pathSweep = createDynamicPathSweep({
|
|
4535
|
+
onFormChange: (listener) => {
|
|
4536
|
+
formChangeListeners.add(listener);
|
|
4537
|
+
},
|
|
4538
|
+
isFixedObjectAtPath: (path) => schema.isFixedObjectAtPath(path)
|
|
4539
|
+
});
|
|
4540
|
+
pathSweep.onEvict((key) => {
|
|
4541
|
+
fields.delete(key);
|
|
4542
|
+
fieldValidationState.delete(key);
|
|
4543
|
+
authoredPaths.delete(key);
|
|
4544
|
+
if (originals.get(key)?.value === void 0) originals.delete(key);
|
|
4545
|
+
errorWindows.delete(key);
|
|
4546
|
+
});
|
|
4547
|
+
const errorWindowAt = (prefix, prefixKey) => {
|
|
4548
|
+
let cached = errorWindows.get(prefixKey);
|
|
4549
|
+
if (cached === void 0) {
|
|
4550
|
+
const frozen = [...prefix];
|
|
4551
|
+
cached = computed((prev) => {
|
|
4552
|
+
const next = windowUnder(errorPathIndex.value, frozen);
|
|
4553
|
+
return prev !== void 0 && isSameWindow(prev, next) ? prev : next;
|
|
4554
|
+
});
|
|
4555
|
+
errorWindows.set(prefixKey, cached);
|
|
4556
|
+
pathSweep.track(frozen, prefixKey);
|
|
4557
|
+
}
|
|
4558
|
+
return cached.value;
|
|
4559
|
+
};
|
|
4561
4560
|
const arrayBookkeeping = createArrayBookkeeping({
|
|
4562
4561
|
form,
|
|
4563
4562
|
fields,
|
|
@@ -4575,6 +4574,7 @@ function createFormStore(options) {
|
|
|
4575
4574
|
touchFieldRecord: (pathKey, path, patch) => touchFieldRecord(st, pathKey, path, patch),
|
|
4576
4575
|
decFieldValidation: (key) => decFieldValidation(st, key)
|
|
4577
4576
|
});
|
|
4577
|
+
const bind = (fn) => (...args) => fn(st, ...args);
|
|
4578
4578
|
const st = {
|
|
4579
4579
|
// --- public data (the FormStore contract's state members) ---
|
|
4580
4580
|
formKey,
|
|
@@ -4582,10 +4582,11 @@ function createFormStore(options) {
|
|
|
4582
4582
|
fields,
|
|
4583
4583
|
errorCells,
|
|
4584
4584
|
derivedBlankErrors,
|
|
4585
|
+
errorWindowAt,
|
|
4585
4586
|
originals,
|
|
4587
|
+
pathSweep,
|
|
4586
4588
|
schema,
|
|
4587
4589
|
ssr,
|
|
4588
|
-
getDisplayState: resolvedGetDisplayState,
|
|
4589
4590
|
submitting,
|
|
4590
4591
|
activeSubmissions,
|
|
4591
4592
|
submissionAttempts,
|
|
@@ -4613,11 +4614,10 @@ function createFormStore(options) {
|
|
|
4613
4614
|
displayEngine,
|
|
4614
4615
|
domBinding,
|
|
4615
4616
|
modules,
|
|
4616
|
-
|
|
4617
|
+
coerceEnabled,
|
|
4617
4618
|
blankPaths,
|
|
4618
4619
|
originalBlankPaths,
|
|
4619
4620
|
// --- kernel-internal state ---
|
|
4620
|
-
strict,
|
|
4621
4621
|
// Defensive copy, not a fix for an observed alias: today
|
|
4622
4622
|
// `getDefaultValues` happens to build a fresh tree, so form storage
|
|
4623
4623
|
// does not currently share structure with the consumer's object.
|
|
@@ -4654,17 +4654,20 @@ function createFormStore(options) {
|
|
|
4654
4654
|
transformTokenSeq: 0,
|
|
4655
4655
|
warnedDisabledWrite: false,
|
|
4656
4656
|
// --- methods: thin per-instance skins over the module kernel ---
|
|
4657
|
-
rehydrate: (
|
|
4658
|
-
activate: (
|
|
4659
|
-
adoptResolvedDefaults: (
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4667
|
-
|
|
4657
|
+
rehydrate: bind(rehydrate),
|
|
4658
|
+
activate: bind(activate),
|
|
4659
|
+
adoptResolvedDefaults: bind(adoptResolvedDefaults),
|
|
4660
|
+
pathHasAsyncValidationByKey: bind(pathHasAsyncValidationByKey),
|
|
4661
|
+
applyFormReplacement: bind(applyFormReplacement),
|
|
4662
|
+
setValueAtPath: bind(setValueAtPath),
|
|
4663
|
+
getValueAtPath: bind(getValueAtPath),
|
|
4664
|
+
arrayElementKey: bind(arrayElementKey),
|
|
4665
|
+
reset: bind(reset),
|
|
4666
|
+
resetField: bind(resetField),
|
|
4667
|
+
// The schema/user pair below reads as a fold waiting to happen. It was
|
|
4668
|
+
// tried: a `setErrorsForPathIn(channel)` factory measured 10 B LARGER,
|
|
4669
|
+
// because gzip had already collected the rent on two adjacent copies
|
|
4670
|
+
// and the helper added a name the original did not need.
|
|
4668
4671
|
setSchemaErrorsForPath: (path, entries) => setErrorChannelForKey(
|
|
4669
4672
|
st,
|
|
4670
4673
|
canonicalizePath(path).key,
|
|
@@ -4673,7 +4676,7 @@ function createFormStore(options) {
|
|
|
4673
4676
|
),
|
|
4674
4677
|
setAllSchemaErrors: (entries) => replaceErrorChannel(st, "schema", entries),
|
|
4675
4678
|
clearSchemaErrors: (path) => clearErrorChannel(st, "schema", path),
|
|
4676
|
-
applySchemaErrorsForSubtree: (
|
|
4679
|
+
applySchemaErrorsForSubtree: bind(applySchemaErrorsForSubtree),
|
|
4677
4680
|
setAllUserErrors: (entries) => replaceErrorChannel(st, "user", entries),
|
|
4678
4681
|
setUserErrorsForPath: (path, entries) => setErrorChannelForKey(
|
|
4679
4682
|
st,
|
|
@@ -4682,37 +4685,34 @@ function createFormStore(options) {
|
|
|
4682
4685
|
entries.length === 0 ? NO_ERRORS : [...entries]
|
|
4683
4686
|
),
|
|
4684
4687
|
clearUserErrors: (path) => clearErrorChannel(st, "user", path),
|
|
4685
|
-
restoreErrorCells: (
|
|
4686
|
-
getErrorsForPath: (
|
|
4687
|
-
ensurePathOrdinal: (
|
|
4688
|
-
noteDomConnected: (
|
|
4689
|
-
noteDomDisconnected: (
|
|
4690
|
-
markFocused: (
|
|
4691
|
-
markInteracted: (
|
|
4692
|
-
touchAtPath: (
|
|
4693
|
-
interactAtPath: (
|
|
4694
|
-
markConnectedOptimistically: (
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
emitSubmitSuccess: () => emitSubmitSuccess(st),
|
|
4714
|
-
registerCleanup: (fn) => registerCleanup(st, fn),
|
|
4715
|
-
dispose: () => dispose(st)
|
|
4688
|
+
restoreErrorCells: bind(restoreErrorCells),
|
|
4689
|
+
getErrorsForPath: bind(getErrorsForPath),
|
|
4690
|
+
ensurePathOrdinal: bind(ensurePathOrdinal),
|
|
4691
|
+
noteDomConnected: bind(noteDomConnected),
|
|
4692
|
+
noteDomDisconnected: bind(noteDomDisconnected),
|
|
4693
|
+
markFocused: bind(markFocused),
|
|
4694
|
+
markInteracted: bind(markInteracted),
|
|
4695
|
+
touchAtPath: bind(touchAtPath),
|
|
4696
|
+
interactAtPath: bind(interactAtPath),
|
|
4697
|
+
markConnectedOptimistically: bind(markConnectedOptimistically),
|
|
4698
|
+
isPristineAtPathByKey: bind(isPristineAtPathByKey),
|
|
4699
|
+
hasStructuralChangeUnder: bind(hasStructuralChangeUnder),
|
|
4700
|
+
hasRemovedSubtreeUnder: bind(hasRemovedSubtreeUnder),
|
|
4701
|
+
getFieldRecord: bind(getFieldRecord),
|
|
4702
|
+
cancelFieldValidation: bind(cancelFieldValidation),
|
|
4703
|
+
beginTransform: bind(beginTransform),
|
|
4704
|
+
isCurrentTransform: bind(isCurrentTransform),
|
|
4705
|
+
endTransform: bind(endTransform),
|
|
4706
|
+
setTransformError: bind(setTransformError),
|
|
4707
|
+
cancelTransformsUnder: bind(cancelTransformsUnder),
|
|
4708
|
+
settleTransforms: bind(settleTransforms),
|
|
4709
|
+
scheduleFieldValidation: bind(scheduleFieldValidation),
|
|
4710
|
+
onFormChange: bind(onFormChange),
|
|
4711
|
+
onSubmitSuccess: bind(onSubmitSuccess),
|
|
4712
|
+
onReset: bind(onReset),
|
|
4713
|
+
emitSubmitSuccess: bind(emitSubmitSuccess),
|
|
4714
|
+
registerCleanup: bind(registerCleanup),
|
|
4715
|
+
dispose: bind(dispose)
|
|
4716
4716
|
};
|
|
4717
4717
|
rebuildAuthoredPaths(st, defaultValues, schemaInitialData);
|
|
4718
4718
|
seedOriginalsFromBaseline(st, schemaInitialData, true);
|
|
@@ -4751,7 +4751,7 @@ function createFormStore(options) {
|
|
|
4751
4751
|
blurredAfterInteraction: false
|
|
4752
4752
|
});
|
|
4753
4753
|
});
|
|
4754
|
-
if (
|
|
4754
|
+
if (!schemaResponse.success) {
|
|
4755
4755
|
replaceErrorChannel(st, "schema", schemaResponse.errors);
|
|
4756
4756
|
}
|
|
4757
4757
|
}
|
|
@@ -4782,19 +4782,18 @@ function useAbstractForm(configuration, options) {
|
|
|
4782
4782
|
const resolvedDefaults = resolveTrichotomy(configuration.defaultValues);
|
|
4783
4783
|
const materialisedDefaults = resolvedDefaults.kind === "sync" ? resolvedDefaults.value : void 0;
|
|
4784
4784
|
const { defaultValues: _droppedDefaults, ...configWithoutDefaults } = configuration;
|
|
4785
|
-
const
|
|
4786
|
-
const merged = mergeWithDefaults(registry.defaults, trichotomyOverride);
|
|
4787
|
-
const maxRecursionDepth = normalizeNumericOption({
|
|
4788
|
-
value: merged.maxRecursionDepth ?? DEFAULT_MAX_RECURSION_DEPTH,
|
|
4789
|
-
source: "useForm.maxRecursionDepth",
|
|
4790
|
-
allowInfinity: true,
|
|
4791
|
-
min: 0,
|
|
4792
|
-
defaultValue: DEFAULT_MAX_RECURSION_DEPTH
|
|
4793
|
-
});
|
|
4794
|
-
const resolvedSchema = getComputedSchema(key, configuration.schema, { maxRecursionDepth });
|
|
4785
|
+
const materialisedConfiguration = materialisedDefaults === void 0 ? configWithoutDefaults : { ...configWithoutDefaults, defaultValues: materialisedDefaults };
|
|
4795
4786
|
const existing = registry.forms.get(key);
|
|
4787
|
+
const resolvedSchema = existing === void 0 || false ? getComputedSchema(key, configuration.schema, {
|
|
4788
|
+
maxRecursionDepth: DEFAULT_MAX_RECURSION_DEPTH
|
|
4789
|
+
}) : existing.schema;
|
|
4796
4790
|
const hadPendingHydration = registry.pendingHydration.has(key);
|
|
4797
|
-
const state = existing ?? buildFreshState(
|
|
4791
|
+
const state = existing ?? buildFreshState(
|
|
4792
|
+
key,
|
|
4793
|
+
resolvedSchema,
|
|
4794
|
+
materialisedConfiguration,
|
|
4795
|
+
registry
|
|
4796
|
+
);
|
|
4798
4797
|
if (existing !== void 0) ; else if (resolvedDefaults.kind === "sync") {
|
|
4799
4798
|
state.defaultsResolved.value = true;
|
|
4800
4799
|
}
|
|
@@ -4819,8 +4818,8 @@ function useAbstractForm(configuration, options) {
|
|
|
4819
4818
|
const releaseConsumer = registry.trackConsumer(key);
|
|
4820
4819
|
onScopeDispose(releaseConsumer);
|
|
4821
4820
|
}
|
|
4822
|
-
if (existing === void 0 &&
|
|
4823
|
-
const historyModule =
|
|
4821
|
+
if (existing === void 0 && materialisedConfiguration.history !== void 0) {
|
|
4822
|
+
const historyModule = materialisedConfiguration.history.attach(state);
|
|
4824
4823
|
state.modules.set(HISTORY_MODULE_KEY, historyModule);
|
|
4825
4824
|
state.registerCleanup(() => historyModule.dispose());
|
|
4826
4825
|
}
|
|
@@ -4833,36 +4832,16 @@ function useAbstractForm(configuration, options) {
|
|
|
4833
4832
|
provide(kFormInstanceId, formInstanceId);
|
|
4834
4833
|
}
|
|
4835
4834
|
const apiOptions = pickDefined({
|
|
4836
|
-
|
|
4835
|
+
focusOnInvalidSubmit: materialisedConfiguration.focusOnInvalidSubmit,
|
|
4837
4836
|
history: state.modules.get(HISTORY_MODULE_KEY),
|
|
4838
|
-
validateOn:
|
|
4839
|
-
debounceMs:
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
rememberVariants: merged.rememberVariants,
|
|
4843
|
-
autoAria: merged.autoAria
|
|
4837
|
+
validateOn: materialisedConfiguration.validateOn,
|
|
4838
|
+
debounceMs: materialisedConfiguration.debounceMs,
|
|
4839
|
+
coerce: materialisedConfiguration.coerce,
|
|
4840
|
+
rememberVariants: materialisedConfiguration.rememberVariants
|
|
4844
4841
|
});
|
|
4845
4842
|
const api = buildFormApi(state, formInstanceId, apiOptions);
|
|
4846
4843
|
return api;
|
|
4847
4844
|
}
|
|
4848
|
-
function mergeWithDefaults(defaults, configuration) {
|
|
4849
|
-
return {
|
|
4850
|
-
...configuration,
|
|
4851
|
-
...pickDefined({
|
|
4852
|
-
strict: configuration.strict ?? defaults.strict,
|
|
4853
|
-
onInvalidSubmit: configuration.onInvalidSubmit ?? defaults.onInvalidSubmit,
|
|
4854
|
-
history: configuration.history ?? defaults.history,
|
|
4855
|
-
rememberVariants: configuration.rememberVariants ?? defaults.rememberVariants,
|
|
4856
|
-
disabled: configuration.disabled ?? defaults.disabled,
|
|
4857
|
-
coerce: configuration.coerce ?? defaults.coerce,
|
|
4858
|
-
validateOn: configuration.validateOn ?? defaults.validateOn,
|
|
4859
|
-
debounceMs: configuration.debounceMs ?? defaults.debounceMs,
|
|
4860
|
-
getDisplayState: configuration.getDisplayState ?? defaults.getDisplayState,
|
|
4861
|
-
maxRecursionDepth: configuration.maxRecursionDepth ?? defaults.maxRecursionDepth,
|
|
4862
|
-
autoAria: configuration.autoAria ?? defaults.autoAria
|
|
4863
|
-
})
|
|
4864
|
-
};
|
|
4865
|
-
}
|
|
4866
4845
|
const HISTORY_MODULE_KEY = "history";
|
|
4867
4846
|
function buildFreshState(key, schema, configuration, registry) {
|
|
4868
4847
|
const pending = registry.pendingHydration.get(key);
|
|
@@ -4882,13 +4861,11 @@ function buildFreshState(key, schema, configuration, registry) {
|
|
|
4882
4861
|
hydration: pending,
|
|
4883
4862
|
ssr: registry.ssr,
|
|
4884
4863
|
...pickDefined({
|
|
4885
|
-
strict: configuration.strict,
|
|
4886
4864
|
validateOn: configuration.validateOn,
|
|
4887
4865
|
debounceMs: configuration.debounceMs,
|
|
4888
4866
|
rememberVariants: configuration.rememberVariants,
|
|
4889
4867
|
disabled: configuration.disabled,
|
|
4890
4868
|
coerce: configuration.coerce,
|
|
4891
|
-
getDisplayState: configuration.getDisplayState,
|
|
4892
4869
|
initialBlankPaths
|
|
4893
4870
|
}),
|
|
4894
4871
|
// Server-only: bind the SSR prefetch coordination handles. `enqueue`
|
|
@@ -5135,25 +5112,18 @@ function createWizardHistory(param) {
|
|
|
5135
5112
|
};
|
|
5136
5113
|
}
|
|
5137
5114
|
|
|
5138
|
-
const NOOP_FINGERPRINT = "attaform:wizard-noop";
|
|
5139
5115
|
const EMPTY_SLIM_KINDS = /* @__PURE__ */ new Set();
|
|
5140
|
-
|
|
5141
|
-
|
|
5142
|
-
|
|
5143
|
-
|
|
5144
|
-
|
|
5145
|
-
|
|
5146
|
-
|
|
5147
|
-
|
|
5148
|
-
|
|
5149
|
-
|
|
5150
|
-
|
|
5151
|
-
errors: void 0,
|
|
5152
|
-
formKey
|
|
5153
|
-
};
|
|
5154
|
-
return {
|
|
5155
|
-
fingerprint: () => Promise.resolve(NOOP_FINGERPRINT),
|
|
5156
|
-
getDefaultValues: () => defaultsResponse,
|
|
5116
|
+
const EMPTY_VALUE = {};
|
|
5117
|
+
const NOOP_SUCCESS = {
|
|
5118
|
+
success: true,
|
|
5119
|
+
data: EMPTY_VALUE,
|
|
5120
|
+
errors: void 0
|
|
5121
|
+
};
|
|
5122
|
+
const NOOP_DEFAULTS = NOOP_SUCCESS;
|
|
5123
|
+
let NOOP_SCHEMA;
|
|
5124
|
+
function buildNoopWizardSchema() {
|
|
5125
|
+
NOOP_SCHEMA ?? (NOOP_SCHEMA = {
|
|
5126
|
+
getDefaultValues: () => NOOP_DEFAULTS,
|
|
5157
5127
|
getDefaultAtPath: () => void 0,
|
|
5158
5128
|
getEmptyValueAtPath: () => void 0,
|
|
5159
5129
|
isPreprocessOrCoerceLeaf: () => false,
|
|
@@ -5164,13 +5134,14 @@ function buildNoopWizardSchema(formKey) {
|
|
|
5164
5134
|
// addressable, root included.
|
|
5165
5135
|
entryKeyKindAtPath: () => void 0,
|
|
5166
5136
|
getSchemasAtPath: () => [],
|
|
5167
|
-
validateAtPath: () =>
|
|
5137
|
+
validateAtPath: () => NOOP_SUCCESS,
|
|
5168
5138
|
getSlimPrimitiveTypesAtPath: () => new Set(EMPTY_SLIM_KINDS),
|
|
5169
5139
|
isLeafAtPath: () => false,
|
|
5170
5140
|
isRequiredAtPath: () => false,
|
|
5171
5141
|
getUnionDiscriminatorAtPath: () => void 0,
|
|
5172
5142
|
hasDiscriminatedUnions: () => false
|
|
5173
|
-
};
|
|
5143
|
+
});
|
|
5144
|
+
return NOOP_SCHEMA;
|
|
5174
5145
|
}
|
|
5175
5146
|
|
|
5176
5147
|
function buildCallableReadonlySnapshotProxy(opts) {
|
|
@@ -5285,7 +5256,7 @@ function useWizard(options) {
|
|
|
5285
5256
|
if (typeof slot !== "string") continue;
|
|
5286
5257
|
if (noopForms.has(slot)) continue;
|
|
5287
5258
|
const noop = useAbstractForm({
|
|
5288
|
-
schema: buildNoopWizardSchema(
|
|
5259
|
+
schema: buildNoopWizardSchema(),
|
|
5289
5260
|
key: slot
|
|
5290
5261
|
});
|
|
5291
5262
|
noopForms.set(slot, noop);
|
|
@@ -5296,7 +5267,7 @@ function useWizard(options) {
|
|
|
5296
5267
|
const noop = lazyNoopScope.run(
|
|
5297
5268
|
() => useAbstractForm(
|
|
5298
5269
|
{
|
|
5299
|
-
schema: buildNoopWizardSchema(
|
|
5270
|
+
schema: buildNoopWizardSchema(),
|
|
5300
5271
|
key
|
|
5301
5272
|
},
|
|
5302
5273
|
{ registry }
|
|
@@ -6380,4 +6351,4 @@ function escapeForInlineScript(json) {
|
|
|
6380
6351
|
});
|
|
6381
6352
|
}
|
|
6382
6353
|
|
|
6383
|
-
export { AttaformErrorCode as A,
|
|
6354
|
+
export { AttaformErrorCode as A, injectWizard as a, isUnset as b, useAbstractForm as c, useRegister as d, escapeForInlineScript as e, useWizard as f, gate as g, getAtPath as h, injectForm as i, humanize as j, isPlainRecord as k, lazy as l, slimKindOf as s, unset as u };
|