attaform 0.28.0 → 0.29.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/chunks/fingerprint.mjs +1 -1
- package/dist/chunks/fingerprint2.mjs +2 -2
- package/dist/dev/abstract.mjs +4 -4
- package/dist/dev/chunks/devtools.mjs +1 -1
- package/dist/dev/chunks/fingerprint.mjs +1 -1
- package/dist/dev/chunks/fingerprint2.mjs +2 -2
- package/dist/dev/directive.mjs +1 -1
- package/dist/dev/history.mjs +1 -1
- package/dist/dev/index.mjs +5 -5
- package/dist/dev/runtime/plugins/attaform.mjs +1 -1
- package/dist/dev/shared/{attaform-dev.Dr2YzS5B.mjs → attaform-dev.A-TpJW0B.mjs} +11 -1
- package/dist/dev/shared/{attaform-dev.oYrkP9dj.mjs → attaform-dev.BO-71R54.mjs} +51 -158
- package/dist/dev/shared/{attaform-dev.6qxD-Yqo.mjs → attaform-dev.BgM6FdtA.mjs} +143 -36
- package/dist/{shared/attaform.h0i6LijT.mjs → dev/shared/attaform-dev.ButTkwHd.mjs} +149 -16
- package/dist/{shared/attaform.BJGA_UOS.mjs → dev/shared/attaform-dev.BxfsuwBR.mjs} +8 -0
- package/dist/dev/shared/{attaform-dev.P7cseiEG.mjs → attaform-dev.D8aoKb89.mjs} +13 -4
- package/dist/dev/shared/{attaform-dev.BXE2cr0L.mjs → attaform-dev.DD5m2W51.mjs} +1 -1
- package/dist/dev/shared/{attaform-dev.WmuhD_CZ.mjs → attaform-dev.DHuydLAC.mjs} +344 -96
- package/dist/dev/shared/{attaform-dev.BR8u0YOZ.mjs → attaform-dev.DrzObAZo.mjs} +4 -4
- package/dist/dev/shared/{attaform-dev.D2I8e_Mm.mjs → attaform-dev.q6UutkCx.mjs} +170 -132
- 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 -1
- package/dist/index.d.mts +9 -7
- package/dist/index.mjs +5 -5
- package/dist/nuxt.d.mts +10 -10
- package/dist/runtime/plugins/attaform.mjs +1 -1
- package/dist/shared/{attaform.C09fpdLS.mjs → attaform.B0dKL8ST.mjs} +143 -36
- package/dist/shared/{attaform.Cs2Rbdlo.mjs → attaform.BK0cgu2K.mjs} +123 -139
- package/dist/shared/{attaform.D6DCnnQu.mjs → attaform.BndjUUYX.mjs} +4 -4
- package/dist/{dev/shared/attaform-dev.BJGA_UOS.mjs → shared/attaform.BxfsuwBR.mjs} +8 -0
- package/dist/shared/{attaform.NLmerepI.mjs → attaform.C2MVyuxC.mjs} +42 -151
- package/dist/shared/{attaform.B4VkS43-.d.mts → attaform.CIWLMY-R.d.mts} +1 -1
- package/dist/shared/{attaform.B8k8JrmK.mjs → attaform.CZMAYwSK.mjs} +338 -95
- package/dist/shared/{attaform.wfY8XFvm.mjs → attaform.CZYt_5N_.mjs} +11 -1
- package/dist/shared/{attaform.Cgu-hdSb.d.mts → attaform.CsoeRi3P.d.mts} +224 -32
- package/dist/{dev/shared/attaform-dev.By4PRjt0.mjs → shared/attaform.Cvao8bW5.mjs} +132 -22
- package/dist/shared/{attaform.Dq4vWxuG.mjs → attaform.D0x-qSXm.mjs} +1 -1
- package/dist/shared/{attaform.CJP3RkGa.mjs → attaform.D1fnTifF.mjs} +168 -132
- package/dist/shared/{attaform.D5V4tZWq.d.mts → attaform.DDtqHYv1.d.mts} +88 -7
- package/dist/shared/{attaform.uLbun31C.mjs → attaform.DffRL5pP.mjs} +12 -4
- package/dist/shared/{attaform.JfSWdEcb.d.mts → attaform.axHXVQO7.d.mts} +1 -1
- package/dist/transforms.d.mts +0 -22
- package/dist/transforms.mjs +1 -1
- package/dist/vite.d.mts +13 -4
- package/dist/vite.mjs +3 -2
- package/dist/zod-v3.d.mts +6 -4
- package/dist/zod-v3.mjs +6 -6
- package/dist/zod-v4.d.mts +14 -27
- package/dist/zod-v4.mjs +6 -6
- package/dist/zod.d.mts +4 -4
- package/dist/zod.mjs +5 -5
- package/package.json +17 -14
- package/skills/attaform/SKILL.md +5 -2
- package/skills/attaform/references/custom-components.md +7 -2
- package/skills/attaform/references/errors.md +8 -3
- package/skills/attaform/references/saving.md +77 -0
- package/skills/attaform/references/wizards.md +10 -8
|
@@ -1,9 +1,9 @@
|
|
|
1
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.
|
|
2
|
+
import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform.D0x-qSXm.mjs';
|
|
3
|
+
import { c as armDomBinding } from './attaform.DffRL5pP.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, i as isShadowedKey,
|
|
6
|
-
import { i as isPathPrefix, e as canonicalizePath,
|
|
5
|
+
import { A as ANONYMOUS_FORM_KEY_PREFIX, d as consumerHas, i as isShadowedKey, e as safeOwnHas, a as safeOwnRead, 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.Cvao8bW5.mjs';
|
|
6
|
+
import { i as isPathPrefix, e as canonicalizePath, j as cellEntriesFor, s as segmentsForPathKey, k as keyForSegments, m as mapSegmentKeys, b as ROOT_PATH_KEY, S as SubmitErrorHandlerError, t as toError, l as groupErrorsByKey, n as normalizeErrorInput, h as SET_MEMBER_SEGMENT, R as ROOT_PATH, o as normalizeErrorInputs, q as coerceToPathKey, a as InvalidUseFormConfigError, d as ReservedFormKeyError } from './attaform.CZYt_5N_.mjs';
|
|
7
7
|
|
|
8
8
|
const AttaformErrorCode = {
|
|
9
9
|
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
@@ -78,6 +78,11 @@ 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
|
+
|
|
81
86
|
function isGateOpen(field, formMeta) {
|
|
82
87
|
return formMeta.submissionAttempts > 0 || field.blurredAfterInteraction === true;
|
|
83
88
|
}
|
|
@@ -100,7 +105,10 @@ function earliestNonNull(a, b) {
|
|
|
100
105
|
}
|
|
101
106
|
const DEFAULT_TIMINGS = { showDelay: 120, minVisible: 120 };
|
|
102
107
|
const FOCUS_OUT_GRACE = 16;
|
|
103
|
-
const defaultFamily =
|
|
108
|
+
const defaultFamily = crossCopyState(
|
|
109
|
+
/* @__PURE__ */ Symbol.for("attaform:default-display-state-family"),
|
|
110
|
+
() => /* @__PURE__ */ new WeakSet()
|
|
111
|
+
);
|
|
104
112
|
function isDefaultDisplayState(fn) {
|
|
105
113
|
return defaultFamily.has(fn);
|
|
106
114
|
}
|
|
@@ -187,6 +195,17 @@ function humanize(segment) {
|
|
|
187
195
|
}
|
|
188
196
|
|
|
189
197
|
const NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
198
|
+
function mapKeyForSegment(map, segment, declared) {
|
|
199
|
+
if (map.has(segment)) return segment;
|
|
200
|
+
if (typeof segment !== "number") return segment;
|
|
201
|
+
const asString = String(segment);
|
|
202
|
+
if (map.has(asString)) return asString;
|
|
203
|
+
return declared === "string" ? asString : segment;
|
|
204
|
+
}
|
|
205
|
+
function isRebuildableContainer(root, segment) {
|
|
206
|
+
if (root === null || root === void 0 || typeof root !== "object") return true;
|
|
207
|
+
return typeof segment === "number" ? Array.isArray(root) : isPlainRecord(root);
|
|
208
|
+
}
|
|
190
209
|
function descendStep(value, segment) {
|
|
191
210
|
if (value === null || value === void 0) return NOT_FOUND;
|
|
192
211
|
if (typeof value !== "object") return NOT_FOUND;
|
|
@@ -195,6 +214,11 @@ function descendStep(value, segment) {
|
|
|
195
214
|
if (!(segment in value)) return NOT_FOUND;
|
|
196
215
|
return value[segment];
|
|
197
216
|
}
|
|
217
|
+
if (value instanceof Map) {
|
|
218
|
+
const key2 = mapKeyForSegment(value, segment);
|
|
219
|
+
if (!value.has(key2)) return NOT_FOUND;
|
|
220
|
+
return value.get(key2);
|
|
221
|
+
}
|
|
198
222
|
const record = value;
|
|
199
223
|
const key = typeof segment === "number" ? String(segment) : segment;
|
|
200
224
|
if (isShadowedKey(key)) {
|
|
@@ -227,11 +251,14 @@ function hasAtPath(root, path) {
|
|
|
227
251
|
if (current === null || current === void 0) return false;
|
|
228
252
|
if (typeof current !== "object") return false;
|
|
229
253
|
if (Array.isArray(current)) {
|
|
230
|
-
return typeof last === "number" && last
|
|
254
|
+
return typeof last === "number" && consumerHas(current, last);
|
|
255
|
+
}
|
|
256
|
+
if (current instanceof Map) {
|
|
257
|
+
return current.has(mapKeyForSegment(current, last));
|
|
231
258
|
}
|
|
232
259
|
const key = typeof last === "number" ? String(last) : last;
|
|
233
260
|
if (isShadowedKey(key)) return safeOwnHas(current, key);
|
|
234
|
-
return key
|
|
261
|
+
return consumerHas(current, key);
|
|
235
262
|
}
|
|
236
263
|
function isPlainRecord(value) {
|
|
237
264
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -246,6 +273,13 @@ function setAtPathOffset(root, path, value, offset) {
|
|
|
246
273
|
if (offset >= path.length) return value;
|
|
247
274
|
const head = path[offset];
|
|
248
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;
|
|
249
283
|
if (typeof head === "number") {
|
|
250
284
|
const arr = Array.isArray(root) ? [...root] : [];
|
|
251
285
|
while (arr.length <= head) arr.push(void 0);
|
|
@@ -259,9 +293,17 @@ function setAtPathOffset(root, path, value, offset) {
|
|
|
259
293
|
const NO_IN_PLACE = { applied: false };
|
|
260
294
|
function tryInPlaceLeafWrite(root, path, value) {
|
|
261
295
|
if (path.length === 0) return NO_IN_PLACE;
|
|
296
|
+
try {
|
|
297
|
+
return descendAndWrite(root, path, value);
|
|
298
|
+
} catch {
|
|
299
|
+
return NO_IN_PLACE;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
function descendAndWrite(root, path, value) {
|
|
262
303
|
let node = root;
|
|
263
304
|
for (let i = 0; i < path.length; i++) {
|
|
264
305
|
const seg = path[i];
|
|
306
|
+
if (node instanceof Map) return NO_IN_PLACE;
|
|
265
307
|
if (Array.isArray(node)) {
|
|
266
308
|
if (typeof seg !== "number" || seg < 0 || seg >= node.length) return NO_IN_PLACE;
|
|
267
309
|
} else if (isPlainRecord(node)) {
|
|
@@ -296,17 +338,40 @@ function mergeStructuralImpl(schema, scratch, consumer, defaultValue) {
|
|
|
296
338
|
if (Array.isArray(consumer)) {
|
|
297
339
|
return mergeStructuralArray(schema, scratch, consumer);
|
|
298
340
|
}
|
|
341
|
+
if (consumer instanceof Map) {
|
|
342
|
+
return mergeStructuralMap(schema, scratch, consumer);
|
|
343
|
+
}
|
|
299
344
|
if (isPlainRecord(consumer)) {
|
|
300
345
|
if (!isPlainRecord(defaultValue)) {
|
|
301
346
|
return consumer;
|
|
302
347
|
}
|
|
303
|
-
const out =
|
|
348
|
+
const out = spreadConsumerRecord(consumer);
|
|
304
349
|
const filledAny = fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out);
|
|
305
350
|
const recursedAny = recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out);
|
|
306
351
|
return filledAny || recursedAny ? out : consumer;
|
|
307
352
|
}
|
|
308
353
|
return consumer;
|
|
309
354
|
}
|
|
355
|
+
function mergeStructuralMap(schema, scratch, consumer) {
|
|
356
|
+
if (consumer.size === 0) return consumer;
|
|
357
|
+
let entryDefault;
|
|
358
|
+
let entryDefaultRead = false;
|
|
359
|
+
let out = null;
|
|
360
|
+
for (const [key, entry] of consumer) {
|
|
361
|
+
if (typeof key !== "string" && typeof key !== "number") continue;
|
|
362
|
+
scratch.push(key);
|
|
363
|
+
if (!entryDefaultRead) {
|
|
364
|
+
entryDefault = schema.getDefaultAtPath(scratch);
|
|
365
|
+
entryDefaultRead = true;
|
|
366
|
+
}
|
|
367
|
+
const merged = mergeStructuralImpl(schema, scratch, entry, entryDefault);
|
|
368
|
+
scratch.pop();
|
|
369
|
+
if (merged === entry) continue;
|
|
370
|
+
out ?? (out = new Map(consumer));
|
|
371
|
+
out.set(key, merged);
|
|
372
|
+
}
|
|
373
|
+
return out ?? consumer;
|
|
374
|
+
}
|
|
310
375
|
function mergeStructuralArray(schema, scratch, consumer) {
|
|
311
376
|
const shape = schema.arrayShapeAtPath(scratch);
|
|
312
377
|
const isTuple = typeof shape === "number";
|
|
@@ -314,7 +379,7 @@ function mergeStructuralArray(schema, scratch, consumer) {
|
|
|
314
379
|
let cachedElementDefault;
|
|
315
380
|
let cachedElementDefaultRead = false;
|
|
316
381
|
let mutated = targetLen > consumer.length;
|
|
317
|
-
const out = consumer
|
|
382
|
+
const out = copyConsumerArray(consumer);
|
|
318
383
|
while (out.length < targetLen) out.push(void 0);
|
|
319
384
|
for (let i = 0; i < targetLen; i++) {
|
|
320
385
|
scratch.push(i);
|
|
@@ -328,7 +393,7 @@ function mergeStructuralArray(schema, scratch, consumer) {
|
|
|
328
393
|
}
|
|
329
394
|
elemDefault = cachedElementDefault;
|
|
330
395
|
}
|
|
331
|
-
const consumerElem = i < consumer.length ? consumer
|
|
396
|
+
const consumerElem = i < consumer.length ? readConsumerIndex(consumer, i) : void 0;
|
|
332
397
|
const merged = mergeStructuralImpl(schema, scratch, consumerElem, elemDefault);
|
|
333
398
|
scratch.pop();
|
|
334
399
|
if (merged !== consumerElem) {
|
|
@@ -356,7 +421,7 @@ function fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out
|
|
|
356
421
|
}
|
|
357
422
|
function recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out) {
|
|
358
423
|
let mutated = false;
|
|
359
|
-
for (const key of
|
|
424
|
+
for (const key of consumerKeys(consumer)) {
|
|
360
425
|
const cVal = safeOwnRead(consumer, key);
|
|
361
426
|
if (cVal === void 0) continue;
|
|
362
427
|
scratch.push(key);
|
|
@@ -377,6 +442,21 @@ function setAtPathWithSchemaFillImpl(root, schema, fullPath, value, startIdx) {
|
|
|
377
442
|
if (startIdx >= fullPath.length) return value;
|
|
378
443
|
const head = fullPath[startIdx];
|
|
379
444
|
const isLeafStep = startIdx === fullPath.length - 1;
|
|
445
|
+
if (root instanceof Map) {
|
|
446
|
+
const next = new Map(root);
|
|
447
|
+
const key = mapKeyForSegment(root, head, schema.entryKeyKindAtPath(fullPath.slice(0, startIdx)));
|
|
448
|
+
if (isLeafStep) {
|
|
449
|
+
next.set(key, value);
|
|
450
|
+
return next;
|
|
451
|
+
}
|
|
452
|
+
let childRoot2 = next.get(key);
|
|
453
|
+
if (childRoot2 === void 0 || childRoot2 !== null && typeof childRoot2 !== "object") {
|
|
454
|
+
childRoot2 = schema.getDefaultAtPath(fullPath.slice(0, startIdx + 1));
|
|
455
|
+
}
|
|
456
|
+
next.set(key, setAtPathWithSchemaFillImpl(childRoot2, schema, fullPath, value, startIdx + 1));
|
|
457
|
+
return next;
|
|
458
|
+
}
|
|
459
|
+
if (!isRebuildableContainer(root, head)) return root;
|
|
380
460
|
if (typeof head === "number") {
|
|
381
461
|
const arr = Array.isArray(root) ? [...root] : [];
|
|
382
462
|
const prefix = fullPath.slice(0, startIdx);
|
|
@@ -443,9 +523,10 @@ function isUnderStubAncestor(state, segments) {
|
|
|
443
523
|
}
|
|
444
524
|
return false;
|
|
445
525
|
}
|
|
446
|
-
function buildFieldStateAccessor(state, formInstanceId, getFormMetaBase, options) {
|
|
526
|
+
function buildFieldStateAccessor(state, formInstanceId, getFormMetaBase, sweep, options) {
|
|
447
527
|
const cache = /* @__PURE__ */ new Map();
|
|
448
528
|
const predicate = options?.getDisplayState;
|
|
529
|
+
sweep.onEvict((key) => cache.delete(key));
|
|
449
530
|
return function getFieldState(pathInput) {
|
|
450
531
|
const { segments, key } = canonicalizePath(pathInput);
|
|
451
532
|
const cached = cache.get(key);
|
|
@@ -454,6 +535,7 @@ function buildFieldStateAccessor(state, formInstanceId, getFormMetaBase, options
|
|
|
454
535
|
() => state.schema.isLeafAtPath(segments) ? buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBase, predicate) : buildContainerFieldState(state, segments, key, formInstanceId, getFormMetaBase, predicate)
|
|
455
536
|
);
|
|
456
537
|
cache.set(key, c);
|
|
538
|
+
sweep.track(segments, key);
|
|
457
539
|
return c;
|
|
458
540
|
};
|
|
459
541
|
}
|
|
@@ -543,7 +625,7 @@ function buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBa
|
|
|
543
625
|
function visitActiveLeafPaths(value, base, visit) {
|
|
544
626
|
if (Array.isArray(value)) {
|
|
545
627
|
for (let i = 0; i < value.length; i++) {
|
|
546
|
-
const child = value
|
|
628
|
+
const child = readConsumerIndex(value, i);
|
|
547
629
|
if (Array.isArray(child) || isPlainRecord(child)) {
|
|
548
630
|
visitActiveLeafPaths(child, [...base, i], visit);
|
|
549
631
|
} else {
|
|
@@ -553,8 +635,8 @@ function visitActiveLeafPaths(value, base, visit) {
|
|
|
553
635
|
return;
|
|
554
636
|
}
|
|
555
637
|
if (isPlainRecord(value)) {
|
|
556
|
-
for (const k of
|
|
557
|
-
const child = value
|
|
638
|
+
for (const k of consumerKeys(value)) {
|
|
639
|
+
const child = readConsumerProp(value, k);
|
|
558
640
|
if (Array.isArray(child) || isPlainRecord(child)) {
|
|
559
641
|
visitActiveLeafPaths(child, [...base, k], visit);
|
|
560
642
|
} else {
|
|
@@ -796,6 +878,10 @@ function liveKeysAtPath(state, segments) {
|
|
|
796
878
|
for (let i = 0; i < value.length; i += 1) keys[i] = String(i);
|
|
797
879
|
return keys;
|
|
798
880
|
}
|
|
881
|
+
if (value instanceof Map) {
|
|
882
|
+
return mapSegmentKeys(value)?.map(String) ?? [];
|
|
883
|
+
}
|
|
884
|
+
if (value instanceof Set) return [];
|
|
799
885
|
if (typeof value === "object") return Object.keys(value);
|
|
800
886
|
return [];
|
|
801
887
|
}
|
|
@@ -806,6 +892,12 @@ function liveContainerHasKey(state, segments, key) {
|
|
|
806
892
|
const index = Number(key);
|
|
807
893
|
return Number.isInteger(index) && index >= 0 && index < value.length && String(index) === key;
|
|
808
894
|
}
|
|
895
|
+
if (value instanceof Map) {
|
|
896
|
+
if (value.has(key)) return true;
|
|
897
|
+
const index = Number(key);
|
|
898
|
+
return Number.isInteger(index) && index >= 0 && String(index) === key && value.has(index);
|
|
899
|
+
}
|
|
900
|
+
if (value instanceof Set) return false;
|
|
809
901
|
return Object.hasOwn(value, key);
|
|
810
902
|
}
|
|
811
903
|
function isArrayPath(state, segments) {
|
|
@@ -829,6 +921,7 @@ function makeReadonlyCoercion(snapshot) {
|
|
|
829
921
|
}
|
|
830
922
|
|
|
831
923
|
const INTEGER_SEGMENT = /^(?:0|[1-9]\d*)$/;
|
|
924
|
+
const RELEASED = /* @__PURE__ */ Symbol();
|
|
832
925
|
const EMPTY_DESCENT = Object.freeze({});
|
|
833
926
|
function keyToSegment(key) {
|
|
834
927
|
return INTEGER_SEGMENT.test(key) ? Number(key) : key;
|
|
@@ -858,12 +951,18 @@ function callableInvokeShim(method, surface, getDescent) {
|
|
|
858
951
|
function buildTree(spec) {
|
|
859
952
|
const containerCache = /* @__PURE__ */ new Map();
|
|
860
953
|
const existsCache = /* @__PURE__ */ new Map();
|
|
954
|
+
spec.sweep.onEvict((key) => {
|
|
955
|
+
containerCache.delete(`${key}+A`);
|
|
956
|
+
containerCache.delete(`${key}+O`);
|
|
957
|
+
existsCache.delete(key);
|
|
958
|
+
});
|
|
861
959
|
function schemaHasPath(segs) {
|
|
862
960
|
const cacheKey = JSON.stringify(segs);
|
|
863
961
|
const cached = existsCache.get(cacheKey);
|
|
864
962
|
if (cached !== void 0) return cached;
|
|
865
963
|
const result = spec.schema.getSlimPrimitiveTypesAtPath(segs).size > 0;
|
|
866
964
|
existsCache.set(cacheKey, result);
|
|
965
|
+
spec.sweep.track(segs, cacheKey);
|
|
867
966
|
return result;
|
|
868
967
|
}
|
|
869
968
|
function descend(segs) {
|
|
@@ -873,7 +972,8 @@ function buildTree(spec) {
|
|
|
873
972
|
}
|
|
874
973
|
function containerAt(segments) {
|
|
875
974
|
const isArrayLike = spec.isArrayAt(segments);
|
|
876
|
-
const
|
|
975
|
+
const pathKey = JSON.stringify(segments);
|
|
976
|
+
const cacheKey = `${pathKey}+${isArrayLike ? "A" : "O"}`;
|
|
877
977
|
const existing = containerCache.get(cacheKey);
|
|
878
978
|
if (existing !== void 0) return existing;
|
|
879
979
|
const isFixedObject = spec.schema.isFixedObjectAtPath(segments);
|
|
@@ -963,12 +1063,14 @@ function buildTree(spec) {
|
|
|
963
1063
|
}
|
|
964
1064
|
});
|
|
965
1065
|
containerCache.set(cacheKey, proxy);
|
|
1066
|
+
spec.sweep.track(segments, pathKey);
|
|
966
1067
|
return proxy;
|
|
967
1068
|
}
|
|
968
1069
|
return containerAt([]);
|
|
969
1070
|
}
|
|
970
|
-
function buildErrorsSurface(state) {
|
|
1071
|
+
function buildErrorsSurface(state, sweep) {
|
|
971
1072
|
const treeCache = /* @__PURE__ */ new Map();
|
|
1073
|
+
sweep.onEvict((key) => treeCache.delete(key));
|
|
972
1074
|
const materialize = (segments) => {
|
|
973
1075
|
const cacheKey = JSON.stringify(segments);
|
|
974
1076
|
let tree = treeCache.get(cacheKey);
|
|
@@ -976,6 +1078,7 @@ function buildErrorsSurface(state) {
|
|
|
976
1078
|
const frozen = [...segments];
|
|
977
1079
|
tree = computed(() => materializeErrors(state, frozen));
|
|
978
1080
|
treeCache.set(cacheKey, tree);
|
|
1081
|
+
sweep.track(segments, cacheKey);
|
|
979
1082
|
}
|
|
980
1083
|
return tree.value;
|
|
981
1084
|
};
|
|
@@ -1021,7 +1124,8 @@ function buildErrorsSurface(state) {
|
|
|
1021
1124
|
// aggregate — the same helper `meta.errors` reads, so the surfaces
|
|
1022
1125
|
// never drift.
|
|
1023
1126
|
call: (path) => aggregateErrorsAt(state, path),
|
|
1024
|
-
surface: "form.errors"
|
|
1127
|
+
surface: "form.errors",
|
|
1128
|
+
sweep
|
|
1025
1129
|
});
|
|
1026
1130
|
}
|
|
1027
1131
|
function errorAwareContainerKeys(state, segments) {
|
|
@@ -1140,7 +1244,7 @@ const FIELD_STATE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1140
1244
|
"placeholder",
|
|
1141
1245
|
"meta"
|
|
1142
1246
|
]);
|
|
1143
|
-
function buildFieldsSurface(state, getFieldStateAt) {
|
|
1247
|
+
function buildFieldsSurface(state, getFieldStateAt, sweep) {
|
|
1144
1248
|
const snapshotAt = (segments) => {
|
|
1145
1249
|
const view = getFieldStateAt(segments).value;
|
|
1146
1250
|
const snapshot = {};
|
|
@@ -1148,6 +1252,7 @@ function buildFieldsSurface(state, getFieldStateAt) {
|
|
|
1148
1252
|
return snapshot;
|
|
1149
1253
|
};
|
|
1150
1254
|
const viewCache = /* @__PURE__ */ new Map();
|
|
1255
|
+
sweep.onEvict((key) => viewCache.delete(key));
|
|
1151
1256
|
function viewAt(segments) {
|
|
1152
1257
|
const cacheKey = JSON.stringify(segments);
|
|
1153
1258
|
const existing = viewCache.get(cacheKey);
|
|
@@ -1199,6 +1304,7 @@ function buildFieldsSurface(state, getFieldStateAt) {
|
|
|
1199
1304
|
}
|
|
1200
1305
|
});
|
|
1201
1306
|
viewCache.set(cacheKey, proxy);
|
|
1307
|
+
sweep.track(segments, cacheKey);
|
|
1202
1308
|
return proxy;
|
|
1203
1309
|
}
|
|
1204
1310
|
return buildTree({
|
|
@@ -1213,7 +1319,8 @@ function buildFieldsSurface(state, getFieldStateAt) {
|
|
|
1213
1319
|
// container's rollup); a path the schema doesn't have is a typo and
|
|
1214
1320
|
// reads `undefined`. The root (`fields()`) is always declared.
|
|
1215
1321
|
call: (path) => state.schema.getSlimPrimitiveTypesAtPath(path).size > 0 ? viewAt(path) : void 0,
|
|
1216
|
-
surface: "form.fields"
|
|
1322
|
+
surface: "form.fields",
|
|
1323
|
+
sweep
|
|
1217
1324
|
});
|
|
1218
1325
|
}
|
|
1219
1326
|
function materializeFields(state, containerSegments, snapshotAt) {
|
|
@@ -1247,18 +1354,34 @@ function materializeFormValue(node) {
|
|
|
1247
1354
|
}
|
|
1248
1355
|
return out;
|
|
1249
1356
|
}
|
|
1250
|
-
function buildValuesSurface(form) {
|
|
1357
|
+
function buildValuesSurface(form, onFormChange) {
|
|
1251
1358
|
const inner = computed(() => readonly(form.value));
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1359
|
+
let held = null;
|
|
1360
|
+
const snapshot = computed(() => {
|
|
1361
|
+
const box = { value: materializeFormValue(inner.value) };
|
|
1362
|
+
held = box;
|
|
1363
|
+
return box;
|
|
1364
|
+
});
|
|
1365
|
+
onFormChange(() => {
|
|
1366
|
+
if (held === null) return;
|
|
1367
|
+
held.value = RELEASED;
|
|
1368
|
+
held = null;
|
|
1369
|
+
});
|
|
1370
|
+
const readSnapshot = () => {
|
|
1371
|
+
const box = snapshot.value;
|
|
1372
|
+
return box.value === RELEASED ? materializeFormValue(inner.value) : box.value;
|
|
1373
|
+
};
|
|
1374
|
+
const { toString, valueOf, toJSON, toPrimitive } = makeReadonlyCoercion(() => readSnapshot());
|
|
1255
1375
|
const target = (() => {
|
|
1256
1376
|
});
|
|
1257
1377
|
return new Proxy(target, {
|
|
1258
1378
|
apply(_, __, args) {
|
|
1259
1379
|
const arg = args[0];
|
|
1260
|
-
if (arg === void 0) return
|
|
1261
|
-
|
|
1380
|
+
if (arg === void 0) return readSnapshot();
|
|
1381
|
+
const segments = canonicalizePath(arg).segments;
|
|
1382
|
+
const node = getAtPath(inner.value, segments);
|
|
1383
|
+
if (node === null || typeof node !== "object") return node;
|
|
1384
|
+
return getAtPath(readSnapshot(), segments);
|
|
1262
1385
|
},
|
|
1263
1386
|
get(_, key) {
|
|
1264
1387
|
if (typeof key === "symbol") {
|
|
@@ -1540,9 +1663,12 @@ function cloneVariantSnapshot(value) {
|
|
|
1540
1663
|
for (let i = 0; i < raw.length; i++) out2[i] = cloneVariantSnapshot(raw[i]);
|
|
1541
1664
|
return out2;
|
|
1542
1665
|
}
|
|
1666
|
+
if (!isPlainRecord(raw)) return raw;
|
|
1543
1667
|
const src = raw;
|
|
1544
1668
|
const out = {};
|
|
1545
|
-
for (const k of
|
|
1669
|
+
for (const k of consumerKeys(src)) {
|
|
1670
|
+
safeAssign(out, k, cloneVariantSnapshot(readConsumerProp(src, k)));
|
|
1671
|
+
}
|
|
1546
1672
|
return out;
|
|
1547
1673
|
}
|
|
1548
1674
|
function createArrayBookkeeping(deps) {
|
|
@@ -1690,6 +1816,45 @@ function buildFieldArrayApi(state) {
|
|
|
1690
1816
|
};
|
|
1691
1817
|
}
|
|
1692
1818
|
|
|
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
|
+
|
|
1693
1858
|
function isErrorInputLike(value) {
|
|
1694
1859
|
if (value instanceof Error) return true;
|
|
1695
1860
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -1999,15 +2164,16 @@ function walk(schema, store, path, value) {
|
|
|
1999
2164
|
if (!accepted.has(kind)) {
|
|
2000
2165
|
return false;
|
|
2001
2166
|
}
|
|
2167
|
+
if (schema.isOpaqueLeafAtPath(path)) return true;
|
|
2002
2168
|
if (Array.isArray(value)) {
|
|
2003
2169
|
for (let i = 0; i < value.length; i++) {
|
|
2004
|
-
if (!walk(schema, store, [...path, i], value
|
|
2170
|
+
if (!walk(schema, store, [...path, i], readConsumerIndex(value, i))) return false;
|
|
2005
2171
|
}
|
|
2006
2172
|
return true;
|
|
2007
2173
|
}
|
|
2008
2174
|
if (isPlainRecord(value)) {
|
|
2009
|
-
for (const key of
|
|
2010
|
-
if (!walk(schema, store, [...path, key], value
|
|
2175
|
+
for (const key of consumerKeys(value)) {
|
|
2176
|
+
if (!walk(schema, store, [...path, key], readConsumerProp(value, key))) {
|
|
2011
2177
|
return false;
|
|
2012
2178
|
}
|
|
2013
2179
|
}
|
|
@@ -2062,19 +2228,26 @@ function indexRules(rules) {
|
|
|
2062
2228
|
}
|
|
2063
2229
|
return idx;
|
|
2064
2230
|
}
|
|
2231
|
+
function memberSlimTypes(schema, segments, accepted) {
|
|
2232
|
+
if (accepted.has("array")) return schema.getSlimPrimitiveTypesAtPath([...segments, 0]);
|
|
2233
|
+
if (accepted.has("set")) {
|
|
2234
|
+
return schema.getSlimPrimitiveTypesAtPath([...segments, SET_MEMBER_SEGMENT]);
|
|
2235
|
+
}
|
|
2236
|
+
return void 0;
|
|
2237
|
+
}
|
|
2065
2238
|
function buildCoerceFn(schema, segments, index) {
|
|
2066
2239
|
if (index === EMPTY_INDEX) return IDENTITY;
|
|
2067
2240
|
if (index.size === 0) return IDENTITY;
|
|
2068
2241
|
const accepted = schema.getSlimPrimitiveTypesAtPath(segments);
|
|
2069
|
-
const elementAccepted =
|
|
2242
|
+
const elementAccepted = memberSlimTypes(schema, segments, accepted);
|
|
2070
2243
|
return (value) => coerceValue(value, accepted, elementAccepted, index);
|
|
2071
2244
|
}
|
|
2072
2245
|
function buildElementCoerceFn(schema, segments, index) {
|
|
2073
2246
|
if (index === EMPTY_INDEX) return void 0;
|
|
2074
2247
|
if (index.size === 0) return void 0;
|
|
2075
2248
|
const accepted = schema.getSlimPrimitiveTypesAtPath(segments);
|
|
2076
|
-
|
|
2077
|
-
|
|
2249
|
+
const elementAccepted = memberSlimTypes(schema, segments, accepted);
|
|
2250
|
+
if (elementAccepted === void 0) return void 0;
|
|
2078
2251
|
return (value) => coerceScalar(value, elementAccepted, index);
|
|
2079
2252
|
}
|
|
2080
2253
|
function pickScalarTarget(accepted) {
|
|
@@ -2317,8 +2490,8 @@ function walkUnsetSentinels(values, schema) {
|
|
|
2317
2490
|
const cleaned = walkCore(values, [], schema, paths, true);
|
|
2318
2491
|
return { cleanedValues: cleaned, paths };
|
|
2319
2492
|
}
|
|
2320
|
-
function
|
|
2321
|
-
return value
|
|
2493
|
+
function isRecursable(value) {
|
|
2494
|
+
return Array.isArray(value) || isPlainRecord(value);
|
|
2322
2495
|
}
|
|
2323
2496
|
function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
2324
2497
|
if (isUnset(input)) {
|
|
@@ -2332,20 +2505,21 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
|
2332
2505
|
return input;
|
|
2333
2506
|
}
|
|
2334
2507
|
if (input === null) return null;
|
|
2335
|
-
if (
|
|
2508
|
+
if (!isRecursable(input)) return input;
|
|
2336
2509
|
if (Array.isArray(input)) {
|
|
2337
2510
|
const out = new Array(input.length);
|
|
2338
2511
|
let mutated = false;
|
|
2339
2512
|
for (let i = 0; i < input.length; i++) {
|
|
2340
|
-
const
|
|
2513
|
+
const original = readConsumerIndex(input, i);
|
|
2514
|
+
const walked = walkCore(original, [...segments, i], schema, paths, synthesizeSchemaKeys);
|
|
2341
2515
|
out[i] = walked;
|
|
2342
|
-
if (walked !==
|
|
2516
|
+
if (walked !== original) mutated = true;
|
|
2343
2517
|
}
|
|
2344
2518
|
return mutated ? out : input;
|
|
2345
2519
|
}
|
|
2346
2520
|
if (typeof input === "object") {
|
|
2347
2521
|
const obj = input;
|
|
2348
|
-
const inputKeys =
|
|
2522
|
+
const inputKeys = consumerKeys(obj);
|
|
2349
2523
|
let keys = inputKeys;
|
|
2350
2524
|
let mutated = false;
|
|
2351
2525
|
let inputKeysSet = null;
|
|
@@ -2353,7 +2527,7 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
|
2353
2527
|
inputKeysSet = new Set(inputKeys);
|
|
2354
2528
|
const allKeys = new Set(inputKeys);
|
|
2355
2529
|
const slim = schema.getDefaultAtPath(segments);
|
|
2356
|
-
if (
|
|
2530
|
+
if (isPlainRecord(slim)) {
|
|
2357
2531
|
for (const k of Object.keys(slim)) allKeys.add(k);
|
|
2358
2532
|
}
|
|
2359
2533
|
keys = allKeys;
|
|
@@ -2361,7 +2535,7 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
|
2361
2535
|
}
|
|
2362
2536
|
const out = {};
|
|
2363
2537
|
for (const key of keys) {
|
|
2364
|
-
const orig = obj
|
|
2538
|
+
const orig = readConsumerProp(obj, key);
|
|
2365
2539
|
if (synthesizeSchemaKeys && orig === void 0 && inputKeysSet?.has(key) === true) {
|
|
2366
2540
|
safeAssign(out, key, void 0);
|
|
2367
2541
|
mutated = true;
|
|
@@ -2382,22 +2556,12 @@ function walkUnspecified(slim, segments, paths) {
|
|
|
2382
2556
|
}
|
|
2383
2557
|
return slim;
|
|
2384
2558
|
}
|
|
2385
|
-
if (
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
if (slim !== null && typeof slim === "object") {
|
|
2390
|
-
const out = {};
|
|
2391
|
-
for (const key of Object.keys(slim)) {
|
|
2392
|
-
safeAssign(
|
|
2393
|
-
out,
|
|
2394
|
-
key,
|
|
2395
|
-
walkUnspecified(slim[key], [...segments, key], paths)
|
|
2396
|
-
);
|
|
2397
|
-
}
|
|
2398
|
-
return out;
|
|
2559
|
+
if (!isPlainRecord(slim)) return slim;
|
|
2560
|
+
const out = {};
|
|
2561
|
+
for (const key of Object.keys(slim)) {
|
|
2562
|
+
safeAssign(out, key, walkUnspecified(slim[key], [...segments, key], paths));
|
|
2399
2563
|
}
|
|
2400
|
-
return
|
|
2564
|
+
return out;
|
|
2401
2565
|
}
|
|
2402
2566
|
function substituteUnsetSentinels(value, prefix, schema) {
|
|
2403
2567
|
const paths = [];
|
|
@@ -2433,11 +2597,11 @@ function expandUnsetAt(segments, schema, paths) {
|
|
|
2433
2597
|
paths.push(canonicalizePath(segments).key);
|
|
2434
2598
|
return slim;
|
|
2435
2599
|
}
|
|
2436
|
-
if (
|
|
2600
|
+
if (Array.isArray(slim)) return slim;
|
|
2601
|
+
if (!isPlainRecord(slim)) {
|
|
2437
2602
|
paths.push(canonicalizePath(segments).key);
|
|
2438
2603
|
return slim;
|
|
2439
2604
|
}
|
|
2440
|
-
if (Array.isArray(slim)) return slim;
|
|
2441
2605
|
const result = {};
|
|
2442
2606
|
for (const key of Object.keys(slim)) {
|
|
2443
2607
|
result[key] = expandUnsetAt([...segments, key], schema, paths);
|
|
@@ -2447,14 +2611,14 @@ function expandUnsetAt(segments, schema, paths) {
|
|
|
2447
2611
|
function walkAuthoredFromConstraints(value, prefix, out) {
|
|
2448
2612
|
if (prefix.length > 0) out.add(canonicalizePath(prefix).key);
|
|
2449
2613
|
if (isPlainRecord(value)) {
|
|
2450
|
-
for (const k of
|
|
2451
|
-
walkAuthoredFromConstraints(value
|
|
2614
|
+
for (const k of consumerKeys(value)) {
|
|
2615
|
+
walkAuthoredFromConstraints(readConsumerProp(value, k), [...prefix, k], out);
|
|
2452
2616
|
}
|
|
2453
2617
|
return;
|
|
2454
2618
|
}
|
|
2455
2619
|
if (Array.isArray(value)) {
|
|
2456
2620
|
for (let i = 0; i < value.length; i++) {
|
|
2457
|
-
walkAuthoredFromConstraints(value
|
|
2621
|
+
walkAuthoredFromConstraints(readConsumerIndex(value, i), [...prefix, i], out);
|
|
2458
2622
|
}
|
|
2459
2623
|
}
|
|
2460
2624
|
}
|
|
@@ -2534,10 +2698,12 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2534
2698
|
return metaBase;
|
|
2535
2699
|
};
|
|
2536
2700
|
const fieldStateAccessorOptions = options.getDisplayState !== void 0 ? { getDisplayState: options.getDisplayState } : void 0;
|
|
2701
|
+
const pathSweep = createDynamicPathSweep(state);
|
|
2537
2702
|
const getRootFieldStateAt = buildFieldStateAccessor(
|
|
2538
2703
|
state,
|
|
2539
2704
|
formInstanceId,
|
|
2540
2705
|
getFormMetaBase,
|
|
2706
|
+
pathSweep,
|
|
2541
2707
|
fieldStateAccessorOptions
|
|
2542
2708
|
);
|
|
2543
2709
|
const getDisplayStateAt = (segments) => getRootFieldStateAt(segments).value.displayState;
|
|
@@ -2564,6 +2730,10 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2564
2730
|
const segments = canonicalizePath(pathInput).segments;
|
|
2565
2731
|
return computed(() => getAtPath(state.form.value, segments));
|
|
2566
2732
|
}
|
|
2733
|
+
function pathStoresFunctions(segments) {
|
|
2734
|
+
if (state.schema.isOpaqueLeafAtPath(segments)) return false;
|
|
2735
|
+
return state.schema.getSlimPrimitiveTypesAtPath(segments).has("function");
|
|
2736
|
+
}
|
|
2567
2737
|
function setValueImpl(pathOrValue, maybeValue) {
|
|
2568
2738
|
const argc = arguments.length;
|
|
2569
2739
|
const isPathForm = argc >= 2 && (typeof pathOrValue === "string" || Array.isArray(pathOrValue));
|
|
@@ -2616,7 +2786,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2616
2786
|
};
|
|
2617
2787
|
if (isUnset(maybeValue)) return writeUnsetAt();
|
|
2618
2788
|
let resolvedValue;
|
|
2619
|
-
if (typeof maybeValue === "function") {
|
|
2789
|
+
if (typeof maybeValue === "function" && !pathStoresFunctions(segments)) {
|
|
2620
2790
|
const current = state.getValueAtPath(segments);
|
|
2621
2791
|
const prev = current === void 0 ? state.schema.getDefaultAtPath(segments) : current;
|
|
2622
2792
|
resolvedValue = maybeValue(prev);
|
|
@@ -2634,7 +2804,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2634
2804
|
reMarkBlanksAfterSubstitution(walked.paths);
|
|
2635
2805
|
return true;
|
|
2636
2806
|
}
|
|
2637
|
-
const errorsProxy = buildErrorsSurface(state);
|
|
2807
|
+
const errorsProxy = buildErrorsSurface(state, pathSweep);
|
|
2638
2808
|
function flattenUserErrors() {
|
|
2639
2809
|
const all = [];
|
|
2640
2810
|
for (const cell of state.errorCells.values()) all.push(...cell.user);
|
|
@@ -2733,8 +2903,9 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2733
2903
|
if (nextDefaultValues === void 0) {
|
|
2734
2904
|
state.reset();
|
|
2735
2905
|
} else {
|
|
2736
|
-
const walked =
|
|
2906
|
+
const walked = substituteUnsetSentinels(
|
|
2737
2907
|
nextDefaultValues,
|
|
2908
|
+
[],
|
|
2738
2909
|
state.schema
|
|
2739
2910
|
);
|
|
2740
2911
|
state.reset(walked.cleanedValues);
|
|
@@ -2808,8 +2979,8 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2808
2979
|
};
|
|
2809
2980
|
return Object.freeze(view);
|
|
2810
2981
|
});
|
|
2811
|
-
const valuesProxy = buildValuesSurface(state.form);
|
|
2812
|
-
const fieldStateProxy = buildFieldsSurface(state, getRootFieldStateAt);
|
|
2982
|
+
const valuesProxy = buildValuesSurface(state.form, state.onFormChange);
|
|
2983
|
+
const fieldStateProxy = buildFieldsSurface(state, getRootFieldStateAt, pathSweep);
|
|
2813
2984
|
const needsLazyGate = state.defaultValuesFactory.value !== void 0 || state.hasSsrPrefetch;
|
|
2814
2985
|
function gated(fn) {
|
|
2815
2986
|
if (!needsLazyGate) return fn;
|
|
@@ -2930,6 +3101,12 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2930
3101
|
|
|
2931
3102
|
const IDLE = Object.freeze({ display: "idle" });
|
|
2932
3103
|
const MAX_DELAY = 2147483647;
|
|
3104
|
+
const PENDING_LIVENESS_MS = 250;
|
|
3105
|
+
function withLiveness(machine, now) {
|
|
3106
|
+
if (machine.display !== "pending") return machine;
|
|
3107
|
+
if (machine.reviewAt !== void 0 && Number.isFinite(machine.reviewAt)) return machine;
|
|
3108
|
+
return { ...machine, reviewAt: now + PENDING_LIVENESS_MS };
|
|
3109
|
+
}
|
|
2933
3110
|
function createDisplayEngine(ssr) {
|
|
2934
3111
|
const machines = /* @__PURE__ */ new Map();
|
|
2935
3112
|
const tick = ref(0);
|
|
@@ -2958,7 +3135,7 @@ function createDisplayEngine(ssr) {
|
|
|
2958
3135
|
return;
|
|
2959
3136
|
}
|
|
2960
3137
|
if (timer !== null && timerTarget === target) return;
|
|
2961
|
-
if (target === lastFiredTarget) {
|
|
3138
|
+
if (target === lastFiredTarget && target <= now) {
|
|
2962
3139
|
clearTimer();
|
|
2963
3140
|
return;
|
|
2964
3141
|
}
|
|
@@ -2977,8 +3154,9 @@ function createDisplayEngine(ssr) {
|
|
|
2977
3154
|
function resolve(key, ctx, reducer) {
|
|
2978
3155
|
void tick.value;
|
|
2979
3156
|
const prev = machines.get(key) ?? IDLE;
|
|
2980
|
-
const
|
|
2981
|
-
if (ssr) return
|
|
3157
|
+
const reduced = reducer(prev, ctx);
|
|
3158
|
+
if (ssr) return reduced;
|
|
3159
|
+
const machine = withLiveness(reduced, ctx.now);
|
|
2982
3160
|
const active = machine.display !== "idle" || machine.reviewAt !== void 0 && Number.isFinite(machine.reviewAt);
|
|
2983
3161
|
if (active) machines.set(key, machine);
|
|
2984
3162
|
else machines.delete(key);
|
|
@@ -3070,6 +3248,7 @@ async function runFactoryAndApply(st, factory) {
|
|
|
3070
3248
|
st.schema
|
|
3071
3249
|
);
|
|
3072
3250
|
st.applyFormReplacement(full, { hydration: true });
|
|
3251
|
+
st.adoptResolvedDefaults(value);
|
|
3073
3252
|
st.scheduleFieldValidation(
|
|
3074
3253
|
[],
|
|
3075
3254
|
true
|
|
@@ -3149,12 +3328,10 @@ function applyDuStubs(schema, data, options = {}) {
|
|
|
3149
3328
|
}
|
|
3150
3329
|
function walkDuStubs(schema, value, path, warned) {
|
|
3151
3330
|
if (value === null || value === void 0 || typeof value !== "object") return value;
|
|
3152
|
-
if (value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || typeof value === "function") {
|
|
3153
|
-
return value;
|
|
3154
|
-
}
|
|
3155
3331
|
if (Array.isArray(value)) {
|
|
3156
3332
|
return value.map((item, i) => walkDuStubs(schema, item, [...path, i]));
|
|
3157
3333
|
}
|
|
3334
|
+
if (!isPlainRecord(value)) return value;
|
|
3158
3335
|
const rec = value;
|
|
3159
3336
|
const du = schema.getUnionDiscriminatorAtPath(path);
|
|
3160
3337
|
if (du !== void 0) {
|
|
@@ -3166,8 +3343,8 @@ function walkDuStubs(schema, value, path, warned) {
|
|
|
3166
3343
|
}
|
|
3167
3344
|
}
|
|
3168
3345
|
const out = {};
|
|
3169
|
-
for (const k of
|
|
3170
|
-
safeAssign(out, k, walkDuStubs(schema, rec
|
|
3346
|
+
for (const k of consumerKeys(rec)) {
|
|
3347
|
+
safeAssign(out, k, walkDuStubs(schema, readConsumerProp(rec, k), [...path, k]));
|
|
3171
3348
|
}
|
|
3172
3349
|
return out;
|
|
3173
3350
|
}
|
|
@@ -3177,23 +3354,25 @@ function stripSymbolsDeep(value) {
|
|
|
3177
3354
|
let mutated2 = false;
|
|
3178
3355
|
const out2 = new Array(value.length);
|
|
3179
3356
|
for (let i = 0; i < value.length; i++) {
|
|
3180
|
-
const
|
|
3357
|
+
const original = readConsumerIndex(value, i);
|
|
3358
|
+
const cleaned = stripSymbolsDeep(original);
|
|
3181
3359
|
out2[i] = cleaned;
|
|
3182
|
-
if (cleaned !==
|
|
3360
|
+
if (cleaned !== original) mutated2 = true;
|
|
3183
3361
|
}
|
|
3184
3362
|
return mutated2 ? out2 : value;
|
|
3185
3363
|
}
|
|
3186
3364
|
const proto = Object.getPrototypeOf(value);
|
|
3187
3365
|
if (proto !== Object.prototype && proto !== null) return value;
|
|
3188
|
-
const symKeys =
|
|
3189
|
-
const stringKeys =
|
|
3366
|
+
const symKeys = consumerSymbolKeys(value);
|
|
3367
|
+
const stringKeys = consumerKeys(value);
|
|
3190
3368
|
let mutated = symKeys.length > 0;
|
|
3191
3369
|
const out = {};
|
|
3192
3370
|
const src = value;
|
|
3193
3371
|
for (const k of stringKeys) {
|
|
3194
|
-
const
|
|
3372
|
+
const original = readConsumerProp(src, k);
|
|
3373
|
+
const cleaned = stripSymbolsDeep(original);
|
|
3195
3374
|
out[k] = cleaned;
|
|
3196
|
-
if (cleaned !==
|
|
3375
|
+
if (cleaned !== original) mutated = true;
|
|
3197
3376
|
}
|
|
3198
3377
|
return mutated ? out : value;
|
|
3199
3378
|
}
|
|
@@ -4096,8 +4275,27 @@ function activate(st) {
|
|
|
4096
4275
|
if (factory === void 0) return Promise.resolve();
|
|
4097
4276
|
return fireFactory(st, factory);
|
|
4098
4277
|
}
|
|
4278
|
+
function adoptResolvedDefaults(st, value) {
|
|
4279
|
+
st.defaultValues = structuralSnapshot(
|
|
4280
|
+
mergeSparseHydration(
|
|
4281
|
+
st.defaultValues,
|
|
4282
|
+
value,
|
|
4283
|
+
st.schema
|
|
4284
|
+
)
|
|
4285
|
+
);
|
|
4286
|
+
seedOriginalsFromBaseline(
|
|
4287
|
+
st,
|
|
4288
|
+
computeBaselineResponse(st.schema, st.strict, st.defaultValues).data,
|
|
4289
|
+
false
|
|
4290
|
+
);
|
|
4291
|
+
}
|
|
4099
4292
|
function reset(st, nextDefaultValues) {
|
|
4100
|
-
const resetSource = nextDefaultValues
|
|
4293
|
+
const resetSource = nextDefaultValues === void 0 ? st.defaultValues : mergeSparseHydration(
|
|
4294
|
+
st.defaultValues,
|
|
4295
|
+
nextDefaultValues,
|
|
4296
|
+
st.schema
|
|
4297
|
+
);
|
|
4298
|
+
st.defaultValues = structuralSnapshot(resetSource);
|
|
4101
4299
|
const resetResponse = computeBaselineResponse(st.schema, st.strict, resetSource);
|
|
4102
4300
|
const next = resetResponse.data;
|
|
4103
4301
|
rebuildAuthoredPaths(st, resetSource, next);
|
|
@@ -4106,13 +4304,13 @@ function reset(st, nextDefaultValues) {
|
|
|
4106
4304
|
st.removedSubtrees.clear();
|
|
4107
4305
|
seedOriginalsFromBaseline(st, next, false);
|
|
4108
4306
|
if (nextDefaultValues !== void 0) {
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
|
|
4112
|
-
|
|
4113
|
-
|
|
4114
|
-
|
|
4115
|
-
|
|
4307
|
+
const mentioned = /* @__PURE__ */ new Set();
|
|
4308
|
+
walkAuthoredFromConstraints(nextDefaultValues, [], mentioned);
|
|
4309
|
+
for (const key of mentioned) st.originalBlankPaths.delete(key);
|
|
4310
|
+
}
|
|
4311
|
+
st.blankPaths.clear();
|
|
4312
|
+
for (const key of st.originalBlankPaths) {
|
|
4313
|
+
st.blankPaths.add(key);
|
|
4116
4314
|
}
|
|
4117
4315
|
st.errorCells.clear();
|
|
4118
4316
|
if (st.strict && !resetResponse.success) {
|
|
@@ -4420,7 +4618,16 @@ function createFormStore(options) {
|
|
|
4420
4618
|
originalBlankPaths,
|
|
4421
4619
|
// --- kernel-internal state ---
|
|
4422
4620
|
strict,
|
|
4423
|
-
|
|
4621
|
+
// Defensive copy, not a fix for an observed alias: today
|
|
4622
|
+
// `getDefaultValues` happens to build a fresh tree, so form storage
|
|
4623
|
+
// does not currently share structure with the consumer's object.
|
|
4624
|
+
// That is an adapter implementation detail rather than a contract,
|
|
4625
|
+
// and this field is now durable state that every `reset()` reads, so
|
|
4626
|
+
// it should not depend on it. The copy also means a consumer who
|
|
4627
|
+
// keeps a reference to the literal they passed cannot mutate the
|
|
4628
|
+
// form's defaults from outside. `reset()` snapshots for a harder
|
|
4629
|
+
// reason (see there) where an alias IS reachable.
|
|
4630
|
+
defaultValues: structuralSnapshot(defaultValues),
|
|
4424
4631
|
ssrPrefetch,
|
|
4425
4632
|
rememberVariants,
|
|
4426
4633
|
fieldValidationMode,
|
|
@@ -4449,6 +4656,7 @@ function createFormStore(options) {
|
|
|
4449
4656
|
// --- methods: thin per-instance skins over the module kernel ---
|
|
4450
4657
|
rehydrate: () => rehydrate(st),
|
|
4451
4658
|
activate: () => activate(st),
|
|
4659
|
+
adoptResolvedDefaults: (value) => adoptResolvedDefaults(st, value),
|
|
4452
4660
|
pathHasAsyncValidation: (path) => pathHasAsyncValidation(st, path),
|
|
4453
4661
|
pathHasAsyncValidationByKey: (key, segments) => pathHasAsyncValidationByKey(st, key, segments),
|
|
4454
4662
|
applyFormReplacement: (next, meta) => applyFormReplacement(st, next, meta),
|
|
@@ -4594,6 +4802,7 @@ function useAbstractForm(configuration, options) {
|
|
|
4594
4802
|
const factory = resolvedDefaults.factory;
|
|
4595
4803
|
state.defaultValuesFactory.value = factory;
|
|
4596
4804
|
if (hadPendingHydration) {
|
|
4805
|
+
state.adoptResolvedDefaults(toRaw(state.form.value));
|
|
4597
4806
|
state.hydrating.value = false;
|
|
4598
4807
|
state.defaultsResolved.value = true;
|
|
4599
4808
|
} else if (registry.ssr) {
|
|
@@ -4775,12 +4984,13 @@ function makeRegisterValueProxy(capturedRegisterValue) {
|
|
|
4775
4984
|
get(_target, prop) {
|
|
4776
4985
|
if (prop === "__v_isRef") return true;
|
|
4777
4986
|
if (prop === "value") return capturedRegisterValue.value;
|
|
4987
|
+
if (prop === "isBound") return capturedRegisterValue.value !== void 0;
|
|
4778
4988
|
const v = capturedRegisterValue.value;
|
|
4779
4989
|
if (v === void 0) return void 0;
|
|
4780
4990
|
return Reflect.get(v, prop);
|
|
4781
4991
|
},
|
|
4782
4992
|
has(_target, prop) {
|
|
4783
|
-
if (prop === "__v_isRef" || prop === "value") return true;
|
|
4993
|
+
if (prop === "__v_isRef" || prop === "value" || prop === "isBound") return true;
|
|
4784
4994
|
const v = capturedRegisterValue.value;
|
|
4785
4995
|
if (v === void 0) return false;
|
|
4786
4996
|
return Reflect.has(v, prop);
|
|
@@ -4801,7 +5011,7 @@ function makeRegisterValueProxy(capturedRegisterValue) {
|
|
|
4801
5011
|
}
|
|
4802
5012
|
});
|
|
4803
5013
|
}
|
|
4804
|
-
function useRegister() {
|
|
5014
|
+
function useRegister(options) {
|
|
4805
5015
|
const instance = getCurrentInstance();
|
|
4806
5016
|
if (instance === null) {
|
|
4807
5017
|
return makeRegisterValueProxy(shallowRef(void 0));
|
|
@@ -4840,7 +5050,7 @@ function useRegister() {
|
|
|
4840
5050
|
if (el !== null && el !== void 0 && typeof el === "object") {
|
|
4841
5051
|
el[REGISTER_OWNER_MARKER] = true;
|
|
4842
5052
|
}
|
|
4843
|
-
if (capturedRegisterValue.value === void 0) ;
|
|
5053
|
+
if (capturedRegisterValue.value === void 0 && options?.optional !== true) ;
|
|
4844
5054
|
});
|
|
4845
5055
|
return makeRegisterValueProxy(capturedRegisterValue);
|
|
4846
5056
|
}
|
|
@@ -4947,8 +5157,12 @@ function buildNoopWizardSchema(formKey) {
|
|
|
4947
5157
|
getDefaultAtPath: () => void 0,
|
|
4948
5158
|
getEmptyValueAtPath: () => void 0,
|
|
4949
5159
|
isPreprocessOrCoerceLeaf: () => false,
|
|
5160
|
+
isOpaqueLeafAtPath: () => false,
|
|
4950
5161
|
arrayShapeAtPath: () => null,
|
|
4951
5162
|
isFixedObjectAtPath: (path) => path.length === 0,
|
|
5163
|
+
// The noop schema declares no shape at all, so nothing under it is
|
|
5164
|
+
// addressable, root included.
|
|
5165
|
+
entryKeyKindAtPath: () => void 0,
|
|
4952
5166
|
getSchemasAtPath: () => [],
|
|
4953
5167
|
validateAtPath: () => success,
|
|
4954
5168
|
getSlimPrimitiveTypesAtPath: () => new Set(EMPTY_SLIM_KINDS),
|
|
@@ -5710,6 +5924,24 @@ function useWizard(options) {
|
|
|
5710
5924
|
const target = list[idx + 1];
|
|
5711
5925
|
moveTo(target.key);
|
|
5712
5926
|
}
|
|
5927
|
+
let cancelDeferredAdvance = null;
|
|
5928
|
+
function advanceWhenInFlightSubmitLands(store, key) {
|
|
5929
|
+
cancelDeferredAdvance?.();
|
|
5930
|
+
const attemptsAtRequest = store.submissionAttempts.value;
|
|
5931
|
+
const off = store.onSubmitSuccess(() => {
|
|
5932
|
+
off();
|
|
5933
|
+
cancelDeferredAdvance = null;
|
|
5934
|
+
if (store.submissionAttempts.value !== attemptsAtRequest) return;
|
|
5935
|
+
if (activeKey.value !== key) return;
|
|
5936
|
+
advanceOne();
|
|
5937
|
+
});
|
|
5938
|
+
cancelDeferredAdvance = off;
|
|
5939
|
+
}
|
|
5940
|
+
function inFlightActiveStore() {
|
|
5941
|
+
const store = registry.forms.get(activeKey.value);
|
|
5942
|
+
if (store === void 0 || store.activeSubmissions.value === 0) return void 0;
|
|
5943
|
+
return store;
|
|
5944
|
+
}
|
|
5713
5945
|
async function next() {
|
|
5714
5946
|
if (submitting.value) {
|
|
5715
5947
|
return;
|
|
@@ -5723,7 +5955,12 @@ function useWizard(options) {
|
|
|
5723
5955
|
return;
|
|
5724
5956
|
}
|
|
5725
5957
|
const active = list[idx];
|
|
5726
|
-
if (active !== void 0 && active.isGate) {
|
|
5958
|
+
if (active !== void 0 && active.isGate && !clearedGates.has(active.key)) {
|
|
5959
|
+
const inFlight = inFlightActiveStore();
|
|
5960
|
+
if (inFlight !== void 0) {
|
|
5961
|
+
advanceWhenInFlightSubmitLands(inFlight, activeKey.value);
|
|
5962
|
+
return;
|
|
5963
|
+
}
|
|
5727
5964
|
await tryNext();
|
|
5728
5965
|
return;
|
|
5729
5966
|
}
|
|
@@ -5744,11 +5981,16 @@ function useWizard(options) {
|
|
|
5744
5981
|
const form = activeForm.value;
|
|
5745
5982
|
if (form === void 0) return false;
|
|
5746
5983
|
const before = activeKey.value;
|
|
5984
|
+
const inFlight = inFlightActiveStore();
|
|
5985
|
+
if (inFlight !== void 0) {
|
|
5986
|
+
advanceWhenInFlightSubmitLands(inFlight, before);
|
|
5987
|
+
return false;
|
|
5988
|
+
}
|
|
5747
5989
|
let ranClean = false;
|
|
5748
5990
|
await asHandleSubmitSource(form).handleSubmit(() => {
|
|
5749
5991
|
ranClean = true;
|
|
5750
5992
|
})();
|
|
5751
|
-
if (ranClean) advanceOne();
|
|
5993
|
+
if (ranClean && activeKey.value === before) advanceOne();
|
|
5752
5994
|
return activeKey.value !== before;
|
|
5753
5995
|
}
|
|
5754
5996
|
function back() {
|
|
@@ -5988,6 +6230,7 @@ function useWizard(options) {
|
|
|
5988
6230
|
onScopeDispose(() => {
|
|
5989
6231
|
historyHandle.dispose();
|
|
5990
6232
|
lazyNoopScope.stop();
|
|
6233
|
+
cancelDeferredAdvance?.();
|
|
5991
6234
|
});
|
|
5992
6235
|
}
|
|
5993
6236
|
const explicitKey = options.key;
|
|
@@ -6137,4 +6380,4 @@ function escapeForInlineScript(json) {
|
|
|
6137
6380
|
});
|
|
6138
6381
|
}
|
|
6139
6382
|
|
|
6140
|
-
export { AttaformErrorCode as A, DEFAULT_TIMINGS as D, defaultDisplayState as a, defineCoercion as b, injectWizard as c, defaultCoercionRules as d, escapeForInlineScript as e, isUnset as f, gate as g, useAbstractForm as h, injectForm as i, useRegister as j, useWizard as k, lazy as l, makeDefaultDisplayState as m, isPlainRecord as n,
|
|
6383
|
+
export { AttaformErrorCode as A, DEFAULT_TIMINGS as D, defaultDisplayState as a, defineCoercion as b, injectWizard as c, defaultCoercionRules as d, escapeForInlineScript as e, isUnset as f, gate as g, useAbstractForm as h, injectForm as i, useRegister as j, useWizard as k, lazy as l, makeDefaultDisplayState as m, isPlainRecord as n, crossCopyState as o, getAtPath as p, humanize as q, slimKindOf as s, unset as u };
|