react-hook-form 7.32.2 → 7.34.0-next.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 (54) hide show
  1. package/README.md +7 -0
  2. package/dist/__typetest__/__fixtures__/index.d.ts +5 -0
  3. package/dist/__typetest__/__fixtures__/index.d.ts.map +1 -0
  4. package/dist/__typetest__/__fixtures__/pathString.d.ts +4 -0
  5. package/dist/__typetest__/__fixtures__/pathString.d.ts.map +1 -0
  6. package/dist/__typetest__/__fixtures__/traversable.d.ts +14 -0
  7. package/dist/__typetest__/__fixtures__/traversable.d.ts.map +1 -0
  8. package/dist/__typetest__/__fixtures__/tuple.d.ts +15 -0
  9. package/dist/__typetest__/__fixtures__/tuple.d.ts.map +1 -0
  10. package/dist/__typetest__/__fixtures__/type.d.ts +12 -0
  11. package/dist/__typetest__/__fixtures__/type.d.ts.map +1 -0
  12. package/dist/__typetest__/errors.test-d.d.ts +2 -0
  13. package/dist/__typetest__/errors.test-d.d.ts.map +1 -0
  14. package/dist/__typetest__/form.test-d.d.ts +2 -0
  15. package/dist/__typetest__/form.test-d.d.ts.map +1 -0
  16. package/dist/__typetest__/path/common.test-d.d.ts +2 -0
  17. package/dist/__typetest__/path/common.test-d.d.ts.map +1 -0
  18. package/dist/__typetest__/path/eager.test-d.d.ts +2 -0
  19. package/dist/__typetest__/path/eager.test-d.d.ts.map +1 -0
  20. package/dist/__typetest__/util.test-d.d.ts +2 -0
  21. package/dist/__typetest__/util.test-d.d.ts.map +1 -0
  22. package/dist/index.cjs.js +1 -1
  23. package/dist/index.cjs.js.map +1 -1
  24. package/dist/index.esm.mjs +299 -260
  25. package/dist/index.esm.mjs.map +1 -1
  26. package/dist/index.umd.js +1 -1
  27. package/dist/index.umd.js.map +1 -1
  28. package/dist/logic/createFormControl.d.ts.map +1 -1
  29. package/dist/logic/schemaErrorLookup.d.ts +1 -1
  30. package/dist/logic/schemaErrorLookup.d.ts.map +1 -1
  31. package/dist/logic/updateFieldArrayRootError.d.ts +4 -0
  32. package/dist/logic/updateFieldArrayRootError.d.ts.map +1 -0
  33. package/dist/logic/validateField.d.ts +1 -1
  34. package/dist/logic/validateField.d.ts.map +1 -1
  35. package/dist/types/controller.d.ts +3 -3
  36. package/dist/types/controller.d.ts.map +1 -1
  37. package/dist/types/errors.d.ts +9 -2
  38. package/dist/types/errors.d.ts.map +1 -1
  39. package/dist/types/fieldArray.d.ts +8 -6
  40. package/dist/types/fieldArray.d.ts.map +1 -1
  41. package/dist/types/form.d.ts +17 -11
  42. package/dist/types/form.d.ts.map +1 -1
  43. package/dist/types/resolvers.d.ts +3 -3
  44. package/dist/types/resolvers.d.ts.map +1 -1
  45. package/dist/types/utils.d.ts +3 -0
  46. package/dist/types/utils.d.ts.map +1 -1
  47. package/dist/useController.d.ts.map +1 -1
  48. package/dist/useFieldArray.d.ts.map +1 -1
  49. package/dist/useForm.d.ts +2 -2
  50. package/dist/useForm.d.ts.map +1 -1
  51. package/dist/useWatch.d.ts +2 -2
  52. package/dist/useWatch.d.ts.map +1 -1
  53. package/dist/utils/unset.d.ts.map +1 -1
  54. package/package.json +31 -26
@@ -124,7 +124,7 @@ const useFormContext = () => React.useContext(HookFormContext);
124
124
  */
125
125
  const FormProvider = (props) => {
126
126
  const { children, ...data } = props;
127
- return (React.createElement(HookFormContext.Provider, { value: data }, props.children));
127
+ return (React.createElement(HookFormContext.Provider, { value: data }, children));
128
128
  };
