react-f0rm 1.3.0 → 1.5.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/README.md +98 -1140
- package/devtools.d.ts +1 -0
- package/devtools.js +1 -0
- package/dist/array-Bu7W8BSz.d.ts +54 -0
- package/dist/devtools/index.cjs.js +1 -1
- package/dist/devtools/index.cjs.js.map +1 -1
- package/dist/devtools/index.d.cts +24 -0
- package/dist/devtools/index.d.mts +24 -0
- package/dist/devtools/index.d.ts +8 -17
- package/dist/devtools/index.mjs +1 -1
- package/dist/devtools/index.mjs.map +1 -1
- package/dist/errors-DA4ReEd9.mjs +2 -0
- package/dist/errors-DA4ReEd9.mjs.map +1 -0
- package/dist/errors-TzyWwBfw.cjs.js +2 -0
- package/dist/errors-TzyWwBfw.cjs.js.map +1 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.cts +1253 -0
- package/dist/index.d.mts +1253 -0
- package/dist/index.d.ts +570 -895
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1256 -535
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +2 -2
- package/dist/index.umd.min.js.map +1 -1
- package/dist/persist.cjs.js +1 -1
- package/dist/persist.cjs.js.map +1 -1
- package/dist/persist.d.cts +28 -0
- package/dist/persist.d.mts +28 -0
- package/dist/persist.d.ts +9 -30
- package/dist/persist.mjs +1 -1
- package/dist/persist.mjs.map +1 -1
- package/dist/resolvers/standard-schema.cjs.js +1 -1
- package/dist/resolvers/standard-schema.cjs.js.map +1 -1
- package/dist/resolvers/standard-schema.d.cts +2 -0
- package/dist/resolvers/standard-schema.d.mts +2 -0
- package/dist/resolvers/standard-schema.d.ts +1 -67
- package/dist/resolvers/standard-schema.mjs +1 -1
- package/dist/resolvers/standard-schema.mjs.map +1 -1
- package/dist/resolvers/yup.cjs.js +1 -1
- package/dist/resolvers/yup.cjs.js.map +1 -1
- package/dist/resolvers/yup.d.cts +6 -0
- package/dist/resolvers/yup.d.mts +6 -0
- package/dist/resolvers/yup.d.ts +0 -1
- package/dist/resolvers/yup.mjs +1 -1
- package/dist/resolvers/yup.mjs.map +1 -1
- package/dist/resolvers/zod.cjs.js +1 -1
- package/dist/resolvers/zod.cjs.js.map +1 -1
- package/dist/resolvers/zod.d.cts +34 -0
- package/dist/resolvers/zod.d.mts +34 -0
- package/dist/resolvers/zod.d.ts +30 -3
- package/dist/resolvers/zod.mjs +1 -1
- package/dist/resolvers/zod.mjs.map +1 -1
- package/dist/server/index.cjs.js +1 -1
- package/dist/server/index.cjs.js.map +1 -1
- package/dist/server/index.d.cts +38 -0
- package/dist/server/index.d.mts +38 -0
- package/dist/server/index.d.ts +26 -65
- package/dist/server/index.mjs +1 -1
- package/dist/server/index.mjs.map +1 -1
- package/dist/standard-schema-BAaTmAHh.d.ts +682 -0
- package/dist/standardSchema-5WezjHlp.mjs +2 -0
- package/dist/standardSchema-5WezjHlp.mjs.map +1 -0
- package/dist/standardSchema-DINHlsYR.cjs.js +2 -0
- package/dist/standardSchema-DINHlsYR.cjs.js.map +1 -0
- package/dist/validate-2pX-N1O6.cjs.js +2 -0
- package/dist/validate-2pX-N1O6.cjs.js.map +1 -0
- package/dist/validate-C0HOsP9v.mjs +2 -0
- package/dist/validate-C0HOsP9v.mjs.map +1 -0
- package/dist/values-BbPnLByD.cjs.js +2 -0
- package/dist/values-BbPnLByD.cjs.js.map +1 -0
- package/dist/values-CHsmcZk4.mjs +2 -0
- package/dist/values-CHsmcZk4.mjs.map +1 -0
- package/package.json +75 -28
- package/persist.d.ts +1 -0
- package/persist.js +1 -0
- package/resolvers/standard-schema.d.ts +1 -0
- package/resolvers/standard-schema.js +1 -0
- package/resolvers/yup.d.ts +1 -0
- package/resolvers/yup.js +1 -0
- package/resolvers/zod.d.ts +1 -0
- package/resolvers/zod.js +1 -0
- package/server.d.ts +1 -0
- package/server.js +1 -0
- package/dist/errors-BKrUdpfI.cjs.js +0 -2
- package/dist/errors-BKrUdpfI.cjs.js.map +0 -1
- package/dist/errors-CrQBddrJ.mjs +0 -2
- package/dist/errors-CrQBddrJ.mjs.map +0 -1
- package/dist/form-CeKSBs31.d.ts +0 -486
- package/dist/validate-CNtuUhmk.mjs +0 -2
- package/dist/validate-CNtuUhmk.mjs.map +0 -1
- package/dist/validate-Cl4ksNFu.cjs.js +0 -2
- package/dist/validate-Cl4ksNFu.cjs.js.map +0 -1
- package/dist/validate-nksgv1pR.d.ts +0 -272
- package/dist/values-Cu6awQOJ.cjs.js +0 -2
- package/dist/values-Cu6awQOJ.cjs.js.map +0 -1
- package/dist/values-DRY-a32G.mjs +0 -2
- package/dist/values-DRY-a32G.mjs.map +0 -1
package/dist/index.umd.js
CHANGED
|
@@ -266,12 +266,31 @@
|
|
|
266
266
|
delete copy[prop];
|
|
267
267
|
return copy;
|
|
268
268
|
}
|
|
269
|
+
function arraySlot(container, prop) {
|
|
270
|
+
if (typeof prop === "number") return prop;
|
|
271
|
+
if (Array.isArray(container) && typeof prop === "string" && isIndex(prop)) {
|
|
272
|
+
return Number(prop);
|
|
273
|
+
}
|
|
274
|
+
return void 0;
|
|
275
|
+
}
|
|
276
|
+
function copyForProp(container, prop) {
|
|
277
|
+
if (arraySlot(container, prop) !== void 0) {
|
|
278
|
+
return Array.isArray(container) ? container.slice() : [];
|
|
279
|
+
}
|
|
280
|
+
return { ...container };
|
|
281
|
+
}
|
|
282
|
+
function ensureOwned(container, prop, owned) {
|
|
283
|
+
if (owned.has(container)) return container;
|
|
284
|
+
const copy = copyForProp(container, prop);
|
|
285
|
+
owned.add(copy);
|
|
286
|
+
return copy;
|
|
287
|
+
}
|
|
269
288
|
function set(values, path, value) {
|
|
270
289
|
if (!path.length) return value;
|
|
271
290
|
const [prop, ...props] = path;
|
|
272
|
-
const index =
|
|
291
|
+
const index = arraySlot(values, prop);
|
|
273
292
|
if (index !== void 0) {
|
|
274
|
-
const arr =
|
|
293
|
+
const arr = copyForProp(values, prop);
|
|
275
294
|
arr[index] = set(arr[index], props, value);
|
|
276
295
|
return arr;
|
|
277
296
|
}
|
|
@@ -284,14 +303,8 @@
|
|
|
284
303
|
let parentProp = "";
|
|
285
304
|
for (let i = 0; i < path.length; i++) {
|
|
286
305
|
const prop = path[i];
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
if (typeof prop === "number" || Array.isArray(container) && typeof prop === "string" && isIndex(prop)) {
|
|
290
|
-
copy = Array.isArray(container) ? container.slice() : [];
|
|
291
|
-
} else {
|
|
292
|
-
copy = { ...container };
|
|
293
|
-
}
|
|
294
|
-
owned.add(copy);
|
|
306
|
+
const copy = ensureOwned(container, prop, owned);
|
|
307
|
+
if (copy !== container) {
|
|
295
308
|
if (i === 0) root = copy;
|
|
296
309
|
else parent[parentProp] = copy;
|
|
297
310
|
container = copy;
|
|
@@ -309,6 +322,18 @@
|
|
|
309
322
|
function isPromise(value) {
|
|
310
323
|
return value && typeof value.then === "function";
|
|
311
324
|
}
|
|
325
|
+
function extractEventValue(e, options) {
|
|
326
|
+
const target = e?.target;
|
|
327
|
+
if (!target) return e;
|
|
328
|
+
if (target.type === "file") return target.files;
|
|
329
|
+
if (target.type === "checkbox") return target.checked;
|
|
330
|
+
if (options?.valueAsNumber) return target.valueAsNumber;
|
|
331
|
+
if (options?.valueAsDate) return target.valueAsDate;
|
|
332
|
+
return target.value;
|
|
333
|
+
}
|
|
334
|
+
function eventToValueOrDefault(eventToValue, options) {
|
|
335
|
+
return eventToValue ?? ((e) => extractEventValue(e, options));
|
|
336
|
+
}
|
|
312
337
|
function isEqual(a, b) {
|
|
313
338
|
if (Object.is(a, b)) return true;
|
|
314
339
|
if (a instanceof Date && b instanceof Date)
|
|
@@ -355,12 +380,28 @@
|
|
|
355
380
|
const value = normalizePath(name);
|
|
356
381
|
return { value, key: JSON.stringify(value) };
|
|
357
382
|
}
|
|
383
|
+
function segmentsFromKey(key) {
|
|
384
|
+
return JSON.parse(key);
|
|
385
|
+
}
|
|
358
386
|
|
|
387
|
+
function getOrCreate(map, form, create) {
|
|
388
|
+
if (map.has(form)) return map.get(form);
|
|
389
|
+
const value = create();
|
|
390
|
+
map.set(form, value);
|
|
391
|
+
return value;
|
|
392
|
+
}
|
|
359
393
|
const valuesCaches = /* @__PURE__ */ new WeakMap();
|
|
360
|
-
function
|
|
361
|
-
const cache =
|
|
394
|
+
function bumpVersion(map, form) {
|
|
395
|
+
const cache = map.get(form);
|
|
362
396
|
if (cache) cache.version++;
|
|
363
397
|
}
|
|
398
|
+
function bumpValuesVersion(form) {
|
|
399
|
+
bumpVersion(valuesCaches, form);
|
|
400
|
+
}
|
|
401
|
+
const errorsCaches = /* @__PURE__ */ new WeakMap();
|
|
402
|
+
function bumpErrorsVersion(form) {
|
|
403
|
+
bumpVersion(errorsCaches, form);
|
|
404
|
+
}
|
|
364
405
|
const dirtyBaselines = /* @__PURE__ */ new WeakMap();
|
|
365
406
|
function getDirtyBaseline(form, key, segments) {
|
|
366
407
|
const baselines = dirtyBaselines.get(form);
|
|
@@ -368,12 +409,7 @@
|
|
|
368
409
|
return get(form.initialValues, segments);
|
|
369
410
|
}
|
|
370
411
|
function setDirtyBaseline(form, { key }, value) {
|
|
371
|
-
|
|
372
|
-
if (!baselines) {
|
|
373
|
-
baselines = /* @__PURE__ */ new Map();
|
|
374
|
-
dirtyBaselines.set(form, baselines);
|
|
375
|
-
}
|
|
376
|
-
baselines.set(key, value);
|
|
412
|
+
getOrCreate(dirtyBaselines, form, () => /* @__PURE__ */ new Map()).set(key, value);
|
|
377
413
|
}
|
|
378
414
|
function pruneDirtyBaselines(form, { key }) {
|
|
379
415
|
const baselines = dirtyBaselines.get(form);
|
|
@@ -391,8 +427,7 @@
|
|
|
391
427
|
}
|
|
392
428
|
const dirtyFieldsCaches = /* @__PURE__ */ new WeakMap();
|
|
393
429
|
function bumpDirtyVersion(form) {
|
|
394
|
-
|
|
395
|
-
if (cache) cache.version++;
|
|
430
|
+
bumpVersion(dirtyFieldsCaches, form);
|
|
396
431
|
}
|
|
397
432
|
function isSegmentsPath(name) {
|
|
398
433
|
return name.some((part) => typeof part === "number");
|
|
@@ -425,11 +460,55 @@
|
|
|
425
460
|
function getErrors({ errors }) {
|
|
426
461
|
const entries = [];
|
|
427
462
|
for (const [key, list] of errors) {
|
|
428
|
-
const path =
|
|
463
|
+
const path = segmentsFromKey(key).join(".");
|
|
429
464
|
for (const { type, message } of list) entries.push({ path, type, message });
|
|
430
465
|
}
|
|
431
466
|
return entries;
|
|
432
467
|
}
|
|
468
|
+
function computeErrorsViews(form) {
|
|
469
|
+
const cached = errorsCaches.get(form);
|
|
470
|
+
if (cached?.version === 0) return;
|
|
471
|
+
const result = {};
|
|
472
|
+
const tree = {};
|
|
473
|
+
for (const [key, list] of form.errors) {
|
|
474
|
+
const segments = segmentsFromKey(key);
|
|
475
|
+
result[segments.join(".")] = list;
|
|
476
|
+
let node = tree;
|
|
477
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
478
|
+
const segment = segments[i];
|
|
479
|
+
const slot = node[segment];
|
|
480
|
+
const container = slot && !(Array.isArray(slot) && slot.length > 0 && isFieldError(slot[0])) ? slot : typeof segments[i + 1] === "number" ? [] : {};
|
|
481
|
+
node[segment] = container;
|
|
482
|
+
node = container;
|
|
483
|
+
}
|
|
484
|
+
node[segments[segments.length - 1]] = list;
|
|
485
|
+
}
|
|
486
|
+
if (cached) {
|
|
487
|
+
cached.result = result;
|
|
488
|
+
cached.tree = tree;
|
|
489
|
+
cached.version = 0;
|
|
490
|
+
} else {
|
|
491
|
+
errorsCaches.set(form, { version: 0, result, tree });
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
function getErrorsRecord(form) {
|
|
495
|
+
computeErrorsViews(form);
|
|
496
|
+
return errorsCaches.get(form).result;
|
|
497
|
+
}
|
|
498
|
+
function getErrorsTree(form) {
|
|
499
|
+
computeErrorsViews(form);
|
|
500
|
+
return errorsCaches.get(form).tree;
|
|
501
|
+
}
|
|
502
|
+
function fieldPathToDottedKey(name) {
|
|
503
|
+
return create$1(name).value.join(".");
|
|
504
|
+
}
|
|
505
|
+
function dottedKeyToFieldPath(key) {
|
|
506
|
+
const segments = key.split(".");
|
|
507
|
+
const numeric = (segment) => /^(0|[1-9]\d*)$/.test(segment);
|
|
508
|
+
return segments.map(
|
|
509
|
+
(segment, i) => i > 0 && numeric(segment) ? `[${segment}]` : `${i > 0 ? "." : ""}${segment}`
|
|
510
|
+
).join("");
|
|
511
|
+
}
|
|
433
512
|
function getFirstError({ errors }) {
|
|
434
513
|
return errors.values().next().value?.[0]?.message;
|
|
435
514
|
}
|
|
@@ -441,6 +520,7 @@
|
|
|
441
520
|
const list = normalizeErrors(error);
|
|
442
521
|
if (list) errors.set(path.key, list);
|
|
443
522
|
else errors.delete(path.key);
|
|
523
|
+
bumpErrorsVersion(form);
|
|
444
524
|
emit(emitter, "errors", path);
|
|
445
525
|
if (options?.shouldFocus) emit(emitter, "focusError", path.key);
|
|
446
526
|
}
|
|
@@ -464,11 +544,13 @@
|
|
|
464
544
|
const { emitter, errors } = form;
|
|
465
545
|
if (name === void 0) {
|
|
466
546
|
errors.clear();
|
|
547
|
+
bumpErrorsVersion(form);
|
|
467
548
|
emit(emitter, "errors");
|
|
468
549
|
return;
|
|
469
550
|
}
|
|
470
551
|
const paths = typeof name === "string" || isSegmentsPath(name) ? [create$1(name)] : name.map((one) => create$1(one));
|
|
471
552
|
for (const { key } of paths) errors.delete(key);
|
|
553
|
+
bumpErrorsVersion(form);
|
|
472
554
|
for (const path of paths) emit(emitter, "errors", path);
|
|
473
555
|
}
|
|
474
556
|
function setServerErrors(form, errors, options) {
|
|
@@ -484,24 +566,110 @@
|
|
|
484
566
|
);
|
|
485
567
|
}
|
|
486
568
|
}
|
|
569
|
+
function clearServerErrors(form) {
|
|
570
|
+
const affected = Array.from(form.errors).filter(
|
|
571
|
+
([, list]) => list.some((error) => error.type === "server")
|
|
572
|
+
);
|
|
573
|
+
if (affected.length === 0) return;
|
|
574
|
+
for (const [key, list] of affected) {
|
|
575
|
+
const kept = list.filter((error) => error.type !== "server");
|
|
576
|
+
if (kept.length) form.errors.set(key, kept);
|
|
577
|
+
else form.errors.delete(key);
|
|
578
|
+
}
|
|
579
|
+
bumpErrorsVersion(form);
|
|
580
|
+
emit(form.emitter, "errors");
|
|
581
|
+
}
|
|
487
582
|
function hasErrors({ errors }) {
|
|
488
583
|
return errors.size > 0;
|
|
489
584
|
}
|
|
490
585
|
|
|
586
|
+
function hasStandardProps(schema) {
|
|
587
|
+
return !!schema && typeof schema === "object" && typeof schema["~standard"]?.validate === "function";
|
|
588
|
+
}
|
|
589
|
+
function toFieldError(issue) {
|
|
590
|
+
return { type: "standard", message: issue?.message || "Validation failed" };
|
|
591
|
+
}
|
|
592
|
+
function schemaToFieldValidator(schema) {
|
|
593
|
+
return async (value) => {
|
|
594
|
+
const result = await schema["~standard"].validate(value);
|
|
595
|
+
if (!result.issues?.length) return void 0;
|
|
596
|
+
return result.issues.map(toFieldError);
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
function schemaToFormValidator(schema) {
|
|
600
|
+
return async (values) => {
|
|
601
|
+
const result = await schema["~standard"].validate(values);
|
|
602
|
+
const { issues } = result;
|
|
603
|
+
if (!issues?.length) {
|
|
604
|
+
return {
|
|
605
|
+
[VALIDATION_OUTCOME]: true,
|
|
606
|
+
values: "value" in result ? result.value : void 0
|
|
607
|
+
};
|
|
608
|
+
}
|
|
609
|
+
const errors = {};
|
|
610
|
+
for (const issue of issues) {
|
|
611
|
+
const segments = toPathSegments(issue);
|
|
612
|
+
if (segments.length) {
|
|
613
|
+
assignAtPath(errors, segments, toFieldError(issue));
|
|
614
|
+
} else {
|
|
615
|
+
const slot = errors[FORM_ERROR] ??= [];
|
|
616
|
+
if (Array.isArray(slot)) slot.push(toFieldError(issue));
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
return { [VALIDATION_OUTCOME]: true, errors: pruneEmpty(errors) || {} };
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
function toPathSegments(issue) {
|
|
623
|
+
return (issue.path || []).map(
|
|
624
|
+
(segment) => String(
|
|
625
|
+
typeof segment === "object" && segment !== null ? segment.key : segment
|
|
626
|
+
)
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
function assignAtPath(root, segments, error) {
|
|
630
|
+
let node = root;
|
|
631
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
632
|
+
const segment = segments[i];
|
|
633
|
+
if (node[segment] === void 0) node[segment] = {};
|
|
634
|
+
const next = node[segment];
|
|
635
|
+
if (!isBranch(next)) return;
|
|
636
|
+
node = next;
|
|
637
|
+
}
|
|
638
|
+
const leaf = segments[segments.length - 1];
|
|
639
|
+
const slot = node[leaf];
|
|
640
|
+
if (slot === void 0) node[leaf] = [error];
|
|
641
|
+
else if (Array.isArray(slot)) slot.push(error);
|
|
642
|
+
}
|
|
643
|
+
function isBranch(value) {
|
|
644
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
645
|
+
}
|
|
646
|
+
function pruneEmpty(node) {
|
|
647
|
+
const result = {};
|
|
648
|
+
for (const [key, value] of Object.entries(node)) {
|
|
649
|
+
if (isBranch(value)) {
|
|
650
|
+
const pruned = pruneEmpty(value);
|
|
651
|
+
if (pruned) result[key] = pruned;
|
|
652
|
+
} else {
|
|
653
|
+
result[key] = value;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
return Object.keys(result).length ? result : void 0;
|
|
657
|
+
}
|
|
658
|
+
|
|
491
659
|
function isFieldDirtyByPath(form, path) {
|
|
492
660
|
const live = form.values.get(path.key);
|
|
493
661
|
return form.values.has(path.key) && getDirtyBaseline(form, path.key, path.value) !== live;
|
|
494
662
|
}
|
|
495
663
|
function isDirty(form) {
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
}
|
|
500
|
-
return
|
|
664
|
+
for (const [key, value] of form.values) {
|
|
665
|
+
const path = segmentsFromKey(key);
|
|
666
|
+
if (getDirtyBaseline(form, key, path) !== value) return true;
|
|
667
|
+
}
|
|
668
|
+
return false;
|
|
501
669
|
}
|
|
502
670
|
function forEachDirtyField(form, fn) {
|
|
503
671
|
for (const [key, value] of form.values) {
|
|
504
|
-
const path =
|
|
672
|
+
const path = segmentsFromKey(key);
|
|
505
673
|
if (getDirtyBaseline(form, key, path) !== value) fn(path.join("."));
|
|
506
674
|
}
|
|
507
675
|
}
|
|
@@ -518,11 +686,11 @@
|
|
|
518
686
|
return aKeys.every((key) => b[key] === true);
|
|
519
687
|
}
|
|
520
688
|
function getDirtyFields(form) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
689
|
+
const cache = getOrCreate(dirtyFieldsCaches, form, () => ({
|
|
690
|
+
version: 0,
|
|
691
|
+
result: computeDirtyFields(form)
|
|
692
|
+
}));
|
|
693
|
+
if (cache.version > 0) {
|
|
526
694
|
const result = computeDirtyFields(form);
|
|
527
695
|
if (!sameDirtyKeys(cache.result, result)) cache.result = result;
|
|
528
696
|
cache.version = 0;
|
|
@@ -545,21 +713,18 @@
|
|
|
545
713
|
return touched.has(path.key);
|
|
546
714
|
}
|
|
547
715
|
function getTouchedFields({ touched }) {
|
|
548
|
-
return Array.from(
|
|
549
|
-
touched,
|
|
550
|
-
(key) => JSON.parse(key).join(".")
|
|
551
|
-
);
|
|
716
|
+
return Array.from(touched, (key) => segmentsFromKey(key).join("."));
|
|
552
717
|
}
|
|
553
718
|
function isTouched({ touched }) {
|
|
554
719
|
return touched.size > 0;
|
|
555
720
|
}
|
|
556
721
|
|
|
557
722
|
function getValues(form) {
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
723
|
+
const cache = getOrCreate(valuesCaches, form, () => ({
|
|
724
|
+
version: 0,
|
|
725
|
+
result: computeValues(form)
|
|
726
|
+
}));
|
|
727
|
+
if (cache.version > 0) {
|
|
563
728
|
cache.result = computeValues(form);
|
|
564
729
|
cache.version = 0;
|
|
565
730
|
}
|
|
@@ -570,10 +735,10 @@
|
|
|
570
735
|
const owned = /* @__PURE__ */ new Set();
|
|
571
736
|
let merged = parsedValues ?? initialValues;
|
|
572
737
|
for (const [key, value] of values) {
|
|
573
|
-
merged = setOwned(merged,
|
|
738
|
+
merged = setOwned(merged, segmentsFromKey(key), value, owned);
|
|
574
739
|
}
|
|
575
740
|
for (const key of deleted) {
|
|
576
|
-
merged = unset(merged,
|
|
741
|
+
merged = unset(merged, segmentsFromKey(key));
|
|
577
742
|
}
|
|
578
743
|
return merged;
|
|
579
744
|
}
|
|
@@ -647,7 +812,7 @@
|
|
|
647
812
|
if (!hasLiveBranch(values, segments)) deleted.add(key);
|
|
648
813
|
}
|
|
649
814
|
if (!options?.keepTouched) touched.delete(key);
|
|
650
|
-
if (!options?.keepError
|
|
815
|
+
if (!options?.keepError && errors.delete(key)) bumpErrorsVersion(form);
|
|
651
816
|
validating.delete(key);
|
|
652
817
|
bumpDirtyVersion(form);
|
|
653
818
|
bumpValuesVersion(form);
|
|
@@ -697,9 +862,9 @@
|
|
|
697
862
|
function collectValueLeaves(node, segments, out) {
|
|
698
863
|
if (node !== null && typeof node === "object") {
|
|
699
864
|
if (Array.isArray(node)) {
|
|
700
|
-
|
|
701
|
-
collectValueLeaves(
|
|
702
|
-
|
|
865
|
+
node.forEach(
|
|
866
|
+
(item, i) => collectValueLeaves(item, [...segments, i], out)
|
|
867
|
+
);
|
|
703
868
|
return;
|
|
704
869
|
}
|
|
705
870
|
const keys = Object.keys(node);
|
|
@@ -712,18 +877,22 @@
|
|
|
712
877
|
}
|
|
713
878
|
out.push({ segments, value: node });
|
|
714
879
|
}
|
|
715
|
-
function
|
|
716
|
-
const
|
|
880
|
+
function collectKeptValues(form, options) {
|
|
881
|
+
const kept = [];
|
|
717
882
|
if (options?.keepValues) {
|
|
718
|
-
collectValueLeaves(getValues(form), [],
|
|
883
|
+
collectValueLeaves(getValues(form), [], kept);
|
|
719
884
|
} else if (options?.keepDirtyValues) {
|
|
720
885
|
for (const [key, value] of form.values) {
|
|
721
|
-
const segments =
|
|
886
|
+
const segments = segmentsFromKey(key);
|
|
722
887
|
if (getDirtyBaseline(form, key, segments) !== value) {
|
|
723
|
-
|
|
888
|
+
kept.push({ segments, value });
|
|
724
889
|
}
|
|
725
890
|
}
|
|
726
891
|
}
|
|
892
|
+
return kept;
|
|
893
|
+
}
|
|
894
|
+
function reset(form, initialValues, options) {
|
|
895
|
+
const keptValues = collectKeptValues(form, options);
|
|
727
896
|
form.initialValues = options?.keepDefaultValues ? form.initialValues : initialValues ?? form.initialValues;
|
|
728
897
|
form.parsedValues = void 0;
|
|
729
898
|
if (!options?.keepErrors) clearErrors(form);
|
|
@@ -769,6 +938,7 @@
|
|
|
769
938
|
emit(emitter, "touched", path);
|
|
770
939
|
}
|
|
771
940
|
if (!options?.keepErrors && errors.delete(path.key)) {
|
|
941
|
+
bumpErrorsVersion(form);
|
|
772
942
|
emit(emitter, "errors", path);
|
|
773
943
|
}
|
|
774
944
|
bumpDirtyVersion(form);
|
|
@@ -783,13 +953,17 @@
|
|
|
783
953
|
validating.add(path.key);
|
|
784
954
|
emit(emitter, "validating", path);
|
|
785
955
|
}
|
|
956
|
+
function asErrorList(output) {
|
|
957
|
+
if (output === void 0) return null;
|
|
958
|
+
const list = Array.isArray(output) ? output : [output];
|
|
959
|
+
return list.length ? list : null;
|
|
960
|
+
}
|
|
786
961
|
function registerValidatorByPath(form, path, registration) {
|
|
787
962
|
let timer = null;
|
|
788
963
|
let controller = null;
|
|
789
964
|
let marked = false;
|
|
790
965
|
let lock = null;
|
|
791
966
|
let errorSource = null;
|
|
792
|
-
const hasErrors2 = (errors) => errors !== void 0 && !(Array.isArray(errors) && errors.length === 0);
|
|
793
967
|
const mark = () => {
|
|
794
968
|
if (marked) return;
|
|
795
969
|
marked = true;
|
|
@@ -803,44 +977,42 @@
|
|
|
803
977
|
const runSync = () => {
|
|
804
978
|
const sync = registration.sync();
|
|
805
979
|
if (!sync) return false;
|
|
806
|
-
const
|
|
807
|
-
if (!
|
|
980
|
+
const gate = asErrorList(sync(getValueByPath(form, path), { form, path }));
|
|
981
|
+
if (!gate) {
|
|
808
982
|
if (!registration.validate() || errorSource === "sync") {
|
|
809
983
|
setErrorByPath(form, path, void 0);
|
|
810
984
|
errorSource = null;
|
|
811
985
|
}
|
|
812
986
|
return false;
|
|
813
987
|
}
|
|
814
|
-
setErrorByPath(form, path,
|
|
988
|
+
setErrorByPath(form, path, gate);
|
|
815
989
|
errorSource = "sync";
|
|
816
990
|
return true;
|
|
817
991
|
};
|
|
818
992
|
const collectSyncErrors = () => {
|
|
819
993
|
const sync = registration.sync();
|
|
820
994
|
if (!sync) return null;
|
|
821
|
-
|
|
822
|
-
if (errors === void 0) return null;
|
|
823
|
-
const list = Array.isArray(errors) ? errors : [errors];
|
|
824
|
-
return list.length ? list : null;
|
|
995
|
+
return asErrorList(sync(getValueByPath(form, path), { form, path }));
|
|
825
996
|
};
|
|
826
997
|
const land = (result) => {
|
|
827
998
|
if (registration.asyncAlways?.()) {
|
|
828
999
|
const gate = collectSyncErrors();
|
|
829
|
-
const own =
|
|
1000
|
+
const own = asErrorList(result) ?? [];
|
|
830
1001
|
setErrorByPath(form, path, [...gate ?? [], ...own]);
|
|
831
|
-
errorSource =
|
|
1002
|
+
errorSource = own.length ? "validator" : gate ? "sync" : null;
|
|
832
1003
|
} else {
|
|
833
1004
|
setErrorByPath(form, path, result);
|
|
834
|
-
errorSource =
|
|
1005
|
+
errorSource = asErrorList(result) ? "validator" : null;
|
|
835
1006
|
}
|
|
836
1007
|
};
|
|
837
|
-
const
|
|
1008
|
+
const cancel = () => {
|
|
838
1009
|
if (timer !== null) {
|
|
839
1010
|
clearTimeout(timer);
|
|
840
1011
|
timer = null;
|
|
841
1012
|
}
|
|
842
1013
|
controller?.abort();
|
|
843
1014
|
lock = {};
|
|
1015
|
+
unmark();
|
|
844
1016
|
};
|
|
845
1017
|
const runValidator = () => {
|
|
846
1018
|
const fn = registration.validate();
|
|
@@ -868,13 +1040,11 @@
|
|
|
868
1040
|
return;
|
|
869
1041
|
}
|
|
870
1042
|
mark();
|
|
871
|
-
result.then(
|
|
872
|
-
(
|
|
873
|
-
|
|
874
|
-
land(error);
|
|
875
|
-
}
|
|
1043
|
+
result.then((error) => {
|
|
1044
|
+
if (lock === round) {
|
|
1045
|
+
land(error);
|
|
876
1046
|
}
|
|
877
|
-
).catch(() => {
|
|
1047
|
+
}).catch(() => {
|
|
878
1048
|
}).finally(() => {
|
|
879
1049
|
if (lock === round) {
|
|
880
1050
|
unmark();
|
|
@@ -882,21 +1052,18 @@
|
|
|
882
1052
|
}
|
|
883
1053
|
});
|
|
884
1054
|
};
|
|
1055
|
+
const gateOwnsKick = () => {
|
|
1056
|
+
if (!(runSync() && !registration.asyncAlways?.())) return false;
|
|
1057
|
+
cancel();
|
|
1058
|
+
return true;
|
|
1059
|
+
};
|
|
885
1060
|
const run = () => {
|
|
886
1061
|
timer = null;
|
|
887
|
-
if (
|
|
888
|
-
supersede();
|
|
889
|
-
unmark();
|
|
890
|
-
return;
|
|
891
|
-
}
|
|
1062
|
+
if (gateOwnsKick()) return;
|
|
892
1063
|
runValidator();
|
|
893
1064
|
};
|
|
894
1065
|
const kick = () => {
|
|
895
|
-
if (
|
|
896
|
-
supersede();
|
|
897
|
-
unmark();
|
|
898
|
-
return;
|
|
899
|
-
}
|
|
1066
|
+
if (gateOwnsKick()) return;
|
|
900
1067
|
if (!registration.validate()) return;
|
|
901
1068
|
const debounce = registration.debounce();
|
|
902
1069
|
if (debounce > 0) {
|
|
@@ -910,12 +1077,7 @@
|
|
|
910
1077
|
form.validators.set(path.key, kick);
|
|
911
1078
|
return () => {
|
|
912
1079
|
form.validators.delete(path.key);
|
|
913
|
-
|
|
914
|
-
clearTimeout(timer);
|
|
915
|
-
timer = null;
|
|
916
|
-
}
|
|
917
|
-
unmark();
|
|
918
|
-
controller?.abort();
|
|
1080
|
+
cancel();
|
|
919
1081
|
};
|
|
920
1082
|
}
|
|
921
1083
|
async function trigger(form, name, options) {
|
|
@@ -925,29 +1087,27 @@
|
|
|
925
1087
|
() => keys2 === void 0 ? fieldsSettled(form) : keys2.every((key) => !form.validating.has(key)),
|
|
926
1088
|
() => false
|
|
927
1089
|
);
|
|
1090
|
+
const focusFirstError = (keys2) => {
|
|
1091
|
+
const firstKey = keys2 === void 0 ? form.errors.keys().next().value : keys2.find((key) => form.errors.has(key));
|
|
1092
|
+
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
1093
|
+
};
|
|
928
1094
|
if (name === void 0) {
|
|
929
1095
|
form.validators.forEach((validator) => validator());
|
|
930
1096
|
await settle();
|
|
931
1097
|
if (form.validate) await runFormValidate(form);
|
|
932
1098
|
if (options?.shouldTouch) touchKeys(form, [...form.validators.keys()]);
|
|
933
|
-
if (options?.shouldFocus)
|
|
934
|
-
const firstKey = form.errors.keys().next().value;
|
|
935
|
-
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
936
|
-
}
|
|
1099
|
+
if (options?.shouldFocus) focusFirstError();
|
|
937
1100
|
return !hasErrors(form);
|
|
938
1101
|
}
|
|
939
1102
|
const keys = typeof name === "string" || isSegmentsPath(name) ? [create$1(name).key] : name.map((one) => create$1(one).key);
|
|
940
1103
|
keys.forEach((key) => form.validators.get(key)?.());
|
|
941
1104
|
await settle(keys);
|
|
942
1105
|
if (options?.shouldTouch) touchKeys(form, keys);
|
|
943
|
-
if (options?.shouldFocus)
|
|
944
|
-
const firstKey = keys.find((key) => form.errors.has(key));
|
|
945
|
-
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
946
|
-
}
|
|
1106
|
+
if (options?.shouldFocus) focusFirstError(keys);
|
|
947
1107
|
return keys.every((key) => !form.errors.has(key));
|
|
948
1108
|
}
|
|
949
1109
|
function touchKeys(form, keys) {
|
|
950
|
-
keys.forEach((key) => setTouchedByPath(form, create$1(
|
|
1110
|
+
keys.forEach((key) => setTouchedByPath(form, create$1(segmentsFromKey(key))));
|
|
951
1111
|
}
|
|
952
1112
|
function setFormErrors(form, result, segments = [], footprint) {
|
|
953
1113
|
Object.entries(result).forEach(([key, value]) => {
|
|
@@ -956,16 +1116,9 @@
|
|
|
956
1116
|
...isIndex(key) ? [key] : normalizePath(key)
|
|
957
1117
|
];
|
|
958
1118
|
if (typeof value === "string") {
|
|
959
|
-
if (value)
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
}
|
|
963
|
-
} else if (Array.isArray(value)) {
|
|
964
|
-
setError(form, path, value);
|
|
965
|
-
recordFootprint(form, path, footprint);
|
|
966
|
-
} else if (isFieldError(value)) {
|
|
967
|
-
setError(form, path, value);
|
|
968
|
-
recordFootprint(form, path, footprint);
|
|
1119
|
+
if (value) landLeafError(form, path, value, footprint);
|
|
1120
|
+
} else if (Array.isArray(value) || isFieldError(value)) {
|
|
1121
|
+
landLeafError(form, path, value, footprint);
|
|
969
1122
|
} else if (value && typeof value === "object") {
|
|
970
1123
|
setFormErrors(form, value, path, footprint);
|
|
971
1124
|
}
|
|
@@ -977,8 +1130,12 @@
|
|
|
977
1130
|
const stored = form.errors.get(path.key);
|
|
978
1131
|
if (stored) footprint.set(path.key, stored);
|
|
979
1132
|
}
|
|
1133
|
+
function landLeafError(form, path, error, footprint) {
|
|
1134
|
+
setError(form, path, error);
|
|
1135
|
+
recordFootprint(form, path, footprint);
|
|
1136
|
+
}
|
|
980
1137
|
function applyValidateResult(form, result) {
|
|
981
|
-
const footprint = form.validateDeps ? getFormErrorFootprint(form) : void 0;
|
|
1138
|
+
const footprint = form.validateDeps || form.validateMode !== "onSubmit" ? getFormErrorFootprint(form) : void 0;
|
|
982
1139
|
if (footprint) {
|
|
983
1140
|
clearFormValidateErrors(form, footprint);
|
|
984
1141
|
footprint.clear();
|
|
@@ -994,12 +1151,7 @@
|
|
|
994
1151
|
}
|
|
995
1152
|
const formErrorFootprints = /* @__PURE__ */ new WeakMap();
|
|
996
1153
|
function getFormErrorFootprint(form) {
|
|
997
|
-
|
|
998
|
-
if (!footprint) {
|
|
999
|
-
footprint = /* @__PURE__ */ new Map();
|
|
1000
|
-
formErrorFootprints.set(form, footprint);
|
|
1001
|
-
}
|
|
1002
|
-
return footprint;
|
|
1154
|
+
return getOrCreate(formErrorFootprints, form, () => /* @__PURE__ */ new Map());
|
|
1003
1155
|
}
|
|
1004
1156
|
function hasFormValidateErrors(form) {
|
|
1005
1157
|
const footprint = formErrorFootprints.get(form);
|
|
@@ -1014,7 +1166,8 @@
|
|
|
1014
1166
|
const stored = form.errors.get(key);
|
|
1015
1167
|
if (stored !== written) continue;
|
|
1016
1168
|
form.errors.delete(key);
|
|
1017
|
-
|
|
1169
|
+
bumpErrorsVersion(form);
|
|
1170
|
+
emit(form.emitter, "errors", create$1(segmentsFromKey(key)));
|
|
1018
1171
|
}
|
|
1019
1172
|
}
|
|
1020
1173
|
const FORM_VALIDATING_KEY = "__form_validate__";
|
|
@@ -1027,18 +1180,13 @@
|
|
|
1027
1180
|
const SETTLED = /* @__PURE__ */ Symbol("form-validate-settled");
|
|
1028
1181
|
const formValidateStates = /* @__PURE__ */ new WeakMap();
|
|
1029
1182
|
function getFormValidateState(form) {
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
waiters: []
|
|
1038
|
-
};
|
|
1039
|
-
formValidateStates.set(form, state);
|
|
1040
|
-
}
|
|
1041
|
-
return state;
|
|
1183
|
+
return getOrCreate(formValidateStates, form, () => ({
|
|
1184
|
+
timer: null,
|
|
1185
|
+
controller: null,
|
|
1186
|
+
round: null,
|
|
1187
|
+
marked: false,
|
|
1188
|
+
waiters: []
|
|
1189
|
+
}));
|
|
1042
1190
|
}
|
|
1043
1191
|
function runFormValidate(form) {
|
|
1044
1192
|
const validate2 = form.validate;
|
|
@@ -1076,14 +1224,9 @@
|
|
|
1076
1224
|
if (!validate2) return Promise.resolve();
|
|
1077
1225
|
state.controller?.abort();
|
|
1078
1226
|
const controller = state.controller = new AbortController();
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
validate2(getValues(form), { form, signal: controller.signal })
|
|
1083
|
-
);
|
|
1084
|
-
} catch (error) {
|
|
1085
|
-
outcome = Promise.reject(error);
|
|
1086
|
-
}
|
|
1227
|
+
const outcome = new Promise(
|
|
1228
|
+
(resolve) => resolve(validate2(getValues(form), { form, signal: controller.signal }))
|
|
1229
|
+
);
|
|
1087
1230
|
return outcome.then(
|
|
1088
1231
|
(result) => {
|
|
1089
1232
|
if (state.round === round) applyValidateResult(form, result);
|
|
@@ -1109,27 +1252,29 @@
|
|
|
1109
1252
|
else waiter.reject(outcome);
|
|
1110
1253
|
}
|
|
1111
1254
|
}
|
|
1255
|
+
function shouldKick(mode, cadence, touched, hasError, reValidateMode) {
|
|
1256
|
+
return mode === cadence || mode === "all" || mode === "onTouched" && touched || reValidateMode === cadence && hasError();
|
|
1257
|
+
}
|
|
1112
1258
|
function revalidateFormOnChange(form, path, mode) {
|
|
1113
1259
|
if (!form.validateDeps?.has(path.key) || !form.validate) return;
|
|
1114
|
-
if (
|
|
1260
|
+
if (shouldKick(
|
|
1261
|
+
mode,
|
|
1262
|
+
"onChange",
|
|
1263
|
+
hasTouchedByPath(form, path),
|
|
1264
|
+
() => hasFormValidateErrors(form),
|
|
1265
|
+
form.reValidateMode
|
|
1266
|
+
)) {
|
|
1115
1267
|
runFormValidate(form).catch(() => {
|
|
1116
1268
|
});
|
|
1117
1269
|
}
|
|
1118
1270
|
}
|
|
1119
1271
|
const fieldValidateDeps = /* @__PURE__ */ new WeakMap();
|
|
1120
1272
|
function registerFieldValidateDeps(form, key, depKeys) {
|
|
1121
|
-
|
|
1122
|
-
if (!deps) {
|
|
1123
|
-
deps = /* @__PURE__ */ new Map();
|
|
1124
|
-
fieldValidateDeps.set(form, deps);
|
|
1125
|
-
}
|
|
1273
|
+
const deps = getOrCreate(fieldValidateDeps, form, () => /* @__PURE__ */ new Map());
|
|
1126
1274
|
for (const depKey of depKeys) {
|
|
1127
|
-
|
|
1128
|
-
if (!dependents) {
|
|
1129
|
-
dependents = /* @__PURE__ */ new Set();
|
|
1130
|
-
deps.set(depKey, dependents);
|
|
1131
|
-
}
|
|
1275
|
+
const dependents = deps.get(depKey) ?? /* @__PURE__ */ new Set();
|
|
1132
1276
|
dependents.add(key);
|
|
1277
|
+
deps.set(depKey, dependents);
|
|
1133
1278
|
}
|
|
1134
1279
|
}
|
|
1135
1280
|
function unregisterFieldValidateDeps(form, key, depKeys) {
|
|
@@ -1146,7 +1291,13 @@
|
|
|
1146
1291
|
if (!dependents?.size) return;
|
|
1147
1292
|
for (const dependent of dependents) {
|
|
1148
1293
|
if (dependent === path.key) continue;
|
|
1149
|
-
if (
|
|
1294
|
+
if (shouldKick(
|
|
1295
|
+
mode,
|
|
1296
|
+
"onChange",
|
|
1297
|
+
hasTouchedByPath(form, path),
|
|
1298
|
+
() => form.errors.has(dependent),
|
|
1299
|
+
form.reValidateMode
|
|
1300
|
+
)) {
|
|
1150
1301
|
form.validators.get(dependent)?.();
|
|
1151
1302
|
}
|
|
1152
1303
|
}
|
|
@@ -1188,11 +1339,7 @@
|
|
|
1188
1339
|
}
|
|
1189
1340
|
}
|
|
1190
1341
|
function registerFieldMode(form, path, mode) {
|
|
1191
|
-
|
|
1192
|
-
if (!modes) {
|
|
1193
|
-
modes = /* @__PURE__ */ new Map();
|
|
1194
|
-
fieldModes.set(form, modes);
|
|
1195
|
-
}
|
|
1342
|
+
const modes = getOrCreate(fieldModes, form, () => /* @__PURE__ */ new Map());
|
|
1196
1343
|
const displaced = modes.has(path.key);
|
|
1197
1344
|
const token = {};
|
|
1198
1345
|
modes.set(path.key, { mode, token });
|
|
@@ -1203,10 +1350,38 @@
|
|
|
1203
1350
|
const entry = modes?.get(path.key);
|
|
1204
1351
|
if (modes && entry && entry.token === token) modes.delete(path.key);
|
|
1205
1352
|
}
|
|
1206
|
-
function
|
|
1207
|
-
|
|
1353
|
+
function firstMountedDescendantKey(form, ancestor) {
|
|
1354
|
+
const prefix = `${ancestor.key.slice(0, -1)},`;
|
|
1355
|
+
for (const key of fieldModes.get(form)?.keys() ?? []) {
|
|
1356
|
+
if (key.startsWith(prefix)) return key;
|
|
1357
|
+
}
|
|
1358
|
+
return void 0;
|
|
1359
|
+
}
|
|
1360
|
+
function fireFormValidate(form, cadence) {
|
|
1361
|
+
if (form.validateMode !== cadence || !form.validate) return;
|
|
1362
|
+
runFormValidate(form).catch(() => {
|
|
1363
|
+
});
|
|
1364
|
+
}
|
|
1365
|
+
function kickFieldValidator(form, path, mode, cadence, touched) {
|
|
1366
|
+
if (shouldKick(
|
|
1367
|
+
mode,
|
|
1368
|
+
cadence,
|
|
1369
|
+
touched,
|
|
1370
|
+
() => getFieldErrorsByPath(form, path).length > 0,
|
|
1371
|
+
form.reValidateMode
|
|
1372
|
+
))
|
|
1208
1373
|
form.validators.get(path.key)?.();
|
|
1374
|
+
}
|
|
1375
|
+
function runUserChangeGate(form, path, mode) {
|
|
1376
|
+
kickFieldValidator(
|
|
1377
|
+
form,
|
|
1378
|
+
path,
|
|
1379
|
+
mode,
|
|
1380
|
+
"onChange",
|
|
1381
|
+
hasTouchedByPath(form, path)
|
|
1382
|
+
);
|
|
1209
1383
|
revalidateFormOnChange(form, path, mode);
|
|
1384
|
+
fireFormValidate(form, "onChange");
|
|
1210
1385
|
revalidateDependentsOnChange(form, path, mode);
|
|
1211
1386
|
}
|
|
1212
1387
|
function userChangeByPath(form, path, value) {
|
|
@@ -1218,9 +1393,323 @@
|
|
|
1218
1393
|
setTouchedByPath(form, path);
|
|
1219
1394
|
const entry = fieldModes.get(form)?.get(path.key);
|
|
1220
1395
|
if (!entry) return;
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1396
|
+
kickFieldValidator(form, path, entry.mode ?? form.mode, "onBlur", true);
|
|
1397
|
+
fireFormValidate(form, "onBlur");
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
function removeFieldForUnmount(form, path) {
|
|
1401
|
+
const { key } = path;
|
|
1402
|
+
const snapshot = {
|
|
1403
|
+
present: form.values.has(key),
|
|
1404
|
+
value: form.values.get(key),
|
|
1405
|
+
touched: form.touched.has(key),
|
|
1406
|
+
errors: form.errors.get(key)
|
|
1407
|
+
};
|
|
1408
|
+
removeFieldByPath(form, path);
|
|
1409
|
+
return snapshot;
|
|
1410
|
+
}
|
|
1411
|
+
function restoreRemovedField(form, path, snapshot) {
|
|
1412
|
+
const { key } = path;
|
|
1413
|
+
if (snapshot.present) {
|
|
1414
|
+
setValueByPath(form, path, snapshot.value, { shouldDirty: false });
|
|
1415
|
+
} else {
|
|
1416
|
+
form.deleted.delete(key);
|
|
1417
|
+
bumpValuesVersion(form);
|
|
1418
|
+
emit(form.emitter, "change", path);
|
|
1419
|
+
}
|
|
1420
|
+
if (snapshot.touched) setTouchedByPath(form, path);
|
|
1421
|
+
if (snapshot.errors) setErrorByPath(form, path, snapshot.errors);
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
function hasRuleConstraints(rules) {
|
|
1425
|
+
return rules.required !== void 0 || rules.min !== void 0 || rules.max !== void 0 || rules.minLength !== void 0 || rules.maxLength !== void 0 || rules.pattern !== void 0 || rules.validate !== void 0;
|
|
1426
|
+
}
|
|
1427
|
+
function defaultMessage(type, bound) {
|
|
1428
|
+
switch (type) {
|
|
1429
|
+
case "required":
|
|
1430
|
+
return "This field is required";
|
|
1431
|
+
case "min":
|
|
1432
|
+
return `Must be at least ${bound}`;
|
|
1433
|
+
case "max":
|
|
1434
|
+
return `Must be at most ${bound}`;
|
|
1435
|
+
case "minLength":
|
|
1436
|
+
return `Must be at least ${bound} characters`;
|
|
1437
|
+
case "maxLength":
|
|
1438
|
+
return `Must be at most ${bound} characters`;
|
|
1439
|
+
case "pattern":
|
|
1440
|
+
return "Invalid format";
|
|
1441
|
+
default:
|
|
1442
|
+
return "Invalid value";
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
function resolveMessage(entry, bound) {
|
|
1446
|
+
return typeof entry === "function" ? entry(bound) : entry?.replace("{bound}", String(bound));
|
|
1447
|
+
}
|
|
1448
|
+
function numericMetric(value) {
|
|
1449
|
+
const n = Number(value);
|
|
1450
|
+
return Number.isNaN(n) ? void 0 : n;
|
|
1451
|
+
}
|
|
1452
|
+
function sizedMetric(value) {
|
|
1453
|
+
return typeof value === "string" || Array.isArray(value) ? value.length : void 0;
|
|
1454
|
+
}
|
|
1455
|
+
const BOUND_CHECKS = [
|
|
1456
|
+
["min", numericMetric, (metric, bound) => metric < bound],
|
|
1457
|
+
["max", numericMetric, (metric, bound) => metric > bound],
|
|
1458
|
+
["minLength", sizedMetric, (metric, bound) => metric < bound],
|
|
1459
|
+
["maxLength", sizedMetric, (metric, bound) => metric > bound]
|
|
1460
|
+
];
|
|
1461
|
+
function rulesToValidator(rules, formMessages) {
|
|
1462
|
+
return (value, meta) => {
|
|
1463
|
+
if (rules.required) {
|
|
1464
|
+
if (value === "" || value === void 0 || value === null || Array.isArray(value) && value.length === 0) {
|
|
1465
|
+
return [
|
|
1466
|
+
{
|
|
1467
|
+
type: "required",
|
|
1468
|
+
message: typeof rules.required === "string" ? rules.required : resolveMessage(formMessages?.required) ?? defaultMessage("required")
|
|
1469
|
+
}
|
|
1470
|
+
];
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
const errors = [];
|
|
1474
|
+
const message = (type, bound) => rules.messages?.[type] ?? resolveMessage(formMessages?.[type], bound) ?? defaultMessage(type, bound);
|
|
1475
|
+
for (const [type, measure, fails] of BOUND_CHECKS) {
|
|
1476
|
+
const bound = rules[type];
|
|
1477
|
+
if (bound === void 0) continue;
|
|
1478
|
+
const metric = measure(value);
|
|
1479
|
+
if (metric !== void 0 && fails(metric, bound)) {
|
|
1480
|
+
errors.push({ type, message: message(type, bound) });
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
if (rules.pattern && !rules.pattern.value.test(value)) {
|
|
1484
|
+
errors.push({
|
|
1485
|
+
type: "pattern",
|
|
1486
|
+
// pattern.message is type-required but JS consumers may omit it.
|
|
1487
|
+
message: rules.messages?.pattern ?? rules.pattern.message ?? resolveMessage(formMessages?.pattern) ?? defaultMessage("pattern")
|
|
1488
|
+
});
|
|
1489
|
+
}
|
|
1490
|
+
if (rules.validate !== void 0) {
|
|
1491
|
+
const fns = typeof rules.validate === "function" ? { validate: rules.validate } : rules.validate;
|
|
1492
|
+
for (const [type, fn] of Object.entries(fns)) {
|
|
1493
|
+
const result = fn(value, meta);
|
|
1494
|
+
if (result === void 0) continue;
|
|
1495
|
+
for (const entry of Array.isArray(result) ? result : [result]) {
|
|
1496
|
+
errors.push(
|
|
1497
|
+
typeof entry === "string" ? { type, message: entry } : { ...entry, type }
|
|
1498
|
+
);
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
return errors.length ? errors : void 0;
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
function rulesToConstraintAttrs(rules) {
|
|
1506
|
+
const attrs = {};
|
|
1507
|
+
if (rules.required) attrs.required = true;
|
|
1508
|
+
for (const key of ["min", "max", "minLength", "maxLength"]) {
|
|
1509
|
+
if (rules[key] !== void 0) attrs[key] = rules[key];
|
|
1510
|
+
}
|
|
1511
|
+
if (rules.pattern) attrs.pattern = rules.pattern.value.source;
|
|
1512
|
+
return attrs;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
function registerField(form, name, options) {
|
|
1516
|
+
const path = create$1(name);
|
|
1517
|
+
const {
|
|
1518
|
+
mode,
|
|
1519
|
+
shouldUnregister,
|
|
1520
|
+
eventToValue,
|
|
1521
|
+
valueAsNumber,
|
|
1522
|
+
valueAsDate,
|
|
1523
|
+
rules
|
|
1524
|
+
} = options ?? {};
|
|
1525
|
+
const toValue = eventToValue ?? ((e) => {
|
|
1526
|
+
const target = e?.target;
|
|
1527
|
+
if (!target) return e;
|
|
1528
|
+
if (target.type === "file") return target.files;
|
|
1529
|
+
if (target.type === "checkbox") return target.checked;
|
|
1530
|
+
if (valueAsNumber) return target.valueAsNumber;
|
|
1531
|
+
if (valueAsDate) return target.valueAsDate;
|
|
1532
|
+
return target.value;
|
|
1533
|
+
});
|
|
1534
|
+
let el = null;
|
|
1535
|
+
let modeToken = null;
|
|
1536
|
+
let disposeValidator = null;
|
|
1537
|
+
let snapshot = null;
|
|
1538
|
+
let offFocus = null;
|
|
1539
|
+
let offBulkSync = null;
|
|
1540
|
+
const syncDom = () => {
|
|
1541
|
+
if (!el || el.type === "file") return;
|
|
1542
|
+
const next = getValueByPath(form, path);
|
|
1543
|
+
const asString = next == null ? "" : String(next);
|
|
1544
|
+
if (el.value !== asString) el.value = asString;
|
|
1545
|
+
};
|
|
1546
|
+
const attach = (node) => {
|
|
1547
|
+
if (snapshot) {
|
|
1548
|
+
restoreRemovedField(form, path, snapshot);
|
|
1549
|
+
snapshot = null;
|
|
1550
|
+
}
|
|
1551
|
+
el = node;
|
|
1552
|
+
if (node.type !== "file" && getValueByPath(form, path) === void 0) {
|
|
1553
|
+
seedValueByPath(
|
|
1554
|
+
form,
|
|
1555
|
+
path,
|
|
1556
|
+
node.type === "checkbox" ? node.checked : node.value
|
|
1557
|
+
);
|
|
1558
|
+
emitChangeByPath(form, path);
|
|
1559
|
+
}
|
|
1560
|
+
modeToken = registerFieldMode(form, path, mode).token;
|
|
1561
|
+
if (rules && hasRuleConstraints(rules)) {
|
|
1562
|
+
const { required, ...rest } = rules;
|
|
1563
|
+
const requiredGate = required !== void 0 ? rulesToValidator({ required }, form.messages) : void 0;
|
|
1564
|
+
disposeValidator = registerValidatorByPath(form, path, {
|
|
1565
|
+
validate: () => hasRuleConstraints(rest) ? rulesToValidator(rest, form.messages) : void 0,
|
|
1566
|
+
debounce: () => 0,
|
|
1567
|
+
sync: () => requiredGate
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1570
|
+
offFocus = on(
|
|
1571
|
+
form.emitter,
|
|
1572
|
+
"focusError",
|
|
1573
|
+
(key, options2) => {
|
|
1574
|
+
if (key !== path.key || !el || typeof el.focus !== "function") return;
|
|
1575
|
+
el.focus();
|
|
1576
|
+
if (options2?.shouldSelect && typeof el.select === "function") {
|
|
1577
|
+
el.select();
|
|
1578
|
+
}
|
|
1579
|
+
}
|
|
1580
|
+
);
|
|
1581
|
+
offBulkSync = on(form.emitter, "change", (changed) => {
|
|
1582
|
+
if (changed) return;
|
|
1583
|
+
syncDom();
|
|
1584
|
+
});
|
|
1585
|
+
};
|
|
1586
|
+
const detach = () => {
|
|
1587
|
+
if (modeToken) {
|
|
1588
|
+
unregisterFieldMode(form, path, modeToken);
|
|
1589
|
+
modeToken = null;
|
|
1590
|
+
}
|
|
1591
|
+
if (disposeValidator) {
|
|
1592
|
+
disposeValidator();
|
|
1593
|
+
disposeValidator = null;
|
|
1594
|
+
}
|
|
1595
|
+
if (offFocus) {
|
|
1596
|
+
offFocus();
|
|
1597
|
+
offFocus = null;
|
|
1598
|
+
}
|
|
1599
|
+
if (offBulkSync) {
|
|
1600
|
+
offBulkSync();
|
|
1601
|
+
offBulkSync = null;
|
|
1602
|
+
}
|
|
1603
|
+
el = null;
|
|
1604
|
+
if ((shouldUnregister ?? form.shouldUnregister) !== false) {
|
|
1605
|
+
snapshot = removeFieldForUnmount(form, path);
|
|
1606
|
+
}
|
|
1607
|
+
};
|
|
1608
|
+
return {
|
|
1609
|
+
name: path.key,
|
|
1610
|
+
onChange: (e) => changeValueByPath(form, path, toValue(e)),
|
|
1611
|
+
onBlur: () => userBlur(form, path),
|
|
1612
|
+
ref: (node) => {
|
|
1613
|
+
if (node) attach(node);
|
|
1614
|
+
else detach();
|
|
1615
|
+
}
|
|
1616
|
+
};
|
|
1617
|
+
}
|
|
1618
|
+
|
|
1619
|
+
function readArray(form, path) {
|
|
1620
|
+
const value = getValueByPath(form, path);
|
|
1621
|
+
return Array.isArray(value) ? value : [];
|
|
1622
|
+
}
|
|
1623
|
+
function appendValueByPath(form, path, value) {
|
|
1624
|
+
const arr = readArray(form, path);
|
|
1625
|
+
setValueByPath(form, path, [...arr, value]);
|
|
1626
|
+
}
|
|
1627
|
+
function prependValueByPath(form, path, value) {
|
|
1628
|
+
const arr = readArray(form, path);
|
|
1629
|
+
setValueByPath(form, path, [value, ...arr]);
|
|
1630
|
+
}
|
|
1631
|
+
function insertValueByPath(form, path, index, value) {
|
|
1632
|
+
const arr = readArray(form, path);
|
|
1633
|
+
if (index < 0 || index > arr.length) return false;
|
|
1634
|
+
setValueByPath(form, path, [
|
|
1635
|
+
...arr.slice(0, index),
|
|
1636
|
+
value,
|
|
1637
|
+
...arr.slice(index)
|
|
1638
|
+
]);
|
|
1639
|
+
return true;
|
|
1640
|
+
}
|
|
1641
|
+
function removeValueByPath(form, path, indices) {
|
|
1642
|
+
const arr = readArray(form, path);
|
|
1643
|
+
const drop = /* @__PURE__ */ new Set();
|
|
1644
|
+
for (const index of Array.isArray(indices) ? indices : [indices]) {
|
|
1645
|
+
if (index >= 0 && index < arr.length) drop.add(index);
|
|
1646
|
+
}
|
|
1647
|
+
if (drop.size === 0) return [];
|
|
1648
|
+
const dropped = [...drop].sort((a, b) => b - a);
|
|
1649
|
+
setValueByPath(
|
|
1650
|
+
form,
|
|
1651
|
+
path,
|
|
1652
|
+
arr.filter((_, i) => !drop.has(i))
|
|
1653
|
+
);
|
|
1654
|
+
return dropped;
|
|
1655
|
+
}
|
|
1656
|
+
function moveValueByPath(form, path, from, to) {
|
|
1657
|
+
const arr = readArray(form, path);
|
|
1658
|
+
if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) {
|
|
1659
|
+
return false;
|
|
1660
|
+
}
|
|
1661
|
+
if (from === to) return false;
|
|
1662
|
+
const next = [...arr];
|
|
1663
|
+
const [item] = next.splice(from, 1);
|
|
1664
|
+
next.splice(to, 0, item);
|
|
1665
|
+
setValueByPath(form, path, next);
|
|
1666
|
+
return true;
|
|
1667
|
+
}
|
|
1668
|
+
function swapValuesByPath(form, path, from, to) {
|
|
1669
|
+
const arr = readArray(form, path);
|
|
1670
|
+
if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) {
|
|
1671
|
+
return false;
|
|
1672
|
+
}
|
|
1673
|
+
if (from === to) return false;
|
|
1674
|
+
const next = [...arr];
|
|
1675
|
+
[next[from], next[to]] = [next[to], next[from]];
|
|
1676
|
+
setValueByPath(form, path, next);
|
|
1677
|
+
return true;
|
|
1678
|
+
}
|
|
1679
|
+
function replaceValuesByPath(form, path, values) {
|
|
1680
|
+
setValueByPath(form, path, [...values]);
|
|
1681
|
+
}
|
|
1682
|
+
function updateValueByPath(form, path, index, value) {
|
|
1683
|
+
const arr = readArray(form, path);
|
|
1684
|
+
if (index < 0 || index >= arr.length) return false;
|
|
1685
|
+
const next = [...arr];
|
|
1686
|
+
next[index] = value;
|
|
1687
|
+
setValueByPath(form, path, next);
|
|
1688
|
+
return true;
|
|
1689
|
+
}
|
|
1690
|
+
function appendValue(form, name, value) {
|
|
1691
|
+
appendValueByPath(form, create$1(name), value);
|
|
1692
|
+
}
|
|
1693
|
+
function prependValue(form, name, value) {
|
|
1694
|
+
prependValueByPath(form, create$1(name), value);
|
|
1695
|
+
}
|
|
1696
|
+
function insertValue(form, name, index, value) {
|
|
1697
|
+
return insertValueByPath(form, create$1(name), index, value);
|
|
1698
|
+
}
|
|
1699
|
+
function removeValue(form, name, indices) {
|
|
1700
|
+
return removeValueByPath(form, create$1(name), indices);
|
|
1701
|
+
}
|
|
1702
|
+
function moveValue(form, name, from, to) {
|
|
1703
|
+
return moveValueByPath(form, create$1(name), from, to);
|
|
1704
|
+
}
|
|
1705
|
+
function swapValues(form, name, from, to) {
|
|
1706
|
+
return swapValuesByPath(form, create$1(name), from, to);
|
|
1707
|
+
}
|
|
1708
|
+
function replaceValues(form, name, values) {
|
|
1709
|
+
replaceValuesByPath(form, create$1(name), values);
|
|
1710
|
+
}
|
|
1711
|
+
function updateValue(form, name, index, value) {
|
|
1712
|
+
return updateValueByPath(form, create$1(name), index, value);
|
|
1224
1713
|
}
|
|
1225
1714
|
|
|
1226
1715
|
function setIsSubmitting(form, value) {
|
|
@@ -1255,9 +1744,7 @@
|
|
|
1255
1744
|
}
|
|
1256
1745
|
function getNativeErrors(formEl) {
|
|
1257
1746
|
const errors = [];
|
|
1258
|
-
const
|
|
1259
|
-
for (let i = 0; i < elements.length; i++) {
|
|
1260
|
-
const el = elements[i];
|
|
1747
|
+
for (const el of formEl.elements) {
|
|
1261
1748
|
if (el.name && typeof el.checkValidity === "function" && !el.checkValidity()) {
|
|
1262
1749
|
errors.push({
|
|
1263
1750
|
path: nameToPath(el.name),
|
|
@@ -1274,18 +1761,21 @@
|
|
|
1274
1761
|
onValidSubmit,
|
|
1275
1762
|
onInvalidSubmit,
|
|
1276
1763
|
onAction,
|
|
1277
|
-
shouldFocusError = true
|
|
1764
|
+
shouldFocusError = true,
|
|
1765
|
+
shouldUseNativeValidation = form.shouldUseNativeValidation
|
|
1278
1766
|
} = options ?? {};
|
|
1279
1767
|
return async (e) => {
|
|
1280
1768
|
if (e && typeof e.preventDefault === "function") {
|
|
1281
1769
|
e.preventDefault();
|
|
1282
1770
|
}
|
|
1283
1771
|
const formEl = e?.currentTarget;
|
|
1772
|
+
if (form.isSubmitting) return;
|
|
1773
|
+
clearServerErrors(form);
|
|
1284
1774
|
form.isSubmitted = true;
|
|
1285
1775
|
setIsSubmitting(form, true);
|
|
1286
1776
|
incrementSubmitCount(form);
|
|
1287
1777
|
const values = getValues(form);
|
|
1288
|
-
if (formEl && typeof formEl.checkValidity === "function" && formEl.checkValidity() === false) {
|
|
1778
|
+
if (shouldUseNativeValidation && formEl && typeof formEl.checkValidity === "function" && formEl.checkValidity() === false) {
|
|
1289
1779
|
formEl.reportValidity();
|
|
1290
1780
|
if (shouldFocusError && typeof formEl.querySelector === "function") {
|
|
1291
1781
|
const invalid = formEl.querySelector(":invalid");
|
|
@@ -1311,7 +1801,14 @@
|
|
|
1311
1801
|
const submitted = getValues(form);
|
|
1312
1802
|
if (onSubmit) await onSubmit(submitted, e);
|
|
1313
1803
|
if (onValidSubmit) await onValidSubmit(submitted, e);
|
|
1314
|
-
if (onAction)
|
|
1804
|
+
if (onAction) {
|
|
1805
|
+
const result = await onAction(submitted, e);
|
|
1806
|
+
if (result && typeof result === "object" && result.errors !== void 0 && typeof result.errors === "object") {
|
|
1807
|
+
setServerErrors(form, result.errors);
|
|
1808
|
+
setSubmitSuccessful(form, false);
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1315
1812
|
setSubmitSuccessful(form, true);
|
|
1316
1813
|
} catch {
|
|
1317
1814
|
setSubmitSuccessful(form, false);
|
|
@@ -1327,19 +1824,45 @@
|
|
|
1327
1824
|
else emit(form.emitter, "focusError", key);
|
|
1328
1825
|
}
|
|
1329
1826
|
|
|
1827
|
+
function seedInitialValues(form, emitter, source) {
|
|
1828
|
+
if (!isPromise(source)) {
|
|
1829
|
+
form.initialValues = source;
|
|
1830
|
+
return;
|
|
1831
|
+
}
|
|
1832
|
+
form.isLoading = true;
|
|
1833
|
+
emit(emitter, "loading");
|
|
1834
|
+
Promise.resolve(source).then(
|
|
1835
|
+
(resolved) => {
|
|
1836
|
+
setInitialValues(form, resolved ?? {});
|
|
1837
|
+
form.isLoading = false;
|
|
1838
|
+
emit(emitter, "loading");
|
|
1839
|
+
},
|
|
1840
|
+
(error) => {
|
|
1841
|
+
form.isLoading = false;
|
|
1842
|
+
emit(emitter, "loading");
|
|
1843
|
+
}
|
|
1844
|
+
);
|
|
1845
|
+
}
|
|
1330
1846
|
function create(options) {
|
|
1331
1847
|
const emitter = create$2();
|
|
1332
1848
|
_setMaxListeners(emitter, 0);
|
|
1333
|
-
|
|
1334
|
-
|
|
1849
|
+
const initialSource = options?.initialValues ?? {};
|
|
1850
|
+
const source = typeof initialSource === "function" ? initialSource() : initialSource;
|
|
1851
|
+
const validateOption = options?.validate;
|
|
1852
|
+
const wrappedValidate = validateOption && hasStandardProps(validateOption) ? schemaToFormValidator(
|
|
1853
|
+
validateOption
|
|
1854
|
+
) : validateOption;
|
|
1335
1855
|
const form = {
|
|
1336
1856
|
emitter,
|
|
1337
1857
|
...options,
|
|
1858
|
+
validate: wrappedValidate,
|
|
1338
1859
|
mode: options?.mode ?? "onSubmit",
|
|
1339
1860
|
reValidateMode: options?.reValidateMode ?? "onChange",
|
|
1861
|
+
validateMode: options?.validateMode ?? "onSubmit",
|
|
1340
1862
|
disabled: options?.disabled ?? false,
|
|
1341
1863
|
validateOnMount: options?.validateOnMount ?? false,
|
|
1342
1864
|
asyncAlways: options?.asyncAlways ?? false,
|
|
1865
|
+
shouldUseNativeValidation: options?.shouldUseNativeValidation ?? true,
|
|
1343
1866
|
validateDeps: options?.validateDeps ? new Set(options.validateDeps.map((dep) => create$1(dep).key)) : void 0,
|
|
1344
1867
|
initialValues: {},
|
|
1345
1868
|
values: /* @__PURE__ */ new Map(),
|
|
@@ -1354,116 +1877,47 @@
|
|
|
1354
1877
|
submitCount: 0,
|
|
1355
1878
|
isSubmitSuccessful: void 0,
|
|
1356
1879
|
isLoading: false,
|
|
1357
|
-
status: void 0
|
|
1880
|
+
status: void 0,
|
|
1881
|
+
register: (name, registerOptions) => registerField(form, name, registerOptions)
|
|
1358
1882
|
};
|
|
1359
|
-
|
|
1360
|
-
form.isLoading = true;
|
|
1361
|
-
emit(emitter, "loading");
|
|
1362
|
-
Promise.resolve(source).then(
|
|
1363
|
-
(resolved) => {
|
|
1364
|
-
setInitialValues(form, resolved ?? {});
|
|
1365
|
-
form.isLoading = false;
|
|
1366
|
-
emit(emitter, "loading");
|
|
1367
|
-
},
|
|
1368
|
-
(error) => {
|
|
1369
|
-
form.isLoading = false;
|
|
1370
|
-
emit(emitter, "loading");
|
|
1371
|
-
}
|
|
1372
|
-
);
|
|
1373
|
-
} else {
|
|
1374
|
-
form.initialValues = source;
|
|
1375
|
-
}
|
|
1883
|
+
seedInitialValues(form, emitter, source);
|
|
1376
1884
|
return form;
|
|
1377
1885
|
}
|
|
1378
1886
|
|
|
1379
|
-
function
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
const
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
if (!Number.isNaN(n) && n < rules.min) {
|
|
1414
|
-
errors.push({ type: "min", message: message("min", rules.min) });
|
|
1415
|
-
}
|
|
1416
|
-
}
|
|
1417
|
-
if (rules.max !== void 0) {
|
|
1418
|
-
const n = Number(value);
|
|
1419
|
-
if (!Number.isNaN(n) && n > rules.max) {
|
|
1420
|
-
errors.push({ type: "max", message: message("max", rules.max) });
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
const isSized = typeof value === "string" || Array.isArray(value);
|
|
1424
|
-
if (rules.minLength !== void 0 && isSized && value.length < rules.minLength) {
|
|
1425
|
-
errors.push({
|
|
1426
|
-
type: "minLength",
|
|
1427
|
-
message: message("minLength", rules.minLength)
|
|
1428
|
-
});
|
|
1429
|
-
}
|
|
1430
|
-
if (rules.maxLength !== void 0 && isSized && value.length > rules.maxLength) {
|
|
1431
|
-
errors.push({
|
|
1432
|
-
type: "maxLength",
|
|
1433
|
-
message: message("maxLength", rules.maxLength)
|
|
1434
|
-
});
|
|
1435
|
-
}
|
|
1436
|
-
if (rules.pattern && !rules.pattern.value.test(value)) {
|
|
1437
|
-
errors.push({
|
|
1438
|
-
type: "pattern",
|
|
1439
|
-
// pattern.message is type-required but JS consumers may omit it.
|
|
1440
|
-
message: rules.messages?.pattern ?? rules.pattern.message ?? defaultMessage("pattern")
|
|
1441
|
-
});
|
|
1442
|
-
}
|
|
1443
|
-
if (rules.validate !== void 0) {
|
|
1444
|
-
const fns = typeof rules.validate === "function" ? { validate: rules.validate } : rules.validate;
|
|
1445
|
-
for (const [type, fn] of Object.entries(fns)) {
|
|
1446
|
-
const result = fn(value, meta);
|
|
1447
|
-
if (result === void 0) continue;
|
|
1448
|
-
for (const entry of Array.isArray(result) ? result : [result]) {
|
|
1449
|
-
errors.push(
|
|
1450
|
-
typeof entry === "string" ? { type, message: entry } : { ...entry, type }
|
|
1451
|
-
);
|
|
1452
|
-
}
|
|
1453
|
-
}
|
|
1454
|
-
}
|
|
1455
|
-
return errors.length ? errors : void 0;
|
|
1456
|
-
};
|
|
1457
|
-
}
|
|
1458
|
-
function rulesToConstraintAttrs(rules) {
|
|
1459
|
-
const attrs = {};
|
|
1460
|
-
if (rules.required) attrs.required = true;
|
|
1461
|
-
if (rules.min !== void 0) attrs.min = rules.min;
|
|
1462
|
-
if (rules.max !== void 0) attrs.max = rules.max;
|
|
1463
|
-
if (rules.minLength !== void 0) attrs.minLength = rules.minLength;
|
|
1464
|
-
if (rules.maxLength !== void 0) attrs.maxLength = rules.maxLength;
|
|
1465
|
-
if (rules.pattern) attrs.pattern = rules.pattern.value.source;
|
|
1466
|
-
return attrs;
|
|
1887
|
+
function errorIdFromKey(key) {
|
|
1888
|
+
const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
|
|
1889
|
+
return id || "field";
|
|
1890
|
+
}
|
|
1891
|
+
function fieldErrorId(name) {
|
|
1892
|
+
return errorIdFromKey(create$1(name).key);
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
const fieldDisabledRegistry = /* @__PURE__ */ new WeakMap();
|
|
1896
|
+
function registerFieldDisabled(form, path, disabled) {
|
|
1897
|
+
if (disabled === void 0) return null;
|
|
1898
|
+
const registry = getOrCreate(fieldDisabledRegistry, form, () => /* @__PURE__ */ new Map());
|
|
1899
|
+
const token = {};
|
|
1900
|
+
registry.set(path.key, { disabled, token });
|
|
1901
|
+
emit(form.emitter, "disabled", path);
|
|
1902
|
+
return { token };
|
|
1903
|
+
}
|
|
1904
|
+
function unregisterFieldDisabled(form, path, token) {
|
|
1905
|
+
const registry = fieldDisabledRegistry.get(form);
|
|
1906
|
+
const entry = registry?.get(path.key);
|
|
1907
|
+
if (registry && entry && entry.token === token) {
|
|
1908
|
+
registry.delete(path.key);
|
|
1909
|
+
emit(form.emitter, "disabled", path);
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
function hasDisabledAncestor(form, path) {
|
|
1913
|
+
const registry = fieldDisabledRegistry.get(form);
|
|
1914
|
+
if (!registry?.size) return false;
|
|
1915
|
+
const segments = path.value;
|
|
1916
|
+
for (let i = 1; i < segments.length; i++) {
|
|
1917
|
+
const prefix = JSON.stringify(segments.slice(0, i));
|
|
1918
|
+
if (registry.get(prefix)?.disabled) return true;
|
|
1919
|
+
}
|
|
1920
|
+
return false;
|
|
1467
1921
|
}
|
|
1468
1922
|
|
|
1469
1923
|
function isDescendant(key, ancestorKey) {
|
|
@@ -1495,7 +1949,62 @@
|
|
|
1495
1949
|
});
|
|
1496
1950
|
return unsubscribes.length === 1 ? unsubscribes[0] : () => unsubscribes.forEach((unsubscribe) => unsubscribe());
|
|
1497
1951
|
}
|
|
1952
|
+
function watch(form, event, getter, isEqual) {
|
|
1953
|
+
const cache = { hasValue: false };
|
|
1954
|
+
const consumers = /* @__PURE__ */ new Set();
|
|
1955
|
+
const wake = () => {
|
|
1956
|
+
if (isEqual && cache.hasValue) {
|
|
1957
|
+
const next = getter();
|
|
1958
|
+
if (isEqual(cache.value, next)) return;
|
|
1959
|
+
cache.value = next;
|
|
1960
|
+
} else {
|
|
1961
|
+
cache.value = getter();
|
|
1962
|
+
cache.hasValue = true;
|
|
1963
|
+
}
|
|
1964
|
+
consumers.forEach((invalidate) => invalidate());
|
|
1965
|
+
};
|
|
1966
|
+
const off = on(form.emitter, event, wake);
|
|
1967
|
+
return {
|
|
1968
|
+
getSnapshot: () => {
|
|
1969
|
+
if (!cache.hasValue) {
|
|
1970
|
+
cache.value = getter();
|
|
1971
|
+
cache.hasValue = true;
|
|
1972
|
+
}
|
|
1973
|
+
return cache.value;
|
|
1974
|
+
},
|
|
1975
|
+
subscribe: (invalidate) => {
|
|
1976
|
+
consumers.add(invalidate);
|
|
1977
|
+
return () => {
|
|
1978
|
+
consumers.delete(invalidate);
|
|
1979
|
+
};
|
|
1980
|
+
},
|
|
1981
|
+
dispose: () => {
|
|
1982
|
+
off();
|
|
1983
|
+
consumers.clear();
|
|
1984
|
+
}
|
|
1985
|
+
};
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
function pathFromKey(key) {
|
|
1989
|
+
return create$1(segmentsFromKey(key));
|
|
1990
|
+
}
|
|
1991
|
+
function usePath(name) {
|
|
1992
|
+
const key = React.useMemo(() => create$1(normalizePath(name)).key, [name]);
|
|
1993
|
+
return React.useMemo(() => pathFromKey(key), [key]);
|
|
1994
|
+
}
|
|
1498
1995
|
|
|
1996
|
+
function seedIfChanged(form, seeded, source, resetOptions) {
|
|
1997
|
+
if (seeded.done && (seeded.source === source || isEqual(seeded.source, source))) {
|
|
1998
|
+
return;
|
|
1999
|
+
}
|
|
2000
|
+
seeded.done = true;
|
|
2001
|
+
seeded.source = source;
|
|
2002
|
+
if (resetOptions !== void 0) {
|
|
2003
|
+
reset(form, source, resetOptions);
|
|
2004
|
+
} else {
|
|
2005
|
+
setInitialValues(form, source);
|
|
2006
|
+
}
|
|
2007
|
+
}
|
|
1499
2008
|
function useForm(options) {
|
|
1500
2009
|
const [form] = React.useState(() => {
|
|
1501
2010
|
const created = create(options);
|
|
@@ -1506,6 +2015,7 @@
|
|
|
1506
2015
|
});
|
|
1507
2016
|
const initialValues = options && options.initialValues;
|
|
1508
2017
|
const values = options && options.values;
|
|
2018
|
+
const resetOptions = options && options.resetOptions;
|
|
1509
2019
|
const seededRef = React.useRef(null);
|
|
1510
2020
|
if (seededRef.current === null)
|
|
1511
2021
|
seededRef.current = { done: false, source: void 0 };
|
|
@@ -1514,28 +2024,15 @@
|
|
|
1514
2024
|
if (typeof initialValues === "function" || isPromise(initialValues)) {
|
|
1515
2025
|
return;
|
|
1516
2026
|
}
|
|
1517
|
-
|
|
1518
|
-
if (seeded.done && (seeded.source === initialValues || isEqual(seeded.source, initialValues))) {
|
|
1519
|
-
return;
|
|
1520
|
-
}
|
|
1521
|
-
seeded.done = true;
|
|
1522
|
-
seeded.source = initialValues;
|
|
1523
|
-
setInitialValues(form, initialValues);
|
|
2027
|
+
seedIfChanged(form, seededRef.current, initialValues);
|
|
1524
2028
|
}, [form, initialValues]);
|
|
1525
2029
|
const controlledRef = React.useRef(null);
|
|
1526
|
-
if (controlledRef.current === null)
|
|
2030
|
+
if (controlledRef.current === null)
|
|
1527
2031
|
controlledRef.current = { done: false, source: void 0 };
|
|
1528
|
-
}
|
|
1529
2032
|
React.useEffect(() => {
|
|
1530
2033
|
if (values === void 0) return;
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
return;
|
|
1534
|
-
}
|
|
1535
|
-
seeded.done = true;
|
|
1536
|
-
seeded.source = values;
|
|
1537
|
-
setInitialValues(form, values);
|
|
1538
|
-
}, [form, values]);
|
|
2034
|
+
seedIfChanged(form, controlledRef.current, values, resetOptions);
|
|
2035
|
+
}, [form, values, resetOptions]);
|
|
1539
2036
|
React.useEffect(() => {
|
|
1540
2037
|
if (!form.validateOnMount || !form.validate) return;
|
|
1541
2038
|
const run = () => {
|
|
@@ -1603,8 +2100,7 @@
|
|
|
1603
2100
|
const { key } = path;
|
|
1604
2101
|
const scope = options?.exact === false ? "branch" : "leaf";
|
|
1605
2102
|
const subscribeFactory = React.useCallback(
|
|
1606
|
-
(invalidate) => onPathEvent(emitter, "change",
|
|
1607
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `key` on purpose: useValue creates a fresh Path per render, so the object must stay out of the deps while the key string pins the subscription
|
|
2103
|
+
(invalidate) => onPathEvent(emitter, "change", pathFromKey(key), scope, invalidate),
|
|
1608
2104
|
[emitter, key, scope]
|
|
1609
2105
|
);
|
|
1610
2106
|
return useWatchCore(subscribeFactory, () => {
|
|
@@ -1615,18 +2111,26 @@
|
|
|
1615
2111
|
return value === void 0 ? options?.defaultValue : value;
|
|
1616
2112
|
});
|
|
1617
2113
|
}
|
|
2114
|
+
function useValues(form) {
|
|
2115
|
+
return useWatch(form, "change", () => getValues(form));
|
|
2116
|
+
}
|
|
1618
2117
|
function useTouched(form, name) {
|
|
1619
2118
|
return useTouchedByPath(form, create$1(name));
|
|
1620
2119
|
}
|
|
1621
|
-
function
|
|
2120
|
+
function useKeyWatch(form, path, event, getter) {
|
|
1622
2121
|
const { emitter } = form;
|
|
1623
2122
|
const { key } = path;
|
|
1624
2123
|
const subscribeFactory = React.useCallback(
|
|
1625
|
-
(invalidate) => onKeyEvent(emitter,
|
|
1626
|
-
[emitter, key]
|
|
2124
|
+
(invalidate) => onKeyEvent(emitter, event, key, invalidate),
|
|
2125
|
+
[emitter, event, key]
|
|
1627
2126
|
);
|
|
1628
|
-
return useWatchCore(
|
|
1629
|
-
|
|
2127
|
+
return useWatchCore(subscribeFactory, getter);
|
|
2128
|
+
}
|
|
2129
|
+
function useTouchedByPath(form, path) {
|
|
2130
|
+
return useKeyWatch(
|
|
2131
|
+
form,
|
|
2132
|
+
path,
|
|
2133
|
+
"touched",
|
|
1630
2134
|
hasTouchedByPath.bind(null, form, path)
|
|
1631
2135
|
);
|
|
1632
2136
|
}
|
|
@@ -1634,26 +2138,21 @@
|
|
|
1634
2138
|
return useErrorByPath(form, create$1(name))?.message;
|
|
1635
2139
|
}
|
|
1636
2140
|
function useErrorByPath(form, path) {
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
2141
|
+
return useKeyWatch(
|
|
2142
|
+
form,
|
|
2143
|
+
path,
|
|
2144
|
+
"errors",
|
|
2145
|
+
getErrorByPath.bind(null, form, path)
|
|
1642
2146
|
);
|
|
1643
|
-
return useWatchCore(subscribeFactory, getErrorByPath.bind(null, form, path));
|
|
1644
2147
|
}
|
|
1645
2148
|
function useFieldErrors(form, name) {
|
|
1646
2149
|
return useFieldErrorsByPath(form, create$1(name));
|
|
1647
2150
|
}
|
|
1648
2151
|
function useFieldErrorsByPath(form, path) {
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
[emitter, key]
|
|
1654
|
-
);
|
|
1655
|
-
return useWatchCore(
|
|
1656
|
-
subscribeFactory,
|
|
2152
|
+
return useKeyWatch(
|
|
2153
|
+
form,
|
|
2154
|
+
path,
|
|
2155
|
+
"errors",
|
|
1657
2156
|
getFieldErrorsByPath.bind(null, form, path)
|
|
1658
2157
|
);
|
|
1659
2158
|
}
|
|
@@ -1667,8 +2166,7 @@
|
|
|
1667
2166
|
const { emitter } = form;
|
|
1668
2167
|
const { key } = path;
|
|
1669
2168
|
const subscribeFactory = React.useCallback(
|
|
1670
|
-
(invalidate) => onPathEvent(emitter, "change",
|
|
1671
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- same key-pinning convention as useValueByPath
|
|
2169
|
+
(invalidate) => onPathEvent(emitter, "change", pathFromKey(key), "leaf", invalidate),
|
|
1672
2170
|
[emitter, key]
|
|
1673
2171
|
);
|
|
1674
2172
|
return useWatchCore(subscribeFactory, () => isFieldDirtyByPath(form, path));
|
|
@@ -1690,14 +2188,22 @@
|
|
|
1690
2188
|
"disabled",
|
|
1691
2189
|
"loading"
|
|
1692
2190
|
];
|
|
2191
|
+
function subscribeFormStateEvents(emitter, invalidate) {
|
|
2192
|
+
const offs = FORM_STATE_EVENTS.map((event) => on(emitter, event, invalidate));
|
|
2193
|
+
return () => {
|
|
2194
|
+
for (const off of offs) off();
|
|
2195
|
+
};
|
|
2196
|
+
}
|
|
1693
2197
|
function getFormState(form) {
|
|
2198
|
+
const anyErrors = hasErrors(form);
|
|
1694
2199
|
return {
|
|
1695
2200
|
isDirty: isDirty(form),
|
|
1696
2201
|
dirtyFields: getDirtyFields(form),
|
|
1697
2202
|
isTouched: form.touched.size > 0,
|
|
1698
2203
|
touchedFields: getTouchedFields(form),
|
|
1699
|
-
hasErrors:
|
|
1700
|
-
isValid: !
|
|
2204
|
+
hasErrors: anyErrors,
|
|
2205
|
+
isValid: !anyErrors,
|
|
2206
|
+
errors: getErrorsRecord(form),
|
|
1701
2207
|
isSubmitting: form.isSubmitting,
|
|
1702
2208
|
isSubmitted: form.isSubmitted,
|
|
1703
2209
|
isValidating: form.validating.size > 0,
|
|
@@ -1709,26 +2215,32 @@
|
|
|
1709
2215
|
}
|
|
1710
2216
|
function isSameFormState(a, b) {
|
|
1711
2217
|
const sameTouched = a.touchedFields.length === b.touchedFields.length && a.touchedFields.every((path, i) => path === b.touchedFields[i]);
|
|
1712
|
-
return a.isDirty === b.isDirty && a.dirtyFields === b.dirtyFields && a.isTouched === b.isTouched && sameTouched && a.hasErrors === b.hasErrors && a.isValid === b.isValid && a.isSubmitting === b.isSubmitting && a.isSubmitted === b.isSubmitted && a.isValidating === b.isValidating && a.isSubmitSuccessful === b.isSubmitSuccessful && a.submitCount === b.submitCount && a.isLoading === b.isLoading && a.disabled === b.disabled;
|
|
2218
|
+
return a.isDirty === b.isDirty && a.dirtyFields === b.dirtyFields && a.isTouched === b.isTouched && sameTouched && a.hasErrors === b.hasErrors && a.isValid === b.isValid && a.errors === b.errors && a.isSubmitting === b.isSubmitting && a.isSubmitted === b.isSubmitted && a.isValidating === b.isValidating && a.isSubmitSuccessful === b.isSubmitSuccessful && a.submitCount === b.submitCount && a.isLoading === b.isLoading && a.disabled === b.disabled;
|
|
1713
2219
|
}
|
|
1714
2220
|
function useFormState(form) {
|
|
1715
2221
|
const getter = React.useCallback(() => getFormState(form), [form]);
|
|
1716
2222
|
const subscribeFactory = React.useCallback(
|
|
1717
|
-
(invalidate) =>
|
|
1718
|
-
const offs = FORM_STATE_EVENTS.map(
|
|
1719
|
-
(event) => on(form.emitter, event, invalidate)
|
|
1720
|
-
);
|
|
1721
|
-
return () => {
|
|
1722
|
-
for (const off of offs) off();
|
|
1723
|
-
};
|
|
1724
|
-
},
|
|
2223
|
+
(invalidate) => subscribeFormStateEvents(form.emitter, invalidate),
|
|
1725
2224
|
[form.emitter]
|
|
1726
2225
|
);
|
|
1727
2226
|
return useWatchCore(subscribeFactory, getter, isSameFormState);
|
|
1728
2227
|
}
|
|
2228
|
+
function useStore(form, selector, isEqual2) {
|
|
2229
|
+
const subscribeFactory = React.useCallback(
|
|
2230
|
+
(invalidate) => subscribeFormStateEvents(form.emitter, invalidate),
|
|
2231
|
+
[form.emitter]
|
|
2232
|
+
);
|
|
2233
|
+
return useWatchCore(subscribeFactory, selector, isEqual2);
|
|
2234
|
+
}
|
|
1729
2235
|
function useHasErrors(form) {
|
|
1730
2236
|
return useWatch(form, "errors", hasErrors.bind(null, form));
|
|
1731
2237
|
}
|
|
2238
|
+
function useErrors(form) {
|
|
2239
|
+
return useWatch(form, "errors", () => getErrorsRecord(form));
|
|
2240
|
+
}
|
|
2241
|
+
function useErrorsTree(form) {
|
|
2242
|
+
return useWatch(form, "errors", () => getErrorsTree(form));
|
|
2243
|
+
}
|
|
1732
2244
|
function useIsValid(form) {
|
|
1733
2245
|
return useWatch(form, "errors", () => !hasErrors(form));
|
|
1734
2246
|
}
|
|
@@ -1779,11 +2291,6 @@
|
|
|
1779
2291
|
return useFieldErrorsByPath(form, create$1(FORM_ERROR));
|
|
1780
2292
|
}
|
|
1781
2293
|
|
|
1782
|
-
function usePath(name) {
|
|
1783
|
-
const path = React.useMemo(() => create$1(normalizePath(name)), [name]);
|
|
1784
|
-
return React.useMemo(() => path, [path.key]);
|
|
1785
|
-
}
|
|
1786
|
-
|
|
1787
2294
|
function useStage(value) {
|
|
1788
2295
|
const ref = React.useRef(value);
|
|
1789
2296
|
ref.current = value;
|
|
@@ -1798,38 +2305,56 @@
|
|
|
1798
2305
|
}
|
|
1799
2306
|
function useUnmountRestore(teardown, restore) {
|
|
1800
2307
|
const removedRef = React.useRef(false);
|
|
2308
|
+
const teardownRef = useStage(teardown);
|
|
2309
|
+
const restoreRef = useStage(restore);
|
|
1801
2310
|
React.useEffect(() => {
|
|
2311
|
+
const teardownOnce = teardownRef.current;
|
|
2312
|
+
const restoreOnce = restoreRef.current;
|
|
1802
2313
|
if (removedRef.current) {
|
|
1803
2314
|
removedRef.current = false;
|
|
1804
|
-
|
|
2315
|
+
restoreOnce();
|
|
1805
2316
|
}
|
|
1806
2317
|
return () => {
|
|
1807
2318
|
removedRef.current = true;
|
|
1808
|
-
|
|
2319
|
+
teardownOnce();
|
|
1809
2320
|
};
|
|
1810
|
-
}, []);
|
|
2321
|
+
}, [removedRef, teardownRef, restoreRef]);
|
|
2322
|
+
}
|
|
2323
|
+
function useUnmountFieldRemoval(form, path, shouldUnregister) {
|
|
2324
|
+
const removalSnapshotRef = React.useRef(null);
|
|
2325
|
+
const teardownOnUnmount = useStageFn(() => {
|
|
2326
|
+
if ((shouldUnregister ?? form.shouldUnregister) === false) return;
|
|
2327
|
+
removalSnapshotRef.current = removeFieldForUnmount(form, path);
|
|
2328
|
+
});
|
|
2329
|
+
const restoreAfterStrictMode = useStageFn(() => {
|
|
2330
|
+
const snapshot = removalSnapshotRef.current;
|
|
2331
|
+
removalSnapshotRef.current = null;
|
|
2332
|
+
if (snapshot) restoreRemovedField(form, path, snapshot);
|
|
2333
|
+
});
|
|
2334
|
+
useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);
|
|
1811
2335
|
}
|
|
1812
2336
|
|
|
2337
|
+
function schemaAsValidator(validate) {
|
|
2338
|
+
return validate && hasStandardProps(validate) ? schemaToFieldValidator(validate) : validate;
|
|
2339
|
+
}
|
|
1813
2340
|
function useValidate(validate, path, formProp, options) {
|
|
1814
2341
|
const contextForm = React.useContext(FormContext);
|
|
1815
2342
|
const form = formProp || contextForm;
|
|
1816
2343
|
if (!form) throw new Error("no form provided");
|
|
1817
|
-
const validateRef =
|
|
1818
|
-
|
|
1819
|
-
const
|
|
1820
|
-
|
|
1821
|
-
const
|
|
1822
|
-
syncRef.current = options?.sync;
|
|
1823
|
-
const asyncAlwaysRef = React.useRef(options?.asyncAlways ?? false);
|
|
1824
|
-
asyncAlwaysRef.current = options?.asyncAlways ?? false;
|
|
2344
|
+
const validateRef = useStage(schemaAsValidator(validate));
|
|
2345
|
+
const debounceRef = useStage(options?.debounce ?? 0);
|
|
2346
|
+
const syncRef = useStage(options?.sync);
|
|
2347
|
+
const asyncAlwaysRef = useStage(options?.asyncAlways ?? false);
|
|
2348
|
+
const validateOnMountRef = useStage(options?.validateOnMount);
|
|
1825
2349
|
React.useEffect(() => {
|
|
1826
|
-
const
|
|
2350
|
+
const spath = pathFromKey(path.key);
|
|
2351
|
+
const dispose = registerValidatorByPath(form, spath, {
|
|
1827
2352
|
validate: () => validateRef.current,
|
|
1828
2353
|
debounce: () => debounceRef.current,
|
|
1829
2354
|
sync: () => syncRef.current,
|
|
1830
2355
|
asyncAlways: () => asyncAlwaysRef.current
|
|
1831
2356
|
});
|
|
1832
|
-
const validateOnMount =
|
|
2357
|
+
const validateOnMount = validateOnMountRef.current ?? form.validateOnMount;
|
|
1833
2358
|
if (!validateOnMount || !validateRef.current && !syncRef.current) {
|
|
1834
2359
|
return dispose;
|
|
1835
2360
|
}
|
|
@@ -1850,41 +2375,40 @@
|
|
|
1850
2375
|
disposed = true;
|
|
1851
2376
|
dispose();
|
|
1852
2377
|
};
|
|
1853
|
-
}, [
|
|
2378
|
+
}, [
|
|
2379
|
+
form,
|
|
2380
|
+
path.key,
|
|
2381
|
+
debounceRef,
|
|
2382
|
+
syncRef,
|
|
2383
|
+
asyncAlwaysRef,
|
|
2384
|
+
validateRef,
|
|
2385
|
+
validateOnMountRef
|
|
2386
|
+
]);
|
|
1854
2387
|
return useStageFn(() => form.validators.get(path.key)?.());
|
|
1855
2388
|
}
|
|
1856
2389
|
|
|
1857
|
-
function removeFieldForUnmount(form, path) {
|
|
1858
|
-
const { key } = path;
|
|
1859
|
-
const snapshot = {
|
|
1860
|
-
present: form.values.has(key),
|
|
1861
|
-
value: form.values.get(key),
|
|
1862
|
-
touched: form.touched.has(key),
|
|
1863
|
-
errors: form.errors.get(key)
|
|
1864
|
-
};
|
|
1865
|
-
removeFieldByPath(form, path);
|
|
1866
|
-
return snapshot;
|
|
1867
|
-
}
|
|
1868
|
-
function restoreRemovedField(form, path, snapshot) {
|
|
1869
|
-
const { key } = path;
|
|
1870
|
-
if (snapshot.present) {
|
|
1871
|
-
setValueByPath(form, path, snapshot.value, { shouldDirty: false });
|
|
1872
|
-
} else {
|
|
1873
|
-
form.deleted.delete(key);
|
|
1874
|
-
bumpValuesVersion(form);
|
|
1875
|
-
emit(form.emitter, "change", path);
|
|
1876
|
-
}
|
|
1877
|
-
if (snapshot.touched) setTouchedByPath(form, path);
|
|
1878
|
-
if (snapshot.errors) setErrorByPath(form, path, snapshot.errors);
|
|
1879
|
-
}
|
|
1880
|
-
|
|
1881
2390
|
const uncontrolledSyncRegistry = /* @__PURE__ */ new WeakMap();
|
|
1882
|
-
function
|
|
1883
|
-
|
|
2391
|
+
function getUncontrolledSyncEntry(form) {
|
|
2392
|
+
const existing = uncontrolledSyncRegistry.get(form);
|
|
2393
|
+
if (existing) return existing;
|
|
2394
|
+
const cells = /* @__PURE__ */ new Map();
|
|
2395
|
+
const off = on(form.emitter, "change", (changed) => {
|
|
2396
|
+
if (changed) return;
|
|
2397
|
+
for (const read of cells.values()) {
|
|
2398
|
+
const { el, path } = read();
|
|
2399
|
+
if (!el || el.type === "file") continue;
|
|
2400
|
+
const next = getValueByPath(form, path);
|
|
2401
|
+
const asString = next == null ? "" : String(next);
|
|
2402
|
+
if (el.value !== asString) el.value = asString;
|
|
2403
|
+
}
|
|
2404
|
+
});
|
|
2405
|
+
const entry = { cells, off };
|
|
2406
|
+
uncontrolledSyncRegistry.set(form, entry);
|
|
2407
|
+
return entry;
|
|
1884
2408
|
}
|
|
1885
|
-
function combineRulesAndValidate(rules, validate) {
|
|
2409
|
+
function combineRulesAndValidate(rules, validate, formMessages) {
|
|
1886
2410
|
if (!rules || !hasRuleConstraints(rules)) return validate;
|
|
1887
|
-
const ruleValidator = rulesToValidator(rules);
|
|
2411
|
+
const ruleValidator = rulesToValidator(rules, formMessages);
|
|
1888
2412
|
if (!validate) return ruleValidator;
|
|
1889
2413
|
return (value, meta) => {
|
|
1890
2414
|
const ruleErrors = ruleValidator(value, meta);
|
|
@@ -1898,22 +2422,59 @@
|
|
|
1898
2422
|
return isPromise(result) ? result.then(merge) : merge(result);
|
|
1899
2423
|
};
|
|
1900
2424
|
}
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
React.
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
2425
|
+
const NO_DELAYED_ERRORS = [];
|
|
2426
|
+
function useDelayedErrors(form, path, delay) {
|
|
2427
|
+
const pendingRef = React.useRef(false);
|
|
2428
|
+
const prevRef = React.useRef(false);
|
|
2429
|
+
const timerRef = React.useRef(null);
|
|
2430
|
+
const subscribeFactory = React.useCallback(
|
|
2431
|
+
(invalidate) => {
|
|
2432
|
+
const spath = pathFromKey(path.key);
|
|
2433
|
+
const clearTimer = () => {
|
|
2434
|
+
if (timerRef.current !== null) {
|
|
2435
|
+
clearTimeout(timerRef.current);
|
|
2436
|
+
timerRef.current = null;
|
|
2437
|
+
}
|
|
2438
|
+
};
|
|
2439
|
+
pendingRef.current = false;
|
|
2440
|
+
prevRef.current = false;
|
|
2441
|
+
clearTimer();
|
|
2442
|
+
const startWindow = () => {
|
|
2443
|
+
clearTimer();
|
|
2444
|
+
pendingRef.current = true;
|
|
2445
|
+
timerRef.current = setTimeout(() => {
|
|
2446
|
+
timerRef.current = null;
|
|
2447
|
+
pendingRef.current = false;
|
|
2448
|
+
invalidate();
|
|
2449
|
+
}, delay);
|
|
2450
|
+
};
|
|
2451
|
+
const off = onKeyEvent(form.emitter, "errors", spath.key, () => {
|
|
2452
|
+
const has = getFieldErrorsByPath(form, spath).length > 0;
|
|
2453
|
+
const was = prevRef.current;
|
|
2454
|
+
prevRef.current = has;
|
|
2455
|
+
if (delay !== void 0) {
|
|
2456
|
+
if (!has) {
|
|
2457
|
+
if (pendingRef.current) {
|
|
2458
|
+
clearTimer();
|
|
2459
|
+
pendingRef.current = false;
|
|
2460
|
+
}
|
|
2461
|
+
} else if (!was || pendingRef.current) {
|
|
2462
|
+
startWindow();
|
|
2463
|
+
}
|
|
2464
|
+
}
|
|
2465
|
+
invalidate();
|
|
2466
|
+
});
|
|
2467
|
+
return () => {
|
|
2468
|
+
off();
|
|
2469
|
+
clearTimer();
|
|
2470
|
+
};
|
|
2471
|
+
},
|
|
2472
|
+
[form, path.key, delay]
|
|
2473
|
+
);
|
|
2474
|
+
return useWatchCore(
|
|
2475
|
+
subscribeFactory,
|
|
2476
|
+
() => delay === void 0 || !pendingRef.current ? getFieldErrorsByPath(form, path) : NO_DELAYED_ERRORS
|
|
2477
|
+
);
|
|
1917
2478
|
}
|
|
1918
2479
|
function useFieldValue(form, path, uncontrolled) {
|
|
1919
2480
|
const snapshotRef = React.useRef({
|
|
@@ -1948,7 +2509,11 @@
|
|
|
1948
2509
|
disabled,
|
|
1949
2510
|
uncontrolled,
|
|
1950
2511
|
asyncAlways,
|
|
1951
|
-
mode: modeOption
|
|
2512
|
+
mode: modeOption,
|
|
2513
|
+
eventToValue,
|
|
2514
|
+
valueAsNumber,
|
|
2515
|
+
valueAsDate,
|
|
2516
|
+
type
|
|
1952
2517
|
}, Context) {
|
|
1953
2518
|
const contextForm = React.useContext(Context);
|
|
1954
2519
|
const form = f1 || contextForm;
|
|
@@ -1966,22 +2531,32 @@
|
|
|
1966
2531
|
emitChangeByPath(form, path);
|
|
1967
2532
|
});
|
|
1968
2533
|
const restRules = rules ? { ...rules, required: void 0 } : void 0;
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
2534
|
+
const validateWrapped = schemaAsValidator(validate);
|
|
2535
|
+
useValidate(
|
|
2536
|
+
combineRulesAndValidate(restRules, validateWrapped, form.messages),
|
|
2537
|
+
path,
|
|
2538
|
+
form,
|
|
2539
|
+
{
|
|
2540
|
+
debounce: validateDebounce,
|
|
2541
|
+
validateOnMount,
|
|
2542
|
+
asyncAlways: asyncAlways ?? form.asyncAlways,
|
|
2543
|
+
sync: rules && rules.required !== void 0 ? rulesToValidator({ required: rules.required }, form.messages) : void 0
|
|
2544
|
+
}
|
|
2545
|
+
);
|
|
2546
|
+
const errors = useDelayedErrors(form, path, delayError);
|
|
1977
2547
|
const errorObject = errors[0];
|
|
1978
2548
|
const error = errorObject?.message;
|
|
1979
2549
|
const value = useFieldValue(form, path, !!uncontrolled);
|
|
1980
2550
|
const isDirty = useWatchCore(
|
|
1981
2551
|
React.useCallback(
|
|
1982
2552
|
(invalidate) => uncontrolled ? () => {
|
|
1983
|
-
} : onPathEvent(
|
|
1984
|
-
|
|
2553
|
+
} : onPathEvent(
|
|
2554
|
+
form.emitter,
|
|
2555
|
+
"change",
|
|
2556
|
+
pathFromKey(path.key),
|
|
2557
|
+
"leaf",
|
|
2558
|
+
invalidate
|
|
2559
|
+
),
|
|
1985
2560
|
[form.emitter, path.key, uncontrolled]
|
|
1986
2561
|
),
|
|
1987
2562
|
() => isFieldDirtyByPath(form, path)
|
|
@@ -1993,20 +2568,46 @@
|
|
|
1993
2568
|
),
|
|
1994
2569
|
() => form.validating.has(path.key)
|
|
1995
2570
|
);
|
|
1996
|
-
const
|
|
2571
|
+
const mergedDisabled = useWatchCore(
|
|
2572
|
+
React.useCallback(
|
|
2573
|
+
(invalidate) => onPathEvent(
|
|
2574
|
+
form.emitter,
|
|
2575
|
+
"disabled",
|
|
2576
|
+
pathFromKey(path.key),
|
|
2577
|
+
"branch",
|
|
2578
|
+
invalidate
|
|
2579
|
+
),
|
|
2580
|
+
[form.emitter, path.key]
|
|
2581
|
+
),
|
|
2582
|
+
() => form.disabled || disabled === true || disabled !== false && hasDisabledAncestor(form, path)
|
|
2583
|
+
);
|
|
2584
|
+
const disabledTokenRef = React.useRef(null);
|
|
2585
|
+
React.useEffect(() => {
|
|
2586
|
+
const spath = pathFromKey(path.key);
|
|
2587
|
+
const registration = registerFieldDisabled(form, spath, disabled);
|
|
2588
|
+
if (registration) disabledTokenRef.current = registration.token;
|
|
2589
|
+
return () => {
|
|
2590
|
+
if (disabledTokenRef.current !== null) {
|
|
2591
|
+
unregisterFieldDisabled(form, spath, disabledTokenRef.current);
|
|
2592
|
+
disabledTokenRef.current = null;
|
|
2593
|
+
}
|
|
2594
|
+
};
|
|
2595
|
+
}, [form, path.key, disabled]);
|
|
1997
2596
|
const onChange = useStageFn((v) => userChangeByPath(form, path, v));
|
|
1998
2597
|
const onBlur = useStageFn(() => userBlur(form, path));
|
|
1999
2598
|
React.useEffect(() => {
|
|
2000
|
-
const
|
|
2001
|
-
|
|
2599
|
+
const spath = pathFromKey(path.key);
|
|
2600
|
+
const { token, displaced } = registerFieldMode(form, spath, modeOption);
|
|
2601
|
+
return () => unregisterFieldMode(form, spath, token);
|
|
2002
2602
|
}, [form, path.key, modeOption]);
|
|
2003
2603
|
const depsKey = validateDeps?.length ? validateDeps.join("\n") : void 0;
|
|
2604
|
+
const validateDepsRef = useStage(validateDeps);
|
|
2004
2605
|
React.useEffect(() => {
|
|
2005
2606
|
if (!depsKey) return;
|
|
2006
|
-
const depKeys =
|
|
2607
|
+
const depKeys = validateDepsRef.current.map((dep) => create$1(dep).key);
|
|
2007
2608
|
registerFieldValidateDeps(form, path.key, depKeys);
|
|
2008
2609
|
return () => unregisterFieldValidateDeps(form, path.key, depKeys);
|
|
2009
|
-
}, [form, path.key, depsKey]);
|
|
2610
|
+
}, [form, path.key, depsKey, validateDepsRef]);
|
|
2010
2611
|
const elementRef = React.useRef(null);
|
|
2011
2612
|
const focusRef = React.useCallback((el) => {
|
|
2012
2613
|
elementRef.current = el;
|
|
@@ -2028,24 +2629,9 @@
|
|
|
2028
2629
|
[form, path.key]
|
|
2029
2630
|
);
|
|
2030
2631
|
React.useEffect(() => {
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
const cells = /* @__PURE__ */ new Map();
|
|
2035
|
-
const off = on(form.emitter, "change", (changed) => {
|
|
2036
|
-
if (changed) return;
|
|
2037
|
-
for (const read of cells.values()) {
|
|
2038
|
-
const { el, path: path2 } = read();
|
|
2039
|
-
if (!el || el.type === "file") continue;
|
|
2040
|
-
const next = getValueByPath(form, path2);
|
|
2041
|
-
const asString = next == null ? "" : String(next);
|
|
2042
|
-
if (el.value !== asString) el.value = asString;
|
|
2043
|
-
}
|
|
2044
|
-
});
|
|
2045
|
-
entry = { cells, off };
|
|
2046
|
-
uncontrolledSyncRegistry.set(form, entry);
|
|
2047
|
-
}
|
|
2048
|
-
entry.cells.set(path.key, () => ({ el: elementRef.current, path }));
|
|
2632
|
+
const spath = pathFromKey(path.key);
|
|
2633
|
+
const entry = getUncontrolledSyncEntry(form);
|
|
2634
|
+
entry.cells.set(path.key, () => ({ el: elementRef.current, path: spath }));
|
|
2049
2635
|
return () => {
|
|
2050
2636
|
entry.cells.delete(path.key);
|
|
2051
2637
|
if (entry.cells.size === 0) {
|
|
@@ -2054,17 +2640,28 @@
|
|
|
2054
2640
|
}
|
|
2055
2641
|
};
|
|
2056
2642
|
}, [form, path.key, uncontrolled]);
|
|
2057
|
-
|
|
2058
|
-
const
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
});
|
|
2062
|
-
const restoreAfterStrictMode = useStageFn(() => {
|
|
2063
|
-
const snapshot = removalSnapshotRef.current;
|
|
2064
|
-
removalSnapshotRef.current = null;
|
|
2065
|
-
if (snapshot) restoreRemovedField(form, path, snapshot);
|
|
2643
|
+
useUnmountFieldRemoval(form, path, shouldUnregister);
|
|
2644
|
+
const extract = eventToValueOrDefault(eventToValue, {
|
|
2645
|
+
valueAsNumber,
|
|
2646
|
+
valueAsDate
|
|
2066
2647
|
});
|
|
2067
|
-
|
|
2648
|
+
const inputProps = {
|
|
2649
|
+
name: path.key,
|
|
2650
|
+
ref: focusRef,
|
|
2651
|
+
onChange: (e) => onChange(extract(e)),
|
|
2652
|
+
onBlur,
|
|
2653
|
+
disabled: mergedDisabled
|
|
2654
|
+
};
|
|
2655
|
+
if (type === "checkbox") {
|
|
2656
|
+
inputProps.checked = !!value;
|
|
2657
|
+
} else if (type !== "file") {
|
|
2658
|
+
if (uncontrolled) inputProps.defaultValue = value;
|
|
2659
|
+
else inputProps.value = value ?? "";
|
|
2660
|
+
}
|
|
2661
|
+
if (error) {
|
|
2662
|
+
inputProps["aria-invalid"] = true;
|
|
2663
|
+
inputProps["aria-describedby"] = errorIdFromKey(path.key);
|
|
2664
|
+
}
|
|
2068
2665
|
return {
|
|
2069
2666
|
form,
|
|
2070
2667
|
value,
|
|
@@ -2076,8 +2673,9 @@
|
|
|
2076
2673
|
onChange,
|
|
2077
2674
|
onBlur,
|
|
2078
2675
|
name: path.key,
|
|
2079
|
-
disabled:
|
|
2080
|
-
focusRef
|
|
2676
|
+
disabled: mergedDisabled,
|
|
2677
|
+
focusRef,
|
|
2678
|
+
inputProps
|
|
2081
2679
|
};
|
|
2082
2680
|
}
|
|
2083
2681
|
function useField(options) {
|
|
@@ -2095,12 +2693,18 @@
|
|
|
2095
2693
|
return arrayIdsRegistry.get(form)?.get(key);
|
|
2096
2694
|
}
|
|
2097
2695
|
function registerArrayIds(form, key, ids) {
|
|
2098
|
-
|
|
2099
|
-
if (!registry) {
|
|
2100
|
-
registry = /* @__PURE__ */ new Map();
|
|
2101
|
-
arrayIdsRegistry.set(form, registry);
|
|
2102
|
-
}
|
|
2696
|
+
const registry = arrayIdsRegistry.get(form) ?? /* @__PURE__ */ new Map();
|
|
2103
2697
|
registry.set(key, ids);
|
|
2698
|
+
arrayIdsRegistry.set(form, registry);
|
|
2699
|
+
}
|
|
2700
|
+
function scheduleArrayRowFocus(form, path, index, options) {
|
|
2701
|
+
const { focus } = options ?? {};
|
|
2702
|
+
if (focus === void 0) return;
|
|
2703
|
+
setTimeout(() => {
|
|
2704
|
+
const segments = [...path.value, index];
|
|
2705
|
+
const key = typeof focus === "string" ? create$1([...segments, focus]).key : firstMountedDescendantKey(form, create$1(segments));
|
|
2706
|
+
if (key !== void 0) emit(form.emitter, "focusError", key);
|
|
2707
|
+
}, 0);
|
|
2104
2708
|
}
|
|
2105
2709
|
function bumpReducer(count) {
|
|
2106
2710
|
return count + 1;
|
|
@@ -2113,18 +2717,8 @@
|
|
|
2113
2717
|
const { rules, shouldUnregister } = options;
|
|
2114
2718
|
const path = usePath(options.name);
|
|
2115
2719
|
const idsRef = React.useRef([]);
|
|
2116
|
-
const getArray = React.useCallback(
|
|
2117
|
-
() => getValueByPath(form, path) || [],
|
|
2118
|
-
[form, path]
|
|
2119
|
-
);
|
|
2120
|
-
const setArray = React.useCallback(
|
|
2121
|
-
(arr) => {
|
|
2122
|
-
setValueByPath(form, path, arr);
|
|
2123
|
-
},
|
|
2124
|
-
[form, path]
|
|
2125
|
-
);
|
|
2126
2720
|
const computeFields = React.useCallback(() => {
|
|
2127
|
-
const arr =
|
|
2721
|
+
const arr = getValueByPath(form, path) || [];
|
|
2128
2722
|
while (idsRef.current.length < arr.length) {
|
|
2129
2723
|
idsRef.current.push(generateId(form));
|
|
2130
2724
|
}
|
|
@@ -2136,7 +2730,7 @@
|
|
|
2136
2730
|
index,
|
|
2137
2731
|
[keyName]: id
|
|
2138
2732
|
}));
|
|
2139
|
-
}, [
|
|
2733
|
+
}, [form, path, keyName]);
|
|
2140
2734
|
const [fields, syncFields] = React.useReducer(
|
|
2141
2735
|
computeFields,
|
|
2142
2736
|
void 0,
|
|
@@ -2148,82 +2742,65 @@
|
|
|
2148
2742
|
);
|
|
2149
2743
|
registerArrayIds(form, path.key, idsRef.current);
|
|
2150
2744
|
React.useEffect(() => {
|
|
2151
|
-
|
|
2745
|
+
const ids = idsRef.current;
|
|
2746
|
+
registerArrayIds(form, path.key, ids);
|
|
2152
2747
|
return () => {
|
|
2153
2748
|
const registry = arrayIdsRegistry.get(form);
|
|
2154
|
-
if (registry?.get(path.key) ===
|
|
2749
|
+
if (registry?.get(path.key) === ids) registry.delete(path.key);
|
|
2155
2750
|
};
|
|
2156
2751
|
}, [form, path.key]);
|
|
2157
|
-
|
|
2158
|
-
const teardownOnUnmount = useStageFn(() => {
|
|
2159
|
-
if ((shouldUnregister ?? form.shouldUnregister) === false) return;
|
|
2160
|
-
removalSnapshotRef.current = removeFieldForUnmount(form, path);
|
|
2161
|
-
});
|
|
2162
|
-
const restoreAfterStrictMode = useStageFn(() => {
|
|
2163
|
-
const snapshot = removalSnapshotRef.current;
|
|
2164
|
-
removalSnapshotRef.current = null;
|
|
2165
|
-
if (snapshot) restoreRemovedField(form, path, snapshot);
|
|
2166
|
-
});
|
|
2167
|
-
useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);
|
|
2752
|
+
useUnmountFieldRemoval(form, path, shouldUnregister);
|
|
2168
2753
|
useValidate(
|
|
2169
|
-
rules ? rulesToValidator({ ...rules, required: void 0 }) : void 0,
|
|
2754
|
+
rules ? rulesToValidator({ ...rules, required: void 0 }, form.messages) : void 0,
|
|
2170
2755
|
path,
|
|
2171
2756
|
form,
|
|
2172
2757
|
{
|
|
2173
|
-
sync: rules
|
|
2758
|
+
sync: rules?.required !== void 0 ? rulesToValidator({ required: rules.required }, form.messages) : void 0
|
|
2174
2759
|
}
|
|
2175
2760
|
);
|
|
2176
|
-
const append = useStageFn(
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2761
|
+
const append = useStageFn(
|
|
2762
|
+
(value, options2) => {
|
|
2763
|
+
idsRef.current.push(generateId(form));
|
|
2764
|
+
appendValueByPath(form, path, value);
|
|
2765
|
+
scheduleArrayRowFocus(form, path, idsRef.current.length - 1, options2);
|
|
2766
|
+
}
|
|
2767
|
+
);
|
|
2768
|
+
const prepend = useStageFn(
|
|
2769
|
+
(value, options2) => {
|
|
2770
|
+
idsRef.current.unshift(generateId(form));
|
|
2771
|
+
prependValueByPath(form, path, value);
|
|
2772
|
+
scheduleArrayRowFocus(form, path, 0, options2);
|
|
2773
|
+
}
|
|
2774
|
+
);
|
|
2775
|
+
const insert = useStageFn(
|
|
2776
|
+
(index, value, options2) => {
|
|
2777
|
+
if (!insertValueByPath(form, path, index, value)) return;
|
|
2778
|
+
idsRef.current.splice(index, 0, generateId(form));
|
|
2779
|
+
scheduleArrayRowFocus(form, path, index, options2);
|
|
2780
|
+
}
|
|
2781
|
+
);
|
|
2782
|
+
const remove = useStageFn((indices) => {
|
|
2783
|
+
const dropped = removeValueByPath(form, path, indices);
|
|
2784
|
+
for (const index of dropped) idsRef.current.splice(index, 1);
|
|
2197
2785
|
});
|
|
2198
2786
|
const swap = useStageFn((from, to) => {
|
|
2199
|
-
|
|
2787
|
+
if (!swapValuesByPath(form, path, from, to)) return;
|
|
2200
2788
|
[idsRef.current[from], idsRef.current[to]] = [
|
|
2201
2789
|
idsRef.current[to],
|
|
2202
2790
|
idsRef.current[from]
|
|
2203
2791
|
];
|
|
2204
|
-
const newArr = [...arr];
|
|
2205
|
-
[newArr[from], newArr[to]] = [newArr[to], newArr[from]];
|
|
2206
|
-
setArray(newArr);
|
|
2207
2792
|
});
|
|
2208
2793
|
const move = useStageFn((from, to) => {
|
|
2209
|
-
|
|
2794
|
+
if (!moveValueByPath(form, path, from, to)) return;
|
|
2210
2795
|
const [id] = idsRef.current.splice(from, 1);
|
|
2211
2796
|
idsRef.current.splice(to, 0, id);
|
|
2212
|
-
const newArr = [...arr];
|
|
2213
|
-
const [item] = newArr.splice(from, 1);
|
|
2214
|
-
newArr.splice(to, 0, item);
|
|
2215
|
-
setArray(newArr);
|
|
2216
2797
|
});
|
|
2217
2798
|
const replace = useStageFn((values) => {
|
|
2218
2799
|
idsRef.current = values.map(() => generateId(form));
|
|
2219
|
-
|
|
2800
|
+
replaceValuesByPath(form, path, values);
|
|
2220
2801
|
});
|
|
2221
2802
|
const update = useStageFn((index, value) => {
|
|
2222
|
-
|
|
2223
|
-
if (index < 0 || index >= arr.length) return;
|
|
2224
|
-
const newArr = [...arr];
|
|
2225
|
-
newArr[index] = value;
|
|
2226
|
-
setArray(newArr);
|
|
2803
|
+
updateValueByPath(form, path, index, value);
|
|
2227
2804
|
});
|
|
2228
2805
|
return { fields, append, prepend, insert, remove, swap, move, replace, update };
|
|
2229
2806
|
}
|
|
@@ -2309,7 +2886,10 @@
|
|
|
2309
2886
|
return useFieldCore(options, Context);
|
|
2310
2887
|
}
|
|
2311
2888
|
function useFieldArray(options) {
|
|
2312
|
-
return useFieldArrayCore(
|
|
2889
|
+
return useFieldArrayCore(
|
|
2890
|
+
options,
|
|
2891
|
+
Context
|
|
2892
|
+
);
|
|
2313
2893
|
}
|
|
2314
2894
|
function useFieldArrayItem(options) {
|
|
2315
2895
|
return useFieldArrayItemCore(options, Context);
|
|
@@ -2333,23 +2913,57 @@
|
|
|
2333
2913
|
|
|
2334
2914
|
function useTransform(form, name, options = {}) {
|
|
2335
2915
|
const path = usePath(name);
|
|
2336
|
-
const { toDisplay, fromDisplay } = options;
|
|
2916
|
+
const { toDisplay, fromDisplay, asyncDebounceMs } = options;
|
|
2337
2917
|
const subscribeFactory = React.useCallback(
|
|
2338
|
-
(invalidate) => onPathEvent(
|
|
2339
|
-
|
|
2918
|
+
(invalidate) => onPathEvent(
|
|
2919
|
+
form.emitter,
|
|
2920
|
+
"change",
|
|
2921
|
+
pathFromKey(path.key),
|
|
2922
|
+
"leaf",
|
|
2923
|
+
invalidate
|
|
2924
|
+
),
|
|
2340
2925
|
[form.emitter, path.key]
|
|
2341
2926
|
);
|
|
2342
2927
|
const raw = useWatchCore(subscribeFactory, () => getValueByPath(form, path));
|
|
2343
2928
|
const value = toDisplay ? toDisplay(raw) : raw;
|
|
2929
|
+
const timerRef = React.useRef(null);
|
|
2930
|
+
const seqRef = React.useRef(0);
|
|
2931
|
+
const fromDisplayRef = useStage(fromDisplay);
|
|
2932
|
+
const debounceRef = useStage(asyncDebounceMs ?? 0);
|
|
2933
|
+
React.useEffect(
|
|
2934
|
+
() => () => {
|
|
2935
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
2936
|
+
},
|
|
2937
|
+
[]
|
|
2938
|
+
);
|
|
2344
2939
|
const onChange = React.useCallback(
|
|
2345
2940
|
(display) => {
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2941
|
+
const run = () => {
|
|
2942
|
+
const seq = ++seqRef.current;
|
|
2943
|
+
const transform = fromDisplayRef.current;
|
|
2944
|
+
const commit = (next) => userChangeByPath(form, path, next);
|
|
2945
|
+
if (!transform) {
|
|
2946
|
+
commit(display);
|
|
2947
|
+
return;
|
|
2948
|
+
}
|
|
2949
|
+
const result = transform(display);
|
|
2950
|
+
if (isPromise(result)) {
|
|
2951
|
+
result.then((next) => {
|
|
2952
|
+
if (seqRef.current === seq) commit(next);
|
|
2953
|
+
});
|
|
2954
|
+
} else if (seqRef.current === seq) {
|
|
2955
|
+
commit(result);
|
|
2956
|
+
}
|
|
2957
|
+
};
|
|
2958
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
2959
|
+
timerRef.current = null;
|
|
2960
|
+
if (debounceRef.current > 0) {
|
|
2961
|
+
timerRef.current = setTimeout(run, debounceRef.current);
|
|
2962
|
+
} else {
|
|
2963
|
+
run();
|
|
2964
|
+
}
|
|
2351
2965
|
},
|
|
2352
|
-
[form, path,
|
|
2966
|
+
[form, path, fromDisplayRef, debounceRef]
|
|
2353
2967
|
);
|
|
2354
2968
|
return { value, onChange };
|
|
2355
2969
|
}
|
|
@@ -2403,6 +3017,7 @@
|
|
|
2403
3017
|
onInvalidSubmit,
|
|
2404
3018
|
action,
|
|
2405
3019
|
shouldFocusError,
|
|
3020
|
+
shouldUseNativeValidation,
|
|
2406
3021
|
...props
|
|
2407
3022
|
}) {
|
|
2408
3023
|
const f2 = useForm({
|
|
@@ -2411,7 +3026,8 @@
|
|
|
2411
3026
|
shouldUnregister,
|
|
2412
3027
|
validateOnMount,
|
|
2413
3028
|
disabled,
|
|
2414
|
-
asyncAlways
|
|
3029
|
+
asyncAlways,
|
|
3030
|
+
shouldUseNativeValidation
|
|
2415
3031
|
});
|
|
2416
3032
|
const form = f1 || f2;
|
|
2417
3033
|
React__namespace.useEffect(() => {
|
|
@@ -2422,10 +3038,12 @@
|
|
|
2422
3038
|
onValidSubmit,
|
|
2423
3039
|
onInvalidSubmit,
|
|
2424
3040
|
shouldFocusError,
|
|
2425
|
-
|
|
3041
|
+
shouldUseNativeValidation,
|
|
3042
|
+
onAction: typeof action === "function" ? (values2) => action(formDataFromValues(values2)) : void 0
|
|
2426
3043
|
});
|
|
2427
3044
|
const { Provider } = context ?? FormContext;
|
|
2428
|
-
|
|
3045
|
+
const nativeAction = typeof action === "string" ? action : void 0;
|
|
3046
|
+
return /* @__PURE__ */ React__namespace.createElement(Provider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, action: nativeAction, noValidate: true, onSubmit: submit }));
|
|
2429
3047
|
}
|
|
2430
3048
|
|
|
2431
3049
|
function FormField({ children, ...options }) {
|
|
@@ -2440,18 +3058,14 @@
|
|
|
2440
3058
|
ref.current = value;
|
|
2441
3059
|
}
|
|
2442
3060
|
}
|
|
2443
|
-
function errorIdFromKey(key) {
|
|
2444
|
-
const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
|
|
2445
|
-
return id || "field";
|
|
2446
|
-
}
|
|
2447
3061
|
function ariaProps(error, fieldKey, props) {
|
|
2448
3062
|
return {
|
|
2449
3063
|
"aria-invalid": error ? true : props["aria-invalid"],
|
|
2450
3064
|
"aria-describedby": error ? [props["aria-describedby"], errorIdFromKey(fieldKey)].filter(Boolean).join(" ") : props["aria-describedby"]
|
|
2451
3065
|
};
|
|
2452
3066
|
}
|
|
2453
|
-
function
|
|
2454
|
-
return
|
|
3067
|
+
function toConstraintAttrs(rules) {
|
|
3068
|
+
return rules ? rulesToConstraintAttrs(rules) : void 0;
|
|
2455
3069
|
}
|
|
2456
3070
|
const Field = React__namespace.forwardRef(
|
|
2457
3071
|
({
|
|
@@ -2479,6 +3093,10 @@
|
|
|
2479
3093
|
}, ref) => {
|
|
2480
3094
|
const innerRef = React__namespace.useRef(null);
|
|
2481
3095
|
const [nativeInvalidCount, setNativeInvalidCount] = React__namespace.useState(0);
|
|
3096
|
+
const contextForm = React__namespace.useContext(FormContext);
|
|
3097
|
+
const resolvedForm = formProp ?? contextForm;
|
|
3098
|
+
const isFile = props.type === "file";
|
|
3099
|
+
const validateWrapped = validate && hasStandardProps(validate) ? schemaToFieldValidator(validate) : validate;
|
|
2482
3100
|
const {
|
|
2483
3101
|
value,
|
|
2484
3102
|
onChange,
|
|
@@ -2486,7 +3104,8 @@
|
|
|
2486
3104
|
error,
|
|
2487
3105
|
name: fieldKey,
|
|
2488
3106
|
disabled: isDisabled,
|
|
2489
|
-
focusRef
|
|
3107
|
+
focusRef,
|
|
3108
|
+
validating
|
|
2490
3109
|
} = useField({
|
|
2491
3110
|
name,
|
|
2492
3111
|
form: formProp,
|
|
@@ -2499,19 +3118,20 @@
|
|
|
2499
3118
|
disabled,
|
|
2500
3119
|
asyncAlways,
|
|
2501
3120
|
mode,
|
|
2502
|
-
// File inputs
|
|
2503
|
-
|
|
2504
|
-
uncontrolled: uncontrolled || props.type === "file",
|
|
3121
|
+
// File inputs can't be value-controlled — force the uncontrolled path.
|
|
3122
|
+
uncontrolled: uncontrolled || isFile,
|
|
2505
3123
|
validate: (...params) => {
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
el.
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
3124
|
+
if (resolvedForm?.shouldUseNativeValidation !== false) {
|
|
3125
|
+
const el = innerRef.current;
|
|
3126
|
+
if (el && typeof el.checkValidity === "function") {
|
|
3127
|
+
el.setCustomValidity("");
|
|
3128
|
+
if (el.checkValidity() === false) {
|
|
3129
|
+
setNativeInvalidCount((count) => count + 1);
|
|
3130
|
+
return void 0;
|
|
3131
|
+
}
|
|
2512
3132
|
}
|
|
2513
3133
|
}
|
|
2514
|
-
if (
|
|
3134
|
+
if (validateWrapped) return validateWrapped(...params);
|
|
2515
3135
|
}
|
|
2516
3136
|
});
|
|
2517
3137
|
const mergedRef = React__namespace.useCallback(
|
|
@@ -2522,7 +3142,6 @@
|
|
|
2522
3142
|
},
|
|
2523
3143
|
[ref, focusRef]
|
|
2524
3144
|
);
|
|
2525
|
-
const Component = as || "input";
|
|
2526
3145
|
React__namespace.useEffect(() => {
|
|
2527
3146
|
const el = innerRef.current;
|
|
2528
3147
|
if (!el || typeof el.setCustomValidity !== "function") return;
|
|
@@ -2536,11 +3155,14 @@
|
|
|
2536
3155
|
React__namespace.useEffect(() => {
|
|
2537
3156
|
if (nativeInvalidCount > 0) innerRef.current?.reportValidity();
|
|
2538
3157
|
}, [nativeInvalidCount]);
|
|
2539
|
-
const
|
|
2540
|
-
const toValue = eventToValue
|
|
3158
|
+
const Component = as || "input";
|
|
3159
|
+
const toValue = eventToValueOrDefault(eventToValue, {
|
|
3160
|
+
valueAsNumber,
|
|
3161
|
+
valueAsDate
|
|
3162
|
+
});
|
|
2541
3163
|
const valueProps = valueToProps ? valueToProps(value) : isFile ? {} : uncontrolled ? { defaultValue: value } : { value };
|
|
2542
3164
|
const errorId = errorIdFromKey(fieldKey);
|
|
2543
|
-
const constraintAttrs =
|
|
3165
|
+
const constraintAttrs = toConstraintAttrs(rules);
|
|
2544
3166
|
return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement(
|
|
2545
3167
|
Component,
|
|
2546
3168
|
{
|
|
@@ -2552,6 +3174,7 @@
|
|
|
2552
3174
|
...valueProps,
|
|
2553
3175
|
...ariaProps(error, fieldKey, props),
|
|
2554
3176
|
disabled: isDisabled,
|
|
3177
|
+
"aria-busy": validating || void 0,
|
|
2555
3178
|
onChange: (e) => onChange(toValue(e)),
|
|
2556
3179
|
ref: mergedRef
|
|
2557
3180
|
}
|
|
@@ -2580,7 +3203,8 @@
|
|
|
2580
3203
|
onBlur,
|
|
2581
3204
|
error,
|
|
2582
3205
|
name: fieldKey,
|
|
2583
|
-
disabled: isDisabled
|
|
3206
|
+
disabled: isDisabled,
|
|
3207
|
+
validating
|
|
2584
3208
|
} = useField({
|
|
2585
3209
|
name,
|
|
2586
3210
|
form,
|
|
@@ -2595,7 +3219,7 @@
|
|
|
2595
3219
|
disabled,
|
|
2596
3220
|
mode
|
|
2597
3221
|
});
|
|
2598
|
-
const constraintAttrs =
|
|
3222
|
+
const constraintAttrs = toConstraintAttrs(rules);
|
|
2599
3223
|
return /* @__PURE__ */ React__namespace.createElement(
|
|
2600
3224
|
"input",
|
|
2601
3225
|
{
|
|
@@ -2607,6 +3231,7 @@
|
|
|
2607
3231
|
checked: !!value,
|
|
2608
3232
|
...ariaProps(error, fieldKey, props),
|
|
2609
3233
|
disabled: isDisabled,
|
|
3234
|
+
"aria-busy": validating || void 0,
|
|
2610
3235
|
onChange: (e) => onChange(e.target.checked),
|
|
2611
3236
|
ref
|
|
2612
3237
|
}
|
|
@@ -2641,7 +3266,8 @@
|
|
|
2641
3266
|
onBlur,
|
|
2642
3267
|
error,
|
|
2643
3268
|
name: fieldKey,
|
|
2644
|
-
disabled: isDisabled
|
|
3269
|
+
disabled: isDisabled,
|
|
3270
|
+
validating
|
|
2645
3271
|
} = useField({
|
|
2646
3272
|
name,
|
|
2647
3273
|
form,
|
|
@@ -2656,7 +3282,7 @@
|
|
|
2656
3282
|
disabled,
|
|
2657
3283
|
mode
|
|
2658
3284
|
});
|
|
2659
|
-
const constraintAttrs =
|
|
3285
|
+
const constraintAttrs = toConstraintAttrs(rules);
|
|
2660
3286
|
return /* @__PURE__ */ React__namespace.createElement(
|
|
2661
3287
|
"select",
|
|
2662
3288
|
{
|
|
@@ -2668,6 +3294,7 @@
|
|
|
2668
3294
|
value: toSelectValue(multiple, value),
|
|
2669
3295
|
...ariaProps(error, fieldKey, props),
|
|
2670
3296
|
disabled: isDisabled,
|
|
3297
|
+
"aria-busy": validating || void 0,
|
|
2671
3298
|
onChange: (e) => onChange(
|
|
2672
3299
|
multiple ? Array.from(e.target.selectedOptions, (option) => option.value) : e.target.value
|
|
2673
3300
|
),
|
|
@@ -2678,9 +3305,74 @@
|
|
|
2678
3305
|
}
|
|
2679
3306
|
);
|
|
2680
3307
|
|
|
3308
|
+
function ErrorSummary({
|
|
3309
|
+
form: formProp,
|
|
3310
|
+
context,
|
|
3311
|
+
heading
|
|
3312
|
+
}) {
|
|
3313
|
+
const contextForm = React__namespace.useContext(context ?? FormContext);
|
|
3314
|
+
const form = formProp ?? contextForm;
|
|
3315
|
+
if (!form) throw new Error("no form provided");
|
|
3316
|
+
const containerRef = React__namespace.useRef(null);
|
|
3317
|
+
const wasSubmittingRef = React__namespace.useRef(false);
|
|
3318
|
+
const headingId = React__namespace.useId();
|
|
3319
|
+
const errors = useErrors(form);
|
|
3320
|
+
const subscribeFactory = React__namespace.useCallback(
|
|
3321
|
+
(invalidate) => {
|
|
3322
|
+
const check = () => {
|
|
3323
|
+
const wasSubmitting = wasSubmittingRef.current;
|
|
3324
|
+
wasSubmittingRef.current = form.isSubmitting;
|
|
3325
|
+
if (wasSubmitting && !form.isSubmitting && hasErrors(form)) {
|
|
3326
|
+
containerRef.current?.focus();
|
|
3327
|
+
}
|
|
3328
|
+
invalidate();
|
|
3329
|
+
};
|
|
3330
|
+
const offErrors = on(form.emitter, "errors", check);
|
|
3331
|
+
const offSubmitting = on(form.emitter, "submitting", check);
|
|
3332
|
+
return () => {
|
|
3333
|
+
offErrors();
|
|
3334
|
+
offSubmitting();
|
|
3335
|
+
};
|
|
3336
|
+
},
|
|
3337
|
+
[form]
|
|
3338
|
+
);
|
|
3339
|
+
useWatchCore(subscribeFactory, () => null);
|
|
3340
|
+
const entries = Object.entries(errors);
|
|
3341
|
+
if (entries.length === 0) return null;
|
|
3342
|
+
return /* @__PURE__ */ React__namespace.createElement(
|
|
3343
|
+
"div",
|
|
3344
|
+
{
|
|
3345
|
+
role: "alert",
|
|
3346
|
+
tabIndex: -1,
|
|
3347
|
+
ref: containerRef,
|
|
3348
|
+
"aria-labelledby": headingId
|
|
3349
|
+
},
|
|
3350
|
+
/* @__PURE__ */ React__namespace.createElement("h2", { id: headingId }, heading ?? "There is a problem"),
|
|
3351
|
+
/* @__PURE__ */ React__namespace.createElement("ul", null, entries.map(([dottedKey, list]) => {
|
|
3352
|
+
const message = list[0]?.message;
|
|
3353
|
+
if (dottedKey === FORM_ERROR) {
|
|
3354
|
+
return /* @__PURE__ */ React__namespace.createElement("li", { key: dottedKey }, /* @__PURE__ */ React__namespace.createElement("p", null, message));
|
|
3355
|
+
}
|
|
3356
|
+
const path = dottedKeyToFieldPath(dottedKey);
|
|
3357
|
+
return /* @__PURE__ */ React__namespace.createElement("li", { key: dottedKey }, /* @__PURE__ */ React__namespace.createElement(
|
|
3358
|
+
"a",
|
|
3359
|
+
{
|
|
3360
|
+
href: `#${fieldErrorId(path)}`,
|
|
3361
|
+
onClick: (e) => {
|
|
3362
|
+
e.preventDefault();
|
|
3363
|
+
setFocus(form, path);
|
|
3364
|
+
}
|
|
3365
|
+
},
|
|
3366
|
+
message
|
|
3367
|
+
));
|
|
3368
|
+
}))
|
|
3369
|
+
);
|
|
3370
|
+
}
|
|
3371
|
+
|
|
2681
3372
|
exports.Checkbox = Checkbox;
|
|
2682
3373
|
exports.CheckboxGroupContext = CheckboxGroupContext;
|
|
2683
3374
|
exports.CheckboxGroupProvider = CheckboxGroupProvider;
|
|
3375
|
+
exports.ErrorSummary = ErrorSummary;
|
|
2684
3376
|
exports.FORM_ERROR = FORM_ERROR;
|
|
2685
3377
|
exports.Field = Field;
|
|
2686
3378
|
exports.Form = Form;
|
|
@@ -2689,18 +3381,26 @@
|
|
|
2689
3381
|
exports.FormProvider = FormProvider;
|
|
2690
3382
|
exports.Select = Select;
|
|
2691
3383
|
exports.VALIDATION_OUTCOME = VALIDATION_OUTCOME;
|
|
3384
|
+
exports.appendValue = appendValue;
|
|
3385
|
+
exports.appendValueByPath = appendValueByPath;
|
|
2692
3386
|
exports.changeValue = changeValue;
|
|
2693
3387
|
exports.changeValueByPath = changeValueByPath;
|
|
2694
3388
|
exports.clearErrors = clearErrors;
|
|
3389
|
+
exports.clearServerErrors = clearServerErrors;
|
|
2695
3390
|
exports.createForm = create;
|
|
2696
3391
|
exports.createFormContext = createFormContext;
|
|
3392
|
+
exports.dottedKeyToFieldPath = dottedKeyToFieldPath;
|
|
2697
3393
|
exports.emitChangeByPath = emitChangeByPath;
|
|
2698
3394
|
exports.ensureValidate = ensureValidate;
|
|
2699
3395
|
exports.fieldErrorId = fieldErrorId;
|
|
3396
|
+
exports.fieldPathToDottedKey = fieldPathToDottedKey;
|
|
3397
|
+
exports.firstMountedDescendantKey = firstMountedDescendantKey;
|
|
2700
3398
|
exports.getDirtyFields = getDirtyFields;
|
|
2701
3399
|
exports.getError = getError;
|
|
2702
3400
|
exports.getErrorByPath = getErrorByPath;
|
|
2703
3401
|
exports.getErrors = getErrors;
|
|
3402
|
+
exports.getErrorsRecord = getErrorsRecord;
|
|
3403
|
+
exports.getErrorsTree = getErrorsTree;
|
|
2704
3404
|
exports.getFieldErrors = getFieldErrors;
|
|
2705
3405
|
exports.getFieldErrorsByPath = getFieldErrorsByPath;
|
|
2706
3406
|
exports.getFieldState = getFieldState;
|
|
@@ -2714,14 +3414,25 @@
|
|
|
2714
3414
|
exports.hasTouched = hasTouched;
|
|
2715
3415
|
exports.hasTouchedByPath = hasTouchedByPath;
|
|
2716
3416
|
exports.incrementSubmitCount = incrementSubmitCount;
|
|
3417
|
+
exports.insertValue = insertValue;
|
|
3418
|
+
exports.insertValueByPath = insertValueByPath;
|
|
2717
3419
|
exports.isDirty = isDirty;
|
|
2718
3420
|
exports.isFieldDirtyByPath = isFieldDirtyByPath;
|
|
2719
3421
|
exports.isTouched = isTouched;
|
|
3422
|
+
exports.moveValue = moveValue;
|
|
3423
|
+
exports.moveValueByPath = moveValueByPath;
|
|
3424
|
+
exports.prependValue = prependValue;
|
|
3425
|
+
exports.prependValueByPath = prependValueByPath;
|
|
3426
|
+
exports.registerField = registerField;
|
|
2720
3427
|
exports.registerFieldMode = registerFieldMode;
|
|
2721
3428
|
exports.registerFieldValidateDeps = registerFieldValidateDeps;
|
|
2722
3429
|
exports.registerValidatorByPath = registerValidatorByPath;
|
|
2723
3430
|
exports.removeField = removeField;
|
|
2724
3431
|
exports.removeFieldByPath = removeFieldByPath;
|
|
3432
|
+
exports.removeValue = removeValue;
|
|
3433
|
+
exports.removeValueByPath = removeValueByPath;
|
|
3434
|
+
exports.replaceValues = replaceValues;
|
|
3435
|
+
exports.replaceValuesByPath = replaceValuesByPath;
|
|
2725
3436
|
exports.reset = reset;
|
|
2726
3437
|
exports.resetField = resetField;
|
|
2727
3438
|
exports.revalidateDependentsOnChange = revalidateDependentsOnChange;
|
|
@@ -2742,16 +3453,23 @@
|
|
|
2742
3453
|
exports.setValidatingByPath = setValidatingByPath;
|
|
2743
3454
|
exports.setValue = setValue;
|
|
2744
3455
|
exports.setValueByPath = setValueByPath;
|
|
3456
|
+
exports.shouldKick = shouldKick;
|
|
2745
3457
|
exports.subscribe = subscribe;
|
|
3458
|
+
exports.swapValues = swapValues;
|
|
3459
|
+
exports.swapValuesByPath = swapValuesByPath;
|
|
2746
3460
|
exports.trigger = trigger;
|
|
2747
3461
|
exports.unregisterFieldMode = unregisterFieldMode;
|
|
2748
3462
|
exports.unregisterFieldValidateDeps = unregisterFieldValidateDeps;
|
|
2749
3463
|
exports.unsetValidatingByPath = unsetValidatingByPath;
|
|
3464
|
+
exports.updateValue = updateValue;
|
|
3465
|
+
exports.updateValueByPath = updateValueByPath;
|
|
2750
3466
|
exports.useCanSubmit = useCanSubmit;
|
|
2751
3467
|
exports.useCheckboxGroupContext = useCheckboxGroupContext;
|
|
2752
3468
|
exports.useDirtyFields = useDirtyFields;
|
|
2753
3469
|
exports.useError = useError;
|
|
2754
3470
|
exports.useErrorByPath = useErrorByPath;
|
|
3471
|
+
exports.useErrors = useErrors;
|
|
3472
|
+
exports.useErrorsTree = useErrorsTree;
|
|
2755
3473
|
exports.useField = useField;
|
|
2756
3474
|
exports.useFieldArray = useFieldArray;
|
|
2757
3475
|
exports.useFieldArrayItem = useFieldArrayItem;
|
|
@@ -2772,6 +3490,7 @@
|
|
|
2772
3490
|
exports.useIsValid = useIsValid;
|
|
2773
3491
|
exports.useIsValidating = useIsValidating;
|
|
2774
3492
|
exports.useStatus = useStatus;
|
|
3493
|
+
exports.useStore = useStore;
|
|
2775
3494
|
exports.useSubmitCount = useSubmitCount;
|
|
2776
3495
|
exports.useTouched = useTouched;
|
|
2777
3496
|
exports.useTouchedByPath = useTouchedByPath;
|
|
@@ -2779,11 +3498,13 @@
|
|
|
2779
3498
|
exports.useTransform = useTransform;
|
|
2780
3499
|
exports.useValue = useValue;
|
|
2781
3500
|
exports.useValueByPath = useValueByPath;
|
|
3501
|
+
exports.useValues = useValues;
|
|
2782
3502
|
exports.useWatch = useWatch;
|
|
2783
3503
|
exports.useWatchCore = useWatchCore;
|
|
2784
3504
|
exports.userBlur = userBlur;
|
|
2785
3505
|
exports.userChangeByPath = userChangeByPath;
|
|
2786
3506
|
exports.validate = validate;
|
|
3507
|
+
exports.watch = watch;
|
|
2787
3508
|
|
|
2788
3509
|
}));
|
|
2789
3510
|
//# sourceMappingURL=index.umd.js.map
|