react-f0rm 1.2.0 → 1.4.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.
Files changed (98) hide show
  1. package/README.md +90 -1062
  2. package/devtools.d.ts +1 -0
  3. package/devtools.js +1 -0
  4. package/dist/array-3hAjl6Bz.d.ts +160 -0
  5. package/dist/devtools/index.cjs.js +1 -1
  6. package/dist/devtools/index.cjs.js.map +1 -1
  7. package/dist/devtools/index.d.cts +34 -0
  8. package/dist/devtools/index.d.mts +34 -0
  9. package/dist/devtools/index.d.ts +3 -2
  10. package/dist/devtools/index.mjs +1 -1
  11. package/dist/devtools/index.mjs.map +1 -1
  12. package/dist/errors-8oPux7GR.cjs.js +2 -0
  13. package/dist/errors-8oPux7GR.cjs.js.map +1 -0
  14. package/dist/errors-ClH3eV1R.mjs +2 -0
  15. package/dist/errors-ClH3eV1R.mjs.map +1 -0
  16. package/dist/index.cjs.js +1 -1
  17. package/dist/index.cjs.js.map +1 -1
  18. package/dist/index.d.cts +1833 -0
  19. package/dist/index.d.mts +1833 -0
  20. package/dist/index.d.ts +678 -128
  21. package/dist/index.mjs +1 -1
  22. package/dist/index.mjs.map +1 -1
  23. package/dist/index.umd.js +1210 -480
  24. package/dist/index.umd.js.map +1 -1
  25. package/dist/index.umd.min.js +2 -2
  26. package/dist/index.umd.min.js.map +1 -1
  27. package/dist/persist.cjs.js +1 -1
  28. package/dist/persist.cjs.js.map +1 -1
  29. package/dist/persist.d.cts +49 -0
  30. package/dist/persist.d.mts +49 -0
  31. package/dist/persist.mjs +1 -1
  32. package/dist/persist.mjs.map +1 -1
  33. package/dist/resolvers/standard-schema.cjs.js +1 -1
  34. package/dist/resolvers/standard-schema.cjs.js.map +1 -1
  35. package/dist/resolvers/standard-schema.d.cts +2 -0
  36. package/dist/resolvers/standard-schema.d.mts +2 -0
  37. package/dist/resolvers/standard-schema.d.ts +1 -67
  38. package/dist/resolvers/standard-schema.mjs +1 -1
  39. package/dist/resolvers/standard-schema.mjs.map +1 -1
  40. package/dist/resolvers/yup.cjs.js +1 -1
  41. package/dist/resolvers/yup.cjs.js.map +1 -1
  42. package/dist/resolvers/yup.d.cts +6 -0
  43. package/dist/resolvers/yup.d.mts +6 -0
  44. package/dist/resolvers/yup.d.ts +0 -1
  45. package/dist/resolvers/yup.mjs +1 -1
  46. package/dist/resolvers/yup.mjs.map +1 -1
  47. package/dist/resolvers/zod.cjs.js +1 -1
  48. package/dist/resolvers/zod.cjs.js.map +1 -1
  49. package/dist/resolvers/zod.d.cts +6 -0
  50. package/dist/resolvers/zod.d.mts +6 -0
  51. package/dist/resolvers/zod.d.ts +0 -1
  52. package/dist/resolvers/zod.mjs +1 -1
  53. package/dist/resolvers/zod.mjs.map +1 -1
  54. package/dist/server/index.cjs.js +1 -1
  55. package/dist/server/index.cjs.js.map +1 -1
  56. package/dist/server/index.d.cts +106 -0
  57. package/dist/server/index.d.mts +106 -0
  58. package/dist/server/index.d.ts +31 -2
  59. package/dist/server/index.mjs +1 -1
  60. package/dist/server/index.mjs.map +1 -1
  61. package/dist/standard-schema-CYbnugL7.d.ts +1184 -0
  62. package/dist/standardSchema-BpZvg0tZ.mjs +2 -0
  63. package/dist/standardSchema-BpZvg0tZ.mjs.map +1 -0
  64. package/dist/standardSchema-CxV_DhBO.cjs.js +2 -0
  65. package/dist/standardSchema-CxV_DhBO.cjs.js.map +1 -0
  66. package/dist/validate-BEjNsNvd.mjs +2 -0
  67. package/dist/validate-BEjNsNvd.mjs.map +1 -0
  68. package/dist/validate-BvN6hiEG.cjs.js +2 -0
  69. package/dist/validate-BvN6hiEG.cjs.js.map +1 -0
  70. package/dist/values-Bod74Kzu.mjs +2 -0
  71. package/dist/values-Bod74Kzu.mjs.map +1 -0
  72. package/dist/values-DKpOCD5J.cjs.js +2 -0
  73. package/dist/values-DKpOCD5J.cjs.js.map +1 -0
  74. package/package.json +90 -34
  75. package/persist.d.ts +1 -0
  76. package/persist.js +1 -0
  77. package/resolvers/standard-schema.d.ts +1 -0
  78. package/resolvers/standard-schema.js +1 -0
  79. package/resolvers/yup.d.ts +1 -0
  80. package/resolvers/yup.js +1 -0
  81. package/resolvers/zod.d.ts +1 -0
  82. package/resolvers/zod.js +1 -0
  83. package/server.d.ts +1 -0
  84. package/server.js +1 -0
  85. package/dist/errors-CxSjrWJO.cjs.js +0 -2
  86. package/dist/errors-CxSjrWJO.cjs.js.map +0 -1
  87. package/dist/errors-CzWtwjO0.mjs +0 -2
  88. package/dist/errors-CzWtwjO0.mjs.map +0 -1
  89. package/dist/form-CvmWHUrd.d.ts +0 -423
  90. package/dist/validate-B1Gdjeaq.mjs +0 -2
  91. package/dist/validate-B1Gdjeaq.mjs.map +0 -1
  92. package/dist/validate-CUmNZqg6.d.ts +0 -238
  93. package/dist/validate-DAfz8Nbb.cjs.js +0 -2
  94. package/dist/validate-DAfz8Nbb.cjs.js.map +0 -1
  95. package/dist/values-B1IV-6V4.mjs +0 -2
  96. package/dist/values-B1IV-6V4.mjs.map +0 -1
  97. package/dist/values-CDNAYEOB.cjs.js +0 -2
  98. package/dist/values-CDNAYEOB.cjs.js.map +0 -1
package/dist/index.umd.js CHANGED
@@ -309,6 +309,15 @@
309
309
  function isPromise(value) {
310
310
  return value && typeof value.then === "function";
311
311
  }
312
+ function extractEventValue(e, options) {
313
+ const target = e?.target;
314
+ if (!target) return e;
315
+ if (target.type === "file") return target.files;
316
+ if (target.type === "checkbox") return target.checked;
317
+ if (options?.valueAsNumber) return target.valueAsNumber;
318
+ if (options?.valueAsDate) return target.valueAsDate;
319
+ return target.value;
320
+ }
312
321
  function isEqual(a, b) {
313
322
  if (Object.is(a, b)) return true;
314
323
  if (a instanceof Date && b instanceof Date)
@@ -361,6 +370,11 @@
361
370
  const cache = valuesCaches.get(form);
362
371
  if (cache) cache.version++;
363
372
  }
373
+ const errorsCaches = /* @__PURE__ */ new WeakMap();
374
+ function bumpErrorsVersion(form) {
375
+ const cache = errorsCaches.get(form);
376
+ if (cache) cache.version++;
377
+ }
364
378
  const dirtyBaselines = /* @__PURE__ */ new WeakMap();
365
379
  function getDirtyBaseline(form, key, segments) {
366
380
  const baselines = dirtyBaselines.get(form);
@@ -430,17 +444,64 @@
430
444
  }
431
445
  return entries;
432
446
  }
447
+ function computeErrorsViews(form) {
448
+ const cached = errorsCaches.get(form);
449
+ if (cached && cached.version === 0) return;
450
+ const result = {};
451
+ const tree = {};
452
+ for (const [key, list] of form.errors) {
453
+ const segments = JSON.parse(key);
454
+ result[segments.join(".")] = list;
455
+ let node = tree;
456
+ for (let i = 0; i < segments.length - 1; i++) {
457
+ const segment = segments[i];
458
+ const slot = node[segment];
459
+ const container = slot && !(Array.isArray(slot) && slot.length > 0 && isFieldError(slot[0])) ? slot : typeof segments[i + 1] === "number" ? [] : {};
460
+ node[segment] = container;
461
+ node = container;
462
+ }
463
+ node[segments[segments.length - 1]] = list;
464
+ }
465
+ if (cached) {
466
+ cached.result = result;
467
+ cached.tree = tree;
468
+ cached.version = 0;
469
+ } else {
470
+ errorsCaches.set(form, { version: 0, result, tree });
471
+ }
472
+ }
473
+ function getErrorsRecord(form) {
474
+ computeErrorsViews(form);
475
+ return errorsCaches.get(form).result;
476
+ }
477
+ function getErrorsTree(form) {
478
+ computeErrorsViews(form);
479
+ return errorsCaches.get(form).tree;
480
+ }
481
+ function fieldPathToDottedKey(name) {
482
+ return create$1(name).value.join(".");
483
+ }
484
+ function dottedKeyToFieldPath(key) {
485
+ const segments = key.split(".");
486
+ const numeric = (segment) => /^(0|[1-9]\d*)$/.test(segment);
487
+ return segments.map(
488
+ (segment, i) => i > 0 && numeric(segment) ? `[${segment}]` : `${i > 0 ? "." : ""}${segment}`
489
+ ).join("");
490
+ }
433
491
  function getFirstError({ errors }) {
434
492
  return errors.values().next().value?.[0]?.message;
435
493
  }
