attaform 0.21.0 → 0.21.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/dev-key-collision-warnings.cjs +1 -1
- package/dist/chunks/dev-key-collision-warnings.mjs +1 -1
- package/dist/chunks/devtools.cjs +1 -1
- package/dist/chunks/devtools.mjs +1 -1
- package/dist/chunks/fingerprint2.cjs +1 -1
- package/dist/chunks/fingerprint2.mjs +1 -1
- package/dist/chunks/indexeddb.cjs +1 -1
- package/dist/chunks/indexeddb.mjs +1 -1
- package/dist/chunks/local-storage.cjs +1 -1
- package/dist/chunks/local-storage.mjs +1 -1
- package/dist/chunks/multi-tab-sync.cjs +2 -2
- package/dist/chunks/multi-tab-sync.mjs +2 -2
- package/dist/chunks/session-storage.cjs +1 -1
- package/dist/chunks/session-storage.mjs +1 -1
- package/dist/chunks/wire-persistence.cjs +2 -2
- package/dist/chunks/wire-persistence.mjs +2 -2
- package/dist/index.cjs +37 -24
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +31 -28
- package/dist/index.d.mts +31 -28
- package/dist/index.d.ts +31 -28
- package/dist/index.mjs +38 -25
- package/dist/index.mjs.map +1 -1
- package/dist/nuxt.d.cts +1 -1
- package/dist/nuxt.d.mts +1 -1
- package/dist/nuxt.d.ts +1 -1
- package/dist/runtime/components/AttaformDevtoolsPanel.vue +396 -216
- package/dist/runtime/components/DevtoolsValueTree.vue +176 -114
- package/dist/runtime/plugins/attaform.cjs +2 -2
- package/dist/runtime/plugins/attaform.mjs +2 -2
- package/dist/shared/{attaform.BA3vRDos.cjs → attaform.B5LNzqQh.cjs} +349 -277
- package/dist/shared/attaform.B5LNzqQh.cjs.map +1 -0
- package/dist/shared/{attaform.PnqML3xW.cjs → attaform.BBDIKtKY.cjs} +13 -16
- package/dist/shared/attaform.BBDIKtKY.cjs.map +1 -0
- package/dist/shared/{attaform.CRsXyy-Y.d.ts → attaform.BCcrLApm.d.mts} +131 -64
- package/dist/shared/{attaform.BupwXkj_.mjs → attaform.BFWb6hDk.mjs} +29 -23
- package/dist/shared/attaform.BFWb6hDk.mjs.map +1 -0
- package/dist/shared/{attaform.7lzO9pdM.d.mts → attaform.BGf_J22U.d.ts} +131 -64
- package/dist/shared/{attaform.BnK_bfcb.mjs → attaform.BVeLgfEh.mjs} +14 -17
- package/dist/shared/attaform.BVeLgfEh.mjs.map +1 -0
- package/dist/shared/{attaform.BK1RE2ha.d.ts → attaform.BYgioWLF.d.ts} +2 -2
- package/dist/shared/{attaform.F8LMHHWV.d.cts → attaform.BkjJfMvJ.d.cts} +131 -64
- package/dist/shared/{attaform.BDIEq9qP.d.cts → attaform.BoY6RZUl.d.cts} +2 -2
- package/dist/shared/{attaform.CEf6wYfD.cjs → attaform.BwLp9KM7.cjs} +2 -2
- package/dist/shared/{attaform.CEf6wYfD.cjs.map → attaform.BwLp9KM7.cjs.map} +1 -1
- package/dist/shared/{attaform._rsCZy2j.cjs → attaform.BwrowMp2.cjs} +25 -45
- package/dist/shared/attaform.BwrowMp2.cjs.map +1 -0
- package/dist/shared/{attaform.ezb5Nh2t.mjs → attaform.C41gjp-a.mjs} +2 -2
- package/dist/shared/{attaform.ezb5Nh2t.mjs.map → attaform.C41gjp-a.mjs.map} +1 -1
- package/dist/shared/{attaform.BM6YD9kZ.cjs → attaform.CR6wGvNu.cjs} +29 -23
- package/dist/shared/attaform.CR6wGvNu.cjs.map +1 -0
- package/dist/shared/{attaform.DSqO6Db7.mjs → attaform.CTheKoTc.mjs} +705 -282
- package/dist/shared/attaform.CTheKoTc.mjs.map +1 -0
- package/dist/shared/{attaform.BzvOdiSI.cjs → attaform.CcnF1AKJ.cjs} +4 -4
- package/dist/shared/attaform.CcnF1AKJ.cjs.map +1 -0
- package/dist/shared/{attaform.BQ6drorq.d.mts → attaform.CnEl--PF.d.mts} +2 -2
- package/dist/shared/{attaform.CkjTapyq.mjs → attaform.CrD73S4m.mjs} +4 -4
- package/dist/shared/attaform.CrD73S4m.mjs.map +1 -0
- package/dist/shared/{attaform.BUszFoKq.cjs → attaform.D2ZuIOCf.cjs} +711 -287
- package/dist/shared/attaform.D2ZuIOCf.cjs.map +1 -0
- package/dist/shared/{attaform.r3PePkDR.mjs → attaform.D6GYGshL.mjs} +25 -45
- package/dist/shared/attaform.D6GYGshL.mjs.map +1 -0
- package/dist/shared/{attaform.Y_Mgg0Yp.mjs → attaform.DP-u7_tk.mjs} +348 -277
- package/dist/shared/attaform.DP-u7_tk.mjs.map +1 -0
- package/dist/shared/{attaform.B1nyO4ec.d.cts → attaform.ory-3WhV.d.cts} +395 -176
- package/dist/shared/{attaform.B1nyO4ec.d.mts → attaform.ory-3WhV.d.mts} +395 -176
- package/dist/shared/{attaform.B1nyO4ec.d.ts → attaform.ory-3WhV.d.ts} +395 -176
- package/dist/transforms.cjs +1 -1
- package/dist/transforms.mjs +1 -1
- package/dist/vite.cjs +1 -1
- package/dist/vite.mjs +1 -1
- package/dist/zod-v3.cjs +3 -4
- package/dist/zod-v3.cjs.map +1 -1
- package/dist/zod-v3.d.cts +4 -4
- package/dist/zod-v3.d.mts +4 -4
- package/dist/zod-v3.d.ts +4 -4
- package/dist/zod-v3.mjs +2 -3
- package/dist/zod-v3.mjs.map +1 -1
- package/dist/zod-v4.cjs +3 -4
- package/dist/zod-v4.cjs.map +1 -1
- package/dist/zod-v4.d.cts +4 -4
- package/dist/zod-v4.d.mts +4 -4
- package/dist/zod-v4.d.ts +4 -4
- package/dist/zod-v4.mjs +2 -3
- package/dist/zod-v4.mjs.map +1 -1
- package/dist/zod.cjs +6 -6
- package/dist/zod.cjs.map +1 -1
- package/dist/zod.d.cts +77 -26
- package/dist/zod.d.mts +77 -26
- package/dist/zod.d.ts +77 -26
- package/dist/zod.mjs +5 -6
- package/dist/zod.mjs.map +1 -1
- package/package.json +3 -11
- package/dist/shared/attaform.BA3vRDos.cjs.map +0 -1
- package/dist/shared/attaform.BM6YD9kZ.cjs.map +0 -1
- package/dist/shared/attaform.BUszFoKq.cjs.map +0 -1
- package/dist/shared/attaform.BnK_bfcb.mjs.map +0 -1
- package/dist/shared/attaform.BupwXkj_.mjs.map +0 -1
- package/dist/shared/attaform.BzvOdiSI.cjs.map +0 -1
- package/dist/shared/attaform.CkjTapyq.mjs.map +0 -1
- package/dist/shared/attaform.DSqO6Db7.mjs.map +0 -1
- package/dist/shared/attaform.PnqML3xW.cjs.map +0 -1
- package/dist/shared/attaform.Y_Mgg0Yp.mjs.map +0 -1
- package/dist/shared/attaform._rsCZy2j.cjs.map +0 -1
- package/dist/shared/attaform.r3PePkDR.mjs.map +0 -1
- package/dist/shared/{attaform.DSD85fHb.d.cts → attaform.nf83TIR5.d.cts} +10 -10
- package/dist/shared/{attaform.DSD85fHb.d.mts → attaform.nf83TIR5.d.mts} +10 -10
- package/dist/shared/{attaform.DSD85fHb.d.ts → attaform.nf83TIR5.d.ts} +10 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const vue = require('vue');
|
|
4
|
-
const paths = require('./attaform.
|
|
4
|
+
const paths = require('./attaform.B5LNzqQh.cjs');
|
|
5
5
|
|
|
6
6
|
function safeAssign(target, key, value) {
|
|
7
7
|
if (key === "__proto__") {
|
|
@@ -15,10 +15,14 @@ function safeAssign(target, key, value) {
|
|
|
15
15
|
}
|
|
16
16
|
target[key] = value;
|
|
17
17
|
}
|
|
18
|
+
function isShadowedKey(key) {
|
|
19
|
+
return key in Object.prototype;
|
|
20
|
+
}
|
|
18
21
|
function safeOwnRead(target, key) {
|
|
19
|
-
if (key
|
|
20
|
-
const desc = Object.getOwnPropertyDescriptor(target,
|
|
21
|
-
return
|
|
22
|
+
if (isShadowedKey(key)) {
|
|
23
|
+
const desc = Object.getOwnPropertyDescriptor(target, key);
|
|
24
|
+
if (desc === void 0) return void 0;
|
|
25
|
+
return "value" in desc ? desc.value : target[key];
|
|
22
26
|
}
|
|
23
27
|
return target[key];
|
|
24
28
|
}
|
|
@@ -37,6 +41,10 @@ function descendStep(value, segment) {
|
|
|
37
41
|
}
|
|
38
42
|
const record = value;
|
|
39
43
|
const key = typeof segment === "number" ? String(segment) : segment;
|
|
44
|
+
if (isShadowedKey(key)) {
|
|
45
|
+
if (!safeOwnHas(record, key)) return NOT_FOUND;
|
|
46
|
+
return safeOwnRead(record, key);
|
|
47
|
+
}
|
|
40
48
|
if (!(key in record)) return NOT_FOUND;
|
|
41
49
|
return record[key];
|
|
42
50
|
}
|
|
@@ -66,6 +74,7 @@ function hasAtPath(root, path) {
|
|
|
66
74
|
return typeof last === "number" && last >= 0 && last < current.length;
|
|
67
75
|
}
|
|
68
76
|
const key = typeof last === "number" ? String(last) : last;
|
|
77
|
+
if (isShadowedKey(key)) return safeOwnHas(current, key);
|
|
69
78
|
return key in current;
|
|
70
79
|
}
|
|
71
80
|
function isPlainRecord(value) {
|
|
@@ -153,68 +162,80 @@ function mergeStructuralImpl(schema, scratch, consumer, defaultValue) {
|
|
|
153
162
|
}
|
|
154
163
|
if (consumer === null) return null;
|
|
155
164
|
if (Array.isArray(consumer)) {
|
|
156
|
-
|
|
157
|
-
const isTuple = typeof shape === "number";
|
|
158
|
-
const targetLen = isTuple ? shape : consumer.length;
|
|
159
|
-
let cachedElementDefault;
|
|
160
|
-
let cachedElementDefaultRead = false;
|
|
161
|
-
let mutated = targetLen > consumer.length;
|
|
162
|
-
const out = consumer.slice();
|
|
163
|
-
while (out.length < targetLen) out.push(void 0);
|
|
164
|
-
for (let i = 0; i < targetLen; i++) {
|
|
165
|
-
scratch.push(i);
|
|
166
|
-
let elemDefault;
|
|
167
|
-
if (isTuple) {
|
|
168
|
-
elemDefault = schema.getDefaultAtPath(scratch);
|
|
169
|
-
} else {
|
|
170
|
-
if (!cachedElementDefaultRead) {
|
|
171
|
-
cachedElementDefault = schema.getDefaultAtPath(scratch);
|
|
172
|
-
cachedElementDefaultRead = true;
|
|
173
|
-
}
|
|
174
|
-
elemDefault = cachedElementDefault;
|
|
175
|
-
}
|
|
176
|
-
const consumerElem = i < consumer.length ? consumer[i] : void 0;
|
|
177
|
-
const merged = mergeStructuralImpl(schema, scratch, consumerElem, elemDefault);
|
|
178
|
-
scratch.pop();
|
|
179
|
-
if (merged !== consumerElem) {
|
|
180
|
-
out[i] = merged;
|
|
181
|
-
mutated = true;
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
return mutated ? out : consumer;
|
|
165
|
+
return mergeStructuralArray(schema, scratch, consumer);
|
|
185
166
|
}
|
|
186
167
|
if (isPlainRecord(consumer)) {
|
|
187
168
|
if (!isPlainRecord(defaultValue)) {
|
|
188
169
|
return consumer;
|
|
189
170
|
}
|
|
190
|
-
let mutated = false;
|
|
191
171
|
const out = { ...consumer };
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
172
|
+
const filledAny = fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out);
|
|
173
|
+
const recursedAny = recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out);
|
|
174
|
+
return filledAny || recursedAny ? out : consumer;
|
|
175
|
+
}
|
|
176
|
+
return consumer;
|
|
177
|
+
}
|
|
178
|
+
function mergeStructuralArray(schema, scratch, consumer) {
|
|
179
|
+
const shape = resolveArrayShape(schema, scratch);
|
|
180
|
+
const isTuple = typeof shape === "number";
|
|
181
|
+
const targetLen = isTuple ? shape : consumer.length;
|
|
182
|
+
let cachedElementDefault;
|
|
183
|
+
let cachedElementDefaultRead = false;
|
|
184
|
+
let mutated = targetLen > consumer.length;
|
|
185
|
+
const out = consumer.slice();
|
|
186
|
+
while (out.length < targetLen) out.push(void 0);
|
|
187
|
+
for (let i = 0; i < targetLen; i++) {
|
|
188
|
+
scratch.push(i);
|
|
189
|
+
let elemDefault;
|
|
190
|
+
if (isTuple) {
|
|
191
|
+
elemDefault = schema.getDefaultAtPath(scratch);
|
|
192
|
+
} else {
|
|
193
|
+
if (!cachedElementDefaultRead) {
|
|
194
|
+
cachedElementDefault = schema.getDefaultAtPath(scratch);
|
|
195
|
+
cachedElementDefaultRead = true;
|
|
202
196
|
}
|
|
197
|
+
elemDefault = cachedElementDefault;
|
|
203
198
|
}
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
199
|
+
const consumerElem = i < consumer.length ? consumer[i] : void 0;
|
|
200
|
+
const merged = mergeStructuralImpl(schema, scratch, consumerElem, elemDefault);
|
|
201
|
+
scratch.pop();
|
|
202
|
+
if (merged !== consumerElem) {
|
|
203
|
+
out[i] = merged;
|
|
204
|
+
mutated = true;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return mutated ? out : consumer;
|
|
208
|
+
}
|
|
209
|
+
function fillMissingKeysFromDefault(schema, scratch, consumer, defaultValue, out) {
|
|
210
|
+
let mutated = false;
|
|
211
|
+
for (const key of Object.keys(defaultValue)) {
|
|
212
|
+
if (!safeOwnHas(consumer, key)) {
|
|
213
|
+
const defAtKey = safeOwnRead(defaultValue, key);
|
|
207
214
|
scratch.push(key);
|
|
208
|
-
const
|
|
215
|
+
const filled = mergeStructuralImpl(schema, scratch, void 0, defAtKey);
|
|
209
216
|
scratch.pop();
|
|
210
|
-
if (
|
|
211
|
-
safeAssign(out, key,
|
|
217
|
+
if (filled !== void 0) {
|
|
218
|
+
safeAssign(out, key, filled);
|
|
212
219
|
mutated = true;
|
|
213
220
|
}
|
|
214
221
|
}
|
|
215
|
-
return mutated ? out : consumer;
|
|
216
222
|
}
|
|
217
|
-
return
|
|
223
|
+
return mutated;
|
|
224
|
+
}
|
|
225
|
+
function recurseIntoConsumerKeys(schema, scratch, consumer, defaultValue, out) {
|
|
226
|
+
let mutated = false;
|
|
227
|
+
for (const key of Object.keys(consumer)) {
|
|
228
|
+
const cVal = safeOwnRead(consumer, key);
|
|
229
|
+
if (cVal === void 0) continue;
|
|
230
|
+
scratch.push(key);
|
|
231
|
+
const merged = mergeStructuralImpl(schema, scratch, cVal, safeOwnRead(defaultValue, key));
|
|
232
|
+
scratch.pop();
|
|
233
|
+
if (merged !== cVal) {
|
|
234
|
+
safeAssign(out, key, merged);
|
|
235
|
+
mutated = true;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return mutated;
|
|
218
239
|
}
|
|
219
240
|
function setAtPathWithSchemaFill(root, schema, fullPath, value) {
|
|
220
241
|
if (fullPath.length === 0) return value;
|
|
@@ -297,55 +318,27 @@ function diffAndApply(oldValue, newValue, prefix, visit) {
|
|
|
297
318
|
const oldIsDescendable = isDescendable(oldValue);
|
|
298
319
|
const newIsDescendable = isDescendable(newValue);
|
|
299
320
|
if (oldValue === void 0 && newIsDescendable) {
|
|
300
|
-
|
|
301
|
-
for (let i = 0; i < newValue.length; i++) {
|
|
302
|
-
diffAndApply(void 0, newValue[i], appendSegment(prefix, i), visit);
|
|
303
|
-
}
|
|
304
|
-
} else {
|
|
305
|
-
const rec = newValue;
|
|
306
|
-
for (const k of Object.keys(rec)) {
|
|
307
|
-
diffAndApply(void 0, rec[k], appendSegment(prefix, k), visit);
|
|
308
|
-
}
|
|
309
|
-
}
|
|
321
|
+
walkNewDescendable(newValue, prefix, visit);
|
|
310
322
|
return;
|
|
311
323
|
}
|
|
312
324
|
if (oldIsDescendable && newValue === void 0) {
|
|
313
|
-
|
|
314
|
-
for (let i = 0; i < oldValue.length; i++) {
|
|
315
|
-
diffAndApply(oldValue[i], void 0, appendSegment(prefix, i), visit);
|
|
316
|
-
}
|
|
317
|
-
} else {
|
|
318
|
-
const rec = oldValue;
|
|
319
|
-
for (const k of Object.keys(rec)) {
|
|
320
|
-
diffAndApply(rec[k], void 0, appendSegment(prefix, k), visit);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
325
|
+
walkOldDescendable(oldValue, prefix, visit);
|
|
323
326
|
return;
|
|
324
327
|
}
|
|
325
328
|
if (oldIsDescendable && newIsDescendable) {
|
|
326
329
|
const oldIsArray = Array.isArray(oldValue);
|
|
327
330
|
const newIsArray = Array.isArray(newValue);
|
|
328
331
|
if (oldIsArray && newIsArray) {
|
|
329
|
-
|
|
330
|
-
const newArr = newValue;
|
|
331
|
-
const max = Math.max(oldArr.length, newArr.length);
|
|
332
|
-
for (let i = 0; i < max; i++) {
|
|
333
|
-
diffAndApply(oldArr[i], newArr[i], appendSegment(prefix, i), visit);
|
|
334
|
-
}
|
|
332
|
+
diffArraysLockstep(oldValue, newValue, prefix, visit);
|
|
335
333
|
return;
|
|
336
334
|
}
|
|
337
335
|
if (!oldIsArray && !newIsArray) {
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
345
|
-
for (const k of Object.keys(newRec)) {
|
|
346
|
-
if (seen.has(k)) continue;
|
|
347
|
-
diffAndApply(oldRec[k], newRec[k], appendSegment(prefix, k), visit);
|
|
348
|
-
}
|
|
336
|
+
diffObjectsLockstep(
|
|
337
|
+
oldValue,
|
|
338
|
+
newValue,
|
|
339
|
+
prefix,
|
|
340
|
+
visit
|
|
341
|
+
);
|
|
349
342
|
return;
|
|
350
343
|
}
|
|
351
344
|
visit({ kind: "changed", path: prefix, oldValue, newValue });
|
|
@@ -369,6 +362,47 @@ function diffAndApply(oldValue, newValue, prefix, visit) {
|
|
|
369
362
|
}
|
|
370
363
|
visit({ kind: "changed", path: prefix, oldValue, newValue });
|
|
371
364
|
}
|
|
365
|
+
function walkNewDescendable(newValue, prefix, visit) {
|
|
366
|
+
if (Array.isArray(newValue)) {
|
|
367
|
+
for (let i = 0; i < newValue.length; i++) {
|
|
368
|
+
diffAndApply(void 0, newValue[i], appendSegment(prefix, i), visit);
|
|
369
|
+
}
|
|
370
|
+
} else {
|
|
371
|
+
const rec = newValue;
|
|
372
|
+
for (const k of Object.keys(rec)) {
|
|
373
|
+
diffAndApply(void 0, rec[k], appendSegment(prefix, k), visit);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function walkOldDescendable(oldValue, prefix, visit) {
|
|
378
|
+
if (Array.isArray(oldValue)) {
|
|
379
|
+
for (let i = 0; i < oldValue.length; i++) {
|
|
380
|
+
diffAndApply(oldValue[i], void 0, appendSegment(prefix, i), visit);
|
|
381
|
+
}
|
|
382
|
+
} else {
|
|
383
|
+
const rec = oldValue;
|
|
384
|
+
for (const k of Object.keys(rec)) {
|
|
385
|
+
diffAndApply(rec[k], void 0, appendSegment(prefix, k), visit);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
function diffArraysLockstep(oldArr, newArr, prefix, visit) {
|
|
390
|
+
const max = Math.max(oldArr.length, newArr.length);
|
|
391
|
+
for (let i = 0; i < max; i++) {
|
|
392
|
+
diffAndApply(oldArr[i], newArr[i], appendSegment(prefix, i), visit);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function diffObjectsLockstep(oldRec, newRec, prefix, visit) {
|
|
396
|
+
const seen = /* @__PURE__ */ new Set();
|
|
397
|
+
for (const k of Object.keys(oldRec)) {
|
|
398
|
+
seen.add(k);
|
|
399
|
+
diffAndApply(oldRec[k], newRec[k], appendSegment(prefix, k), visit);
|
|
400
|
+
}
|
|
401
|
+
for (const k of Object.keys(newRec)) {
|
|
402
|
+
if (seen.has(k)) continue;
|
|
403
|
+
diffAndApply(oldRec[k], newRec[k], appendSegment(prefix, k), visit);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
372
406
|
function applyChangedKeys(target, source) {
|
|
373
407
|
if (!isDescendable(target) || !isDescendable(source)) return false;
|
|
374
408
|
const targetIsArray = Array.isArray(target);
|
|
@@ -472,7 +506,12 @@ function computeVerdict(field, formMeta) {
|
|
|
472
506
|
if (field.valid === true && field.blank !== true && field.dirty === true) return "success";
|
|
473
507
|
return "idle";
|
|
474
508
|
}
|
|
475
|
-
|
|
509
|
+
function earliestNonNull(a, b) {
|
|
510
|
+
if (a === null) return b;
|
|
511
|
+
if (b === null) return a;
|
|
512
|
+
return a < b ? a : b;
|
|
513
|
+
}
|
|
514
|
+
const DEFAULT_TIMINGS = { showDelay: 120, minVisible: 120 };
|
|
476
515
|
const FOCUS_OUT_GRACE = 16;
|
|
477
516
|
const defaultFamily = /* @__PURE__ */ new WeakSet();
|
|
478
517
|
function isDefaultDisplayState(fn) {
|
|
@@ -482,10 +521,11 @@ function makeDefaultDisplayState({
|
|
|
482
521
|
showDelay,
|
|
483
522
|
minVisible
|
|
484
523
|
}) {
|
|
485
|
-
const reducer = (prev, { field, formMeta, validatingSince, now }) => {
|
|
524
|
+
const reducer = (prev, { field, formMeta, validatingSince, transformingSince, now }) => {
|
|
486
525
|
const verdict = computeVerdict(field, formMeta);
|
|
487
526
|
if (!isGateOpen(field, formMeta)) return { display: verdict };
|
|
488
|
-
|
|
527
|
+
const inFlightSince = earliestNonNull(validatingSince, transformingSince);
|
|
528
|
+
if (inFlightSince === null) {
|
|
489
529
|
if (prev.display === "pending") {
|
|
490
530
|
const shownAt = prev.pendingShownAt ?? now;
|
|
491
531
|
if (now < shownAt + minVisible)
|
|
@@ -496,8 +536,8 @@ function makeDefaultDisplayState({
|
|
|
496
536
|
if (prev.display === "pending")
|
|
497
537
|
return { display: "pending", pendingShownAt: prev.pendingShownAt ?? now };
|
|
498
538
|
const window = field.focused === false ? Math.min(showDelay, FOCUS_OUT_GRACE) : showDelay;
|
|
499
|
-
if (now -
|
|
500
|
-
return { display: prev.display, reviewAt:
|
|
539
|
+
if (now - inFlightSince < window) {
|
|
540
|
+
return { display: prev.display, reviewAt: inFlightSince + window };
|
|
501
541
|
}
|
|
502
542
|
return { display: "pending", pendingShownAt: now, reviewAt: now + minVisible };
|
|
503
543
|
};
|
|
@@ -610,6 +650,12 @@ function buildFieldStateAccessor(state, formInstanceId, getFormMetaBase, options
|
|
|
610
650
|
return c;
|
|
611
651
|
};
|
|
612
652
|
}
|
|
653
|
+
function resolveFieldMetaAndLabel(state, segments) {
|
|
654
|
+
const resolved = state.schema.getFieldMetaAtPath ? state.schema.getFieldMetaAtPath(segments) : EMPTY_RESOLVED_FIELD_META;
|
|
655
|
+
const lastSegment = segments.length === 0 ? "" : segments[segments.length - 1] ?? "";
|
|
656
|
+
const label = resolved.label || humanize(lastSegment);
|
|
657
|
+
return { resolved, label };
|
|
658
|
+
}
|
|
613
659
|
function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
614
660
|
const record = state.fields.get(key);
|
|
615
661
|
const value = state.getValueAtPath(segments);
|
|
@@ -623,15 +669,15 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
623
669
|
if (blankForKey !== void 0) errors.push(...blankForKey);
|
|
624
670
|
if (userForKey !== void 0) errors.push(...userForKey);
|
|
625
671
|
const validating = (state.fieldValidationCounts.get(key) ?? 0) > 0;
|
|
672
|
+
const transforming = (state.fieldTransformCounts.get(key) ?? 0) > 0;
|
|
673
|
+
const transformError = state.transformErrors.get(key) ?? null;
|
|
626
674
|
const gated = state.pathHasAsyncValidation(segments) && !state.firstValidationDone.value;
|
|
627
675
|
const isOrphan = segments.length > 0 && !hasAtPath(state.form.value, segments) && isUnderStubAncestor(state, segments);
|
|
628
676
|
const valid = !gated && errors.length === 0 && !validating && !isOrphan;
|
|
629
677
|
const elementRecord = state.elements.get(key);
|
|
630
678
|
const elementsArr = elementRecord ? Object.freeze([...elementRecord.elements]) : EMPTY_ELEMENTS;
|
|
631
679
|
const firstElement = elementsArr[0] ?? null;
|
|
632
|
-
const resolved = state
|
|
633
|
-
const lastSegment = segments.length === 0 ? "" : segments[segments.length - 1] ?? "";
|
|
634
|
-
const label = resolved.label || humanize(lastSegment);
|
|
680
|
+
const { resolved, label } = resolveFieldMetaAndLabel(state, segments);
|
|
635
681
|
return {
|
|
636
682
|
value,
|
|
637
683
|
original,
|
|
@@ -649,6 +695,9 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
649
695
|
errors,
|
|
650
696
|
validating,
|
|
651
697
|
valid,
|
|
698
|
+
transforming,
|
|
699
|
+
busy: transforming || validating,
|
|
700
|
+
transformError,
|
|
652
701
|
path: segments,
|
|
653
702
|
...computeFieldIdentity(formInstanceId, state.formKey, key),
|
|
654
703
|
key: state.arrayElementKey(segments),
|
|
@@ -662,12 +711,14 @@ function buildLeafFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
662
711
|
function buildLeafFieldState(state, segments, key, formInstanceId, getFormMetaBase, getDisplayState) {
|
|
663
712
|
const base = buildLeafFieldStateBase(state, segments, key, formInstanceId);
|
|
664
713
|
const validatingSince = state.fieldValidatingSince.get(key) ?? null;
|
|
714
|
+
const transformingSince = state.fieldTransformingSince.get(key) ?? null;
|
|
665
715
|
return decorateWithDerivedProps(
|
|
666
716
|
base,
|
|
667
717
|
state,
|
|
668
718
|
getFormMetaBase,
|
|
669
719
|
key,
|
|
670
720
|
validatingSince,
|
|
721
|
+
transformingSince,
|
|
671
722
|
false,
|
|
672
723
|
// revealedDescendantError: leaves have no descendants
|
|
673
724
|
false,
|
|
@@ -690,6 +741,8 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
690
741
|
let connected = false;
|
|
691
742
|
let validating = false;
|
|
692
743
|
let validatingSince = null;
|
|
744
|
+
let transforming = false;
|
|
745
|
+
let transformingSince = null;
|
|
693
746
|
let updatedAt = null;
|
|
694
747
|
let asyncPending = false;
|
|
695
748
|
const submissionAttempts = state.submissionAttempts.value;
|
|
@@ -720,6 +773,13 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
720
773
|
if (leafGateOpen && since !== void 0 && (validatingSince === null || since < validatingSince))
|
|
721
774
|
validatingSince = since;
|
|
722
775
|
}
|
|
776
|
+
if ((state.fieldTransformCounts.get(leafKey) ?? 0) > 0) {
|
|
777
|
+
transforming = true;
|
|
778
|
+
const leafGateOpen = submissionAttempts > 0 || leafRecord?.blurredAfterInteraction === true;
|
|
779
|
+
const since = state.fieldTransformingSince.get(leafKey);
|
|
780
|
+
if (leafGateOpen && since !== void 0 && (transformingSince === null || since < transformingSince))
|
|
781
|
+
transformingSince = since;
|
|
782
|
+
}
|
|
723
783
|
if (state.pathHasAsyncValidationByKey(leafKey, entry.segments)) asyncPending = true;
|
|
724
784
|
const ts = leafRecord?.updatedAt;
|
|
725
785
|
if (ts !== void 0 && ts !== null) {
|
|
@@ -739,11 +799,22 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
739
799
|
return blurredLeafSegments.some((s) => paths.isPathPrefix(ePath, s));
|
|
740
800
|
});
|
|
741
801
|
if (!asyncPending && state.pathHasAsyncValidation(segments)) asyncPending = true;
|
|
802
|
+
if ((state.fieldValidationCounts.get(key) ?? 0) > 0) {
|
|
803
|
+
validating = true;
|
|
804
|
+
const since = state.fieldValidatingSince.get(key);
|
|
805
|
+
if (since !== void 0 && (validatingSince === null || since < validatingSince))
|
|
806
|
+
validatingSince = since;
|
|
807
|
+
}
|
|
808
|
+
if ((state.fieldTransformCounts.get(key) ?? 0) > 0) {
|
|
809
|
+
transforming = true;
|
|
810
|
+
const since = state.fieldTransformingSince.get(key);
|
|
811
|
+
if (since !== void 0 && (transformingSince === null || since < transformingSince))
|
|
812
|
+
transformingSince = since;
|
|
813
|
+
}
|
|
814
|
+
const ownTransformError = state.transformErrors.get(key) ?? null;
|
|
742
815
|
const gated = asyncPending && !state.firstValidationDone.value;
|
|
743
816
|
const valid = !gated && errors.length === 0 && !validating;
|
|
744
|
-
const resolved = state
|
|
745
|
-
const lastSegment = segments.length === 0 ? "" : segments[segments.length - 1] ?? "";
|
|
746
|
-
const label = resolved.label || humanize(lastSegment);
|
|
817
|
+
const { resolved, label } = resolveFieldMetaAndLabel(state, segments);
|
|
747
818
|
return {
|
|
748
819
|
base: {
|
|
749
820
|
value,
|
|
@@ -762,6 +833,12 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
762
833
|
errors,
|
|
763
834
|
validating,
|
|
764
835
|
valid,
|
|
836
|
+
transforming,
|
|
837
|
+
busy: transforming || validating,
|
|
838
|
+
// A container surfaces its OWN transform failure (a transform registered
|
|
839
|
+
// on the container path, e.g. a file normalizer) but never rolls up a
|
|
840
|
+
// descendant leaf's failure — that stays a per-field channel.
|
|
841
|
+
transformError: ownTransformError,
|
|
765
842
|
path: segments,
|
|
766
843
|
...computeFieldIdentity(formInstanceId, state.formKey, key),
|
|
767
844
|
key: state.arrayElementKey(segments),
|
|
@@ -772,28 +849,25 @@ function buildContainerFieldStateBase(state, segments, key, formInstanceId) {
|
|
|
772
849
|
meta: resolved.meta
|
|
773
850
|
},
|
|
774
851
|
validatingSince,
|
|
852
|
+
transformingSince,
|
|
775
853
|
revealedDescendantError
|
|
776
854
|
};
|
|
777
855
|
}
|
|
778
856
|
function buildContainerFieldState(state, segments, key, formInstanceId, getFormMetaBase, getDisplayState) {
|
|
779
|
-
const { base, validatingSince, revealedDescendantError } = buildContainerFieldStateBase(
|
|
780
|
-
state,
|
|
781
|
-
segments,
|
|
782
|
-
key,
|
|
783
|
-
formInstanceId
|
|
784
|
-
);
|
|
857
|
+
const { base, validatingSince, transformingSince, revealedDescendantError } = buildContainerFieldStateBase(state, segments, key, formInstanceId);
|
|
785
858
|
return decorateWithDerivedProps(
|
|
786
859
|
base,
|
|
787
860
|
state,
|
|
788
861
|
getFormMetaBase,
|
|
789
862
|
key,
|
|
790
863
|
validatingSince,
|
|
864
|
+
transformingSince,
|
|
791
865
|
revealedDescendantError,
|
|
792
866
|
segments.length === 0,
|
|
793
867
|
getDisplayState
|
|
794
868
|
);
|
|
795
869
|
}
|
|
796
|
-
function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingSince, revealedDescendantError, isRoot, getDisplayState) {
|
|
870
|
+
function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingSince, transformingSince, revealedDescendantError, isRoot, getDisplayState) {
|
|
797
871
|
const firstError = base.errors[0];
|
|
798
872
|
const predicate = getDisplayState ?? state.getDisplayState;
|
|
799
873
|
const formMeta = getFormMetaBase();
|
|
@@ -801,6 +875,7 @@ function decorateWithDerivedProps(base, state, getFormMetaBase, key, validatingS
|
|
|
801
875
|
field: base,
|
|
802
876
|
formMeta,
|
|
803
877
|
validatingSince,
|
|
878
|
+
transformingSince,
|
|
804
879
|
// The engine's clock. Frozen to 0 under SSR (no clock, nothing in
|
|
805
880
|
// flight) so the reducer returns the plain verdict and hydration matches.
|
|
806
881
|
now: state.ssr ? 0 : Date.now()
|
|
@@ -867,6 +942,15 @@ function liveKeysAtPath(state, segments) {
|
|
|
867
942
|
if (typeof value === "object") return Object.keys(value);
|
|
868
943
|
return [];
|
|
869
944
|
}
|
|
945
|
+
function liveContainerHasKey(state, segments, key) {
|
|
946
|
+
const value = getAtPath(state.form.value, segments);
|
|
947
|
+
if (value === null || value === void 0 || typeof value !== "object") return false;
|
|
948
|
+
if (Array.isArray(value)) {
|
|
949
|
+
const index = Number(key);
|
|
950
|
+
return Number.isInteger(index) && index >= 0 && index < value.length && String(index) === key;
|
|
951
|
+
}
|
|
952
|
+
return Object.hasOwn(value, key);
|
|
953
|
+
}
|
|
870
954
|
function isArrayPath(state, segments) {
|
|
871
955
|
if (segments.length === 0) return false;
|
|
872
956
|
return Array.isArray(getAtPath(state.form.value, segments));
|
|
@@ -895,6 +979,21 @@ const INTEGER_SEGMENT = /^(?:0|[1-9]\d*)$/;
|
|
|
895
979
|
function keyToSegment(key) {
|
|
896
980
|
return INTEGER_SEGMENT.test(key) ? Number(key) : key;
|
|
897
981
|
}
|
|
982
|
+
function callableInvokeShim(method, surface, getDescent) {
|
|
983
|
+
const fnMethod = Reflect.get(Function.prototype, method);
|
|
984
|
+
return new Proxy((() => {
|
|
985
|
+
}), {
|
|
986
|
+
apply: (_target, _thisArg, args) => Reflect.apply(fnMethod, surface, args),
|
|
987
|
+
get: (_target, key) => Reflect.get(getDescent(), key),
|
|
988
|
+
has: (_target, key) => Reflect.has(getDescent(), key),
|
|
989
|
+
ownKeys: () => Reflect.ownKeys(getDescent()),
|
|
990
|
+
getOwnPropertyDescriptor: (_target, key) => {
|
|
991
|
+
const descriptor = Reflect.getOwnPropertyDescriptor(getDescent(), key);
|
|
992
|
+
if (descriptor !== void 0) descriptor.configurable = true;
|
|
993
|
+
return descriptor;
|
|
994
|
+
}
|
|
995
|
+
});
|
|
996
|
+
}
|
|
898
997
|
function buildSurfaceProxy(opts) {
|
|
899
998
|
const containerCache = /* @__PURE__ */ new Map();
|
|
900
999
|
const leafViewCache = /* @__PURE__ */ new Map();
|
|
@@ -921,6 +1020,8 @@ function buildSurfaceProxy(opts) {
|
|
|
921
1020
|
const cacheKey = `${JSON.stringify(segments)}+${isArrayLike ? "A" : "O"}`;
|
|
922
1021
|
const existing = containerCache.get(cacheKey);
|
|
923
1022
|
if (existing !== void 0) return existing;
|
|
1023
|
+
const isFixedObject = opts.schema.isFixedObjectAtPath(segments);
|
|
1024
|
+
const containerHasKey = (k) => opts.containerHasOwnKey !== void 0 ? opts.containerHasOwnKey(segments, k) : opts.containerOwnKeys?.(segments).includes(k) === true;
|
|
924
1025
|
const snapshotContainer = () => opts.materializeContainer === void 0 ? {} : opts.materializeContainer(segments);
|
|
925
1026
|
const {
|
|
926
1027
|
toString: containerToString,
|
|
@@ -928,8 +1029,9 @@ function buildSurfaceProxy(opts) {
|
|
|
928
1029
|
toJSON: containerToJSON,
|
|
929
1030
|
toPrimitive: containerToPrimitive
|
|
930
1031
|
} = makeReadonlyCoercion(snapshotContainer);
|
|
931
|
-
const
|
|
932
|
-
|
|
1032
|
+
const isRoot = segments.length === 0;
|
|
1033
|
+
const target = isRoot ? (() => {
|
|
1034
|
+
}) : isArrayLike ? [] : {};
|
|
933
1035
|
const proxy = new Proxy(target, {
|
|
934
1036
|
apply(_, __, args) {
|
|
935
1037
|
const arg = args[0];
|
|
@@ -960,7 +1062,16 @@ function buildSurfaceProxy(opts) {
|
|
|
960
1062
|
return key === "toString" ? containerToString : containerValueOf;
|
|
961
1063
|
}
|
|
962
1064
|
}
|
|
963
|
-
|
|
1065
|
+
if (key === "hasOwnProperty" && !schemaHasPath(childSegs)) {
|
|
1066
|
+
return Object.prototype.hasOwnProperty;
|
|
1067
|
+
}
|
|
1068
|
+
if (isRoot && (key === "call" || key === "apply" || key === "bind")) {
|
|
1069
|
+
return callableInvokeShim(key, proxy, () => descendOrTerminate(childSegs));
|
|
1070
|
+
}
|
|
1071
|
+
if (opts.isTerminalAt?.(childSegs) === true || isFixedObject && schemaHasPath(childSegs) || containerHasKey(key)) {
|
|
1072
|
+
return descendOrTerminate(childSegs);
|
|
1073
|
+
}
|
|
1074
|
+
return void 0;
|
|
964
1075
|
},
|
|
965
1076
|
has(_, key) {
|
|
966
1077
|
if (typeof key === "symbol") return Reflect.has(target, key);
|
|
@@ -1045,15 +1156,8 @@ function buildSurfaceProxy(opts) {
|
|
|
1045
1156
|
toJSON: leafToJSONHandler,
|
|
1046
1157
|
toPrimitive: leafToPrimitive
|
|
1047
1158
|
} = makeReadonlyCoercion(snapshotLeaf);
|
|
1048
|
-
const target =
|
|
1049
|
-
});
|
|
1159
|
+
const target = {};
|
|
1050
1160
|
const proxy = new Proxy(target, {
|
|
1051
|
-
apply(_, __, args) {
|
|
1052
|
-
const arg = args[0];
|
|
1053
|
-
if (arg === void 0) return opts.resolveCallTarget(segments);
|
|
1054
|
-
const { segments: argSegs } = paths.canonicalizePath(arg);
|
|
1055
|
-
return opts.resolveCallTarget(argSegs);
|
|
1056
|
-
},
|
|
1057
1161
|
get(_, key) {
|
|
1058
1162
|
if (typeof key === "symbol") {
|
|
1059
1163
|
if (key === Symbol.toPrimitive) return leafToPrimitive;
|
|
@@ -1063,6 +1167,9 @@ function buildSurfaceProxy(opts) {
|
|
|
1063
1167
|
if (key === "toString") return leafToString;
|
|
1064
1168
|
if (key === "valueOf") return leafValueOf;
|
|
1065
1169
|
if (key === "toJSON") return leafToJSONHandler;
|
|
1170
|
+
if (key === "hasOwnProperty" && !schemaHasPath([...segments, keyToSegment(key)])) {
|
|
1171
|
+
return Object.prototype.hasOwnProperty;
|
|
1172
|
+
}
|
|
1066
1173
|
if (leafKeys.has(key)) {
|
|
1067
1174
|
const leaf = opts.resolveLeaf(segments);
|
|
1068
1175
|
return readLeafKey(leaf, key);
|
|
@@ -1075,8 +1182,8 @@ function buildSurfaceProxy(opts) {
|
|
|
1075
1182
|
return true;
|
|
1076
1183
|
},
|
|
1077
1184
|
// Iteration: leaf-views expose the leaf-key set so
|
|
1078
|
-
// `
|
|
1079
|
-
//
|
|
1185
|
+
// `Object.keys(form.fields.email)` / spread enumerate the
|
|
1186
|
+
// FieldState props. (`JSON.stringify` routes through `toJSON` above.)
|
|
1080
1187
|
ownKeys: () => Array.from(leafKeys),
|
|
1081
1188
|
getOwnPropertyDescriptor(_, key) {
|
|
1082
1189
|
if (typeof key !== "string") return void 0;
|
|
@@ -1185,6 +1292,12 @@ function buildErrorsProxy(state) {
|
|
|
1185
1292
|
// library-produced verdicts (schema + derived-blank) at unreachable
|
|
1186
1293
|
// paths stay hidden; user-supplied errors are unconditional.
|
|
1187
1294
|
containerOwnKeys: (segments) => errorAwareContainerKeys(state, segments),
|
|
1295
|
+
// Fast path: a key the live form data holds short-circuits before the
|
|
1296
|
+
// O(n) error-store scan, so iterating `form.errors.<array>` over live
|
|
1297
|
+
// indices stays linear. The scan still runs for a key with no live
|
|
1298
|
+
// home — a server error at a non-schema key (`form.errors.ghost`) —
|
|
1299
|
+
// so it keeps surfacing while a genuinely-absent key reads undefined.
|
|
1300
|
+
containerHasOwnKey: (segments, key) => liveContainerHasKey(state, segments, key) || errorAwareContainerKeys(state, segments).includes(key),
|
|
1188
1301
|
isArrayContainer: (segments) => isArrayPath(state, segments)
|
|
1189
1302
|
});
|
|
1190
1303
|
}
|
|
@@ -1358,6 +1471,9 @@ const FIELD_STATE_KEYS = /* @__PURE__ */ new Set([
|
|
|
1358
1471
|
"errors",
|
|
1359
1472
|
"validating",
|
|
1360
1473
|
"valid",
|
|
1474
|
+
"transforming",
|
|
1475
|
+
"busy",
|
|
1476
|
+
"transformError",
|
|
1361
1477
|
"displayState",
|
|
1362
1478
|
"showErrors",
|
|
1363
1479
|
"showPending",
|
|
@@ -1460,33 +1576,41 @@ function buildFieldStateProxy(state, formInstanceId, getFormMetaBase, options) {
|
|
|
1460
1576
|
terminalCache.set(cacheKey, proxy);
|
|
1461
1577
|
return proxy;
|
|
1462
1578
|
}
|
|
1579
|
+
const surfaceSchema = state.schema;
|
|
1463
1580
|
return buildSurfaceProxy({
|
|
1464
|
-
schema:
|
|
1581
|
+
schema: surfaceSchema,
|
|
1465
1582
|
resolveLeaf: (path) => getFieldStateAt(path),
|
|
1466
1583
|
leafKeys: FIELD_STATE_KEYS,
|
|
1467
1584
|
readLeafKey: (computed, key) => computed.value[key],
|
|
1468
1585
|
materializeContainer: (segments) => materializeFields(state, segments, snapshotFieldStateAt),
|
|
1469
|
-
|
|
1586
|
+
// `form.fields(path)` resolves a FieldState for any path the SCHEMA
|
|
1587
|
+
// declares — a leaf, a container, an inactive discriminated-union
|
|
1588
|
+
// variant key, or an out-of-bounds array index (the element schema
|
|
1589
|
+
// admits any index). A path the schema doesn't have is a typo, not a
|
|
1590
|
+
// field, so it reads `undefined` rather than a phantom stub. The
|
|
1591
|
+
// empty path (`form.fields()`) is the root object, always valid.
|
|
1592
|
+
resolveCallTarget: (path) => surfaceSchema.getSlimPrimitiveTypesAtPath(path).size > 0 ? fieldStateTerminalAt(path) : void 0,
|
|
1470
1593
|
containerOwnKeys: (segments) => liveKeysAtPath(state, segments),
|
|
1594
|
+
containerHasOwnKey: (segments, key) => liveContainerHasKey(state, segments, key),
|
|
1471
1595
|
isArrayContainer: (segments) => isArrayPath(state, segments)
|
|
1472
1596
|
});
|
|
1473
1597
|
}
|
|
1474
1598
|
function materializeFields(state, containerSegments, snapshotFieldStateAt) {
|
|
1475
1599
|
const liveValue = getAtPath(state.form.value, containerSegments);
|
|
1476
|
-
return walk$
|
|
1600
|
+
return walk$1(liveValue, containerSegments, state.schema, snapshotFieldStateAt);
|
|
1477
1601
|
}
|
|
1478
|
-
function walk$
|
|
1602
|
+
function walk$1(value, basePath, schema, snapshotFieldStateAt) {
|
|
1479
1603
|
if (schema.isLeafAtPath(basePath)) return snapshotFieldStateAt(basePath);
|
|
1480
1604
|
if (value === null || value === void 0) return value;
|
|
1481
1605
|
if (typeof value !== "object") {
|
|
1482
1606
|
return value;
|
|
1483
1607
|
}
|
|
1484
1608
|
if (Array.isArray(value)) {
|
|
1485
|
-
return value.map((_, i) => walk$
|
|
1609
|
+
return value.map((_, i) => walk$1(value[i], [...basePath, i], schema, snapshotFieldStateAt));
|
|
1486
1610
|
}
|
|
1487
1611
|
const result = {};
|
|
1488
1612
|
for (const key of Object.keys(value)) {
|
|
1489
|
-
result[key] = walk$
|
|
1613
|
+
result[key] = walk$1(
|
|
1490
1614
|
value[key],
|
|
1491
1615
|
[...basePath, key],
|
|
1492
1616
|
schema,
|
|
@@ -1570,47 +1694,42 @@ function mergeDeep(target, source, path, schema) {
|
|
|
1570
1694
|
if (!isPlainRecord(source)) return source;
|
|
1571
1695
|
if (schema !== void 0) {
|
|
1572
1696
|
const du = schema.getUnionDiscriminatorAtPath(path);
|
|
1573
|
-
if (du !== void 0)
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
out2,
|
|
1587
|
-
key,
|
|
1588
|
-
mergeDeep(
|
|
1589
|
-
safeOwnRead(out2, key),
|
|
1590
|
-
safeOwnRead(sourceRecord, key),
|
|
1591
|
-
[...path, key],
|
|
1592
|
-
schema
|
|
1593
|
-
)
|
|
1594
|
-
);
|
|
1595
|
-
}
|
|
1596
|
-
return out2;
|
|
1597
|
-
}
|
|
1598
|
-
}
|
|
1599
|
-
return {};
|
|
1697
|
+
if (du !== void 0) return mergeDuAwareKeys(source, path, schema, du);
|
|
1698
|
+
}
|
|
1699
|
+
return mergeObjectKeys(target, source, path, schema);
|
|
1700
|
+
}
|
|
1701
|
+
function mergeDuAwareKeys(source, path, schema, du) {
|
|
1702
|
+
const sourceDisc = source[du.discriminatorKey];
|
|
1703
|
+
if (sourceDisc !== void 0 && !du.isVariantSelected(sourceDisc)) {
|
|
1704
|
+
return { [du.discriminatorKey]: sourceDisc };
|
|
1705
|
+
}
|
|
1706
|
+
if (sourceDisc !== void 0) {
|
|
1707
|
+
const variantDefault = du.getVariantDefault(sourceDisc);
|
|
1708
|
+
if (isPlainRecord(variantDefault)) {
|
|
1709
|
+
return mergeVariantKeys(source, variantDefault, path, schema, du);
|
|
1600
1710
|
}
|
|
1601
1711
|
}
|
|
1602
|
-
|
|
1603
|
-
|
|
1712
|
+
return {};
|
|
1713
|
+
}
|
|
1714
|
+
function mergeVariantKeys(source, variantDefault, path, schema, du) {
|
|
1715
|
+
const out = { ...variantDefault };
|
|
1604
1716
|
for (const key of Object.keys(source)) {
|
|
1717
|
+
if (!safeOwnHas(variantDefault, key) && key !== du.discriminatorKey) continue;
|
|
1605
1718
|
safeAssign(
|
|
1606
1719
|
out,
|
|
1607
1720
|
key,
|
|
1608
|
-
mergeDeep(
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1721
|
+
mergeDeep(safeOwnRead(out, key), safeOwnRead(source, key), [...path, key], schema)
|
|
1722
|
+
);
|
|
1723
|
+
}
|
|
1724
|
+
return out;
|
|
1725
|
+
}
|
|
1726
|
+
function mergeObjectKeys(target, source, path, schema) {
|
|
1727
|
+
const out = isPlainRecord(target) ? { ...target } : {};
|
|
1728
|
+
for (const key of Object.keys(source)) {
|
|
1729
|
+
safeAssign(
|
|
1730
|
+
out,
|
|
1731
|
+
key,
|
|
1732
|
+
mergeDeep(safeOwnRead(out, key), safeOwnRead(source, key), [...path, key], schema)
|
|
1614
1733
|
);
|
|
1615
1734
|
}
|
|
1616
1735
|
return out;
|
|
@@ -1743,7 +1862,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
1743
1862
|
if (!result.ok) return result.error;
|
|
1744
1863
|
return stripData(composeWithDerivedBlank(result.refinement, result.segments));
|
|
1745
1864
|
}
|
|
1746
|
-
async function
|
|
1865
|
+
async function parse(pathInput) {
|
|
1747
1866
|
const result = await runImperativeValidation(pathInput, {
|
|
1748
1867
|
cancelInFlight: false,
|
|
1749
1868
|
commitToSchemaErrors: false
|
|
@@ -1796,6 +1915,8 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
1796
1915
|
state.activeSubmissions.value += 1;
|
|
1797
1916
|
state.submitting.value = true;
|
|
1798
1917
|
state.submitError.value = null;
|
|
1918
|
+
state.clearUserErrors();
|
|
1919
|
+
while (state.activeTransforms.value > 0) await state.settleTransforms();
|
|
1799
1920
|
state.cancelFieldValidation();
|
|
1800
1921
|
state.displayEngine.clear();
|
|
1801
1922
|
state.activeValidations.value += 1;
|
|
@@ -1834,9 +1955,8 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
1834
1955
|
state.emitSubmitSuccess();
|
|
1835
1956
|
} catch (err) {
|
|
1836
1957
|
if (state.submissionGeneration.value === genAtEntry) {
|
|
1837
|
-
state.submitError.value = err;
|
|
1958
|
+
state.submitError.value = paths.toError(err);
|
|
1838
1959
|
}
|
|
1839
|
-
throw err;
|
|
1840
1960
|
} finally {
|
|
1841
1961
|
if (!validationSettled) {
|
|
1842
1962
|
state.activeValidations.value = Math.max(0, state.activeValidations.value - 1);
|
|
@@ -1850,7 +1970,7 @@ function buildProcessForm(state, formInstanceId, options = {}) {
|
|
|
1850
1970
|
};
|
|
1851
1971
|
return submitHandler;
|
|
1852
1972
|
};
|
|
1853
|
-
return { validate, validateAsync,
|
|
1973
|
+
return { validate, validateAsync, parse, handleSubmit };
|
|
1854
1974
|
}
|
|
1855
1975
|
function toSegments(pathInput) {
|
|
1856
1976
|
return paths.canonicalizePath(pathInput).segments;
|
|
@@ -1908,6 +2028,33 @@ function applyInvalidSubmitPolicy(state, formInstanceId, policy) {
|
|
|
1908
2028
|
target.element.focus({ preventScroll: true });
|
|
1909
2029
|
}
|
|
1910
2030
|
|
|
2031
|
+
function captureUserCallSite() {
|
|
2032
|
+
const raw = new Error().stack;
|
|
2033
|
+
if (typeof raw !== "string") return void 0;
|
|
2034
|
+
const lines = raw.split("\n");
|
|
2035
|
+
for (let i = 1; i < lines.length; i++) {
|
|
2036
|
+
const frame = lines[i];
|
|
2037
|
+
if (frame === void 0) continue;
|
|
2038
|
+
if (/attaform[/-]forms?/i.test(frame)) continue;
|
|
2039
|
+
if (/\bforms\.[A-Za-z0-9_-]+\.m?js\b/.test(frame)) continue;
|
|
2040
|
+
const trimmed = frame.trim();
|
|
2041
|
+
if (trimmed.length === 0) continue;
|
|
2042
|
+
return shortenSourceFrame(trimmed);
|
|
2043
|
+
}
|
|
2044
|
+
return void 0;
|
|
2045
|
+
}
|
|
2046
|
+
function shortenSourceFrame(frame) {
|
|
2047
|
+
const match = /(?:^|\s|\()([^\s()]+):(\d+):\d+\)?$/.exec(frame);
|
|
2048
|
+
if (match === null) return frame;
|
|
2049
|
+
const [, urlOrPath, line] = match;
|
|
2050
|
+
if (urlOrPath === void 0 || line === void 0) return frame;
|
|
2051
|
+
let path = urlOrPath;
|
|
2052
|
+
path = path.replace(/^[a-z]+:\/\/[^/]+\//i, "");
|
|
2053
|
+
path = path.replace(/^_nuxt\//, "");
|
|
2054
|
+
path = path.replace(/^\//, "");
|
|
2055
|
+
return `(${path}:${line})`;
|
|
2056
|
+
}
|
|
2057
|
+
|
|
1911
2058
|
function extractSchemaFields(schema) {
|
|
1912
2059
|
try {
|
|
1913
2060
|
const root = schema.getDefaultAtPath([]);
|
|
@@ -1966,9 +2113,9 @@ function isLeafValue(value) {
|
|
|
1966
2113
|
return true;
|
|
1967
2114
|
}
|
|
1968
2115
|
function isSlimPrimitiveValid(schema, store, path, value) {
|
|
1969
|
-
return walk
|
|
2116
|
+
return walk(schema, store, path, value);
|
|
1970
2117
|
}
|
|
1971
|
-
function walk
|
|
2118
|
+
function walk(schema, store, path, value) {
|
|
1972
2119
|
if (schema.isPreprocessOrCoerceLeaf(path)) return true;
|
|
1973
2120
|
const accepted = schema.getSlimPrimitiveTypesAtPath(path);
|
|
1974
2121
|
const kind = isLeafValue(value) ? slimKindOf(value) : Array.isArray(value) ? "array" : "object";
|
|
@@ -1978,13 +2125,13 @@ function walk$1(schema, store, path, value) {
|
|
|
1978
2125
|
}
|
|
1979
2126
|
if (Array.isArray(value)) {
|
|
1980
2127
|
for (let i = 0; i < value.length; i++) {
|
|
1981
|
-
if (!walk
|
|
2128
|
+
if (!walk(schema, store, [...path, i], value[i])) return false;
|
|
1982
2129
|
}
|
|
1983
2130
|
return true;
|
|
1984
2131
|
}
|
|
1985
2132
|
if (isPlainRecord(value)) {
|
|
1986
2133
|
for (const key of Object.keys(value)) {
|
|
1987
|
-
if (!walk
|
|
2134
|
+
if (!walk(schema, store, [...path, key], value[key])) {
|
|
1988
2135
|
return false;
|
|
1989
2136
|
}
|
|
1990
2137
|
}
|
|
@@ -2272,7 +2419,7 @@ function buildRegister(state, formInstanceId, instanceConfig) {
|
|
|
2272
2419
|
throw new paths.AnonPersistError({
|
|
2273
2420
|
cause: "register-without-config",
|
|
2274
2421
|
schemaFields: extractSchemaFields(state.schema),
|
|
2275
|
-
callSite:
|
|
2422
|
+
callSite: captureUserCallSite()
|
|
2276
2423
|
});
|
|
2277
2424
|
}
|
|
2278
2425
|
const { aria } = computeFieldIdentity(formInstanceId, state.formKey, pathKey);
|
|
@@ -2323,6 +2470,23 @@ function buildRegister(state, formInstanceId, instanceConfig) {
|
|
|
2323
2470
|
markConnectedOptimistically: () => {
|
|
2324
2471
|
state.markConnectedOptimistically(segments);
|
|
2325
2472
|
},
|
|
2473
|
+
// --- Async transform lifecycle (internal; the directive's
|
|
2474
|
+
// deferred orchestrator is the only legitimate consumer). Thin
|
|
2475
|
+
// path-bound delegates to the store's per-path token / counter
|
|
2476
|
+
// machinery — same pattern as `markBlank` / `setValueWithInternalPath`,
|
|
2477
|
+
// so the directive (which holds only this RegisterValue, never the
|
|
2478
|
+
// store) can drive the busy/discard/error bookkeeping. ---
|
|
2479
|
+
beginTransform: (holder) => state.beginTransform(pathKey, holder),
|
|
2480
|
+
isCurrentTransform: (token) => state.isCurrentTransform(pathKey, token),
|
|
2481
|
+
endTransform: (token) => state.endTransform(pathKey, token),
|
|
2482
|
+
setTransformError: (err) => state.setTransformError(pathKey, err),
|
|
2483
|
+
// Synchronous read of "is a transform in flight at this path". The
|
|
2484
|
+
// orchestrator's `beginTransform` bumps the count before the
|
|
2485
|
+
// listener's force-sync block runs, so the directive reads this to
|
|
2486
|
+
// skip reverting the DOM to stale storage mid-flight.
|
|
2487
|
+
get transforming() {
|
|
2488
|
+
return (state.fieldTransformCounts.get(pathKey) ?? 0) > 0;
|
|
2489
|
+
},
|
|
2326
2490
|
path: pathKey,
|
|
2327
2491
|
// Frozen so a wrapper component can pass `rv.segments` directly
|
|
2328
2492
|
// to `form.fields(...)` without defensive copying — and so test
|
|
@@ -2367,49 +2531,60 @@ function walkUnsetSentinels(values, schema) {
|
|
|
2367
2531
|
walkUnspecified(rootSlim, [], paths);
|
|
2368
2532
|
return { cleanedValues: void 0, paths };
|
|
2369
2533
|
}
|
|
2370
|
-
const cleaned =
|
|
2534
|
+
const cleaned = walkCore(values, [], schema, paths, true);
|
|
2371
2535
|
return { cleanedValues: cleaned, paths };
|
|
2372
2536
|
}
|
|
2373
|
-
function
|
|
2537
|
+
function isOpaqueLeaf(value) {
|
|
2538
|
+
return value instanceof Date || value instanceof RegExp || value instanceof Map || value instanceof Set || typeof value === "function";
|
|
2539
|
+
}
|
|
2540
|
+
function walkCore(input, segments, schema, paths, synthesizeSchemaKeys) {
|
|
2374
2541
|
if (isUnset(input)) {
|
|
2375
2542
|
return expandUnsetAt(segments, schema, paths);
|
|
2376
2543
|
}
|
|
2377
2544
|
if (input === void 0) {
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
if (input instanceof Date || input instanceof RegExp || input instanceof Map || input instanceof Set || typeof input === "function") {
|
|
2545
|
+
if (synthesizeSchemaKeys) {
|
|
2546
|
+
const slim = schema.getDefaultAtPath(segments);
|
|
2547
|
+
return walkUnspecified(slim, segments, paths);
|
|
2548
|
+
}
|
|
2383
2549
|
return input;
|
|
2384
2550
|
}
|
|
2551
|
+
if (input === null) return null;
|
|
2552
|
+
if (isOpaqueLeaf(input)) return input;
|
|
2385
2553
|
if (Array.isArray(input)) {
|
|
2386
2554
|
const out = new Array(input.length);
|
|
2387
2555
|
let mutated = false;
|
|
2388
2556
|
for (let i = 0; i < input.length; i++) {
|
|
2389
|
-
const walked =
|
|
2557
|
+
const walked = walkCore(input[i], [...segments, i], schema, paths, synthesizeSchemaKeys);
|
|
2390
2558
|
out[i] = walked;
|
|
2391
2559
|
if (walked !== input[i]) mutated = true;
|
|
2392
2560
|
}
|
|
2393
2561
|
return mutated ? out : input;
|
|
2394
2562
|
}
|
|
2395
2563
|
if (typeof input === "object") {
|
|
2396
|
-
const
|
|
2397
|
-
const inputKeys = Object.keys(
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2564
|
+
const obj = input;
|
|
2565
|
+
const inputKeys = Object.keys(obj);
|
|
2566
|
+
let keys = inputKeys;
|
|
2567
|
+
let mutated = false;
|
|
2568
|
+
let inputKeysSet = null;
|
|
2569
|
+
if (synthesizeSchemaKeys) {
|
|
2570
|
+
inputKeysSet = new Set(inputKeys);
|
|
2571
|
+
const allKeys = new Set(inputKeys);
|
|
2572
|
+
const slim = schema.getDefaultAtPath(segments);
|
|
2573
|
+
if (slim !== null && slim !== void 0 && typeof slim === "object" && !Array.isArray(slim) && !isOpaqueLeaf(slim)) {
|
|
2574
|
+
for (const k of Object.keys(slim)) allKeys.add(k);
|
|
2575
|
+
}
|
|
2576
|
+
keys = allKeys;
|
|
2577
|
+
mutated = allKeys.size !== inputKeys.length;
|
|
2402
2578
|
}
|
|
2403
2579
|
const out = {};
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
if (orig === void 0 && inputKeysSet.has(key)) {
|
|
2580
|
+
for (const key of keys) {
|
|
2581
|
+
const orig = obj[key];
|
|
2582
|
+
if (synthesizeSchemaKeys && orig === void 0 && inputKeysSet?.has(key) === true) {
|
|
2408
2583
|
safeAssign(out, key, void 0);
|
|
2409
2584
|
mutated = true;
|
|
2410
2585
|
continue;
|
|
2411
2586
|
}
|
|
2412
|
-
const walked =
|
|
2587
|
+
const walked = walkCore(orig, [...segments, key], schema, paths, synthesizeSchemaKeys);
|
|
2413
2588
|
safeAssign(out, key, walked);
|
|
2414
2589
|
if (walked !== orig) mutated = true;
|
|
2415
2590
|
}
|
|
@@ -2424,7 +2599,7 @@ function walkUnspecified(slim, segments, paths$1) {
|
|
|
2424
2599
|
}
|
|
2425
2600
|
return slim;
|
|
2426
2601
|
}
|
|
2427
|
-
if (slim
|
|
2602
|
+
if (isOpaqueLeaf(slim)) {
|
|
2428
2603
|
return slim;
|
|
2429
2604
|
}
|
|
2430
2605
|
if (Array.isArray(slim)) return slim;
|
|
@@ -2443,40 +2618,9 @@ function walkUnspecified(slim, segments, paths$1) {
|
|
|
2443
2618
|
}
|
|
2444
2619
|
function substituteUnsetSentinels(value, prefix, schema) {
|
|
2445
2620
|
const paths = [];
|
|
2446
|
-
const cleaned =
|
|
2621
|
+
const cleaned = walkCore(value, [...prefix], schema, paths, false);
|
|
2447
2622
|
return { cleanedValues: cleaned, paths };
|
|
2448
2623
|
}
|
|
2449
|
-
function substitute(input, segments, schema, paths) {
|
|
2450
|
-
if (isUnset(input)) {
|
|
2451
|
-
return expandUnsetAt(segments, schema, paths);
|
|
2452
|
-
}
|
|
2453
|
-
if (input === void 0 || input === null) return input;
|
|
2454
|
-
if (input instanceof Date || input instanceof RegExp || input instanceof Map || input instanceof Set || typeof input === "function") {
|
|
2455
|
-
return input;
|
|
2456
|
-
}
|
|
2457
|
-
if (Array.isArray(input)) {
|
|
2458
|
-
let mutated = false;
|
|
2459
|
-
const out = new Array(input.length);
|
|
2460
|
-
for (let i = 0; i < input.length; i++) {
|
|
2461
|
-
const walked = substitute(input[i], [...segments, i], schema, paths);
|
|
2462
|
-
out[i] = walked;
|
|
2463
|
-
if (walked !== input[i]) mutated = true;
|
|
2464
|
-
}
|
|
2465
|
-
return mutated ? out : input;
|
|
2466
|
-
}
|
|
2467
|
-
if (typeof input === "object") {
|
|
2468
|
-
let mutated = false;
|
|
2469
|
-
const out = {};
|
|
2470
|
-
for (const key of Object.keys(input)) {
|
|
2471
|
-
const orig = input[key];
|
|
2472
|
-
const walked = substitute(orig, [...segments, key], schema, paths);
|
|
2473
|
-
safeAssign(out, key, walked);
|
|
2474
|
-
if (walked !== orig) mutated = true;
|
|
2475
|
-
}
|
|
2476
|
-
return mutated ? out : input;
|
|
2477
|
-
}
|
|
2478
|
-
return input;
|
|
2479
|
-
}
|
|
2480
2624
|
function isPrimitiveOrEmpty(value) {
|
|
2481
2625
|
if (value === null || value === void 0) return true;
|
|
2482
2626
|
const t = typeof value;
|
|
@@ -2506,7 +2650,7 @@ function expandUnsetAt(segments, schema, paths$1) {
|
|
|
2506
2650
|
paths$1.push(paths.canonicalizePath(segments).key);
|
|
2507
2651
|
return slim;
|
|
2508
2652
|
}
|
|
2509
|
-
if (slim
|
|
2653
|
+
if (isOpaqueLeaf(slim)) {
|
|
2510
2654
|
paths$1.push(paths.canonicalizePath(segments).key);
|
|
2511
2655
|
return slim;
|
|
2512
2656
|
}
|
|
@@ -2521,7 +2665,9 @@ function expandUnsetAt(segments, schema, paths$1) {
|
|
|
2521
2665
|
function buildCallableReadonlySnapshotProxy(opts) {
|
|
2522
2666
|
const target = (() => {
|
|
2523
2667
|
});
|
|
2524
|
-
const { toString, valueOf, toJSON, toPrimitive } = makeReadonlyCoercion(
|
|
2668
|
+
const { toString, valueOf, toJSON, toPrimitive } = makeReadonlyCoercion(
|
|
2669
|
+
opts.coercionSnapshot ?? opts.snapshot
|
|
2670
|
+
);
|
|
2525
2671
|
const callResolve = opts.resolveCall ?? ((arg) => opts.resolveKey(String(arg)));
|
|
2526
2672
|
return new Proxy(target, {
|
|
2527
2673
|
apply(_, __, args) {
|
|
@@ -2570,27 +2716,52 @@ function buildCallableReadonlySnapshotProxy(opts) {
|
|
|
2570
2716
|
});
|
|
2571
2717
|
}
|
|
2572
2718
|
|
|
2719
|
+
function materializeFormValue(node) {
|
|
2720
|
+
if (node === null || typeof node !== "object") return node;
|
|
2721
|
+
if (Array.isArray(node)) {
|
|
2722
|
+
const out2 = new Array(node.length);
|
|
2723
|
+
for (let i = 0; i < node.length; i++) out2[i] = materializeFormValue(node[i]);
|
|
2724
|
+
return out2;
|
|
2725
|
+
}
|
|
2726
|
+
if (!isPlainRecord(node)) return vue.toRaw(node);
|
|
2727
|
+
const rec = node;
|
|
2728
|
+
const out = {};
|
|
2729
|
+
for (const key of Object.keys(rec)) {
|
|
2730
|
+
safeAssign(out, key, materializeFormValue(safeOwnRead(rec, key)));
|
|
2731
|
+
}
|
|
2732
|
+
return out;
|
|
2733
|
+
}
|
|
2573
2734
|
function buildValuesProxy(form) {
|
|
2574
2735
|
const inner = vue.computed(() => vue.readonly(form.value));
|
|
2575
2736
|
return buildCallableReadonlySnapshotProxy({
|
|
2576
2737
|
surface: "form.values",
|
|
2577
2738
|
snapshot: () => inner.value,
|
|
2739
|
+
// Faithful, reactivity-preserving serialisation: walk the reactive
|
|
2740
|
+
// proxy with own-safe reads so `JSON.stringify(form.values)` /
|
|
2741
|
+
// `String(form.values)` reflect the stored data — including a field
|
|
2742
|
+
// literally named `hasOwnProperty` that Vue would otherwise shim —
|
|
2743
|
+
// while still tracking the per-key reads that drive re-render.
|
|
2744
|
+
coercionSnapshot: () => materializeFormValue(inner.value),
|
|
2578
2745
|
// Read through the readonly proxy at access time so Vue's
|
|
2579
2746
|
// dependency tracking lands inside the consumer's active effect
|
|
2580
2747
|
// — `inner.value[key]` is what triggers per-key tracking.
|
|
2581
|
-
|
|
2582
|
-
//
|
|
2583
|
-
//
|
|
2584
|
-
//
|
|
2585
|
-
|
|
2586
|
-
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
|
|
2592
|
-
|
|
2593
|
-
|
|
2748
|
+
//
|
|
2749
|
+
// Prototype-shadowed names (`hasOwnProperty`, `constructor`, …) read
|
|
2750
|
+
// off the RAW target instead: own-shadows-inherited semantics still
|
|
2751
|
+
// hold (a data field by that name returns its stored value), but
|
|
2752
|
+
// when there's no such field the inherited member resolves — so
|
|
2753
|
+
// `form.values.hasOwnProperty('x')` keeps working as the real
|
|
2754
|
+
// method. The raw read dodges Vue's `hasOwnProperty` proxy shim,
|
|
2755
|
+
// which would otherwise mask a data field of that name. (`toString`
|
|
2756
|
+
// / `valueOf` / `toJSON` never reach here — the base get trap
|
|
2757
|
+
// intercepts them as coercion handlers first.)
|
|
2758
|
+
resolveKey: (key) => isShadowedKey(key) ? vue.toRaw(inner.value)[key] : inner.value[key],
|
|
2759
|
+
// Dynamic path: walk segments through the readonly proxy with the
|
|
2760
|
+
// same own-property-safe descent the rest of the runtime uses
|
|
2761
|
+
// (`getAtPath`), so `form.values('a.hasOwnProperty')` resolves the
|
|
2762
|
+
// stored value. Per-level reads still propagate Vue's tracking for
|
|
2763
|
+
// ordinary keys.
|
|
2764
|
+
resolveCall: (arg) => getAtPath(inner.value, paths.canonicalizePath(arg).segments),
|
|
2594
2765
|
ownKeys: () => Reflect.ownKeys(inner.value),
|
|
2595
2766
|
hasKey: (key) => Reflect.has(inner.value, key),
|
|
2596
2767
|
describeKey: (key) => {
|
|
@@ -2613,6 +2784,17 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2613
2784
|
if (instanceMeta === void 0) return meta;
|
|
2614
2785
|
return meta === void 0 ? { instance: instanceMeta } : { ...meta, instance: instanceMeta };
|
|
2615
2786
|
};
|
|
2787
|
+
const reMarkBlanksAfterSubstitution = (paths$1) => {
|
|
2788
|
+
for (const pathKey of paths$1) {
|
|
2789
|
+
const blankSegments = paths.segmentsForPathKey(pathKey);
|
|
2790
|
+
if (blankSegments === null) continue;
|
|
2791
|
+
state.setValueAtPath(
|
|
2792
|
+
blankSegments,
|
|
2793
|
+
state.getValueAtPath(blankSegments),
|
|
2794
|
+
withInstanceMeta({ blank: true })
|
|
2795
|
+
);
|
|
2796
|
+
}
|
|
2797
|
+
};
|
|
2616
2798
|
const getFormMetaBase = () => {
|
|
2617
2799
|
const { base: rootBase } = buildContainerFieldStateBase(
|
|
2618
2800
|
state,
|
|
@@ -2651,12 +2833,12 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2651
2833
|
const {
|
|
2652
2834
|
validate: validateBuilt,
|
|
2653
2835
|
validateAsync: validateAsyncBuilt,
|
|
2654
|
-
|
|
2836
|
+
parse: parseBuilt,
|
|
2655
2837
|
handleSubmit
|
|
2656
2838
|
} = buildProcessForm(state, formInstanceId, processOptions);
|
|
2657
2839
|
const validate = (pathInput) => validateBuilt(pathInput);
|
|
2658
2840
|
const validateAsync = (pathInput) => validateAsyncBuilt(pathInput);
|
|
2659
|
-
const
|
|
2841
|
+
const parse = (pathInput) => parseBuilt(pathInput);
|
|
2660
2842
|
function pathToRef(pathInput) {
|
|
2661
2843
|
const segments = paths.canonicalizePath(pathInput).segments;
|
|
2662
2844
|
return vue.computed(() => getAtPath(state.form.value, segments));
|
|
@@ -2670,15 +2852,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2670
2852
|
);
|
|
2671
2853
|
const ok2 = state.setValueAtPath([], walked2.cleanedValues, withInstanceMeta());
|
|
2672
2854
|
if (!ok2) return false;
|
|
2673
|
-
|
|
2674
|
-
const blankSegments = paths.segmentsForPathKey(pathKey);
|
|
2675
|
-
if (blankSegments === null) continue;
|
|
2676
|
-
state.setValueAtPath(
|
|
2677
|
-
blankSegments,
|
|
2678
|
-
state.getValueAtPath(blankSegments),
|
|
2679
|
-
withInstanceMeta({ blank: true })
|
|
2680
|
-
);
|
|
2681
|
-
}
|
|
2855
|
+
reMarkBlanksAfterSubstitution(walked2.paths);
|
|
2682
2856
|
return true;
|
|
2683
2857
|
}
|
|
2684
2858
|
const segments = paths.canonicalizePath(pathOrValue).segments;
|
|
@@ -2733,15 +2907,7 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2733
2907
|
);
|
|
2734
2908
|
const ok = state.setValueAtPath(segments, walked.cleanedValues, withInstanceMeta());
|
|
2735
2909
|
if (!ok) return false;
|
|
2736
|
-
|
|
2737
|
-
const blankSegments = paths.segmentsForPathKey(pathKey);
|
|
2738
|
-
if (blankSegments === null) continue;
|
|
2739
|
-
state.setValueAtPath(
|
|
2740
|
-
blankSegments,
|
|
2741
|
-
state.getValueAtPath(blankSegments),
|
|
2742
|
-
withInstanceMeta({ blank: true })
|
|
2743
|
-
);
|
|
2744
|
-
}
|
|
2910
|
+
reMarkBlanksAfterSubstitution(walked.paths);
|
|
2745
2911
|
return true;
|
|
2746
2912
|
}
|
|
2747
2913
|
const errorsProxy = buildErrorsProxy(state);
|
|
@@ -2884,6 +3050,21 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
2884
3050
|
// keep the explicit form-level computation for the gate.
|
|
2885
3051
|
valid,
|
|
2886
3052
|
errors: metaErrors,
|
|
3053
|
+
// Whole-form transforming mirrors the global `activeTransforms`
|
|
3054
|
+
// counter ORed with any per-leaf transform in flight (the root
|
|
3055
|
+
// rollup), exactly as `validating` composes its lifecycle and
|
|
3056
|
+
// per-field sources. `busy` is the union of both work signals at
|
|
3057
|
+
// the form level. `transformError` is leaf-only, so the root
|
|
3058
|
+
// rollup reads it as `null` (kept for FieldState-shape parity).
|
|
3059
|
+
transforming: vue.computed(
|
|
3060
|
+
() => state.activeTransforms.value > 0 || rootFieldState.value.transforming
|
|
3061
|
+
),
|
|
3062
|
+
busy: vue.computed(
|
|
3063
|
+
() => state.activeValidations.value > 0 || state.activeTransforms.value > 0 || rootFieldState.value.validating || rootFieldState.value.transforming
|
|
3064
|
+
),
|
|
3065
|
+
get transformError() {
|
|
3066
|
+
return rootFieldState.value.transformError;
|
|
3067
|
+
},
|
|
2887
3068
|
// `displayState` / the `show*` booleans / `firstError` flow
|
|
2888
3069
|
// through the same root field-state computed as the rest of the
|
|
2889
3070
|
// FieldState surface, so `form.meta.displayState` matches
|
|
@@ -3112,7 +3293,8 @@ function buildFormApi(state, formInstanceId, options = {}) {
|
|
|
3112
3293
|
setValue: gated(setValueImpl),
|
|
3113
3294
|
validate: gated(validate),
|
|
3114
3295
|
validateAsync: gated(validateAsync),
|
|
3115
|
-
|
|
3296
|
+
parse: gated(parse),
|
|
3297
|
+
settleTransforms: gated(state.settleTransforms),
|
|
3116
3298
|
register: gated(register),
|
|
3117
3299
|
key: state.formKey,
|
|
3118
3300
|
// Auto-unwrapping views over the per-store async-defaults lifecycle
|
|
@@ -3979,6 +4161,106 @@ function createFormStore(options) {
|
|
|
3979
4161
|
fieldValidationCounts.set(key, next);
|
|
3980
4162
|
}
|
|
3981
4163
|
}
|
|
4164
|
+
const fieldTransformCounts = vue.reactive(/* @__PURE__ */ new Map());
|
|
4165
|
+
const fieldTransformingSince = vue.reactive(/* @__PURE__ */ new Map());
|
|
4166
|
+
const transformErrors = vue.reactive(/* @__PURE__ */ new Map());
|
|
4167
|
+
const activeTransforms = vue.ref(0);
|
|
4168
|
+
const transformRuns = /* @__PURE__ */ new Map();
|
|
4169
|
+
let transformTokenSeq = 0;
|
|
4170
|
+
const transformWaiters = [];
|
|
4171
|
+
function incFieldTransform(key) {
|
|
4172
|
+
fieldTransformingSince.set(key, ssr ? 0 : Date.now());
|
|
4173
|
+
fieldTransformCounts.set(key, (fieldTransformCounts.get(key) ?? 0) + 1);
|
|
4174
|
+
}
|
|
4175
|
+
function decFieldTransform(key) {
|
|
4176
|
+
const next = (fieldTransformCounts.get(key) ?? 0) - 1;
|
|
4177
|
+
if (next <= 0) {
|
|
4178
|
+
fieldTransformCounts.delete(key);
|
|
4179
|
+
fieldTransformingSince.delete(key);
|
|
4180
|
+
} else {
|
|
4181
|
+
fieldTransformCounts.set(key, next);
|
|
4182
|
+
}
|
|
4183
|
+
}
|
|
4184
|
+
function flushSettledTransformWaiters() {
|
|
4185
|
+
if (transformWaiters.length === 0) return;
|
|
4186
|
+
const globalIdle = activeTransforms.value === 0;
|
|
4187
|
+
for (let i = transformWaiters.length - 1; i >= 0; i--) {
|
|
4188
|
+
const w = transformWaiters[i];
|
|
4189
|
+
if (w === void 0) continue;
|
|
4190
|
+
const idle = w.key === null ? globalIdle : (fieldTransformCounts.get(w.key) ?? 0) === 0;
|
|
4191
|
+
if (idle) {
|
|
4192
|
+
transformWaiters.splice(i, 1);
|
|
4193
|
+
w.resolve();
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
function releaseTransformRun(key, run) {
|
|
4198
|
+
if (run.released) return;
|
|
4199
|
+
run.released = true;
|
|
4200
|
+
run.holder.aborted = true;
|
|
4201
|
+
run.holder.controller?.abort();
|
|
4202
|
+
activeTransforms.value = Math.max(0, activeTransforms.value - 1);
|
|
4203
|
+
decFieldTransform(key);
|
|
4204
|
+
}
|
|
4205
|
+
function beginTransform(key, holder) {
|
|
4206
|
+
const prior = transformRuns.get(key);
|
|
4207
|
+
if (prior !== void 0) releaseTransformRun(key, prior);
|
|
4208
|
+
const token = ++transformTokenSeq;
|
|
4209
|
+
transformRuns.set(key, { token, holder, released: false });
|
|
4210
|
+
incFieldTransform(key);
|
|
4211
|
+
activeTransforms.value += 1;
|
|
4212
|
+
if (transformErrors.has(key)) transformErrors.delete(key);
|
|
4213
|
+
return token;
|
|
4214
|
+
}
|
|
4215
|
+
function isCurrentTransform(key, token) {
|
|
4216
|
+
return transformRuns.get(key)?.token === token;
|
|
4217
|
+
}
|
|
4218
|
+
function endTransform(key, token) {
|
|
4219
|
+
const run = transformRuns.get(key);
|
|
4220
|
+
if (run?.token === token) {
|
|
4221
|
+
if (!run.released) {
|
|
4222
|
+
activeTransforms.value = Math.max(0, activeTransforms.value - 1);
|
|
4223
|
+
decFieldTransform(key);
|
|
4224
|
+
}
|
|
4225
|
+
transformRuns.delete(key);
|
|
4226
|
+
}
|
|
4227
|
+
flushSettledTransformWaiters();
|
|
4228
|
+
}
|
|
4229
|
+
function setTransformError(key, err) {
|
|
4230
|
+
transformErrors.set(key, err);
|
|
4231
|
+
}
|
|
4232
|
+
function cancelTransforms() {
|
|
4233
|
+
for (const [key, run] of [...transformRuns]) {
|
|
4234
|
+
releaseTransformRun(key, run);
|
|
4235
|
+
transformRuns.delete(key);
|
|
4236
|
+
}
|
|
4237
|
+
if (transformErrors.size > 0) transformErrors.clear();
|
|
4238
|
+
flushSettledTransformWaiters();
|
|
4239
|
+
}
|
|
4240
|
+
function cancelTransformsUnder(prefix) {
|
|
4241
|
+
for (const [key, run] of [...transformRuns]) {
|
|
4242
|
+
const segs = paths.segmentsForPathKey(key);
|
|
4243
|
+
if (segs === null) continue;
|
|
4244
|
+
if (!paths.isPathPrefix(prefix, segs)) continue;
|
|
4245
|
+
releaseTransformRun(key, run);
|
|
4246
|
+
transformRuns.delete(key);
|
|
4247
|
+
transformErrors.delete(key);
|
|
4248
|
+
}
|
|
4249
|
+
flushSettledTransformWaiters();
|
|
4250
|
+
}
|
|
4251
|
+
function settleTransforms(path) {
|
|
4252
|
+
if (path === void 0) {
|
|
4253
|
+
if (activeTransforms.value === 0) return Promise.resolve();
|
|
4254
|
+
return new Promise((resolve) => {
|
|
4255
|
+
transformWaiters.push({ key: null, resolve });
|
|
4256
|
+
});
|
|
4257
|
+
}
|
|
4258
|
+
const { key } = paths.canonicalizePath(path);
|
|
4259
|
+
if ((fieldTransformCounts.get(key) ?? 0) === 0) return Promise.resolve();
|
|
4260
|
+
return new Promise((resolve) => {
|
|
4261
|
+
transformWaiters.push({ key, resolve });
|
|
4262
|
+
});
|
|
4263
|
+
}
|
|
3982
4264
|
const initStamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3983
4265
|
diffAndApply({}, schemaInitialData, [], (patch) => {
|
|
3984
4266
|
if (patch.kind !== "added") return;
|
|
@@ -4128,6 +4410,7 @@ function createFormStore(options) {
|
|
|
4128
4410
|
}
|
|
4129
4411
|
}
|
|
4130
4412
|
}
|
|
4413
|
+
if (transformRuns.size !== 0) cancelTransformsUnder(path);
|
|
4131
4414
|
if (meta?.skipDiscriminatorReshape !== true) {
|
|
4132
4415
|
if (path.length > 0) {
|
|
4133
4416
|
const last = path[path.length - 1];
|
|
@@ -4462,6 +4745,7 @@ function createFormStore(options) {
|
|
|
4462
4745
|
drainHooks.length = 0;
|
|
4463
4746
|
modules.clear();
|
|
4464
4747
|
cancelFieldValidation();
|
|
4748
|
+
cancelTransforms();
|
|
4465
4749
|
fieldValidatingSince.clear();
|
|
4466
4750
|
formChangeListeners.clear();
|
|
4467
4751
|
submitSuccessListeners.clear();
|
|
@@ -4598,6 +4882,7 @@ function createFormStore(options) {
|
|
|
4598
4882
|
if (remaining === 0) {
|
|
4599
4883
|
elements.delete(key);
|
|
4600
4884
|
touchFieldRecord(key, path, { connected: false, focused: null, blurred: null });
|
|
4885
|
+
if (transformRuns.size !== 0) cancelTransformsUnder(path);
|
|
4601
4886
|
}
|
|
4602
4887
|
return remaining;
|
|
4603
4888
|
}
|
|
@@ -4819,6 +5104,7 @@ function createFormStore(options) {
|
|
|
4819
5104
|
submitError.value = null;
|
|
4820
5105
|
departAttempts.value = 0;
|
|
4821
5106
|
cancelFieldValidation();
|
|
5107
|
+
cancelTransforms();
|
|
4822
5108
|
displayEngine.clear();
|
|
4823
5109
|
fieldValidatingSince.clear();
|
|
4824
5110
|
pathSnapshots.clear();
|
|
@@ -4837,6 +5123,7 @@ function createFormStore(options) {
|
|
|
4837
5123
|
const { key: targetKey, segments: targetSegments } = paths.canonicalizePath(path);
|
|
4838
5124
|
variantMemory.clearUnderPath(targetSegments);
|
|
4839
5125
|
cancelFieldValidationUnder(targetSegments);
|
|
5126
|
+
cancelTransformsUnder(targetSegments);
|
|
4840
5127
|
for (const [snapKey] of [...pathSnapshots]) {
|
|
4841
5128
|
const segs = paths.segmentsForPathKey(snapKey);
|
|
4842
5129
|
if (segs === null) continue;
|
|
@@ -4972,6 +5259,10 @@ function createFormStore(options) {
|
|
|
4972
5259
|
pathHasAsyncValidationByKey,
|
|
4973
5260
|
fieldValidationCounts,
|
|
4974
5261
|
fieldValidatingSince,
|
|
5262
|
+
fieldTransformCounts,
|
|
5263
|
+
fieldTransformingSince,
|
|
5264
|
+
transformErrors,
|
|
5265
|
+
activeTransforms,
|
|
4975
5266
|
displayEngine,
|
|
4976
5267
|
applyFormReplacement,
|
|
4977
5268
|
setValueAtPath,
|
|
@@ -5001,6 +5292,13 @@ function createFormStore(options) {
|
|
|
5001
5292
|
getOriginalAtPath,
|
|
5002
5293
|
getFirstErrorElement,
|
|
5003
5294
|
cancelFieldValidation,
|
|
5295
|
+
beginTransform,
|
|
5296
|
+
isCurrentTransform,
|
|
5297
|
+
endTransform,
|
|
5298
|
+
setTransformError,
|
|
5299
|
+
cancelTransforms,
|
|
5300
|
+
cancelTransformsUnder,
|
|
5301
|
+
settleTransforms,
|
|
5004
5302
|
scheduleFieldValidation,
|
|
5005
5303
|
onFormChange,
|
|
5006
5304
|
onSubmitSuccess,
|
|
@@ -5032,6 +5330,20 @@ function captureErrorEntries(map) {
|
|
|
5032
5330
|
for (const [k, v] of map) out.push([k, [...v]]);
|
|
5033
5331
|
return out;
|
|
5034
5332
|
}
|
|
5333
|
+
function pathsEqual(a, b) {
|
|
5334
|
+
if (a.length !== b.length) return false;
|
|
5335
|
+
for (let j = 0; j < a.length; j++) {
|
|
5336
|
+
if (a[j] !== b[j]) return false;
|
|
5337
|
+
}
|
|
5338
|
+
return true;
|
|
5339
|
+
}
|
|
5340
|
+
function errorFieldsEqual(av, bvi) {
|
|
5341
|
+
if (av === bvi) return true;
|
|
5342
|
+
if (av.message !== bvi.message) return false;
|
|
5343
|
+
if (av.code !== bvi.code) return false;
|
|
5344
|
+
if (av.formKey !== bvi.formKey) return false;
|
|
5345
|
+
return av.path === bvi.path || pathsEqual(av.path, bvi.path);
|
|
5346
|
+
}
|
|
5035
5347
|
function errorsEqual(a, b) {
|
|
5036
5348
|
if (a.length !== b.length) return false;
|
|
5037
5349
|
const bMap = /* @__PURE__ */ new Map();
|
|
@@ -5041,18 +5353,7 @@ function errorsEqual(a, b) {
|
|
|
5041
5353
|
if (bv === void 0) return false;
|
|
5042
5354
|
if (v.length !== bv.length) return false;
|
|
5043
5355
|
for (let i = 0; i < v.length; i++) {
|
|
5044
|
-
|
|
5045
|
-
const bvi = bv[i];
|
|
5046
|
-
if (av === bvi) continue;
|
|
5047
|
-
if (av.message !== bvi.message) return false;
|
|
5048
|
-
if (av.code !== bvi.code) return false;
|
|
5049
|
-
if (av.formKey !== bvi.formKey) return false;
|
|
5050
|
-
if (av.path !== bvi.path) {
|
|
5051
|
-
if (av.path.length !== bvi.path.length) return false;
|
|
5052
|
-
for (let j = 0; j < av.path.length; j++) {
|
|
5053
|
-
if (av.path[j] !== bvi.path[j]) return false;
|
|
5054
|
-
}
|
|
5055
|
-
}
|
|
5356
|
+
if (!errorFieldsEqual(v[i], bv[i])) return false;
|
|
5056
5357
|
}
|
|
5057
5358
|
}
|
|
5058
5359
|
return true;
|
|
@@ -5266,7 +5567,7 @@ function useAbstractForm(configuration, options) {
|
|
|
5266
5567
|
throw new paths.AnonPersistError({
|
|
5267
5568
|
cause: "no-key",
|
|
5268
5569
|
schemaFields: extractSchemaFields(resolvedSchema),
|
|
5269
|
-
callSite:
|
|
5570
|
+
callSite: captureUserCallSite()
|
|
5270
5571
|
});
|
|
5271
5572
|
}
|
|
5272
5573
|
const existing = registry.forms.get(key);
|
|
@@ -5515,7 +5816,7 @@ function recordAmbientProvide(ssr) {
|
|
|
5515
5816
|
if (instance === null) return;
|
|
5516
5817
|
const instanceKey = instance;
|
|
5517
5818
|
const entry = {
|
|
5518
|
-
source:
|
|
5819
|
+
source: captureUserCallSite()
|
|
5519
5820
|
};
|
|
5520
5821
|
const existing = ambientProvideHistory.get(instanceKey);
|
|
5521
5822
|
if (existing === void 0) {
|
|
@@ -5554,7 +5855,7 @@ function enforceAnonPersistRule(formKey, ssr) {
|
|
|
5554
5855
|
if (paths.__DEV__)
|
|
5555
5856
|
throw new paths.AnonPersistError({
|
|
5556
5857
|
cause: "no-key",
|
|
5557
|
-
callSite:
|
|
5858
|
+
callSite: captureUserCallSite()
|
|
5558
5859
|
});
|
|
5559
5860
|
if (!ssr && !warnedAnonPersistKeys.has(formKey)) {
|
|
5560
5861
|
warnedAnonPersistKeys.add(formKey);
|
|
@@ -5611,7 +5912,7 @@ function resolveState(key, registry) {
|
|
|
5611
5912
|
}
|
|
5612
5913
|
function warnMiss$1(detail, ssr) {
|
|
5613
5914
|
if (!paths.__DEV__ || ssr) return;
|
|
5614
|
-
const frame =
|
|
5915
|
+
const frame = captureUserCallSite();
|
|
5615
5916
|
console.warn(
|
|
5616
5917
|
`[attaform] injectForm: ${detail}. Returning null.` + (frame !== void 0 ? ` ${frame}` : "")
|
|
5617
5918
|
);
|
|
@@ -5634,6 +5935,99 @@ function warnIfAmbientProviderHadDuplicates() {
|
|
|
5634
5935
|
}
|
|
5635
5936
|
}
|
|
5636
5937
|
|
|
5938
|
+
const warnedNoParentRV = paths.__DEV__ ? /* @__PURE__ */ new WeakSet() : null;
|
|
5939
|
+
let warnedOutsideSetup = false;
|
|
5940
|
+
function makeRegisterValueProxy(capturedRegisterValue) {
|
|
5941
|
+
return new Proxy({}, {
|
|
5942
|
+
get(_target, prop) {
|
|
5943
|
+
if (prop === "__v_isRef") return true;
|
|
5944
|
+
if (prop === "value") return capturedRegisterValue.value;
|
|
5945
|
+
const v = capturedRegisterValue.value;
|
|
5946
|
+
if (v === void 0) return void 0;
|
|
5947
|
+
return Reflect.get(v, prop);
|
|
5948
|
+
},
|
|
5949
|
+
has(_target, prop) {
|
|
5950
|
+
if (prop === "__v_isRef" || prop === "value") return true;
|
|
5951
|
+
const v = capturedRegisterValue.value;
|
|
5952
|
+
if (v === void 0) return false;
|
|
5953
|
+
return Reflect.has(v, prop);
|
|
5954
|
+
},
|
|
5955
|
+
ownKeys(_target) {
|
|
5956
|
+
const v = capturedRegisterValue.value;
|
|
5957
|
+
if (v === void 0) return [];
|
|
5958
|
+
return Reflect.ownKeys(v);
|
|
5959
|
+
},
|
|
5960
|
+
getOwnPropertyDescriptor(_target, prop) {
|
|
5961
|
+
const v = capturedRegisterValue.value;
|
|
5962
|
+
if (v === void 0) return void 0;
|
|
5963
|
+
const desc = Reflect.getOwnPropertyDescriptor(v, prop);
|
|
5964
|
+
if (desc !== void 0) {
|
|
5965
|
+
desc.configurable = true;
|
|
5966
|
+
}
|
|
5967
|
+
return desc;
|
|
5968
|
+
}
|
|
5969
|
+
});
|
|
5970
|
+
}
|
|
5971
|
+
function useRegister() {
|
|
5972
|
+
const instance = vue.getCurrentInstance();
|
|
5973
|
+
if (instance === null) {
|
|
5974
|
+
warnOutsideSetup();
|
|
5975
|
+
return makeRegisterValueProxy(vue.shallowRef(void 0));
|
|
5976
|
+
}
|
|
5977
|
+
paths.ensureAttaformInstalled(instance.appContext.app);
|
|
5978
|
+
const capturedRegisterValue = vue.shallowRef(void 0);
|
|
5979
|
+
const refreshAndStripBridgeAttrs = () => {
|
|
5980
|
+
const rawAttrs = instance.attrs;
|
|
5981
|
+
if ("registerValue" in rawAttrs) {
|
|
5982
|
+
capturedRegisterValue.value = rawAttrs["registerValue"];
|
|
5983
|
+
delete rawAttrs["registerValue"];
|
|
5984
|
+
} else {
|
|
5985
|
+
const dirs = instance.vnode.dirs;
|
|
5986
|
+
if (dirs !== null && dirs !== void 0) {
|
|
5987
|
+
for (const dir of dirs) {
|
|
5988
|
+
const marked = dir.dir?.[paths.V_REGISTER_MARKER];
|
|
5989
|
+
if (marked === true) {
|
|
5990
|
+
capturedRegisterValue.value = dir.value;
|
|
5991
|
+
break;
|
|
5992
|
+
}
|
|
5993
|
+
}
|
|
5994
|
+
}
|
|
5995
|
+
}
|
|
5996
|
+
if ("value" in rawAttrs) delete rawAttrs["value"];
|
|
5997
|
+
};
|
|
5998
|
+
refreshAndStripBridgeAttrs();
|
|
5999
|
+
vue.onBeforeMount(refreshAndStripBridgeAttrs);
|
|
6000
|
+
vue.onBeforeUpdate(refreshAndStripBridgeAttrs);
|
|
6001
|
+
vue.onMounted(() => {
|
|
6002
|
+
const el = instance.vnode.el;
|
|
6003
|
+
if (el !== null && el !== void 0 && typeof el === "object") {
|
|
6004
|
+
el[paths.REGISTER_OWNER_MARKER] = true;
|
|
6005
|
+
}
|
|
6006
|
+
if (capturedRegisterValue.value === void 0) {
|
|
6007
|
+
warnNoParentRV(instance);
|
|
6008
|
+
}
|
|
6009
|
+
});
|
|
6010
|
+
return makeRegisterValueProxy(capturedRegisterValue);
|
|
6011
|
+
}
|
|
6012
|
+
function warnOutsideSetup() {
|
|
6013
|
+
if (!paths.__DEV__) return;
|
|
6014
|
+
if (warnedOutsideSetup) return;
|
|
6015
|
+
warnedOutsideSetup = true;
|
|
6016
|
+
const frame = captureUserCallSite();
|
|
6017
|
+
console.warn(
|
|
6018
|
+
`[attaform] useRegister() called outside a component setup; returning an unbound RegisterValue proxy. Fix: call it inside <script setup> or a setup() function \u2014 not from an event handler or async callback.` + (frame !== void 0 ? ` ${frame}` : "")
|
|
6019
|
+
);
|
|
6020
|
+
}
|
|
6021
|
+
function warnNoParentRV(instance) {
|
|
6022
|
+
if (!paths.__DEV__ || warnedNoParentRV === null) return;
|
|
6023
|
+
if (warnedNoParentRV.has(instance)) return;
|
|
6024
|
+
warnedNoParentRV.add(instance);
|
|
6025
|
+
const frame = captureUserCallSite();
|
|
6026
|
+
console.warn(
|
|
6027
|
+
`[attaform] useRegister: no parent registerValue prop; RegisterValue fields will read as undefined. Pass v-register on the parent: \`<YourComponent v-register="form.register('field')" />\`.` + (frame !== void 0 ? ` ${frame}` : "")
|
|
6028
|
+
);
|
|
6029
|
+
}
|
|
6030
|
+
|
|
5637
6031
|
const LAZY_BRAND = Symbol.for("attaform/wizard-lazy");
|
|
5638
6032
|
function lazy(resolve) {
|
|
5639
6033
|
return { [LAZY_BRAND]: true, resolve };
|
|
@@ -5643,6 +6037,8 @@ function isLazyMarker(value) {
|
|
|
5643
6037
|
}
|
|
5644
6038
|
|
|
5645
6039
|
const NOOP_WIZARD_HISTORY = {
|
|
6040
|
+
push() {
|
|
6041
|
+
},
|
|
5646
6042
|
replace() {
|
|
5647
6043
|
},
|
|
5648
6044
|
read() {
|
|
@@ -5657,6 +6053,9 @@ function createWizardHistory(param) {
|
|
|
5657
6053
|
if (typeof window === "undefined") return NOOP_WIZARD_HISTORY;
|
|
5658
6054
|
const subscribers = [];
|
|
5659
6055
|
let disposed = false;
|
|
6056
|
+
function currentKey() {
|
|
6057
|
+
return new URL(window.location.href).searchParams.get(param) ?? void 0;
|
|
6058
|
+
}
|
|
5660
6059
|
function buildUrl(key) {
|
|
5661
6060
|
const url = new URL(window.location.href);
|
|
5662
6061
|
url.searchParams.set(param, key);
|
|
@@ -5664,25 +6063,29 @@ function createWizardHistory(param) {
|
|
|
5664
6063
|
}
|
|
5665
6064
|
function handlePopstate() {
|
|
5666
6065
|
if (disposed) return;
|
|
5667
|
-
const
|
|
5668
|
-
const value = url.searchParams.get(param) ?? void 0;
|
|
6066
|
+
const value = currentKey();
|
|
5669
6067
|
for (const subscriber of subscribers) subscriber(value);
|
|
5670
6068
|
}
|
|
5671
6069
|
window.addEventListener("popstate", handlePopstate);
|
|
5672
|
-
function
|
|
6070
|
+
function safeWrite(key, mode) {
|
|
5673
6071
|
try {
|
|
5674
|
-
window.history.
|
|
6072
|
+
if (mode === "push") window.history.pushState({}, "", buildUrl(key));
|
|
6073
|
+
else window.history.replaceState({}, "", buildUrl(key));
|
|
5675
6074
|
} catch {
|
|
5676
6075
|
}
|
|
5677
6076
|
}
|
|
5678
6077
|
return {
|
|
6078
|
+
push(key) {
|
|
6079
|
+
if (disposed) return;
|
|
6080
|
+
if (currentKey() === key) return;
|
|
6081
|
+
safeWrite(key, "push");
|
|
6082
|
+
},
|
|
5679
6083
|
replace(key) {
|
|
5680
6084
|
if (disposed) return;
|
|
5681
|
-
|
|
6085
|
+
safeWrite(key, "replace");
|
|
5682
6086
|
},
|
|
5683
6087
|
read() {
|
|
5684
|
-
|
|
5685
|
-
return url.searchParams.get(param) ?? void 0;
|
|
6088
|
+
return currentKey();
|
|
5686
6089
|
},
|
|
5687
6090
|
subscribe(callback) {
|
|
5688
6091
|
if (disposed) return;
|
|
@@ -5720,6 +6123,7 @@ function buildNoopWizardSchema(formKey) {
|
|
|
5720
6123
|
getEmptyValueAtPath: () => void 0,
|
|
5721
6124
|
isPreprocessOrCoerceLeaf: () => false,
|
|
5722
6125
|
arrayShapeAtPath: () => void 0,
|
|
6126
|
+
isFixedObjectAtPath: (path) => path.length === 0,
|
|
5723
6127
|
getSchemasAtPath: () => [],
|
|
5724
6128
|
validateAtPath: () => success,
|
|
5725
6129
|
getSlimPrimitiveTypesAtPath: () => new Set(EMPTY_SLIM_KINDS),
|
|
@@ -6173,7 +6577,10 @@ function useWizard(options) {
|
|
|
6173
6577
|
};
|
|
6174
6578
|
const persistCallback = options.persist === false ? void 0 : options.persist !== void 0 ? options.persist : (state) => {
|
|
6175
6579
|
if (state.step === void 0) return;
|
|
6176
|
-
historyHandle.
|
|
6580
|
+
const current = historyHandle.read();
|
|
6581
|
+
const effectiveCurrent = current !== void 0 && isCompiledKey(current) ? current : firstKey();
|
|
6582
|
+
if (state.step === effectiveCurrent) historyHandle.replace(state.step);
|
|
6583
|
+
else historyHandle.push(state.step);
|
|
6177
6584
|
};
|
|
6178
6585
|
function isCompiledKey(key) {
|
|
6179
6586
|
const list = compiledSteps.value;
|
|
@@ -6254,6 +6661,7 @@ function useWizard(options) {
|
|
|
6254
6661
|
}
|
|
6255
6662
|
const submitting = vue.ref(false);
|
|
6256
6663
|
const submissionAttempts = vue.ref(0);
|
|
6664
|
+
const submitError = vue.ref(null);
|
|
6257
6665
|
const done = vue.ref(false);
|
|
6258
6666
|
function activateForm(form) {
|
|
6259
6667
|
const source = asSubmissionSource(form);
|
|
@@ -6381,7 +6789,7 @@ function useWizard(options) {
|
|
|
6381
6789
|
formKey: form.key
|
|
6382
6790
|
};
|
|
6383
6791
|
}
|
|
6384
|
-
return full.
|
|
6792
|
+
return full.parse();
|
|
6385
6793
|
}
|
|
6386
6794
|
function collectErrors(results) {
|
|
6387
6795
|
const out = [];
|
|
@@ -6412,6 +6820,7 @@ function useWizard(options) {
|
|
|
6412
6820
|
return;
|
|
6413
6821
|
}
|
|
6414
6822
|
submitting.value = true;
|
|
6823
|
+
submitError.value = null;
|
|
6415
6824
|
try {
|
|
6416
6825
|
const currentKey = activeKey.value;
|
|
6417
6826
|
const final = isFinalStep.value;
|
|
@@ -6420,12 +6829,14 @@ function useWizard(options) {
|
|
|
6420
6829
|
if (final) {
|
|
6421
6830
|
await Promise.all(
|
|
6422
6831
|
list.map(async (step) => {
|
|
6832
|
+
registry.forms.get(step.key)?.clearUserErrors();
|
|
6423
6833
|
const result = await processOne(step.form);
|
|
6424
6834
|
results.set(step.key, result);
|
|
6425
6835
|
})
|
|
6426
6836
|
);
|
|
6427
6837
|
} else {
|
|
6428
6838
|
const active = activeForm.value;
|
|
6839
|
+
registry.forms.get(active.key)?.clearUserErrors();
|
|
6429
6840
|
const result = await processOne(active);
|
|
6430
6841
|
results.set(active.key, result);
|
|
6431
6842
|
}
|
|
@@ -6460,7 +6871,6 @@ function useWizard(options) {
|
|
|
6460
6871
|
if (target !== void 0) moveTo(target.key);
|
|
6461
6872
|
}
|
|
6462
6873
|
} else {
|
|
6463
|
-
if (onError !== void 0) await onError(errors);
|
|
6464
6874
|
if (options.focusFirstError !== false) {
|
|
6465
6875
|
const firstFailedKey = errors[0]?.formKey;
|
|
6466
6876
|
if (firstFailedKey !== void 0 && isCompiledKey(firstFailedKey)) {
|
|
@@ -6475,7 +6885,16 @@ function useWizard(options) {
|
|
|
6475
6885
|
}
|
|
6476
6886
|
}
|
|
6477
6887
|
}
|
|
6888
|
+
if (onError !== void 0) {
|
|
6889
|
+
try {
|
|
6890
|
+
await onError(errors);
|
|
6891
|
+
} catch (cause) {
|
|
6892
|
+
throw new paths.SubmitErrorHandlerError("User-provided onError threw", { cause });
|
|
6893
|
+
}
|
|
6894
|
+
}
|
|
6478
6895
|
}
|
|
6896
|
+
} catch (err) {
|
|
6897
|
+
submitError.value = paths.toError(err);
|
|
6479
6898
|
} finally {
|
|
6480
6899
|
submitting.value = false;
|
|
6481
6900
|
}
|
|
@@ -6484,6 +6903,7 @@ function useWizard(options) {
|
|
|
6484
6903
|
function reset() {
|
|
6485
6904
|
submissionAttempts.value = 0;
|
|
6486
6905
|
done.value = false;
|
|
6906
|
+
submitError.value = null;
|
|
6487
6907
|
lazyEpoch.value += 1;
|
|
6488
6908
|
for (const step of compiledSteps.value) {
|
|
6489
6909
|
const full = asSubmissionSource(step.form);
|
|
@@ -6559,6 +6979,9 @@ function useWizard(options) {
|
|
|
6559
6979
|
get submissionAttempts() {
|
|
6560
6980
|
return submissionAttempts.value;
|
|
6561
6981
|
},
|
|
6982
|
+
get submitError() {
|
|
6983
|
+
return submitError.value;
|
|
6984
|
+
},
|
|
6562
6985
|
get visited() {
|
|
6563
6986
|
return visited.value;
|
|
6564
6987
|
}
|
|
@@ -6589,7 +7012,7 @@ function recordAmbientWizardProvide(ssr) {
|
|
|
6589
7012
|
if (instance === null) return;
|
|
6590
7013
|
const instanceKey = instance;
|
|
6591
7014
|
const entry = {
|
|
6592
|
-
source:
|
|
7015
|
+
source: captureUserCallSite()
|
|
6593
7016
|
};
|
|
6594
7017
|
const existing = ambientWizardProvideHistory.get(instanceKey);
|
|
6595
7018
|
if (existing === void 0) {
|
|
@@ -6644,7 +7067,7 @@ function availableKeysHint(wizards) {
|
|
|
6644
7067
|
}
|
|
6645
7068
|
function warnMiss(detail, ssr, hint) {
|
|
6646
7069
|
if (!paths.__DEV__ || ssr) return;
|
|
6647
|
-
const frame =
|
|
7070
|
+
const frame = captureUserCallSite();
|
|
6648
7071
|
const parts = [`[attaform] injectWizard: ${detail}. Returning null.`];
|
|
6649
7072
|
if (hint !== void 0) parts.push(hint);
|
|
6650
7073
|
if (frame !== void 0) parts.push(frame);
|
|
@@ -6698,5 +7121,6 @@ exports.slimKindOf = slimKindOf;
|
|
|
6698
7121
|
exports.structuralSnapshot = structuralSnapshot;
|
|
6699
7122
|
exports.unset = unset;
|
|
6700
7123
|
exports.useAbstractForm = useAbstractForm;
|
|
7124
|
+
exports.useRegister = useRegister;
|
|
6701
7125
|
exports.useWizard = useWizard;
|
|
6702
|
-
//# sourceMappingURL=attaform.
|
|
7126
|
+
//# sourceMappingURL=attaform.D2ZuIOCf.cjs.map
|