129
129
 
130
130
  var getProxyFormState = (formState, _proxyFormState, localProxyFormState, isRoot = true) => {
@@ -409,6 +409,7 @@ function useController(props) {
409
409
  if (elm && field && elm.focus) {
410
410
  field._f.ref = {
411
411
  focus: () => elm.focus(),
412
+ select: () => elm.select(),
412
413
  setCustomValidity: (message) => elm.setCustomValidity(message),
413
414
  reportValidity: () => elm.reportValidity(),
414
415
  };
@@ -554,6 +555,243 @@ var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
554
555
  [..._names.watch].some((watchName) => name.startsWith(watchName) &&
555
556
  /^\.\w+/.test(name.slice(watchName.length))));
556
557
 
558
+ var updateFieldArrayRootError = (errors, error, name) => {
559
+ const fieldArrayErrors = compact(get(errors, name));
560
+ set(fieldArrayErrors, 'root', error[name]);
561
+ set(errors, name, fieldArrayErrors);
562
+ return errors;
563
+ };
564
+
565
+ var isBoolean = (value) => typeof value === 'boolean';
566
+
567
+ var isFileInput = (element) => element.type === 'file';
568
+
569
+ var isMessage = (value) => isString(value) || React.isValidElement(value);
570
+
571
+ var isRadioInput = (element) => element.type === 'radio';
572
+
573
+ var isRegex = (value) => value instanceof RegExp;
574
+
575
+ const defaultResult = {
576
+ value: false,
577
+ isValid: false,
578
+ };
579
+ const validResult = { value: true, isValid: true };
580
+ var getCheckboxValue = (options) => {
581
+ if (Array.isArray(options)) {
582
+ if (options.length > 1) {
583
+ const values = options
584
+ .filter((option) => option && option.checked && !option.disabled)
585
+ .map((option) => option.value);
586
+ return { value: values, isValid: !!values.length };
587
+ }
588
+ return options[0].checked && !options[0].disabled
589
+ ? // @ts-expect-error expected to work in the browser
590
+ options[0].attributes && !isUndefined(options[0].attributes.value)
591
+ ? isUndefined(options[0].value) || options[0].value === ''
592
+ ? validResult
593
+ : { value: options[0].value, isValid: true }
594
+ : validResult
595
+ : defaultResult;
596
+ }
597
+ return defaultResult;
598
+ };
599
+
600
+ const defaultReturn = {
601
+ isValid: false,
602
+ value: null,
603
+ };
604
+ var getRadioValue = (options) => Array.isArray(options)
605
+ ? options.reduce((previous, option) => option && option.checked && !option.disabled
606
+ ? {
607
+ isValid: true,
608
+ value: option.value,
609
+ }
610
+ : previous, defaultReturn)
611
+ : defaultReturn;
612
+
613
+ function getValidateError(result, ref, type = 'validate') {
614
+ if (isMessage(result) ||
615
+ (Array.isArray(result) && result.every(isMessage)) ||
616
+ (isBoolean(result) && !result)) {
617
+ return {
618
+ type,
619
+ message: isMessage(result) ? result : '',
620
+ ref,
621
+ };
622
+ }
623
+ }
624
+
625
+ var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
626
+ ? validationData
627
+ : {
628
+ value: validationData,
629
+ message: '',
630
+ };
631
+
632
+ var validateField = async (field, inputValue, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
633
+ const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, disabled, } = field._f;
634
+ if (!mount || disabled) {
635
+ return {};
636
+ }
637
+ const inputRef = refs ? refs[0] : ref;
638
+ const setCustomValidity = (message) => {
639
+ if (shouldUseNativeValidation && inputRef.reportValidity) {
640
+ inputRef.setCustomValidity(isBoolean(message) ? '' : message || ' ');
641
+ inputRef.reportValidity();
642
+ }
643
+ };
644
+ const error = {};
645
+ const isRadio = isRadioInput(ref);
646
+ const isCheckBox = isCheckBoxInput(ref);
647
+ const isRadioOrCheckbox = isRadio || isCheckBox;
648
+ const isEmpty = ((valueAsNumber || isFileInput(ref)) && !ref.value) ||
649
+ inputValue === '' ||
650
+ (Array.isArray(inputValue) && !inputValue.length);
651
+ const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error);
652
+ const getMinMaxMessage = (exceedMax, maxLengthMessage, minLengthMessage, maxType = INPUT_VALIDATION_RULES.maxLength, minType = INPUT_VALIDATION_RULES.minLength) => {
653
+ const message = exceedMax ? maxLengthMessage : minLengthMessage;
654
+ error[name] = {
655
+ type: exceedMax ? maxType : minType,
656
+ message,
657
+ ref,
658
+ ...appendErrorsCurry(exceedMax ? maxType : minType, message),
659
+ };
660
+ };
661
+ if (isFieldArray
662
+ ? Array.isArray(inputValue) && !inputValue.length
663
+ : required &&
664
+ ((!isRadioOrCheckbox && (isEmpty || isNullOrUndefined(inputValue))) ||
665
+ (isBoolean(inputValue) && !inputValue) ||
666
+ (isCheckBox && !getCheckboxValue(refs).isValid) ||
667
+ (isRadio && !getRadioValue(refs).isValid))) {
668
+ const { value, message } = isMessage(required)
669
+ ? { value: !!required, message: required }
670
+ : getValueAndMessage(required);
671
+ if (value) {
672
+ error[name] = {
673
+ type: INPUT_VALIDATION_RULES.required,
674
+ message,
675
+ ref: inputRef,
676
+ ...appendErrorsCurry(INPUT_VALIDATION_RULES.required, message),
677
+ };
678
+ if (!validateAllFieldCriteria) {
679
+ setCustomValidity(message);
680
+ return error;
681
+ }
682
+ }
683
+ }
684
+ if (!isEmpty && (!isNullOrUndefined(min) || !isNullOrUndefined(max))) {
685
+ let exceedMax;
686
+ let exceedMin;
687
+ const maxOutput = getValueAndMessage(max);
688
+ const minOutput = getValueAndMessage(min);
689
+ if (!isNullOrUndefined(inputValue) && !isNaN(inputValue)) {
690
+ const valueNumber = ref.valueAsNumber || +inputValue;
691
+ if (!isNullOrUndefined(maxOutput.value)) {
692
+ exceedMax = valueNumber > maxOutput.value;
693
+ }
694
+ if (!isNullOrUndefined(minOutput.value)) {
695
+ exceedMin = valueNumber < minOutput.value;
696
+ }
697
+ }
698
+ else {
699
+ const valueDate = ref.valueAsDate || new Date(inputValue);
700
+ if (isString(maxOutput.value)) {
701
+ exceedMax = valueDate > new Date(maxOutput.value);
702
+ }
703
+ if (isString(minOutput.value)) {
704
+ exceedMin = valueDate < new Date(minOutput.value);
705
+ }
706
+ }
707
+ if (exceedMax || exceedMin) {
708
+ getMinMaxMessage(!!exceedMax, maxOutput.message, minOutput.message, INPUT_VALIDATION_RULES.max, INPUT_VALIDATION_RULES.min);
709
+ if (!validateAllFieldCriteria) {
710
+ setCustomValidity(error[name].message);
711
+ return error;
712
+ }
713
+ }
714
+ }
715
+ if ((maxLength || minLength) &&
716
+ !isEmpty &&
717
+ (isString(inputValue) || (isFieldArray && Array.isArray(inputValue)))) {
718
+ const maxLengthOutput = getValueAndMessage(maxLength);
719
+ const minLengthOutput = getValueAndMessage(minLength);
720
+ const exceedMax = !isNullOrUndefined(maxLengthOutput.value) &&
721
+ inputValue.length > maxLengthOutput.value;
722
+ const exceedMin = !isNullOrUndefined(minLengthOutput.value) &&
723
+ inputValue.length < minLengthOutput.value;
724
+ if (exceedMax || exceedMin) {
725
+ getMinMaxMessage(exceedMax, maxLengthOutput.message, minLengthOutput.message);
726
+ if (!validateAllFieldCriteria) {
727
+ setCustomValidity(error[name].message);
728
+ return error;
729
+ }
730
+ }
731
+ }
732
+ if (pattern && !isEmpty && isString(inputValue)) {
733
+ const { value: patternValue, message } = getValueAndMessage(pattern);
734
+ if (isRegex(patternValue) && !inputValue.match(patternValue)) {
735
+ error[name] = {
736
+ type: INPUT_VALIDATION_RULES.pattern,
737
+ message,
738
+ ref,
739
+ ...appendErrorsCurry(INPUT_VALIDATION_RULES.pattern, message),
740
+ };
741
+ if (!validateAllFieldCriteria) {
742
+ setCustomValidity(message);
743
+ return error;
744
+ }
745
+ }
746
+ }
747
+ if (validate) {
748
+ if (isFunction(validate)) {
749
+ const result = await validate(inputValue);
750
+ const validateError = getValidateError(result, inputRef);
751
+ if (validateError) {
752
+ error[name] = {
753
+ ...validateError,
754
+ ...appendErrorsCurry(INPUT_VALIDATION_RULES.validate, validateError.message),
755
+ };
756
+ if (!validateAllFieldCriteria) {
757
+ setCustomValidity(validateError.message);
758
+ return error;
759
+ }
760
+ }
761
+ }
762
+ else if (isObject(validate)) {
763
+ let validationResult = {};
764
+ for (const key in validate) {
765
+ if (!isEmptyObject(validationResult) && !validateAllFieldCriteria) {
766
+ break;
767
+ }
768
+ const validateError = getValidateError(await validate[key](inputValue), inputRef, key);
769
+ if (validateError) {
770
+ validationResult = {
771
+ ...validateError,
772
+ ...appendErrorsCurry(key, validateError.message),
773
+ };
774
+ setCustomValidity(validateError.message);
775
+ if (validateAllFieldCriteria) {
776
+ error[name] = validationResult;
777
+ }
778
+ }
779
+ }
780
+ if (!isEmptyObject(validationResult)) {
781
+ error[name] = {
782
+ ref: inputRef,
783
+ ...validationResult,
784
+ };
785
+ if (!validateAllFieldCriteria) {
786
+ return error;
787
+ }
788
+ }
789
+ }
790
+ }
791
+ setCustomValidity(true);
792
+ return error;
793
+ };
794
+
557
795
  function append(data, value) {
558
796
  return [...data, ...convertToArrayPayload(value)];
559
797
  }
