react-f0rm 1.4.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 +17 -4
- 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 +8 -18
- package/dist/devtools/index.d.mts +8 -18
- package/dist/devtools/index.d.ts +8 -18
- 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 +347 -927
- package/dist/index.d.mts +347 -927
- package/dist/index.d.ts +347 -927
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +538 -451
- 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 +9 -30
- package/dist/persist.d.mts +9 -30
- 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.d.cts +1 -1
- package/dist/resolvers/standard-schema.d.mts +1 -1
- package/dist/resolvers/standard-schema.d.ts +1 -1
- package/dist/resolvers/standard-schema.mjs +1 -1
- package/dist/resolvers/yup.cjs.js +1 -1
- package/dist/resolvers/yup.mjs +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 +30 -2
- package/dist/resolvers/zod.d.mts +30 -2
- package/dist/resolvers/zod.d.ts +30 -2
- 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 +24 -92
- package/dist/server/index.d.mts +24 -92
- package/dist/server/index.d.ts +24 -92
- 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 +6 -4
- package/dist/array-3hAjl6Bz.d.ts +0 -160
- package/dist/errors-8oPux7GR.cjs.js +0 -2
- package/dist/errors-8oPux7GR.cjs.js.map +0 -1
- package/dist/errors-ClH3eV1R.mjs +0 -2
- package/dist/errors-ClH3eV1R.mjs.map +0 -1
- package/dist/standard-schema-CYbnugL7.d.ts +0 -1184
- package/dist/standardSchema-BpZvg0tZ.mjs +0 -2
- package/dist/standardSchema-BpZvg0tZ.mjs.map +0 -1
- package/dist/standardSchema-CxV_DhBO.cjs.js +0 -2
- package/dist/standardSchema-CxV_DhBO.cjs.js.map +0 -1
- package/dist/validate-BEjNsNvd.mjs +0 -2
- package/dist/validate-BEjNsNvd.mjs.map +0 -1
- package/dist/validate-BvN6hiEG.cjs.js +0 -2
- package/dist/validate-BvN6hiEG.cjs.js.map +0 -1
- package/dist/values-Bod74Kzu.mjs +0 -2
- package/dist/values-Bod74Kzu.mjs.map +0 -1
- package/dist/values-DKpOCD5J.cjs.js +0 -2
- package/dist/values-DKpOCD5J.cjs.js.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;
|
|
@@ -318,6 +331,9 @@
|
|
|
318
331
|
if (options?.valueAsDate) return target.valueAsDate;
|
|
319
332
|
return target.value;
|
|
320
333
|
}
|
|
334
|
+
function eventToValueOrDefault(eventToValue, options) {
|
|
335
|
+
return eventToValue ?? ((e) => extractEventValue(e, options));
|
|
336
|
+
}
|
|
321
337
|
function isEqual(a, b) {
|
|
322
338
|
if (Object.is(a, b)) return true;
|
|
323
339
|
if (a instanceof Date && b instanceof Date)
|
|
@@ -364,16 +380,27 @@
|
|
|
364
380
|
const value = normalizePath(name);
|
|
365
381
|
return { value, key: JSON.stringify(value) };
|
|
366
382
|
}
|
|
383
|
+
function segmentsFromKey(key) {
|
|
384
|
+
return JSON.parse(key);
|
|
385
|
+
}
|
|
367
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
|
+
}
|
|
368
393
|
const valuesCaches = /* @__PURE__ */ new WeakMap();
|
|
369
|
-
function
|
|
370
|
-
const cache =
|
|
394
|
+
function bumpVersion(map, form) {
|
|
395
|
+
const cache = map.get(form);
|
|
371
396
|
if (cache) cache.version++;
|
|
372
397
|
}
|
|
398
|
+
function bumpValuesVersion(form) {
|
|
399
|
+
bumpVersion(valuesCaches, form);
|
|
400
|
+
}
|
|
373
401
|
const errorsCaches = /* @__PURE__ */ new WeakMap();
|
|
374
402
|
function bumpErrorsVersion(form) {
|
|
375
|
-
|
|
376
|
-
if (cache) cache.version++;
|
|
403
|
+
bumpVersion(errorsCaches, form);
|
|
377
404
|
}
|
|
378
405
|
const dirtyBaselines = /* @__PURE__ */ new WeakMap();
|
|
379
406
|
function getDirtyBaseline(form, key, segments) {
|
|
@@ -382,12 +409,7 @@
|
|
|
382
409
|
return get(form.initialValues, segments);
|
|
383
410
|
}
|
|
384
411
|
function setDirtyBaseline(form, { key }, value) {
|
|
385
|
-
|
|
386
|
-
if (!baselines) {
|
|
387
|
-
baselines = /* @__PURE__ */ new Map();
|
|
388
|
-
dirtyBaselines.set(form, baselines);
|
|
389
|
-
}
|
|
390
|
-
baselines.set(key, value);
|
|
412
|
+
getOrCreate(dirtyBaselines, form, () => /* @__PURE__ */ new Map()).set(key, value);
|
|
391
413
|
}
|
|
392
414
|
function pruneDirtyBaselines(form, { key }) {
|
|
393
415
|
const baselines = dirtyBaselines.get(form);
|
|
@@ -405,8 +427,7 @@
|
|
|
405
427
|
}
|
|
406
428
|
const dirtyFieldsCaches = /* @__PURE__ */ new WeakMap();
|
|
407
429
|
function bumpDirtyVersion(form) {
|
|
408
|
-
|
|
409
|
-
if (cache) cache.version++;
|
|
430
|
+
bumpVersion(dirtyFieldsCaches, form);
|
|
410
431
|
}
|
|
411
432
|
function isSegmentsPath(name) {
|
|
412
433
|
return name.some((part) => typeof part === "number");
|
|
@@ -439,18 +460,18 @@
|
|
|
439
460
|
function getErrors({ errors }) {
|
|
440
461
|
const entries = [];
|
|
441
462
|
for (const [key, list] of errors) {
|
|
442
|
-
const path =
|
|
463
|
+
const path = segmentsFromKey(key).join(".");
|
|
443
464
|
for (const { type, message } of list) entries.push({ path, type, message });
|
|
444
465
|
}
|
|
445
466
|
return entries;
|
|
446
467
|
}
|
|
447
468
|
function computeErrorsViews(form) {
|
|
448
469
|
const cached = errorsCaches.get(form);
|
|
449
|
-
if (cached
|
|
470
|
+
if (cached?.version === 0) return;
|
|
450
471
|
const result = {};
|
|
451
472
|
const tree = {};
|
|
452
473
|
for (const [key, list] of form.errors) {
|
|
453
|
-
const segments =
|
|
474
|
+
const segments = segmentsFromKey(key);
|
|
454
475
|
result[segments.join(".")] = list;
|
|
455
476
|
let node = tree;
|
|
456
477
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
@@ -546,21 +567,17 @@
|
|
|
546
567
|
}
|
|
547
568
|
}
|
|
548
569
|
function clearServerErrors(form) {
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
changed = true;
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
if (changed) {
|
|
561
|
-
bumpErrorsVersion(form);
|
|
562
|
-
emit(form.emitter, "errors");
|
|
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);
|
|
563
578
|
}
|
|
579
|
+
bumpErrorsVersion(form);
|
|
580
|
+
emit(form.emitter, "errors");
|
|
564
581
|
}
|
|
565
582
|
function hasErrors({ errors }) {
|
|
566
583
|
return errors.size > 0;
|
|
@@ -603,22 +620,18 @@
|
|
|
603
620
|
};
|
|
604
621
|
}
|
|
605
622
|
function toPathSegments(issue) {
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
}
|
|
612
|
-
return segments;
|
|
623
|
+
return (issue.path || []).map(
|
|
624
|
+
(segment) => String(
|
|
625
|
+
typeof segment === "object" && segment !== null ? segment.key : segment
|
|
626
|
+
)
|
|
627
|
+
);
|
|
613
628
|
}
|
|
614
629
|
function assignAtPath(root, segments, error) {
|
|
615
630
|
let node = root;
|
|
616
631
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
617
632
|
const segment = segments[i];
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
next = node[segment] = {};
|
|
621
|
-
}
|
|
633
|
+
if (node[segment] === void 0) node[segment] = {};
|
|
634
|
+
const next = node[segment];
|
|
622
635
|
if (!isBranch(next)) return;
|
|
623
636
|
node = next;
|
|
624
637
|
}
|
|
@@ -631,21 +644,16 @@
|
|
|
631
644
|
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
632
645
|
}
|
|
633
646
|
function pruneEmpty(node) {
|
|
634
|
-
let hasLeaf = false;
|
|
635
647
|
const result = {};
|
|
636
|
-
|
|
648
|
+
for (const [key, value] of Object.entries(node)) {
|
|
637
649
|
if (isBranch(value)) {
|
|
638
650
|
const pruned = pruneEmpty(value);
|
|
639
|
-
if (pruned)
|
|
640
|
-
result[key] = pruned;
|
|
641
|
-
hasLeaf = true;
|
|
642
|
-
}
|
|
651
|
+
if (pruned) result[key] = pruned;
|
|
643
652
|
} else {
|
|
644
653
|
result[key] = value;
|
|
645
|
-
hasLeaf = true;
|
|
646
654
|
}
|
|
647
|
-
}
|
|
648
|
-
return
|
|
655
|
+
}
|
|
656
|
+
return Object.keys(result).length ? result : void 0;
|
|
649
657
|
}
|
|
650
658
|
|
|
651
659
|
function isFieldDirtyByPath(form, path) {
|
|
@@ -653,15 +661,15 @@
|
|
|
653
661
|
return form.values.has(path.key) && getDirtyBaseline(form, path.key, path.value) !== live;
|
|
654
662
|
}
|
|
655
663
|
function isDirty(form) {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
}
|
|
660
|
-
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;
|
|
661
669
|
}
|
|
662
670
|
function forEachDirtyField(form, fn) {
|
|
663
671
|
for (const [key, value] of form.values) {
|
|
664
|
-
const path =
|
|
672
|
+
const path = segmentsFromKey(key);
|
|
665
673
|
if (getDirtyBaseline(form, key, path) !== value) fn(path.join("."));
|
|
666
674
|
}
|
|
667
675
|
}
|
|
@@ -678,11 +686,11 @@
|
|
|
678
686
|
return aKeys.every((key) => b[key] === true);
|
|
679
687
|
}
|
|
680
688
|
function getDirtyFields(form) {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
689
|
+
const cache = getOrCreate(dirtyFieldsCaches, form, () => ({
|
|
690
|
+
version: 0,
|
|
691
|
+
result: computeDirtyFields(form)
|
|
692
|
+
}));
|
|
693
|
+
if (cache.version > 0) {
|
|
686
694
|
const result = computeDirtyFields(form);
|
|
687
695
|
if (!sameDirtyKeys(cache.result, result)) cache.result = result;
|
|
688
696
|
cache.version = 0;
|
|
@@ -705,21 +713,18 @@
|
|
|
705
713
|
return touched.has(path.key);
|
|
706
714
|
}
|
|
707
715
|
function getTouchedFields({ touched }) {
|
|
708
|
-
return Array.from(
|
|
709
|
-
touched,
|
|
710
|
-
(key) => JSON.parse(key).join(".")
|
|
711
|
-
);
|
|
716
|
+
return Array.from(touched, (key) => segmentsFromKey(key).join("."));
|
|
712
717
|
}
|
|
713
718
|
function isTouched({ touched }) {
|
|
714
719
|
return touched.size > 0;
|
|
715
720
|
}
|
|
716
721
|
|
|
717
722
|
function getValues(form) {
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
+
const cache = getOrCreate(valuesCaches, form, () => ({
|
|
724
|
+
version: 0,
|
|
725
|
+
result: computeValues(form)
|
|
726
|
+
}));
|
|
727
|
+
if (cache.version > 0) {
|
|
723
728
|
cache.result = computeValues(form);
|
|
724
729
|
cache.version = 0;
|
|
725
730
|
}
|
|
@@ -730,10 +735,10 @@
|
|
|
730
735
|
const owned = /* @__PURE__ */ new Set();
|
|
731
736
|
let merged = parsedValues ?? initialValues;
|
|
732
737
|
for (const [key, value] of values) {
|
|
733
|
-
merged = setOwned(merged,
|
|
738
|
+
merged = setOwned(merged, segmentsFromKey(key), value, owned);
|
|
734
739
|
}
|
|
735
740
|
for (const key of deleted) {
|
|
736
|
-
merged = unset(merged,
|
|
741
|
+
merged = unset(merged, segmentsFromKey(key));
|
|
737
742
|
}
|
|
738
743
|
return merged;
|
|
739
744
|
}
|
|
@@ -857,9 +862,9 @@
|
|
|
857
862
|
function collectValueLeaves(node, segments, out) {
|
|
858
863
|
if (node !== null && typeof node === "object") {
|
|
859
864
|
if (Array.isArray(node)) {
|
|
860
|
-
|
|
861
|
-
collectValueLeaves(
|
|
862
|
-
|
|
865
|
+
node.forEach(
|
|
866
|
+
(item, i) => collectValueLeaves(item, [...segments, i], out)
|
|
867
|
+
);
|
|
863
868
|
return;
|
|
864
869
|
}
|
|
865
870
|
const keys = Object.keys(node);
|
|
@@ -872,18 +877,22 @@
|
|
|
872
877
|
}
|
|
873
878
|
out.push({ segments, value: node });
|
|
874
879
|
}
|
|
875
|
-
function
|
|
876
|
-
const
|
|
880
|
+
function collectKeptValues(form, options) {
|
|
881
|
+
const kept = [];
|
|
877
882
|
if (options?.keepValues) {
|
|
878
|
-
collectValueLeaves(getValues(form), [],
|
|
883
|
+
collectValueLeaves(getValues(form), [], kept);
|
|
879
884
|
} else if (options?.keepDirtyValues) {
|
|
880
885
|
for (const [key, value] of form.values) {
|
|
881
|
-
const segments =
|
|
886
|
+
const segments = segmentsFromKey(key);
|
|
882
887
|
if (getDirtyBaseline(form, key, segments) !== value) {
|
|
883
|
-
|
|
888
|
+
kept.push({ segments, value });
|
|
884
889
|
}
|
|
885
890
|
}
|
|
886
891
|
}
|
|
892
|
+
return kept;
|
|
893
|
+
}
|
|
894
|
+
function reset(form, initialValues, options) {
|
|
895
|
+
const keptValues = collectKeptValues(form, options);
|
|
887
896
|
form.initialValues = options?.keepDefaultValues ? form.initialValues : initialValues ?? form.initialValues;
|
|
888
897
|
form.parsedValues = void 0;
|
|
889
898
|
if (!options?.keepErrors) clearErrors(form);
|
|
@@ -944,13 +953,17 @@
|
|
|
944
953
|
validating.add(path.key);
|
|
945
954
|
emit(emitter, "validating", path);
|
|
946
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
|
+
}
|
|
947
961
|
function registerValidatorByPath(form, path, registration) {
|
|
948
962
|
let timer = null;
|
|
949
963
|
let controller = null;
|
|
950
964
|
let marked = false;
|
|
951
965
|
let lock = null;
|
|
952
966
|
let errorSource = null;
|
|
953
|
-
const hasErrors2 = (errors) => errors !== void 0 && !(Array.isArray(errors) && errors.length === 0);
|
|
954
967
|
const mark = () => {
|
|
955
968
|
if (marked) return;
|
|
956
969
|
marked = true;
|
|
@@ -964,44 +977,42 @@
|
|
|
964
977
|
const runSync = () => {
|
|
965
978
|
const sync = registration.sync();
|
|
966
979
|
if (!sync) return false;
|
|
967
|
-
const
|
|
968
|
-
if (!
|
|
980
|
+
const gate = asErrorList(sync(getValueByPath(form, path), { form, path }));
|
|
981
|
+
if (!gate) {
|
|
969
982
|
if (!registration.validate() || errorSource === "sync") {
|
|
970
983
|
setErrorByPath(form, path, void 0);
|
|
971
984
|
errorSource = null;
|
|
972
985
|
}
|
|
973
986
|
return false;
|
|
974
987
|
}
|
|
975
|
-
setErrorByPath(form, path,
|
|
988
|
+
setErrorByPath(form, path, gate);
|
|
976
989
|
errorSource = "sync";
|
|
977
990
|
return true;
|
|
978
991
|
};
|
|
979
992
|
const collectSyncErrors = () => {
|
|
980
993
|
const sync = registration.sync();
|
|
981
994
|
if (!sync) return null;
|
|
982
|
-
|
|
983
|
-
if (errors === void 0) return null;
|
|
984
|
-
const list = Array.isArray(errors) ? errors : [errors];
|
|
985
|
-
return list.length ? list : null;
|
|
995
|
+
return asErrorList(sync(getValueByPath(form, path), { form, path }));
|
|
986
996
|
};
|
|
987
997
|
const land = (result) => {
|
|
988
998
|
if (registration.asyncAlways?.()) {
|
|
989
999
|
const gate = collectSyncErrors();
|
|
990
|
-
const own =
|
|
1000
|
+
const own = asErrorList(result) ?? [];
|
|
991
1001
|
setErrorByPath(form, path, [...gate ?? [], ...own]);
|
|
992
|
-
errorSource =
|
|
1002
|
+
errorSource = own.length ? "validator" : gate ? "sync" : null;
|
|
993
1003
|
} else {
|
|
994
1004
|
setErrorByPath(form, path, result);
|
|
995
|
-
errorSource =
|
|
1005
|
+
errorSource = asErrorList(result) ? "validator" : null;
|
|
996
1006
|
}
|
|
997
1007
|
};
|
|
998
|
-
const
|
|
1008
|
+
const cancel = () => {
|
|
999
1009
|
if (timer !== null) {
|
|
1000
1010
|
clearTimeout(timer);
|
|
1001
1011
|
timer = null;
|
|
1002
1012
|
}
|
|
1003
1013
|
controller?.abort();
|
|
1004
1014
|
lock = {};
|
|
1015
|
+
unmark();
|
|
1005
1016
|
};
|
|
1006
1017
|
const runValidator = () => {
|
|
1007
1018
|
const fn = registration.validate();
|
|
@@ -1029,13 +1040,11 @@
|
|
|
1029
1040
|
return;
|
|
1030
1041
|
}
|
|
1031
1042
|
mark();
|
|
1032
|
-
result.then(
|
|
1033
|
-
(
|
|
1034
|
-
|
|
1035
|
-
land(error);
|
|
1036
|
-
}
|
|
1043
|
+
result.then((error) => {
|
|
1044
|
+
if (lock === round) {
|
|
1045
|
+
land(error);
|
|
1037
1046
|
}
|
|
1038
|
-
).catch(() => {
|
|
1047
|
+
}).catch(() => {
|
|
1039
1048
|
}).finally(() => {
|
|
1040
1049
|
if (lock === round) {
|
|
1041
1050
|
unmark();
|
|
@@ -1043,21 +1052,18 @@
|
|
|
1043
1052
|
}
|
|
1044
1053
|
});
|
|
1045
1054
|
};
|
|
1055
|
+
const gateOwnsKick = () => {
|
|
1056
|
+
if (!(runSync() && !registration.asyncAlways?.())) return false;
|
|
1057
|
+
cancel();
|
|
1058
|
+
return true;
|
|
1059
|
+
};
|
|
1046
1060
|
const run = () => {
|
|
1047
1061
|
timer = null;
|
|
1048
|
-
if (
|
|
1049
|
-
supersede();
|
|
1050
|
-
unmark();
|
|
1051
|
-
return;
|
|
1052
|
-
}
|
|
1062
|
+
if (gateOwnsKick()) return;
|
|
1053
1063
|
runValidator();
|
|
1054
1064
|
};
|
|
1055
1065
|
const kick = () => {
|
|
1056
|
-
if (
|
|
1057
|
-
supersede();
|
|
1058
|
-
unmark();
|
|
1059
|
-
return;
|
|
1060
|
-
}
|
|
1066
|
+
if (gateOwnsKick()) return;
|
|
1061
1067
|
if (!registration.validate()) return;
|
|
1062
1068
|
const debounce = registration.debounce();
|
|
1063
1069
|
if (debounce > 0) {
|
|
@@ -1071,12 +1077,7 @@
|
|
|
1071
1077
|
form.validators.set(path.key, kick);
|
|
1072
1078
|
return () => {
|
|
1073
1079
|
form.validators.delete(path.key);
|
|
1074
|
-
|
|
1075
|
-
clearTimeout(timer);
|
|
1076
|
-
timer = null;
|
|
1077
|
-
}
|
|
1078
|
-
unmark();
|
|
1079
|
-
controller?.abort();
|
|
1080
|
+
cancel();
|
|
1080
1081
|
};
|
|
1081
1082
|
}
|
|
1082
1083
|
async function trigger(form, name, options) {
|
|
@@ -1086,29 +1087,27 @@
|
|
|
1086
1087
|
() => keys2 === void 0 ? fieldsSettled(form) : keys2.every((key) => !form.validating.has(key)),
|
|
1087
1088
|
() => false
|
|
1088
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
|
+
};
|
|
1089
1094
|
if (name === void 0) {
|
|
1090
1095
|
form.validators.forEach((validator) => validator());
|
|
1091
1096
|
await settle();
|
|
1092
1097
|
if (form.validate) await runFormValidate(form);
|
|
1093
1098
|
if (options?.shouldTouch) touchKeys(form, [...form.validators.keys()]);
|
|
1094
|
-
if (options?.shouldFocus)
|
|
1095
|
-
const firstKey = form.errors.keys().next().value;
|
|
1096
|
-
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
1097
|
-
}
|
|
1099
|
+
if (options?.shouldFocus) focusFirstError();
|
|
1098
1100
|
return !hasErrors(form);
|
|
1099
1101
|
}
|
|
1100
1102
|
const keys = typeof name === "string" || isSegmentsPath(name) ? [create$1(name).key] : name.map((one) => create$1(one).key);
|
|
1101
1103
|
keys.forEach((key) => form.validators.get(key)?.());
|
|
1102
1104
|
await settle(keys);
|
|
1103
1105
|
if (options?.shouldTouch) touchKeys(form, keys);
|
|
1104
|
-
if (options?.shouldFocus)
|
|
1105
|
-
const firstKey = keys.find((key) => form.errors.has(key));
|
|
1106
|
-
if (firstKey !== void 0) emit(form.emitter, "focusError", firstKey);
|
|
1107
|
-
}
|
|
1106
|
+
if (options?.shouldFocus) focusFirstError(keys);
|
|
1108
1107
|
return keys.every((key) => !form.errors.has(key));
|
|
1109
1108
|
}
|
|
1110
1109
|
function touchKeys(form, keys) {
|
|
1111
|
-
keys.forEach((key) => setTouchedByPath(form, create$1(
|
|
1110
|
+
keys.forEach((key) => setTouchedByPath(form, create$1(segmentsFromKey(key))));
|
|
1112
1111
|
}
|
|
1113
1112
|
function setFormErrors(form, result, segments = [], footprint) {
|
|
1114
1113
|
Object.entries(result).forEach(([key, value]) => {
|
|
@@ -1117,16 +1116,9 @@
|
|
|
1117
1116
|
...isIndex(key) ? [key] : normalizePath(key)
|
|
1118
1117
|
];
|
|
1119
1118
|
if (typeof value === "string") {
|
|
1120
|
-
if (value)
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
}
|
|
1124
|
-
} else if (Array.isArray(value)) {
|
|
1125
|
-
setError(form, path, value);
|
|
1126
|
-
recordFootprint(form, path, footprint);
|
|
1127
|
-
} else if (isFieldError(value)) {
|
|
1128
|
-
setError(form, path, value);
|
|
1129
|
-
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);
|
|
1130
1122
|
} else if (value && typeof value === "object") {
|
|
1131
1123
|
setFormErrors(form, value, path, footprint);
|
|
1132
1124
|
}
|
|
@@ -1138,6 +1130,10 @@
|
|
|
1138
1130
|
const stored = form.errors.get(path.key);
|
|
1139
1131
|
if (stored) footprint.set(path.key, stored);
|
|
1140
1132
|
}
|
|
1133
|
+
function landLeafError(form, path, error, footprint) {
|
|
1134
|
+
setError(form, path, error);
|
|
1135
|
+
recordFootprint(form, path, footprint);
|
|
1136
|
+
}
|
|
1141
1137
|
function applyValidateResult(form, result) {
|
|
1142
1138
|
const footprint = form.validateDeps || form.validateMode !== "onSubmit" ? getFormErrorFootprint(form) : void 0;
|
|
1143
1139
|
if (footprint) {
|
|
@@ -1155,12 +1151,7 @@
|
|
|
1155
1151
|
}
|
|
1156
1152
|
const formErrorFootprints = /* @__PURE__ */ new WeakMap();
|
|
1157
1153
|
function getFormErrorFootprint(form) {
|
|
1158
|
-
|
|
1159
|
-
if (!footprint) {
|
|
1160
|
-
footprint = /* @__PURE__ */ new Map();
|
|
1161
|
-
formErrorFootprints.set(form, footprint);
|
|
1162
|
-
}
|
|
1163
|
-
return footprint;
|
|
1154
|
+
return getOrCreate(formErrorFootprints, form, () => /* @__PURE__ */ new Map());
|
|
1164
1155
|
}
|
|
1165
1156
|
function hasFormValidateErrors(form) {
|
|
1166
1157
|
const footprint = formErrorFootprints.get(form);
|
|
@@ -1176,7 +1167,7 @@
|
|
|
1176
1167
|
if (stored !== written) continue;
|
|
1177
1168
|
form.errors.delete(key);
|
|
1178
1169
|
bumpErrorsVersion(form);
|
|
1179
|
-
emit(form.emitter, "errors", create$1(
|
|
1170
|
+
emit(form.emitter, "errors", create$1(segmentsFromKey(key)));
|
|
1180
1171
|
}
|
|
1181
1172
|
}
|
|
1182
1173
|
const FORM_VALIDATING_KEY = "__form_validate__";
|
|
@@ -1189,18 +1180,13 @@
|
|
|
1189
1180
|
const SETTLED = /* @__PURE__ */ Symbol("form-validate-settled");
|
|
1190
1181
|
const formValidateStates = /* @__PURE__ */ new WeakMap();
|
|
1191
1182
|
function getFormValidateState(form) {
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
waiters: []
|
|
1200
|
-
};
|
|
1201
|
-
formValidateStates.set(form, state);
|
|
1202
|
-
}
|
|
1203
|
-
return state;
|
|
1183
|
+
return getOrCreate(formValidateStates, form, () => ({
|
|
1184
|
+
timer: null,
|
|
1185
|
+
controller: null,
|
|
1186
|
+
round: null,
|
|
1187
|
+
marked: false,
|
|
1188
|
+
waiters: []
|
|
1189
|
+
}));
|
|
1204
1190
|
}
|
|
1205
1191
|
function runFormValidate(form) {
|
|
1206
1192
|
const validate2 = form.validate;
|
|
@@ -1238,14 +1224,9 @@
|
|
|
1238
1224
|
if (!validate2) return Promise.resolve();
|
|
1239
1225
|
state.controller?.abort();
|
|
1240
1226
|
const controller = state.controller = new AbortController();
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
validate2(getValues(form), { form, signal: controller.signal })
|
|
1245
|
-
);
|
|
1246
|
-
} catch (error) {
|
|
1247
|
-
outcome = Promise.reject(error);
|
|
1248
|
-
}
|
|
1227
|
+
const outcome = new Promise(
|
|
1228
|
+
(resolve) => resolve(validate2(getValues(form), { form, signal: controller.signal }))
|
|
1229
|
+
);
|
|
1249
1230
|
return outcome.then(
|
|
1250
1231
|
(result) => {
|
|
1251
1232
|
if (state.round === round) applyValidateResult(form, result);
|
|
@@ -1271,27 +1252,29 @@
|
|
|
1271
1252
|
else waiter.reject(outcome);
|
|
1272
1253
|
}
|
|
1273
1254
|
}
|
|
1255
|
+
function shouldKick(mode, cadence, touched, hasError, reValidateMode) {
|
|
1256
|
+
return mode === cadence || mode === "all" || mode === "onTouched" && touched || reValidateMode === cadence && hasError();
|
|
1257
|
+
}
|
|
1274
1258
|
function revalidateFormOnChange(form, path, mode) {
|
|
1275
1259
|
if (!form.validateDeps?.has(path.key) || !form.validate) return;
|
|
1276
|
-
if (
|
|
1260
|
+
if (shouldKick(
|
|
1261
|
+
mode,
|
|
1262
|
+
"onChange",
|
|
1263
|
+
hasTouchedByPath(form, path),
|
|
1264
|
+
() => hasFormValidateErrors(form),
|
|
1265
|
+
form.reValidateMode
|
|
1266
|
+
)) {
|
|
1277
1267
|
runFormValidate(form).catch(() => {
|
|
1278
1268
|
});
|
|
1279
1269
|
}
|
|
1280
1270
|
}
|
|
1281
1271
|
const fieldValidateDeps = /* @__PURE__ */ new WeakMap();
|
|
1282
1272
|
function registerFieldValidateDeps(form, key, depKeys) {
|
|
1283
|
-
|
|
1284
|
-
if (!deps) {
|
|
1285
|
-
deps = /* @__PURE__ */ new Map();
|
|
1286
|
-
fieldValidateDeps.set(form, deps);
|
|
1287
|
-
}
|
|
1273
|
+
const deps = getOrCreate(fieldValidateDeps, form, () => /* @__PURE__ */ new Map());
|
|
1288
1274
|
for (const depKey of depKeys) {
|
|
1289
|
-
|
|
1290
|
-
if (!dependents) {
|
|
1291
|
-
dependents = /* @__PURE__ */ new Set();
|
|
1292
|
-
deps.set(depKey, dependents);
|
|
1293
|
-
}
|
|
1275
|
+
const dependents = deps.get(depKey) ?? /* @__PURE__ */ new Set();
|
|
1294
1276
|
dependents.add(key);
|
|
1277
|
+
deps.set(depKey, dependents);
|
|
1295
1278
|
}
|
|
1296
1279
|
}
|
|
1297
1280
|
function unregisterFieldValidateDeps(form, key, depKeys) {
|
|
@@ -1308,7 +1291,13 @@
|
|
|
1308
1291
|
if (!dependents?.size) return;
|
|
1309
1292
|
for (const dependent of dependents) {
|
|
1310
1293
|
if (dependent === path.key) continue;
|
|
1311
|
-
if (
|
|
1294
|
+
if (shouldKick(
|
|
1295
|
+
mode,
|
|
1296
|
+
"onChange",
|
|
1297
|
+
hasTouchedByPath(form, path),
|
|
1298
|
+
() => form.errors.has(dependent),
|
|
1299
|
+
form.reValidateMode
|
|
1300
|
+
)) {
|
|
1312
1301
|
form.validators.get(dependent)?.();
|
|
1313
1302
|
}
|
|
1314
1303
|
}
|
|
@@ -1350,11 +1339,7 @@
|
|
|
1350
1339
|
}
|
|
1351
1340
|
}
|
|
1352
1341
|
function registerFieldMode(form, path, mode) {
|
|
1353
|
-
|
|
1354
|
-
if (!modes) {
|
|
1355
|
-
modes = /* @__PURE__ */ new Map();
|
|
1356
|
-
fieldModes.set(form, modes);
|
|
1357
|
-
}
|
|
1342
|
+
const modes = getOrCreate(fieldModes, form, () => /* @__PURE__ */ new Map());
|
|
1358
1343
|
const displaced = modes.has(path.key);
|
|
1359
1344
|
const token = {};
|
|
1360
1345
|
modes.set(path.key, { mode, token });
|
|
@@ -1365,14 +1350,38 @@
|
|
|
1365
1350
|
const entry = modes?.get(path.key);
|
|
1366
1351
|
if (modes && entry && entry.token === token) modes.delete(path.key);
|
|
1367
1352
|
}
|
|
1368
|
-
function
|
|
1369
|
-
|
|
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
|
+
))
|
|
1370
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
|
+
);
|
|
1371
1383
|
revalidateFormOnChange(form, path, mode);
|
|
1372
|
-
|
|
1373
|
-
runFormValidate(form).catch(() => {
|
|
1374
|
-
});
|
|
1375
|
-
}
|
|
1384
|
+
fireFormValidate(form, "onChange");
|
|
1376
1385
|
revalidateDependentsOnChange(form, path, mode);
|
|
1377
1386
|
}
|
|
1378
1387
|
function userChangeByPath(form, path, value) {
|
|
@@ -1384,13 +1393,8 @@
|
|
|
1384
1393
|
setTouchedByPath(form, path);
|
|
1385
1394
|
const entry = fieldModes.get(form)?.get(path.key);
|
|
1386
1395
|
if (!entry) return;
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
form.validators.get(path.key)?.();
|
|
1390
|
-
if (form.validateMode === "onBlur" && form.validate) {
|
|
1391
|
-
runFormValidate(form).catch(() => {
|
|
1392
|
-
});
|
|
1393
|
-
}
|
|
1396
|
+
kickFieldValidator(form, path, entry.mode ?? form.mode, "onBlur", true);
|
|
1397
|
+
fireFormValidate(form, "onBlur");
|
|
1394
1398
|
}
|
|
1395
1399
|
|
|
1396
1400
|
function removeFieldForUnmount(form, path) {
|
|
@@ -1438,50 +1442,49 @@
|
|
|
1438
1442
|
return "Invalid value";
|
|
1439
1443
|
}
|
|
1440
1444
|
}
|
|
1441
|
-
function
|
|
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) {
|
|
1442
1462
|
return (value, meta) => {
|
|
1443
1463
|
if (rules.required) {
|
|
1444
1464
|
if (value === "" || value === void 0 || value === null || Array.isArray(value) && value.length === 0) {
|
|
1445
1465
|
return [
|
|
1446
1466
|
{
|
|
1447
1467
|
type: "required",
|
|
1448
|
-
message: typeof rules.required === "string" ? rules.required : defaultMessage("required")
|
|
1468
|
+
message: typeof rules.required === "string" ? rules.required : resolveMessage(formMessages?.required) ?? defaultMessage("required")
|
|
1449
1469
|
}
|
|
1450
1470
|
];
|
|
1451
1471
|
}
|
|
1452
1472
|
}
|
|
1453
1473
|
const errors = [];
|
|
1454
|
-
const message = (type, bound) => rules.messages?.[type] ?? defaultMessage(type, bound);
|
|
1455
|
-
|
|
1456
|
-
const
|
|
1457
|
-
if (
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
if (rules.max !== void 0) {
|
|
1462
|
-
const n = Number(value);
|
|
1463
|
-
if (!Number.isNaN(n) && n > rules.max) {
|
|
1464
|
-
errors.push({ type: "max", message: message("max", rules.max) });
|
|
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) });
|
|
1465
1481
|
}
|
|
1466
1482
|
}
|
|
1467
|
-
const isSized = typeof value === "string" || Array.isArray(value);
|
|
1468
|
-
if (rules.minLength !== void 0 && isSized && value.length < rules.minLength) {
|
|
1469
|
-
errors.push({
|
|
1470
|
-
type: "minLength",
|
|
1471
|
-
message: message("minLength", rules.minLength)
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
if (rules.maxLength !== void 0 && isSized && value.length > rules.maxLength) {
|
|
1475
|
-
errors.push({
|
|
1476
|
-
type: "maxLength",
|
|
1477
|
-
message: message("maxLength", rules.maxLength)
|
|
1478
|
-
});
|
|
1479
|
-
}
|
|
1480
1483
|
if (rules.pattern && !rules.pattern.value.test(value)) {
|
|
1481
1484
|
errors.push({
|
|
1482
1485
|
type: "pattern",
|
|
1483
1486
|
// pattern.message is type-required but JS consumers may omit it.
|
|
1484
|
-
message: rules.messages?.pattern ?? rules.pattern.message ?? defaultMessage("pattern")
|
|
1487
|
+
message: rules.messages?.pattern ?? rules.pattern.message ?? resolveMessage(formMessages?.pattern) ?? defaultMessage("pattern")
|
|
1485
1488
|
});
|
|
1486
1489
|
}
|
|
1487
1490
|
if (rules.validate !== void 0) {
|
|
@@ -1502,10 +1505,9 @@
|
|
|
1502
1505
|
function rulesToConstraintAttrs(rules) {
|
|
1503
1506
|
const attrs = {};
|
|
1504
1507
|
if (rules.required) attrs.required = true;
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
if (rules.maxLength !== void 0) attrs.maxLength = rules.maxLength;
|
|
1508
|
+
for (const key of ["min", "max", "minLength", "maxLength"]) {
|
|
1509
|
+
if (rules[key] !== void 0) attrs[key] = rules[key];
|
|
1510
|
+
}
|
|
1509
1511
|
if (rules.pattern) attrs.pattern = rules.pattern.value.source;
|
|
1510
1512
|
return attrs;
|
|
1511
1513
|
}
|
|
@@ -1557,12 +1559,12 @@
|
|
|
1557
1559
|
}
|
|
1558
1560
|
modeToken = registerFieldMode(form, path, mode).token;
|
|
1559
1561
|
if (rules && hasRuleConstraints(rules)) {
|
|
1560
|
-
const
|
|
1561
|
-
const
|
|
1562
|
+
const { required, ...rest } = rules;
|
|
1563
|
+
const requiredGate = required !== void 0 ? rulesToValidator({ required }, form.messages) : void 0;
|
|
1562
1564
|
disposeValidator = registerValidatorByPath(form, path, {
|
|
1563
|
-
validate: () => hasRuleConstraints(rest) ? rulesToValidator(rest) : void 0,
|
|
1565
|
+
validate: () => hasRuleConstraints(rest) ? rulesToValidator(rest, form.messages) : void 0,
|
|
1564
1566
|
debounce: () => 0,
|
|
1565
|
-
sync: () =>
|
|
1567
|
+
sync: () => requiredGate
|
|
1566
1568
|
});
|
|
1567
1569
|
}
|
|
1568
1570
|
offFocus = on(
|
|
@@ -1742,9 +1744,7 @@
|
|
|
1742
1744
|
}
|
|
1743
1745
|
function getNativeErrors(formEl) {
|
|
1744
1746
|
const errors = [];
|
|
1745
|
-
const
|
|
1746
|
-
for (let i = 0; i < elements.length; i++) {
|
|
1747
|
-
const el = elements[i];
|
|
1747
|
+
for (const el of formEl.elements) {
|
|
1748
1748
|
if (el.name && typeof el.checkValidity === "function" && !el.checkValidity()) {
|
|
1749
1749
|
errors.push({
|
|
1750
1750
|
path: nameToPath(el.name),
|
|
@@ -1769,6 +1769,7 @@
|
|
|
1769
1769
|
e.preventDefault();
|
|
1770
1770
|
}
|
|
1771
1771
|
const formEl = e?.currentTarget;
|
|
1772
|
+
if (form.isSubmitting) return;
|
|
1772
1773
|
clearServerErrors(form);
|
|
1773
1774
|
form.isSubmitted = true;
|
|
1774
1775
|
setIsSubmitting(form, true);
|
|
@@ -1823,11 +1824,30 @@
|
|
|
1823
1824
|
else emit(form.emitter, "focusError", key);
|
|
1824
1825
|
}
|
|
1825
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
|
+
}
|
|
1826
1846
|
function create(options) {
|
|
1827
1847
|
const emitter = create$2();
|
|
1828
1848
|
_setMaxListeners(emitter, 0);
|
|
1829
|
-
|
|
1830
|
-
|
|
1849
|
+
const initialSource = options?.initialValues ?? {};
|
|
1850
|
+
const source = typeof initialSource === "function" ? initialSource() : initialSource;
|
|
1831
1851
|
const validateOption = options?.validate;
|
|
1832
1852
|
const wrappedValidate = validateOption && hasStandardProps(validateOption) ? schemaToFormValidator(
|
|
1833
1853
|
validateOption
|
|
@@ -1860,23 +1880,7 @@
|
|
|
1860
1880
|
status: void 0,
|
|
1861
1881
|
register: (name, registerOptions) => registerField(form, name, registerOptions)
|
|
1862
1882
|
};
|
|
1863
|
-
|
|
1864
|
-
form.isLoading = true;
|
|
1865
|
-
emit(emitter, "loading");
|
|
1866
|
-
Promise.resolve(source).then(
|
|
1867
|
-
(resolved) => {
|
|
1868
|
-
setInitialValues(form, resolved ?? {});
|
|
1869
|
-
form.isLoading = false;
|
|
1870
|
-
emit(emitter, "loading");
|
|
1871
|
-
},
|
|
1872
|
-
(error) => {
|
|
1873
|
-
form.isLoading = false;
|
|
1874
|
-
emit(emitter, "loading");
|
|
1875
|
-
}
|
|
1876
|
-
);
|
|
1877
|
-
} else {
|
|
1878
|
-
form.initialValues = source;
|
|
1879
|
-
}
|
|
1883
|
+
seedInitialValues(form, emitter, source);
|
|
1880
1884
|
return form;
|
|
1881
1885
|
}
|
|
1882
1886
|
|
|
@@ -1891,11 +1895,7 @@
|
|
|
1891
1895
|
const fieldDisabledRegistry = /* @__PURE__ */ new WeakMap();
|
|
1892
1896
|
function registerFieldDisabled(form, path, disabled) {
|
|
1893
1897
|
if (disabled === void 0) return null;
|
|
1894
|
-
|
|
1895
|
-
if (!registry) {
|
|
1896
|
-
registry = /* @__PURE__ */ new Map();
|
|
1897
|
-
fieldDisabledRegistry.set(form, registry);
|
|
1898
|
-
}
|
|
1898
|
+
const registry = getOrCreate(fieldDisabledRegistry, form, () => /* @__PURE__ */ new Map());
|
|
1899
1899
|
const token = {};
|
|
1900
1900
|
registry.set(path.key, { disabled, token });
|
|
1901
1901
|
emit(form.emitter, "disabled", path);
|
|
@@ -1985,6 +1985,26 @@
|
|
|
1985
1985
|
};
|
|
1986
1986
|
}
|
|
1987
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
|
+
}
|
|
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
|
+
}
|
|
1988
2008
|
function useForm(options) {
|
|
1989
2009
|
const [form] = React.useState(() => {
|
|
1990
2010
|
const created = create(options);
|
|
@@ -1995,6 +2015,7 @@
|
|
|
1995
2015
|
});
|
|
1996
2016
|
const initialValues = options && options.initialValues;
|
|
1997
2017
|
const values = options && options.values;
|
|
2018
|
+
const resetOptions = options && options.resetOptions;
|
|
1998
2019
|
const seededRef = React.useRef(null);
|
|
1999
2020
|
if (seededRef.current === null)
|
|
2000
2021
|
seededRef.current = { done: false, source: void 0 };
|
|
@@ -2003,28 +2024,15 @@
|
|
|
2003
2024
|
if (typeof initialValues === "function" || isPromise(initialValues)) {
|
|
2004
2025
|
return;
|
|
2005
2026
|
}
|
|
2006
|
-
|
|
2007
|
-
if (seeded.done && (seeded.source === initialValues || isEqual(seeded.source, initialValues))) {
|
|
2008
|
-
return;
|
|
2009
|
-
}
|
|
2010
|
-
seeded.done = true;
|
|
2011
|
-
seeded.source = initialValues;
|
|
2012
|
-
setInitialValues(form, initialValues);
|
|
2027
|
+
seedIfChanged(form, seededRef.current, initialValues);
|
|
2013
2028
|
}, [form, initialValues]);
|
|
2014
2029
|
const controlledRef = React.useRef(null);
|
|
2015
|
-
if (controlledRef.current === null)
|
|
2030
|
+
if (controlledRef.current === null)
|
|
2016
2031
|
controlledRef.current = { done: false, source: void 0 };
|
|
2017
|
-
}
|
|
2018
2032
|
React.useEffect(() => {
|
|
2019
2033
|
if (values === void 0) return;
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
return;
|
|
2023
|
-
}
|
|
2024
|
-
seeded.done = true;
|
|
2025
|
-
seeded.source = values;
|
|
2026
|
-
setInitialValues(form, values);
|
|
2027
|
-
}, [form, values]);
|
|
2034
|
+
seedIfChanged(form, controlledRef.current, values, resetOptions);
|
|
2035
|
+
}, [form, values, resetOptions]);
|
|
2028
2036
|
React.useEffect(() => {
|
|
2029
2037
|
if (!form.validateOnMount || !form.validate) return;
|
|
2030
2038
|
const run = () => {
|
|
@@ -2092,13 +2100,7 @@
|
|
|
2092
2100
|
const { key } = path;
|
|
2093
2101
|
const scope = options?.exact === false ? "branch" : "leaf";
|
|
2094
2102
|
const subscribeFactory = React.useCallback(
|
|
2095
|
-
(invalidate) => onPathEvent(
|
|
2096
|
-
emitter,
|
|
2097
|
-
"change",
|
|
2098
|
-
create$1(JSON.parse(key)),
|
|
2099
|
-
scope,
|
|
2100
|
-
invalidate
|
|
2101
|
-
),
|
|
2103
|
+
(invalidate) => onPathEvent(emitter, "change", pathFromKey(key), scope, invalidate),
|
|
2102
2104
|
[emitter, key, scope]
|
|
2103
2105
|
);
|
|
2104
2106
|
return useWatchCore(subscribeFactory, () => {
|
|
@@ -2115,15 +2117,20 @@
|
|
|
2115
2117
|
function useTouched(form, name) {
|
|
2116
2118
|
return useTouchedByPath(form, create$1(name));
|
|
2117
2119
|
}
|
|
2118
|
-
function
|
|
2120
|
+
function useKeyWatch(form, path, event, getter) {
|
|
2119
2121
|
const { emitter } = form;
|
|
2120
2122
|
const { key } = path;
|
|
2121
2123
|
const subscribeFactory = React.useCallback(
|
|
2122
|
-
(invalidate) => onKeyEvent(emitter,
|
|
2123
|
-
[emitter, key]
|
|
2124
|
+
(invalidate) => onKeyEvent(emitter, event, key, invalidate),
|
|
2125
|
+
[emitter, event, key]
|
|
2124
2126
|
);
|
|
2125
|
-
return useWatchCore(
|
|
2126
|
-
|
|
2127
|
+
return useWatchCore(subscribeFactory, getter);
|
|
2128
|
+
}
|
|
2129
|
+
function useTouchedByPath(form, path) {
|
|
2130
|
+
return useKeyWatch(
|
|
2131
|
+
form,
|
|
2132
|
+
path,
|
|
2133
|
+
"touched",
|
|
2127
2134
|
hasTouchedByPath.bind(null, form, path)
|
|
2128
2135
|
);
|
|
2129
2136
|
}
|
|
@@ -2131,26 +2138,21 @@
|
|
|
2131
2138
|
return useErrorByPath(form, create$1(name))?.message;
|
|
2132
2139
|
}
|
|
2133
2140
|
function useErrorByPath(form, path) {
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
|
|
2137
|
-
|
|
2138
|
-
|
|
2141
|
+
return useKeyWatch(
|
|
2142
|
+
form,
|
|
2143
|
+
path,
|
|
2144
|
+
"errors",
|
|
2145
|
+
getErrorByPath.bind(null, form, path)
|
|
2139
2146
|
);
|
|
2140
|
-
return useWatchCore(subscribeFactory, getErrorByPath.bind(null, form, path));
|
|
2141
2147
|
}
|
|
2142
2148
|
function useFieldErrors(form, name) {
|
|
2143
2149
|
return useFieldErrorsByPath(form, create$1(name));
|
|
2144
2150
|
}
|
|
2145
2151
|
function useFieldErrorsByPath(form, path) {
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
[emitter, key]
|
|
2151
|
-
);
|
|
2152
|
-
return useWatchCore(
|
|
2153
|
-
subscribeFactory,
|
|
2152
|
+
return useKeyWatch(
|
|
2153
|
+
form,
|
|
2154
|
+
path,
|
|
2155
|
+
"errors",
|
|
2154
2156
|
getFieldErrorsByPath.bind(null, form, path)
|
|
2155
2157
|
);
|
|
2156
2158
|
}
|
|
@@ -2164,13 +2166,7 @@
|
|
|
2164
2166
|
const { emitter } = form;
|
|
2165
2167
|
const { key } = path;
|
|
2166
2168
|
const subscribeFactory = React.useCallback(
|
|
2167
|
-
(invalidate) => onPathEvent(
|
|
2168
|
-
emitter,
|
|
2169
|
-
"change",
|
|
2170
|
-
create$1(JSON.parse(key)),
|
|
2171
|
-
"leaf",
|
|
2172
|
-
invalidate
|
|
2173
|
-
),
|
|
2169
|
+
(invalidate) => onPathEvent(emitter, "change", pathFromKey(key), "leaf", invalidate),
|
|
2174
2170
|
[emitter, key]
|
|
2175
2171
|
);
|
|
2176
2172
|
return useWatchCore(subscribeFactory, () => isFieldDirtyByPath(form, path));
|
|
@@ -2192,14 +2188,21 @@
|
|
|
2192
2188
|
"disabled",
|
|
2193
2189
|
"loading"
|
|
2194
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
|
+
}
|
|
2195
2197
|
function getFormState(form) {
|
|
2198
|
+
const anyErrors = hasErrors(form);
|
|
2196
2199
|
return {
|
|
2197
2200
|
isDirty: isDirty(form),
|
|
2198
2201
|
dirtyFields: getDirtyFields(form),
|
|
2199
2202
|
isTouched: form.touched.size > 0,
|
|
2200
2203
|
touchedFields: getTouchedFields(form),
|
|
2201
|
-
hasErrors:
|
|
2202
|
-
isValid: !
|
|
2204
|
+
hasErrors: anyErrors,
|
|
2205
|
+
isValid: !anyErrors,
|
|
2203
2206
|
errors: getErrorsRecord(form),
|
|
2204
2207
|
isSubmitting: form.isSubmitting,
|
|
2205
2208
|
isSubmitted: form.isSubmitted,
|
|
@@ -2217,28 +2220,14 @@
|
|
|
2217
2220
|
function useFormState(form) {
|
|
2218
2221
|
const getter = React.useCallback(() => getFormState(form), [form]);
|
|
2219
2222
|
const subscribeFactory = React.useCallback(
|
|
2220
|
-
(invalidate) =>
|
|
2221
|
-
const offs = FORM_STATE_EVENTS.map(
|
|
2222
|
-
(event) => on(form.emitter, event, invalidate)
|
|
2223
|
-
);
|
|
2224
|
-
return () => {
|
|
2225
|
-
for (const off of offs) off();
|
|
2226
|
-
};
|
|
2227
|
-
},
|
|
2223
|
+
(invalidate) => subscribeFormStateEvents(form.emitter, invalidate),
|
|
2228
2224
|
[form.emitter]
|
|
2229
2225
|
);
|
|
2230
2226
|
return useWatchCore(subscribeFactory, getter, isSameFormState);
|
|
2231
2227
|
}
|
|
2232
2228
|
function useStore(form, selector, isEqual2) {
|
|
2233
2229
|
const subscribeFactory = React.useCallback(
|
|
2234
|
-
(invalidate) =>
|
|
2235
|
-
const offs = FORM_STATE_EVENTS.map(
|
|
2236
|
-
(event) => on(form.emitter, event, invalidate)
|
|
2237
|
-
);
|
|
2238
|
-
return () => {
|
|
2239
|
-
for (const off of offs) off();
|
|
2240
|
-
};
|
|
2241
|
-
},
|
|
2230
|
+
(invalidate) => subscribeFormStateEvents(form.emitter, invalidate),
|
|
2242
2231
|
[form.emitter]
|
|
2243
2232
|
);
|
|
2244
2233
|
return useWatchCore(subscribeFactory, selector, isEqual2);
|
|
@@ -2302,11 +2291,6 @@
|
|
|
2302
2291
|
return useFieldErrorsByPath(form, create$1(FORM_ERROR));
|
|
2303
2292
|
}
|
|
2304
2293
|
|
|
2305
|
-
function usePath(name) {
|
|
2306
|
-
const key = React.useMemo(() => create$1(normalizePath(name)).key, [name]);
|
|
2307
|
-
return React.useMemo(() => create$1(JSON.parse(key)), [key]);
|
|
2308
|
-
}
|
|
2309
|
-
|
|
2310
2294
|
function useStage(value) {
|
|
2311
2295
|
const ref = React.useRef(value);
|
|
2312
2296
|
ref.current = value;
|
|
@@ -2336,24 +2320,34 @@
|
|
|
2336
2320
|
};
|
|
2337
2321
|
}, [removedRef, teardownRef, restoreRef]);
|
|
2338
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);
|
|
2335
|
+
}
|
|
2339
2336
|
|
|
2337
|
+
function schemaAsValidator(validate) {
|
|
2338
|
+
return validate && hasStandardProps(validate) ? schemaToFieldValidator(validate) : validate;
|
|
2339
|
+
}
|
|
2340
2340
|
function useValidate(validate, path, formProp, options) {
|
|
2341
2341
|
const contextForm = React.useContext(FormContext);
|
|
2342
2342
|
const form = formProp || contextForm;
|
|
2343
2343
|
if (!form) throw new Error("no form provided");
|
|
2344
|
-
const
|
|
2345
|
-
const
|
|
2346
|
-
|
|
2347
|
-
const
|
|
2348
|
-
|
|
2349
|
-
const syncRef = React.useRef(options?.sync);
|
|
2350
|
-
syncRef.current = options?.sync;
|
|
2351
|
-
const asyncAlwaysRef = React.useRef(options?.asyncAlways ?? false);
|
|
2352
|
-
asyncAlwaysRef.current = options?.asyncAlways ?? false;
|
|
2353
|
-
const validateOnMountRef = React.useRef(options?.validateOnMount);
|
|
2354
|
-
validateOnMountRef.current = options?.validateOnMount;
|
|
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);
|
|
2355
2349
|
React.useEffect(() => {
|
|
2356
|
-
const spath =
|
|
2350
|
+
const spath = pathFromKey(path.key);
|
|
2357
2351
|
const dispose = registerValidatorByPath(form, spath, {
|
|
2358
2352
|
validate: () => validateRef.current,
|
|
2359
2353
|
debounce: () => debounceRef.current,
|
|
@@ -2381,14 +2375,40 @@
|
|
|
2381
2375
|
disposed = true;
|
|
2382
2376
|
dispose();
|
|
2383
2377
|
};
|
|
2384
|
-
}, [
|
|
2378
|
+
}, [
|
|
2379
|
+
form,
|
|
2380
|
+
path.key,
|
|
2381
|
+
debounceRef,
|
|
2382
|
+
syncRef,
|
|
2383
|
+
asyncAlwaysRef,
|
|
2384
|
+
validateRef,
|
|
2385
|
+
validateOnMountRef
|
|
2386
|
+
]);
|
|
2385
2387
|
return useStageFn(() => form.validators.get(path.key)?.());
|
|
2386
2388
|
}
|
|
2387
2389
|
|
|
2388
2390
|
const uncontrolledSyncRegistry = /* @__PURE__ */ new WeakMap();
|
|
2389
|
-
function
|
|
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;
|
|
2408
|
+
}
|
|
2409
|
+
function combineRulesAndValidate(rules, validate, formMessages) {
|
|
2390
2410
|
if (!rules || !hasRuleConstraints(rules)) return validate;
|
|
2391
|
-
const ruleValidator = rulesToValidator(rules);
|
|
2411
|
+
const ruleValidator = rulesToValidator(rules, formMessages);
|
|
2392
2412
|
if (!validate) return ruleValidator;
|
|
2393
2413
|
return (value, meta) => {
|
|
2394
2414
|
const ruleErrors = ruleValidator(value, meta);
|
|
@@ -2409,7 +2429,7 @@
|
|
|
2409
2429
|
const timerRef = React.useRef(null);
|
|
2410
2430
|
const subscribeFactory = React.useCallback(
|
|
2411
2431
|
(invalidate) => {
|
|
2412
|
-
const spath =
|
|
2432
|
+
const spath = pathFromKey(path.key);
|
|
2413
2433
|
const clearTimer = () => {
|
|
2414
2434
|
if (timerRef.current !== null) {
|
|
2415
2435
|
clearTimeout(timerRef.current);
|
|
@@ -2511,14 +2531,18 @@
|
|
|
2511
2531
|
emitChangeByPath(form, path);
|
|
2512
2532
|
});
|
|
2513
2533
|
const restRules = rules ? { ...rules, required: void 0 } : void 0;
|
|
2514
|
-
const
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
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
|
+
);
|
|
2522
2546
|
const errors = useDelayedErrors(form, path, delayError);
|
|
2523
2547
|
const errorObject = errors[0];
|
|
2524
2548
|
const error = errorObject?.message;
|
|
@@ -2529,7 +2553,7 @@
|
|
|
2529
2553
|
} : onPathEvent(
|
|
2530
2554
|
form.emitter,
|
|
2531
2555
|
"change",
|
|
2532
|
-
|
|
2556
|
+
pathFromKey(path.key),
|
|
2533
2557
|
"leaf",
|
|
2534
2558
|
invalidate
|
|
2535
2559
|
),
|
|
@@ -2549,7 +2573,7 @@
|
|
|
2549
2573
|
(invalidate) => onPathEvent(
|
|
2550
2574
|
form.emitter,
|
|
2551
2575
|
"disabled",
|
|
2552
|
-
|
|
2576
|
+
pathFromKey(path.key),
|
|
2553
2577
|
"branch",
|
|
2554
2578
|
invalidate
|
|
2555
2579
|
),
|
|
@@ -2559,7 +2583,7 @@
|
|
|
2559
2583
|
);
|
|
2560
2584
|
const disabledTokenRef = React.useRef(null);
|
|
2561
2585
|
React.useEffect(() => {
|
|
2562
|
-
const spath =
|
|
2586
|
+
const spath = pathFromKey(path.key);
|
|
2563
2587
|
const registration = registerFieldDisabled(form, spath, disabled);
|
|
2564
2588
|
if (registration) disabledTokenRef.current = registration.token;
|
|
2565
2589
|
return () => {
|
|
@@ -2572,7 +2596,7 @@
|
|
|
2572
2596
|
const onChange = useStageFn((v) => userChangeByPath(form, path, v));
|
|
2573
2597
|
const onBlur = useStageFn(() => userBlur(form, path));
|
|
2574
2598
|
React.useEffect(() => {
|
|
2575
|
-
const spath =
|
|
2599
|
+
const spath = pathFromKey(path.key);
|
|
2576
2600
|
const { token, displaced } = registerFieldMode(form, spath, modeOption);
|
|
2577
2601
|
return () => unregisterFieldMode(form, spath, token);
|
|
2578
2602
|
}, [form, path.key, modeOption]);
|
|
@@ -2605,23 +2629,8 @@
|
|
|
2605
2629
|
[form, path.key]
|
|
2606
2630
|
);
|
|
2607
2631
|
React.useEffect(() => {
|
|
2608
|
-
const spath =
|
|
2609
|
-
|
|
2610
|
-
if (!entry) {
|
|
2611
|
-
const cells = /* @__PURE__ */ new Map();
|
|
2612
|
-
const off = on(form.emitter, "change", (changed) => {
|
|
2613
|
-
if (changed) return;
|
|
2614
|
-
for (const read of cells.values()) {
|
|
2615
|
-
const { el, path: path2 } = read();
|
|
2616
|
-
if (!el || el.type === "file") continue;
|
|
2617
|
-
const next = getValueByPath(form, path2);
|
|
2618
|
-
const asString = next == null ? "" : String(next);
|
|
2619
|
-
if (el.value !== asString) el.value = asString;
|
|
2620
|
-
}
|
|
2621
|
-
});
|
|
2622
|
-
entry = { cells, off };
|
|
2623
|
-
uncontrolledSyncRegistry.set(form, entry);
|
|
2624
|
-
}
|
|
2632
|
+
const spath = pathFromKey(path.key);
|
|
2633
|
+
const entry = getUncontrolledSyncEntry(form);
|
|
2625
2634
|
entry.cells.set(path.key, () => ({ el: elementRef.current, path: spath }));
|
|
2626
2635
|
return () => {
|
|
2627
2636
|
entry.cells.delete(path.key);
|
|
@@ -2631,27 +2640,28 @@
|
|
|
2631
2640
|
}
|
|
2632
2641
|
};
|
|
2633
2642
|
}, [form, path.key, uncontrolled]);
|
|
2634
|
-
|
|
2635
|
-
const
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
});
|
|
2639
|
-
const restoreAfterStrictMode = useStageFn(() => {
|
|
2640
|
-
const snapshot = removalSnapshotRef.current;
|
|
2641
|
-
removalSnapshotRef.current = null;
|
|
2642
|
-
if (snapshot) restoreRemovedField(form, path, snapshot);
|
|
2643
|
+
useUnmountFieldRemoval(form, path, shouldUnregister);
|
|
2644
|
+
const extract = eventToValueOrDefault(eventToValue, {
|
|
2645
|
+
valueAsNumber,
|
|
2646
|
+
valueAsDate
|
|
2643
2647
|
});
|
|
2644
|
-
useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);
|
|
2645
|
-
const extract = eventToValue ?? ((e) => extractEventValue(e, { valueAsNumber, valueAsDate }));
|
|
2646
2648
|
const inputProps = {
|
|
2647
2649
|
name: path.key,
|
|
2648
2650
|
ref: focusRef,
|
|
2649
2651
|
onChange: (e) => onChange(extract(e)),
|
|
2650
2652
|
onBlur,
|
|
2651
|
-
disabled: mergedDisabled
|
|
2652
|
-
...type === "checkbox" ? { checked: !!value } : type === "file" ? {} : uncontrolled ? { defaultValue: value } : { value: value ?? "" },
|
|
2653
|
-
...error ? { "aria-invalid": true, "aria-describedby": errorIdFromKey(path.key) } : {}
|
|
2653
|
+
disabled: mergedDisabled
|
|
2654
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
|
+
}
|
|
2655
2665
|
return {
|
|
2656
2666
|
form,
|
|
2657
2667
|
value,
|
|
@@ -2683,12 +2693,18 @@
|
|
|
2683
2693
|
return arrayIdsRegistry.get(form)?.get(key);
|
|
2684
2694
|
}
|
|
2685
2695
|
function registerArrayIds(form, key, ids) {
|
|
2686
|
-
|
|
2687
|
-
if (!registry) {
|
|
2688
|
-
registry = /* @__PURE__ */ new Map();
|
|
2689
|
-
arrayIdsRegistry.set(form, registry);
|
|
2690
|
-
}
|
|
2696
|
+
const registry = arrayIdsRegistry.get(form) ?? /* @__PURE__ */ new Map();
|
|
2691
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);
|
|
2692
2708
|
}
|
|
2693
2709
|
function bumpReducer(count) {
|
|
2694
2710
|
return count + 1;
|
|
@@ -2701,12 +2717,8 @@
|
|
|
2701
2717
|
const { rules, shouldUnregister } = options;
|
|
2702
2718
|
const path = usePath(options.name);
|
|
2703
2719
|
const idsRef = React.useRef([]);
|
|
2704
|
-
const getArray = React.useCallback(
|
|
2705
|
-
() => getValueByPath(form, path) || [],
|
|
2706
|
-
[form, path]
|
|
2707
|
-
);
|
|
2708
2720
|
const computeFields = React.useCallback(() => {
|
|
2709
|
-
const arr =
|
|
2721
|
+
const arr = getValueByPath(form, path) || [];
|
|
2710
2722
|
while (idsRef.current.length < arr.length) {
|
|
2711
2723
|
idsRef.current.push(generateId(form));
|
|
2712
2724
|
}
|
|
@@ -2718,7 +2730,7 @@
|
|
|
2718
2730
|
index,
|
|
2719
2731
|
[keyName]: id
|
|
2720
2732
|
}));
|
|
2721
|
-
}, [
|
|
2733
|
+
}, [form, path, keyName]);
|
|
2722
2734
|
const [fields, syncFields] = React.useReducer(
|
|
2723
2735
|
computeFields,
|
|
2724
2736
|
void 0,
|
|
@@ -2730,43 +2742,43 @@
|
|
|
2730
2742
|
);
|
|
2731
2743
|
registerArrayIds(form, path.key, idsRef.current);
|
|
2732
2744
|
React.useEffect(() => {
|
|
2733
|
-
|
|
2745
|
+
const ids = idsRef.current;
|
|
2746
|
+
registerArrayIds(form, path.key, ids);
|
|
2734
2747
|
return () => {
|
|
2735
2748
|
const registry = arrayIdsRegistry.get(form);
|
|
2736
|
-
if (registry?.get(path.key) ===
|
|
2749
|
+
if (registry?.get(path.key) === ids) registry.delete(path.key);
|
|
2737
2750
|
};
|
|
2738
2751
|
}, [form, path.key]);
|
|
2739
|
-
|
|
2740
|
-
const teardownOnUnmount = useStageFn(() => {
|
|
2741
|
-
if ((shouldUnregister ?? form.shouldUnregister) === false) return;
|
|
2742
|
-
removalSnapshotRef.current = removeFieldForUnmount(form, path);
|
|
2743
|
-
});
|
|
2744
|
-
const restoreAfterStrictMode = useStageFn(() => {
|
|
2745
|
-
const snapshot = removalSnapshotRef.current;
|
|
2746
|
-
removalSnapshotRef.current = null;
|
|
2747
|
-
if (snapshot) restoreRemovedField(form, path, snapshot);
|
|
2748
|
-
});
|
|
2749
|
-
useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);
|
|
2752
|
+
useUnmountFieldRemoval(form, path, shouldUnregister);
|
|
2750
2753
|
useValidate(
|
|
2751
|
-
rules ? rulesToValidator({ ...rules, required: void 0 }) : void 0,
|
|
2754
|
+
rules ? rulesToValidator({ ...rules, required: void 0 }, form.messages) : void 0,
|
|
2752
2755
|
path,
|
|
2753
2756
|
form,
|
|
2754
2757
|
{
|
|
2755
|
-
sync: rules
|
|
2758
|
+
sync: rules?.required !== void 0 ? rulesToValidator({ required: rules.required }, form.messages) : void 0
|
|
2759
|
+
}
|
|
2760
|
+
);
|
|
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);
|
|
2756
2780
|
}
|
|
2757
2781
|
);
|
|
2758
|
-
const append = useStageFn((value) => {
|
|
2759
|
-
idsRef.current.push(generateId(form));
|
|
2760
|
-
appendValueByPath(form, path, value);
|
|
2761
|
-
});
|
|
2762
|
-
const prepend = useStageFn((value) => {
|
|
2763
|
-
idsRef.current.unshift(generateId(form));
|
|
2764
|
-
prependValueByPath(form, path, value);
|
|
2765
|
-
});
|
|
2766
|
-
const insert = useStageFn((index, value) => {
|
|
2767
|
-
if (!insertValueByPath(form, path, index, value)) return;
|
|
2768
|
-
idsRef.current.splice(index, 0, generateId(form));
|
|
2769
|
-
});
|
|
2770
2782
|
const remove = useStageFn((indices) => {
|
|
2771
2783
|
const dropped = removeValueByPath(form, path, indices);
|
|
2772
2784
|
for (const index of dropped) idsRef.current.splice(index, 1);
|
|
@@ -2906,7 +2918,7 @@
|
|
|
2906
2918
|
(invalidate) => onPathEvent(
|
|
2907
2919
|
form.emitter,
|
|
2908
2920
|
"change",
|
|
2909
|
-
|
|
2921
|
+
pathFromKey(path.key),
|
|
2910
2922
|
"leaf",
|
|
2911
2923
|
invalidate
|
|
2912
2924
|
),
|
|
@@ -2916,10 +2928,8 @@
|
|
|
2916
2928
|
const value = toDisplay ? toDisplay(raw) : raw;
|
|
2917
2929
|
const timerRef = React.useRef(null);
|
|
2918
2930
|
const seqRef = React.useRef(0);
|
|
2919
|
-
const fromDisplayRef =
|
|
2920
|
-
|
|
2921
|
-
const debounceRef = React.useRef(asyncDebounceMs ?? 0);
|
|
2922
|
-
debounceRef.current = asyncDebounceMs ?? 0;
|
|
2931
|
+
const fromDisplayRef = useStage(fromDisplay);
|
|
2932
|
+
const debounceRef = useStage(asyncDebounceMs ?? 0);
|
|
2923
2933
|
React.useEffect(
|
|
2924
2934
|
() => () => {
|
|
2925
2935
|
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
@@ -2953,7 +2963,7 @@
|
|
|
2953
2963
|
run();
|
|
2954
2964
|
}
|
|
2955
2965
|
},
|
|
2956
|
-
[form, path]
|
|
2966
|
+
[form, path, fromDisplayRef, debounceRef]
|
|
2957
2967
|
);
|
|
2958
2968
|
return { value, onChange };
|
|
2959
2969
|
}
|
|
@@ -3054,6 +3064,9 @@
|
|
|
3054
3064
|
"aria-describedby": error ? [props["aria-describedby"], errorIdFromKey(fieldKey)].filter(Boolean).join(" ") : props["aria-describedby"]
|
|
3055
3065
|
};
|
|
3056
3066
|
}
|
|
3067
|
+
function toConstraintAttrs(rules) {
|
|
3068
|
+
return rules ? rulesToConstraintAttrs(rules) : void 0;
|
|
3069
|
+
}
|
|
3057
3070
|
const Field = React__namespace.forwardRef(
|
|
3058
3071
|
({
|
|
3059
3072
|
validate,
|
|
@@ -3082,8 +3095,8 @@
|
|
|
3082
3095
|
const [nativeInvalidCount, setNativeInvalidCount] = React__namespace.useState(0);
|
|
3083
3096
|
const contextForm = React__namespace.useContext(FormContext);
|
|
3084
3097
|
const resolvedForm = formProp ?? contextForm;
|
|
3085
|
-
const
|
|
3086
|
-
const validateWrapped =
|
|
3098
|
+
const isFile = props.type === "file";
|
|
3099
|
+
const validateWrapped = validate && hasStandardProps(validate) ? schemaToFieldValidator(validate) : validate;
|
|
3087
3100
|
const {
|
|
3088
3101
|
value,
|
|
3089
3102
|
onChange,
|
|
@@ -3091,7 +3104,8 @@
|
|
|
3091
3104
|
error,
|
|
3092
3105
|
name: fieldKey,
|
|
3093
3106
|
disabled: isDisabled,
|
|
3094
|
-
focusRef
|
|
3107
|
+
focusRef,
|
|
3108
|
+
validating
|
|
3095
3109
|
} = useField({
|
|
3096
3110
|
name,
|
|
3097
3111
|
form: formProp,
|
|
@@ -3104,9 +3118,8 @@
|
|
|
3104
3118
|
disabled,
|
|
3105
3119
|
asyncAlways,
|
|
3106
3120
|
mode,
|
|
3107
|
-
// File inputs
|
|
3108
|
-
|
|
3109
|
-
uncontrolled: uncontrolled || props.type === "file",
|
|
3121
|
+
// File inputs can't be value-controlled — force the uncontrolled path.
|
|
3122
|
+
uncontrolled: uncontrolled || isFile,
|
|
3110
3123
|
validate: (...params) => {
|
|
3111
3124
|
if (resolvedForm?.shouldUseNativeValidation !== false) {
|
|
3112
3125
|
const el = innerRef.current;
|
|
@@ -3129,7 +3142,6 @@
|
|
|
3129
3142
|
},
|
|
3130
3143
|
[ref, focusRef]
|
|
3131
3144
|
);
|
|
3132
|
-
const Component = as || "input";
|
|
3133
3145
|
React__namespace.useEffect(() => {
|
|
3134
3146
|
const el = innerRef.current;
|
|
3135
3147
|
if (!el || typeof el.setCustomValidity !== "function") return;
|
|
@@ -3143,11 +3155,14 @@
|
|
|
3143
3155
|
React__namespace.useEffect(() => {
|
|
3144
3156
|
if (nativeInvalidCount > 0) innerRef.current?.reportValidity();
|
|
3145
3157
|
}, [nativeInvalidCount]);
|
|
3146
|
-
const
|
|
3147
|
-
const toValue = eventToValue
|
|
3158
|
+
const Component = as || "input";
|
|
3159
|
+
const toValue = eventToValueOrDefault(eventToValue, {
|
|
3160
|
+
valueAsNumber,
|
|
3161
|
+
valueAsDate
|
|
3162
|
+
});
|
|
3148
3163
|
const valueProps = valueToProps ? valueToProps(value) : isFile ? {} : uncontrolled ? { defaultValue: value } : { value };
|
|
3149
3164
|
const errorId = errorIdFromKey(fieldKey);
|
|
3150
|
-
const constraintAttrs =
|
|
3165
|
+
const constraintAttrs = toConstraintAttrs(rules);
|
|
3151
3166
|
return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement(
|
|
3152
3167
|
Component,
|
|
3153
3168
|
{
|
|
@@ -3159,6 +3174,7 @@
|
|
|
3159
3174
|
...valueProps,
|
|
3160
3175
|
...ariaProps(error, fieldKey, props),
|
|
3161
3176
|
disabled: isDisabled,
|
|
3177
|
+
"aria-busy": validating || void 0,
|
|
3162
3178
|
onChange: (e) => onChange(toValue(e)),
|
|
3163
3179
|
ref: mergedRef
|
|
3164
3180
|
}
|
|
@@ -3187,7 +3203,8 @@
|
|
|
3187
3203
|
onBlur,
|
|
3188
3204
|
error,
|
|
3189
3205
|
name: fieldKey,
|
|
3190
|
-
disabled: isDisabled
|
|
3206
|
+
disabled: isDisabled,
|
|
3207
|
+
validating
|
|
3191
3208
|
} = useField({
|
|
3192
3209
|
name,
|
|
3193
3210
|
form,
|
|
@@ -3202,7 +3219,7 @@
|
|
|
3202
3219
|
disabled,
|
|
3203
3220
|
mode
|
|
3204
3221
|
});
|
|
3205
|
-
const constraintAttrs =
|
|
3222
|
+
const constraintAttrs = toConstraintAttrs(rules);
|
|
3206
3223
|
return /* @__PURE__ */ React__namespace.createElement(
|
|
3207
3224
|
"input",
|
|
3208
3225
|
{
|
|
@@ -3214,6 +3231,7 @@
|
|
|
3214
3231
|
checked: !!value,
|
|
3215
3232
|
...ariaProps(error, fieldKey, props),
|
|
3216
3233
|
disabled: isDisabled,
|
|
3234
|
+
"aria-busy": validating || void 0,
|
|
3217
3235
|
onChange: (e) => onChange(e.target.checked),
|
|
3218
3236
|
ref
|
|
3219
3237
|
}
|
|
@@ -3248,7 +3266,8 @@
|
|
|
3248
3266
|
onBlur,
|
|
3249
3267
|
error,
|
|
3250
3268
|
name: fieldKey,
|
|
3251
|
-
disabled: isDisabled
|
|
3269
|
+
disabled: isDisabled,
|
|
3270
|
+
validating
|
|
3252
3271
|
} = useField({
|
|
3253
3272
|
name,
|
|
3254
3273
|
form,
|
|
@@ -3263,7 +3282,7 @@
|
|
|
3263
3282
|
disabled,
|
|
3264
3283
|
mode
|
|
3265
3284
|
});
|
|
3266
|
-
const constraintAttrs =
|
|
3285
|
+
const constraintAttrs = toConstraintAttrs(rules);
|
|
3267
3286
|
return /* @__PURE__ */ React__namespace.createElement(
|
|
3268
3287
|
"select",
|
|
3269
3288
|
{
|
|
@@ -3275,6 +3294,7 @@
|
|
|
3275
3294
|
value: toSelectValue(multiple, value),
|
|
3276
3295
|
...ariaProps(error, fieldKey, props),
|
|
3277
3296
|
disabled: isDisabled,
|
|
3297
|
+
"aria-busy": validating || void 0,
|
|
3278
3298
|
onChange: (e) => onChange(
|
|
3279
3299
|
multiple ? Array.from(e.target.selectedOptions, (option) => option.value) : e.target.value
|
|
3280
3300
|
),
|
|
@@ -3285,9 +3305,74 @@
|
|
|
3285
3305
|
}
|
|
3286
3306
|
);
|
|
3287
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
|
+
|
|
3288
3372
|
exports.Checkbox = Checkbox;
|
|
3289
3373
|
exports.CheckboxGroupContext = CheckboxGroupContext;
|
|
3290
3374
|
exports.CheckboxGroupProvider = CheckboxGroupProvider;
|
|
3375
|
+
exports.ErrorSummary = ErrorSummary;
|
|
3291
3376
|
exports.FORM_ERROR = FORM_ERROR;
|
|
3292
3377
|
exports.Field = Field;
|
|
3293
3378
|
exports.Form = Form;
|
|
@@ -3309,6 +3394,7 @@
|
|
|
3309
3394
|
exports.ensureValidate = ensureValidate;
|
|
3310
3395
|
exports.fieldErrorId = fieldErrorId;
|
|
3311
3396
|
exports.fieldPathToDottedKey = fieldPathToDottedKey;
|
|
3397
|
+
exports.firstMountedDescendantKey = firstMountedDescendantKey;
|
|
3312
3398
|
exports.getDirtyFields = getDirtyFields;
|
|
3313
3399
|
exports.getError = getError;
|
|
3314
3400
|
exports.getErrorByPath = getErrorByPath;
|
|
@@ -3367,6 +3453,7 @@
|
|
|
3367
3453
|
exports.setValidatingByPath = setValidatingByPath;
|
|
3368
3454
|
exports.setValue = setValue;
|
|
3369
3455
|
exports.setValueByPath = setValueByPath;
|
|
3456
|
+
exports.shouldKick = shouldKick;
|
|
3370
3457
|
exports.subscribe = subscribe;
|
|
3371
3458
|
exports.swapValues = swapValues;
|
|
3372
3459
|
exports.swapValuesByPath = swapValuesByPath;
|