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,8 +1,8 @@
|
|
|
1
1
|
import { computed, readonly, toRaw, ref, watchEffect, getCurrentScope, onScopeDispose, shallowReadonly, nextTick, warn, reactive, shallowRef, toValue, watch, triggerRef, getCurrentInstance, onServerPrefetch, provide, useId, inject, onBeforeMount, onBeforeUpdate, onMounted, effectScope } from 'vue';
|
|
2
|
-
import { A as ANONYMOUS_FORM_KEY_PREFIX, i as isShadowedKey,
|
|
3
|
-
import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform-dev.
|
|
4
|
-
import { R as REGISTER_OWNER_MARKER, d as armDomBinding, V as V_REGISTER_MARKER } from './attaform-dev.
|
|
5
|
-
import { i as isPathPrefix, e as canonicalizePath,
|
|
2
|
+
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-dev.ButTkwHd.mjs';
|
|
3
|
+
import { e as ensureAttaformInstalled, u as useRegistry, d as kFormContext, f as kFormInstanceId, b as kAttaformWizardActiveStepResolver, i as kAttaformAncestorWizard } from './attaform-dev.DD5m2W51.mjs';
|
|
4
|
+
import { R as REGISTER_OWNER_MARKER, d as armDomBinding, V as V_REGISTER_MARKER } from './attaform-dev.D8aoKb89.mjs';
|
|
5
|
+
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-dev.A-TpJW0B.mjs';
|
|
6
6
|
|
|
7
7
|
const AttaformErrorCode = {
|
|
8
8
|
/** A required field is in the blank set — user hasn't supplied a value. */
|
|
@@ -77,6 +77,11 @@ function makeBlankRequiredError(segments) {
|
|
|
77
77
|
}
|
|
78
78
|
const NO_ERRORS = Object.freeze([]);
|
|
79
79
|
|
|
80
|
+
function crossCopyState(key, create) {
|
|
81
|
+
const carrier = globalThis;
|
|
82
|
+
return carrier[key] ?? (carrier[key] = create());
|
|
83
|
+
}
|
|
84
|
+
|
|
80
85
|
function isGateOpen(field, formMeta) {
|
|
81
86
|
return formMeta.submissionAttempts > 0 || field.blurredAfterInteraction === true;
|
|
82
87
|
}
|
|
@@ -99,7 +104,10 @@ function earliestNonNull(a, b) {
|
|
|
99
104
|
}
|
|
100
105
|
const DEFAULT_TIMINGS = { showDelay: 120, minVisible: 120 };
|
|
101
106
|
const FOCUS_OUT_GRACE = 16;
|
|
102
|
-
const defaultFamily =
|
|
107
|
+
const defaultFamily = crossCopyState(
|
|
108
|
+
/* @__PURE__ */ Symbol.for("attaform:default-display-state-family"),
|
|
109
|
+
() => /* @__PURE__ */ new WeakSet()
|
|
110
|
+
);
|
|
103
111
|
function isDefaultDisplayState(fn) {
|
|
104
112
|
return defaultFamily.has(fn);
|
|
105
113
|
}
|
|
@@ -186,6 +194,17 @@ function humanize(segment) {
|
|
|
186
194
|
}
|
|
187
195
|
|
|
188
196
|
const NOT_FOUND = /* @__PURE__ */ Symbol("NOT_FOUND");
|
|
197
|
+
function mapKeyForSegment(map, segment, declared) {
|
|
198
|
+
if (map.has(segment)) return segment;
|
|
199
|
+
if (typeof segment !== "number") return segment;
|
|
200
|
+
const asString = String(segment);
|
|
201
|
+
if (map.has(asString)) return asString;
|
|
202
|
+
return declared === "string" ? asString : segment;
|
|
203
|
+
}
|
|
204
|
+
function isRebuildableContainer(root, segment) {
|
|
205
|
+
if (root === null || root === void 0 || typeof root !== "object") return true;
|
|
206
|
+
return typeof segment === "number" ? Array.isArray(root) : isPlainRecord(root);
|
|
207
|
+
}
|
|
189
208
|
function descendStep(value, segment) {
|
|
190
209
|
if (value === null || value === void 0) return NOT_FOUND;
|
|
191
210
|
if (typeof value !== "object") return NOT_FOUND;
|
|
@@ -194,6 +213,11 @@ function descendStep(value, segment) {
|
|
|
194
213
|
if (!(segment in value)) return NOT_FOUND;
|
|
195
214
|
return value[segment];
|
|
196
215
|
}
|
|
216
|
+
if (value instanceof Map) {
|
|
217
|
+
const key2 = mapKeyForSegment(value, segment);
|
|
218
|
+
if (!value.has(key2)) return NOT_FOUND;
|
|
219
|
+
return value.get(key2);
|
|
220
|
+
}
|
|
197
221
|
const record = value;
|
|
198
222
|
const key = typeof segment === "number" ? String(segment) : segment;
|
|
199
223
|
if (isShadowedKey(key)) {
|
|
@@ -226,11 +250,14 @@ function hasAtPath(root, path) {
|
|
|
226
250
|
if (current === null || current === void 0) return false;
|
|
227
251
|
if (typeof current !== "object") return false;
|
|
228
252
|
if (Array.isArray(current)) {
|
|
229
|
-
return typeof last === "number" && last
|
|
253
|
+
return typeof last === "number" && consumerHas(current, last);
|
|
254
|
+
}
|
|
255
|
+
if (current instanceof Map) {
|
|
256
|
+
return current.has(mapKeyForSegment(current, last));
|
|
230
257
|
}
|
|
231
258
|
const key = typeof last === "number" ? String(last) : last;
|
|
232
259
|
if (isShadowedKey(key)) return safeOwnHas(current, key);
|
|
233
|
-
return key
|
|
260
|
+
return consumerHas(current, key);
|
|
234
261
|
}
|
|
235
262
|
function isPlainRecord(value) {
|
|
236
263
|
if (value === null || typeof value !== "object") return false;
|
|
@@ -245,6 +272,13 @@ function setAtPathOffset(root, path, value, offset) {
|
|
|
245
272
|
if (offset >= path.length) return value;
|
|
246
273
|
const head = path[offset];
|
|
247
274
|
const nextOffset = offset + 1;
|
|
275
|
+
if (root instanceof Map) {
|
|
276
|
+
const next = new Map(root);
|
|
277
|
+
const key = mapKeyForSegment(root, head);
|
|
278
|
+
next.set(key, setAtPathOffset(root.get(key), path, value, nextOffset));
|
|
279
|
+
return next;
|
|
280
|
+
}
|
|
281
|
+
if (!isRebuildableContainer(root, head)) return root;
|
|
248
282
|
if (typeof head === "number") {
|
|
249
283
|
const arr = Array.isArray(root) ? [...root] : [];
|
|
250
284
|
while (arr.length <= head) arr.push(void 0);
|
|
@@ -258,9 +292,17 @@ function setAtPathOffset(root, path, value, offset) {
|
|
|
258
292
|
const NO_IN_PLACE = { applied: false };
|
|
259
293
|
function tryInPlaceLeafWrite(root, path, value) {
|
|
260
294
|
if (path.length === 0) return NO_IN_PLACE;
|
|
295
|
+
try {
|
|
296
|
+
return descendAndWrite(root, path, value);
|
|
297
|
+
} catch {
|
|
298
|
+
return NO_IN_PLACE;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function descendAndWrite(root, path, value) {
|
|
261
302
|
let node = root;
|
|
262
303
|
for (let i = 0; i < path.length; i++) {
|
|
263
304
|
const seg = path[i];
|
|
305
|
+
if (node instanceof Map) return NO_IN_PLACE;
|
|
264
306
|
if (Array.isArray(node)) {
|
|
265
307
|
if (typeof seg !== "number" || seg < 0 || seg >= node.length) return NO_IN_PLACE;
|
|
266
308
|
} else if (isPlainRecord(node)) {
|
|
@@ -295,17 +337,40 @@ function mergeStructuralImpl(schema, scratch, consumer, defaultValue) {
|
|
|
295
337
|
if (Array.isArray(consumer)) {
|
|
296
338
|
return mergeStructuralArray(schema, scratch, consumer);
|
|
297
339
|
}
|
|
340
|
+
if (consumer instanceof Map) {
|
|
341
|
+
return mergeStructuralMap(schema, scratch, consumer);
|
|
342
|
+
}
|
|
298
343
|
if (isPlainRecord(consumer)) {
|
|
299
344
|
if (!isPlainRecord(defaultValue)) {
|
|
300
345
|
return consumer;
|
|
301
346
|
}
|
|
302
|
-
const out =
|
|
347
|
+
const out = spreadConsumerRecord(consumer);
|
|
303
348
|
const filledAny = fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out);
|
|
304
349
|
const recursedAny = recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out);
|
|
305
350
|
return filledAny || recursedAny ? out : consumer;
|
|
306
351
|
}
|
|
307
352
|
return consumer;
|
|
308
353
|
}
|
|
354
|
+
function mergeStructuralMap(schema, scratch, consumer) {
|
|
355
|
+
if (consumer.size === 0) return consumer;
|
|
356
|
+
let entryDefault;
|
|
357
|
+
let entryDefaultRead = false;
|
|
358
|
+
let out = null;
|
|
359
|
+
for (const [key, entry] of consumer) {
|
|
360
|
+
if (typeof key !== "string" && typeof key !== "number") continue;
|
|
361
|
+
scratch.push(key);
|
|
362
|
+
if (!entryDefaultRead) {
|
|
363
|
+
entryDefault = schema.getDefaultAtPath(scratch);
|
|
364
|
+
entryDefaultRead = true;
|
|
365
|
+
}
|
|
366
|
+
const merged = mergeStructuralImpl(schema, scratch, entry, entryDefault);
|
|
367
|
+
scratch.pop();
|
|
368
|
+
if (merged === entry) continue;
|
|
369
|
+
out ?? (out = new Map(consumer));
|
|
370
|
+
out.set(key, merged);
|
|
371
|
+
}
|
|
372
|
+
return out ?? consumer;
|
|
373
|
+
}
|
|
309
374
|
function mergeStructuralArray(schema, scratch, consumer) {
|
|
310
375
|
const shape = schema.arrayShapeAtPath(scratch);
|
|
311
376
|
const isTuple = typeof shape === "number";
|
|
@@ -313,7 +378,7 @@ function mergeStructuralArray(schema, scratch, consumer) {
|
|
|
313
378
|
let cachedElementDefault;
|
|
314
379
|
let cachedElementDefaultRead = false;
|
|
315
380
|
let mutated = targetLen > consumer.length;
|
|
316
|
-
const out = consumer
|
|
381
|
+
const out = copyConsumerArray(consumer);
|
|
317
382
|
while (out.length < targetLen) out.push(void 0);
|
|
318
383
|
for (let i = 0; i < targetLen; i++) {
|
|
319
384
|
scratch.push(i);
|
|
@@ -327,7 +392,7 @@ function mergeStructuralArray(schema, scratch, consumer) {
|
|
|
327
392
|
}
|
|
328
393
|
elemDefault = cachedElementDefault;
|
|
329
394
|
}
|
|
330
|
-
const consumerElem = i < consumer.length ? consumer
|
|
395
|
+
const consumerElem = i < consumer.length ? readConsumerIndex(consumer, i) : void 0;
|
|
331
396
|
const merged = mergeStructuralImpl(schema, scratch, consumerElem, elemDefault);
|
|
332
397
|
scratch.pop();
|
|
333
398
|
if (merged !== consumerElem) {
|
|
@@ -355,7 +420,7 @@ function fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out
|
|
|
355
420
|
}
|
|
356
421
|
function recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out) {
|
|
357
422
|
let mutated = false;
|
|
358
|
-
for (const key of
|
|
423
|
+
for (const key of consumerKeys(consumer)) {
|
|
359
424
|
const cVal = safeOwnRead(consumer, key);
|
|
360
425
|
if (cVal === void 0) continue;
|
|
361
426
|
scratch.push(key);
|
|
@@ -376,6 +441,21 @@ function setAtPathWithSchemaFillImpl(root, schema, fullPath, value, startIdx) {
|
|
|
376
441
|
if (startIdx >= fullPath.length) return value;
|
|
377
442
|
const head = fullPath[startIdx];
|
|
378
443
|
const isLeafStep = startIdx === fullPath.length - 1;
|
|
444
|
+
if (root instanceof Map) {
|
|
445
|
+
const next = new Map(root);
|
|
446
|
+
const key = mapKeyForSegment(root, head, schema.entryKeyKindAtPath(fullPath.slice(0, startIdx)));
|
|
447
|
+
if (isLeafStep) {
|
|
448
|
+
next.set(key, value);
|
|
449
|
+
return next;
|
|
450
|
+
}
|
|
451
|
+
let childRoot2 = next.get(key);
|
|
452
|
+
if (childRoot2 === void 0 || childRoot2 !== null && typeof childRoot2 !== "object") {
|
|
453
|
+
childRoot2 = schema.getDefaultAtPath(fullPath.slice(0, startIdx + 1));
|
|
454
|
+
}
|
|
455
|
+
next.set(key, setAtPathWithSchemaFillImpl(childRoot2, schema, fullPath, value, startIdx + 1));
|
|
456
|
+
return next;
|
|
457
|
+
}
|
|
458
|
+
if (!isRebuildableContainer(root, head)) return root;
|
|
379
459
|
if (typeof head === "number") {
|
|
380
460
|
const arr = Array.isArray(root) ? [...root] : [];
|
|
381
461
|
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 {
|
|
@@ -803,6 +885,10 @@ function liveKeysAtPath(state, segments) {
|
|
|
803
885
|
for (let i = 0; i < value.length; i += 1) keys[i] = String(i);
|
|
804
886
|
return keys;
|
|
805
887
|
}
|
|
888
|
+
if (value instanceof Map) {
|
|
889
|
+
return mapSegmentKeys(value)?.map(String) ?? [];
|
|
890
|
+
}
|
|
891
|
+
if (value instanceof Set) return [];
|
|
806
892
|
if (typeof value === "object") return Object.keys(value);
|
|
807
893
|
return [];
|
|
808
894
|
}
|
|
@@ -813,6 +899,12 @@ function liveContainerHasKey(state, segments, key) {
|
|
|
813
899
|
const index = Number(key);
|
|
814
900
|
return Number.isInteger(index) && index >= 0 && index < value.length && String(index) === key;
|
|
815
901
|
}
|
|
902
|
+
if (value instanceof Map) {
|
|
903
|
+
if (value.has(key)) return true;
|
|
904
|
+
const index = Number(key);
|
|
905
|
+
return Number.isInteger(index) && index >= 0 && String(index) === key && value.has(index);
|
|
906
|
+
}
|
|
907
|
+
if (value instanceof Set) return false;
|
|
816
908
|
return Object.hasOwn(value, key);
|
|
817
909
|
}
|
|
818
910
|
function isArrayPath(state, segments) {
|
|
@@ -839,6 +931,7 @@ function makeReadonlyCoercion(snapshot) {
|
|
|
839
931
|
}
|
|
840
932
|
|
|
841
933
|
const INTEGER_SEGMENT = /^(?:0|[1-9]\d*)$/;
|
|
934
|
+
const RELEASED = /* @__PURE__ */ Symbol();
|
|
842
935
|
const EMPTY_DESCENT = Object.freeze({});
|
|
843
936
|
function keyToSegment(key) {
|
|
844
937
|
return INTEGER_SEGMENT.test(key) ? Number(key) : key;
|
|
@@ -868,12 +961,18 @@ function callableInvokeShim(method, surface, getDescent) {
|
|
|
868
961
|
function buildTree(spec) {
|
|
869
962
|
const containerCache = /* @__PURE__ */ new Map();
|
|
870
963
|
const existsCache = /* @__PURE__ */ new Map();
|
|
964
|
+
spec.sweep.onEvict((key) => {
|
|
965
|
+
containerCache.delete(`${key}+A`);
|
|
966
|
+
containerCache.delete(`${key}+O`);
|
|
967
|
+
existsCache.delete(key);
|
|
968
|
+
});
|
|
871
969
|
function schemaHasPath(segs) {
|
|
872
970
|
const cacheKey = JSON.stringify(segs);
|
|
873
971
|
const cached = existsCache.get(cacheKey);
|
|
874
972
|
if (cached !== void 0) return cached;
|
|
875
973
|
const result = spec.schema.getSlimPrimitiveTypesAtPath(segs).size > 0;
|
|
876
974
|
existsCache.set(cacheKey, result);
|
|
975
|
+
spec.sweep.track(segs, cacheKey);
|
|
877
976
|
return result;
|
|
878
977
|
}
|
|
879
978
|
function descend(segs) {
|
|
@@ -883,7 +982,8 @@ function buildTree(spec) {
|
|
|
883
982
|
}
|
|
884
983
|
function containerAt(segments) {
|
|
885
984
|
const isArrayLike = spec.isArrayAt(segments);
|
|
886
|
-
const
|
|
985
|
+
const pathKey = JSON.stringify(segments);
|
|
986
|
+
const cacheKey = `${pathKey}+${isArrayLike ? "A" : "O"}`;
|
|
887
987
|
const existing = containerCache.get(cacheKey);
|
|
888
988
|
if (existing !== void 0) return existing;
|
|
889
989
|
const isFixedObject = spec.schema.isFixedObjectAtPath(segments);
|
|
@@ -973,12 +1073,14 @@ function buildTree(spec) {
|
|
|
973
1073
|
}
|
|
974
1074
|
});
|
|
975
1075
|
containerCache.set(cacheKey, proxy);
|
|
1076
|
+
spec.sweep.track(segments, pathKey);
|
|
976
1077
|
return proxy;
|
|
977
1078
|
}
|
|
978
1079
|
return containerAt([]);
|
|
979
1080
|
}
|
|
980
|
-
function buildErrorsSurface(state) {
|
|
1081
|
+
function buildErrorsSurface(state, sweep) {
|
|
981
1082
|
const treeCache = /* @__PURE__ */ new Map();
|
|
1083
|
+
sweep.onEvict((key) => treeCache.delete(key));
|
|
982
1084
|
const materialize = (segments) => {
|
|
983
1085
|
const cacheKey = JSON.stringify(segments);
|
|
984
1086
|
let tree = treeCache.get(cacheKey);
|
|
@@ -986,6 +1088,7 @@ function buildErrorsSurface(state) {
|
|
|
986
1088
|
const frozen = [...segments];
|
|
987
1089
|
tree = computed(() => materializeErrors(state, frozen));
|
|
988
1090
|
treeCache.set(cacheKey, tree);
|
|
1091
|
+
sweep.track(segments, cacheKey);
|
|
989
1092
|
}
|
|
990
1093
|
return tree.value;
|
|
991
1094
|
};
|
|
@@ -1031,7 +1134,8 @@ function buildErrorsSurface(state) {
|
|
|
1031
1134
|
// aggregate — the same helper `meta.errors` reads, so the surfaces
|
|
1032
1135
|
// never drift.
|
|
1033
1136
|
call: (path) => aggregateErrorsAt(state, path),
|
|
1034
|
-
surface: "form.errors"
|
|
1137
|
+
surface: "form.errors",
|
|
1138
|
+
sweep
|
|
1035
1139
|
});
|
|
1036
1140
|
}
|
|
1037
1141
|
function errorAwareContainerKeys(state, segments) {
|
|
@@ -1150,7 +1254,7 @@ const FIELD_STATE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1150
1254
|
"placeholder",
|
|
1151
1255
|
"meta"
|
|
1152
1256
|
]);
|
|
1153
|
-
function buildFieldsSurface(state, getFieldStateAt) {
|
|
1257
|
+
function buildFieldsSurface(state, getFieldStateAt, sweep) {
|
|
1154
1258
|
const snapshotAt = (segments) => {
|
|
1155
1259
|
const view = getFieldStateAt(segments).value;
|
|
1156
1260
|
const snapshot = {};
|
|
@@ -1158,6 +1262,7 @@ function buildFieldsSurface(state, getFieldStateAt) {
|
|
|
1158
1262
|
return snapshot;
|
|
1159
1263
|
};
|
|
1160
1264
|
const viewCache = /* @__PURE__ */ new Map();
|
|
1265
|
+
sweep.onEvict((key) => viewCache.delete(key));
|
|
1161
1266
|
function viewAt(segments) {
|
|
1162
1267
|
const cacheKey = JSON.stringify(segments);
|
|
1163
1268
|
const existing = viewCache.get(cacheKey);
|
|
@@ -1212,6 +1317,7 @@ function buildFieldsSurface(state, getFieldStateAt) {
|
|
|
1212
1317
|
}
|
|
1213
1318
|
});
|
|
1214
1319
|
viewCache.set(cacheKey, proxy);
|
|
1320
|
+
sweep.track(segments, cacheKey);
|
|
1215
1321
|
return proxy;
|
|
1216
1322
|
}
|
|
1217
1323
|
return buildTree({
|
|
@@ -1226,7 +1332,8 @@ function buildFieldsSurface(state, getFieldStateAt) {
|
|
|
1226
1332
|
// container's rollup); a path the schema doesn't have is a typo and
|
|
1227
1333
|
// reads `undefined`. The root (`fields()`) is always declared.
|
|
1228
1334
|
call: (path) => state.schema.getSlimPrimitiveTypesAtPath(path).size > 0 ? viewAt(path) : void 0,
|
|
1229
|
-
surface: "form.fields"
|
|
1335
|
+
surface: "form.fields",
|
|
1336
|
+
sweep
|
|
1230
1337
|
});
|
|
1231
1338
|
}
|
|
1232
1339
|
function materializeFields(state, containerSegments, snapshotAt) {
|
|
@@ -1260,18 +1367,34 @@ function materializeFormValue(node) {
|
|
|
1260
1367
|
}
|
|
1261
1368
|
return out;
|
|
1262
1369
|
}
|
|
1263
|
-
function buildValuesSurface(form) {
|
|
1370
|
+
function buildValuesSurface(form, onFormChange) {
|
|
1264
1371
|
const inner = computed(() => readonly(form.value));
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1372
|
+
let held = null;
|
|
1373
|
+
const snapshot = computed(() => {
|
|
1374
|
+
const box = { value: materializeFormValue(inner.value) };
|
|
1375
|
+
held = box;
|
|
1376
|
+
return box;
|
|
1377
|
+
});
|
|
1378
|
+
onFormChange(() => {
|
|
1379
|
+
if (held === null) return;
|
|
1380
|
+
held.value = RELEASED;
|
|
1381
|
+
held = null;
|
|
1382
|
+
});
|
|
1383
|
+
const readSnapshot = () => {
|
|
1384
|
+
const box = snapshot.value;
|
|
1385
|
+
return box.value === RELEASED ? materializeFormValue(inner.value) : box.value;
|
|
1386
|
+
};
|
|
1387
|
+
const { toString, valueOf, toJSON, toPrimitive } = makeReadonlyCoercion(() => readSnapshot());
|
|
1268
1388
|
const target = (() => {
|
|
1269
1389
|
});
|
|
1270
1390
|
return new Proxy(target, {
|
|
1271
1391
|
apply(_, __, args) {
|
|
1272
1392
|
const arg = args[0];
|
|
1273
|
-
if (arg === void 0) return
|
|
1274
|
-
|
|
1393
|
+
if (arg === void 0) return readSnapshot();
|
|
1394
|
+
const segments = canonicalizePath(arg).segments;
|
|
1395
|
+
const node = getAtPath(inner.value, segments);
|
|
1396
|
+
if (node === null || typeof node !== "object") return node;
|
|
1397
|
+
return getAtPath(readSnapshot(), segments);
|
|
1275
1398
|
},
|
|
1276
1399
|
get(_, key) {
|
|
1277
1400
|
if (typeof key === "symbol") {
|
|
@@ -1556,9 +1679,12 @@ function cloneVariantSnapshot(value) {
|
|
|
1556
1679
|
for (let i = 0; i < raw.length; i++) out2[i] = cloneVariantSnapshot(raw[i]);
|
|
1557
1680
|
return out2;
|
|
1558
1681
|
}
|
|
1682
|
+
if (!isPlainRecord(raw)) return raw;
|
|
1559
1683
|
const src = raw;
|
|
1560
1684
|
const out = {};
|
|
1561
|
-
for (const k of
|
|
1685
|
+
for (const k of consumerKeys(src)) {
|
|
1686
|
+
safeAssign(out, k, cloneVariantSnapshot(readConsumerProp(src, k)));
|
|
1687
|
+
}
|
|
1562
1688
|
return out;
|
|
1563
1689
|
}
|
|
1564
1690
|
function createArrayBookkeeping(deps) {
|
|
@@ -1706,6 +1832,45 @@ function buildFieldArrayApi(state) {
|
|
|
1706
1832
|
};
|
|
1707
1833
|
}
|
|
1708
1834
|
|
|
1835
|
+
const SWEEP_SLICE = 8;
|
|
1836
|
+
function createDynamicPathSweep(state) {
|
|
1837
|
+
const dynamicKeys = /* @__PURE__ */ new Set();
|
|
1838
|
+
const evictors = [];
|
|
1839
|
+
const isDynamicPath = (segments) => {
|
|
1840
|
+
for (let i = 0; i < segments.length; i++) {
|
|
1841
|
+
if (typeof segments[i] === "number") return true;
|
|
1842
|
+
if (!state.schema.isFixedObjectAtPath(segments.slice(0, i))) return true;
|
|
1843
|
+
}
|
|
1844
|
+
return false;
|
|
1845
|
+
};
|
|
1846
|
+
let sweepCursor = null;
|
|
1847
|
+
state.onFormChange((next) => {
|
|
1848
|
+
if (dynamicKeys.size === 0) return;
|
|
1849
|
+
const raw = toRaw(next);
|
|
1850
|
+
for (let i = 0; i < SWEEP_SLICE; i++) {
|
|
1851
|
+
sweepCursor ?? (sweepCursor = dynamicKeys.values());
|
|
1852
|
+
const step = sweepCursor.next();
|
|
1853
|
+
if (step.done === true) {
|
|
1854
|
+
sweepCursor = null;
|
|
1855
|
+
break;
|
|
1856
|
+
}
|
|
1857
|
+
const segments = segmentsForPathKey(step.value);
|
|
1858
|
+
if (segments !== null && hasAtPath(raw, segments)) continue;
|
|
1859
|
+
dynamicKeys.delete(step.value);
|
|
1860
|
+
for (const evict of evictors) evict(step.value);
|
|
1861
|
+
}
|
|
1862
|
+
});
|
|
1863
|
+
return {
|
|
1864
|
+
track(segments, key) {
|
|
1865
|
+
if (dynamicKeys.has(key)) return;
|
|
1866
|
+
if (isDynamicPath(segments)) dynamicKeys.add(key);
|
|
1867
|
+
},
|
|
1868
|
+
onEvict(evict) {
|
|
1869
|
+
evictors.push(evict);
|
|
1870
|
+
}
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1709
1874
|
const warnedNoScopeStores = /* @__PURE__ */ new WeakSet() ;
|
|
1710
1875
|
function isErrorInputLike(value) {
|
|
1711
1876
|
if (value instanceof Error) return true;
|
|
@@ -1853,6 +2018,11 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
1853
2018
|
event.preventDefault();
|
|
1854
2019
|
}
|
|
1855
2020
|
if (state.activeSubmissions.value > 0) {
|
|
2021
|
+
if (event === void 0) {
|
|
2022
|
+
console.warn(
|
|
2023
|
+
`[attaform] handleSubmit: a submit is already in flight on form "${String(state.formKey)}", so this call was ignored; its callback never ran. Await the first submit before starting another, or move the work into that submit's callback.`
|
|
2024
|
+
);
|
|
2025
|
+
}
|
|
1856
2026
|
return;
|
|
1857
2027
|
}
|
|
1858
2028
|
const genAtEntry = state.submissionGeneration.value;
|
|
@@ -2039,15 +2209,16 @@ function walk(schema, store, path, value) {
|
|
|
2039
2209
|
reportRejection(store, path, kind, accepted);
|
|
2040
2210
|
return false;
|
|
2041
2211
|
}
|
|
2212
|
+
if (schema.isOpaqueLeafAtPath(path)) return true;
|
|
2042
2213
|
if (Array.isArray(value)) {
|
|
2043
2214
|
for (let i = 0; i < value.length; i++) {
|
|
2044
|
-
if (!walk(schema, store, [...path, i], value
|
|
2215
|
+
if (!walk(schema, store, [...path, i], readConsumerIndex(value, i))) return false;
|
|
2045
2216
|
}
|
|
2046
2217
|
return true;
|
|
2047
2218
|
}
|
|
2048
2219
|
if (isPlainRecord(value)) {
|
|
2049
|
-
for (const key of
|
|
2050
|
-
if (!walk(schema, store, [...path, key], value
|
|
2220
|
+
for (const key of consumerKeys(value)) {
|
|
2221
|
+
if (!walk(schema, store, [...path, key], readConsumerProp(value, key))) {
|
|
2051
2222
|
return false;
|
|
2052
2223
|
}
|
|
2053
2224
|
}
|
|
@@ -2142,19 +2313,26 @@ function indexRules(rules) {
|
|
|
2142
2313
|
}
|
|
2143
2314
|
return idx;
|
|
2144
2315
|
}
|
|
2316
|
+
function memberSlimTypes(schema, segments, accepted) {
|
|
2317
|
+
if (accepted.has("array")) return schema.getSlimPrimitiveTypesAtPath([...segments, 0]);
|
|
2318
|
+
if (accepted.has("set")) {
|
|
2319
|
+
return schema.getSlimPrimitiveTypesAtPath([...segments, SET_MEMBER_SEGMENT]);
|
|
2320
|
+
}
|
|
2321
|
+
return void 0;
|
|
2322
|
+
}
|
|
2145
2323
|
function buildCoerceFn(schema, segments, index) {
|
|
2146
2324
|
if (index === EMPTY_INDEX) return IDENTITY;
|
|
2147
2325
|
if (index.size === 0) return IDENTITY;
|
|
2148
2326
|
const accepted = schema.getSlimPrimitiveTypesAtPath(segments);
|
|
2149
|
-
const elementAccepted =
|
|
2327
|
+
const elementAccepted = memberSlimTypes(schema, segments, accepted);
|
|
2150
2328
|
return (value) => coerceValue(value, accepted, elementAccepted, index);
|
|
2151
2329
|
}
|
|
2152
2330
|
function buildElementCoerceFn(schema, segments, index) {
|
|
2153
2331
|
if (index === EMPTY_INDEX) return void 0;
|
|
2154
2332
|
if (index.size === 0) return void 0;
|
|
2155
2333
|
const accepted = schema.getSlimPrimitiveTypesAtPath(segments);
|
|
2156
|
-
|
|
2157
|
-
|
|
2334
|
+
const elementAccepted = memberSlimTypes(schema, segments, accepted);
|
|
2335
|
+
if (elementAccepted === void 0) return void 0;
|
|
2158
2336
|
return (value) => coerceScalar(value, elementAccepted, index);
|
|
2159
2337
|
}
|
|
2160
2338
|
function pickScalarTarget(accepted) {
|
|
@@ -2445,8 +2623,8 @@ function walkUnsetSentinels(values, schema) {
|
|
|
2445
2623
|
const cleaned = walkCore(values, [], schema, paths, true);
|
|
2446
2624
|
return { cleanedValues: cleaned, paths };
|
|
2447
2625
|
}
|
|
2448
|
-
function
|
|
2449
|
-
return value
|
|
2626
|
+
function isRecursable(value) {
|
|
2627
|
+
return Array.isArray(value) || isPlainRecord(value);
|
|
2450
2628
|
}
|
|
2451
2629
|
function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
2452
2630
|
if (isUnset(input)) {
|
|
@@ -2460,20 +2638,21 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
|
2460
2638
|
return input;
|
|
2461
2639
|
}
|
|
2462
2640
|
if (input === null) return null;
|
|
2463
|
-
if (
|
|
2641
|
+
if (!isRecursable(input)) return input;
|
|
2464
2642
|
if (Array.isArray(input)) {
|
|
2465
2643
|
const out = new Array(input.length);
|
|
2466
2644
|
let mutated = false;
|
|
2467
2645
|
for (let i = 0; i < input.length; i++) {
|
|
2468
|
-
const
|
|
2646
|
+
const original = readConsumerIndex(input, i);
|
|
2647
|
+
const walked = walkCore(original, [...segments, i], schema, paths, synthesizeSchemaKeys);
|
|
2469
2648
|
out[i] = walked;
|
|
2470
|
-
if (walked !==
|
|
2649
|
+
if (walked !== original) mutated = true;
|
|
2471
2650
|
}
|
|
2472
2651
|
return mutated ? out : input;
|
|
2473
2652
|
}
|
|
2474
2653
|
if (typeof input === "object") {
|
|
2475
2654
|
const obj = input;
|
|
2476
|
-
const inputKeys =
|
|
2655
|
+
const inputKeys = consumerKeys(obj);
|
|
2477
2656
|
let keys = inputKeys;
|
|
2478
2657
|
let mutated = false;
|
|
2479
2658
|
let inputKeysSet = null;
|
|
@@ -2481,7 +2660,7 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
|
2481
2660
|
inputKeysSet = new Set(inputKeys);
|
|
2482
2661
|
const allKeys = new Set(inputKeys);
|
|
2483
2662
|
const slim = schema.getDefaultAtPath(segments);
|
|
2484
|
-
if (
|
|
2663
|
+
if (isPlainRecord(slim)) {
|
|
2485
2664
|
for (const k of Object.keys(slim)) allKeys.add(k);
|
|
2486
2665
|
}
|
|
2487
2666
|
keys = allKeys;
|
|
@@ -2489,7 +2668,7 @@ function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
|
2489
2668
|
}
|
|
2490
2669
|
const out = {};
|
|
2491
2670
|
for (const key of keys) {
|
|
2492
|
-
const orig = obj
|
|
2671
|
+
const orig = readConsumerProp(obj, key);
|
|
2493
2672
|
if (synthesizeSchemaKeys && orig === void 0 && inputKeysSet?.has(key) === true) {
|
|
2494
2673
|
safeAssign(out, key, void 0);
|
|
2495
2674
|
mutated = true;
|
|
@@ -2510,22 +2689,12 @@ function walkUnspecified(slim, segments, paths) {
|
|
|
2510
2689
|
}
|
|
2511
2690
|
return slim;
|
|
2512
2691
|
}
|
|
2513
|
-
if (
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
if (slim !== null && typeof slim === "object") {
|
|
2518
|
-
const out = {};
|
|
2519
|
-
for (const key of Object.keys(slim)) {
|
|
2520
|
-
safeAssign(
|
|
2521
|
-
out,
|
|
2522
|
-
key,
|
|
2523
|
-
walkUnspecified(slim[key], [...segments, key], paths)
|
|
2524
|
-
);
|
|
2525
|
-
}
|
|
2526
|
-
return out;
|
|
2692
|
+
if (!isPlainRecord(slim)) return slim;
|
|
2693
|
+
const out = {};
|
|
2694
|
+
for (const key of Object.keys(slim)) {
|
|
2695
|
+
safeAssign(out, key, walkUnspecified(slim[key], [...segments, key], paths));
|
|
2527
2696
|
}
|
|
2528
|
-
return
|
|
2697
|
+
return out;
|
|
2529
2698
|
}
|
|
2530
2699
|
function substituteUnsetSentinels(value, prefix, schema) {
|
|
2531
2700
|
const paths = [];
|
|
@@ -2561,11 +2730,11 @@ function expandUnsetAt(segments, schema, paths) {
|
|
|
2561
2730
|
paths.push(canonicalizePath(segments).key);
|
|
2562
2731
|
return slim;
|
|
2563
2732
|
}
|
|
2564
|
-
if (
|
|
2733
|
+
if (Array.isArray(slim)) return slim;
|
|
2734
|
+
if (!isPlainRecord(slim)) {
|
|
2565
2735
|
paths.push(canonicalizePath(segments).key);
|
|
2566
2736
|
return slim;
|
|
2567
2737
|
}
|
|
2568
|
-
if (Array.isArray(slim)) return slim;
|
|
2569
2738
|
const result = {};
|
|
2570
2739
|
for (const key of Object.keys(slim)) {
|
|
2571
2740
|
result[key] = expandUnsetAt([...segments, key], schema, paths);
|
|
@@ -2575,14 +2744,14 @@ function expandUnsetAt(segments, schema, paths) {
|
|
|
2575
2744
|
function walkAuthoredFromConstraints(value, prefix, out) {
|
|
2576
2745
|
if (prefix.length > 0) out.add(canonicalizePath(prefix).key);
|
|
2577
2746
|
if (isPlainRecord(value)) {
|
|
2578
|
-
for (const k of
|
|
2579
|
-
walkAuthoredFromConstraints(value
|
|
2747
|
+
for (const k of consumerKeys(value)) {
|
|
2748
|
+
walkAuthoredFromConstraints(readConsumerProp(value, k), [...prefix, k], out);
|
|
2580
2749
|
}
|
|
2581
2750
|
return;
|
|
2582
2751
|
}
|
|
2583
2752
|
if (Array.isArray(value)) {
|
|
2584
2753
|
for (let i = 0; i < value.length; i++) {
|
|
2585
|
-
walkAuthoredFromConstraints(value
|
|
2754
|
+
walkAuthoredFromConstraints(readConsumerIndex(value, i), [...prefix, i], out);
|
|
2586
2755
|
}
|
|
2587
2756
|
}
|
|
2588
2757
|
}
|
|
@@ -2662,10 +2831,12 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2662
2831
|
return metaBase;
|
|
2663
2832
|
};
|
|
2664
2833
|
const fieldStateAccessorOptions = options.getDisplayState !== void 0 ? { getDisplayState: options.getDisplayState } : void 0;
|
|
2834
|
+
const pathSweep = createDynamicPathSweep(state);
|
|
2665
2835
|
const getRootFieldStateAt = buildFieldStateAccessor(
|
|
2666
2836
|
state,
|
|
2667
2837
|
formInstanceId,
|
|
2668
2838
|
getFormMetaBase,
|
|
2839
|
+
pathSweep,
|
|
2669
2840
|
fieldStateAccessorOptions
|
|
2670
2841
|
);
|
|
2671
2842
|
const getDisplayStateAt = (segments) => getRootFieldStateAt(segments).value.displayState;
|
|
@@ -2692,6 +2863,10 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2692
2863
|
const segments = canonicalizePath(pathInput).segments;
|
|
2693
2864
|
return computed(() => getAtPath(state.form.value, segments));
|
|
2694
2865
|
}
|
|
2866
|
+
function pathStoresFunctions(segments) {
|
|
2867
|
+
if (state.schema.isOpaqueLeafAtPath(segments)) return false;
|
|
2868
|
+
return state.schema.getSlimPrimitiveTypesAtPath(segments).has("function");
|
|
2869
|
+
}
|
|
2695
2870
|
function setValueImpl(pathOrValue, maybeValue) {
|
|
2696
2871
|
const argc = arguments.length;
|
|
2697
2872
|
const isPathForm = argc >= 2 && (typeof pathOrValue === "string" || Array.isArray(pathOrValue));
|
|
@@ -2744,7 +2919,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2744
2919
|
};
|
|
2745
2920
|
if (isUnset(maybeValue)) return writeUnsetAt();
|
|
2746
2921
|
let resolvedValue;
|
|
2747
|
-
if (typeof maybeValue === "function") {
|
|
2922
|
+
if (typeof maybeValue === "function" && !pathStoresFunctions(segments)) {
|
|
2748
2923
|
const current = state.getValueAtPath(segments);
|
|
2749
2924
|
const prev = current === void 0 ? state.schema.getDefaultAtPath(segments) : current;
|
|
2750
2925
|
resolvedValue = maybeValue(prev);
|
|
@@ -2762,7 +2937,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2762
2937
|
reMarkBlanksAfterSubstitution(walked.paths);
|
|
2763
2938
|
return true;
|
|
2764
2939
|
}
|
|
2765
|
-
const errorsProxy = buildErrorsSurface(state);
|
|
2940
|
+
const errorsProxy = buildErrorsSurface(state, pathSweep);
|
|
2766
2941
|
function flattenUserErrors() {
|
|
2767
2942
|
const all = [];
|
|
2768
2943
|
for (const cell of state.errorCells.values()) all.push(...cell.user);
|
|
@@ -2861,8 +3036,9 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2861
3036
|
if (nextDefaultValues === void 0) {
|
|
2862
3037
|
state.reset();
|
|
2863
3038
|
} else {
|
|
2864
|
-
const walked =
|
|
3039
|
+
const walked = substituteUnsetSentinels(
|
|
2865
3040
|
nextDefaultValues,
|
|
3041
|
+
[],
|
|
2866
3042
|
state.schema
|
|
2867
3043
|
);
|
|
2868
3044
|
state.reset(walked.cleanedValues);
|
|
@@ -2936,8 +3112,8 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2936
3112
|
};
|
|
2937
3113
|
return Object.freeze(view);
|
|
2938
3114
|
});
|
|
2939
|
-
const valuesProxy = buildValuesSurface(state.form);
|
|
2940
|
-
const fieldStateProxy = buildFieldsSurface(state, getRootFieldStateAt);
|
|
3115
|
+
const valuesProxy = buildValuesSurface(state.form, state.onFormChange);
|
|
3116
|
+
const fieldStateProxy = buildFieldsSurface(state, getRootFieldStateAt, pathSweep);
|
|
2941
3117
|
const needsLazyGate = state.defaultValuesFactory.value !== void 0 || state.hasSsrPrefetch;
|
|
2942
3118
|
function gated(fn) {
|
|
2943
3119
|
if (!needsLazyGate) return fn;
|
|
@@ -3085,6 +3261,12 @@ function shortenSourceFrame(frame) {
|
|
|
3085
3261
|
|
|
3086
3262
|
const IDLE = Object.freeze({ display: "idle" });
|
|
3087
3263
|
const MAX_DELAY = 2147483647;
|
|
3264
|
+
const PENDING_LIVENESS_MS = 250;
|
|
3265
|
+
function withLiveness(machine, now) {
|
|
3266
|
+
if (machine.display !== "pending") return machine;
|
|
3267
|
+
if (machine.reviewAt !== void 0 && Number.isFinite(machine.reviewAt)) return machine;
|
|
3268
|
+
return { ...machine, reviewAt: now + PENDING_LIVENESS_MS };
|
|
3269
|
+
}
|
|
3088
3270
|
function createDisplayEngine(ssr) {
|
|
3089
3271
|
const machines = /* @__PURE__ */ new Map();
|
|
3090
3272
|
const tick = ref(0);
|
|
@@ -3113,7 +3295,7 @@ function createDisplayEngine(ssr) {
|
|
|
3113
3295
|
return;
|
|
3114
3296
|
}
|
|
3115
3297
|
if (timer !== null && timerTarget === target) return;
|
|
3116
|
-
if (target === lastFiredTarget) {
|
|
3298
|
+
if (target === lastFiredTarget && target <= now) {
|
|
3117
3299
|
clearTimer();
|
|
3118
3300
|
return;
|
|
3119
3301
|
}
|
|
@@ -3132,8 +3314,9 @@ function createDisplayEngine(ssr) {
|
|
|
3132
3314
|
function resolve(key, ctx, reducer) {
|
|
3133
3315
|
void tick.value;
|
|
3134
3316
|
const prev = machines.get(key) ?? IDLE;
|
|
3135
|
-
const
|
|
3136
|
-
if (ssr) return
|
|
3317
|
+
const reduced = reducer(prev, ctx);
|
|
3318
|
+
if (ssr) return reduced;
|
|
3319
|
+
const machine = withLiveness(reduced, ctx.now);
|
|
3137
3320
|
const active = machine.display !== "idle" || machine.reviewAt !== void 0 && Number.isFinite(machine.reviewAt);
|
|
3138
3321
|
if (active) machines.set(key, machine);
|
|
3139
3322
|
else machines.delete(key);
|
|
@@ -3230,6 +3413,7 @@ async function runFactoryAndApply(st, factory) {
|
|
|
3230
3413
|
st.schema
|
|
3231
3414
|
);
|
|
3232
3415
|
st.applyFormReplacement(full, { hydration: true });
|
|
3416
|
+
st.adoptResolvedDefaults(value);
|
|
3233
3417
|
st.scheduleFieldValidation(
|
|
3234
3418
|
[],
|
|
3235
3419
|
true
|
|
@@ -3314,12 +3498,10 @@ function applyDuStubs(schema, data, options = {}) {
|
|
|
3314
3498
|
}
|
|
3315
3499
|
function walkDuStubs(schema, value, path, warned) {
|
|
3316
3500
|
if (value === null || value === void 0 || typeof value !== "object") return value;
|
|
3317
|
-
if (value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || typeof value === "function") {
|
|
3318
|
-
return value;
|
|
3319
|
-
}
|
|
3320
3501
|
if (Array.isArray(value)) {
|
|
3321
3502
|
return value.map((item, i) => walkDuStubs(schema, item, [...path, i], warned));
|
|
3322
3503
|
}
|
|
3504
|
+
if (!isPlainRecord(value)) return value;
|
|
3323
3505
|
const rec = value;
|
|
3324
3506
|
const du = schema.getUnionDiscriminatorAtPath(path);
|
|
3325
3507
|
if (du !== void 0) {
|
|
@@ -3342,8 +3524,8 @@ function walkDuStubs(schema, value, path, warned) {
|
|
|
3342
3524
|
}
|
|
3343
3525
|
}
|
|
3344
3526
|
const out = {};
|
|
3345
|
-
for (const k of
|
|
3346
|
-
safeAssign(out, k, walkDuStubs(schema, rec
|
|
3527
|
+
for (const k of consumerKeys(rec)) {
|
|
3528
|
+
safeAssign(out, k, walkDuStubs(schema, readConsumerProp(rec, k), [...path, k], warned));
|
|
3347
3529
|
}
|
|
3348
3530
|
return out;
|
|
3349
3531
|
}
|
|
@@ -3353,23 +3535,25 @@ function stripSymbolsDeep(value) {
|
|
|
3353
3535
|
let mutated2 = false;
|
|
3354
3536
|
const out2 = new Array(value.length);
|
|
3355
3537
|
for (let i = 0; i < value.length; i++) {
|
|
3356
|
-
const
|
|
3538
|
+
const original = readConsumerIndex(value, i);
|
|
3539
|
+
const cleaned = stripSymbolsDeep(original);
|
|
3357
3540
|
out2[i] = cleaned;
|
|
3358
|
-
if (cleaned !==
|
|
3541
|
+
if (cleaned !== original) mutated2 = true;
|
|
3359
3542
|
}
|
|
3360
3543
|
return mutated2 ? out2 : value;
|
|
3361
3544
|
}
|
|
3362
3545
|
const proto = Object.getPrototypeOf(value);
|
|
3363
3546
|
if (proto !== Object.prototype && proto !== null) return value;
|
|
3364
|
-
const symKeys =
|
|
3365
|
-
const stringKeys =
|
|
3547
|
+
const symKeys = consumerSymbolKeys(value);
|
|
3548
|
+
const stringKeys = consumerKeys(value);
|
|
3366
3549
|
let mutated = symKeys.length > 0;
|
|
3367
3550
|
const out = {};
|
|
3368
3551
|
const src = value;
|
|
3369
3552
|
for (const k of stringKeys) {
|
|
3370
|
-
const
|
|
3553
|
+
const original = readConsumerProp(src, k);
|
|
3554
|
+
const cleaned = stripSymbolsDeep(original);
|
|
3371
3555
|
out[k] = cleaned;
|
|
3372
|
-
if (cleaned !==
|
|
3556
|
+
if (cleaned !== original) mutated = true;
|
|
3373
3557
|
}
|
|
3374
3558
|
return mutated ? out : value;
|
|
3375
3559
|
}
|
|
@@ -4290,8 +4474,27 @@ function activate(st) {
|
|
|
4290
4474
|
if (factory === void 0) return Promise.resolve();
|
|
4291
4475
|
return fireFactory(st, factory);
|
|
4292
4476
|
}
|
|
4477
|
+
function adoptResolvedDefaults(st, value) {
|
|
4478
|
+
st.defaultValues = structuralSnapshot(
|
|
4479
|
+
mergeSparseHydration(
|
|
4480
|
+
st.defaultValues,
|
|
4481
|
+
value,
|
|
4482
|
+
st.schema
|
|
4483
|
+
)
|
|
4484
|
+
);
|
|
4485
|
+
seedOriginalsFromBaseline(
|
|
4486
|
+
st,
|
|
4487
|
+
computeBaselineResponse(st.schema, st.strict, st.defaultValues).data,
|
|
4488
|
+
false
|
|
4489
|
+
);
|
|
4490
|
+
}
|
|
4293
4491
|
function reset(st, nextDefaultValues) {
|
|
4294
|
-
const resetSource = nextDefaultValues
|
|
4492
|
+
const resetSource = nextDefaultValues === void 0 ? st.defaultValues : mergeSparseHydration(
|
|
4493
|
+
st.defaultValues,
|
|
4494
|
+
nextDefaultValues,
|
|
4495
|
+
st.schema
|
|
4496
|
+
);
|
|
4497
|
+
st.defaultValues = structuralSnapshot(resetSource);
|
|
4295
4498
|
const resetResponse = computeBaselineResponse(st.schema, st.strict, resetSource);
|
|
4296
4499
|
const next = resetResponse.data;
|
|
4297
4500
|
rebuildAuthoredPaths(st, resetSource, next);
|
|
@@ -4300,13 +4503,13 @@ function reset(st, nextDefaultValues) {
|
|
|
4300
4503
|
st.removedSubtrees.clear();
|
|
4301
4504
|
seedOriginalsFromBaseline(st, next, false);
|
|
4302
4505
|
if (nextDefaultValues !== void 0) {
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4506
|
+
const mentioned = /* @__PURE__ */ new Set();
|
|
4507
|
+
walkAuthoredFromConstraints(nextDefaultValues, [], mentioned);
|
|
4508
|
+
for (const key of mentioned) st.originalBlankPaths.delete(key);
|
|
4509
|
+
}
|
|
4510
|
+
st.blankPaths.clear();
|
|
4511
|
+
for (const key of st.originalBlankPaths) {
|
|
4512
|
+
st.blankPaths.add(key);
|
|
4310
4513
|
}
|
|
4311
4514
|
st.errorCells.clear();
|
|
4312
4515
|
if (st.strict && !resetResponse.success) {
|
|
@@ -4622,7 +4825,16 @@ function createFormStore(options) {
|
|
|
4622
4825
|
originalBlankPaths,
|
|
4623
4826
|
// --- kernel-internal state ---
|
|
4624
4827
|
strict,
|
|
4625
|
-
|
|
4828
|
+
// Defensive copy, not a fix for an observed alias: today
|
|
4829
|
+
// `getDefaultValues` happens to build a fresh tree, so form storage
|
|
4830
|
+
// does not currently share structure with the consumer's object.
|
|
4831
|
+
// That is an adapter implementation detail rather than a contract,
|
|
4832
|
+
// and this field is now durable state that every `reset()` reads, so
|
|
4833
|
+
// it should not depend on it. The copy also means a consumer who
|
|
4834
|
+
// keeps a reference to the literal they passed cannot mutate the
|
|
4835
|
+
// form's defaults from outside. `reset()` snapshots for a harder
|
|
4836
|
+
// reason (see there) where an alias IS reachable.
|
|
4837
|
+
defaultValues: structuralSnapshot(defaultValues),
|
|
4626
4838
|
ssrPrefetch,
|
|
4627
4839
|
rememberVariants,
|
|
4628
4840
|
fieldValidationMode,
|
|
@@ -4651,6 +4863,7 @@ function createFormStore(options) {
|
|
|
4651
4863
|
// --- methods: thin per-instance skins over the module kernel ---
|
|
4652
4864
|
rehydrate: () => rehydrate(st),
|
|
4653
4865
|
activate: () => activate(st),
|
|
4866
|
+
adoptResolvedDefaults: (value) => adoptResolvedDefaults(st, value),
|
|
4654
4867
|
pathHasAsyncValidation: (path) => pathHasAsyncValidation(st, path),
|
|
4655
4868
|
pathHasAsyncValidationByKey: (key, segments) => pathHasAsyncValidationByKey(st, key, segments),
|
|
4656
4869
|
applyFormReplacement: (next, meta) => applyFormReplacement(st, next, meta),
|
|
@@ -4804,6 +5017,7 @@ function useAbstractForm(configuration, options) {
|
|
|
4804
5017
|
const factory = resolvedDefaults.factory;
|
|
4805
5018
|
state.defaultValuesFactory.value = factory;
|
|
4806
5019
|
if (hadPendingHydration) {
|
|
5020
|
+
state.adoptResolvedDefaults(toRaw(state.form.value));
|
|
4807
5021
|
state.hydrating.value = false;
|
|
4808
5022
|
state.defaultsResolved.value = true;
|
|
4809
5023
|
} else if (registry.ssr) {
|
|
@@ -5032,12 +5246,13 @@ function makeRegisterValueProxy(capturedRegisterValue) {
|
|
|
5032
5246
|
get(_target, prop) {
|
|
5033
5247
|
if (prop === "__v_isRef") return true;
|
|
5034
5248
|
if (prop === "value") return capturedRegisterValue.value;
|
|
5249
|
+
if (prop === "isBound") return capturedRegisterValue.value !== void 0;
|
|
5035
5250
|
const v = capturedRegisterValue.value;
|
|
5036
5251
|
if (v === void 0) return void 0;
|
|
5037
5252
|
return Reflect.get(v, prop);
|
|
5038
5253
|
},
|
|
5039
5254
|
has(_target, prop) {
|
|
5040
|
-
if (prop === "__v_isRef" || prop === "value") return true;
|
|
5255
|
+
if (prop === "__v_isRef" || prop === "value" || prop === "isBound") return true;
|
|
5041
5256
|
const v = capturedRegisterValue.value;
|
|
5042
5257
|
if (v === void 0) return false;
|
|
5043
5258
|
return Reflect.has(v, prop);
|
|
@@ -5058,7 +5273,7 @@ function makeRegisterValueProxy(capturedRegisterValue) {
|
|
|
5058
5273
|
}
|
|
5059
5274
|
});
|
|
5060
5275
|
}
|
|
5061
|
-
function useRegister() {
|
|
5276
|
+
function useRegister(options) {
|
|
5062
5277
|
const instance = getCurrentInstance();
|
|
5063
5278
|
if (instance === null) {
|
|
5064
5279
|
warnOutsideSetup();
|
|
@@ -5098,7 +5313,7 @@ function useRegister() {
|
|
|
5098
5313
|
if (el !== null && el !== void 0 && typeof el === "object") {
|
|
5099
5314
|
el[REGISTER_OWNER_MARKER] = true;
|
|
5100
5315
|
}
|
|
5101
|
-
if (capturedRegisterValue.value === void 0) {
|
|
5316
|
+
if (capturedRegisterValue.value === void 0 && options?.optional !== true) {
|
|
5102
5317
|
warnNoParentRV(instance);
|
|
5103
5318
|
}
|
|
5104
5319
|
});
|
|
@@ -5118,7 +5333,7 @@ function warnNoParentRV(instance) {
|
|
|
5118
5333
|
warnedNoParentRV.add(instance);
|
|
5119
5334
|
const frame = captureUserCallSite();
|
|
5120
5335
|
console.warn(
|
|
5121
|
-
`[attaform] useRegister: no parent registerValue prop; RegisterValue fields will read as undefined. Pass v-register on the parent: \`<YourComponent v-register="form.register('field')"
|
|
5336
|
+
`[attaform] useRegister: no parent registerValue prop; RegisterValue fields will read as undefined. Pass v-register on the parent: \`<YourComponent v-register="form.register('field')" />\`. If this component is meant to work without a form too, say so with \`useRegister({ optional: true })\` and branch on \`rv?.isBound\`.` + (frame !== void 0 ? ` ${frame}` : "")
|
|
5122
5337
|
);
|
|
5123
5338
|
}
|
|
5124
5339
|
|
|
@@ -5224,8 +5439,12 @@ function buildNoopWizardSchema(formKey) {
|
|
|
5224
5439
|
getDefaultAtPath: () => void 0,
|
|
5225
5440
|
getEmptyValueAtPath: () => void 0,
|
|
5226
5441
|
isPreprocessOrCoerceLeaf: () => false,
|
|
5442
|
+
isOpaqueLeafAtPath: () => false,
|
|
5227
5443
|
arrayShapeAtPath: () => null,
|
|
5228
5444
|
isFixedObjectAtPath: (path) => path.length === 0,
|
|
5445
|
+
// The noop schema declares no shape at all, so nothing under it is
|
|
5446
|
+
// addressable, root included.
|
|
5447
|
+
entryKeyKindAtPath: () => void 0,
|
|
5229
5448
|
getSchemasAtPath: () => [],
|
|
5230
5449
|
validateAtPath: () => success,
|
|
5231
5450
|
getSlimPrimitiveTypesAtPath: () => new Set(EMPTY_SLIM_KINDS),
|
|
@@ -6024,6 +6243,24 @@ function useWizard(options) {
|
|
|
6024
6243
|
const target = list[idx + 1];
|
|
6025
6244
|
moveTo(target.key);
|
|
6026
6245
|
}
|
|
6246
|
+
let cancelDeferredAdvance = null;
|
|
6247
|
+
function advanceWhenInFlightSubmitLands(store, key) {
|
|
6248
|
+
cancelDeferredAdvance?.();
|
|
6249
|
+
const attemptsAtRequest = store.submissionAttempts.value;
|
|
6250
|
+
const off = store.onSubmitSuccess(() => {
|
|
6251
|
+
off();
|
|
6252
|
+
cancelDeferredAdvance = null;
|
|
6253
|
+
if (store.submissionAttempts.value !== attemptsAtRequest) return;
|
|
6254
|
+
if (activeKey.value !== key) return;
|
|
6255
|
+
advanceOne();
|
|
6256
|
+
});
|
|
6257
|
+
cancelDeferredAdvance = off;
|
|
6258
|
+
}
|
|
6259
|
+
function inFlightActiveStore() {
|
|
6260
|
+
const store = registry.forms.get(activeKey.value);
|
|
6261
|
+
if (store === void 0 || store.activeSubmissions.value === 0) return void 0;
|
|
6262
|
+
return store;
|
|
6263
|
+
}
|
|
6027
6264
|
async function next() {
|
|
6028
6265
|
if (submitting.value) {
|
|
6029
6266
|
{
|
|
@@ -6050,7 +6287,12 @@ function useWizard(options) {
|
|
|
6050
6287
|
return;
|
|
6051
6288
|
}
|
|
6052
6289
|
const active = list[idx];
|
|
6053
|
-
if (active !== void 0 && active.isGate) {
|
|
6290
|
+
if (active !== void 0 && active.isGate && !clearedGates.has(active.key)) {
|
|
6291
|
+
const inFlight = inFlightActiveStore();
|
|
6292
|
+
if (inFlight !== void 0) {
|
|
6293
|
+
advanceWhenInFlightSubmitLands(inFlight, activeKey.value);
|
|
6294
|
+
return;
|
|
6295
|
+
}
|
|
6054
6296
|
await tryNext();
|
|
6055
6297
|
return;
|
|
6056
6298
|
}
|
|
@@ -6082,11 +6324,16 @@ function useWizard(options) {
|
|
|
6082
6324
|
const form = activeForm.value;
|
|
6083
6325
|
if (form === void 0) return false;
|
|
6084
6326
|
const before = activeKey.value;
|
|
6327
|
+
const inFlight = inFlightActiveStore();
|
|
6328
|
+
if (inFlight !== void 0) {
|
|
6329
|
+
advanceWhenInFlightSubmitLands(inFlight, before);
|
|
6330
|
+
return false;
|
|
6331
|
+
}
|
|
6085
6332
|
let ranClean = false;
|
|
6086
6333
|
await asHandleSubmitSource(form).handleSubmit(() => {
|
|
6087
6334
|
ranClean = true;
|
|
6088
6335
|
})();
|
|
6089
|
-
if (ranClean) advanceOne();
|
|
6336
|
+
if (ranClean && activeKey.value === before) advanceOne();
|
|
6090
6337
|
return activeKey.value !== before;
|
|
6091
6338
|
}
|
|
6092
6339
|
function back() {
|
|
@@ -6366,6 +6613,7 @@ function useWizard(options) {
|
|
|
6366
6613
|
onScopeDispose(() => {
|
|
6367
6614
|
historyHandle.dispose();
|
|
6368
6615
|
lazyNoopScope.stop();
|
|
6616
|
+
cancelDeferredAdvance?.();
|
|
6369
6617
|
});
|
|
6370
6618
|
}
|
|
6371
6619
|
const explicitKey = options.key;
|
|
@@ -6558,4 +6806,4 @@ function escapeForInlineScript(json) {
|
|
|
6558
6806
|
});
|
|
6559
6807
|
}
|
|
6560
6808
|
|
|
6561
|
-
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,
|
|
6809
|
+
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 };
|