436
- function setError(form, name, error) {
437
- setErrorByPath(form, create$1(name), error);
494
+ function setError(form, name, error, options) {
495
+ setErrorByPath(form, create$1(name), error, options);
438
496
  }
439
- function setErrorByPath({ emitter, errors }, path, error) {
497
+ function setErrorByPath(form, path, error, options) {
498
+ const { emitter, errors } = form;
440
499
  const list = normalizeErrors(error);
441
500
  if (list) errors.set(path.key, list);
442
501
  else errors.delete(path.key);
502
+ bumpErrorsVersion(form);
443
503
  emit(emitter, "errors", path);
504
+ if (options?.shouldFocus) emit(emitter, "focusError", path.key);
444
505
  }
445
506
  function normalizeErrors(error) {
446
507
  if (typeof error === "string") {
@@ -462,11 +523,13 @@
462
523
  const { emitter, errors } = form;
463
524
  if (name === void 0) {
464
525
  errors.clear();
526
+ bumpErrorsVersion(form);
465
527
  emit(emitter, "errors");
466
528
  return;
467
529
  }
468
530
  const paths = typeof name === "string" || isSegmentsPath(name) ? [create$1(name)] : name.map((one) => create$1(one));
469
531
  for (const { key } of paths) errors.delete(key);
532
+ bumpErrorsVersion(form);
470
533
  for (const path of paths) emit(emitter, "errors", path);
471
534
  }
472
535
  function setServerErrors(form, errors, options) {
@@ -482,10 +545,151 @@
482
545
  );
483
546
  }
484
547
  }
548
+ function clearServerErrors(form) {
549
+ let changed = false;
550
+ for (const [key, errors] of form.errors) {
551
+ const kept = errors.filter((error) => error.type !== "server");
552
+ if (kept.length === 0) {
553
+ form.errors.delete(key);
554
+ changed = true;
555
+ } else if (kept.length !== errors.length) {
556
+ form.errors.set(key, kept);
557
+ changed = true;
558
+ }
559
+ }
560
+ if (changed) {
561
+ bumpErrorsVersion(form);
562
+ emit(form.emitter, "errors");
563
+ }
564
+ }
485
565
  function hasErrors({ errors }) {
486
566
  return errors.size > 0;
487
567
  }
488
568
 
569
+ function hasStandardProps(schema) {
570
+ return !!schema && typeof schema === "object" && typeof schema["~standard"]?.validate === "function";
571
+ }
572
+ function toFieldError(issue) {
573
+ return { type: "standard", message: issue?.message || "Validation failed" };
574
+ }
575
+ function schemaToFieldValidator(schema) {
576
+ return async (value) => {
577
+ const result = await schema["~standard"].validate(value);
578
+ if (!result.issues?.length) return void 0;
579
+ return result.issues.map(toFieldError);
580
+ };
581
+ }
582
+ function schemaToFormValidator(schema) {
583
+ return async (values) => {
584
+ const result = await schema["~standard"].validate(values);
585
+ const { issues } = result;
586
+ if (!issues?.length) {
587
+ return {
588
+ [VALIDATION_OUTCOME]: true,
589
+ values: "value" in result ? result.value : void 0
590
+ };
591
+ }
592
+ const errors = {};
593
+ for (const issue of issues) {
594
+ const segments = toPathSegments(issue);
595
+ if (segments.length) {
596
+ assignAtPath(errors, segments, toFieldError(issue));
597
+ } else {
598
+ const slot = errors[FORM_ERROR] ??= [];
599
+ if (Array.isArray(slot)) slot.push(toFieldError(issue));
600
+ }
601
+ }
602
+ return { [VALIDATION_OUTCOME]: true, errors: pruneEmpty(errors) || {} };
603
+ };
604
+ }
605
+ function toPathSegments(issue) {
606
+ const path = issue.path || [];
607
+ const segments = [];
608
+ for (const segment of path) {
609
+ const key = typeof segment === "object" && segment !== null ? segment.key : segment;
610
+ segments.push(String(key));
611
+ }
612
+ return segments;
613
+ }
614
+ function assignAtPath(root, segments, error) {
615
+ let node = root;
616
+ for (let i = 0; i < segments.length - 1; i++) {
617
+ const segment = segments[i];
618
+ let next = node[segment];
619
+ if (next === void 0) {
620
+ next = node[segment] = {};
621
+ }
622
+ if (!isBranch(next)) return;
623
+ node = next;
624
+ }
625
+ const leaf = segments[segments.length - 1];
626
+ const slot = node[leaf];
627
+ if (slot === void 0) node[leaf] = [error];
628
+ else if (Array.isArray(slot)) slot.push(error);
629
+ }
630
+ function isBranch(value) {
631
+ return !!value && typeof value === "object" && !Array.isArray(value);
632
+ }
633
+ function pruneEmpty(node) {
634
+ let hasLeaf = false;
635
+ const result = {};
636
+ Object.entries(node).forEach(([key, value]) => {
637
+ if (isBranch(value)) {
638
+ const pruned = pruneEmpty(value);
639
+ if (pruned) {
640
+ result[key] = pruned;
641
+ hasLeaf = true;
642
+ }
643
+ } else {
644
+ result[key] = value;
645
+ hasLeaf = true;
646
+ }
647
+ });
648
+ return hasLeaf ? result : void 0;
649
+ }
650
+
651
+ function isFieldDirtyByPath(form, path) {
652
+ const live = form.values.get(path.key);
653
+ return form.values.has(path.key) && getDirtyBaseline(form, path.key, path.value) !== live;
654
+ }
655
+ function isDirty(form) {
656
+ let dirty = false;
657
+ forEachDirtyField(form, () => {
658
+ dirty = true;
659
+ });
660
+ return dirty;
661
+ }
662
+ function forEachDirtyField(form, fn) {
663
+ for (const [key, value] of form.values) {
664
+ const path = JSON.parse(key);
665
+ if (getDirtyBaseline(form, key, path) !== value) fn(path.join("."));
666
+ }
667
+ }
668
+ function computeDirtyFields(form) {
669
+ const dirtyFields = {};
670
+ forEachDirtyField(form, (key) => {
671
+ dirtyFields[key] = true;
672
+ });
673
+ return dirtyFields;
674
+ }
675
+ function sameDirtyKeys(a, b) {
676
+ const aKeys = Object.keys(a);
677
+ if (aKeys.length !== Object.keys(b).length) return false;
678
+ return aKeys.every((key) => b[key] === true);
679
+ }
680
+ function getDirtyFields(form) {
681
+ let cache = dirtyFieldsCaches.get(form);
682
+ if (!cache) {
683
+ cache = { version: 0, result: computeDirtyFields(form) };
684
+ dirtyFieldsCaches.set(form, cache);
685
+ } else if (cache.version > 0) {
686
+ const result = computeDirtyFields(form);
687
+ if (!sameDirtyKeys(cache.result, result)) cache.result = result;
688
+ cache.version = 0;
689
+ }
690
+ return cache.result;
691
+ }
692
+
489
693
  function setTouched(form, name) {
490
694
  setTouchedByPath(form, create$1(name));
491
695
  }
@@ -553,11 +757,12 @@
553
757
  }
554
758
  function setValueByPath(form, path, value, options) {
555
759
  const { emitter, values, deleted } = form;
556
- values.set(path.key, value);
760
+ const next = typeof value === "function" ? value(getValueByPath(form, path)) : value;
761
+ values.set(path.key, next);
557
762
  pruneDescendantKeys(values, path);
558
763
  reviveBranch(deleted, path);
559
764
  pruneDirtyBaselines(form, path);
560
- if (options?.shouldDirty === false) setDirtyBaseline(form, path, value);
765
+ if (options?.shouldDirty === false) setDirtyBaseline(form, path, next);
561
766
  bumpDirtyVersion(form);
562
767
  bumpValuesVersion(form);
563
768
  if (options?.shouldTouch) setTouchedByPath(form, path);
@@ -578,15 +783,14 @@
578
783
  }
579
784
  function getFieldState(form, name) {
580
785
  const path = create$1(name);
581
- const { values, touched, validating } = form;
582
- const live = values.get(path.key);
786
+ const { touched, validating } = form;
583
787
  return {
584
788
  value: getValueByPath(form, path),
585
789
  error: getErrorByPath(form, path),
586
790
  errors: getFieldErrorsByPath(form, path),
587
- // Same rule as getDirtyFields, committed baselines included: the field
791
+ // The shared per-field rule (committed baselines included): the field
588
792
  // is dirty while its live value differs from its effective baseline.
589
- isDirty: values.has(path.key) && getDirtyBaseline(form, path.key, path.value) !== live,
793
+ isDirty: isFieldDirtyByPath(form, path),
590
794
  isTouched: touched.has(path.key),
591
795
  isValidating: validating.has(path.key)
592
796
  };
@@ -603,7 +807,7 @@
603
807
  if (!hasLiveBranch(values, segments)) deleted.add(key);
604
808
  }
605
809
  if (!options?.keepTouched) touched.delete(key);
606
- if (!options?.keepError) errors.delete(key);
810
+ if (!options?.keepError && errors.delete(key)) bumpErrorsVersion(form);
607
811
  validating.delete(key);
608
812
  bumpDirtyVersion(form);
609
813
  bumpValuesVersion(form);
@@ -691,7 +895,8 @@
691
895
  validating.clear();
692
896
  if (!options?.keepIsSubmitting) form.isSubmitting = false;
693
897
  if (!options?.keepSubmitCount) form.submitCount = 0;
694
- if (!options?.keepIsSubmitted) form.isSubmitSuccessful = void 0;
898
+ if (!options?.keepIsSubmitted) form.isSubmitted = false;
899
+ if (!options?.keepIsSubmitSuccessful) form.isSubmitSuccessful = void 0;
695
900
  bumpDirtyVersion(form);
696
901
  bumpValuesVersion(form);
697
902
  for (const { segments, value } of keptValues) {
@@ -724,50 +929,13 @@
724
929
  emit(emitter, "touched", path);
725
930
  }
726
931
  if (!options?.keepErrors && errors.delete(path.key)) {
932
+ bumpErrorsVersion(form);
727
933
  emit(emitter, "errors", path);
728
934
  }
729
935
  bumpDirtyVersion(form);
730
936
  bumpValuesVersion(form);
731
937
  }
732
938
 
733
- function isDirty(form) {
734
- let dirty = false;
735
- forEachDirtyField(form, () => {
736
- dirty = true;
737
- });
738
- return dirty;
739
- }
740
- function forEachDirtyField(form, fn) {
741
- for (const [key, value] of form.values) {
742
- const path = JSON.parse(key);
743
- if (getDirtyBaseline(form, key, path) !== value) fn(path.join("."));
744
- }
745
- }
746
- function computeDirtyFields(form) {
747
- const dirtyFields = {};
748
- forEachDirtyField(form, (key) => {
749
- dirtyFields[key] = true;
750
- });
751
- return dirtyFields;
752
- }
753
- function sameDirtyKeys(a, b) {
754
- const aKeys = Object.keys(a);
755
- if (aKeys.length !== Object.keys(b).length) return false;
756
- return aKeys.every((key) => b[key] === true);
757
- }
758
- function getDirtyFields(form) {
759
- let cache = dirtyFieldsCaches.get(form);
760
- if (!cache) {
761
- cache = { version: 0, result: computeDirtyFields(form) };
762
- dirtyFieldsCaches.set(form, cache);
763
- } else if (cache.version > 0) {
764
- const result = computeDirtyFields(form);
765
- if (!sameDirtyKeys(cache.result, result)) cache.result = result;
766
- cache.version = 0;
767
- }
768
- return cache.result;
769
- }
770
-
771
939
  function unsetValidatingByPath({ emitter, validating }, path) {
772
940
  validating.delete(path.key);
773
941
  emit(emitter, "validating", path);
@@ -808,6 +976,25 @@
808
976
  errorSource = "sync";
809
977
  return true;
810
978
  };