@@ -590,6 +828,14 @@ function cloneObject(data) {
590
828
 
591
829
  var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
592
830
 
831
+ var getValidationModes = (mode) => ({
832
+ isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
833
+ isOnBlur: mode === VALIDATION_MODE.onBlur,
834
+ isOnChange: mode === VALIDATION_MODE.onChange,
835
+ isOnAll: mode === VALIDATION_MODE.all,
836
+ isOnTouch: mode === VALIDATION_MODE.onTouched,
837
+ });
838
+
593
839
  function insert(data, index, value) {
594
840
  return [
595
841
  ...data.slice(0, index),
@@ -638,6 +884,14 @@ function baseGet(object, updatePath) {
638
884
  }
639
885
  return object;
640
886
  }
887
+ function isEmptyArray(obj) {
888
+ for (const key in obj) {
889
+ if (!isUndefined(obj[key])) {
890
+ return false;
891
+ }
892
+ }
893
+ return true;
894
+ }
641
895
  function unset(object, path) {
642
896
  const updatePath = isKey(path) ? [path] : stringToPath(path);
643
897
  const childObject = updatePath.length == 1 ? object : baseGet(object, updatePath);
@@ -659,8 +913,7 @@ function unset(object, path) {
659
913
  objectRef = objectRef ? objectRef[item] : object[item];
660
914
  if (currentPathsLength === index &&
661
915
  ((isObject(objectRef) && isEmptyObject(objectRef)) ||
662
- (Array.isArray(objectRef) &&
663
- !objectRef.filter((data) => !isUndefined(data)).length))) {
916
+ (Array.isArray(objectRef) && isEmptyArray(objectRef)))) {
664
917
  previousObjRef ? delete previousObjRef[item] : delete object[item];
665
918
  }
666
919
  previousObjRef = objectRef;
@@ -722,7 +975,9 @@ function useFieldArray(props) {
722
975
  _name.current = name;
723
976
  _fieldIds.current = fields;
724
977
  control._names.array.add(name);
725
- const callback = React.useCallback(({ values, name: fieldArrayName }) => {
978
+ props.rules &&
979
+ control.register(name, props.rules);
980
+ const callback = React.useCallback(({ values, name: fieldArrayName, }) => {
726
981
  if (fieldArrayName === _name.current || !fieldArrayName) {
727
982
  const fieldValues = get(values, _name.current, []);
728
983
  setFields(fieldValues);
@@ -824,18 +1079,33 @@ function useFieldArray(props) {
824
1079
  control._stateFlags.action = false;
825
1080
  isWatched(name, control._names) && control._subjects.state.next({});
826
1081
  if (_actioned.current) {
827
- control._executeSchema([name]).then((result) => {
828
- const error = get(result.errors, name);
829
- const existingError = get(control._formState.errors, name);
830
- if (existingError ? !error && existingError.type : error && error.type) {
831
- error
832
- ? set(control._formState.errors, name, error)
833
- : unset(control._formState.errors, name);
834
- control._subjects.state.next({
835
- errors: control._formState.errors,
836
- });
1082
+ if (control._options.resolver) {
1083
+ control._executeSchema([name]).then((result) => {
1084
+ const error = get(result.errors, name);
1085
+ const existingError = get(control._formState.errors, name);
1086
+ if (existingError ? !error && existingError.type : error && error.type) {
1087
+ error
1088
+ ? set(control._formState.errors, name, error)
1089
+ : unset(control._formState.errors, name);
1090
+ control._subjects.state.next({
1091
+ errors: control._formState.errors,
1092
+ });
1093
+ }
1094
+ });
1095
+ }
1096
+ else {
1097
+ const field = get(control._fields, name);
1098
+ const validationModeBeforeSubmit = getValidationModes(control._options.mode);
1099
+ if ((!validationModeBeforeSubmit.isOnSubmit ||
1100
+ control._formState.isSubmitted) &&
1101
+ field &&
1102
+ field._f) {
1103
+ validateField(field, get(control._formValues, name), control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
1104
+ control._subjects.state.next({
1105
+ errors: updateFieldArrayRootError(control._formState.errors, error, name),
1106
+ }));
837
1107
  }
838
- });
1108
+ }
839
1109
  }
840
1110
  control._subjects.watch.next({
841
1111
  name,
@@ -930,18 +1200,6 @@ function deepEqual(object1, object2) {
930
1200
  return true;
931
1201
  }
932
1202
 
933
- var getValidationModes = (mode) => ({
934
- isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
935
- isOnBlur: mode === VALIDATION_MODE.onBlur,
936
- isOnChange: mode === VALIDATION_MODE.onChange,
937
- isOnAll: mode === VALIDATION_MODE.all,
938
- isOnTouch: mode === VALIDATION_MODE.onTouched,
939
- });
940
-
941
- var isBoolean = (value) => typeof value === 'boolean';
942
-
943
- var isFileInput = (element) => element.type === 'file';
944
-
945
1203
  var isHTMLElement = (value) => {
946
1204
  const owner = value ? value.ownerDocument : 0;
947
1205
  const ElementClass = owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement;
@@ -950,8 +1208,6 @@ var isHTMLElement = (value) => {
950
1208
 
951
1209
  var isMultipleSelect = (element) => element.type === `select-multiple`;
952
1210
 
953
- var isRadioInput = (element) => element.type === 'radio';
954
-
955
1211
  var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
956
1212
 
957
1213
  var live = (ref) => isHTMLElement(ref) && ref.isConnected;
@@ -997,31 +1253,6 @@ function getDirtyFieldsFromDefaultValues(data, formValues, dirtyFieldsFromValues
997
1253
  }
998
1254
  var getDirtyFields = (defaultValues, formValues) => getDirtyFieldsFromDefaultValues(defaultValues, formValues, markFieldsDirty(formValues));
999
1255
 
1000
- const defaultResult = {
1001
- value: false,
1002
- isValid: false,
1003
- };
1004
- const validResult = { value: true, isValid: true };
1005
- var getCheckboxValue = (options) => {
1006
- if (Array.isArray(options)) {
1007
- if (options.length > 1) {
1008
- const values = options
1009
- .filter((option) => option && option.checked && !option.disabled)
1010
- .map((option) => option.value);
1011
- return { value: values, isValid: !!values.length };
1012
- }
1013
- return options[0].checked && !options[0].disabled
1014
- ? // @ts-expect-error expected to work in the browser
1015
- options[0].attributes && !isUndefined(options[0].attributes.value)
1016
- ? isUndefined(options[0].value) || options[0].value === ''
1017
- ? validResult
1018
- : { value: options[0].value, isValid: true }
1019
- : validResult
1020
- : defaultResult;
1021
- }
1022
- return defaultResult;
1023
- };
1024
-
1025
1256
  var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
1026
1257
  ? value
1027
1258
  : valueAsNumber
@@ -1034,19 +1265,6 @@ var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isU
1034
1265
  ? setValueAs(value)
1035
1266
  : value;
1036
1267
 
1037
- const defaultReturn = {
1038
- isValid: false,
1039
- value: null,
1040
- };
1041
- var getRadioValue = (options) => Array.isArray(options)
1042
- ? options.reduce((previous, option) => option && option.checked && !option.disabled
1043
- ? {
1044
- isValid: true,
1045
- value: option.value,
1046
- }
1047
- : previous, defaultReturn)
1048
- : defaultReturn;
1049
-
1050
1268
  function getFieldValue(_f) {
1051
1269
  const ref = _f.ref;
1052
1270
  if (_f.refs ? _f.refs.every((ref) => ref.disabled) : ref.disabled) {
@@ -1081,8 +1299,6 @@ var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeVal
1081
1299
  };
1082
1300
  };
1083
1301
 
1084
- var isRegex = (value) => value instanceof RegExp;
1085
-
1086
1302
  var getRuleValue = (rule) => isUndefined(rule)
1087
1303
  ? undefined
1088
1304
  : isRegex(rule)
@@ -1149,186 +1365,6 @@ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode)
1149
1365
 
1150
1366
  var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
1151
1367
 
1152
- var isMessage = (value) => isString(value) || React.isValidElement(value);
1153
-
1154
- function getValidateError(result, ref, type = 'validate') {
1155
- if (isMessage(result) ||
1156
- (Array.isArray(result) && result.every(isMessage)) ||
1157
- (isBoolean(result) && !result)) {
1158
- return {
1159
- type,
1160
- message: isMessage(result) ? result : '',
1161
- ref,
1162
- };
1163
- }
1164
- }
1165
-
1166
- var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
1167
- ? validationData
1168
- : {
1169
- value: validationData,
1170
- message: '',
1171
- };
1172
-
1173
- var validateField = async (field, inputValue, validateAllFieldCriteria, shouldUseNativeValidation) => {
1174
- const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, disabled, } = field._f;
1175
- if (!mount || disabled) {
1176
- return {};
1177
- }
1178
- const inputRef = refs ? refs[0] : ref;
1179
- const setCustomValidity = (message) => {
1180
- if (shouldUseNativeValidation && inputRef.reportValidity) {
1181
- inputRef.setCustomValidity(isBoolean(message) ? '' : message || ' ');
1182
- inputRef.reportValidity();
1183
- }
1184
- };
1185
- const error = {};
1186
- const isRadio = isRadioInput(ref);
1187
- const isCheckBox = isCheckBoxInput(ref);
1188
- const isRadioOrCheckbox = isRadio || isCheckBox;
1189
- const isEmpty = ((valueAsNumber || isFileInput(ref)) && !ref.value) ||
1190
- inputValue === '' ||
1191
- (Array.isArray(inputValue) && !inputValue.length);
1192
- const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error);
1193
- const getMinMaxMessage = (exceedMax, maxLengthMessage, minLengthMessage, maxType = INPUT_VALIDATION_RULES.maxLength, minType = INPUT_VALIDATION_RULES.minLength) => {
1194
- const message = exceedMax ? maxLengthMessage : minLengthMessage;
1195
- error[name] = {
1196
- type: exceedMax ? maxType : minType,
1197
- message,
1198
- ref,
1199
- ...appendErrorsCurry(exceedMax ? maxType : minType, message),
1200
- };
1201
- };
1202
- if (required &&
1203
- ((!isRadioOrCheckbox && (isEmpty || isNullOrUndefined(inputValue))) ||
1204
- (isBoolean(inputValue) && !inputValue) ||
1205
- (isCheckBox && !getCheckboxValue(refs).isValid) ||
1206
- (isRadio && !getRadioValue(refs).isValid))) {
1207
- const { value, message } = isMessage(required)
1208
- ? { value: !!required, message: required }
1209
- : getValueAndMessage(required);
1210
- if (value) {
1211
- error[name] = {
1212
- type: INPUT_VALIDATION_RULES.required,
1213
- message,
1214
- ref: inputRef,
1215
- ...appendErrorsCurry(INPUT_VALIDATION_RULES.required, message),
1216
- };
1217
- if (!validateAllFieldCriteria) {
1218
- setCustomValidity(message);
1219
- return error;
1220
- }
1221
- }
1222
- }
1223
- if (!isEmpty && (!isNullOrUndefined(min) || !isNullOrUndefined(max))) {
1224
- let exceedMax;
1225
- let exceedMin;
1226
- const maxOutput = getValueAndMessage(max);
1227
- const minOutput = getValueAndMessage(min);
1228
- if (!isNullOrUndefined(inputValue) && !isNaN(inputValue)) {
1229
- const valueNumber = ref.valueAsNumber || +inputValue;
1230
- if (!isNullOrUndefined(maxOutput.value)) {
1231
- exceedMax = valueNumber > maxOutput.value;
1232
- }
1233
- if (!isNullOrUndefined(minOutput.value)) {
1234
- exceedMin = valueNumber < minOutput.value;
1235
- }
1236
- }
1237
- else {
1238
- const valueDate = ref.valueAsDate || new Date(inputValue);
1239
- if (isString(maxOutput.value)) {
1240
- exceedMax = valueDate > new Date(maxOutput.value);
1241
- }
1242
- if (isString(minOutput.value)) {
1243
- exceedMin = valueDate < new Date(minOutput.value);
1244
- }
1245
- }
1246
- if (exceedMax || exceedMin) {
1247
- getMinMaxMessage(!!exceedMax, maxOutput.message, minOutput.message, INPUT_VALIDATION_RULES.max, INPUT_VALIDATION_RULES.min);
1248
- if (!validateAllFieldCriteria) {
1249
- setCustomValidity(error[name].message);
1250
- return error;
1251
- }
1252
- }
1253
- }
1254
- if ((maxLength || minLength) && !isEmpty && isString(inputValue)) {
1255
- const maxLengthOutput = getValueAndMessage(maxLength);
1256
- const minLengthOutput = getValueAndMessage(minLength);
1257
- const exceedMax = !isNullOrUndefined(maxLengthOutput.value) &&
1258
- inputValue.length > maxLengthOutput.value;
1259
- const exceedMin = !isNullOrUndefined(minLengthOutput.value) &&
1260
- inputValue.length < minLengthOutput.value;
1261
- if (exceedMax || exceedMin) {
1262
- getMinMaxMessage(exceedMax, maxLengthOutput.message, minLengthOutput.message);
1263
- if (!validateAllFieldCriteria) {
1264
- setCustomValidity(error[name].message);
1265
- return error;
1266
- }
1267
- }
1268
- }
1269
- if (pattern && !isEmpty && isString(inputValue)) {
1270
- const { value: patternValue, message } = getValueAndMessage(pattern);
1271
- if (isRegex(patternValue) && !inputValue.match(patternValue)) {
1272
- error[name] = {
1273
- type: INPUT_VALIDATION_RULES.pattern,
1274
- message,
1275
- ref,
1276
- ...appendErrorsCurry(INPUT_VALIDATION_RULES.pattern, message),
1277
- };
1278
- if (!validateAllFieldCriteria) {
1279
- setCustomValidity(message);
1280
- return error;
1281
- }
1282
- }
1283
- }
1284
- if (validate) {
1285
- if (isFunction(validate)) {
1286
- const result = await validate(inputValue);
1287
- const validateError = getValidateError(result, inputRef);
1288
- if (validateError) {
1289
- error[name] = {
1290
- ...validateError,
1291
- ...appendErrorsCurry(INPUT_VALIDATION_RULES.validate, validateError.message),
1292
- };
1293
- if (!validateAllFieldCriteria) {
1294
- setCustomValidity(validateError.message);
1295
- return error;
1296
- }
1297
- }
1298
- }
1299
- else if (isObject(validate)) {
1300
- let validationResult = {};
1301
- for (const key in validate) {
1302
- if (!isEmptyObject(validationResult) && !validateAllFieldCriteria) {
1303
- break;
1304
- }
1305
- const validateError = getValidateError(await validate[key](inputValue), inputRef, key);
1306
- if (validateError) {
1307
- validationResult = {
1308
- ...validateError,
1309
- ...appendErrorsCurry(key, validateError.message),
1310
- };
1311
- setCustomValidity(validateError.message);
1312
- if (validateAllFieldCriteria) {
1313
- error[name] = validationResult;
1314
- }
1315
- }
1316
- }
1317
- if (!isEmptyObject(validationResult)) {
1318
- error[name] = {
1319
- ref: inputRef,
1320
- ...validationResult,
1321
- };
1322
- if (!validateAllFieldCriteria) {
1323
- return error;
1324
- }
1325
- }
1326
- }
1327
- }
1328
- setCustomValidity(true);
1329
- return error;
1330
- };
1331
-
1332
1368
  const defaultOptions = {
1333
1369
  mode: VALIDATION_MODE.onSubmit,
1334
1370
  reValidateMode: VALIDATION_MODE.onChange,
@@ -1552,20 +1588,22 @@ function createFormControl(props = {}) {
1552
1588
  for (const name in fields) {
1553
1589
  const field = fields[name];
1554
1590
  if (field) {
1555
- const { _f: fieldReference, ...fieldValue } = field;
1556
- if (fieldReference) {
1557
- const fieldError = await validateField(field, get(_formValues, fieldReference.name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation);
1558
- if (fieldError[fieldReference.name]) {
1591
+ const { _f, ...fieldValue } = field;
1592
+ if (_f) {
1593
+ const isFieldArrayRoot = _names.array.has(_f.name);
1594
+ const fieldError = await validateField(field, get(_formValues, _f.name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation, isFieldArrayRoot);
1595
+ if (fieldError[_f.name]) {
1559
1596
  context.valid = false;
1560
1597
  if (shouldOnlyCheckValid) {
1561
1598
  break;
1562
1599
  }
1563
1600
  }
1564
- if (!shouldOnlyCheckValid) {
1565
- fieldError[fieldReference.name]
1566
- ? set(_formState.errors, fieldReference.name, fieldError[fieldReference.name])
1567
- : unset(_formState.errors, fieldReference.name);
1568
- }
1601
+ !shouldOnlyCheckValid &&
1602
+ (get(fieldError, _f.name)
1603
+ ? isFieldArrayRoot
1604
+ ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
1605
+ : set(_formState.errors, _f.name, fieldError[_f.name])
1606
+ : unset(_formState.errors, _f.name));
1569
1607
  }
1570
1608
  fieldValue &&
1571
1609
  (await executeBuildInValidation(fieldValue, shouldOnlyCheckValid, context));
@@ -2093,7 +2131,8 @@ function createFormControl(props = {}) {
2093
2131
  const setFocus = (name, options = {}) => {
2094
2132
  const field = get(_fields, name)._f;
2095
2133
  const fieldRef = field.refs ? field.refs[0] : field.ref;
2096
- options.shouldSelect ? fieldRef.select() : fieldRef.focus();
2134
+ fieldRef.focus();
2135
+ options.shouldSelect && fieldRef.select();
2097
2136
  };
2098
2137
  return {
2099
2138
  control: {
@@ -2163,7 +2202,7 @@ function createFormControl(props = {}) {
2163
2202
  }
2164
2203
 
2165
2204
  /**
2166
- * Custom hook to mange the entire form.
2205
+ * Custom hook to manage the entire form.
2167
2206
  *
2168
2207
  * @remarks
2169
2208
  * [API](https://react-hook-form.com/api/useform) • [Demo](https://codesandbox.io/s/react-hook-form-get-started-ts-5ksmm) • [Video](https://www.youtube.com/watch?v=RkXv4AXXC_4)