979
+ const collectSyncErrors = () => {
980
+ const sync = registration.sync();
981
+ if (!sync) return null;
982
+ const errors = sync(getValueByPath(form, path), { form, path });
983
+ if (errors === void 0) return null;
984
+ const list = Array.isArray(errors) ? errors : [errors];
985
+ return list.length ? list : null;
986
+ };
987
+ const land = (result) => {
988
+ if (registration.asyncAlways?.()) {
989
+ const gate = collectSyncErrors();
990
+ const own = result === void 0 ? [] : Array.isArray(result) ? result : [result];
991
+ setErrorByPath(form, path, [...gate ?? [], ...own]);
992
+ errorSource = hasErrors2(result) ? "validator" : gate ? "sync" : null;
993
+ } else {
994
+ setErrorByPath(form, path, result);
995
+ errorSource = hasErrors2(result) ? "validator" : null;
996
+ }
997
+ };
811
998
  const supersede = () => {
812
999
  if (timer !== null) {
813
1000
  clearTimeout(timer);
@@ -837,8 +1024,7 @@
837
1024
  throw e;
838
1025
  }
839
1026
  if (!isPromise(result)) {
840
- setErrorByPath(form, path, result);
841
- errorSource = hasErrors2(result) ? "validator" : null;
1027
+ land(result);
842
1028
  unmark();
843
1029
  return;
844
1030
  }
@@ -846,8 +1032,7 @@
846
1032
  result.then(
847
1033
  (error) => {
848
1034
  if (lock === round) {
849
- setErrorByPath(form, path, error);
850
- errorSource = hasErrors2(error) ? "validator" : null;
1035
+ land(error);
851
1036
  }
852
1037
  }
853
1038
  ).catch(() => {
@@ -860,7 +1045,7 @@
860
1045
  };
861
1046
  const run = () => {
862
1047
  timer = null;
863
- if (runSync()) {
1048
+ if (runSync() && !registration.asyncAlways?.()) {
864
1049
  supersede();
865
1050
  unmark();
866
1051
  return;
@@ -868,7 +1053,7 @@
868
1053
  runValidator();
869
1054
  };
870
1055
  const kick = () => {
871
- if (runSync()) {
1056
+ if (runSync() && !registration.asyncAlways?.()) {
872
1057
  supersede();
873
1058
  unmark();
874
1059
  return;
@@ -954,7 +1139,7 @@
954
1139
  if (stored) footprint.set(path.key, stored);
955
1140
  }
956
1141
  function applyValidateResult(form, result) {
957
- const footprint = form.validateDeps ? getFormErrorFootprint(form) : void 0;
1142
+ const footprint = form.validateDeps || form.validateMode !== "onSubmit" ? getFormErrorFootprint(form) : void 0;
958
1143
  if (footprint) {
959
1144
  clearFormValidateErrors(form, footprint);
960
1145
  footprint.clear();
@@ -990,6 +1175,7 @@
990
1175
  const stored = form.errors.get(key);
991
1176
  if (stored !== written) continue;
992
1177
  form.errors.delete(key);
1178
+ bumpErrorsVersion(form);
993
1179
  emit(form.emitter, "errors", create$1(JSON.parse(key)));
994
1180
  }
995
1181
  }
@@ -1183,6 +1369,10 @@
1183
1369
  if (mode === "onChange" || mode === "all" || mode === "onTouched" && hasTouchedByPath(form, path) || getFieldErrorsByPath(form, path).length > 0 && form.reValidateMode === "onChange")
1184
1370
  form.validators.get(path.key)?.();
1185
1371
  revalidateFormOnChange(form, path, mode);
1372
+ if (form.validateMode === "onChange" && form.validate) {
1373
+ runFormValidate(form).catch(() => {
1374
+ });
1375
+ }
1186
1376
  revalidateDependentsOnChange(form, path, mode);
1187
1377
  }
1188
1378
  function userChangeByPath(form, path, value) {
@@ -1197,71 +1387,399 @@
1197
1387
  const mode = entry.mode ?? form.mode;
1198
1388
  if (mode === "onBlur" || mode === "onTouched" || mode === "all" || getFieldErrorsByPath(form, path).length > 0 && form.reValidateMode === "onBlur")
1199
1389
  form.validators.get(path.key)?.();
1390
+ if (form.validateMode === "onBlur" && form.validate) {
1391
+ runFormValidate(form).catch(() => {
1392
+ });
1393
+ }
1200
1394
  }
1201
1395
 
1202
- function setIsSubmitting(form, value) {
1203
- form.isSubmitting = value;
1204
- emit(form.emitter, "submitting");
1205
- }
1206
- function incrementSubmitCount(form) {
1207
- form.submitCount++;
1208
- emit(form.emitter, "submitCount");
1396
+ function removeFieldForUnmount(form, path) {
1397
+ const { key } = path;
1398
+ const snapshot = {
1399
+ present: form.values.has(key),
1400
+ value: form.values.get(key),
1401
+ touched: form.touched.has(key),
1402
+ errors: form.errors.get(key)
1403
+ };
1404
+ removeFieldByPath(form, path);
1405
+ return snapshot;
1209
1406
  }
1210
- function setSubmitSuccessful(form, value) {
1211
- form.isSubmitSuccessful = value;
1212
- emit(form.emitter, "submitSuccessful");
1407
+ function restoreRemovedField(form, path, snapshot) {
1408
+ const { key } = path;
1409
+ if (snapshot.present) {
1410
+ setValueByPath(form, path, snapshot.value, { shouldDirty: false });
1411
+ } else {
1412
+ form.deleted.delete(key);
1413
+ bumpValuesVersion(form);
1414
+ emit(form.emitter, "change", path);
1415
+ }
1416
+ if (snapshot.touched) setTouchedByPath(form, path);
1417
+ if (snapshot.errors) setErrorByPath(form, path, snapshot.errors);
1213
1418
  }
1214
- function setDisabled(form, value) {
1215
- form.disabled = value;
1216
- emit(form.emitter, "disabled");
1419
+
1420
+ function hasRuleConstraints(rules) {
1421
+ 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;
1217
1422
  }
1218
- function nameToPath(name) {
1219
- if (name.startsWith("[")) {
1220
- try {
1221
- const segments = JSON.parse(name);
1222
- if (Array.isArray(segments)) return segments.join(".");
1223
- } catch {
1224
- }
1423
+ function defaultMessage(type, bound) {
1424
+ switch (type) {
1425
+ case "required":
1426
+ return "This field is required";
1427
+ case "min":
1428
+ return `Must be at least ${bound}`;
1429
+ case "max":
1430
+ return `Must be at most ${bound}`;
1431
+ case "minLength":
1432
+ return `Must be at least ${bound} characters`;
1433
+ case "maxLength":
1434
+ return `Must be at most ${bound} characters`;
1435
+ case "pattern":
1436
+ return "Invalid format";
1437
+ default:
1438
+ return "Invalid value";
1225
1439
  }
1226
- return name;
1227
1440
  }
1228
- function getNativeErrors(formEl) {
1229
- const errors = [];
1230
- const { elements } = formEl;
1231
- for (let i = 0; i < elements.length; i++) {
1232
- const el = elements[i];
1233
- if (el.name && typeof el.checkValidity === "function" && !el.checkValidity()) {
1441
+ function rulesToValidator(rules) {
1442
+ return (value, meta) => {
1443
+ if (rules.required) {
1444
+ if (value === "" || value === void 0 || value === null || Array.isArray(value) && value.length === 0) {
1445
+ return [
1446
+ {
1447
+ type: "required",
1448
+ message: typeof rules.required === "string" ? rules.required : defaultMessage("required")
1449
+ }
1450
+ ];
1451
+ }
1452
+ }
1453
+ const errors = [];
1454
+ const message = (type, bound) => rules.messages?.[type] ?? defaultMessage(type, bound);
1455
+ if (rules.min !== void 0) {
1456
+ const n = Number(value);
1457
+ if (!Number.isNaN(n) && n < rules.min) {
1458
+ errors.push({ type: "min", message: message("min", rules.min) });
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) });
1465
+ }
1466
+ }
1467
+ const isSized = typeof value === "string" || Array.isArray(value);
1468
+ if (rules.minLength !== void 0 && isSized && value.length < rules.minLength) {
1234
1469
  errors.push({
1235
- path: nameToPath(el.name),
1236
- type: "native",
1237
- message: el.validationMessage
1470
+ type: "minLength",
1471
+ message: message("minLength", rules.minLength)
1238
1472
  });
1239
1473
  }
1240
- }
1241
- return errors;
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
+ if (rules.pattern && !rules.pattern.value.test(value)) {
1481
+ errors.push({
1482
+ type: "pattern",
1483
+ // pattern.message is type-required but JS consumers may omit it.
1484
+ message: rules.messages?.pattern ?? rules.pattern.message ?? defaultMessage("pattern")
1485
+ });
1486
+ }
1487
+ if (rules.validate !== void 0) {
1488
+ const fns = typeof rules.validate === "function" ? { validate: rules.validate } : rules.validate;
1489
+ for (const [type, fn] of Object.entries(fns)) {
1490
+ const result = fn(value, meta);
1491
+ if (result === void 0) continue;
1492
+ for (const entry of Array.isArray(result) ? result : [result]) {
1493
+ errors.push(
1494
+ typeof entry === "string" ? { type, message: entry } : { ...entry, type }
1495
+ );
1496
+ }
1497
+ }
1498
+ }
1499
+ return errors.length ? errors : void 0;
1500
+ };
1242
1501
  }
1243
- function handleSubmit(form, options) {
1502
+ function rulesToConstraintAttrs(rules) {
1503
+ const attrs = {};
1504
+ if (rules.required) attrs.required = true;
1505
+ if (rules.min !== void 0) attrs.min = rules.min;
1506
+ if (rules.max !== void 0) attrs.max = rules.max;
1507
+ if (rules.minLength !== void 0) attrs.minLength = rules.minLength;
1508
+ if (rules.maxLength !== void 0) attrs.maxLength = rules.maxLength;
1509
+ if (rules.pattern) attrs.pattern = rules.pattern.value.source;
1510
+ return attrs;
1511
+ }
1512
+
1513
+ function registerField(form, name, options) {
1514
+ const path = create$1(name);
1244
1515
  const {
1245
- onSubmit,
1246
- onValidSubmit,
1247
- onInvalidSubmit,
1248
- onAction,
1249
- shouldFocusError = true
1516
+ mode,
1517
+ shouldUnregister,
1518
+ eventToValue,
1519
+ valueAsNumber,
1520
+ valueAsDate,
1521
+ rules
1250
1522
  } = options ?? {};
1251
- return async (e) => {
1252
- if (e && typeof e.preventDefault === "function") {
1253
- e.preventDefault();
1523
+ const toValue = eventToValue ?? ((e) => {
1524
+ const target = e?.target;
1525
+ if (!target) return e;
1526
+ if (target.type === "file") return target.files;
1527
+ if (target.type === "checkbox") return target.checked;
1528
+ if (valueAsNumber) return target.valueAsNumber;
1529
+ if (valueAsDate) return target.valueAsDate;
1530
+ return target.value;
1531
+ });
1532
+ let el = null;
1533
+ let modeToken = null;
1534
+ let disposeValidator = null;
1535
+ let snapshot = null;
1536
+ let offFocus = null;
1537
+ let offBulkSync = null;
1538
+ const syncDom = () => {
1539
+ if (!el || el.type === "file") return;
1540
+ const next = getValueByPath(form, path);
1541
+ const asString = next == null ? "" : String(next);
1542
+ if (el.value !== asString) el.value = asString;
1543
+ };
1544
+ const attach = (node) => {
1545
+ if (snapshot) {
1546
+ restoreRemovedField(form, path, snapshot);
1547
+ snapshot = null;
1254
1548
  }
1255
- const formEl = e?.currentTarget;
1256
- setIsSubmitting(form, true);
1257
- incrementSubmitCount(form);
1258
- const values = getValues(form);
1259
- if (formEl && typeof formEl.checkValidity === "function" && formEl.checkValidity() === false) {
1260
- formEl.reportValidity();
1261
- if (shouldFocusError && typeof formEl.querySelector === "function") {
1262
- const invalid = formEl.querySelector(":invalid");
1263
- if (invalid && typeof invalid.focus === "function") invalid.focus();
1264
- }
1549
+ el = node;
1550
+ if (node.type !== "file" && getValueByPath(form, path) === void 0) {
1551
+ seedValueByPath(
1552
+ form,
1553
+ path,
1554
+ node.type === "checkbox" ? node.checked : node.value
1555
+ );
1556
+ emitChangeByPath(form, path);
1557
+ }
1558
+ modeToken = registerFieldMode(form, path, mode).token;
1559
+ if (rules && hasRuleConstraints(rules)) {
1560
+ const sync = rules.required !== void 0 ? rulesToValidator({ required: rules.required }) : void 0;
1561
+ const rest = rules.required !== void 0 ? { ...rules, required: void 0 } : rules;
1562
+ disposeValidator = registerValidatorByPath(form, path, {
1563
+ validate: () => hasRuleConstraints(rest) ? rulesToValidator(rest) : void 0,
1564
+ debounce: () => 0,
1565
+ sync: () => sync
1566
+ });
1567
+ }
1568
+ offFocus = on(
1569
+ form.emitter,
1570
+ "focusError",
1571
+ (key, options2) => {
1572
+ if (key !== path.key || !el || typeof el.focus !== "function") return;
1573
+ el.focus();
1574
+ if (options2?.shouldSelect && typeof el.select === "function") {
1575
+ el.select();
1576
+ }
1577
+ }
1578
+ );
1579
+ offBulkSync = on(form.emitter, "change", (changed) => {
1580
+ if (changed) return;
1581
+ syncDom();
1582
+ });
1583
+ };
1584
+ const detach = () => {
1585
+ if (modeToken) {
1586
+ unregisterFieldMode(form, path, modeToken);
1587
+ modeToken = null;
1588
+ }
1589
+ if (disposeValidator) {
1590
+ disposeValidator();
1591
+ disposeValidator = null;
1592
+ }
1593
+ if (offFocus) {
1594
+ offFocus();
1595
+ offFocus = null;
1596
+ }
1597
+ if (offBulkSync) {
1598
+ offBulkSync();
1599
+ offBulkSync = null;
1600
+ }
1601
+ el = null;
1602
+ if ((shouldUnregister ?? form.shouldUnregister) !== false) {
1603
+ snapshot = removeFieldForUnmount(form, path);
1604
+ }
1605
+ };
1606
+ return {
1607
+ name: path.key,
1608
+ onChange: (e) => changeValueByPath(form, path, toValue(e)),
1609
+ onBlur: () => userBlur(form, path),
1610
+ ref: (node) => {
1611
+ if (node) attach(node);
1612
+ else detach();
1613
+ }
1614
+ };
1615
+ }
1616
+
1617
+ function readArray(form, path) {
1618
+ const value = getValueByPath(form, path);
1619
+ return Array.isArray(value) ? value : [];
1620
+ }
1621
+ function appendValueByPath(form, path, value) {
1622
+ const arr = readArray(form, path);
1623
+ setValueByPath(form, path, [...arr, value]);
1624
+ }
1625
+ function prependValueByPath(form, path, value) {
1626
+ const arr = readArray(form, path);
1627
+ setValueByPath(form, path, [value, ...arr]);
1628
+ }
1629
+ function insertValueByPath(form, path, index, value) {
1630
+ const arr = readArray(form, path);
1631
+ if (index < 0 || index > arr.length) return false;
1632
+ setValueByPath(form, path, [
1633
+ ...arr.slice(0, index),
1634
+ value,
1635
+ ...arr.slice(index)
1636
+ ]);
1637
+ return true;
1638
+ }
1639
+ function removeValueByPath(form, path, indices) {
1640
+ const arr = readArray(form, path);
1641
+ const drop = /* @__PURE__ */ new Set();
1642
+ for (const index of Array.isArray(indices) ? indices : [indices]) {
1643
+ if (index >= 0 && index < arr.length) drop.add(index);
1644
+ }
1645
+ if (drop.size === 0) return [];
1646
+ const dropped = [...drop].sort((a, b) => b - a);
1647
+ setValueByPath(
1648
+ form,
1649
+ path,
1650
+ arr.filter((_, i) => !drop.has(i))
1651
+ );
1652
+ return dropped;
1653
+ }
1654
+ function moveValueByPath(form, path, from, to) {
1655
+ const arr = readArray(form, path);
1656
+ if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) {
1657
+ return false;
1658
+ }
1659
+ if (from === to) return false;
1660
+ const next = [...arr];
1661
+ const [item] = next.splice(from, 1);
1662
+ next.splice(to, 0, item);
1663
+ setValueByPath(form, path, next);
1664
+ return true;
1665
+ }
1666
+ function swapValuesByPath(form, path, from, to) {
1667
+ const arr = readArray(form, path);
1668
+ if (from < 0 || from >= arr.length || to < 0 || to >= arr.length) {
1669
+ return false;
1670
+ }
1671
+ if (from === to) return false;
1672
+ const next = [...arr];
1673
+ [next[from], next[to]] = [next[to], next[from]];
1674
+ setValueByPath(form, path, next);
1675
+ return true;
1676
+ }
1677
+ function replaceValuesByPath(form, path, values) {
1678
+ setValueByPath(form, path, [...values]);
1679
+ }
1680
+ function updateValueByPath(form, path, index, value) {
1681
+ const arr = readArray(form, path);
1682
+ if (index < 0 || index >= arr.length) return false;
1683
+ const next = [...arr];
1684
+ next[index] = value;
1685
+ setValueByPath(form, path, next);
1686
+ return true;
1687
+ }
1688
+ function appendValue(form, name, value) {
1689
+ appendValueByPath(form, create$1(name), value);
1690
+ }
1691
+ function prependValue(form, name, value) {
1692
+ prependValueByPath(form, create$1(name), value);
1693
+ }
1694
+ function insertValue(form, name, index, value) {
1695
+ return insertValueByPath(form, create$1(name), index, value);
1696
+ }
1697
+ function removeValue(form, name, indices) {
1698
+ return removeValueByPath(form, create$1(name), indices);
1699
+ }
1700
+ function moveValue(form, name, from, to) {
1701
+ return moveValueByPath(form, create$1(name), from, to);
1702
+ }
1703
+ function swapValues(form, name, from, to) {
1704
+ return swapValuesByPath(form, create$1(name), from, to);
1705
+ }
1706
+ function replaceValues(form, name, values) {
1707
+ replaceValuesByPath(form, create$1(name), values);
1708
+ }
1709
+ function updateValue(form, name, index, value) {
1710
+ return updateValueByPath(form, create$1(name), index, value);
1711
+ }
1712
+
1713
+ function setIsSubmitting(form, value) {
1714
+ form.isSubmitting = value;
1715
+ emit(form.emitter, "submitting");
1716
+ }
1717
+ function incrementSubmitCount(form) {
1718
+ form.submitCount++;
1719
+ emit(form.emitter, "submitCount");
1720
+ }
1721
+ function setSubmitSuccessful(form, value) {
1722
+ form.isSubmitSuccessful = value;
1723
+ emit(form.emitter, "submitSuccessful");
1724
+ }
1725
+ function setDisabled(form, value) {
1726
+ form.disabled = value;
1727
+ emit(form.emitter, "disabled");
1728
+ }
1729
+ function setStatus(form, value) {
1730
+ form.status = value;
1731
+ emit(form.emitter, "status");
1732
+ }
1733
+ function nameToPath(name) {
1734
+ if (name.startsWith("[")) {
1735
+ try {
1736
+ const segments = JSON.parse(name);
1737
+ if (Array.isArray(segments)) return segments.join(".");
1738
+ } catch {
1739
+ }
1740
+ }
1741
+ return name;
1742
+ }
1743
+ function getNativeErrors(formEl) {
1744
+ const errors = [];
1745
+ const { elements } = formEl;
1746
+ for (let i = 0; i < elements.length; i++) {
1747
+ const el = elements[i];
1748
+ if (el.name && typeof el.checkValidity === "function" && !el.checkValidity()) {
1749
+ errors.push({
1750
+ path: nameToPath(el.name),
1751
+ type: "native",
1752
+ message: el.validationMessage
1753
+ });
1754
+ }
1755
+ }
1756
+ return errors;
1757
+ }
1758
+ function handleSubmit(form, options) {
1759
+ const {
1760
+ onSubmit,
1761
+ onValidSubmit,
1762
+ onInvalidSubmit,
1763
+ onAction,
1764
+ shouldFocusError = true,
1765
+ shouldUseNativeValidation = form.shouldUseNativeValidation
1766
+ } = options ?? {};
1767
+ return async (e) => {
1768
+ if (e && typeof e.preventDefault === "function") {
1769
+ e.preventDefault();
1770
+ }
1771
+ const formEl = e?.currentTarget;
1772
+ clearServerErrors(form);
1773
+ form.isSubmitted = true;
1774
+ setIsSubmitting(form, true);
1775
+ incrementSubmitCount(form);
1776
+ const values = getValues(form);
1777
+ if (shouldUseNativeValidation && formEl && typeof formEl.checkValidity === "function" && formEl.checkValidity() === false) {
1778
+ formEl.reportValidity();
1779
+ if (shouldFocusError && typeof formEl.querySelector === "function") {
1780
+ const invalid = formEl.querySelector(":invalid");
1781
+ if (invalid && typeof invalid.focus === "function") invalid.focus();
1782
+ }
1265
1783
  setIsSubmitting(form, false);
1266
1784
  setSubmitSuccessful(form, false);
1267
1785
  if (onInvalidSubmit) onInvalidSubmit(getNativeErrors(formEl), values);
@@ -1282,7 +1800,14 @@
1282
1800
  const submitted = getValues(form);
1283
1801
  if (onSubmit) await onSubmit(submitted, e);
1284
1802
  if (onValidSubmit) await onValidSubmit(submitted, e);
1285
- if (onAction) await onAction(submitted, e);
1803
+ if (onAction) {
1804
+ const result = await onAction(submitted, e);
1805
+ if (result && typeof result === "object" && result.errors !== void 0 && typeof result.errors === "object") {
1806
+ setServerErrors(form, result.errors);
1807
+ setSubmitSuccessful(form, false);
1808
+ return;
1809
+ }
1810
+ }
1286
1811
  setSubmitSuccessful(form, true);
1287
1812
  } catch {
1288
1813
  setSubmitSuccessful(form, false);
@@ -1303,12 +1828,21 @@
1303
1828
  _setMaxListeners(emitter, 0);
1304
1829
  let source = options?.initialValues ?? {};
1305
1830
  if (typeof source === "function") source = source();
1831
+ const validateOption = options?.validate;
1832
+ const wrappedValidate = validateOption && hasStandardProps(validateOption) ? schemaToFormValidator(
1833
+ validateOption
1834
+ ) : validateOption;
1306
1835
  const form = {
1307
1836
  emitter,
1308
1837
  ...options,
1838
+ validate: wrappedValidate,
1309
1839
  mode: options?.mode ?? "onSubmit",
1310
1840
  reValidateMode: options?.reValidateMode ?? "onChange",
1841
+ validateMode: options?.validateMode ?? "onSubmit",
1311
1842
  disabled: options?.disabled ?? false,
1843
+ validateOnMount: options?.validateOnMount ?? false,
1844
+ asyncAlways: options?.asyncAlways ?? false,
1845
+ shouldUseNativeValidation: options?.shouldUseNativeValidation ?? true,
1312
1846
  validateDeps: options?.validateDeps ? new Set(options.validateDeps.map((dep) => create$1(dep).key)) : void 0,
1313
1847
  initialValues: {},
1314
1848
  values: /* @__PURE__ */ new Map(),
@@ -1319,18 +1853,21 @@
1319
1853
  validating: /* @__PURE__ */ new Set(),
1320
1854
  parsedValues: void 0,
1321
1855
  isSubmitting: false,
1856
+ isSubmitted: false,
1322
1857
  submitCount: 0,
1323
1858
  isSubmitSuccessful: void 0,
1324
- isLoading: false
1859
+ isLoading: false,
1860
+ status: void 0,
1861
+ register: (name, registerOptions) => registerField(form, name, registerOptions)
1325
1862
  };
1326
1863
  if (isPromise(source)) {
1327
1864
  form.isLoading = true;
1328
1865
  emit(emitter, "loading");
1329
1866
  Promise.resolve(source).then(
1330
1867
  (resolved) => {
1868
+ setInitialValues(form, resolved ?? {});
1331
1869
  form.isLoading = false;
1332
1870
  emit(emitter, "loading");
1333
- setInitialValues(form, resolved ?? {});
1334
1871
  },
1335
1872
  (error) => {
1336
1873
  form.isLoading = false;
@@ -1343,270 +1880,46 @@
1343
1880
  return form;
1344
1881
  }
1345
1882
 
1346
- function defaultMessage(type, bound) {
1347
- switch (type) {
1348
- case "required":
1349
- return "This field is required";
1350
- case "min":
1351
- return `Must be at least ${bound}`;
1352
- case "max":
1353
- return `Must be at most ${bound}`;
1354
- case "minLength":
1355
- return `Must be at least ${bound} characters`;
1356
- case "maxLength":
1357
- return `Must be at most ${bound} characters`;
1358
- case "pattern":
1359
- return "Invalid format";
1360
- default:
1361
- return "Invalid value";
1362
- }
1363
- }
1364
- function rulesToValidator(rules) {
1365
- return (value) => {
1366
- if (rules.required) {
1367
- if (value === "" || value === void 0 || value === null) {
1368
- return [
1369
- {
1370
- type: "required",
1371
- message: typeof rules.required === "string" ? rules.required : defaultMessage("required")
1372
- }
1373
- ];
1374
- }
1375
- }
1376
- const errors = [];
1377
- const message = (type, bound) => rules.messages?.[type] ?? defaultMessage(type, bound);
1378
- if (rules.min !== void 0) {
1379
- const n = Number(value);
1380
- if (!Number.isNaN(n) && n < rules.min) {
1381
- errors.push({ type: "min", message: message("min", rules.min) });
1382
- }
1383
- }
1384
- if (rules.max !== void 0) {
1385
- const n = Number(value);
1386
- if (!Number.isNaN(n) && n > rules.max) {
1387
- errors.push({ type: "max", message: message("max", rules.max) });
1388
- }
1389
- }
1390
- if (rules.minLength !== void 0 && typeof value === "string" && value.length < rules.minLength) {
1391
- errors.push({
1392
- type: "minLength",
1393
- message: message("minLength", rules.minLength)
1394
- });
1395
- }
1396
- if (rules.maxLength !== void 0 && typeof value === "string" && value.length > rules.maxLength) {
1397
- errors.push({
1398
- type: "maxLength",
1399
- message: message("maxLength", rules.maxLength)
1400
- });
1401
- }
1402
- if (rules.pattern && !rules.pattern.value.test(value)) {
1403
- errors.push({
1404
- type: "pattern",
1405
- // pattern.message is type-required but JS consumers may omit it.
1406
- message: rules.messages?.pattern ?? rules.pattern.message ?? defaultMessage("pattern")
1407
- });
1408
- }
1409
- return errors.length ? errors : void 0;
1410
- };
1411
- }
1412
-
1413
- var shim = {exports: {}};
1414
-
1415
- var useSyncExternalStoreShim_production = {};
1416
-
1417
- /**
1418
- * @license React
1419
- * use-sync-external-store-shim.production.js
1420
- *
1421
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1422
- *
1423
- * This source code is licensed under the MIT license found in the
1424
- * LICENSE file in the root directory of this source tree.
1425
- */
1426
-
1427
- var hasRequiredUseSyncExternalStoreShim_production;
1428
-
1429
- function requireUseSyncExternalStoreShim_production () {
1430
- if (hasRequiredUseSyncExternalStoreShim_production) return useSyncExternalStoreShim_production;
1431
- hasRequiredUseSyncExternalStoreShim_production = 1;
1432
- var React$1 = React;
1433
- function is(x, y) {
1434
- return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
1435
- }
1436
- var objectIs = "function" === typeof Object.is ? Object.is : is,
1437
- useState = React$1.useState,
1438
- useEffect = React$1.useEffect,
1439
- useLayoutEffect = React$1.useLayoutEffect,
1440
- useDebugValue = React$1.useDebugValue;
1441
- function useSyncExternalStore$2(subscribe, getSnapshot) {
1442
- var value = getSnapshot(),
1443
- _useState = useState({ inst: { value: value, getSnapshot: getSnapshot } }),
1444
- inst = _useState[0].inst,
1445
- forceUpdate = _useState[1];
1446
- useLayoutEffect(
1447
- function () {
1448
- inst.value = value;
1449
- inst.getSnapshot = getSnapshot;
1450
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
1451
- },
1452
- [subscribe, value, getSnapshot]
1453
- );
1454
- useEffect(
1455
- function () {
1456
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
1457
- return subscribe(function () {
1458
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
1459
- });
1460
- },
1461
- [subscribe]
1462
- );
1463
- useDebugValue(value);
1464
- return value;
1465
- }
1466
- function checkIfSnapshotChanged(inst) {
1467
- var latestGetSnapshot = inst.getSnapshot;
1468
- inst = inst.value;
1469
- try {
1470
- var nextValue = latestGetSnapshot();
1471
- return !objectIs(inst, nextValue);
1472
- } catch (error) {
1473
- return true;
1474
- }
1475
- }
1476
- function useSyncExternalStore$1(subscribe, getSnapshot) {
1477
- return getSnapshot();
1478
- }
1479
- var shim =
1480
- "undefined" === typeof window ||
1481
- "undefined" === typeof window.document ||
1482
- "undefined" === typeof window.document.createElement
1483
- ? useSyncExternalStore$1
1484
- : useSyncExternalStore$2;
1485
- useSyncExternalStoreShim_production.useSyncExternalStore =
1486
- void 0 !== React$1.useSyncExternalStore ? React$1.useSyncExternalStore : shim;
1487
- return useSyncExternalStoreShim_production;
1883
+ function errorIdFromKey(key) {
1884
+ const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
1885
+ return id || "field";
1488
1886
  }
1489
-
1490
- var useSyncExternalStoreShim_development = {};
1491
-
1492
- /**
1493
- * @license React
1494
- * use-sync-external-store-shim.development.js
1495
- *
1496
- * Copyright (c) Meta Platforms, Inc. and affiliates.
1497
- *
1498
- * This source code is licensed under the MIT license found in the
1499
- * LICENSE file in the root directory of this source tree.
1500
- */
1501
-
1502
- var hasRequiredUseSyncExternalStoreShim_development;
1503
-
1504
- function requireUseSyncExternalStoreShim_development () {
1505
- if (hasRequiredUseSyncExternalStoreShim_development) return useSyncExternalStoreShim_development;
1506
- hasRequiredUseSyncExternalStoreShim_development = 1;
1507
- "production" !== process.env.NODE_ENV &&
1508
- (function () {
1509
- function is(x, y) {
1510
- return (x === y && (0 !== x || 1 / x === 1 / y)) || (x !== x && y !== y);
1511
- }
1512
- function useSyncExternalStore$2(subscribe, getSnapshot) {
1513
- didWarnOld18Alpha ||
1514
- void 0 === React$1.startTransition ||
1515
- ((didWarnOld18Alpha = true),
1516
- console.error(
1517
- "You are using an outdated, pre-release alpha of React 18 that does not support useSyncExternalStore. The use-sync-external-store shim will not work correctly. Upgrade to a newer pre-release."
1518
- ));
1519
- var value = getSnapshot();
1520
- if (!didWarnUncachedGetSnapshot) {
1521
- var cachedValue = getSnapshot();
1522
- objectIs(value, cachedValue) ||
1523
- (console.error(
1524
- "The result of getSnapshot should be cached to avoid an infinite loop"
1525
- ),
1526
- (didWarnUncachedGetSnapshot = true));
1527
- }
1528
- cachedValue = useState({
1529
- inst: { value: value, getSnapshot: getSnapshot }
1530
- });
1531
- var inst = cachedValue[0].inst,
1532
- forceUpdate = cachedValue[1];
1533
- useLayoutEffect(
1534
- function () {
1535
- inst.value = value;
1536
- inst.getSnapshot = getSnapshot;
1537
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
1538
- },
1539
- [subscribe, value, getSnapshot]
1540
- );
1541
- useEffect(
1542
- function () {
1543
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
1544
- return subscribe(function () {
1545
- checkIfSnapshotChanged(inst) && forceUpdate({ inst: inst });
1546
- });
1547
- },
1548
- [subscribe]
1549
- );
1550
- useDebugValue(value);
1551
- return value;
1552
- }
1553
- function checkIfSnapshotChanged(inst) {
1554
- var latestGetSnapshot = inst.getSnapshot;
1555
- inst = inst.value;
1556
- try {
1557
- var nextValue = latestGetSnapshot();
1558
- return !objectIs(inst, nextValue);
1559
- } catch (error) {
1560
- return true;
1561
- }
1562
- }
1563
- function useSyncExternalStore$1(subscribe, getSnapshot) {
1564
- return getSnapshot();
1565
- }
1566
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1567
- "function" ===
1568
- typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart &&
1569
- __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error());
1570
- var React$1 = React,
1571
- objectIs = "function" === typeof Object.is ? Object.is : is,
1572
- useState = React$1.useState,
1573
- useEffect = React$1.useEffect,
1574
- useLayoutEffect = React$1.useLayoutEffect,
1575
- useDebugValue = React$1.useDebugValue,
1576
- didWarnOld18Alpha = false,
1577
- didWarnUncachedGetSnapshot = false,
1578
- shim =
1579
- "undefined" === typeof window ||
1580
- "undefined" === typeof window.document ||
1581
- "undefined" === typeof window.document.createElement
1582
- ? useSyncExternalStore$1
1583
- : useSyncExternalStore$2;
1584
- useSyncExternalStoreShim_development.useSyncExternalStore =
1585
- void 0 !== React$1.useSyncExternalStore ? React$1.useSyncExternalStore : shim;
1586
- "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ &&
1587
- "function" ===
1588
- typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop &&
1589
- __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error());
1590
- })();
1591
- return useSyncExternalStoreShim_development;
1887
+ function fieldErrorId(name) {
1888
+ return errorIdFromKey(create$1(name).key);
1592
1889
  }
1593
1890
 
1594
- var hasRequiredShim;
1595
-
1596
- function requireShim () {
1597
- if (hasRequiredShim) return shim.exports;
1598
- hasRequiredShim = 1;
1599
-
1600
- if (process.env.NODE_ENV === 'production') {
1601
- shim.exports = requireUseSyncExternalStoreShim_production();
1602
- } else {
1603
- shim.exports = requireUseSyncExternalStoreShim_development();
1604
- }
1605
- return shim.exports;
1891
+ const fieldDisabledRegistry = /* @__PURE__ */ new WeakMap();
1892
+ function registerFieldDisabled(form, path, disabled) {
1893
+ if (disabled === void 0) return null;
1894
+ let registry = fieldDisabledRegistry.get(form);
1895
+ if (!registry) {
1896
+ registry = /* @__PURE__ */ new Map();
1897
+ fieldDisabledRegistry.set(form, registry);
1898
+ }
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;
1606
1921
  }
1607
1922
 
1608
- var shimExports = requireShim();
1609
-
1610
1923
  function isDescendant(key, ancestorKey) {
1611
1924
  return key.startsWith(`${ancestorKey.slice(0, -1)},`);
1612
1925
  }
@@ -1636,6 +1949,41 @@
1636
1949
  });
1637
1950
  return unsubscribes.length === 1 ? unsubscribes[0] : () => unsubscribes.forEach((unsubscribe) => unsubscribe());
1638
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
+ }
1639
1987
 
1640
1988
  function useForm(options) {
1641
1989
  const [form] = React.useState(() => {
@@ -1677,6 +2025,19 @@
1677
2025
  seeded.source = values;
1678
2026
  setInitialValues(form, values);
1679
2027
  }, [form, values]);
2028
+ React.useEffect(() => {
2029
+ if (!form.validateOnMount || !form.validate) return;
2030
+ const run = () => {
2031
+ void runFormValidate(form).catch(() => void 0);
2032
+ };
2033
+ if (!form.isLoading) {
2034
+ run();
2035
+ return;
2036
+ }
2037
+ return on(form.emitter, "loading", () => {
2038
+ run();
2039
+ });
2040
+ }, [form]);
1680
2041
  return form;
1681
2042
  }
1682
2043
  function useWatchCore(subscribeFactory, getter, isEqual2) {
@@ -1713,7 +2074,7 @@
1713
2074
  },
1714
2075
  [subscribeFactory, cache]
1715
2076
  );
1716
- return shimExports.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
2077
+ return React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
1717
2078
  }
1718
2079
  function useWatch(formOrEmitter, event, getter, isEqual2) {
1719
2080
  const emitter = "emitter" in formOrEmitter ? formOrEmitter.emitter : formOrEmitter;
@@ -1723,18 +2084,33 @@
1723
2084
  );
1724
2085
  return useWatchCore(subscribeFactory, getter, isEqual2);
1725
2086
  }
1726
- function useValue(form, name) {
1727
- return useValueByPath(form, create$1(name));
2087
+ function useValue(form, name, options) {
2088
+ return useValueByPath(form, create$1(name), options);
1728
2089
  }
1729
- function useValueByPath(form, path) {
2090
+ function useValueByPath(form, path, options) {
1730
2091
  const { emitter } = form;
1731
2092
  const { key } = path;
2093
+ const scope = options?.exact === false ? "branch" : "leaf";
1732
2094
  const subscribeFactory = React.useCallback(
1733
- (invalidate) => onPathEvent(emitter, "change", path, "leaf", invalidate),
1734
- // 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
1735
- [emitter, key]
2095
+ (invalidate) => onPathEvent(
2096
+ emitter,
2097
+ "change",
2098
+ create$1(JSON.parse(key)),
2099
+ scope,
2100
+ invalidate
2101
+ ),
2102
+ [emitter, key, scope]
1736
2103
  );
1737
- return useWatchCore(subscribeFactory, getValueByPath.bind(null, form, path));
2104
+ return useWatchCore(subscribeFactory, () => {
2105
+ if (options?.exact === false) {
2106
+ return get(getValues(form), path.value);
2107
+ }
2108
+ const value = getValueByPath(form, path);
2109
+ return value === void 0 ? options?.defaultValue : value;
2110
+ });
2111
+ }
2112
+ function useValues(form) {
2113
+ return useWatch(form, "change", () => getValues(form));
1738
2114
  }
1739
2115
  function useTouched(form, name) {
1740
2116
  return useTouchedByPath(form, create$1(name));
@@ -1781,6 +2157,24 @@
1781
2157
  function useIsDirty(form) {
1782
2158
  return useWatch(form, "change", isDirty.bind(null, form));
1783
2159
  }
2160
+ function useIsFieldDirty(form, name) {
2161
+ return useIsFieldDirtyByPath(form, create$1(name));
2162
+ }
2163
+ function useIsFieldDirtyByPath(form, path) {
2164
+ const { emitter } = form;
2165
+ const { key } = path;
2166
+ const subscribeFactory = React.useCallback(
2167
+ (invalidate) => onPathEvent(
2168
+ emitter,
2169
+ "change",
2170
+ create$1(JSON.parse(key)),
2171
+ "leaf",
2172
+ invalidate
2173
+ ),
2174
+ [emitter, key]
2175
+ );
2176
+ return useWatchCore(subscribeFactory, () => isFieldDirtyByPath(form, path));
2177
+ }
1784
2178
  function useDirtyFields(form) {
1785
2179
  return useWatch(form, "change", getDirtyFields.bind(null, form));
1786
2180
  }
@@ -1806,7 +2200,9 @@
1806
2200
  touchedFields: getTouchedFields(form),
1807
2201
  hasErrors: hasErrors(form),
1808
2202
  isValid: !hasErrors(form),
2203
+ errors: getErrorsRecord(form),
1809
2204
  isSubmitting: form.isSubmitting,
2205
+ isSubmitted: form.isSubmitted,
1810
2206
  isValidating: form.validating.size > 0,
1811
2207
  isSubmitSuccessful: form.isSubmitSuccessful,
1812
2208
  submitCount: form.submitCount,
@@ -1816,7 +2212,7 @@
1816
2212
  }
1817
2213
  function isSameFormState(a, b) {
1818
2214
  const sameTouched = a.touchedFields.length === b.touchedFields.length && a.touchedFields.every((path, i) => path === b.touchedFields[i]);
1819
- 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.isValidating === b.isValidating && a.isSubmitSuccessful === b.isSubmitSuccessful && a.submitCount === b.submitCount && a.isLoading === b.isLoading && a.disabled === b.disabled;
2215
+ 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;
1820
2216
  }
1821
2217
  function useFormState(form) {
1822
2218
  const getter = React.useCallback(() => getFormState(form), [form]);
@@ -1833,9 +2229,29 @@
1833
2229
  );
1834
2230
  return useWatchCore(subscribeFactory, getter, isSameFormState);
1835
2231
  }
2232
+ function useStore(form, selector, isEqual2) {
2233
+ 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
+ },
2242
+ [form.emitter]
2243
+ );
2244
+ return useWatchCore(subscribeFactory, selector, isEqual2);
2245
+ }
1836
2246
  function useHasErrors(form) {
1837
2247
  return useWatch(form, "errors", hasErrors.bind(null, form));
1838
2248
  }
2249
+ function useErrors(form) {
2250
+ return useWatch(form, "errors", () => getErrorsRecord(form));
2251
+ }
2252
+ function useErrorsTree(form) {
2253
+ return useWatch(form, "errors", () => getErrorsTree(form));
2254
+ }
1839
2255
  function useIsValid(form) {
1840
2256
  return useWatch(form, "errors", () => !hasErrors(form));
1841
2257
  }
@@ -1845,6 +2261,9 @@
1845
2261
  function useIsLoading(form) {
1846
2262
  return useWatch(form, "loading", () => form.isLoading);
1847
2263
  }
2264
+ function useStatus(form) {
2265
+ return useWatch(form, "status", () => form.status);
2266
+ }
1848
2267
  function useCanSubmit(form) {
1849
2268
  const { emitter } = form;
1850
2269
  const subscribeFactory = React.useCallback(
@@ -1884,8 +2303,8 @@
1884
2303
  }
1885
2304
 
1886
2305
  function usePath(name) {
1887
- const path = React.useMemo(() => create$1(normalizePath(name)), [name]);
1888
- return React.useMemo(() => path, [path.key]);
2306
+ const key = React.useMemo(() => create$1(normalizePath(name)).key, [name]);
2307
+ return React.useMemo(() => create$1(JSON.parse(key)), [key]);
1889
2308
  }
1890
2309
 
1891
2310
  function useStage(value) {
@@ -1900,32 +2319,73 @@
1900
2319
  [ref]
1901
2320
  );
1902
2321
  }
2322
+ function useUnmountRestore(teardown, restore) {
2323
+ const removedRef = React.useRef(false);
2324
+ const teardownRef = useStage(teardown);
2325
+ const restoreRef = useStage(restore);
2326
+ React.useEffect(() => {
2327
+ const teardownOnce = teardownRef.current;
2328
+ const restoreOnce = restoreRef.current;
2329
+ if (removedRef.current) {
2330
+ removedRef.current = false;
2331
+ restoreOnce();
2332
+ }
2333
+ return () => {
2334
+ removedRef.current = true;
2335
+ teardownOnce();
2336
+ };
2337
+ }, [removedRef, teardownRef, restoreRef]);
2338
+ }
1903
2339
 
1904
2340
  function useValidate(validate, path, formProp, options) {
1905
2341
  const contextForm = React.useContext(FormContext);
1906
2342
  const form = formProp || contextForm;
1907
2343
  if (!form) throw new Error("no form provided");
1908
- const validateRef = React.useRef(validate);
1909
- validateRef.current = validate;
2344
+ const validateOption = validate;
2345
+ const validateRef = React.useRef(void 0);
2346
+ validateRef.current = validateOption && hasStandardProps(validateOption) ? schemaToFieldValidator(validateOption) : validateOption;
1910
2347
  const debounceRef = React.useRef(options?.debounce ?? 0);
1911
2348
  debounceRef.current = options?.debounce ?? 0;
1912
2349
  const syncRef = React.useRef(options?.sync);
1913
2350
  syncRef.current = options?.sync;
1914
- React.useEffect(
1915
- () => registerValidatorByPath(form, path, {
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;
2355
+ React.useEffect(() => {
2356
+ const spath = create$1(JSON.parse(path.key));
2357
+ const dispose = registerValidatorByPath(form, spath, {
1916
2358
  validate: () => validateRef.current,
1917
2359
  debounce: () => debounceRef.current,
1918
- sync: () => syncRef.current
1919
- }),
1920
- // eslint-disable-next-line react-hooks/exhaustive-deps -- deps are `path.key` on purpose: usePath returns a stable Path per key, so re-subscribing on key (not object identity) is enough
1921
- [form, path.key]
1922
- );
2360
+ sync: () => syncRef.current,
2361
+ asyncAlways: () => asyncAlwaysRef.current
2362
+ });
2363
+ const validateOnMount = validateOnMountRef.current ?? form.validateOnMount;
2364
+ if (!validateOnMount || !validateRef.current && !syncRef.current) {
2365
+ return dispose;
2366
+ }
2367
+ let disposed = false;
2368
+ const kick = () => {
2369
+ if (disposed) return;
2370
+ form.validators.get(path.key)?.();
2371
+ };
2372
+ if (!form.isLoading) {
2373
+ kick();
2374
+ } else {
2375
+ const off = on(form.emitter, "loading", () => {
2376
+ off();
2377
+ kick();
2378
+ });
2379
+ }
2380
+ return () => {
2381
+ disposed = true;
2382
+ dispose();
2383
+ };
2384
+ }, [form, path.key]);
1923
2385
  return useStageFn(() => form.validators.get(path.key)?.());
1924
2386
  }
1925
2387
 
1926
- function hasRuleConstraints(rules) {
1927
- 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;
1928
- }
2388
+ const uncontrolledSyncRegistry = /* @__PURE__ */ new WeakMap();
1929
2389
  function combineRulesAndValidate(rules, validate) {
1930
2390
  if (!rules || !hasRuleConstraints(rules)) return validate;
1931
2391
  const ruleValidator = rulesToValidator(rules);
@@ -1942,22 +2402,59 @@
1942
2402
  return isPromise(result) ? result.then(merge) : merge(result);
1943
2403
  };
1944
2404
  }
1945
- function useDelayedErrors(errors, delay) {
1946
- const [shown, setShown] = React.useState(errors);
1947
- React.useEffect(() => {
1948
- if (delay === void 0) return;
1949
- if (errors.length === 0) {
1950
- setShown(errors);
1951
- return;
1952
- }
1953
- if (shown.length > 0) {
1954
- setShown(errors);
1955
- return;
1956
- }
1957
- const timer = setTimeout(() => setShown(errors), delay);
1958
- return () => clearTimeout(timer);
1959
- }, [errors, delay, shown]);
1960
- return delay === void 0 ? errors : shown;
2405
+ const NO_DELAYED_ERRORS = [];
2406
+ function useDelayedErrors(form, path, delay) {
2407
+ const pendingRef = React.useRef(false);
2408
+ const prevRef = React.useRef(false);
2409
+ const timerRef = React.useRef(null);
2410
+ const subscribeFactory = React.useCallback(
2411
+ (invalidate) => {
2412
+ const spath = create$1(JSON.parse(path.key));
2413
+ const clearTimer = () => {
2414
+ if (timerRef.current !== null) {
2415
+ clearTimeout(timerRef.current);
2416
+ timerRef.current = null;
2417
+ }
2418
+ };
2419
+ pendingRef.current = false;
2420
+ prevRef.current = false;
2421
+ clearTimer();
2422
+ const startWindow = () => {
2423
+ clearTimer();
2424
+ pendingRef.current = true;
2425
+ timerRef.current = setTimeout(() => {
2426
+ timerRef.current = null;
2427
+ pendingRef.current = false;
2428
+ invalidate();
2429
+ }, delay);
2430
+ };
2431
+ const off = onKeyEvent(form.emitter, "errors", spath.key, () => {
2432
+ const has = getFieldErrorsByPath(form, spath).length > 0;
2433
+ const was = prevRef.current;
2434
+ prevRef.current = has;
2435
+ if (delay !== void 0) {
2436
+ if (!has) {
2437
+ if (pendingRef.current) {
2438
+ clearTimer();
2439
+ pendingRef.current = false;
2440
+ }
2441
+ } else if (!was || pendingRef.current) {
2442
+ startWindow();
2443
+ }
2444
+ }
2445
+ invalidate();
2446
+ });
2447
+ return () => {
2448
+ off();
2449
+ clearTimer();
2450
+ };
2451
+ },
2452
+ [form, path.key, delay]
2453
+ );
2454
+ return useWatchCore(
2455
+ subscribeFactory,
2456
+ () => delay === void 0 || !pendingRef.current ? getFieldErrorsByPath(form, path) : NO_DELAYED_ERRORS
2457
+ );
1961
2458
  }
1962
2459
  function useFieldValue(form, path, uncontrolled) {
1963
2460
  const snapshotRef = React.useRef({
@@ -1987,10 +2484,16 @@
1987
2484
  rules,
1988
2485
  validateDebounce,
1989
2486
  validateDeps,
2487
+ validateOnMount,
1990
2488
  delayError,
1991
2489
  disabled,
1992
2490
  uncontrolled,
1993
- mode: modeOption
2491
+ asyncAlways,
2492
+ mode: modeOption,
2493
+ eventToValue,
2494
+ valueAsNumber,
2495
+ valueAsDate,
2496
+ type
1994
2497
  }, Context) {
1995
2498
  const contextForm = React.useContext(Context);
1996
2499
  const form = f1 || contextForm;
@@ -2008,29 +2511,79 @@
2008
2511
  emitChangeByPath(form, path);
2009
2512
  });
2010
2513
  const restRules = rules ? { ...rules, required: void 0 } : void 0;
2011
- useValidate(combineRulesAndValidate(restRules, validate), path, form, {
2514
+ const validateOption = validate;
2515
+ const validateWrapped = validateOption && hasStandardProps(validateOption) ? schemaToFieldValidator(validateOption) : validateOption;
2516
+ useValidate(combineRulesAndValidate(restRules, validateWrapped), path, form, {
2012
2517
  debounce: validateDebounce,
2518
+ validateOnMount,
2519
+ asyncAlways: asyncAlways ?? form.asyncAlways,
2013
2520
  sync: rules && rules.required !== void 0 ? rulesToValidator({ required: rules.required }) : void 0
2014
2521
  });
2015
- const liveErrors = useFieldErrorsByPath(form, path);
2016
- const errors = useDelayedErrors(liveErrors, delayError);
2522
+ const errors = useDelayedErrors(form, path, delayError);
2017
2523
  const errorObject = errors[0];
2018
2524
  const error = errorObject?.message;
2019
2525
  const value = useFieldValue(form, path, !!uncontrolled);
2020
- const formDisabled = useWatch(form, "disabled", () => form.disabled);
2526
+ const isDirty = useWatchCore(
2527
+ React.useCallback(
2528
+ (invalidate) => uncontrolled ? () => {
2529
+ } : onPathEvent(
2530
+ form.emitter,
2531
+ "change",
2532
+ create$1(JSON.parse(path.key)),
2533
+ "leaf",
2534
+ invalidate
2535
+ ),
2536
+ [form.emitter, path.key, uncontrolled]
2537
+ ),
2538
+ () => isFieldDirtyByPath(form, path)
2539
+ );
2540
+ const validating = useWatchCore(
2541
+ React.useCallback(
2542
+ (invalidate) => onKeyEvent(form.emitter, "validating", path.key, invalidate),
2543
+ [form.emitter, path.key]
2544
+ ),
2545
+ () => form.validating.has(path.key)
2546
+ );
2547
+ const mergedDisabled = useWatchCore(
2548
+ React.useCallback(
2549
+ (invalidate) => onPathEvent(
2550
+ form.emitter,
2551
+ "disabled",
2552
+ create$1(JSON.parse(path.key)),
2553
+ "branch",
2554
+ invalidate
2555
+ ),
2556
+ [form.emitter, path.key]
2557
+ ),
2558
+ () => form.disabled || disabled === true || disabled !== false && hasDisabledAncestor(form, path)
2559
+ );
2560
+ const disabledTokenRef = React.useRef(null);
2561
+ React.useEffect(() => {
2562
+ const spath = create$1(JSON.parse(path.key));
2563
+ const registration = registerFieldDisabled(form, spath, disabled);
2564
+ if (registration) disabledTokenRef.current = registration.token;
2565
+ return () => {
2566
+ if (disabledTokenRef.current !== null) {
2567
+ unregisterFieldDisabled(form, spath, disabledTokenRef.current);
2568
+ disabledTokenRef.current = null;
2569
+ }
2570
+ };
2571
+ }, [form, path.key, disabled]);
2021
2572
  const onChange = useStageFn((v) => userChangeByPath(form, path, v));
2022
2573
  const onBlur = useStageFn(() => userBlur(form, path));
2023
2574
  React.useEffect(() => {
2024
- const { token, displaced } = registerFieldMode(form, path, modeOption);
2025
- return () => unregisterFieldMode(form, path, token);
2575
+ const spath = create$1(JSON.parse(path.key));
2576
+ const { token, displaced } = registerFieldMode(form, spath, modeOption);
2577
+ return () => unregisterFieldMode(form, spath, token);
2026
2578
  }, [form, path.key, modeOption]);
2027
2579
  const depsKey = validateDeps?.length ? validateDeps.join("\n") : void 0;
2580
+ const validateDepsRef = useStage(validateDeps);
2028
2581
  React.useEffect(() => {
2029
2582
  if (!depsKey) return;
2030
- const depKeys = validateDeps.map((dep) => create$1(dep).key);
2583
+ const depKeys = validateDepsRef.current.map((dep) => create$1(dep).key);
2031
2584
  registerFieldValidateDeps(form, path.key, depKeys);
2032
2585
  return () => unregisterFieldValidateDeps(form, path.key, depKeys);
2033
- }, [form, path.key, depsKey]);
2586
+ }, [form, path.key, depsKey, validateDepsRef]);
2034
2587
  const elementRef = React.useRef(null);
2035
2588
  const focusRef = React.useCallback((el) => {
2036
2589
  elementRef.current = el;
@@ -2051,25 +2604,68 @@
2051
2604
  ),
2052
2605
  [form, path.key]
2053
2606
  );
2054
- React.useEffect(
2055
- () => () => {
2056
- if ((shouldUnregister ?? form.shouldUnregister) !== false) {
2057
- removeFieldByPath(form, path);
2607
+ React.useEffect(() => {
2608
+ const spath = create$1(JSON.parse(path.key));
2609
+ let entry = uncontrolledSyncRegistry.get(form);
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
+ }
2625
+ entry.cells.set(path.key, () => ({ el: elementRef.current, path: spath }));
2626
+ return () => {
2627
+ entry.cells.delete(path.key);
2628
+ if (entry.cells.size === 0) {
2629
+ entry.off();
2630
+ uncontrolledSyncRegistry.delete(form);
2058
2631
  }
2059
- },
2060
- [path, form, shouldUnregister]
2061
- );
2632
+ };
2633
+ }, [form, path.key, uncontrolled]);
2634
+ const removalSnapshotRef = React.useRef(null);
2635
+ const teardownOnUnmount = useStageFn(() => {
2636
+ if ((shouldUnregister ?? form.shouldUnregister) === false) return;
2637
+ removalSnapshotRef.current = removeFieldForUnmount(form, path);
2638
+ });
2639
+ const restoreAfterStrictMode = useStageFn(() => {
2640
+ const snapshot = removalSnapshotRef.current;
2641
+ removalSnapshotRef.current = null;
2642
+ if (snapshot) restoreRemovedField(form, path, snapshot);
2643
+ });
2644
+ useUnmountRestore(teardownOnUnmount, restoreAfterStrictMode);
2645
+ const extract = eventToValue ?? ((e) => extractEventValue(e, { valueAsNumber, valueAsDate }));
2646
+ const inputProps = {
2647
+ name: path.key,
2648
+ ref: focusRef,
2649
+ onChange: (e) => onChange(extract(e)),
2650
+ 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) } : {}
2654
+ };
2062
2655
  return {
2063
2656
  form,
2064
2657
  value,
2065
2658
  error,
2066
2659
  errorObject,
2067
2660
  errors,
2661
+ isDirty,
2662
+ validating,
2068
2663
  onChange,
2069
2664
  onBlur,
2070
2665
  name: path.key,
2071
- disabled: formDisabled || !!disabled,
2072
- focusRef
2666
+ disabled: mergedDisabled,
2667
+ focusRef,
2668
+ inputProps
2073
2669
  };
2074
2670
  }
2075
2671
  function useField(options) {
@@ -2101,18 +2697,14 @@
2101
2697
  const contextForm = React.useContext(Context);
2102
2698
  const form = options.form || contextForm;
2103
2699
  if (!form) throw new Error("no form provided");
2700
+ const keyName = options.keyName ?? "id";
2701
+ const { rules, shouldUnregister } = options;
2104
2702
  const path = usePath(options.name);
2105
2703
  const idsRef = React.useRef([]);
2106
2704
  const getArray = React.useCallback(
2107
2705
  () => getValueByPath(form, path) || [],
2108
2706
  [form, path]
2109
2707
  );
2110
- const setArray = React.useCallback(
2111
- (arr) => {
2112
- setValueByPath(form, path, arr);
2113
- },
2114
- [form, path]
2115
- );
2116
2708
  const computeFields = React.useCallback(() => {
2117
2709
  const arr = getArray();
2118
2710
  while (idsRef.current.length < arr.length) {
@@ -2121,8 +2713,12 @@
2121
2713
  while (idsRef.current.length > arr.length) {
2122
2714
  idsRef.current.pop();
2123
2715
  }
2124
- return idsRef.current.map((id, index) => ({ id, index }));
2125
- }, [getArray, form]);
2716
+ return idsRef.current.map((id, index) => ({
2717
+ id,
2718
+ index,
2719
+ [keyName]: id
2720
+ }));
2721
+ }, [getArray, form, keyName]);
2126
2722
  const [fields, syncFields] = React.useReducer(
2127
2723
  computeFields,
2128
2724
  void 0,
@@ -2140,57 +2736,59 @@
2140
2736
  if (registry?.get(path.key) === idsRef.current) registry.delete(path.key);
2141
2737
  };
2142
2738
  }, [form, path.key]);
2739
+ const removalSnapshotRef = React.useRef(null);
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);
2750
+ useValidate(
2751
+ rules ? rulesToValidator({ ...rules, required: void 0 }) : void 0,
2752
+ path,
2753
+ form,
2754
+ {
2755
+ sync: rules && rules.required !== void 0 ? rulesToValidator({ required: rules.required }) : void 0
2756
+ }
2757
+ );
2143
2758
  const append = useStageFn((value) => {
2144
- const arr = getArray();
2145
2759
  idsRef.current.push(generateId(form));
2146
- setArray([...arr, value]);
2760
+ appendValueByPath(form, path, value);
2147
2761
  });
2148
2762
  const prepend = useStageFn((value) => {
2149
- const arr = getArray();
2150
2763
  idsRef.current.unshift(generateId(form));
2151
- setArray([value, ...arr]);
2764
+ prependValueByPath(form, path, value);
2152
2765
  });
2153
2766
  const insert = useStageFn((index, value) => {
2154
- const arr = getArray();
2767
+ if (!insertValueByPath(form, path, index, value)) return;
2155
2768
  idsRef.current.splice(index, 0, generateId(form));
2156
- const newArr = [...arr.slice(0, index), value, ...arr.slice(index)];
2157
- setArray(newArr);
2158
2769
  });
2159
- const remove = useStageFn((index) => {
2160
- const arr = getArray();
2161
- idsRef.current.splice(index, 1);
2162
- const newArr = arr.filter((_, i) => i !== index);
2163
- setArray(newArr);
2770
+ const remove = useStageFn((indices) => {
2771
+ const dropped = removeValueByPath(form, path, indices);
2772
+ for (const index of dropped) idsRef.current.splice(index, 1);
2164
2773
  });
2165
2774
  const swap = useStageFn((from, to) => {
2166
- const arr = getArray();
2775
+ if (!swapValuesByPath(form, path, from, to)) return;
2167
2776
  [idsRef.current[from], idsRef.current[to]] = [
2168
2777
  idsRef.current[to],
2169
2778
  idsRef.current[from]
2170
2779
  ];
2171
- const newArr = [...arr];
2172
- [newArr[from], newArr[to]] = [newArr[to], newArr[from]];
2173
- setArray(newArr);
2174
2780
  });
2175
2781
  const move = useStageFn((from, to) => {
2176
- const arr = getArray();
2782
+ if (!moveValueByPath(form, path, from, to)) return;
2177
2783
  const [id] = idsRef.current.splice(from, 1);
2178
2784
  idsRef.current.splice(to, 0, id);
2179
- const newArr = [...arr];
2180
- const [item] = newArr.splice(from, 1);
2181
- newArr.splice(to, 0, item);
2182
- setArray(newArr);
2183
2785
  });
2184
2786
  const replace = useStageFn((values) => {
2185
2787
  idsRef.current = values.map(() => generateId(form));
2186
- setArray([...values]);
2788
+ replaceValuesByPath(form, path, values);
2187
2789
  });
2188
2790
  const update = useStageFn((index, value) => {
2189
- const arr = getArray();
2190
- if (index < 0 || index >= arr.length) return;
2191
- const newArr = [...arr];
2192
- newArr[index] = value;
2193
- setArray(newArr);
2791
+ updateValueByPath(form, path, index, value);
2194
2792
  });
2195
2793
  return { fields, append, prepend, insert, remove, swap, move, replace, update };
2196
2794
  }
@@ -2276,7 +2874,10 @@
2276
2874
  return useFieldCore(options, Context);
2277
2875
  }
2278
2876
  function useFieldArray(options) {
2279
- return useFieldArrayCore(options, Context);
2877
+ return useFieldArrayCore(
2878
+ options,
2879
+ Context
2880
+ );
2280
2881
  }
2281
2882
  function useFieldArrayItem(options) {
2282
2883
  return useFieldArrayItemCore(options, Context);
@@ -2298,6 +2899,65 @@
2298
2899
  return group;
2299
2900
  }
2300
2901
 
2902
+ function useTransform(form, name, options = {}) {
2903
+ const path = usePath(name);
2904
+ const { toDisplay, fromDisplay, asyncDebounceMs } = options;
2905
+ const subscribeFactory = React.useCallback(
2906
+ (invalidate) => onPathEvent(
2907
+ form.emitter,
2908
+ "change",
2909
+ create$1(JSON.parse(path.key)),
2910
+ "leaf",
2911
+ invalidate
2912
+ ),
2913
+ [form.emitter, path.key]
2914
+ );
2915
+ const raw = useWatchCore(subscribeFactory, () => getValueByPath(form, path));
2916
+ const value = toDisplay ? toDisplay(raw) : raw;
2917
+ const timerRef = React.useRef(null);
2918
+ const seqRef = React.useRef(0);
2919
+ const fromDisplayRef = React.useRef(fromDisplay);
2920
+ fromDisplayRef.current = fromDisplay;
2921
+ const debounceRef = React.useRef(asyncDebounceMs ?? 0);
2922
+ debounceRef.current = asyncDebounceMs ?? 0;
2923
+ React.useEffect(
2924
+ () => () => {
2925
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
2926
+ },
2927
+ []
2928
+ );
2929
+ const onChange = React.useCallback(
2930
+ (display) => {
2931
+ const run = () => {
2932
+ const seq = ++seqRef.current;
2933
+ const transform = fromDisplayRef.current;
2934
+ const commit = (next) => userChangeByPath(form, path, next);
2935
+ if (!transform) {
2936
+ commit(display);
2937
+ return;
2938
+ }
2939
+ const result = transform(display);
2940
+ if (isPromise(result)) {
2941
+ result.then((next) => {
2942
+ if (seqRef.current === seq) commit(next);
2943
+ });
2944
+ } else if (seqRef.current === seq) {
2945
+ commit(result);
2946
+ }
2947
+ };
2948
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
2949
+ timerRef.current = null;
2950
+ if (debounceRef.current > 0) {
2951
+ timerRef.current = setTimeout(run, debounceRef.current);
2952
+ } else {
2953
+ run();
2954
+ }
2955
+ },
2956
+ [form, path]
2957
+ );
2958
+ return { value, onChange };
2959
+ }
2960
+
2301
2961
  function appendFormDataValue(fd, key, value) {
2302
2962
  if (value == null) return;
2303
2963
  if (Array.isArray(value)) {
@@ -2339,24 +2999,41 @@
2339
2999
  initialValues,
2340
3000
  values,
2341
3001
  shouldUnregister,
3002
+ validateOnMount,
3003
+ disabled,
3004
+ asyncAlways,
2342
3005
  onSubmit,
2343
3006
  onValidSubmit,
2344
3007
  onInvalidSubmit,
2345
3008
  action,
2346
3009
  shouldFocusError,
3010
+ shouldUseNativeValidation,
2347
3011
  ...props
2348
3012
  }) {
2349
- const f2 = useForm({ initialValues, values, shouldUnregister });
3013
+ const f2 = useForm({
3014
+ initialValues,
3015
+ values,
3016
+ shouldUnregister,
3017
+ validateOnMount,
3018
+ disabled,
3019
+ asyncAlways,
3020
+ shouldUseNativeValidation
3021
+ });
2350
3022
  const form = f1 || f2;
3023
+ React__namespace.useEffect(() => {
3024
+ if (disabled !== void 0) setDisabled(form, disabled);
3025
+ }, [form, disabled]);
2351
3026
  const submit = handleSubmit(form, {
2352
3027
  onSubmit,
2353
3028
  onValidSubmit,
2354
3029
  onInvalidSubmit,
2355
3030
  shouldFocusError,
2356
- onAction: action ? (values2) => action(formDataFromValues(values2)) : void 0
3031
+ shouldUseNativeValidation,
3032
+ onAction: typeof action === "function" ? (values2) => action(formDataFromValues(values2)) : void 0
2357
3033
  });
2358
3034
  const { Provider } = context ?? FormContext;
2359
- return /* @__PURE__ */ React__namespace.createElement(Provider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, noValidate: true, onSubmit: submit }));
3035
+ const nativeAction = typeof action === "string" ? action : void 0;
3036
+ return /* @__PURE__ */ React__namespace.createElement(Provider, { value: form }, /* @__PURE__ */ React__namespace.createElement("form", { ...props, action: nativeAction, noValidate: true, onSubmit: submit }));
2360
3037
  }
2361
3038
 
2362
3039
  function FormField({ children, ...options }) {
@@ -2371,19 +3048,12 @@
2371
3048
  ref.current = value;
2372
3049
  }
2373
3050
  }
2374
- function errorIdFromKey(key) {
2375
- const id = key.replace(/["'[\],\s]+/g, "-").replace(/^-+|-+$/g, "");
2376
- return id || "field";
2377
- }
2378
3051
  function ariaProps(error, fieldKey, props) {
2379
3052
  return {
2380
3053
  "aria-invalid": error ? true : props["aria-invalid"],
2381
3054
  "aria-describedby": error ? [props["aria-describedby"], errorIdFromKey(fieldKey)].filter(Boolean).join(" ") : props["aria-describedby"]
2382
3055
  };
2383
3056
  }
2384
- function fieldErrorId(name) {
2385
- return errorIdFromKey(create$1(name).key);
2386
- }
2387
3057
  const Field = React__namespace.forwardRef(
2388
3058
  ({
2389
3059
  validate,
@@ -2398,6 +3068,10 @@
2398
3068
  shouldUnregister,
2399
3069
  rules,
2400
3070
  validateDebounce,
3071
+ validateOnMount,
3072
+ valueAsNumber,
3073
+ valueAsDate,
3074
+ asyncAlways,
2401
3075
  disabled,
2402
3076
  delayError,
2403
3077
  mode,
@@ -2406,6 +3080,10 @@
2406
3080
  }, ref) => {
2407
3081
  const innerRef = React__namespace.useRef(null);
2408
3082
  const [nativeInvalidCount, setNativeInvalidCount] = React__namespace.useState(0);
3083
+ const contextForm = React__namespace.useContext(FormContext);
3084
+ const resolvedForm = formProp ?? contextForm;
3085
+ const validateOption = validate;
3086
+ const validateWrapped = validateOption && hasStandardProps(validateOption) ? schemaToFieldValidator(validateOption) : validateOption;
2409
3087
  const {
2410
3088
  value,
2411
3089
  onChange,
@@ -2421,22 +3099,26 @@
2421
3099
  shouldUnregister,
2422
3100
  rules,
2423
3101
  validateDebounce,
3102
+ validateOnMount,
2424
3103
  delayError,
2425
3104
  disabled,
3105
+ asyncAlways,
2426
3106
  mode,
2427
3107
  // File inputs cannot be value-controlled at all — force the
2428
3108
  // uncontrolled path so no `value` prop ever reaches the element.
2429
3109
  uncontrolled: uncontrolled || props.type === "file",
2430
3110
  validate: (...params) => {
2431
- const el = innerRef.current;
2432
- if (el && typeof el.checkValidity === "function") {
2433
- el.setCustomValidity("");
2434
- if (el.checkValidity() === false) {
2435
- setNativeInvalidCount((count) => count + 1);
2436
- return void 0;
3111
+ if (resolvedForm?.shouldUseNativeValidation !== false) {
3112
+ const el = innerRef.current;
3113
+ if (el && typeof el.checkValidity === "function") {
3114
+ el.setCustomValidity("");
3115
+ if (el.checkValidity() === false) {
3116
+ setNativeInvalidCount((count) => count + 1);
3117
+ return void 0;
3118
+ }
2437
3119
  }
2438
3120
  }
2439
- if (validate) return validate(...params);
3121
+ if (validateWrapped) return validateWrapped(...params);
2440
3122
  }
2441
3123
  });
2442
3124
  const mergedRef = React__namespace.useCallback(
@@ -2462,12 +3144,14 @@
2462
3144
  if (nativeInvalidCount > 0) innerRef.current?.reportValidity();
2463
3145
  }, [nativeInvalidCount]);
2464
3146
  const isFile = props.type === "file";
2465
- const toValue = eventToValue ?? (isFile ? (e) => e.target.files : (e) => e.target.value);
3147
+ const toValue = eventToValue ?? ((e) => extractEventValue(e, { valueAsNumber, valueAsDate }));
2466
3148
  const valueProps = valueToProps ? valueToProps(value) : isFile ? {} : uncontrolled ? { defaultValue: value } : { value };
2467
3149
  const errorId = errorIdFromKey(fieldKey);
3150
+ const constraintAttrs = rules ? rulesToConstraintAttrs(rules) : void 0;
2468
3151
  return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement(
2469
3152
  Component,
2470
3153
  {
3154
+ ...constraintAttrs,
2471
3155
  ...props,
2472
3156
  name: fieldKey,
2473
3157
  onBlur,
@@ -2490,6 +3174,8 @@
2490
3174
  validate,
2491
3175
  rules,
2492
3176
  validateDebounce,
3177
+ validateOnMount,
3178
+ asyncAlways,
2493
3179
  disabled,
2494
3180
  delayError,
2495
3181
  mode,
@@ -2510,13 +3196,17 @@
2510
3196
  validate,
2511
3197
  rules,
2512
3198
  validateDebounce,
3199
+ validateOnMount,
3200
+ asyncAlways,
2513
3201
  delayError,
2514
3202
  disabled,
2515
3203
  mode
2516
3204
  });
3205
+ const constraintAttrs = rules ? rulesToConstraintAttrs(rules) : void 0;
2517
3206
  return /* @__PURE__ */ React__namespace.createElement(
2518
3207
  "input",
2519
3208
  {
3209
+ ...constraintAttrs,
2520
3210
  ...props,
2521
3211
  name: fieldKey,
2522
3212
  onBlur,
@@ -2545,6 +3235,8 @@
2545
3235
  validate,
2546
3236
  rules,
2547
3237
  validateDebounce,
3238
+ validateOnMount,
3239
+ asyncAlways,
2548
3240
  disabled,
2549
3241
  delayError,
2550
3242
  mode,
@@ -2565,13 +3257,17 @@
2565
3257
  validate,
2566
3258
  rules,
2567
3259
  validateDebounce,
3260
+ validateOnMount,
3261
+ asyncAlways,
2568
3262
  delayError,
2569
3263
  disabled,
2570
3264
  mode
2571
3265
  });
3266
+ const constraintAttrs = rules ? rulesToConstraintAttrs(rules) : void 0;
2572
3267
  return /* @__PURE__ */ React__namespace.createElement(
2573
3268
  "select",
2574
3269
  {
3270
+ ...constraintAttrs,
2575
3271
  ...props,
2576
3272
  name: fieldKey,
2577
3273
  onBlur,
@@ -2600,18 +3296,25 @@
2600
3296
  exports.FormProvider = FormProvider;
2601
3297
  exports.Select = Select;
2602
3298
  exports.VALIDATION_OUTCOME = VALIDATION_OUTCOME;
3299
+ exports.appendValue = appendValue;
3300
+ exports.appendValueByPath = appendValueByPath;
2603
3301
  exports.changeValue = changeValue;
2604
3302
  exports.changeValueByPath = changeValueByPath;
2605
3303
  exports.clearErrors = clearErrors;
3304
+ exports.clearServerErrors = clearServerErrors;
2606
3305
  exports.createForm = create;
2607
3306
  exports.createFormContext = createFormContext;
3307
+ exports.dottedKeyToFieldPath = dottedKeyToFieldPath;
2608
3308
  exports.emitChangeByPath = emitChangeByPath;
2609
3309
  exports.ensureValidate = ensureValidate;
2610
3310
  exports.fieldErrorId = fieldErrorId;
3311
+ exports.fieldPathToDottedKey = fieldPathToDottedKey;
2611
3312
  exports.getDirtyFields = getDirtyFields;
2612
3313
  exports.getError = getError;
2613
3314
  exports.getErrorByPath = getErrorByPath;
2614
3315
  exports.getErrors = getErrors;
3316
+ exports.getErrorsRecord = getErrorsRecord;
3317
+ exports.getErrorsTree = getErrorsTree;
2615
3318
  exports.getFieldErrors = getFieldErrors;
2616
3319
  exports.getFieldErrorsByPath = getFieldErrorsByPath;
2617
3320
  exports.getFieldState = getFieldState;
@@ -2625,17 +3328,30 @@
2625
3328
  exports.hasTouched = hasTouched;
2626
3329
  exports.hasTouchedByPath = hasTouchedByPath;
2627
3330
  exports.incrementSubmitCount = incrementSubmitCount;
3331
+ exports.insertValue = insertValue;
3332
+ exports.insertValueByPath = insertValueByPath;
2628
3333
  exports.isDirty = isDirty;
3334
+ exports.isFieldDirtyByPath = isFieldDirtyByPath;
2629
3335
  exports.isTouched = isTouched;
3336
+ exports.moveValue = moveValue;
3337
+ exports.moveValueByPath = moveValueByPath;
3338
+ exports.prependValue = prependValue;
3339
+ exports.prependValueByPath = prependValueByPath;
3340
+ exports.registerField = registerField;
2630
3341
  exports.registerFieldMode = registerFieldMode;
2631
3342
  exports.registerFieldValidateDeps = registerFieldValidateDeps;
2632
3343
  exports.registerValidatorByPath = registerValidatorByPath;
2633
3344
  exports.removeField = removeField;
2634
3345
  exports.removeFieldByPath = removeFieldByPath;
3346
+ exports.removeValue = removeValue;
3347
+ exports.removeValueByPath = removeValueByPath;
3348
+ exports.replaceValues = replaceValues;
3349
+ exports.replaceValuesByPath = replaceValuesByPath;
2635
3350
  exports.reset = reset;
2636
3351
  exports.resetField = resetField;
2637
3352
  exports.revalidateDependentsOnChange = revalidateDependentsOnChange;
2638
3353
  exports.revalidateFormOnChange = revalidateFormOnChange;
3354
+ exports.runFormValidate = runFormValidate;
2639
3355
  exports.seedValueByPath = seedValueByPath;
2640
3356
  exports.setDisabled = setDisabled;
2641
3357
  exports.setError = setError;
@@ -2644,6 +3360,7 @@
2644
3360
  exports.setInitialValues = setInitialValues;
2645
3361
  exports.setIsSubmitting = setIsSubmitting;
2646
3362
  exports.setServerErrors = setServerErrors;
3363
+ exports.setStatus = setStatus;
2647
3364
  exports.setSubmitSuccessful = setSubmitSuccessful;
2648
3365
  exports.setTouched = setTouched;
2649
3366
  exports.setTouchedByPath = setTouchedByPath;
@@ -2651,15 +3368,21 @@
2651
3368
  exports.setValue = setValue;
2652
3369
  exports.setValueByPath = setValueByPath;
2653
3370
  exports.subscribe = subscribe;
3371
+ exports.swapValues = swapValues;
3372
+ exports.swapValuesByPath = swapValuesByPath;
2654
3373
  exports.trigger = trigger;
2655
3374
  exports.unregisterFieldMode = unregisterFieldMode;
2656
3375
  exports.unregisterFieldValidateDeps = unregisterFieldValidateDeps;
2657
3376
  exports.unsetValidatingByPath = unsetValidatingByPath;
3377
+ exports.updateValue = updateValue;
3378
+ exports.updateValueByPath = updateValueByPath;
2658
3379
  exports.useCanSubmit = useCanSubmit;
2659
3380
  exports.useCheckboxGroupContext = useCheckboxGroupContext;
2660
3381
  exports.useDirtyFields = useDirtyFields;
2661
3382
  exports.useError = useError;
2662
3383
  exports.useErrorByPath = useErrorByPath;
3384
+ exports.useErrors = useErrors;
3385
+ exports.useErrorsTree = useErrorsTree;
2663
3386
  exports.useField = useField;
2664
3387
  exports.useFieldArray = useFieldArray;
2665
3388
  exports.useFieldArrayItem = useFieldArrayItem;
@@ -2672,22 +3395,29 @@
2672
3395
  exports.useFormState = useFormState;
2673
3396
  exports.useHasErrors = useHasErrors;
2674
3397
  exports.useIsDirty = useIsDirty;
3398
+ exports.useIsFieldDirty = useIsFieldDirty;
3399
+ exports.useIsFieldDirtyByPath = useIsFieldDirtyByPath;
2675
3400
  exports.useIsLoading = useIsLoading;
2676
3401
  exports.useIsSubmitSuccessful = useIsSubmitSuccessful;
2677
3402
  exports.useIsSubmitting = useIsSubmitting;
2678
3403
  exports.useIsValid = useIsValid;
2679
3404
  exports.useIsValidating = useIsValidating;
3405
+ exports.useStatus = useStatus;
3406
+ exports.useStore = useStore;
2680
3407
  exports.useSubmitCount = useSubmitCount;
2681
3408
  exports.useTouched = useTouched;
2682
3409
  exports.useTouchedByPath = useTouchedByPath;
2683
3410
  exports.useTouchedFields = useTouchedFields;
3411
+ exports.useTransform = useTransform;
2684
3412
  exports.useValue = useValue;
2685
3413
  exports.useValueByPath = useValueByPath;
3414
+ exports.useValues = useValues;
2686
3415
  exports.useWatch = useWatch;
2687
3416
  exports.useWatchCore = useWatchCore;
2688
3417
  exports.userBlur = userBlur;
2689
3418
  exports.userChangeByPath = userChangeByPath;
2690
3419
  exports.validate = validate;
3420
+ exports.watch = watch;
2691
3421
 
2692
3422
  }));
2693
3423
  //# sourceMappingURL=index.umd.js.map