@depup/react-hook-form 7.72.1-depup.0 → 7.83.0-depup.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/changes.json +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.d.ts.map +1 -1
- package/dist/fieldArray.d.ts +36 -0
- package/dist/fieldArray.d.ts.map +1 -0
- package/dist/form.d.ts.map +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.mjs +2271 -1847
- package/dist/index.esm.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/createFormControl.d.ts +13 -0
- package/dist/logic/createFormControl.d.ts.map +1 -1
- package/dist/logic/getDirtyFields.d.ts +3 -2
- package/dist/logic/getDirtyFields.d.ts.map +1 -1
- package/dist/logic/getEventValue.d.ts.map +1 -1
- package/dist/logic/getNodeParentName.d.ts.map +1 -1
- package/dist/logic/getProxyFormState.d.ts.map +1 -1
- package/dist/logic/getResolverOptions.d.ts +2 -2
- package/dist/logic/getValueAndMessage.d.ts +1 -4
- package/dist/logic/getValueAndMessage.d.ts.map +1 -1
- package/dist/logic/hasPromiseValidation.d.ts.map +1 -1
- package/dist/logic/hasValidation.d.ts +1 -1
- package/dist/logic/index.d.ts +2 -3
- package/dist/logic/index.d.ts.map +1 -1
- package/dist/logic/isWatched.d.ts.map +1 -1
- package/dist/logic/shouldRenderFormState.d.ts.map +1 -1
- package/dist/logic/skipValidation.d.ts +1 -4
- package/dist/logic/skipValidation.d.ts.map +1 -1
- package/dist/logic/updateFieldArrayRootError.d.ts.map +1 -1
- package/dist/logic/validateField.d.ts.map +1 -1
- package/dist/react-server.esm.mjs +480 -179
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/errors.d.ts +2 -2
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/fieldArray.d.ts +25 -1
- package/dist/types/fieldArray.d.ts.map +1 -1
- package/dist/types/form.d.ts +80 -56
- package/dist/types/form.d.ts.map +1 -1
- package/dist/types/path/common.d.ts +6 -0
- package/dist/types/path/common.d.ts.map +1 -1
- package/dist/types/path/eager.d.ts +15 -11
- package/dist/types/path/eager.d.ts.map +1 -1
- package/dist/types/utils.d.ts +4 -4
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/validator.d.ts +1 -1
- package/dist/types/validator.d.ts.map +1 -1
- package/dist/types/watch.d.ts +1 -1
- package/dist/types/watch.d.ts.map +1 -1
- package/dist/useController.d.ts.map +1 -1
- package/dist/useFieldArray.d.ts.map +1 -1
- package/dist/useForm.d.ts.map +1 -1
- package/dist/useFormContext.d.ts +1 -1
- package/dist/useFormContext.d.ts.map +1 -1
- package/dist/useFormState.d.ts +2 -2
- package/dist/useFormState.d.ts.map +1 -1
- package/dist/useIsomorphicLayoutEffect.d.ts.map +1 -1
- package/dist/useWatch.d.ts +14 -14
- package/dist/utils/deepEqual.d.ts +1 -1
- package/dist/utils/deepEqual.d.ts.map +1 -1
- package/dist/utils/flatten.d.ts.map +1 -1
- package/dist/utils/get.d.ts.map +1 -1
- package/dist/utils/index.d.ts +2 -3
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/isKey.d.ts.map +1 -1
- package/dist/utils/set.d.ts.map +1 -1
- package/dist/utils/stringToPath.d.ts.map +1 -1
- package/dist/utils/unset.d.ts.map +1 -1
- package/dist/watch.d.ts +1 -1
- package/dist/watch.d.ts.map +1 -1
- package/package.json +29 -26
- package/dist/__tests__/controller.server.test.d.ts +0 -2
- package/dist/__tests__/controller.server.test.d.ts.map +0 -1
- package/dist/__tests__/controller.test.d.ts +0 -2
- package/dist/__tests__/controller.test.d.ts.map +0 -1
- package/dist/__tests__/form.test.d.ts +0 -2
- package/dist/__tests__/form.test.d.ts.map +0 -1
- package/dist/__tests__/formStateSubscribe.server.test.d.ts +0 -2
- package/dist/__tests__/formStateSubscribe.server.test.d.ts.map +0 -1
- package/dist/__tests__/formStateSubscribe.test.d.ts +0 -2
- package/dist/__tests__/formStateSubscribe.test.d.ts.map +0 -1
- package/dist/__tests__/isPlainObject.test.d.ts +0 -2
- package/dist/__tests__/isPlainObject.test.d.ts.map +0 -1
- package/dist/__tests__/logic/appendErrors.test.d.ts +0 -2
- package/dist/__tests__/logic/appendErrors.test.d.ts.map +0 -1
- package/dist/__tests__/logic/createFormControl.test.d.ts +0 -2
- package/dist/__tests__/logic/createFormControl.test.d.ts.map +0 -1
- package/dist/__tests__/logic/generateId.test.d.ts +0 -2
- package/dist/__tests__/logic/generateId.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getCheckboxValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getCheckboxValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getDirtyFields.test.d.ts +0 -2
- package/dist/__tests__/logic/getDirtyFields.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getEventValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getEventValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getFieldValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getFieldValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getFieldValueAs.test.d.ts +0 -2
- package/dist/__tests__/logic/getFieldValueAs.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getFocusFieldName.test.d.ts +0 -2
- package/dist/__tests__/logic/getFocusFieldName.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getNodeParentName.test.d.ts +0 -2
- package/dist/__tests__/logic/getNodeParentName.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getRadioValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getRadioValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getResolverOptions.test.d.ts +0 -2
- package/dist/__tests__/logic/getResolverOptions.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getRuleValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getRuleValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getValidateError.test.d.ts +0 -2
- package/dist/__tests__/logic/getValidateError.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getValidationModes.test.d.ts +0 -2
- package/dist/__tests__/logic/getValidationModes.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getValueAndMessage.test.d.ts +0 -2
- package/dist/__tests__/logic/getValueAndMessage.test.d.ts.map +0 -1
- package/dist/__tests__/logic/hasPromiseValidation.test.d.ts +0 -2
- package/dist/__tests__/logic/hasPromiseValidation.test.d.ts.map +0 -1
- package/dist/__tests__/logic/hasValidation.test.d.ts +0 -2
- package/dist/__tests__/logic/hasValidation.test.d.ts.map +0 -1
- package/dist/__tests__/logic/isNameInFieldArray.test.d.ts +0 -2
- package/dist/__tests__/logic/isNameInFieldArray.test.d.ts.map +0 -1
- package/dist/__tests__/logic/isWatched.test.d.ts +0 -2
- package/dist/__tests__/logic/isWatched.test.d.ts.map +0 -1
- package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts +0 -2
- package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts.map +0 -1
- package/dist/__tests__/logic/schemaErrorLookup.test.d.ts +0 -2
- package/dist/__tests__/logic/schemaErrorLookup.test.d.ts.map +0 -1
- package/dist/__tests__/logic/shouldRenderFormState.test.d.ts +0 -2
- package/dist/__tests__/logic/shouldRenderFormState.test.d.ts.map +0 -1
- package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts +0 -2
- package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts.map +0 -1
- package/dist/__tests__/logic/skipValidation.test.d.ts +0 -2
- package/dist/__tests__/logic/skipValidation.test.d.ts.map +0 -1
- package/dist/__tests__/logic/unsetEmptyArray.test.d.ts +0 -2
- package/dist/__tests__/logic/unsetEmptyArray.test.d.ts.map +0 -1
- package/dist/__tests__/logic/validateField.test.d.ts +0 -2
- package/dist/__tests__/logic/validateField.test.d.ts.map +0 -1
- package/dist/__tests__/type.test.d.ts +0 -2
- package/dist/__tests__/type.test.d.ts.map +0 -1
- package/dist/__tests__/useController.test.d.ts +0 -2
- package/dist/__tests__/useController.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/append.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/append.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/dirtyFields.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/dirtyFields.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/focus.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/focus.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/insert.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/insert.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/move.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/move.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/prepend.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/prepend.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/remove.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/remove.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/replace.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/replace.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/swap.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/swap.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/update.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/update.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/clearErrors.test.d.ts +0 -2
- package/dist/__tests__/useForm/clearErrors.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/formState.test.d.ts +0 -2
- package/dist/__tests__/useForm/formState.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/getFieldState.test.d.ts +0 -2
- package/dist/__tests__/useForm/getFieldState.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/getValues.test.d.ts +0 -2
- package/dist/__tests__/useForm/getValues.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/handleSubmit.test.d.ts +0 -2
- package/dist/__tests__/useForm/handleSubmit.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/register.test.d.ts +0 -2
- package/dist/__tests__/useForm/register.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/reset.test.d.ts +0 -2
- package/dist/__tests__/useForm/reset.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/resetField.test.d.ts +0 -2
- package/dist/__tests__/useForm/resetField.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/resolver.test.d.ts +0 -2
- package/dist/__tests__/useForm/resolver.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/setError.test.d.ts +0 -2
- package/dist/__tests__/useForm/setError.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/setFocus.test.d.ts +0 -2
- package/dist/__tests__/useForm/setFocus.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/setValue.test.d.ts +0 -2
- package/dist/__tests__/useForm/setValue.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/subscribe.test.d.ts +0 -2
- package/dist/__tests__/useForm/subscribe.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/trigger.test.d.ts +0 -2
- package/dist/__tests__/useForm/trigger.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/unregister.test.d.ts +0 -2
- package/dist/__tests__/useForm/unregister.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts +0 -2
- package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts.map +0 -1
- package/dist/__tests__/useForm/watch.test.d.ts +0 -2
- package/dist/__tests__/useForm/watch.test.d.ts.map +0 -1
- package/dist/__tests__/useForm.server.test.d.ts +0 -2
- package/dist/__tests__/useForm.server.test.d.ts.map +0 -1
- package/dist/__tests__/useForm.test.d.ts +0 -2
- package/dist/__tests__/useForm.test.d.ts.map +0 -1
- package/dist/__tests__/useFormContext.server.test.d.ts +0 -2
- package/dist/__tests__/useFormContext.server.test.d.ts.map +0 -1
- package/dist/__tests__/useFormContext.test.d.ts +0 -2
- package/dist/__tests__/useFormContext.test.d.ts.map +0 -1
- package/dist/__tests__/useFormState.test.d.ts +0 -2
- package/dist/__tests__/useFormState.test.d.ts.map +0 -1
- package/dist/__tests__/useWatch.test.d.ts +0 -2
- package/dist/__tests__/useWatch.test.d.ts.map +0 -1
- package/dist/__tests__/utils/append.test.d.ts +0 -2
- package/dist/__tests__/utils/append.test.d.ts.map +0 -1
- package/dist/__tests__/utils/cloneObject.test.d.ts +0 -2
- package/dist/__tests__/utils/cloneObject.test.d.ts.map +0 -1
- package/dist/__tests__/utils/compact.test.d.ts +0 -2
- package/dist/__tests__/utils/compact.test.d.ts.map +0 -1
- package/dist/__tests__/utils/convertToArrayPayload.test.d.ts +0 -2
- package/dist/__tests__/utils/convertToArrayPayload.test.d.ts.map +0 -1
- package/dist/__tests__/utils/createSubject.test.d.ts +0 -2
- package/dist/__tests__/utils/createSubject.test.d.ts.map +0 -1
- package/dist/__tests__/utils/deepEqual.test.d.ts +0 -2
- package/dist/__tests__/utils/deepEqual.test.d.ts.map +0 -1
- package/dist/__tests__/utils/deepMerge.test.d.ts +0 -2
- package/dist/__tests__/utils/deepMerge.test.d.ts.map +0 -1
- package/dist/__tests__/utils/extractFormValues.test.d.ts +0 -2
- package/dist/__tests__/utils/extractFormValues.test.d.ts.map +0 -1
- package/dist/__tests__/utils/fillEmptyArray.test.d.ts +0 -2
- package/dist/__tests__/utils/fillEmptyArray.test.d.ts.map +0 -1
- package/dist/__tests__/utils/flatten.test.d.ts +0 -2
- package/dist/__tests__/utils/flatten.test.d.ts.map +0 -1
- package/dist/__tests__/utils/get.test.d.ts +0 -2
- package/dist/__tests__/utils/get.test.d.ts.map +0 -1
- package/dist/__tests__/utils/insert.test.d.ts +0 -2
- package/dist/__tests__/utils/insert.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isBoolean.test.d.ts +0 -2
- package/dist/__tests__/utils/isBoolean.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isCheckBoxInput.test.d.ts +0 -2
- package/dist/__tests__/utils/isCheckBoxInput.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isEmptyObject.test.d.ts +0 -2
- package/dist/__tests__/utils/isEmptyObject.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isFileInput.test.d.ts +0 -2
- package/dist/__tests__/utils/isFileInput.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isFunction.test.d.ts +0 -2
- package/dist/__tests__/utils/isFunction.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isHTMLElement.test.d.ts +0 -2
- package/dist/__tests__/utils/isHTMLElement.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isKey.test.d.ts +0 -2
- package/dist/__tests__/utils/isKey.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isMultipleSelect.test.d.ts +0 -2
- package/dist/__tests__/utils/isMultipleSelect.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isNullOrUndefined.test.d.ts +0 -2
- package/dist/__tests__/utils/isNullOrUndefined.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isObject.test.d.ts +0 -2
- package/dist/__tests__/utils/isObject.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isPrimitive.test.d.ts +0 -2
- package/dist/__tests__/utils/isPrimitive.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isRadioInput.test.d.ts +0 -2
- package/dist/__tests__/utils/isRadioInput.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts +0 -2
- package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isRegex.test.d.ts +0 -2
- package/dist/__tests__/utils/isRegex.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isString.test.d.ts +0 -2
- package/dist/__tests__/utils/isString.test.d.ts.map +0 -1
- package/dist/__tests__/utils/isUndefined.test.d.ts +0 -2
- package/dist/__tests__/utils/isUndefined.test.d.ts.map +0 -1
- package/dist/__tests__/utils/live.test.d.ts +0 -2
- package/dist/__tests__/utils/live.test.d.ts.map +0 -1
- package/dist/__tests__/utils/move.test.d.ts +0 -2
- package/dist/__tests__/utils/move.test.d.ts.map +0 -1
- package/dist/__tests__/utils/noop.test.d.ts +0 -2
- package/dist/__tests__/utils/noop.test.d.ts.map +0 -1
- package/dist/__tests__/utils/objectHasFunction.test.d.ts +0 -2
- package/dist/__tests__/utils/objectHasFunction.test.d.ts.map +0 -1
- package/dist/__tests__/utils/prepend.test.d.ts +0 -2
- package/dist/__tests__/utils/prepend.test.d.ts.map +0 -1
- package/dist/__tests__/utils/remove.test.d.ts +0 -2
- package/dist/__tests__/utils/remove.test.d.ts.map +0 -1
- package/dist/__tests__/utils/set.test.d.ts +0 -2
- package/dist/__tests__/utils/set.test.d.ts.map +0 -1
- package/dist/__tests__/utils/stringToPath.test.d.ts +0 -2
- package/dist/__tests__/utils/stringToPath.test.d.ts.map +0 -1
- package/dist/__tests__/utils/swap.test.d.ts +0 -2
- package/dist/__tests__/utils/swap.test.d.ts.map +0 -1
- package/dist/__tests__/utils/unset.test.d.ts +0 -2
- package/dist/__tests__/utils/unset.test.d.ts.map +0 -1
- package/dist/__tests__/utils/update.test.d.ts +0 -2
- package/dist/__tests__/utils/update.test.d.ts.map +0 -1
- package/dist/__tests__/utils/validationModeChecker.test.d.ts +0 -2
- package/dist/__tests__/utils/validationModeChecker.test.d.ts.map +0 -1
- package/dist/__tests__/watch.server.test.d.ts +0 -2
- package/dist/__tests__/watch.server.test.d.ts.map +0 -1
- package/dist/__tests__/watch.test.d.ts +0 -2
- package/dist/__tests__/watch.test.d.ts.map +0 -1
package/dist/index.esm.mjs
CHANGED
|
@@ -2,6 +2,8 @@ import React from 'react';
|
|
|
2
2
|
|
|
3
3
|
var isCheckBoxInput = (element) => element.type === 'checkbox';
|
|
4
4
|
|
|
5
|
+
var isFileInput = (element) => element.type === 'file';
|
|
6
|
+
|
|
5
7
|
var isDateObject = (value) => value instanceof Date;
|
|
6
8
|
|
|
7
9
|
var isNullOrUndefined = (value) => value == null;
|
|
@@ -15,7 +17,9 @@ var isObject = (value) => !isNullOrUndefined(value) &&
|
|
|
15
17
|
var getEventValue = (event) => isObject(event) && event.target
|
|
16
18
|
? isCheckBoxInput(event.target)
|
|
17
19
|
? event.target.checked
|
|
18
|
-
: event.target
|
|
20
|
+
: isFileInput(event.target)
|
|
21
|
+
? event.target.files
|
|
22
|
+
: event.target.value
|
|
19
23
|
: event;
|
|
20
24
|
|
|
21
25
|
var isNameInFieldArray = (names, name) => name
|
|
@@ -52,19 +56,52 @@ function cloneObject(data) {
|
|
|
52
56
|
return copy;
|
|
53
57
|
}
|
|
54
58
|
|
|
55
|
-
|
|
59
|
+
const EVENTS = {
|
|
60
|
+
BLUR: 'blur',
|
|
61
|
+
FOCUS_OUT: 'focusout',
|
|
62
|
+
CHANGE: 'change',
|
|
63
|
+
SUBMIT: 'submit',
|
|
64
|
+
TRIGGER: 'trigger',
|
|
65
|
+
VALID: 'valid',
|
|
66
|
+
};
|
|
67
|
+
const VALIDATION_MODE = {
|
|
68
|
+
onBlur: 'onBlur',
|
|
69
|
+
onChange: 'onChange',
|
|
70
|
+
onSubmit: 'onSubmit',
|
|
71
|
+
onTouched: 'onTouched',
|
|
72
|
+
all: 'all',
|
|
73
|
+
};
|
|
74
|
+
const INPUT_VALIDATION_RULES = {
|
|
75
|
+
max: 'max',
|
|
76
|
+
min: 'min',
|
|
77
|
+
maxLength: 'maxLength',
|
|
78
|
+
minLength: 'minLength',
|
|
79
|
+
pattern: 'pattern',
|
|
80
|
+
required: 'required',
|
|
81
|
+
validate: 'validate',
|
|
82
|
+
};
|
|
83
|
+
const ROOT_ERROR_TYPE = 'root';
|
|
84
|
+
const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
|
|
85
|
+
|
|
86
|
+
const IS_KEY_RE = /^\w*$/;
|
|
87
|
+
var isKey = (value) => IS_KEY_RE.test(value);
|
|
56
88
|
|
|
57
89
|
var isUndefined = (val) => val === undefined;
|
|
58
90
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
|
|
91
|
+
const FIELD_PATH_RE = /[.[\]'"]/;
|
|
92
|
+
var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
|
|
62
93
|
|
|
63
94
|
var get = (object, path, defaultValue) => {
|
|
64
95
|
if (!path || !isObject(object)) {
|
|
65
96
|
return defaultValue;
|
|
66
97
|
}
|
|
67
|
-
const
|
|
98
|
+
const paths = isKey(path) ? [path] : stringToPath(path);
|
|
99
|
+
if (paths.some((key) => PROTOTYPE_KEYWORDS.includes(key))) {
|
|
100
|
+
return defaultValue;
|
|
101
|
+
}
|
|
102
|
+
const result = paths.reduce((result, key) => {
|
|
103
|
+
return isNullOrUndefined(result) ? undefined : result[key];
|
|
104
|
+
}, object);
|
|
68
105
|
return isUndefined(result) || result === object
|
|
69
106
|
? isUndefined(object[path])
|
|
70
107
|
? defaultValue
|
|
@@ -93,7 +130,7 @@ var set = (object, path, value) => {
|
|
|
93
130
|
? []
|
|
94
131
|
: {};
|
|
95
132
|
}
|
|
96
|
-
if (key
|
|
133
|
+
if (PROTOTYPE_KEYWORDS.includes(key)) {
|
|
97
134
|
return;
|
|
98
135
|
}
|
|
99
136
|
object[key] = newValue;
|
|
@@ -101,33 +138,6 @@ var set = (object, path, value) => {
|
|
|
101
138
|
}
|
|
102
139
|
};
|
|
103
140
|
|
|
104
|
-
const EVENTS = {
|
|
105
|
-
BLUR: 'blur',
|
|
106
|
-
FOCUS_OUT: 'focusout',
|
|
107
|
-
CHANGE: 'change',
|
|
108
|
-
SUBMIT: 'submit',
|
|
109
|
-
TRIGGER: 'trigger',
|
|
110
|
-
VALID: 'valid',
|
|
111
|
-
};
|
|
112
|
-
const VALIDATION_MODE = {
|
|
113
|
-
onBlur: 'onBlur',
|
|
114
|
-
onChange: 'onChange',
|
|
115
|
-
onSubmit: 'onSubmit',
|
|
116
|
-
onTouched: 'onTouched',
|
|
117
|
-
all: 'all',
|
|
118
|
-
};
|
|
119
|
-
const INPUT_VALIDATION_RULES = {
|
|
120
|
-
max: 'max',
|
|
121
|
-
min: 'min',
|
|
122
|
-
maxLength: 'maxLength',
|
|
123
|
-
minLength: 'minLength',
|
|
124
|
-
pattern: 'pattern',
|
|
125
|
-
required: 'required',
|
|
126
|
-
validate: 'validate',
|
|
127
|
-
};
|
|
128
|
-
const FORM_ERROR_TYPE = 'form';
|
|
129
|
-
const ROOT_ERROR_TYPE = 'root';
|
|
130
|
-
|
|
131
141
|
/**
|
|
132
142
|
* Separate context for `control` to prevent unnecessary rerenders.
|
|
133
143
|
* Internal hooks that only need control use this instead of full form context.
|
|
@@ -140,9 +150,7 @@ HookFormControlContext.displayName = 'HookFormControlContext';
|
|
|
140
150
|
const useFormControlContext = () => React.useContext(HookFormControlContext);
|
|
141
151
|
|
|
142
152
|
var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
|
|
143
|
-
const result = {
|
|
144
|
-
defaultValues: control._defaultValues,
|
|
145
|
-
};
|
|
153
|
+
const result = {};
|
|
146
154
|
for (const key in formState) {
|
|
147
155
|
Object.defineProperty(result, key, {
|
|
148
156
|
get: () => {
|
|
@@ -158,15 +166,17 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
|
|
|
158
166
|
return result;
|
|
159
167
|
};
|
|
160
168
|
|
|
161
|
-
const useIsomorphicLayoutEffect =
|
|
169
|
+
const useIsomorphicLayoutEffect = isWeb
|
|
170
|
+
? React.useLayoutEffect
|
|
171
|
+
: React.useEffect;
|
|
162
172
|
|
|
163
173
|
/**
|
|
164
|
-
*
|
|
174
|
+
* Subscribes to each form state and isolates re-renders at the custom hook level. It has its own scope for form state subscriptions, so it will not affect other useFormState or useForm instances. Using this hook can reduce the re-render impact on large and complex form applications.
|
|
165
175
|
*
|
|
166
176
|
* @remarks
|
|
167
177
|
* [API](https://react-hook-form.com/docs/useformstate) • [Demo](https://codesandbox.io/s/useformstate-75xly)
|
|
168
178
|
*
|
|
169
|
-
* @param props -
|
|
179
|
+
* @param props - Include options to specify fields to subscribe to. {@link UseFormStateReturn}
|
|
170
180
|
*
|
|
171
181
|
* @example
|
|
172
182
|
* ```tsx
|
|
@@ -193,7 +203,10 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayou
|
|
|
193
203
|
function useFormState(props) {
|
|
194
204
|
const formControl = useFormControlContext();
|
|
195
205
|
const { control = formControl, disabled, name, exact } = props || {};
|
|
196
|
-
const [formState, updateFormState] = React.useState(
|
|
206
|
+
const [formState, updateFormState] = React.useState(() => ({
|
|
207
|
+
...control._formState,
|
|
208
|
+
defaultValues: control._defaultValues,
|
|
209
|
+
}));
|
|
197
210
|
const _localProxyFormState = React.useRef({
|
|
198
211
|
isDirty: false,
|
|
199
212
|
isLoading: false,
|
|
@@ -213,6 +226,7 @@ function useFormState(props) {
|
|
|
213
226
|
updateFormState({
|
|
214
227
|
...control._formState,
|
|
215
228
|
...formState,
|
|
229
|
+
defaultValues: control._defaultValues,
|
|
216
230
|
});
|
|
217
231
|
},
|
|
218
232
|
}), [name, disabled, exact]);
|
|
@@ -239,7 +253,11 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
|
|
|
239
253
|
|
|
240
254
|
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
|
241
255
|
|
|
242
|
-
|
|
256
|
+
const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
|
|
257
|
+
function deepEqual(object1, object2, visited = new WeakMap()) {
|
|
258
|
+
if (object1 === object2) {
|
|
259
|
+
return true;
|
|
260
|
+
}
|
|
243
261
|
if (isPrimitive(object1) || isPrimitive(object2)) {
|
|
244
262
|
return Object.is(object1, object2);
|
|
245
263
|
}
|
|
@@ -251,14 +269,28 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
|
|
|
251
269
|
if (keys1.length !== keys2.length) {
|
|
252
270
|
return false;
|
|
253
271
|
}
|
|
254
|
-
if (
|
|
272
|
+
if (isEmptyObjectWithCustomPrototype(object1, keys1) ||
|
|
273
|
+
isEmptyObjectWithCustomPrototype(object2, keys2)) {
|
|
274
|
+
return Object.is(object1, object2);
|
|
275
|
+
}
|
|
276
|
+
if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
const visitedPairs = visited.get(object1);
|
|
280
|
+
if (visitedPairs && visitedPairs.has(object2)) {
|
|
255
281
|
return true;
|
|
256
282
|
}
|
|
257
|
-
|
|
258
|
-
|
|
283
|
+
if (visitedPairs) {
|
|
284
|
+
visitedPairs.add(object2);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
const ws = new WeakSet();
|
|
288
|
+
ws.add(object2);
|
|
289
|
+
visited.set(object1, ws);
|
|
290
|
+
}
|
|
259
291
|
for (const key of keys1) {
|
|
260
292
|
const val1 = object1[key];
|
|
261
|
-
if (!
|
|
293
|
+
if (!(key in object2)) {
|
|
262
294
|
return false;
|
|
263
295
|
}
|
|
264
296
|
if (key !== 'ref') {
|
|
@@ -266,7 +298,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
|
|
|
266
298
|
if ((isDateObject(val1) && isDateObject(val2)) ||
|
|
267
299
|
((isObject(val1) || Array.isArray(val1)) &&
|
|
268
300
|
(isObject(val2) || Array.isArray(val2)))
|
|
269
|
-
? !deepEqual(val1, val2,
|
|
301
|
+
? !deepEqual(val1, val2, visited)
|
|
270
302
|
: !Object.is(val1, val2)) {
|
|
271
303
|
return false;
|
|
272
304
|
}
|
|
@@ -276,7 +308,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
|
|
|
276
308
|
}
|
|
277
309
|
|
|
278
310
|
/**
|
|
279
|
-
* Custom hook to subscribe to field
|
|
311
|
+
* Custom hook to subscribe to field changes and isolate re-rendering at the component level.
|
|
280
312
|
*
|
|
281
313
|
* @remarks
|
|
282
314
|
*
|
|
@@ -286,7 +318,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
|
|
|
286
318
|
* ```tsx
|
|
287
319
|
* const { control } = useForm();
|
|
288
320
|
* const values = useWatch({
|
|
289
|
-
* name: "fieldName"
|
|
321
|
+
* name: "fieldName",
|
|
290
322
|
* control,
|
|
291
323
|
* })
|
|
292
324
|
* ```
|
|
@@ -402,7 +434,7 @@ function useController(props) {
|
|
|
402
434
|
exact,
|
|
403
435
|
});
|
|
404
436
|
const _props = React.useRef(props);
|
|
405
|
-
const
|
|
437
|
+
const _proxyRef = React.useRef(null);
|
|
406
438
|
const _registerProps = React.useRef(control.register(name, {
|
|
407
439
|
...props.rules,
|
|
408
440
|
value,
|
|
@@ -431,13 +463,22 @@ function useController(props) {
|
|
|
431
463
|
get: () => get(formState.errors, name),
|
|
432
464
|
},
|
|
433
465
|
}), [formState, name]);
|
|
434
|
-
const onChange = React.useCallback((event) =>
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
466
|
+
const onChange = React.useCallback((event) => {
|
|
467
|
+
const value = getEventValue(event);
|
|
468
|
+
if (!get(control._fields, name)) {
|
|
469
|
+
_registerProps.current = control.register(name, {
|
|
470
|
+
..._props.current.rules,
|
|
471
|
+
value,
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
return _registerProps.current.onChange({
|
|
475
|
+
target: {
|
|
476
|
+
value: getEventValue(event),
|
|
477
|
+
name: name,
|
|
478
|
+
},
|
|
479
|
+
type: EVENTS.CHANGE,
|
|
480
|
+
});
|
|
481
|
+
}, [name, control]);
|
|
441
482
|
const onBlur = React.useCallback(() => _registerProps.current.onBlur({
|
|
442
483
|
target: {
|
|
443
484
|
value: get(control._formValues, name),
|
|
@@ -446,15 +487,18 @@ function useController(props) {
|
|
|
446
487
|
type: EVENTS.BLUR,
|
|
447
488
|
}), [name, control._formValues]);
|
|
448
489
|
const ref = React.useCallback((elm) => {
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
field._f.ref = {
|
|
490
|
+
if (elm) {
|
|
491
|
+
_proxyRef.current = {
|
|
452
492
|
focus: () => isFunction(elm.focus) && elm.focus(),
|
|
453
493
|
select: () => isFunction(elm.select) && elm.select(),
|
|
454
494
|
setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
|
|
455
495
|
reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
|
|
456
496
|
};
|
|
457
497
|
}
|
|
498
|
+
const field = get(control._fields, name);
|
|
499
|
+
if (field && field._f && elm) {
|
|
500
|
+
field._f.ref = _proxyRef.current;
|
|
501
|
+
}
|
|
458
502
|
}, [control._fields, name]);
|
|
459
503
|
const field = React.useMemo(() => ({
|
|
460
504
|
name,
|
|
@@ -468,11 +512,7 @@ function useController(props) {
|
|
|
468
512
|
}), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
|
|
469
513
|
React.useEffect(() => {
|
|
470
514
|
const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
|
|
471
|
-
|
|
472
|
-
if (previousName && previousName !== name && !isArrayField) {
|
|
473
|
-
control.unregister(previousName);
|
|
474
|
-
}
|
|
475
|
-
control.register(name, {
|
|
515
|
+
_registerProps.current = control.register(name, {
|
|
476
516
|
..._props.current.rules,
|
|
477
517
|
...(isBoolean(_props.current.disabled)
|
|
478
518
|
? { disabled: _props.current.disabled }
|
|
@@ -486,14 +526,21 @@ function useController(props) {
|
|
|
486
526
|
};
|
|
487
527
|
updateMounted(name, true);
|
|
488
528
|
if (_shouldUnregisterField) {
|
|
489
|
-
const value = cloneObject(get(
|
|
529
|
+
const value = cloneObject(get(shouldUnregister
|
|
530
|
+
? control._defaultValues
|
|
531
|
+
: control._options.values || control._defaultValues, name, get(control._options.defaultValues, name, _props.current.defaultValue)));
|
|
490
532
|
set(control._defaultValues, name, value);
|
|
491
533
|
if (isUndefined(get(control._formValues, name))) {
|
|
492
534
|
set(control._formValues, name, value);
|
|
493
535
|
}
|
|
494
536
|
}
|
|
495
537
|
!isArrayField && control.register(name);
|
|
496
|
-
|
|
538
|
+
if (_proxyRef.current) {
|
|
539
|
+
const field = get(control._fields, name);
|
|
540
|
+
if (field && field._f) {
|
|
541
|
+
field._f.ref = _proxyRef.current;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
497
544
|
return () => {
|
|
498
545
|
(isArrayField
|
|
499
546
|
? _shouldUnregisterField && !control._state.action
|
|
@@ -559,293 +606,80 @@ function useController(props) {
|
|
|
559
606
|
*/
|
|
560
607
|
const Controller = (props) => props.render(useController(props));
|
|
561
608
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
609
|
+
var generateId = () => {
|
|
610
|
+
if (typeof crypto !== 'undefined' && crypto.randomUUID) {
|
|
611
|
+
return crypto.randomUUID();
|
|
612
|
+
}
|
|
613
|
+
const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
|
|
614
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
|
|
615
|
+
const r = ((Math.random() * 16 + d) % 16) | 0;
|
|
616
|
+
return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
|
|
617
|
+
});
|
|
618
|
+
};
|
|
619
|
+
|
|
620
|
+
var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
|
|
621
|
+
? options.focusName ||
|
|
622
|
+
`${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
|
|
623
|
+
: '';
|
|
624
|
+
|
|
625
|
+
var getValidationModes = (mode) => ({
|
|
626
|
+
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
|
|
627
|
+
isOnBlur: mode === VALIDATION_MODE.onBlur,
|
|
628
|
+
isOnChange: mode === VALIDATION_MODE.onChange,
|
|
629
|
+
isOnAll: mode === VALIDATION_MODE.all,
|
|
630
|
+
isOnTouch: mode === VALIDATION_MODE.onTouched,
|
|
631
|
+
});
|
|
632
|
+
|
|
633
|
+
var isWatched = (name, _names, isBlurEvent) => {
|
|
634
|
+
if (isBlurEvent)
|
|
635
|
+
return false;
|
|
636
|
+
if (_names.watchAll || _names.watch.has(name))
|
|
637
|
+
return true;
|
|
638
|
+
for (const watchName of _names.watch) {
|
|
639
|
+
if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
|
|
640
|
+
return true;
|
|
641
|
+
}
|
|
642
|
+
return false;
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
|
646
|
+
for (const key of fieldsNames || Object.keys(fields)) {
|
|
647
|
+
const field = get(fields, key);
|
|
648
|
+
if (field) {
|
|
649
|
+
const { _f, ...currentField } = field;
|
|
650
|
+
if (_f) {
|
|
651
|
+
if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
|
|
652
|
+
return true;
|
|
653
|
+
}
|
|
654
|
+
else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
|
|
655
|
+
return true;
|
|
656
|
+
}
|
|
657
|
+
else {
|
|
658
|
+
if (iterateFieldsByAction(currentField, action)) {
|
|
659
|
+
break;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
else if (isObject(currentField)) {
|
|
664
|
+
if (iterateFieldsByAction(currentField, action)) {
|
|
665
|
+
break;
|
|
666
|
+
}
|
|
569
667
|
}
|
|
570
|
-
}
|
|
571
|
-
else {
|
|
572
|
-
output[key] = obj[key];
|
|
573
668
|
}
|
|
574
669
|
}
|
|
575
|
-
return
|
|
670
|
+
return;
|
|
576
671
|
};
|
|
577
672
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
585
|
-
*
|
|
586
|
-
* @returns return all useForm methods
|
|
587
|
-
*
|
|
588
|
-
* @example
|
|
589
|
-
* ```tsx
|
|
590
|
-
* function App() {
|
|
591
|
-
* const methods = useForm();
|
|
592
|
-
* const onSubmit = data => console.log(data);
|
|
593
|
-
*
|
|
594
|
-
* return (
|
|
595
|
-
* <FormProvider {...methods} >
|
|
596
|
-
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
597
|
-
* <NestedInput />
|
|
598
|
-
* <input type="submit" />
|
|
599
|
-
* </form>
|
|
600
|
-
* </FormProvider>
|
|
601
|
-
* );
|
|
602
|
-
* }
|
|
603
|
-
*
|
|
604
|
-
* function NestedInput() {
|
|
605
|
-
* const { register } = useFormContext(); // retrieve all hook methods
|
|
606
|
-
* return <input {...register("test")} />;
|
|
607
|
-
* }
|
|
608
|
-
* ```
|
|
609
|
-
*/
|
|
610
|
-
const useFormContext = () => React.useContext(HookFormContext);
|
|
611
|
-
/**
|
|
612
|
-
* A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
|
|
613
|
-
*
|
|
614
|
-
* @remarks
|
|
615
|
-
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
616
|
-
*
|
|
617
|
-
* @param props - all useForm methods
|
|
618
|
-
*
|
|
619
|
-
* @example
|
|
620
|
-
* ```tsx
|
|
621
|
-
* function App() {
|
|
622
|
-
* const methods = useForm();
|
|
623
|
-
* const onSubmit = data => console.log(data);
|
|
624
|
-
*
|
|
625
|
-
* return (
|
|
626
|
-
* <FormProvider {...methods} >
|
|
627
|
-
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
628
|
-
* <NestedInput />
|
|
629
|
-
* <input type="submit" />
|
|
630
|
-
* </form>
|
|
631
|
-
* </FormProvider>
|
|
632
|
-
* );
|
|
633
|
-
* }
|
|
634
|
-
*
|
|
635
|
-
* function NestedInput() {
|
|
636
|
-
* const { register } = useFormContext(); // retrieve all hook methods
|
|
637
|
-
* return <input {...register("test")} />;
|
|
638
|
-
* }
|
|
639
|
-
* ```
|
|
640
|
-
*/
|
|
641
|
-
const FormProvider = (props) => {
|
|
642
|
-
const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, } = props;
|
|
643
|
-
const memoizedValue = React.useMemo(() => ({
|
|
644
|
-
watch,
|
|
645
|
-
getValues,
|
|
646
|
-
getFieldState,
|
|
647
|
-
setError,
|
|
648
|
-
clearErrors,
|
|
649
|
-
setValue,
|
|
650
|
-
trigger,
|
|
651
|
-
formState,
|
|
652
|
-
resetField,
|
|
653
|
-
reset,
|
|
654
|
-
handleSubmit,
|
|
655
|
-
unregister,
|
|
656
|
-
control,
|
|
657
|
-
register,
|
|
658
|
-
setFocus,
|
|
659
|
-
subscribe,
|
|
660
|
-
}), [
|
|
661
|
-
clearErrors,
|
|
662
|
-
control,
|
|
663
|
-
formState,
|
|
664
|
-
getFieldState,
|
|
665
|
-
getValues,
|
|
666
|
-
handleSubmit,
|
|
667
|
-
register,
|
|
668
|
-
reset,
|
|
669
|
-
resetField,
|
|
670
|
-
setError,
|
|
671
|
-
setFocus,
|
|
672
|
-
setValue,
|
|
673
|
-
subscribe,
|
|
674
|
-
trigger,
|
|
675
|
-
unregister,
|
|
676
|
-
watch,
|
|
677
|
-
]);
|
|
678
|
-
return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
|
|
679
|
-
React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
|
|
673
|
+
var updateFieldArrayRootError = (errors, error, name) => {
|
|
674
|
+
const existingErrors = get(errors, name);
|
|
675
|
+
const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
|
|
676
|
+
set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
|
|
677
|
+
set(errors, name, fieldArrayErrors);
|
|
678
|
+
return errors;
|
|
680
679
|
};
|
|
681
680
|
|
|
682
|
-
const POST_REQUEST = 'post';
|
|
683
|
-
/**
|
|
684
|
-
* Form component to manage submission.
|
|
685
|
-
*
|
|
686
|
-
* @param props - to setup submission detail. {@link FormProps}
|
|
687
|
-
*
|
|
688
|
-
* @returns form component or headless render prop.
|
|
689
|
-
*
|
|
690
|
-
* @example
|
|
691
|
-
* ```tsx
|
|
692
|
-
* function App() {
|
|
693
|
-
* const { control, formState: { errors } } = useForm();
|
|
694
|
-
*
|
|
695
|
-
* return (
|
|
696
|
-
* <Form action="/api" control={control}>
|
|
697
|
-
* <input {...register("name")} />
|
|
698
|
-
* <p>{errors?.root?.server && 'Server error'}</p>
|
|
699
|
-
* <button>Submit</button>
|
|
700
|
-
* </Form>
|
|
701
|
-
* );
|
|
702
|
-
* }
|
|
703
|
-
* ```
|
|
704
|
-
*/
|
|
705
|
-
function Form(props) {
|
|
706
|
-
const methods = useFormContext();
|
|
707
|
-
const [mounted, setMounted] = React.useState(false);
|
|
708
|
-
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
|
|
709
|
-
const submit = async (event) => {
|
|
710
|
-
let hasError = false;
|
|
711
|
-
let type = '';
|
|
712
|
-
await control.handleSubmit(async (data) => {
|
|
713
|
-
const formData = new FormData();
|
|
714
|
-
let formDataJson = '';
|
|
715
|
-
try {
|
|
716
|
-
formDataJson = JSON.stringify(data);
|
|
717
|
-
}
|
|
718
|
-
catch (_a) { }
|
|
719
|
-
const flattenFormValues = flatten(control._formValues);
|
|
720
|
-
for (const key in flattenFormValues) {
|
|
721
|
-
formData.append(key, flattenFormValues[key]);
|
|
722
|
-
}
|
|
723
|
-
if (onSubmit) {
|
|
724
|
-
await onSubmit({
|
|
725
|
-
data,
|
|
726
|
-
event,
|
|
727
|
-
method,
|
|
728
|
-
formData,
|
|
729
|
-
formDataJson,
|
|
730
|
-
});
|
|
731
|
-
}
|
|
732
|
-
if (action) {
|
|
733
|
-
try {
|
|
734
|
-
const shouldStringifySubmissionData = [
|
|
735
|
-
headers && headers['Content-Type'],
|
|
736
|
-
encType,
|
|
737
|
-
].some((value) => value && value.includes('json'));
|
|
738
|
-
const response = await fetch(String(action), {
|
|
739
|
-
method,
|
|
740
|
-
headers: {
|
|
741
|
-
...headers,
|
|
742
|
-
...(encType && encType !== 'multipart/form-data'
|
|
743
|
-
? { 'Content-Type': encType }
|
|
744
|
-
: {}),
|
|
745
|
-
},
|
|
746
|
-
body: shouldStringifySubmissionData ? formDataJson : formData,
|
|
747
|
-
});
|
|
748
|
-
if (response &&
|
|
749
|
-
(validateStatus
|
|
750
|
-
? !validateStatus(response.status)
|
|
751
|
-
: response.status < 200 || response.status >= 300)) {
|
|
752
|
-
hasError = true;
|
|
753
|
-
onError && onError({ response });
|
|
754
|
-
type = String(response.status);
|
|
755
|
-
}
|
|
756
|
-
else {
|
|
757
|
-
onSuccess && onSuccess({ response });
|
|
758
|
-
}
|
|
759
|
-
}
|
|
760
|
-
catch (error) {
|
|
761
|
-
hasError = true;
|
|
762
|
-
onError && onError({ error });
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
})(event);
|
|
766
|
-
if (hasError && props.control) {
|
|
767
|
-
props.control._subjects.state.next({
|
|
768
|
-
isSubmitSuccessful: false,
|
|
769
|
-
});
|
|
770
|
-
props.control.setError('root.server', {
|
|
771
|
-
type,
|
|
772
|
-
});
|
|
773
|
-
}
|
|
774
|
-
};
|
|
775
|
-
React.useEffect(() => {
|
|
776
|
-
setMounted(true);
|
|
777
|
-
}, []);
|
|
778
|
-
return render ? (React.createElement(React.Fragment, null, render({
|
|
779
|
-
submit,
|
|
780
|
-
}))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
|
|
781
|
-
}
|
|
782
|
-
|
|
783
|
-
const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
|
|
784
|
-
|
|
785
|
-
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
|
786
|
-
? {
|
|
787
|
-
...errors[name],
|
|
788
|
-
types: {
|
|
789
|
-
...(errors[name] && errors[name].types ? errors[name].types : {}),
|
|
790
|
-
[type]: message || true,
|
|
791
|
-
},
|
|
792
|
-
}
|
|
793
|
-
: {};
|
|
794
|
-
|
|
795
|
-
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
|
796
|
-
|
|
797
|
-
var createSubject = () => {
|
|
798
|
-
let _observers = [];
|
|
799
|
-
const next = (value) => {
|
|
800
|
-
for (const observer of _observers) {
|
|
801
|
-
observer.next && observer.next(value);
|
|
802
|
-
}
|
|
803
|
-
};
|
|
804
|
-
const subscribe = (observer) => {
|
|
805
|
-
_observers.push(observer);
|
|
806
|
-
return {
|
|
807
|
-
unsubscribe: () => {
|
|
808
|
-
_observers = _observers.filter((o) => o !== observer);
|
|
809
|
-
},
|
|
810
|
-
};
|
|
811
|
-
};
|
|
812
|
-
const unsubscribe = () => {
|
|
813
|
-
_observers = [];
|
|
814
|
-
};
|
|
815
|
-
return {
|
|
816
|
-
get observers() {
|
|
817
|
-
return _observers;
|
|
818
|
-
},
|
|
819
|
-
next,
|
|
820
|
-
subscribe,
|
|
821
|
-
unsubscribe,
|
|
822
|
-
};
|
|
823
|
-
};
|
|
824
|
-
|
|
825
|
-
function extractFormValues(fieldsState, formValues) {
|
|
826
|
-
const values = {};
|
|
827
|
-
for (const key in fieldsState) {
|
|
828
|
-
if (fieldsState.hasOwnProperty(key)) {
|
|
829
|
-
const fieldState = fieldsState[key];
|
|
830
|
-
const fieldValue = formValues[key];
|
|
831
|
-
if (fieldState && isObject(fieldState) && fieldValue) {
|
|
832
|
-
const nestedFieldsState = extractFormValues(fieldState, fieldValue);
|
|
833
|
-
if (isObject(nestedFieldsState)) {
|
|
834
|
-
values[key] = nestedFieldsState;
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
else if (fieldsState[key]) {
|
|
838
|
-
values[key] = fieldValue;
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
return values;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
681
|
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
|
846
682
|
|
|
847
|
-
var isFileInput = (element) => element.type === 'file';
|
|
848
|
-
|
|
849
683
|
var isHTMLElement = (value) => {
|
|
850
684
|
if (!isWeb) {
|
|
851
685
|
return false;
|
|
@@ -855,96 +689,19 @@ var isHTMLElement = (value) => {
|
|
|
855
689
|
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
|
|
856
690
|
};
|
|
857
691
|
|
|
858
|
-
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
|
859
|
-
|
|
860
692
|
var isRadioInput = (element) => element.type === 'radio';
|
|
861
693
|
|
|
862
|
-
var
|
|
863
|
-
|
|
864
|
-
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
|
865
|
-
|
|
866
|
-
function baseGet(object, updatePath) {
|
|
867
|
-
const length = updatePath.slice(0, -1).length;
|
|
868
|
-
let index = 0;
|
|
869
|
-
while (index < length) {
|
|
870
|
-
object = isUndefined(object) ? index++ : object[updatePath[index++]];
|
|
871
|
-
}
|
|
872
|
-
return object;
|
|
873
|
-
}
|
|
874
|
-
function isEmptyArray(obj) {
|
|
875
|
-
for (const key in obj) {
|
|
876
|
-
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
|
877
|
-
return false;
|
|
878
|
-
}
|
|
879
|
-
}
|
|
880
|
-
return true;
|
|
881
|
-
}
|
|
882
|
-
function unset(object, path) {
|
|
883
|
-
const paths = Array.isArray(path)
|
|
884
|
-
? path
|
|
885
|
-
: isKey(path)
|
|
886
|
-
? [path]
|
|
887
|
-
: stringToPath(path);
|
|
888
|
-
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
|
889
|
-
const index = paths.length - 1;
|
|
890
|
-
const key = paths[index];
|
|
891
|
-
if (childObject) {
|
|
892
|
-
delete childObject[key];
|
|
893
|
-
}
|
|
894
|
-
if (index !== 0 &&
|
|
895
|
-
((isObject(childObject) && isEmptyObject(childObject)) ||
|
|
896
|
-
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
|
897
|
-
unset(object, paths.slice(0, -1));
|
|
898
|
-
}
|
|
899
|
-
return object;
|
|
900
|
-
}
|
|
901
|
-
|
|
902
|
-
var objectHasFunction = (data) => {
|
|
903
|
-
for (const key in data) {
|
|
904
|
-
if (isFunction(data[key])) {
|
|
905
|
-
return true;
|
|
906
|
-
}
|
|
907
|
-
}
|
|
908
|
-
return false;
|
|
909
|
-
};
|
|
694
|
+
var isRegex = (value) => value instanceof RegExp;
|
|
910
695
|
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
fields[key] = Array.isArray(value) ? [] : {};
|
|
919
|
-
markFieldsDirty(value, fields[key]);
|
|
920
|
-
}
|
|
921
|
-
else if (!isUndefined(value)) {
|
|
922
|
-
fields[key] = true;
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
return fields;
|
|
926
|
-
}
|
|
927
|
-
function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
|
|
928
|
-
if (!dirtyFieldsFromValues) {
|
|
929
|
-
dirtyFieldsFromValues = markFieldsDirty(formValues);
|
|
930
|
-
}
|
|
931
|
-
for (const key in data) {
|
|
932
|
-
const value = data[key];
|
|
933
|
-
if (isTraversable(value)) {
|
|
934
|
-
if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
|
|
935
|
-
dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {});
|
|
936
|
-
}
|
|
937
|
-
else {
|
|
938
|
-
getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
else {
|
|
942
|
-
const formValue = formValues[key];
|
|
943
|
-
dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
|
|
944
|
-
}
|
|
696
|
+
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
|
697
|
+
? {
|
|
698
|
+
...errors[name],
|
|
699
|
+
types: {
|
|
700
|
+
...(errors[name] && errors[name].types ? errors[name].types : {}),
|
|
701
|
+
[type]: message || true,
|
|
702
|
+
},
|
|
945
703
|
}
|
|
946
|
-
|
|
947
|
-
}
|
|
704
|
+
: {};
|
|
948
705
|
|
|
949
706
|
const defaultResult = {
|
|
950
707
|
value: false,
|
|
@@ -971,20 +728,6 @@ var getCheckboxValue = (options) => {
|
|
|
971
728
|
return defaultResult;
|
|
972
729
|
};
|
|
973
730
|
|
|
974
|
-
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
|
975
|
-
? value
|
|
976
|
-
: valueAsNumber
|
|
977
|
-
? value === ''
|
|
978
|
-
? NaN
|
|
979
|
-
: value
|
|
980
|
-
? +value
|
|
981
|
-
: value
|
|
982
|
-
: valueAsDate && isString(value)
|
|
983
|
-
? new Date(value)
|
|
984
|
-
: setValueAs
|
|
985
|
-
? setValueAs(value)
|
|
986
|
-
: value;
|
|
987
|
-
|
|
988
731
|
const defaultReturn = {
|
|
989
732
|
isValid: false,
|
|
990
733
|
value: null,
|
|
@@ -998,188 +741,6 @@ var getRadioValue = (options) => Array.isArray(options)
|
|
|
998
741
|
: previous, defaultReturn)
|
|
999
742
|
: defaultReturn;
|
|
1000
743
|
|
|
1001
|
-
function getFieldValue(_f) {
|
|
1002
|
-
const ref = _f.ref;
|
|
1003
|
-
if (isFileInput(ref)) {
|
|
1004
|
-
return ref.files;
|
|
1005
|
-
}
|
|
1006
|
-
if (isRadioInput(ref)) {
|
|
1007
|
-
return getRadioValue(_f.refs).value;
|
|
1008
|
-
}
|
|
1009
|
-
if (isMultipleSelect(ref)) {
|
|
1010
|
-
return [...ref.selectedOptions].map(({ value }) => value);
|
|
1011
|
-
}
|
|
1012
|
-
if (isCheckBoxInput(ref)) {
|
|
1013
|
-
return getCheckboxValue(_f.refs).value;
|
|
1014
|
-
}
|
|
1015
|
-
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
|
1016
|
-
}
|
|
1017
|
-
|
|
1018
|
-
var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
|
|
1019
|
-
|
|
1020
|
-
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
|
1021
|
-
const fields = {};
|
|
1022
|
-
for (const name of fieldsNames) {
|
|
1023
|
-
const field = get(_fields, name);
|
|
1024
|
-
field && set(fields, name, field._f);
|
|
1025
|
-
}
|
|
1026
|
-
return {
|
|
1027
|
-
criteriaMode,
|
|
1028
|
-
names: [...fieldsNames],
|
|
1029
|
-
fields,
|
|
1030
|
-
shouldUseNativeValidation,
|
|
1031
|
-
};
|
|
1032
|
-
};
|
|
1033
|
-
|
|
1034
|
-
var isRegex = (value) => value instanceof RegExp;
|
|
1035
|
-
|
|
1036
|
-
var getRuleValue = (rule) => isUndefined(rule)
|
|
1037
|
-
? rule
|
|
1038
|
-
: isRegex(rule)
|
|
1039
|
-
? rule.source
|
|
1040
|
-
: isObject(rule)
|
|
1041
|
-
? isRegex(rule.value)
|
|
1042
|
-
? rule.value.source
|
|
1043
|
-
: rule.value
|
|
1044
|
-
: rule;
|
|
1045
|
-
|
|
1046
|
-
var getValidationModes = (mode) => ({
|
|
1047
|
-
isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
|
|
1048
|
-
isOnBlur: mode === VALIDATION_MODE.onBlur,
|
|
1049
|
-
isOnChange: mode === VALIDATION_MODE.onChange,
|
|
1050
|
-
isOnAll: mode === VALIDATION_MODE.all,
|
|
1051
|
-
isOnTouch: mode === VALIDATION_MODE.onTouched,
|
|
1052
|
-
});
|
|
1053
|
-
|
|
1054
|
-
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
1055
|
-
var hasPromiseValidation = (fieldReference) => !!fieldReference &&
|
|
1056
|
-
!!fieldReference.validate &&
|
|
1057
|
-
!!((isFunction(fieldReference.validate) &&
|
|
1058
|
-
fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
|
|
1059
|
-
(isObject(fieldReference.validate) &&
|
|
1060
|
-
Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
|
|
1061
|
-
|
|
1062
|
-
var hasValidation = (options) => options.mount &&
|
|
1063
|
-
(options.required ||
|
|
1064
|
-
options.min ||
|
|
1065
|
-
options.max ||
|
|
1066
|
-
options.maxLength ||
|
|
1067
|
-
options.minLength ||
|
|
1068
|
-
options.pattern ||
|
|
1069
|
-
options.validate);
|
|
1070
|
-
|
|
1071
|
-
var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
|
|
1072
|
-
(_names.watchAll ||
|
|
1073
|
-
_names.watch.has(name) ||
|
|
1074
|
-
[..._names.watch].some((watchName) => name.startsWith(watchName) &&
|
|
1075
|
-
/^\.\w+/.test(name.slice(watchName.length))));
|
|
1076
|
-
|
|
1077
|
-
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
|
1078
|
-
for (const key of fieldsNames || Object.keys(fields)) {
|
|
1079
|
-
const field = get(fields, key);
|
|
1080
|
-
if (field) {
|
|
1081
|
-
const { _f, ...currentField } = field;
|
|
1082
|
-
if (_f) {
|
|
1083
|
-
if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
|
|
1084
|
-
return true;
|
|
1085
|
-
}
|
|
1086
|
-
else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
|
|
1087
|
-
return true;
|
|
1088
|
-
}
|
|
1089
|
-
else {
|
|
1090
|
-
if (iterateFieldsByAction(currentField, action)) {
|
|
1091
|
-
break;
|
|
1092
|
-
}
|
|
1093
|
-
}
|
|
1094
|
-
}
|
|
1095
|
-
else if (isObject(currentField)) {
|
|
1096
|
-
if (iterateFieldsByAction(currentField, action)) {
|
|
1097
|
-
break;
|
|
1098
|
-
}
|
|
1099
|
-
}
|
|
1100
|
-
}
|
|
1101
|
-
}
|
|
1102
|
-
return;
|
|
1103
|
-
};
|
|
1104
|
-
|
|
1105
|
-
function schemaErrorLookup(errors, _fields, name) {
|
|
1106
|
-
const error = get(errors, name);
|
|
1107
|
-
if (error || isKey(name)) {
|
|
1108
|
-
return {
|
|
1109
|
-
error,
|
|
1110
|
-
name,
|
|
1111
|
-
};
|
|
1112
|
-
}
|
|
1113
|
-
const names = name.split('.');
|
|
1114
|
-
while (names.length) {
|
|
1115
|
-
const fieldName = names.join('.');
|
|
1116
|
-
const field = get(_fields, fieldName);
|
|
1117
|
-
const foundError = get(errors, fieldName);
|
|
1118
|
-
if (field && !Array.isArray(field) && name !== fieldName) {
|
|
1119
|
-
return { name };
|
|
1120
|
-
}
|
|
1121
|
-
if (foundError && foundError.type) {
|
|
1122
|
-
return {
|
|
1123
|
-
name: fieldName,
|
|
1124
|
-
error: foundError,
|
|
1125
|
-
};
|
|
1126
|
-
}
|
|
1127
|
-
if (foundError && foundError.root && foundError.root.type) {
|
|
1128
|
-
return {
|
|
1129
|
-
name: `${fieldName}.root`,
|
|
1130
|
-
error: foundError.root,
|
|
1131
|
-
};
|
|
1132
|
-
}
|
|
1133
|
-
names.pop();
|
|
1134
|
-
}
|
|
1135
|
-
return {
|
|
1136
|
-
name,
|
|
1137
|
-
};
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
1141
|
-
updateFormState(formStateData);
|
|
1142
|
-
const { name, ...formState } = formStateData;
|
|
1143
|
-
return (isEmptyObject(formState) ||
|
|
1144
|
-
Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
|
|
1145
|
-
Object.keys(formState).find((key) => _proxyFormState[key] ===
|
|
1146
|
-
(!isRoot || VALIDATION_MODE.all)));
|
|
1147
|
-
};
|
|
1148
|
-
|
|
1149
|
-
var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
|
1150
|
-
!signalName ||
|
|
1151
|
-
name === signalName ||
|
|
1152
|
-
convertToArrayPayload(name).some((currentName) => currentName &&
|
|
1153
|
-
(exact
|
|
1154
|
-
? currentName === signalName
|
|
1155
|
-
: currentName.startsWith(signalName) ||
|
|
1156
|
-
signalName.startsWith(currentName)));
|
|
1157
|
-
|
|
1158
|
-
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
|
|
1159
|
-
if (mode.isOnAll) {
|
|
1160
|
-
return false;
|
|
1161
|
-
}
|
|
1162
|
-
else if (!isSubmitted && mode.isOnTouch) {
|
|
1163
|
-
return !(isTouched || isBlurEvent);
|
|
1164
|
-
}
|
|
1165
|
-
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
|
|
1166
|
-
return !isBlurEvent;
|
|
1167
|
-
}
|
|
1168
|
-
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
|
|
1169
|
-
return isBlurEvent;
|
|
1170
|
-
}
|
|
1171
|
-
return true;
|
|
1172
|
-
};
|
|
1173
|
-
|
|
1174
|
-
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
|
1175
|
-
|
|
1176
|
-
var updateFieldArrayRootError = (errors, error, name) => {
|
|
1177
|
-
const fieldArrayErrors = convertToArrayPayload(get(errors, name));
|
|
1178
|
-
set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
|
|
1179
|
-
set(errors, name, fieldArrayErrors);
|
|
1180
|
-
return errors;
|
|
1181
|
-
};
|
|
1182
|
-
|
|
1183
744
|
function getValidateError(result, ref, type = 'validate') {
|
|
1184
745
|
if (isString(result) ||
|
|
1185
746
|
(Array.isArray(result) && result.every(isString)) ||
|
|
@@ -1208,7 +769,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
|
|
|
1208
769
|
const inputRef = refs ? refs[0] : ref;
|
|
1209
770
|
const setCustomValidity = (message) => {
|
|
1210
771
|
if (shouldUseNativeValidation && inputRef.reportValidity) {
|
|
1211
|
-
|
|
772
|
+
const validityMessage = isBoolean(message) ? '' : message || '';
|
|
773
|
+
if (refs) {
|
|
774
|
+
refs.forEach((ref) => ref.setCustomValidity(validityMessage));
|
|
775
|
+
}
|
|
776
|
+
else {
|
|
777
|
+
inputRef.setCustomValidity(validityMessage);
|
|
778
|
+
}
|
|
1212
779
|
inputRef.reportValidity();
|
|
1213
780
|
}
|
|
1214
781
|
};
|
|
@@ -1378,374 +945,1420 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
|
|
|
1378
945
|
return error;
|
|
1379
946
|
};
|
|
1380
947
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
948
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
|
949
|
+
|
|
950
|
+
var appendAt = (data, value) => [
|
|
951
|
+
...data,
|
|
952
|
+
...convertToArrayPayload(value),
|
|
953
|
+
];
|
|
954
|
+
|
|
955
|
+
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
|
|
956
|
+
|
|
957
|
+
function insert(data, index, value) {
|
|
958
|
+
return [
|
|
959
|
+
...data.slice(0, index),
|
|
960
|
+
...convertToArrayPayload(value),
|
|
961
|
+
...data.slice(index),
|
|
962
|
+
];
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
var moveArrayAt = (data, from, to) => {
|
|
966
|
+
if (!Array.isArray(data)) {
|
|
967
|
+
return [];
|
|
968
|
+
}
|
|
969
|
+
if (isUndefined(data[to])) {
|
|
970
|
+
data[to] = undefined;
|
|
971
|
+
}
|
|
972
|
+
data.splice(to, 0, data.splice(from, 1)[0]);
|
|
973
|
+
return data;
|
|
1385
974
|
};
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
keepIsValid: false,
|
|
1419
|
-
};
|
|
1420
|
-
let _names = {
|
|
1421
|
-
mount: new Set(),
|
|
1422
|
-
disabled: new Set(),
|
|
1423
|
-
unMount: new Set(),
|
|
1424
|
-
array: new Set(),
|
|
1425
|
-
watch: new Set(),
|
|
1426
|
-
registerName: new Set(),
|
|
1427
|
-
};
|
|
1428
|
-
let delayErrorCallback;
|
|
1429
|
-
let timer = 0;
|
|
1430
|
-
const defaultProxyFormState = {
|
|
1431
|
-
isDirty: false,
|
|
1432
|
-
dirtyFields: false,
|
|
1433
|
-
validatingFields: false,
|
|
1434
|
-
touchedFields: false,
|
|
1435
|
-
isValidating: false,
|
|
1436
|
-
isValid: false,
|
|
1437
|
-
errors: false,
|
|
1438
|
-
};
|
|
1439
|
-
const _proxyFormState = {
|
|
1440
|
-
...defaultProxyFormState,
|
|
1441
|
-
};
|
|
1442
|
-
let _proxySubscribeFormState = {
|
|
1443
|
-
..._proxyFormState,
|
|
1444
|
-
};
|
|
1445
|
-
const _subjects = {
|
|
1446
|
-
array: createSubject(),
|
|
1447
|
-
state: createSubject(),
|
|
1448
|
-
};
|
|
1449
|
-
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
|
1450
|
-
const debounce = (callback) => (wait) => {
|
|
1451
|
-
clearTimeout(timer);
|
|
1452
|
-
timer = setTimeout(callback, wait);
|
|
1453
|
-
};
|
|
1454
|
-
const _setValid = async (shouldUpdateValid) => {
|
|
1455
|
-
if (_state.keepIsValid) {
|
|
1456
|
-
return;
|
|
975
|
+
|
|
976
|
+
var prependAt = (data, value) => [
|
|
977
|
+
...convertToArrayPayload(value),
|
|
978
|
+
...convertToArrayPayload(data),
|
|
979
|
+
];
|
|
980
|
+
|
|
981
|
+
var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
|
|
982
|
+
|
|
983
|
+
function removeAtIndexes(data, indexes) {
|
|
984
|
+
let i = 0;
|
|
985
|
+
const temp = [...data];
|
|
986
|
+
for (const index of indexes) {
|
|
987
|
+
temp.splice(index - i, 1);
|
|
988
|
+
i++;
|
|
989
|
+
}
|
|
990
|
+
return compact(temp).length ? temp : [];
|
|
991
|
+
}
|
|
992
|
+
var removeArrayAt = (data, index) => isUndefined(index)
|
|
993
|
+
? []
|
|
994
|
+
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
|
995
|
+
|
|
996
|
+
var swapArrayAt = (data, indexA, indexB) => {
|
|
997
|
+
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
|
998
|
+
};
|
|
999
|
+
|
|
1000
|
+
function baseGet(object, updatePath) {
|
|
1001
|
+
const length = updatePath.slice(0, -1).length;
|
|
1002
|
+
let index = 0;
|
|
1003
|
+
while (index < length) {
|
|
1004
|
+
if (isNullOrUndefined(object)) {
|
|
1005
|
+
object = undefined;
|
|
1006
|
+
break;
|
|
1457
1007
|
}
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
else {
|
|
1468
|
-
isValid = await executeBuiltInValidation({
|
|
1469
|
-
fields: _fields,
|
|
1470
|
-
onlyCheckValid: true,
|
|
1471
|
-
eventType: EVENTS.VALID,
|
|
1472
|
-
});
|
|
1473
|
-
}
|
|
1474
|
-
if (isValid !== _formState.isValid) {
|
|
1475
|
-
_subjects.state.next({
|
|
1476
|
-
isValid,
|
|
1477
|
-
});
|
|
1478
|
-
}
|
|
1008
|
+
object = object[updatePath[index]];
|
|
1009
|
+
index++;
|
|
1010
|
+
}
|
|
1011
|
+
return object;
|
|
1012
|
+
}
|
|
1013
|
+
function isEmptyArray(obj) {
|
|
1014
|
+
for (const key in obj) {
|
|
1015
|
+
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
|
1016
|
+
return false;
|
|
1479
1017
|
}
|
|
1480
|
-
}
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1018
|
+
}
|
|
1019
|
+
return true;
|
|
1020
|
+
}
|
|
1021
|
+
function unset(object, path) {
|
|
1022
|
+
if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
|
|
1023
|
+
delete object[path];
|
|
1024
|
+
return object;
|
|
1025
|
+
}
|
|
1026
|
+
const paths = Array.isArray(path)
|
|
1027
|
+
? path
|
|
1028
|
+
: isKey(path)
|
|
1029
|
+
? [path]
|
|
1030
|
+
: stringToPath(path);
|
|
1031
|
+
if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
|
|
1032
|
+
return object;
|
|
1033
|
+
}
|
|
1034
|
+
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
|
1035
|
+
const index = paths.length - 1;
|
|
1036
|
+
const key = paths[index];
|
|
1037
|
+
if (childObject) {
|
|
1038
|
+
delete childObject[key];
|
|
1039
|
+
}
|
|
1040
|
+
if (index !== 0 &&
|
|
1041
|
+
((isObject(childObject) && isEmptyObject(childObject)) ||
|
|
1042
|
+
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
|
1043
|
+
unset(object, paths.slice(0, -1));
|
|
1044
|
+
}
|
|
1045
|
+
return object;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
var updateAt = (fieldValues, index, value) => {
|
|
1049
|
+
fieldValues[index] = value;
|
|
1050
|
+
return fieldValues;
|
|
1051
|
+
};
|
|
1052
|
+
|
|
1053
|
+
/**
|
|
1054
|
+
* A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A)
|
|
1055
|
+
*
|
|
1056
|
+
* @remarks
|
|
1057
|
+
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
|
1058
|
+
*
|
|
1059
|
+
* @param props - useFieldArray props
|
|
1060
|
+
*
|
|
1061
|
+
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
|
1062
|
+
*
|
|
1063
|
+
* @example
|
|
1064
|
+
* ```tsx
|
|
1065
|
+
* function App() {
|
|
1066
|
+
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
|
1067
|
+
* defaultValues: {
|
|
1068
|
+
* test: []
|
|
1069
|
+
* }
|
|
1070
|
+
* });
|
|
1071
|
+
* const { fields, append } = useFieldArray({
|
|
1072
|
+
* control,
|
|
1073
|
+
* name: "test"
|
|
1074
|
+
* });
|
|
1075
|
+
*
|
|
1076
|
+
* return (
|
|
1077
|
+
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
|
1078
|
+
* {fields.map((item, index) => (
|
|
1079
|
+
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
|
1080
|
+
* ))}
|
|
1081
|
+
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
|
1082
|
+
* append
|
|
1083
|
+
* </button>
|
|
1084
|
+
* <input type="submit" />
|
|
1085
|
+
* </form>
|
|
1086
|
+
* );
|
|
1087
|
+
* }
|
|
1088
|
+
* ```
|
|
1089
|
+
*/
|
|
1090
|
+
function useFieldArray(props) {
|
|
1091
|
+
const formControl = useFormControlContext();
|
|
1092
|
+
const { control = formControl, name, keyName = 'id', disabled, shouldUnregister, rules, } = props;
|
|
1093
|
+
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
|
1094
|
+
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
|
1095
|
+
const _actioned = React.useRef(false);
|
|
1096
|
+
if (!disabled) {
|
|
1097
|
+
control._names.array.add(name);
|
|
1098
|
+
}
|
|
1099
|
+
React.useMemo(() => !disabled &&
|
|
1100
|
+
rules &&
|
|
1101
|
+
fields.length >= 0 &&
|
|
1102
|
+
control.register(name, rules), [control, name, fields.length, rules, disabled]);
|
|
1103
|
+
useIsomorphicLayoutEffect(() => {
|
|
1104
|
+
if (disabled) {
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
return control._subjects.array.subscribe({
|
|
1108
|
+
next: ({ values, name: fieldArrayName, }) => {
|
|
1109
|
+
if (fieldArrayName === name || !fieldArrayName) {
|
|
1110
|
+
const fieldValues = get(values, name);
|
|
1111
|
+
if (Array.isArray(fieldValues)) {
|
|
1112
|
+
setFields(fieldValues);
|
|
1113
|
+
ids.current = fieldValues.map(generateId);
|
|
1114
|
+
}
|
|
1115
|
+
else if (!fieldArrayName) {
|
|
1116
|
+
setFields([]);
|
|
1117
|
+
ids.current = [];
|
|
1118
|
+
}
|
|
1492
1119
|
}
|
|
1493
|
-
}
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1120
|
+
},
|
|
1121
|
+
}).unsubscribe;
|
|
1122
|
+
}, [control, name, disabled]);
|
|
1123
|
+
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
|
1124
|
+
_actioned.current = true;
|
|
1125
|
+
control._setFieldArray(name, updatedFieldArrayValues);
|
|
1126
|
+
}, [control, name]);
|
|
1127
|
+
const append = (value, options) => {
|
|
1128
|
+
if (disabled) {
|
|
1129
|
+
return;
|
|
1498
1130
|
}
|
|
1131
|
+
const appendValue = convertToArrayPayload(cloneObject(value));
|
|
1132
|
+
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
|
|
1133
|
+
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
|
|
1134
|
+
ids.current = appendAt(ids.current, appendValue.map(generateId));
|
|
1135
|
+
updateValues(updatedFieldArrayValues);
|
|
1136
|
+
setFields(updatedFieldArrayValues);
|
|
1137
|
+
control._setFieldArray(name, updatedFieldArrayValues, appendAt, {
|
|
1138
|
+
argA: fillEmptyArray(value),
|
|
1139
|
+
});
|
|
1499
1140
|
};
|
|
1500
|
-
const
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
set(_formState.dirtyFields, rootName, get(fullDirtyFields, rootName));
|
|
1504
|
-
};
|
|
1505
|
-
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
|
1506
|
-
if (args && method && !_options.disabled) {
|
|
1507
|
-
_state.action = true;
|
|
1508
|
-
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
|
|
1509
|
-
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
|
1510
|
-
shouldSetValues && set(_fields, name, fieldValues);
|
|
1511
|
-
}
|
|
1512
|
-
if (shouldUpdateFieldsAndState &&
|
|
1513
|
-
Array.isArray(get(_formState.errors, name))) {
|
|
1514
|
-
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
|
1515
|
-
shouldSetValues && set(_formState.errors, name, errors);
|
|
1516
|
-
unsetEmptyArray(_formState.errors, name);
|
|
1517
|
-
}
|
|
1518
|
-
if ((_proxyFormState.touchedFields ||
|
|
1519
|
-
_proxySubscribeFormState.touchedFields) &&
|
|
1520
|
-
shouldUpdateFieldsAndState &&
|
|
1521
|
-
Array.isArray(get(_formState.touchedFields, name))) {
|
|
1522
|
-
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
|
1523
|
-
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
|
1524
|
-
}
|
|
1525
|
-
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
|
1526
|
-
_updateDirtyFields(name);
|
|
1527
|
-
}
|
|
1528
|
-
_subjects.state.next({
|
|
1529
|
-
name,
|
|
1530
|
-
isDirty: _getDirty(name, values),
|
|
1531
|
-
dirtyFields: _formState.dirtyFields,
|
|
1532
|
-
errors: _formState.errors,
|
|
1533
|
-
isValid: _formState.isValid,
|
|
1534
|
-
});
|
|
1535
|
-
}
|
|
1536
|
-
else {
|
|
1537
|
-
set(_formValues, name, values);
|
|
1141
|
+
const prepend = (value, options) => {
|
|
1142
|
+
if (disabled) {
|
|
1143
|
+
return;
|
|
1538
1144
|
}
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1145
|
+
const prependValue = convertToArrayPayload(cloneObject(value));
|
|
1146
|
+
const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
|
|
1147
|
+
control._names.focus = getFocusFieldName(name, 0, options);
|
|
1148
|
+
ids.current = prependAt(ids.current, prependValue.map(generateId));
|
|
1149
|
+
updateValues(updatedFieldArrayValues);
|
|
1150
|
+
setFields(updatedFieldArrayValues);
|
|
1151
|
+
control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
|
|
1152
|
+
argA: fillEmptyArray(value),
|
|
1544
1153
|
});
|
|
1545
1154
|
};
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1155
|
+
const remove = (index) => {
|
|
1156
|
+
if (disabled) {
|
|
1157
|
+
return;
|
|
1158
|
+
}
|
|
1159
|
+
const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
|
|
1160
|
+
ids.current = removeArrayAt(ids.current, index);
|
|
1161
|
+
updateValues(updatedFieldArrayValues);
|
|
1162
|
+
setFields(updatedFieldArrayValues);
|
|
1163
|
+
!Array.isArray(get(control._fields, name)) &&
|
|
1164
|
+
set(control._fields, name, undefined);
|
|
1165
|
+
control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
|
|
1166
|
+
argA: index,
|
|
1551
1167
|
});
|
|
1552
1168
|
};
|
|
1553
|
-
const
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
|
|
1557
|
-
isUndefined(defaultValue) ||
|
|
1558
|
-
(ref && ref.defaultChecked) ||
|
|
1559
|
-
shouldSkipSetValueAs
|
|
1560
|
-
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
|
1561
|
-
: setFieldValue(name, defaultValue);
|
|
1562
|
-
_state.mount && !_state.action && _setValid();
|
|
1169
|
+
const insert$1 = (index, value, options) => {
|
|
1170
|
+
if (disabled) {
|
|
1171
|
+
return;
|
|
1563
1172
|
}
|
|
1173
|
+
const insertValue = convertToArrayPayload(cloneObject(value));
|
|
1174
|
+
const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
|
|
1175
|
+
control._names.focus = getFocusFieldName(name, index, options);
|
|
1176
|
+
ids.current = insert(ids.current, index, insertValue.map(generateId));
|
|
1177
|
+
updateValues(updatedFieldArrayValues);
|
|
1178
|
+
setFields(updatedFieldArrayValues);
|
|
1179
|
+
control._setFieldArray(name, updatedFieldArrayValues, insert, {
|
|
1180
|
+
argA: index,
|
|
1181
|
+
argB: fillEmptyArray(value),
|
|
1182
|
+
});
|
|
1564
1183
|
};
|
|
1565
|
-
const
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
const output = {
|
|
1569
|
-
name,
|
|
1570
|
-
};
|
|
1571
|
-
if (!_options.disabled) {
|
|
1572
|
-
if (!isBlurEvent || shouldDirty) {
|
|
1573
|
-
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
1574
|
-
isPreviousDirty = _formState.isDirty;
|
|
1575
|
-
_formState.isDirty = output.isDirty = _getDirty();
|
|
1576
|
-
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
1577
|
-
}
|
|
1578
|
-
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
1579
|
-
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
1580
|
-
isCurrentFieldPristine
|
|
1581
|
-
? unset(_formState.dirtyFields, name)
|
|
1582
|
-
: set(_formState.dirtyFields, name, true);
|
|
1583
|
-
output.dirtyFields = _formState.dirtyFields;
|
|
1584
|
-
shouldUpdateField =
|
|
1585
|
-
shouldUpdateField ||
|
|
1586
|
-
((_proxyFormState.dirtyFields ||
|
|
1587
|
-
_proxySubscribeFormState.dirtyFields) &&
|
|
1588
|
-
isPreviousDirty !== !isCurrentFieldPristine);
|
|
1589
|
-
}
|
|
1590
|
-
if (isBlurEvent) {
|
|
1591
|
-
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
|
1592
|
-
if (!isPreviousFieldTouched) {
|
|
1593
|
-
set(_formState.touchedFields, name, isBlurEvent);
|
|
1594
|
-
output.touchedFields = _formState.touchedFields;
|
|
1595
|
-
shouldUpdateField =
|
|
1596
|
-
shouldUpdateField ||
|
|
1597
|
-
((_proxyFormState.touchedFields ||
|
|
1598
|
-
_proxySubscribeFormState.touchedFields) &&
|
|
1599
|
-
isPreviousFieldTouched !== isBlurEvent);
|
|
1600
|
-
}
|
|
1601
|
-
}
|
|
1602
|
-
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
|
1603
|
-
}
|
|
1604
|
-
return shouldUpdateField ? output : {};
|
|
1605
|
-
};
|
|
1606
|
-
const shouldRenderByError = (name, isValid, error, fieldState) => {
|
|
1607
|
-
const previousFieldError = get(_formState.errors, name);
|
|
1608
|
-
const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
1609
|
-
isBoolean(isValid) &&
|
|
1610
|
-
_formState.isValid !== isValid;
|
|
1611
|
-
if (_options.delayError && error) {
|
|
1612
|
-
delayErrorCallback = debounce(() => updateErrors(name, error));
|
|
1613
|
-
delayErrorCallback(_options.delayError);
|
|
1614
|
-
}
|
|
1615
|
-
else {
|
|
1616
|
-
clearTimeout(timer);
|
|
1617
|
-
delayErrorCallback = null;
|
|
1618
|
-
error
|
|
1619
|
-
? set(_formState.errors, name, error)
|
|
1620
|
-
: unset(_formState.errors, name);
|
|
1621
|
-
}
|
|
1622
|
-
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
|
1623
|
-
!isEmptyObject(fieldState) ||
|
|
1624
|
-
shouldUpdateValid) {
|
|
1625
|
-
const updatedFormState = {
|
|
1626
|
-
...fieldState,
|
|
1627
|
-
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
|
1628
|
-
errors: _formState.errors,
|
|
1629
|
-
name,
|
|
1630
|
-
};
|
|
1631
|
-
_formState = {
|
|
1632
|
-
..._formState,
|
|
1633
|
-
...updatedFormState,
|
|
1634
|
-
};
|
|
1635
|
-
_subjects.state.next(updatedFormState);
|
|
1184
|
+
const swap = (indexA, indexB) => {
|
|
1185
|
+
if (disabled) {
|
|
1186
|
+
return;
|
|
1636
1187
|
}
|
|
1188
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
1189
|
+
swapArrayAt(updatedFieldArrayValues, indexA, indexB);
|
|
1190
|
+
swapArrayAt(ids.current, indexA, indexB);
|
|
1191
|
+
updateValues(updatedFieldArrayValues);
|
|
1192
|
+
setFields(updatedFieldArrayValues);
|
|
1193
|
+
control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
|
|
1194
|
+
argA: indexA,
|
|
1195
|
+
argB: indexB,
|
|
1196
|
+
}, false);
|
|
1637
1197
|
};
|
|
1638
|
-
const
|
|
1639
|
-
|
|
1640
|
-
|
|
1198
|
+
const move = (from, to) => {
|
|
1199
|
+
if (disabled) {
|
|
1200
|
+
return;
|
|
1201
|
+
}
|
|
1202
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
1203
|
+
moveArrayAt(updatedFieldArrayValues, from, to);
|
|
1204
|
+
moveArrayAt(ids.current, from, to);
|
|
1205
|
+
updateValues(updatedFieldArrayValues);
|
|
1206
|
+
setFields(updatedFieldArrayValues);
|
|
1207
|
+
control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
|
|
1208
|
+
argA: from,
|
|
1209
|
+
argB: to,
|
|
1210
|
+
}, false);
|
|
1641
1211
|
};
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
if (names) {
|
|
1646
|
-
for (const name of names) {
|
|
1647
|
-
const error = get(errors, name);
|
|
1648
|
-
error
|
|
1649
|
-
? set(_formState.errors, name, error)
|
|
1650
|
-
: unset(_formState.errors, name);
|
|
1651
|
-
}
|
|
1212
|
+
const update = (index, value) => {
|
|
1213
|
+
if (disabled) {
|
|
1214
|
+
return;
|
|
1652
1215
|
}
|
|
1653
|
-
|
|
1654
|
-
|
|
1216
|
+
const updateValue = cloneObject(value);
|
|
1217
|
+
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
|
|
1218
|
+
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
|
1219
|
+
updateValues(updatedFieldArrayValues);
|
|
1220
|
+
setFields([...updatedFieldArrayValues]);
|
|
1221
|
+
control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
|
|
1222
|
+
argA: index,
|
|
1223
|
+
argB: updateValue,
|
|
1224
|
+
}, true, false);
|
|
1225
|
+
};
|
|
1226
|
+
const replace = (value) => {
|
|
1227
|
+
if (disabled) {
|
|
1228
|
+
return;
|
|
1655
1229
|
}
|
|
1656
|
-
|
|
1230
|
+
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
|
|
1231
|
+
ids.current = updatedFieldArrayValues.map(generateId);
|
|
1232
|
+
updateValues([...updatedFieldArrayValues]);
|
|
1233
|
+
setFields([...updatedFieldArrayValues]);
|
|
1234
|
+
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
|
1657
1235
|
};
|
|
1658
|
-
|
|
1659
|
-
if (
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1236
|
+
React.useEffect(() => {
|
|
1237
|
+
if (disabled) {
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
control._state.action = false;
|
|
1241
|
+
isWatched(name, control._names) &&
|
|
1242
|
+
control._subjects.state.next({
|
|
1243
|
+
...control._formState,
|
|
1665
1244
|
});
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1245
|
+
const validationModes = getValidationModes(control._options.mode);
|
|
1246
|
+
if (_actioned.current &&
|
|
1247
|
+
(!validationModes.isOnSubmit || control._formState.isSubmitted) &&
|
|
1248
|
+
!getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
|
1249
|
+
!validationModes.isOnBlur) {
|
|
1250
|
+
if (control._options.resolver) {
|
|
1251
|
+
control._runSchema([name]).then((result) => {
|
|
1252
|
+
var _a, _b;
|
|
1253
|
+
control._updateIsValidating([name]);
|
|
1254
|
+
const error = get(result.errors, name);
|
|
1255
|
+
const existingError = get(control._formState.errors, name);
|
|
1256
|
+
const existingErrorType = existingError && (existingError.type || ((_a = existingError.root) === null || _a === void 0 ? void 0 : _a.type));
|
|
1257
|
+
const existingErrorMessage = existingError &&
|
|
1258
|
+
(existingError.message || ((_b = existingError.root) === null || _b === void 0 ? void 0 : _b.message));
|
|
1259
|
+
if (existingError
|
|
1260
|
+
? (!error && existingErrorType) ||
|
|
1261
|
+
(error &&
|
|
1262
|
+
(existingErrorType !== error.type ||
|
|
1263
|
+
existingErrorMessage !== error.message))
|
|
1264
|
+
: error && error.type) {
|
|
1265
|
+
if (error) {
|
|
1266
|
+
isObject(error) &&
|
|
1267
|
+
!Object.keys(error).some((key) => !Number.isNaN(+key))
|
|
1268
|
+
? updateFieldArrayRootError(control._formState.errors, { [name]: error }, name)
|
|
1269
|
+
: set(control._formState.errors, name, error);
|
|
1270
|
+
}
|
|
1271
|
+
else {
|
|
1272
|
+
unset(control._formState.errors, name);
|
|
1273
|
+
}
|
|
1274
|
+
control._subjects.state.next({
|
|
1275
|
+
errors: control._formState.errors,
|
|
1673
1276
|
});
|
|
1674
1277
|
}
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
else if (isString(result) || !result) {
|
|
1678
|
-
setError(FORM_ERROR_TYPE, {
|
|
1679
|
-
message: result || '',
|
|
1680
|
-
type: INPUT_VALIDATION_RULES.validate,
|
|
1681
1278
|
});
|
|
1682
1279
|
}
|
|
1683
1280
|
else {
|
|
1684
|
-
|
|
1281
|
+
const field = get(control._fields, name);
|
|
1282
|
+
if (field &&
|
|
1283
|
+
field._f &&
|
|
1284
|
+
!(getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
|
1285
|
+
getValidationModes(control._options.mode).isOnSubmit)) {
|
|
1286
|
+
validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
|
|
1287
|
+
control._subjects.state.next({
|
|
1288
|
+
errors: updateFieldArrayRootError(control._formState.errors, error, name),
|
|
1289
|
+
}));
|
|
1290
|
+
}
|
|
1685
1291
|
}
|
|
1686
|
-
return result;
|
|
1687
1292
|
}
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
}, }) => {
|
|
1694
|
-
if (props.validate) {
|
|
1695
|
-
context.runRootValidation = true;
|
|
1696
|
-
const result = await validateForm({
|
|
1293
|
+
// External updates that change `fields` (e.g. reset() or setValue() on
|
|
1294
|
+
// the array) already notify subscribers with the up-to-date values
|
|
1295
|
+
// themselves, so only re-broadcast here for genuine array method calls.
|
|
1296
|
+
_actioned.current &&
|
|
1297
|
+
control._subjects.state.next({
|
|
1697
1298
|
name,
|
|
1698
|
-
|
|
1299
|
+
values: cloneObject(control._formValues),
|
|
1699
1300
|
});
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
if (
|
|
1703
|
-
|
|
1301
|
+
control._names.focus &&
|
|
1302
|
+
iterateFieldsByAction(control._fields, (ref, key) => {
|
|
1303
|
+
if (control._names.focus &&
|
|
1304
|
+
key.startsWith(control._names.focus) &&
|
|
1305
|
+
ref.focus) {
|
|
1306
|
+
ref.focus();
|
|
1307
|
+
return 1;
|
|
1704
1308
|
}
|
|
1705
|
-
|
|
1309
|
+
return;
|
|
1310
|
+
});
|
|
1311
|
+
control._names.focus = '';
|
|
1312
|
+
control._setValid();
|
|
1313
|
+
_actioned.current = false;
|
|
1314
|
+
}, [fields, name, control, disabled]);
|
|
1315
|
+
React.useEffect(() => {
|
|
1316
|
+
if (!disabled) {
|
|
1317
|
+
!get(control._formValues, name) && control._setFieldArray(name);
|
|
1706
1318
|
}
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
}
|
|
1717
|
-
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
|
|
1718
|
-
if (isPromiseFunction && _proxyFormState.validatingFields) {
|
|
1719
|
-
_updateIsValidating([_f.name]);
|
|
1720
|
-
}
|
|
1721
|
-
if (fieldError[_f.name]) {
|
|
1722
|
-
context.valid = false;
|
|
1723
|
-
if (onlyCheckValid) {
|
|
1724
|
-
break;
|
|
1725
|
-
}
|
|
1726
|
-
}
|
|
1727
|
-
!onlyCheckValid &&
|
|
1728
|
-
(get(fieldError, _f.name)
|
|
1729
|
-
? isFieldArrayRoot
|
|
1730
|
-
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
|
1731
|
-
: set(_formState.errors, _f.name, fieldError[_f.name])
|
|
1732
|
-
: unset(_formState.errors, _f.name));
|
|
1733
|
-
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
|
|
1734
|
-
break;
|
|
1735
|
-
}
|
|
1319
|
+
return () => {
|
|
1320
|
+
if (disabled) {
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
|
|
1324
|
+
const updateMounted = (name, value) => {
|
|
1325
|
+
const field = get(control._fields, name);
|
|
1326
|
+
if (field && field._f) {
|
|
1327
|
+
field._f.mount = value;
|
|
1736
1328
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
eventType,
|
|
1744
|
-
}));
|
|
1329
|
+
};
|
|
1330
|
+
if (_actioned.current && shouldKeepFieldArrayValues) {
|
|
1331
|
+
control._subjects.state.next({
|
|
1332
|
+
name,
|
|
1333
|
+
values: cloneObject(control._formValues),
|
|
1334
|
+
});
|
|
1745
1335
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1336
|
+
shouldKeepFieldArrayValues
|
|
1337
|
+
? updateMounted(name, false)
|
|
1338
|
+
: control.unregister(name);
|
|
1339
|
+
};
|
|
1340
|
+
}, [name, control, keyName, shouldUnregister, disabled]);
|
|
1341
|
+
return {
|
|
1342
|
+
swap: React.useCallback(swap, [updateValues, name, control, disabled]),
|
|
1343
|
+
move: React.useCallback(move, [updateValues, name, control, disabled]),
|
|
1344
|
+
prepend: React.useCallback(prepend, [
|
|
1345
|
+
updateValues,
|
|
1346
|
+
name,
|
|
1347
|
+
control,
|
|
1348
|
+
disabled,
|
|
1349
|
+
]),
|
|
1350
|
+
append: React.useCallback(append, [updateValues, name, control, disabled]),
|
|
1351
|
+
remove: React.useCallback(remove, [updateValues, name, control, disabled]),
|
|
1352
|
+
insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
|
|
1353
|
+
update: React.useCallback(update, [updateValues, name, control, disabled]),
|
|
1354
|
+
replace: React.useCallback(replace, [
|
|
1355
|
+
updateValues,
|
|
1356
|
+
name,
|
|
1357
|
+
control,
|
|
1358
|
+
disabled,
|
|
1359
|
+
]),
|
|
1360
|
+
fields: React.useMemo(() => fields.map((field, index) => ({
|
|
1361
|
+
...field,
|
|
1362
|
+
...(isBoolean(disabled) ? { disabled } : {}),
|
|
1363
|
+
[keyName]: ids.current[index] || generateId(),
|
|
1364
|
+
})), [fields, keyName, disabled]),
|
|
1365
|
+
};
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Component based on `useFieldArray` hook to work with controlled component.
|
|
1370
|
+
*
|
|
1371
|
+
* @example
|
|
1372
|
+
* ```tsx
|
|
1373
|
+
* function App() {
|
|
1374
|
+
* const { control, register } = useForm<FormValues>({
|
|
1375
|
+
* defaultValues: {
|
|
1376
|
+
* test: [
|
|
1377
|
+
* {
|
|
1378
|
+
* value: '',
|
|
1379
|
+
* },
|
|
1380
|
+
* ],
|
|
1381
|
+
* },
|
|
1382
|
+
* });
|
|
1383
|
+
*
|
|
1384
|
+
* return (
|
|
1385
|
+
* <form>
|
|
1386
|
+
* <FieldArray
|
|
1387
|
+
* control={control}
|
|
1388
|
+
* name="test"
|
|
1389
|
+
* render={({ fields }) =>
|
|
1390
|
+
* fields.map((field, index) => (
|
|
1391
|
+
* <input key={field.id} {...register(`test.${index}.value`)} />
|
|
1392
|
+
* ))
|
|
1393
|
+
* }
|
|
1394
|
+
* />
|
|
1395
|
+
* </form>
|
|
1396
|
+
* );
|
|
1397
|
+
* }
|
|
1398
|
+
* ```
|
|
1399
|
+
*/
|
|
1400
|
+
const FieldArray = (props) => props.render(useFieldArray(props));
|
|
1401
|
+
|
|
1402
|
+
const flatten = (obj) => {
|
|
1403
|
+
const output = {};
|
|
1404
|
+
for (const key of Object.keys(obj)) {
|
|
1405
|
+
if (isObjectType(obj[key]) &&
|
|
1406
|
+
obj[key] !== null &&
|
|
1407
|
+
!isDateObject(obj[key])) {
|
|
1408
|
+
const nested = flatten(obj[key]);
|
|
1409
|
+
for (const nestedKey of Object.keys(nested)) {
|
|
1410
|
+
output[`${key}.${nestedKey}`] = nested[nestedKey];
|
|
1411
|
+
}
|
|
1412
|
+
}
|
|
1413
|
+
else {
|
|
1414
|
+
output[key] = obj[key];
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
return output;
|
|
1418
|
+
};
|
|
1419
|
+
|
|
1420
|
+
const HookFormContext = React.createContext(null);
|
|
1421
|
+
HookFormContext.displayName = 'HookFormContext';
|
|
1422
|
+
/**
|
|
1423
|
+
* This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
|
|
1424
|
+
*
|
|
1425
|
+
* @remarks
|
|
1426
|
+
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
1427
|
+
*
|
|
1428
|
+
* @returns return all useForm methods
|
|
1429
|
+
*
|
|
1430
|
+
* @example
|
|
1431
|
+
* ```tsx
|
|
1432
|
+
* function App() {
|
|
1433
|
+
* const methods = useForm();
|
|
1434
|
+
* const onSubmit = data => console.log(data);
|
|
1435
|
+
*
|
|
1436
|
+
* return (
|
|
1437
|
+
* <FormProvider {...methods} >
|
|
1438
|
+
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
1439
|
+
* <NestedInput />
|
|
1440
|
+
* <input type="submit" />
|
|
1441
|
+
* </form>
|
|
1442
|
+
* </FormProvider>
|
|
1443
|
+
* );
|
|
1444
|
+
* }
|
|
1445
|
+
*
|
|
1446
|
+
* function NestedInput() {
|
|
1447
|
+
* const { register } = useFormContext(); // retrieve all hook methods
|
|
1448
|
+
* return <input {...register("test")} />;
|
|
1449
|
+
* }
|
|
1450
|
+
* ```
|
|
1451
|
+
*/
|
|
1452
|
+
const useFormContext = () => React.useContext(HookFormContext);
|
|
1453
|
+
/**
|
|
1454
|
+
* A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
|
|
1455
|
+
*
|
|
1456
|
+
* @remarks
|
|
1457
|
+
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
1458
|
+
*
|
|
1459
|
+
* @param props - all useForm methods
|
|
1460
|
+
*
|
|
1461
|
+
* @example
|
|
1462
|
+
* ```tsx
|
|
1463
|
+
* function App() {
|
|
1464
|
+
* const methods = useForm();
|
|
1465
|
+
* const onSubmit = data => console.log(data);
|
|
1466
|
+
*
|
|
1467
|
+
* return (
|
|
1468
|
+
* <FormProvider {...methods} >
|
|
1469
|
+
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
1470
|
+
* <NestedInput />
|
|
1471
|
+
* <input type="submit" />
|
|
1472
|
+
* </form>
|
|
1473
|
+
* </FormProvider>
|
|
1474
|
+
* );
|
|
1475
|
+
* }
|
|
1476
|
+
*
|
|
1477
|
+
* function NestedInput() {
|
|
1478
|
+
* const { register } = useFormContext(); // retrieve all hook methods
|
|
1479
|
+
* return <input {...register("test")} />;
|
|
1480
|
+
* }
|
|
1481
|
+
* ```
|
|
1482
|
+
*/
|
|
1483
|
+
const FormProvider = ({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
|
|
1484
|
+
const memoizedValue = React.useMemo(() => ({
|
|
1485
|
+
watch,
|
|
1486
|
+
getValues,
|
|
1487
|
+
getFieldState,
|
|
1488
|
+
setError,
|
|
1489
|
+
clearErrors,
|
|
1490
|
+
setValue,
|
|
1491
|
+
setValues,
|
|
1492
|
+
trigger,
|
|
1493
|
+
formState,
|
|
1494
|
+
resetField,
|
|
1495
|
+
reset,
|
|
1496
|
+
resetDefaultValues,
|
|
1497
|
+
handleSubmit,
|
|
1498
|
+
unregister,
|
|
1499
|
+
control,
|
|
1500
|
+
register,
|
|
1501
|
+
setFocus,
|
|
1502
|
+
subscribe,
|
|
1503
|
+
}), [
|
|
1504
|
+
clearErrors,
|
|
1505
|
+
control,
|
|
1506
|
+
formState,
|
|
1507
|
+
getFieldState,
|
|
1508
|
+
getValues,
|
|
1509
|
+
handleSubmit,
|
|
1510
|
+
register,
|
|
1511
|
+
reset,
|
|
1512
|
+
resetDefaultValues,
|
|
1513
|
+
resetField,
|
|
1514
|
+
setError,
|
|
1515
|
+
setFocus,
|
|
1516
|
+
setValue,
|
|
1517
|
+
setValues,
|
|
1518
|
+
subscribe,
|
|
1519
|
+
trigger,
|
|
1520
|
+
unregister,
|
|
1521
|
+
watch,
|
|
1522
|
+
]);
|
|
1523
|
+
return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
|
|
1524
|
+
React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
|
|
1525
|
+
};
|
|
1526
|
+
|
|
1527
|
+
const POST_REQUEST = 'post';
|
|
1528
|
+
/**
|
|
1529
|
+
* Form component to manage submission.
|
|
1530
|
+
*
|
|
1531
|
+
* @param props - to setup submission detail. {@link FormProps}
|
|
1532
|
+
*
|
|
1533
|
+
* @returns form component or headless render prop.
|
|
1534
|
+
*
|
|
1535
|
+
* @example
|
|
1536
|
+
* ```tsx
|
|
1537
|
+
* function App() {
|
|
1538
|
+
* const { control, formState: { errors } } = useForm();
|
|
1539
|
+
*
|
|
1540
|
+
* return (
|
|
1541
|
+
* <Form action="/api" control={control}>
|
|
1542
|
+
* <input {...register("name")} />
|
|
1543
|
+
* <p>{errors?.root?.server && 'Server error'}</p>
|
|
1544
|
+
* <button>Submit</button>
|
|
1545
|
+
* </Form>
|
|
1546
|
+
* );
|
|
1547
|
+
* }
|
|
1548
|
+
* ```
|
|
1549
|
+
*/
|
|
1550
|
+
function Form(props) {
|
|
1551
|
+
const methods = useFormContext();
|
|
1552
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1553
|
+
const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
|
|
1554
|
+
const submit = React.useCallback(async (event) => {
|
|
1555
|
+
let hasError = false;
|
|
1556
|
+
let type = '';
|
|
1557
|
+
await control.handleSubmit(async (data) => {
|
|
1558
|
+
const formData = new FormData();
|
|
1559
|
+
let formDataJson = '';
|
|
1560
|
+
try {
|
|
1561
|
+
formDataJson = JSON.stringify(data);
|
|
1562
|
+
}
|
|
1563
|
+
catch (_a) { }
|
|
1564
|
+
const flattenFormValues = flatten(data);
|
|
1565
|
+
for (const key in flattenFormValues) {
|
|
1566
|
+
formData.append(key, flattenFormValues[key]);
|
|
1567
|
+
}
|
|
1568
|
+
if (onSubmit) {
|
|
1569
|
+
await onSubmit({
|
|
1570
|
+
data,
|
|
1571
|
+
event,
|
|
1572
|
+
method,
|
|
1573
|
+
formData,
|
|
1574
|
+
formDataJson,
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1577
|
+
if (action) {
|
|
1578
|
+
try {
|
|
1579
|
+
const shouldStringifySubmissionData = [
|
|
1580
|
+
headers && headers['Content-Type'],
|
|
1581
|
+
encType,
|
|
1582
|
+
].some((value) => value && value.includes('json'));
|
|
1583
|
+
const response = await fetch(String(action), {
|
|
1584
|
+
method,
|
|
1585
|
+
headers: {
|
|
1586
|
+
...headers,
|
|
1587
|
+
...(encType && encType !== 'multipart/form-data'
|
|
1588
|
+
? { 'Content-Type': encType }
|
|
1589
|
+
: {}),
|
|
1590
|
+
},
|
|
1591
|
+
body: shouldStringifySubmissionData ? formDataJson : formData,
|
|
1592
|
+
});
|
|
1593
|
+
if (response &&
|
|
1594
|
+
(validateStatus
|
|
1595
|
+
? !validateStatus(response.status)
|
|
1596
|
+
: response.status < 200 || response.status >= 300)) {
|
|
1597
|
+
hasError = true;
|
|
1598
|
+
onError && onError({ response });
|
|
1599
|
+
type = String(response.status);
|
|
1600
|
+
}
|
|
1601
|
+
else {
|
|
1602
|
+
onSuccess && onSuccess({ response });
|
|
1603
|
+
}
|
|
1604
|
+
}
|
|
1605
|
+
catch (error) {
|
|
1606
|
+
hasError = true;
|
|
1607
|
+
onError && onError({ error });
|
|
1608
|
+
}
|
|
1609
|
+
}
|
|
1610
|
+
})(event);
|
|
1611
|
+
if (hasError && control) {
|
|
1612
|
+
control._subjects.state.next({
|
|
1613
|
+
isSubmitSuccessful: false,
|
|
1614
|
+
});
|
|
1615
|
+
control.setError('root.server', {
|
|
1616
|
+
type,
|
|
1617
|
+
});
|
|
1618
|
+
}
|
|
1619
|
+
}, [
|
|
1620
|
+
control,
|
|
1621
|
+
onSubmit,
|
|
1622
|
+
method,
|
|
1623
|
+
action,
|
|
1624
|
+
headers,
|
|
1625
|
+
encType,
|
|
1626
|
+
validateStatus,
|
|
1627
|
+
onError,
|
|
1628
|
+
onSuccess,
|
|
1629
|
+
]);
|
|
1630
|
+
React.useEffect(() => {
|
|
1631
|
+
setMounted(true);
|
|
1632
|
+
}, []);
|
|
1633
|
+
return render ? (React.createElement(React.Fragment, null, render({
|
|
1634
|
+
submit,
|
|
1635
|
+
}))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
|
|
1639
|
+
|
|
1640
|
+
var createSubject = () => {
|
|
1641
|
+
let _observers = [];
|
|
1642
|
+
const next = (value) => {
|
|
1643
|
+
for (const observer of _observers) {
|
|
1644
|
+
observer.next && observer.next(value);
|
|
1645
|
+
}
|
|
1646
|
+
};
|
|
1647
|
+
const subscribe = (observer) => {
|
|
1648
|
+
_observers.push(observer);
|
|
1649
|
+
return {
|
|
1650
|
+
unsubscribe: () => {
|
|
1651
|
+
_observers = _observers.filter((o) => o !== observer);
|
|
1652
|
+
},
|
|
1653
|
+
};
|
|
1654
|
+
};
|
|
1655
|
+
const unsubscribe = () => {
|
|
1656
|
+
_observers = [];
|
|
1657
|
+
};
|
|
1658
|
+
return {
|
|
1659
|
+
get observers() {
|
|
1660
|
+
return _observers;
|
|
1661
|
+
},
|
|
1662
|
+
next,
|
|
1663
|
+
subscribe,
|
|
1664
|
+
unsubscribe,
|
|
1665
|
+
};
|
|
1666
|
+
};
|
|
1667
|
+
|
|
1668
|
+
function extractFormValues(fieldsState, formValues) {
|
|
1669
|
+
const values = {};
|
|
1670
|
+
for (const key in fieldsState) {
|
|
1671
|
+
if (fieldsState.hasOwnProperty(key)) {
|
|
1672
|
+
const fieldState = fieldsState[key];
|
|
1673
|
+
const fieldValue = formValues[key];
|
|
1674
|
+
if (fieldState && isObject(fieldState) && fieldValue) {
|
|
1675
|
+
const nestedFieldsState = extractFormValues(fieldState, fieldValue);
|
|
1676
|
+
if (isObject(nestedFieldsState)) {
|
|
1677
|
+
values[key] = nestedFieldsState;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
else if (fieldsState[key]) {
|
|
1681
|
+
values[key] = fieldValue;
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1685
|
+
return values;
|
|
1686
|
+
}
|
|
1687
|
+
|
|
1688
|
+
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
|
1689
|
+
|
|
1690
|
+
var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
|
1691
|
+
|
|
1692
|
+
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
|
1693
|
+
|
|
1694
|
+
var objectHasFunction = (data) => {
|
|
1695
|
+
for (const key in data) {
|
|
1696
|
+
if (isFunction(data[key])) {
|
|
1697
|
+
return true;
|
|
1698
|
+
}
|
|
1699
|
+
}
|
|
1700
|
+
return false;
|
|
1701
|
+
};
|
|
1702
|
+
|
|
1703
|
+
function isTraversable(value) {
|
|
1704
|
+
return Array.isArray(value) || (isObject(value) && !objectHasFunction(value));
|
|
1705
|
+
}
|
|
1706
|
+
function isRegisteredLeaf(fieldRef) {
|
|
1707
|
+
return !!(fieldRef && '_f' in fieldRef);
|
|
1708
|
+
}
|
|
1709
|
+
function isEmptyDirtyContainer(value) {
|
|
1710
|
+
return Array.isArray(value)
|
|
1711
|
+
? !value.some((item) => !isUndefined(item))
|
|
1712
|
+
: !Object.keys(value).length;
|
|
1713
|
+
}
|
|
1714
|
+
function clearDirtyField(container, key) {
|
|
1715
|
+
if (Array.isArray(container)) {
|
|
1716
|
+
container[key] = undefined;
|
|
1717
|
+
}
|
|
1718
|
+
else {
|
|
1719
|
+
delete container[key];
|
|
1720
|
+
}
|
|
1721
|
+
}
|
|
1722
|
+
function markFieldsDirty(data, fields = {}, fieldRefs) {
|
|
1723
|
+
for (const key in data) {
|
|
1724
|
+
const value = data[key];
|
|
1725
|
+
const fieldRef = fieldRefs && fieldRefs[key];
|
|
1726
|
+
if (isTraversable(value) &&
|
|
1727
|
+
(!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
|
|
1728
|
+
fields[key] = Array.isArray(value) ? [] : {};
|
|
1729
|
+
markFieldsDirty(value, fields[key], fieldRef);
|
|
1730
|
+
if (isEmptyDirtyContainer(fields[key])) {
|
|
1731
|
+
clearDirtyField(fields, key);
|
|
1732
|
+
}
|
|
1733
|
+
}
|
|
1734
|
+
else if (!isUndefined(value)) {
|
|
1735
|
+
fields[key] = true;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
return fields;
|
|
1739
|
+
}
|
|
1740
|
+
function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
|
|
1741
|
+
if (!dirtyFieldsFromValues) {
|
|
1742
|
+
dirtyFieldsFromValues = markFieldsDirty(formValues, {}, fieldRefs);
|
|
1743
|
+
}
|
|
1744
|
+
for (const key in data) {
|
|
1745
|
+
const value = data[key];
|
|
1746
|
+
const fieldRef = fieldRefs && fieldRefs[key];
|
|
1747
|
+
if (isTraversable(value) &&
|
|
1748
|
+
(!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
|
|
1749
|
+
if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
|
|
1750
|
+
dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}, fieldRef);
|
|
1751
|
+
}
|
|
1752
|
+
else {
|
|
1753
|
+
getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key], fieldRef);
|
|
1754
|
+
}
|
|
1755
|
+
if (isEmptyDirtyContainer(dirtyFieldsFromValues[key])) {
|
|
1756
|
+
clearDirtyField(dirtyFieldsFromValues, key);
|
|
1757
|
+
}
|
|
1758
|
+
}
|
|
1759
|
+
else if (deepEqual(value, formValues[key])) {
|
|
1760
|
+
clearDirtyField(dirtyFieldsFromValues, key);
|
|
1761
|
+
}
|
|
1762
|
+
else {
|
|
1763
|
+
dirtyFieldsFromValues[key] = true;
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
return dirtyFieldsFromValues;
|
|
1767
|
+
}
|
|
1768
|
+
|
|
1769
|
+
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
|
1770
|
+
? value
|
|
1771
|
+
: valueAsNumber
|
|
1772
|
+
? value === ''
|
|
1773
|
+
? NaN
|
|
1774
|
+
: value
|
|
1775
|
+
? +value
|
|
1776
|
+
: value
|
|
1777
|
+
: valueAsDate && isString(value)
|
|
1778
|
+
? new Date(value)
|
|
1779
|
+
: setValueAs
|
|
1780
|
+
? setValueAs(value)
|
|
1781
|
+
: value;
|
|
1782
|
+
|
|
1783
|
+
function getFieldValue(_f) {
|
|
1784
|
+
const ref = _f.ref;
|
|
1785
|
+
if (isFileInput(ref)) {
|
|
1786
|
+
return ref.files;
|
|
1787
|
+
}
|
|
1788
|
+
if (isRadioInput(ref)) {
|
|
1789
|
+
return getRadioValue(_f.refs).value;
|
|
1790
|
+
}
|
|
1791
|
+
if (isMultipleSelect(ref)) {
|
|
1792
|
+
return [...ref.selectedOptions].map(({ value }) => value);
|
|
1793
|
+
}
|
|
1794
|
+
if (isCheckBoxInput(ref)) {
|
|
1795
|
+
return getCheckboxValue(_f.refs).value;
|
|
1796
|
+
}
|
|
1797
|
+
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
|
1798
|
+
}
|
|
1799
|
+
|
|
1800
|
+
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
|
1801
|
+
const fields = {};
|
|
1802
|
+
for (const name of fieldsNames) {
|
|
1803
|
+
const field = get(_fields, name);
|
|
1804
|
+
field && set(fields, name, field._f);
|
|
1805
|
+
}
|
|
1806
|
+
return {
|
|
1807
|
+
criteriaMode,
|
|
1808
|
+
names: [...fieldsNames],
|
|
1809
|
+
fields,
|
|
1810
|
+
shouldUseNativeValidation,
|
|
1811
|
+
};
|
|
1812
|
+
};
|
|
1813
|
+
|
|
1814
|
+
var getRuleValue = (rule) => isUndefined(rule)
|
|
1815
|
+
? rule
|
|
1816
|
+
: isRegex(rule)
|
|
1817
|
+
? rule.source
|
|
1818
|
+
: isObject(rule)
|
|
1819
|
+
? isRegex(rule.value)
|
|
1820
|
+
? rule.value.source
|
|
1821
|
+
: rule.value
|
|
1822
|
+
: rule;
|
|
1823
|
+
|
|
1824
|
+
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
1825
|
+
var hasPromiseValidation = (fieldReference) => {
|
|
1826
|
+
if (!fieldReference || !fieldReference.validate)
|
|
1827
|
+
return false;
|
|
1828
|
+
if (isFunction(fieldReference.validate)) {
|
|
1829
|
+
return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
|
|
1830
|
+
}
|
|
1831
|
+
if (isObject(fieldReference.validate)) {
|
|
1832
|
+
for (const key in fieldReference.validate) {
|
|
1833
|
+
if (fieldReference.validate[key].constructor
|
|
1834
|
+
.name === ASYNC_FUNCTION) {
|
|
1835
|
+
return true;
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1839
|
+
return false;
|
|
1840
|
+
};
|
|
1841
|
+
|
|
1842
|
+
var hasValidation = (options) => options.mount &&
|
|
1843
|
+
(options.required ||
|
|
1844
|
+
options.min ||
|
|
1845
|
+
options.max ||
|
|
1846
|
+
options.maxLength ||
|
|
1847
|
+
options.minLength ||
|
|
1848
|
+
options.pattern ||
|
|
1849
|
+
options.validate);
|
|
1850
|
+
|
|
1851
|
+
function schemaErrorLookup(errors, _fields, name) {
|
|
1852
|
+
const error = get(errors, name);
|
|
1853
|
+
if (error || isKey(name)) {
|
|
1854
|
+
return {
|
|
1855
|
+
error,
|
|
1856
|
+
name,
|
|
1857
|
+
};
|
|
1858
|
+
}
|
|
1859
|
+
const names = name.split('.');
|
|
1860
|
+
while (names.length) {
|
|
1861
|
+
const fieldName = names.join('.');
|
|
1862
|
+
const field = get(_fields, fieldName);
|
|
1863
|
+
const foundError = get(errors, fieldName);
|
|
1864
|
+
if (field && !Array.isArray(field) && name !== fieldName) {
|
|
1865
|
+
return { name };
|
|
1866
|
+
}
|
|
1867
|
+
if (foundError && foundError.type) {
|
|
1868
|
+
return {
|
|
1869
|
+
name: fieldName,
|
|
1870
|
+
error: foundError,
|
|
1871
|
+
};
|
|
1872
|
+
}
|
|
1873
|
+
if (foundError && foundError.root && foundError.root.type) {
|
|
1874
|
+
return {
|
|
1875
|
+
name: `${fieldName}.root`,
|
|
1876
|
+
error: foundError.root,
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
names.pop();
|
|
1880
|
+
}
|
|
1881
|
+
return {
|
|
1882
|
+
name,
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
1887
|
+
updateFormState(formStateData);
|
|
1888
|
+
const { name, ...formState } = formStateData;
|
|
1889
|
+
const keys = Object.keys(formState);
|
|
1890
|
+
return (!keys.length ||
|
|
1891
|
+
(isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
|
|
1892
|
+
keys.find((key) => _proxyFormState[key] ===
|
|
1893
|
+
(!isRoot || VALIDATION_MODE.all)));
|
|
1894
|
+
};
|
|
1895
|
+
|
|
1896
|
+
var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
|
1897
|
+
!signalName ||
|
|
1898
|
+
name === signalName ||
|
|
1899
|
+
convertToArrayPayload(name).some((currentName) => currentName &&
|
|
1900
|
+
(exact
|
|
1901
|
+
? currentName === signalName || currentName.startsWith(signalName + '.')
|
|
1902
|
+
: currentName.startsWith(signalName) ||
|
|
1903
|
+
signalName.startsWith(currentName)));
|
|
1904
|
+
|
|
1905
|
+
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
|
|
1906
|
+
if (mode.isOnAll) {
|
|
1907
|
+
return false;
|
|
1908
|
+
}
|
|
1909
|
+
else if (!isSubmitted && mode.isOnTouch) {
|
|
1910
|
+
return !(isTouched || isBlurEvent);
|
|
1911
|
+
}
|
|
1912
|
+
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
|
|
1913
|
+
return !isBlurEvent;
|
|
1914
|
+
}
|
|
1915
|
+
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
|
|
1916
|
+
return isBlurEvent;
|
|
1917
|
+
}
|
|
1918
|
+
return true;
|
|
1919
|
+
};
|
|
1920
|
+
|
|
1921
|
+
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
|
1922
|
+
|
|
1923
|
+
const defaultOptions = {
|
|
1924
|
+
mode: VALIDATION_MODE.onSubmit,
|
|
1925
|
+
reValidateMode: VALIDATION_MODE.onChange,
|
|
1926
|
+
shouldFocusError: true,
|
|
1927
|
+
};
|
|
1928
|
+
const FORM_ERROR_TYPE = 'form';
|
|
1929
|
+
const updateDirtyFields = (dirtyFields, nextDirtyFields) => {
|
|
1930
|
+
for (const key in dirtyFields) {
|
|
1931
|
+
if (!(key in nextDirtyFields)) {
|
|
1932
|
+
delete dirtyFields[key];
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
Object.assign(dirtyFields, nextDirtyFields);
|
|
1936
|
+
};
|
|
1937
|
+
const DEFAULT_FORM_STATE = {
|
|
1938
|
+
submitCount: 0,
|
|
1939
|
+
isDirty: false,
|
|
1940
|
+
isReady: false,
|
|
1941
|
+
isValidating: false,
|
|
1942
|
+
isSubmitted: false,
|
|
1943
|
+
isSubmitting: false,
|
|
1944
|
+
isSubmitSuccessful: false,
|
|
1945
|
+
isValid: false,
|
|
1946
|
+
touchedFields: {},
|
|
1947
|
+
dirtyFields: {},
|
|
1948
|
+
validatingFields: {},
|
|
1949
|
+
};
|
|
1950
|
+
function createFormControl(props = {}) {
|
|
1951
|
+
let _options = {
|
|
1952
|
+
...defaultOptions,
|
|
1953
|
+
...props,
|
|
1954
|
+
};
|
|
1955
|
+
let _formState = {
|
|
1956
|
+
...cloneObject(DEFAULT_FORM_STATE),
|
|
1957
|
+
isLoading: isFunction(_options.defaultValues),
|
|
1958
|
+
errors: _options.errors || {},
|
|
1959
|
+
disabled: _options.disabled || false,
|
|
1960
|
+
};
|
|
1961
|
+
let _fields = {};
|
|
1962
|
+
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
|
|
1963
|
+
? cloneObject(_options.defaultValues || _options.values) || {}
|
|
1964
|
+
: {};
|
|
1965
|
+
let _formValues = _options.shouldUnregister
|
|
1966
|
+
? {}
|
|
1967
|
+
: cloneObject(_defaultValues);
|
|
1968
|
+
let _state = {
|
|
1969
|
+
action: false,
|
|
1970
|
+
mount: false,
|
|
1971
|
+
watch: false,
|
|
1972
|
+
keepIsValid: false,
|
|
1973
|
+
};
|
|
1974
|
+
let _names = {
|
|
1975
|
+
mount: new Set(),
|
|
1976
|
+
disabled: new Set(),
|
|
1977
|
+
unMount: new Set(),
|
|
1978
|
+
array: new Set(),
|
|
1979
|
+
watch: new Set(),
|
|
1980
|
+
registerName: new Set(),
|
|
1981
|
+
};
|
|
1982
|
+
const delayErrorCallbacks = {};
|
|
1983
|
+
const timers = {};
|
|
1984
|
+
let _valuesSubscriberCount = 0;
|
|
1985
|
+
let _validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
1986
|
+
let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1987
|
+
const defaultProxyFormState = {
|
|
1988
|
+
isDirty: false,
|
|
1989
|
+
dirtyFields: false,
|
|
1990
|
+
validatingFields: false,
|
|
1991
|
+
touchedFields: false,
|
|
1992
|
+
isValidating: false,
|
|
1993
|
+
isValid: false,
|
|
1994
|
+
errors: false,
|
|
1995
|
+
};
|
|
1996
|
+
const _proxyFormState = {
|
|
1997
|
+
...defaultProxyFormState,
|
|
1998
|
+
};
|
|
1999
|
+
let _proxySubscribeFormState = {
|
|
2000
|
+
..._proxyFormState,
|
|
2001
|
+
};
|
|
2002
|
+
const _subjects = {
|
|
2003
|
+
array: createSubject(),
|
|
2004
|
+
state: createSubject(),
|
|
2005
|
+
};
|
|
2006
|
+
let _setValidCallId = 0;
|
|
2007
|
+
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
|
2008
|
+
const debounce = (name, callback) => (wait) => {
|
|
2009
|
+
clearTimeout(timers[name]);
|
|
2010
|
+
timers[name] = setTimeout(callback, wait);
|
|
2011
|
+
};
|
|
2012
|
+
const _setValid = async (shouldUpdateValid) => {
|
|
2013
|
+
if (_state.keepIsValid) {
|
|
2014
|
+
return;
|
|
2015
|
+
}
|
|
2016
|
+
if (!_options.disabled &&
|
|
2017
|
+
(_proxyFormState.isValid ||
|
|
2018
|
+
_proxySubscribeFormState.isValid ||
|
|
2019
|
+
shouldUpdateValid)) {
|
|
2020
|
+
const callId = ++_setValidCallId;
|
|
2021
|
+
let isValid;
|
|
2022
|
+
if (_options.resolver) {
|
|
2023
|
+
isValid = isEmptyObject((await _runSchema()).errors);
|
|
2024
|
+
callId === _setValidCallId && _updateIsValidating();
|
|
2025
|
+
}
|
|
2026
|
+
else {
|
|
2027
|
+
isValid = await executeBuiltInValidation({
|
|
2028
|
+
fields: _fields,
|
|
2029
|
+
onlyCheckValid: true,
|
|
2030
|
+
eventType: EVENTS.VALID,
|
|
2031
|
+
});
|
|
2032
|
+
}
|
|
2033
|
+
if (callId === _setValidCallId && isValid !== _formState.isValid) {
|
|
2034
|
+
_subjects.state.next({
|
|
2035
|
+
isValid,
|
|
2036
|
+
});
|
|
2037
|
+
}
|
|
2038
|
+
}
|
|
2039
|
+
};
|
|
2040
|
+
const _updateIsValidating = (names, isValidating) => {
|
|
2041
|
+
if (!_options.disabled &&
|
|
2042
|
+
(_proxyFormState.isValidating ||
|
|
2043
|
+
_proxyFormState.validatingFields ||
|
|
2044
|
+
_proxySubscribeFormState.isValidating ||
|
|
2045
|
+
_proxySubscribeFormState.validatingFields)) {
|
|
2046
|
+
(names || Array.from(_names.mount)).forEach((name) => {
|
|
2047
|
+
if (name) {
|
|
2048
|
+
isValidating
|
|
2049
|
+
? set(_formState.validatingFields, name, isValidating)
|
|
2050
|
+
: unset(_formState.validatingFields, name);
|
|
2051
|
+
}
|
|
2052
|
+
});
|
|
2053
|
+
_subjects.state.next({
|
|
2054
|
+
validatingFields: _formState.validatingFields,
|
|
2055
|
+
isValidating: !isEmptyObject(_formState.validatingFields),
|
|
2056
|
+
});
|
|
2057
|
+
}
|
|
2058
|
+
};
|
|
2059
|
+
const _updateDirtyFields = () => {
|
|
2060
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
2061
|
+
};
|
|
2062
|
+
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
|
2063
|
+
if (args && method && !_options.disabled) {
|
|
2064
|
+
_state.action = true;
|
|
2065
|
+
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
|
|
2066
|
+
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
|
2067
|
+
shouldSetValues && set(_fields, name, fieldValues);
|
|
2068
|
+
}
|
|
2069
|
+
if (shouldUpdateFieldsAndState &&
|
|
2070
|
+
Array.isArray(get(_formState.errors, name))) {
|
|
2071
|
+
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
|
2072
|
+
shouldSetValues && set(_formState.errors, name, errors);
|
|
2073
|
+
unsetEmptyArray(_formState.errors, name);
|
|
2074
|
+
}
|
|
2075
|
+
if ((_proxyFormState.touchedFields ||
|
|
2076
|
+
_proxySubscribeFormState.touchedFields) &&
|
|
2077
|
+
shouldUpdateFieldsAndState &&
|
|
2078
|
+
Array.isArray(get(_formState.touchedFields, name))) {
|
|
2079
|
+
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
|
2080
|
+
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
|
2081
|
+
}
|
|
2082
|
+
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
|
2083
|
+
_updateDirtyFields();
|
|
2084
|
+
}
|
|
2085
|
+
_subjects.state.next({
|
|
2086
|
+
name,
|
|
2087
|
+
isDirty: _getDirty(name, values),
|
|
2088
|
+
dirtyFields: _formState.dirtyFields,
|
|
2089
|
+
errors: _formState.errors,
|
|
2090
|
+
isValid: _formState.isValid,
|
|
2091
|
+
});
|
|
2092
|
+
}
|
|
2093
|
+
else {
|
|
2094
|
+
set(_formValues, name, values);
|
|
2095
|
+
}
|
|
2096
|
+
};
|
|
2097
|
+
const updateErrors = (name, error) => {
|
|
2098
|
+
set(_formState.errors, name, error);
|
|
2099
|
+
_formState.errors = { ..._formState.errors };
|
|
2100
|
+
_subjects.state.next({
|
|
2101
|
+
errors: _formState.errors,
|
|
2102
|
+
});
|
|
2103
|
+
};
|
|
2104
|
+
const _setErrors = (errors) => {
|
|
2105
|
+
_formState.errors = errors;
|
|
2106
|
+
_subjects.state.next({
|
|
2107
|
+
errors: _formState.errors,
|
|
2108
|
+
isValid: false,
|
|
2109
|
+
});
|
|
2110
|
+
};
|
|
2111
|
+
const hasExplicitNullIntermediate = (name) => {
|
|
2112
|
+
const segments = isKey(name) ? [name] : stringToPath(name);
|
|
2113
|
+
let formValues = _formValues;
|
|
2114
|
+
let defaultValues = _defaultValues;
|
|
2115
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
2116
|
+
const key = segments[i];
|
|
2117
|
+
formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
|
|
2118
|
+
defaultValues = isNullOrUndefined(defaultValues)
|
|
2119
|
+
? defaultValues
|
|
2120
|
+
: defaultValues[key];
|
|
2121
|
+
if (formValues === null && defaultValues !== null) {
|
|
2122
|
+
return true;
|
|
2123
|
+
}
|
|
2124
|
+
}
|
|
2125
|
+
return false;
|
|
2126
|
+
};
|
|
2127
|
+
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
|
|
2128
|
+
const field = get(_fields, name);
|
|
2129
|
+
if (field) {
|
|
2130
|
+
if (hasExplicitNullIntermediate(name)) {
|
|
2131
|
+
return;
|
|
2132
|
+
}
|
|
2133
|
+
const wasUnsetInFormValues = isUndefined(get(_formValues, name));
|
|
2134
|
+
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
|
|
2135
|
+
isUndefined(defaultValue) ||
|
|
2136
|
+
(ref && ref.defaultChecked) ||
|
|
2137
|
+
shouldSkipSetValueAs
|
|
2138
|
+
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
|
2139
|
+
: setFieldValue(name, defaultValue);
|
|
2140
|
+
if (_state.mount && !_state.action) {
|
|
2141
|
+
_setValid();
|
|
2142
|
+
if (wasUnsetInFormValues &&
|
|
2143
|
+
_formState.isDirty &&
|
|
2144
|
+
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
|
|
2145
|
+
const isDirty = _getDirty();
|
|
2146
|
+
if (!isDirty) {
|
|
2147
|
+
_formState.isDirty = false;
|
|
2148
|
+
_subjects.state.next({ ..._formState });
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
if (props.shouldUnregister &&
|
|
2152
|
+
wasUnsetInFormValues &&
|
|
2153
|
+
!isUndefined(get(_formValues, name)) &&
|
|
2154
|
+
isWatched(name, _names)) {
|
|
2155
|
+
_state.watch = true;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
};
|
|
2160
|
+
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
|
2161
|
+
let shouldUpdateField = false;
|
|
2162
|
+
let isPreviousDirty = false;
|
|
2163
|
+
const output = {
|
|
2164
|
+
name,
|
|
2165
|
+
};
|
|
2166
|
+
// an explicit programmatic update (e.g. setValue with shouldDirty: true)
|
|
2167
|
+
// opts into dirty tracking even when the form is disabled
|
|
2168
|
+
if (!_options.disabled || shouldDirty === true) {
|
|
2169
|
+
if (!isBlurEvent || shouldDirty) {
|
|
2170
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
2171
|
+
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
2172
|
+
isPreviousDirty = _formState.isDirty;
|
|
2173
|
+
_formState.isDirty = output.isDirty =
|
|
2174
|
+
!isCurrentFieldPristine || _getDirty();
|
|
2175
|
+
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
2176
|
+
}
|
|
2177
|
+
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
2178
|
+
if (isCurrentFieldPristine !== _formState.isDirty) {
|
|
2179
|
+
updateDirtyFields(_formState.dirtyFields, getDirtyFields(_defaultValues, _formValues, undefined, _fields));
|
|
2180
|
+
}
|
|
2181
|
+
else {
|
|
2182
|
+
isCurrentFieldPristine
|
|
2183
|
+
? unset(_formState.dirtyFields, name)
|
|
2184
|
+
: set(_formState.dirtyFields, name, true);
|
|
2185
|
+
}
|
|
2186
|
+
output.dirtyFields = _formState.dirtyFields;
|
|
2187
|
+
shouldUpdateField =
|
|
2188
|
+
shouldUpdateField ||
|
|
2189
|
+
((_proxyFormState.dirtyFields ||
|
|
2190
|
+
_proxySubscribeFormState.dirtyFields) &&
|
|
2191
|
+
isPreviousDirty !== !isCurrentFieldPristine);
|
|
2192
|
+
}
|
|
2193
|
+
if (isBlurEvent) {
|
|
2194
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
|
2195
|
+
if (!isPreviousFieldTouched) {
|
|
2196
|
+
set(_formState.touchedFields, name, isBlurEvent);
|
|
2197
|
+
output.touchedFields = _formState.touchedFields;
|
|
2198
|
+
shouldUpdateField =
|
|
2199
|
+
shouldUpdateField ||
|
|
2200
|
+
((_proxyFormState.touchedFields ||
|
|
2201
|
+
_proxySubscribeFormState.touchedFields) &&
|
|
2202
|
+
isPreviousFieldTouched !== isBlurEvent);
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
|
2206
|
+
}
|
|
2207
|
+
return shouldUpdateField ? output : {};
|
|
2208
|
+
};
|
|
2209
|
+
const shouldRenderByError = (name, isValid, error, fieldState) => {
|
|
2210
|
+
const previousFieldError = get(_formState.errors, name);
|
|
2211
|
+
const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
2212
|
+
isBoolean(isValid) &&
|
|
2213
|
+
_formState.isValid !== isValid;
|
|
2214
|
+
if (_options.delayError && error) {
|
|
2215
|
+
delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
|
|
2216
|
+
delayErrorCallbacks[name](_options.delayError);
|
|
2217
|
+
}
|
|
2218
|
+
else {
|
|
2219
|
+
clearTimeout(timers[name]);
|
|
2220
|
+
delete delayErrorCallbacks[name];
|
|
2221
|
+
error
|
|
2222
|
+
? set(_formState.errors, name, error)
|
|
2223
|
+
: unset(_formState.errors, name);
|
|
2224
|
+
_formState.errors = { ..._formState.errors };
|
|
2225
|
+
}
|
|
2226
|
+
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
|
2227
|
+
!isEmptyObject(fieldState) ||
|
|
2228
|
+
shouldUpdateValid) {
|
|
2229
|
+
const updatedFormState = {
|
|
2230
|
+
...fieldState,
|
|
2231
|
+
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
|
2232
|
+
errors: _formState.errors,
|
|
2233
|
+
name,
|
|
2234
|
+
};
|
|
2235
|
+
_formState = {
|
|
2236
|
+
..._formState,
|
|
2237
|
+
...updatedFormState,
|
|
2238
|
+
};
|
|
2239
|
+
_subjects.state.next(updatedFormState);
|
|
2240
|
+
}
|
|
2241
|
+
};
|
|
2242
|
+
const _runSchema = async (name) => {
|
|
2243
|
+
_updateIsValidating(name, true);
|
|
2244
|
+
return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
|
|
2245
|
+
};
|
|
2246
|
+
const executeSchemaAndUpdateState = async (names) => {
|
|
2247
|
+
const { errors } = await _runSchema(names);
|
|
2248
|
+
_updateIsValidating(names);
|
|
2249
|
+
if (names) {
|
|
2250
|
+
for (const name of names) {
|
|
2251
|
+
const error = get(errors, name);
|
|
2252
|
+
error
|
|
2253
|
+
? _names.array.has(name) &&
|
|
2254
|
+
isObject(error) &&
|
|
2255
|
+
!Object.keys(error).some((key) => !Number.isNaN(Number(key)))
|
|
2256
|
+
? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
|
|
2257
|
+
: set(_formState.errors, name, error)
|
|
2258
|
+
: unset(_formState.errors, name);
|
|
2259
|
+
}
|
|
2260
|
+
_formState.errors = { ..._formState.errors };
|
|
2261
|
+
}
|
|
2262
|
+
else {
|
|
2263
|
+
_formState.errors = errors;
|
|
2264
|
+
}
|
|
2265
|
+
return errors;
|
|
2266
|
+
};
|
|
2267
|
+
const validateForm = async ({ name, eventType, }) => {
|
|
2268
|
+
if (props.validate) {
|
|
2269
|
+
const result = await props.validate({
|
|
2270
|
+
formValues: _formValues,
|
|
2271
|
+
formState: _formState,
|
|
2272
|
+
name,
|
|
2273
|
+
eventType,
|
|
2274
|
+
});
|
|
2275
|
+
if (isObject(result)) {
|
|
2276
|
+
for (const key in result) {
|
|
2277
|
+
const error = result[key];
|
|
2278
|
+
if (error) {
|
|
2279
|
+
setError(`${FORM_ERROR_TYPE}.${key}`, {
|
|
2280
|
+
message: isString(error.message) ? error.message : '',
|
|
2281
|
+
type: error.type || INPUT_VALIDATION_RULES.validate,
|
|
2282
|
+
});
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
else if (isString(result) || !result) {
|
|
2287
|
+
setError(FORM_ERROR_TYPE, {
|
|
2288
|
+
message: result || '',
|
|
2289
|
+
type: INPUT_VALIDATION_RULES.validate,
|
|
2290
|
+
});
|
|
2291
|
+
}
|
|
2292
|
+
else {
|
|
2293
|
+
clearErrors(FORM_ERROR_TYPE);
|
|
2294
|
+
}
|
|
2295
|
+
return result;
|
|
2296
|
+
}
|
|
2297
|
+
return true;
|
|
2298
|
+
};
|
|
2299
|
+
const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
|
|
2300
|
+
valid: true,
|
|
2301
|
+
runRootValidation: false,
|
|
2302
|
+
}, }) => {
|
|
2303
|
+
if (props.validate) {
|
|
2304
|
+
context.runRootValidation = true;
|
|
2305
|
+
const result = await validateForm({
|
|
2306
|
+
name,
|
|
2307
|
+
eventType,
|
|
2308
|
+
});
|
|
2309
|
+
if (!result) {
|
|
2310
|
+
context.valid = false;
|
|
2311
|
+
if (onlyCheckValid) {
|
|
2312
|
+
return context.valid;
|
|
2313
|
+
}
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
for (const name in fields) {
|
|
2317
|
+
const field = fields[name];
|
|
2318
|
+
if (field) {
|
|
2319
|
+
const { _f, ...fieldValue } = field;
|
|
2320
|
+
if (_f) {
|
|
2321
|
+
const isFieldArrayRoot = _names.array.has(_f.name);
|
|
2322
|
+
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
|
|
2323
|
+
const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
|
|
2324
|
+
_proxyFormState.isValidating ||
|
|
2325
|
+
_proxySubscribeFormState.validatingFields ||
|
|
2326
|
+
_proxySubscribeFormState.isValidating;
|
|
2327
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
2328
|
+
_updateIsValidating([_f.name], true);
|
|
2329
|
+
}
|
|
2330
|
+
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
|
|
2331
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
2332
|
+
_updateIsValidating([_f.name]);
|
|
2333
|
+
}
|
|
2334
|
+
if (fieldError[_f.name]) {
|
|
2335
|
+
context.valid = false;
|
|
2336
|
+
if (onlyCheckValid) {
|
|
2337
|
+
break;
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2340
|
+
!onlyCheckValid &&
|
|
2341
|
+
(get(fieldError, _f.name)
|
|
2342
|
+
? isFieldArrayRoot
|
|
2343
|
+
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
|
2344
|
+
: set(_formState.errors, _f.name, fieldError[_f.name])
|
|
2345
|
+
: unset(_formState.errors, _f.name));
|
|
2346
|
+
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
|
|
2347
|
+
break;
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
!isEmptyObject(fieldValue) &&
|
|
2351
|
+
(await executeBuiltInValidation({
|
|
2352
|
+
context,
|
|
2353
|
+
onlyCheckValid,
|
|
2354
|
+
fields: fieldValue,
|
|
2355
|
+
name: name,
|
|
2356
|
+
eventType,
|
|
2357
|
+
}));
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
return context.valid;
|
|
2361
|
+
};
|
|
1749
2362
|
const _removeUnmounted = () => {
|
|
1750
2363
|
for (const name of _names.unMount) {
|
|
1751
2364
|
const field = get(_fields, name);
|
|
@@ -1757,9 +2370,8 @@ function createFormControl(props = {}) {
|
|
|
1757
2370
|
}
|
|
1758
2371
|
_names.unMount = new Set();
|
|
1759
2372
|
};
|
|
1760
|
-
const _getDirty = (name, data) =>
|
|
1761
|
-
(
|
|
1762
|
-
!deepEqual(getValues(), _defaultValues));
|
|
2373
|
+
const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
|
|
2374
|
+
!deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
|
|
1763
2375
|
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
|
1764
2376
|
...(_state.mount
|
|
1765
2377
|
? _formValues
|
|
@@ -1770,7 +2382,7 @@ function createFormControl(props = {}) {
|
|
|
1770
2382
|
: defaultValue),
|
|
1771
2383
|
}, isGlobal, defaultValue);
|
|
1772
2384
|
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
|
1773
|
-
const setFieldValue = (name, value, options = {}) => {
|
|
2385
|
+
const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
|
|
1774
2386
|
const field = get(_fields, name);
|
|
1775
2387
|
let fieldValue = value;
|
|
1776
2388
|
if (field) {
|
|
@@ -1808,20 +2420,23 @@ function createFormControl(props = {}) {
|
|
|
1808
2420
|
}
|
|
1809
2421
|
else {
|
|
1810
2422
|
fieldReference.ref.value = fieldValue;
|
|
1811
|
-
if (!fieldReference.ref.type) {
|
|
2423
|
+
if (!fieldReference.ref.type && !skipRender) {
|
|
1812
2424
|
_subjects.state.next({
|
|
1813
2425
|
name,
|
|
1814
|
-
values: cloneObject(_formValues),
|
|
2426
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
1815
2427
|
});
|
|
1816
2428
|
}
|
|
1817
2429
|
}
|
|
1818
2430
|
}
|
|
1819
2431
|
}
|
|
1820
2432
|
(options.shouldDirty || options.shouldTouch) &&
|
|
1821
|
-
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty,
|
|
1822
|
-
options.shouldValidate &&
|
|
2433
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
|
|
2434
|
+
options.shouldValidate &&
|
|
2435
|
+
trigger(name, {
|
|
2436
|
+
delayError: options.delayError,
|
|
2437
|
+
});
|
|
1823
2438
|
};
|
|
1824
|
-
const
|
|
2439
|
+
const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
|
|
1825
2440
|
for (const fieldKey in value) {
|
|
1826
2441
|
if (!value.hasOwnProperty(fieldKey)) {
|
|
1827
2442
|
return;
|
|
@@ -1833,50 +2448,84 @@ function createFormControl(props = {}) {
|
|
|
1833
2448
|
isObject(fieldValue) ||
|
|
1834
2449
|
(field && !field._f)) &&
|
|
1835
2450
|
!isDateObject(fieldValue)
|
|
1836
|
-
?
|
|
1837
|
-
: setFieldValue(fieldName, fieldValue, options);
|
|
2451
|
+
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
2452
|
+
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
1838
2453
|
}
|
|
1839
2454
|
};
|
|
1840
|
-
const
|
|
2455
|
+
const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
|
|
1841
2456
|
const field = get(_fields, name);
|
|
1842
2457
|
const isFieldArray = _names.array.has(name);
|
|
1843
|
-
const cloneValue = cloneObject(value);
|
|
1844
|
-
|
|
2458
|
+
const cloneValue = skipClone ? value : cloneObject(value);
|
|
2459
|
+
const previousValue = get(_formValues, name);
|
|
2460
|
+
const isValueUnchanged = deepEqual(previousValue, cloneValue);
|
|
2461
|
+
if (!isValueUnchanged) {
|
|
2462
|
+
set(_formValues, name, cloneValue);
|
|
2463
|
+
}
|
|
1845
2464
|
if (isFieldArray) {
|
|
1846
2465
|
_subjects.array.next({
|
|
1847
2466
|
name,
|
|
1848
|
-
values: cloneObject(_formValues),
|
|
2467
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
1849
2468
|
});
|
|
1850
2469
|
if ((_proxyFormState.isDirty ||
|
|
1851
2470
|
_proxyFormState.dirtyFields ||
|
|
1852
2471
|
_proxySubscribeFormState.isDirty ||
|
|
1853
2472
|
_proxySubscribeFormState.dirtyFields) &&
|
|
1854
2473
|
options.shouldDirty) {
|
|
1855
|
-
_updateDirtyFields(
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
2474
|
+
_updateDirtyFields();
|
|
2475
|
+
if (!skipStateEmit) {
|
|
2476
|
+
_subjects.state.next({
|
|
2477
|
+
name,
|
|
2478
|
+
dirtyFields: _formState.dirtyFields,
|
|
2479
|
+
isDirty: _getDirty(name, cloneValue),
|
|
2480
|
+
});
|
|
2481
|
+
}
|
|
1861
2482
|
}
|
|
1862
2483
|
}
|
|
1863
2484
|
else {
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
2485
|
+
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
2486
|
+
isEmptyObject(cloneValue);
|
|
2487
|
+
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
2488
|
+
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2489
|
+
}
|
|
2490
|
+
else {
|
|
2491
|
+
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2492
|
+
}
|
|
1867
2493
|
}
|
|
1868
|
-
if (
|
|
2494
|
+
if (!isValueUnchanged && !skipStateEmit) {
|
|
2495
|
+
const watched = isWatched(name, _names);
|
|
2496
|
+
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
1869
2497
|
_subjects.state.next({
|
|
1870
|
-
..._formState,
|
|
1871
|
-
name,
|
|
1872
|
-
values
|
|
2498
|
+
...(watched && _formState),
|
|
2499
|
+
name: _state.mount || watched ? name : undefined,
|
|
2500
|
+
values,
|
|
1873
2501
|
});
|
|
1874
2502
|
}
|
|
1875
|
-
|
|
2503
|
+
};
|
|
2504
|
+
const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
|
|
2505
|
+
const setValues = (formValues, options = {}) => {
|
|
2506
|
+
const updatedFormValues = isFunction(formValues)
|
|
2507
|
+
? formValues(_formValues)
|
|
2508
|
+
: formValues;
|
|
2509
|
+
if (!deepEqual(_formValues, updatedFormValues)) {
|
|
2510
|
+
_formValues = {
|
|
2511
|
+
..._formValues,
|
|
2512
|
+
...updatedFormValues,
|
|
2513
|
+
};
|
|
2514
|
+
const flattenedUpdates = flatten(updatedFormValues);
|
|
2515
|
+
for (const fieldName of _names.mount) {
|
|
2516
|
+
if (fieldName in flattenedUpdates) {
|
|
2517
|
+
_setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
|
|
2518
|
+
}
|
|
2519
|
+
}
|
|
1876
2520
|
_subjects.state.next({
|
|
1877
|
-
|
|
1878
|
-
|
|
2521
|
+
..._formState,
|
|
2522
|
+
name: undefined,
|
|
2523
|
+
type: undefined,
|
|
2524
|
+
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
1879
2525
|
});
|
|
2526
|
+
if (options.shouldValidate) {
|
|
2527
|
+
_setValid();
|
|
2528
|
+
}
|
|
1880
2529
|
}
|
|
1881
2530
|
};
|
|
1882
2531
|
const onChange = async (event) => {
|
|
@@ -1891,8 +2540,6 @@ function createFormControl(props = {}) {
|
|
|
1891
2540
|
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
1892
2541
|
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
1893
2542
|
};
|
|
1894
|
-
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
1895
|
-
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1896
2543
|
if (field) {
|
|
1897
2544
|
let error;
|
|
1898
2545
|
let isValid;
|
|
@@ -1900,18 +2547,20 @@ function createFormControl(props = {}) {
|
|
|
1900
2547
|
? getFieldValue(field._f)
|
|
1901
2548
|
: getEventValue(event);
|
|
1902
2549
|
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
1903
|
-
const
|
|
2550
|
+
const hasNoValidationEffect = !hasValidation(field._f) &&
|
|
1904
2551
|
!props.validate &&
|
|
1905
2552
|
!_options.resolver &&
|
|
1906
2553
|
!get(_formState.errors, name) &&
|
|
1907
|
-
!field._f.deps
|
|
1908
|
-
|
|
2554
|
+
!field._f.deps;
|
|
2555
|
+
const shouldSkipValidation = hasNoValidationEffect ||
|
|
2556
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
|
|
1909
2557
|
const watched = isWatched(name, _names, isBlurEvent);
|
|
1910
2558
|
set(_formValues, name, fieldValue);
|
|
1911
2559
|
if (isBlurEvent) {
|
|
1912
2560
|
if (!target || !target.readOnly) {
|
|
1913
2561
|
field._f.onBlur && field._f.onBlur(event);
|
|
1914
|
-
|
|
2562
|
+
const pendingDelayError = delayErrorCallbacks[name];
|
|
2563
|
+
pendingDelayError && pendingDelayError(0);
|
|
1915
2564
|
}
|
|
1916
2565
|
}
|
|
1917
2566
|
else if (field._f.onChange) {
|
|
@@ -1923,10 +2572,13 @@ function createFormControl(props = {}) {
|
|
|
1923
2572
|
_subjects.state.next({
|
|
1924
2573
|
name,
|
|
1925
2574
|
type: event.type,
|
|
1926
|
-
|
|
2575
|
+
...(_valuesSubscriberCount
|
|
2576
|
+
? { values: cloneObject(_formValues) }
|
|
2577
|
+
: {}),
|
|
1927
2578
|
});
|
|
1928
2579
|
if (shouldSkipValidation) {
|
|
1929
|
-
if (
|
|
2580
|
+
if ((!hasNoValidationEffect || !_formState.isValid) &&
|
|
2581
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
|
|
1930
2582
|
if (_options.mode === 'onBlur') {
|
|
1931
2583
|
if (isBlurEvent) {
|
|
1932
2584
|
_setValid();
|
|
@@ -1950,13 +2602,15 @@ function createFormControl(props = {}) {
|
|
|
1950
2602
|
const { errors } = await _runSchema([name]);
|
|
1951
2603
|
_updateIsValidating([name]);
|
|
1952
2604
|
_updateIsFieldValueUpdated(fieldValue);
|
|
1953
|
-
if (isFieldValueUpdated) {
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
error = errorLookupResult.error;
|
|
1957
|
-
name = errorLookupResult.name;
|
|
1958
|
-
isValid = isEmptyObject(errors);
|
|
2605
|
+
if (!isFieldValueUpdated) {
|
|
2606
|
+
!isEmptyObject(fieldState) && _subjects.state.next(fieldState);
|
|
2607
|
+
return;
|
|
1959
2608
|
}
|
|
2609
|
+
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
|
2610
|
+
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
|
2611
|
+
error = errorLookupResult.error;
|
|
2612
|
+
name = errorLookupResult.name;
|
|
2613
|
+
isValid = isEmptyObject(errors);
|
|
1960
2614
|
}
|
|
1961
2615
|
else {
|
|
1962
2616
|
_updateIsValidating([name], true);
|
|
@@ -2021,6 +2675,18 @@ function createFormControl(props = {}) {
|
|
|
2021
2675
|
eventType: EVENTS.TRIGGER,
|
|
2022
2676
|
});
|
|
2023
2677
|
}
|
|
2678
|
+
if (options.delayError && _options.delayError && isString(name)) {
|
|
2679
|
+
const error = get(_formState.errors, name);
|
|
2680
|
+
if (error) {
|
|
2681
|
+
unset(_formState.errors, name);
|
|
2682
|
+
delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
|
|
2683
|
+
delayErrorCallbacks[name](_options.delayError);
|
|
2684
|
+
}
|
|
2685
|
+
else {
|
|
2686
|
+
clearTimeout(timers[name]);
|
|
2687
|
+
delete delayErrorCallbacks[name];
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2024
2690
|
_subjects.state.next({
|
|
2025
2691
|
...(!isString(name) ||
|
|
2026
2692
|
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
@@ -2032,868 +2698,630 @@ function createFormControl(props = {}) {
|
|
|
2032
2698
|
});
|
|
2033
2699
|
options.shouldFocus &&
|
|
2034
2700
|
!validationResult &&
|
|
2035
|
-
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
|
2036
|
-
return validationResult;
|
|
2037
|
-
};
|
|
2038
|
-
const getValues = (fieldNames, config) => {
|
|
2039
|
-
let values = {
|
|
2040
|
-
...(_state.mount ? _formValues : _defaultValues),
|
|
2041
|
-
};
|
|
2042
|
-
if (config) {
|
|
2043
|
-
values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
|
|
2044
|
-
}
|
|
2045
|
-
return isUndefined(fieldNames)
|
|
2046
|
-
? values
|
|
2047
|
-
: isString(fieldNames)
|
|
2048
|
-
? get(values, fieldNames)
|
|
2049
|
-
: fieldNames.map((name) => get(values, name));
|
|
2050
|
-
};
|
|
2051
|
-
const getFieldState = (name, formState) => ({
|
|
2052
|
-
invalid: !!get((formState || _formState).errors, name),
|
|
2053
|
-
isDirty: !!get((formState || _formState).dirtyFields, name),
|
|
2054
|
-
error: get((formState || _formState).errors, name),
|
|
2055
|
-
isValidating: !!get(_formState.validatingFields, name),
|
|
2056
|
-
isTouched: !!get((formState || _formState).touchedFields, name),
|
|
2057
|
-
});
|
|
2058
|
-
const clearErrors = (name) => {
|
|
2059
|
-
const names = name ? convertToArrayPayload(name) : undefined;
|
|
2060
|
-
names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
|
|
2061
|
-
if (names) {
|
|
2062
|
-
// Emit for each cleared field with the field name so that
|
|
2063
|
-
// shouldSubscribeByName can filter and avoid broad re-renders
|
|
2064
|
-
names.forEach((inputName) => {
|
|
2065
|
-
_subjects.state.next({
|
|
2066
|
-
name: inputName,
|
|
2067
|
-
errors: _formState.errors,
|
|
2068
|
-
});
|
|
2069
|
-
});
|
|
2070
|
-
}
|
|
2071
|
-
else {
|
|
2072
|
-
// Clear all errors - emit without name to notify all subscribers
|
|
2073
|
-
_subjects.state.next({
|
|
2074
|
-
errors: {},
|
|
2075
|
-
});
|
|
2076
|
-
}
|
|
2077
|
-
};
|
|
2078
|
-
const setError = (name, error, options) => {
|
|
2079
|
-
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
2080
|
-
const currentError = get(_formState.errors, name) || {};
|
|
2081
|
-
// Don't override existing error messages elsewhere in the object tree.
|
|
2082
|
-
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
2083
|
-
set(_formState.errors, name, {
|
|
2084
|
-
...restOfErrorTree,
|
|
2085
|
-
...error,
|
|
2086
|
-
ref,
|
|
2087
|
-
});
|
|
2088
|
-
_subjects.state.next({
|
|
2089
|
-
name,
|
|
2090
|
-
errors: _formState.errors,
|
|
2091
|
-
isValid: false,
|
|
2092
|
-
});
|
|
2093
|
-
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
2094
|
-
};
|
|
2095
|
-
const watch = (name, defaultValue) => isFunction(name)
|
|
2096
|
-
? _subjects.state.subscribe({
|
|
2097
|
-
next: (payload) => 'values' in payload &&
|
|
2098
|
-
name(_getWatch(undefined, defaultValue), payload),
|
|
2099
|
-
})
|
|
2100
|
-
: _getWatch(name, defaultValue, true);
|
|
2101
|
-
const _subscribe = (props) => _subjects.state.subscribe({
|
|
2102
|
-
next: (formState) => {
|
|
2103
|
-
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
2104
|
-
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
2105
|
-
props.callback({
|
|
2106
|
-
values: { ..._formValues },
|
|
2107
|
-
..._formState,
|
|
2108
|
-
...formState,
|
|
2109
|
-
defaultValues: _defaultValues,
|
|
2110
|
-
});
|
|
2111
|
-
}
|
|
2112
|
-
},
|
|
2113
|
-
}).unsubscribe;
|
|
2114
|
-
const subscribe = (props) => {
|
|
2115
|
-
_state.mount = true;
|
|
2116
|
-
_proxySubscribeFormState = {
|
|
2117
|
-
..._proxySubscribeFormState,
|
|
2118
|
-
...props.formState,
|
|
2119
|
-
};
|
|
2120
|
-
return _subscribe({
|
|
2121
|
-
...props,
|
|
2122
|
-
formState: {
|
|
2123
|
-
...defaultProxyFormState,
|
|
2124
|
-
...props.formState,
|
|
2125
|
-
},
|
|
2126
|
-
});
|
|
2127
|
-
};
|
|
2128
|
-
const unregister = (name, options = {}) => {
|
|
2129
|
-
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
|
2130
|
-
_names.mount.delete(fieldName);
|
|
2131
|
-
_names.array.delete(fieldName);
|
|
2132
|
-
if (!options.keepValue) {
|
|
2133
|
-
unset(_fields, fieldName);
|
|
2134
|
-
unset(_formValues, fieldName);
|
|
2135
|
-
}
|
|
2136
|
-
!options.keepError && unset(_formState.errors, fieldName);
|
|
2137
|
-
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
|
2138
|
-
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
|
2139
|
-
!options.keepIsValidating &&
|
|
2140
|
-
unset(_formState.validatingFields, fieldName);
|
|
2141
|
-
!_options.shouldUnregister &&
|
|
2142
|
-
!options.keepDefaultValue &&
|
|
2143
|
-
unset(_defaultValues, fieldName);
|
|
2144
|
-
}
|
|
2145
|
-
_subjects.state.next({
|
|
2146
|
-
values: cloneObject(_formValues),
|
|
2147
|
-
});
|
|
2148
|
-
_subjects.state.next({
|
|
2149
|
-
..._formState,
|
|
2150
|
-
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
|
2151
|
-
});
|
|
2152
|
-
!options.keepIsValid && _setValid();
|
|
2153
|
-
};
|
|
2154
|
-
const _setDisabledField = ({ disabled, name, }) => {
|
|
2155
|
-
if ((isBoolean(disabled) && _state.mount) ||
|
|
2156
|
-
!!disabled ||
|
|
2157
|
-
_names.disabled.has(name)) {
|
|
2158
|
-
const wasDisabled = _names.disabled.has(name);
|
|
2159
|
-
const isDisabled = !!disabled;
|
|
2160
|
-
const disabledStateChanged = wasDisabled !== isDisabled;
|
|
2161
|
-
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
|
2162
|
-
disabledStateChanged && _state.mount && !_state.action && _setValid();
|
|
2163
|
-
}
|
|
2164
|
-
};
|
|
2165
|
-
const register = (name, options = {}) => {
|
|
2166
|
-
let field = get(_fields, name);
|
|
2167
|
-
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
|
2168
|
-
const shouldRevalidateRemount = !_names.registerName.has(name) && field && !field._f.mount;
|
|
2169
|
-
set(_fields, name, {
|
|
2170
|
-
...(field || {}),
|
|
2171
|
-
_f: {
|
|
2172
|
-
...(field && field._f ? field._f : { ref: { name } }),
|
|
2173
|
-
name,
|
|
2174
|
-
mount: true,
|
|
2175
|
-
...options,
|
|
2176
|
-
},
|
|
2177
|
-
});
|
|
2178
|
-
_names.mount.add(name);
|
|
2179
|
-
if (field && !shouldRevalidateRemount) {
|
|
2180
|
-
_setDisabledField({
|
|
2181
|
-
disabled: isBoolean(options.disabled)
|
|
2182
|
-
? options.disabled
|
|
2183
|
-
: _options.disabled,
|
|
2184
|
-
name,
|
|
2185
|
-
});
|
|
2186
|
-
}
|
|
2187
|
-
else {
|
|
2188
|
-
updateValidAndValue(name, true, options.value);
|
|
2189
|
-
}
|
|
2190
|
-
return {
|
|
2191
|
-
...(disabledIsDefined
|
|
2192
|
-
? { disabled: options.disabled || _options.disabled }
|
|
2193
|
-
: {}),
|
|
2194
|
-
...(_options.progressive
|
|
2195
|
-
? {
|
|
2196
|
-
required: !!options.required,
|
|
2197
|
-
min: getRuleValue(options.min),
|
|
2198
|
-
max: getRuleValue(options.max),
|
|
2199
|
-
minLength: getRuleValue(options.minLength),
|
|
2200
|
-
maxLength: getRuleValue(options.maxLength),
|
|
2201
|
-
pattern: getRuleValue(options.pattern),
|
|
2202
|
-
}
|
|
2203
|
-
: {}),
|
|
2204
|
-
name,
|
|
2205
|
-
onChange,
|
|
2206
|
-
onBlur: onChange,
|
|
2207
|
-
ref: (ref) => {
|
|
2208
|
-
if (ref) {
|
|
2209
|
-
_names.registerName.add(name);
|
|
2210
|
-
register(name, options);
|
|
2211
|
-
_names.registerName.delete(name);
|
|
2212
|
-
field = get(_fields, name);
|
|
2213
|
-
const fieldRef = isUndefined(ref.value)
|
|
2214
|
-
? ref.querySelectorAll
|
|
2215
|
-
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
|
2216
|
-
: ref
|
|
2217
|
-
: ref;
|
|
2218
|
-
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
|
2219
|
-
const refs = field._f.refs || [];
|
|
2220
|
-
if (radioOrCheckbox
|
|
2221
|
-
? refs.find((option) => option === fieldRef)
|
|
2222
|
-
: fieldRef === field._f.ref) {
|
|
2223
|
-
return;
|
|
2224
|
-
}
|
|
2225
|
-
set(_fields, name, {
|
|
2226
|
-
_f: {
|
|
2227
|
-
...field._f,
|
|
2228
|
-
...(radioOrCheckbox
|
|
2229
|
-
? {
|
|
2230
|
-
refs: [
|
|
2231
|
-
...refs.filter(live),
|
|
2232
|
-
fieldRef,
|
|
2233
|
-
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
|
2234
|
-
],
|
|
2235
|
-
ref: { type: fieldRef.type, name },
|
|
2236
|
-
}
|
|
2237
|
-
: { ref: fieldRef }),
|
|
2238
|
-
},
|
|
2239
|
-
});
|
|
2240
|
-
updateValidAndValue(name, false, undefined, fieldRef);
|
|
2241
|
-
}
|
|
2242
|
-
else {
|
|
2243
|
-
field = get(_fields, name, {});
|
|
2244
|
-
if (field._f) {
|
|
2245
|
-
field._f.mount = false;
|
|
2246
|
-
}
|
|
2247
|
-
(_options.shouldUnregister || options.shouldUnregister) &&
|
|
2248
|
-
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
|
2249
|
-
_names.unMount.add(name);
|
|
2250
|
-
}
|
|
2251
|
-
},
|
|
2252
|
-
};
|
|
2253
|
-
};
|
|
2254
|
-
const _focusError = () => _options.shouldFocusError &&
|
|
2255
|
-
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
|
2256
|
-
const _disableForm = (disabled) => {
|
|
2257
|
-
if (isBoolean(disabled)) {
|
|
2258
|
-
_subjects.state.next({ disabled });
|
|
2259
|
-
iterateFieldsByAction(_fields, (ref, name) => {
|
|
2260
|
-
const currentField = get(_fields, name);
|
|
2261
|
-
if (currentField) {
|
|
2262
|
-
ref.disabled = currentField._f.disabled || disabled;
|
|
2263
|
-
if (Array.isArray(currentField._f.refs)) {
|
|
2264
|
-
currentField._f.refs.forEach((inputRef) => {
|
|
2265
|
-
inputRef.disabled = currentField._f.disabled || disabled;
|
|
2266
|
-
});
|
|
2267
|
-
}
|
|
2268
|
-
}
|
|
2269
|
-
}, 0, false);
|
|
2270
|
-
}
|
|
2271
|
-
};
|
|
2272
|
-
const handleSubmit = (onValid, onInvalid) => async (e) => {
|
|
2273
|
-
let onValidError = undefined;
|
|
2274
|
-
if (e) {
|
|
2275
|
-
e.preventDefault && e.preventDefault();
|
|
2276
|
-
e.persist &&
|
|
2277
|
-
e.persist();
|
|
2278
|
-
}
|
|
2279
|
-
let fieldValues = cloneObject(_formValues);
|
|
2280
|
-
_subjects.state.next({
|
|
2281
|
-
isSubmitting: true,
|
|
2282
|
-
});
|
|
2283
|
-
if (_options.resolver) {
|
|
2284
|
-
const { errors, values } = await _runSchema();
|
|
2285
|
-
_updateIsValidating();
|
|
2286
|
-
_formState.errors = errors;
|
|
2287
|
-
fieldValues = cloneObject(values);
|
|
2701
|
+
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
|
2702
|
+
return validationResult;
|
|
2703
|
+
};
|
|
2704
|
+
const getValues = (fieldNames, config) => {
|
|
2705
|
+
let values = {
|
|
2706
|
+
...(_state.mount ? _formValues : _defaultValues),
|
|
2707
|
+
};
|
|
2708
|
+
if (config) {
|
|
2709
|
+
values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
|
|
2288
2710
|
}
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2711
|
+
return isUndefined(fieldNames)
|
|
2712
|
+
? values
|
|
2713
|
+
: isString(fieldNames)
|
|
2714
|
+
? get(values, fieldNames)
|
|
2715
|
+
: fieldNames.map((name) => get(values, name));
|
|
2716
|
+
};
|
|
2717
|
+
const getFieldState = (name, formState) => ({
|
|
2718
|
+
invalid: !!get((formState || _formState).errors, name),
|
|
2719
|
+
isDirty: !!get((formState || _formState).dirtyFields, name),
|
|
2720
|
+
error: get((formState || _formState).errors, name),
|
|
2721
|
+
isValidating: !!get(_formState.validatingFields, name),
|
|
2722
|
+
isTouched: !!get((formState || _formState).touchedFields, name),
|
|
2723
|
+
});
|
|
2724
|
+
const clearErrors = (name) => {
|
|
2725
|
+
const names = name ? convertToArrayPayload(name) : undefined;
|
|
2726
|
+
names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
|
|
2727
|
+
if (names) {
|
|
2728
|
+
names.forEach((inputName) => {
|
|
2729
|
+
_subjects.state.next({
|
|
2730
|
+
name: inputName,
|
|
2731
|
+
errors: _formState.errors,
|
|
2732
|
+
});
|
|
2293
2733
|
});
|
|
2294
2734
|
}
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
unset(fieldValues, name);
|
|
2298
|
-
}
|
|
2299
|
-
}
|
|
2300
|
-
unset(_formState.errors, ROOT_ERROR_TYPE);
|
|
2301
|
-
if (isEmptyObject(_formState.errors)) {
|
|
2735
|
+
else {
|
|
2736
|
+
_formState.errors = {};
|
|
2302
2737
|
_subjects.state.next({
|
|
2303
|
-
errors:
|
|
2738
|
+
errors: _formState.errors,
|
|
2304
2739
|
});
|
|
2305
|
-
try {
|
|
2306
|
-
await onValid(fieldValues, e);
|
|
2307
|
-
}
|
|
2308
|
-
catch (error) {
|
|
2309
|
-
onValidError = error;
|
|
2310
|
-
}
|
|
2311
|
-
}
|
|
2312
|
-
else {
|
|
2313
|
-
if (onInvalid) {
|
|
2314
|
-
await onInvalid({ ..._formState.errors }, e);
|
|
2315
|
-
}
|
|
2316
|
-
_focusError();
|
|
2317
|
-
setTimeout(_focusError);
|
|
2318
2740
|
}
|
|
2741
|
+
};
|
|
2742
|
+
const setError = (name, error, options) => {
|
|
2743
|
+
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
2744
|
+
const currentError = get(_formState.errors, name) || {};
|
|
2745
|
+
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
2746
|
+
set(_formState.errors, name, {
|
|
2747
|
+
...restOfErrorTree,
|
|
2748
|
+
...error,
|
|
2749
|
+
ref,
|
|
2750
|
+
});
|
|
2319
2751
|
_subjects.state.next({
|
|
2320
|
-
|
|
2321
|
-
isSubmitting: false,
|
|
2322
|
-
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
|
2323
|
-
submitCount: _formState.submitCount + 1,
|
|
2752
|
+
name,
|
|
2324
2753
|
errors: _formState.errors,
|
|
2754
|
+
isValid: false,
|
|
2325
2755
|
});
|
|
2326
|
-
|
|
2327
|
-
throw onValidError;
|
|
2328
|
-
}
|
|
2756
|
+
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
2329
2757
|
};
|
|
2330
|
-
const
|
|
2331
|
-
if (
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
}
|
|
2348
|
-
if (!options.keepError) {
|
|
2349
|
-
unset(_formState.errors, name);
|
|
2350
|
-
_proxyFormState.isValid && _setValid();
|
|
2351
|
-
}
|
|
2352
|
-
_subjects.state.next({ ..._formState });
|
|
2758
|
+
const watch = (name, defaultValue) => {
|
|
2759
|
+
if (isFunction(name)) {
|
|
2760
|
+
_valuesSubscriberCount++;
|
|
2761
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2762
|
+
next: (payload) => 'values' in payload &&
|
|
2763
|
+
name(payload.values || _getWatch(undefined, defaultValue), payload),
|
|
2764
|
+
});
|
|
2765
|
+
let called = false;
|
|
2766
|
+
return {
|
|
2767
|
+
unsubscribe: () => {
|
|
2768
|
+
if (called) {
|
|
2769
|
+
return;
|
|
2770
|
+
}
|
|
2771
|
+
called = true;
|
|
2772
|
+
_valuesSubscriberCount--;
|
|
2773
|
+
unsubscribe();
|
|
2774
|
+
},
|
|
2775
|
+
};
|
|
2353
2776
|
}
|
|
2777
|
+
return _getWatch(name, defaultValue, true);
|
|
2354
2778
|
};
|
|
2355
|
-
const
|
|
2356
|
-
|
|
2357
|
-
const
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
const newValue = get(values, fieldName);
|
|
2373
|
-
if (isDirty && !isUndefined(existingValue)) {
|
|
2374
|
-
set(values, fieldName, existingValue);
|
|
2375
|
-
}
|
|
2376
|
-
else if (!isDirty && !isUndefined(newValue)) {
|
|
2377
|
-
setValue(fieldName, newValue);
|
|
2378
|
-
}
|
|
2379
|
-
}
|
|
2380
|
-
}
|
|
2381
|
-
else {
|
|
2382
|
-
if (isWeb && isUndefined(formValues)) {
|
|
2383
|
-
for (const name of _names.mount) {
|
|
2384
|
-
const field = get(_fields, name);
|
|
2385
|
-
if (field && field._f) {
|
|
2386
|
-
const fieldReference = Array.isArray(field._f.refs)
|
|
2387
|
-
? field._f.refs[0]
|
|
2388
|
-
: field._f.ref;
|
|
2389
|
-
if (isHTMLElement(fieldReference)) {
|
|
2390
|
-
const form = fieldReference.closest('form');
|
|
2391
|
-
if (form) {
|
|
2392
|
-
form.reset();
|
|
2393
|
-
break;
|
|
2394
|
-
}
|
|
2395
|
-
}
|
|
2396
|
-
}
|
|
2397
|
-
}
|
|
2398
|
-
}
|
|
2399
|
-
if (keepStateOptions.keepFieldsRef) {
|
|
2400
|
-
for (const fieldName of _names.mount) {
|
|
2401
|
-
setValue(fieldName, get(values, fieldName));
|
|
2402
|
-
}
|
|
2403
|
-
}
|
|
2404
|
-
else {
|
|
2405
|
-
_fields = {};
|
|
2779
|
+
const _subscribe = (props) => {
|
|
2780
|
+
var _a;
|
|
2781
|
+
const needsValues = !!((_a = props.formState) === null || _a === void 0 ? void 0 : _a.values);
|
|
2782
|
+
if (needsValues) {
|
|
2783
|
+
_valuesSubscriberCount++;
|
|
2784
|
+
}
|
|
2785
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2786
|
+
next: (formState) => {
|
|
2787
|
+
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
2788
|
+
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
2789
|
+
const snapshot = { ..._formValues };
|
|
2790
|
+
props.callback({
|
|
2791
|
+
values: snapshot,
|
|
2792
|
+
..._formState,
|
|
2793
|
+
...formState,
|
|
2794
|
+
defaultValues: _defaultValues,
|
|
2795
|
+
});
|
|
2406
2796
|
}
|
|
2407
|
-
}
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
: {}
|
|
2412
|
-
: cloneObject(values);
|
|
2413
|
-
_subjects.array.next({
|
|
2414
|
-
values: { ...values },
|
|
2415
|
-
});
|
|
2416
|
-
_subjects.state.next({
|
|
2417
|
-
values: { ...values },
|
|
2418
|
-
});
|
|
2797
|
+
},
|
|
2798
|
+
});
|
|
2799
|
+
if (!needsValues) {
|
|
2800
|
+
return unsubscribe;
|
|
2419
2801
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
focus: '',
|
|
2802
|
+
let called = false;
|
|
2803
|
+
return () => {
|
|
2804
|
+
if (called) {
|
|
2805
|
+
return;
|
|
2806
|
+
}
|
|
2807
|
+
called = true;
|
|
2808
|
+
_valuesSubscriberCount--;
|
|
2809
|
+
unsubscribe();
|
|
2429
2810
|
};
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
}
|
|
2444
|
-
_subjects.state.next({
|
|
2445
|
-
submitCount: keepStateOptions.keepSubmitCount
|
|
2446
|
-
? _formState.submitCount
|
|
2447
|
-
: 0,
|
|
2448
|
-
isDirty: isEmptyResetValues
|
|
2449
|
-
? false
|
|
2450
|
-
: keepStateOptions.keepDirty
|
|
2451
|
-
? _formState.isDirty
|
|
2452
|
-
: !!(keepStateOptions.keepDefaultValues &&
|
|
2453
|
-
!deepEqual(formValues, _defaultValues)),
|
|
2454
|
-
isSubmitted: keepStateOptions.keepIsSubmitted
|
|
2455
|
-
? _formState.isSubmitted
|
|
2456
|
-
: false,
|
|
2457
|
-
dirtyFields: isEmptyResetValues
|
|
2458
|
-
? {}
|
|
2459
|
-
: keepStateOptions.keepDirtyValues
|
|
2460
|
-
? keepStateOptions.keepDefaultValues && _formValues
|
|
2461
|
-
? getDirtyFields(_defaultValues, _formValues)
|
|
2462
|
-
: _formState.dirtyFields
|
|
2463
|
-
: keepStateOptions.keepDefaultValues && formValues
|
|
2464
|
-
? getDirtyFields(_defaultValues, formValues)
|
|
2465
|
-
: keepStateOptions.keepDirty
|
|
2466
|
-
? _formState.dirtyFields
|
|
2467
|
-
: {},
|
|
2468
|
-
touchedFields: keepStateOptions.keepTouched
|
|
2469
|
-
? _formState.touchedFields
|
|
2470
|
-
: {},
|
|
2471
|
-
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
|
2472
|
-
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
|
2473
|
-
? _formState.isSubmitSuccessful
|
|
2474
|
-
: false,
|
|
2475
|
-
isSubmitting: false,
|
|
2476
|
-
defaultValues: _defaultValues,
|
|
2811
|
+
};
|
|
2812
|
+
const subscribe = (props) => {
|
|
2813
|
+
_state.mount = true;
|
|
2814
|
+
_proxySubscribeFormState = {
|
|
2815
|
+
..._proxySubscribeFormState,
|
|
2816
|
+
...props.formState,
|
|
2817
|
+
};
|
|
2818
|
+
return _subscribe({
|
|
2819
|
+
...props,
|
|
2820
|
+
formState: {
|
|
2821
|
+
...defaultProxyFormState,
|
|
2822
|
+
...props.formState,
|
|
2823
|
+
},
|
|
2477
2824
|
});
|
|
2478
2825
|
};
|
|
2479
|
-
const
|
|
2480
|
-
?
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
const fieldRef = fieldReference.refs
|
|
2487
|
-
? fieldReference.refs[0]
|
|
2488
|
-
: fieldReference.ref;
|
|
2489
|
-
if (fieldRef.focus) {
|
|
2490
|
-
// Use setTimeout to ensure focus happens after any pending state updates
|
|
2491
|
-
// This fixes the issue where setFocus doesn't work immediately after setError
|
|
2492
|
-
setTimeout(() => {
|
|
2493
|
-
fieldRef.focus();
|
|
2494
|
-
options.shouldSelect &&
|
|
2495
|
-
isFunction(fieldRef.select) &&
|
|
2496
|
-
fieldRef.select();
|
|
2497
|
-
});
|
|
2826
|
+
const unregister = (name, options = {}) => {
|
|
2827
|
+
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
|
2828
|
+
_names.mount.delete(fieldName);
|
|
2829
|
+
_names.array.delete(fieldName);
|
|
2830
|
+
if (!options.keepValue) {
|
|
2831
|
+
unset(_fields, fieldName);
|
|
2832
|
+
unset(_formValues, fieldName);
|
|
2498
2833
|
}
|
|
2834
|
+
!options.keepError && unset(_formState.errors, fieldName);
|
|
2835
|
+
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
|
2836
|
+
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
|
2837
|
+
!options.keepIsValidating &&
|
|
2838
|
+
unset(_formState.validatingFields, fieldName);
|
|
2839
|
+
!_options.shouldUnregister &&
|
|
2840
|
+
!options.keepDefaultValue &&
|
|
2841
|
+
unset(_defaultValues, fieldName);
|
|
2499
2842
|
}
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2843
|
+
_subjects.state.next({
|
|
2844
|
+
values: cloneObject(_formValues),
|
|
2845
|
+
});
|
|
2846
|
+
_subjects.state.next({
|
|
2503
2847
|
..._formState,
|
|
2504
|
-
...
|
|
2505
|
-
};
|
|
2506
|
-
};
|
|
2507
|
-
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
|
2508
|
-
_options.defaultValues().then((values) => {
|
|
2509
|
-
reset(values, _options.resetOptions);
|
|
2510
|
-
_subjects.state.next({
|
|
2511
|
-
isLoading: false,
|
|
2512
|
-
});
|
|
2848
|
+
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
|
2513
2849
|
});
|
|
2514
|
-
|
|
2515
|
-
control: {
|
|
2516
|
-
register,
|
|
2517
|
-
unregister,
|
|
2518
|
-
getFieldState,
|
|
2519
|
-
handleSubmit,
|
|
2520
|
-
setError,
|
|
2521
|
-
_subscribe,
|
|
2522
|
-
_runSchema,
|
|
2523
|
-
_updateIsValidating,
|
|
2524
|
-
_focusError,
|
|
2525
|
-
_getWatch,
|
|
2526
|
-
_getDirty,
|
|
2527
|
-
_setValid,
|
|
2528
|
-
_setFieldArray,
|
|
2529
|
-
_setDisabledField,
|
|
2530
|
-
_setErrors,
|
|
2531
|
-
_getFieldArray,
|
|
2532
|
-
_reset,
|
|
2533
|
-
_resetDefaultValues,
|
|
2534
|
-
_removeUnmounted,
|
|
2535
|
-
_disableForm,
|
|
2536
|
-
_subjects,
|
|
2537
|
-
_proxyFormState,
|
|
2538
|
-
get _fields() {
|
|
2539
|
-
return _fields;
|
|
2540
|
-
},
|
|
2541
|
-
get _formValues() {
|
|
2542
|
-
return _formValues;
|
|
2543
|
-
},
|
|
2544
|
-
get _state() {
|
|
2545
|
-
return _state;
|
|
2546
|
-
},
|
|
2547
|
-
set _state(value) {
|
|
2548
|
-
_state = value;
|
|
2549
|
-
},
|
|
2550
|
-
get _defaultValues() {
|
|
2551
|
-
return _defaultValues;
|
|
2552
|
-
},
|
|
2553
|
-
get _names() {
|
|
2554
|
-
return _names;
|
|
2555
|
-
},
|
|
2556
|
-
set _names(value) {
|
|
2557
|
-
_names = value;
|
|
2558
|
-
},
|
|
2559
|
-
get _formState() {
|
|
2560
|
-
return _formState;
|
|
2561
|
-
},
|
|
2562
|
-
get _options() {
|
|
2563
|
-
return _options;
|
|
2564
|
-
},
|
|
2565
|
-
set _options(value) {
|
|
2566
|
-
_options = {
|
|
2567
|
-
..._options,
|
|
2568
|
-
...value,
|
|
2569
|
-
};
|
|
2570
|
-
},
|
|
2571
|
-
},
|
|
2572
|
-
subscribe,
|
|
2573
|
-
trigger,
|
|
2574
|
-
register,
|
|
2575
|
-
handleSubmit,
|
|
2576
|
-
watch,
|
|
2577
|
-
setValue,
|
|
2578
|
-
getValues,
|
|
2579
|
-
reset,
|
|
2580
|
-
resetField,
|
|
2581
|
-
clearErrors,
|
|
2582
|
-
unregister,
|
|
2583
|
-
setError,
|
|
2584
|
-
setFocus,
|
|
2585
|
-
getFieldState,
|
|
2850
|
+
!options.keepIsValid && _setValid();
|
|
2586
2851
|
};
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2852
|
+
const _setDisabledField = ({ disabled, name, }) => {
|
|
2853
|
+
if ((isBoolean(disabled) && _state.mount) ||
|
|
2854
|
+
!!disabled ||
|
|
2855
|
+
_names.disabled.has(name)) {
|
|
2856
|
+
const wasDisabled = _names.disabled.has(name);
|
|
2857
|
+
const isDisabled = !!disabled;
|
|
2858
|
+
const disabledStateChanged = wasDisabled !== isDisabled;
|
|
2859
|
+
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
|
2860
|
+
disabledStateChanged && _state.mount && !_state.action && _setValid();
|
|
2861
|
+
}
|
|
2590
2862
|
};
|
|
2591
|
-
}
|
|
2592
|
-
|
|
2593
|
-
|
|
2594
|
-
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
}
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2628
|
-
if (isUndefined(data[to])) {
|
|
2629
|
-
data[to] = undefined;
|
|
2630
|
-
}
|
|
2631
|
-
data.splice(to, 0, data.splice(from, 1)[0]);
|
|
2632
|
-
return data;
|
|
2633
|
-
};
|
|
2634
|
-
|
|
2635
|
-
var prependAt = (data, value) => [
|
|
2636
|
-
...convertToArrayPayload(value),
|
|
2637
|
-
...convertToArrayPayload(data),
|
|
2638
|
-
];
|
|
2639
|
-
|
|
2640
|
-
function removeAtIndexes(data, indexes) {
|
|
2641
|
-
let i = 0;
|
|
2642
|
-
const temp = [...data];
|
|
2643
|
-
for (const index of indexes) {
|
|
2644
|
-
temp.splice(index - i, 1);
|
|
2645
|
-
i++;
|
|
2646
|
-
}
|
|
2647
|
-
return compact(temp).length ? temp : [];
|
|
2648
|
-
}
|
|
2649
|
-
var removeArrayAt = (data, index) => isUndefined(index)
|
|
2650
|
-
? []
|
|
2651
|
-
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
|
2652
|
-
|
|
2653
|
-
var swapArrayAt = (data, indexA, indexB) => {
|
|
2654
|
-
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
|
2655
|
-
};
|
|
2656
|
-
|
|
2657
|
-
var updateAt = (fieldValues, index, value) => {
|
|
2658
|
-
fieldValues[index] = value;
|
|
2659
|
-
return fieldValues;
|
|
2660
|
-
};
|
|
2661
|
-
|
|
2662
|
-
/**
|
|
2663
|
-
* A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A)
|
|
2664
|
-
*
|
|
2665
|
-
* @remarks
|
|
2666
|
-
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
|
2667
|
-
*
|
|
2668
|
-
* @param props - useFieldArray props
|
|
2669
|
-
*
|
|
2670
|
-
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
|
2671
|
-
*
|
|
2672
|
-
* @example
|
|
2673
|
-
* ```tsx
|
|
2674
|
-
* function App() {
|
|
2675
|
-
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
|
2676
|
-
* defaultValues: {
|
|
2677
|
-
* test: []
|
|
2678
|
-
* }
|
|
2679
|
-
* });
|
|
2680
|
-
* const { fields, append } = useFieldArray({
|
|
2681
|
-
* control,
|
|
2682
|
-
* name: "test"
|
|
2683
|
-
* });
|
|
2684
|
-
*
|
|
2685
|
-
* return (
|
|
2686
|
-
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
|
2687
|
-
* {fields.map((item, index) => (
|
|
2688
|
-
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
|
2689
|
-
* ))}
|
|
2690
|
-
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
|
2691
|
-
* append
|
|
2692
|
-
* </button>
|
|
2693
|
-
* <input type="submit" />
|
|
2694
|
-
* </form>
|
|
2695
|
-
* );
|
|
2696
|
-
* }
|
|
2697
|
-
* ```
|
|
2698
|
-
*/
|
|
2699
|
-
function useFieldArray(props) {
|
|
2700
|
-
const formControl = useFormControlContext();
|
|
2701
|
-
const { control = formControl, name, keyName = 'id', shouldUnregister, rules, } = props;
|
|
2702
|
-
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
|
2703
|
-
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
|
2704
|
-
const _actioned = React.useRef(false);
|
|
2705
|
-
control._names.array.add(name);
|
|
2706
|
-
React.useMemo(() => rules &&
|
|
2707
|
-
fields.length >= 0 &&
|
|
2708
|
-
control.register(name, rules), [control, name, fields.length, rules]);
|
|
2709
|
-
useIsomorphicLayoutEffect(() => control._subjects.array.subscribe({
|
|
2710
|
-
next: ({ values, name: fieldArrayName, }) => {
|
|
2711
|
-
if (fieldArrayName === name || !fieldArrayName) {
|
|
2712
|
-
const fieldValues = get(values, name);
|
|
2713
|
-
if (Array.isArray(fieldValues)) {
|
|
2714
|
-
setFields(fieldValues);
|
|
2715
|
-
ids.current = fieldValues.map(generateId);
|
|
2863
|
+
const register = (name, options = {}) => {
|
|
2864
|
+
let field = get(_fields, name);
|
|
2865
|
+
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
|
2866
|
+
const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
|
|
2867
|
+
set(_fields, name, {
|
|
2868
|
+
...(field || {}),
|
|
2869
|
+
_f: {
|
|
2870
|
+
...(field && field._f ? field._f : { ref: { name } }),
|
|
2871
|
+
name,
|
|
2872
|
+
mount: true,
|
|
2873
|
+
...options,
|
|
2874
|
+
},
|
|
2875
|
+
});
|
|
2876
|
+
_names.mount.add(name);
|
|
2877
|
+
if (field && !shouldRevalidateRemount) {
|
|
2878
|
+
_setDisabledField({
|
|
2879
|
+
disabled: isBoolean(options.disabled)
|
|
2880
|
+
? options.disabled
|
|
2881
|
+
: _options.disabled,
|
|
2882
|
+
name,
|
|
2883
|
+
});
|
|
2884
|
+
}
|
|
2885
|
+
else {
|
|
2886
|
+
updateValidAndValue(name, true, options.value);
|
|
2887
|
+
}
|
|
2888
|
+
return {
|
|
2889
|
+
...(disabledIsDefined
|
|
2890
|
+
? { disabled: options.disabled || _options.disabled }
|
|
2891
|
+
: {}),
|
|
2892
|
+
...(_options.progressive
|
|
2893
|
+
? {
|
|
2894
|
+
required: !!options.required,
|
|
2895
|
+
min: getRuleValue(options.min),
|
|
2896
|
+
max: getRuleValue(options.max),
|
|
2897
|
+
minLength: getRuleValue(options.minLength),
|
|
2898
|
+
maxLength: getRuleValue(options.maxLength),
|
|
2899
|
+
pattern: getRuleValue(options.pattern),
|
|
2716
2900
|
}
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2901
|
+
: {}),
|
|
2902
|
+
name,
|
|
2903
|
+
onChange,
|
|
2904
|
+
onBlur: onChange,
|
|
2905
|
+
ref: (ref) => {
|
|
2906
|
+
if (ref) {
|
|
2907
|
+
_names.registerName.add(name);
|
|
2908
|
+
register(name, options);
|
|
2909
|
+
_names.registerName.delete(name);
|
|
2910
|
+
field = get(_fields, name);
|
|
2911
|
+
const fieldRef = isUndefined(ref.value)
|
|
2912
|
+
? ref.querySelectorAll
|
|
2913
|
+
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
|
2914
|
+
: ref
|
|
2915
|
+
: ref;
|
|
2916
|
+
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
|
2917
|
+
const refs = field._f.refs || [];
|
|
2918
|
+
if (radioOrCheckbox
|
|
2919
|
+
? refs.find((option) => option === fieldRef)
|
|
2920
|
+
: fieldRef === field._f.ref) {
|
|
2921
|
+
return;
|
|
2922
|
+
}
|
|
2923
|
+
const newField = {
|
|
2924
|
+
...field._f,
|
|
2925
|
+
};
|
|
2926
|
+
if (radioOrCheckbox) {
|
|
2927
|
+
newField.refs = [
|
|
2928
|
+
...refs.filter(live),
|
|
2929
|
+
fieldRef,
|
|
2930
|
+
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
|
2931
|
+
];
|
|
2932
|
+
newField.ref = { type: fieldRef.type, name };
|
|
2933
|
+
}
|
|
2934
|
+
else {
|
|
2935
|
+
newField.ref = fieldRef;
|
|
2936
|
+
delete newField.refs;
|
|
2937
|
+
}
|
|
2938
|
+
set(_fields, name, {
|
|
2939
|
+
_f: newField,
|
|
2940
|
+
});
|
|
2941
|
+
updateValidAndValue(name, false, undefined, fieldRef);
|
|
2942
|
+
}
|
|
2943
|
+
else {
|
|
2944
|
+
field = get(_fields, name, {});
|
|
2945
|
+
if (field._f) {
|
|
2946
|
+
field._f.mount = false;
|
|
2947
|
+
}
|
|
2948
|
+
(_options.shouldUnregister || options.shouldUnregister) &&
|
|
2949
|
+
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
|
2950
|
+
_names.unMount.add(name);
|
|
2951
|
+
}
|
|
2952
|
+
},
|
|
2953
|
+
};
|
|
2734
2954
|
};
|
|
2735
|
-
const
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
2955
|
+
const _focusError = () => _options.shouldFocusError &&
|
|
2956
|
+
!_options.shouldUseNativeValidation &&
|
|
2957
|
+
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
|
2958
|
+
const _disableForm = (disabled) => {
|
|
2959
|
+
if (isBoolean(disabled)) {
|
|
2960
|
+
_subjects.state.next({ disabled });
|
|
2961
|
+
iterateFieldsByAction(_fields, (ref, name) => {
|
|
2962
|
+
const currentField = get(_fields, name);
|
|
2963
|
+
if (currentField) {
|
|
2964
|
+
ref.disabled = currentField._f.disabled || disabled;
|
|
2965
|
+
if (Array.isArray(currentField._f.refs)) {
|
|
2966
|
+
currentField._f.refs.forEach((inputRef) => {
|
|
2967
|
+
inputRef.disabled = currentField._f.disabled || disabled;
|
|
2968
|
+
});
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
}, 0, false);
|
|
2972
|
+
}
|
|
2745
2973
|
};
|
|
2746
|
-
const
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2974
|
+
const handleSubmit = (onValid, onInvalid) => async (e) => {
|
|
2975
|
+
let onValidError = undefined;
|
|
2976
|
+
if (e) {
|
|
2977
|
+
e.preventDefault && e.preventDefault();
|
|
2978
|
+
e.persist &&
|
|
2979
|
+
e.persist();
|
|
2980
|
+
}
|
|
2981
|
+
let fieldValues = cloneObject(_formValues);
|
|
2982
|
+
_subjects.state.next({
|
|
2983
|
+
isSubmitting: true,
|
|
2755
2984
|
});
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
2985
|
+
if (_options.resolver) {
|
|
2986
|
+
const { errors, values } = await _runSchema();
|
|
2987
|
+
_updateIsValidating();
|
|
2988
|
+
_formState.errors = errors;
|
|
2989
|
+
fieldValues = cloneObject(values);
|
|
2990
|
+
}
|
|
2991
|
+
else {
|
|
2992
|
+
await executeBuiltInValidation({
|
|
2993
|
+
fields: _fields,
|
|
2994
|
+
eventType: EVENTS.SUBMIT,
|
|
2995
|
+
});
|
|
2996
|
+
}
|
|
2997
|
+
if (_names.disabled.size) {
|
|
2998
|
+
for (const name of _names.disabled) {
|
|
2999
|
+
unset(fieldValues, name);
|
|
3000
|
+
}
|
|
3001
|
+
}
|
|
3002
|
+
unset(_formState.errors, ROOT_ERROR_TYPE);
|
|
3003
|
+
if (isEmptyObject(_formState.errors)) {
|
|
3004
|
+
_subjects.state.next({
|
|
3005
|
+
errors: {},
|
|
3006
|
+
});
|
|
3007
|
+
try {
|
|
3008
|
+
await onValid(fieldValues, e);
|
|
3009
|
+
}
|
|
3010
|
+
catch (error) {
|
|
3011
|
+
onValidError = error;
|
|
3012
|
+
}
|
|
3013
|
+
}
|
|
3014
|
+
else {
|
|
3015
|
+
if (onInvalid) {
|
|
3016
|
+
await onInvalid({ ..._formState.errors }, e);
|
|
3017
|
+
}
|
|
3018
|
+
_focusError();
|
|
3019
|
+
setTimeout(_focusError);
|
|
3020
|
+
}
|
|
3021
|
+
_subjects.state.next({
|
|
3022
|
+
isSubmitted: true,
|
|
3023
|
+
isSubmitting: false,
|
|
3024
|
+
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
|
3025
|
+
submitCount: _formState.submitCount + 1,
|
|
3026
|
+
errors: _formState.errors,
|
|
2767
3027
|
});
|
|
3028
|
+
if (onValidError) {
|
|
3029
|
+
throw onValidError;
|
|
3030
|
+
}
|
|
2768
3031
|
};
|
|
2769
|
-
const
|
|
2770
|
-
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
|
|
2788
|
-
|
|
2789
|
-
|
|
2790
|
-
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
|
|
2794
|
-
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
|
2795
|
-
updateValues(updatedFieldArrayValues);
|
|
2796
|
-
setFields([...updatedFieldArrayValues]);
|
|
2797
|
-
control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
|
|
2798
|
-
argA: index,
|
|
2799
|
-
argB: updateValue,
|
|
2800
|
-
}, true, false);
|
|
2801
|
-
};
|
|
2802
|
-
const replace = (value) => {
|
|
2803
|
-
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
|
|
2804
|
-
ids.current = updatedFieldArrayValues.map(generateId);
|
|
2805
|
-
updateValues([...updatedFieldArrayValues]);
|
|
2806
|
-
setFields([...updatedFieldArrayValues]);
|
|
2807
|
-
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
|
3032
|
+
const resetField = (name, options = {}) => {
|
|
3033
|
+
if (get(_fields, name)) {
|
|
3034
|
+
if (isUndefined(options.defaultValue)) {
|
|
3035
|
+
setValue(name, cloneObject(get(_defaultValues, name)));
|
|
3036
|
+
}
|
|
3037
|
+
else {
|
|
3038
|
+
setValue(name, options.defaultValue);
|
|
3039
|
+
set(_defaultValues, name, cloneObject(options.defaultValue));
|
|
3040
|
+
}
|
|
3041
|
+
if (!options.keepTouched) {
|
|
3042
|
+
unset(_formState.touchedFields, name);
|
|
3043
|
+
}
|
|
3044
|
+
if (!options.keepDirty) {
|
|
3045
|
+
unset(_formState.dirtyFields, name);
|
|
3046
|
+
_formState.isDirty = options.defaultValue
|
|
3047
|
+
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
|
3048
|
+
: _getDirty();
|
|
3049
|
+
}
|
|
3050
|
+
if (!options.keepError) {
|
|
3051
|
+
unset(_formState.errors, name);
|
|
3052
|
+
_proxyFormState.isValid && _setValid();
|
|
3053
|
+
}
|
|
3054
|
+
_subjects.state.next({ ..._formState });
|
|
3055
|
+
}
|
|
2808
3056
|
};
|
|
2809
|
-
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
if (
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
|
|
2819
|
-
if (
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
|
|
2828
|
-
|
|
2829
|
-
|
|
2830
|
-
error
|
|
2831
|
-
? set(control._formState.errors, name, error)
|
|
2832
|
-
: unset(control._formState.errors, name);
|
|
2833
|
-
control._subjects.state.next({
|
|
2834
|
-
errors: control._formState.errors,
|
|
2835
|
-
});
|
|
3057
|
+
const _reset = (formValues, keepStateOptions = {}) => {
|
|
3058
|
+
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
|
|
3059
|
+
const cloneUpdatedValues = cloneObject(updatedValues);
|
|
3060
|
+
const isEmptyResetValues = isEmptyObject(formValues);
|
|
3061
|
+
const values = cloneUpdatedValues;
|
|
3062
|
+
const fieldRefs = _fields;
|
|
3063
|
+
if (!keepStateOptions.keepDefaultValues) {
|
|
3064
|
+
_defaultValues = updatedValues;
|
|
3065
|
+
}
|
|
3066
|
+
if (!keepStateOptions.keepValues) {
|
|
3067
|
+
if (keepStateOptions.keepDirtyValues) {
|
|
3068
|
+
const fieldsToCheck = new Set([
|
|
3069
|
+
..._names.mount,
|
|
3070
|
+
...Object.keys(getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)),
|
|
3071
|
+
]);
|
|
3072
|
+
for (const fieldName of Array.from(fieldsToCheck)) {
|
|
3073
|
+
const isDirty = get(_formState.dirtyFields, fieldName);
|
|
3074
|
+
const existingValue = get(_formValues, fieldName);
|
|
3075
|
+
const newValue = get(values, fieldName);
|
|
3076
|
+
if (isDirty && !isUndefined(existingValue)) {
|
|
3077
|
+
set(values, fieldName, existingValue);
|
|
2836
3078
|
}
|
|
2837
|
-
|
|
3079
|
+
else if (!isDirty && !isUndefined(newValue)) {
|
|
3080
|
+
setValue(fieldName, newValue);
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
2838
3083
|
}
|
|
2839
3084
|
else {
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
3085
|
+
if (isWeb && isUndefined(formValues)) {
|
|
3086
|
+
for (const name of _names.mount) {
|
|
3087
|
+
const field = get(_fields, name);
|
|
3088
|
+
if (field && field._f) {
|
|
3089
|
+
const fieldReference = Array.isArray(field._f.refs)
|
|
3090
|
+
? field._f.refs[0]
|
|
3091
|
+
: field._f.ref;
|
|
3092
|
+
if (isHTMLElement(fieldReference)) {
|
|
3093
|
+
const form = fieldReference.closest('form');
|
|
3094
|
+
if (form) {
|
|
3095
|
+
form.reset();
|
|
3096
|
+
break;
|
|
3097
|
+
}
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
3103
|
+
for (const fieldName of _names.mount) {
|
|
3104
|
+
setValue(fieldName, get(values, fieldName));
|
|
3105
|
+
}
|
|
3106
|
+
}
|
|
3107
|
+
else {
|
|
3108
|
+
_fields = {};
|
|
2849
3109
|
}
|
|
2850
3110
|
}
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
key.startsWith(control._names.focus) &&
|
|
2860
|
-
ref.focus) {
|
|
2861
|
-
ref.focus();
|
|
2862
|
-
return 1;
|
|
3111
|
+
if (_options.shouldUnregister) {
|
|
3112
|
+
_formValues = keepStateOptions.keepDefaultValues
|
|
3113
|
+
? cloneObject(_defaultValues)
|
|
3114
|
+
: {};
|
|
3115
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
3116
|
+
for (const fieldName of _names.mount) {
|
|
3117
|
+
set(_formValues, fieldName, get(values, fieldName));
|
|
3118
|
+
}
|
|
2863
3119
|
}
|
|
2864
|
-
|
|
3120
|
+
}
|
|
3121
|
+
else {
|
|
3122
|
+
_formValues = cloneObject(values);
|
|
3123
|
+
}
|
|
3124
|
+
_subjects.array.next({
|
|
3125
|
+
values: { ...values },
|
|
2865
3126
|
});
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
3127
|
+
_subjects.state.next({
|
|
3128
|
+
name: undefined,
|
|
3129
|
+
type: undefined,
|
|
3130
|
+
values: { ...values },
|
|
3131
|
+
});
|
|
3132
|
+
}
|
|
3133
|
+
_names = {
|
|
3134
|
+
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
|
|
3135
|
+
unMount: new Set(),
|
|
3136
|
+
array: new Set(),
|
|
3137
|
+
registerName: new Set(),
|
|
3138
|
+
disabled: new Set(),
|
|
3139
|
+
watch: new Set(),
|
|
3140
|
+
watchAll: false,
|
|
3141
|
+
focus: '',
|
|
3142
|
+
};
|
|
3143
|
+
_state.mount =
|
|
3144
|
+
!_proxyFormState.isValid ||
|
|
3145
|
+
!!keepStateOptions.keepIsValid ||
|
|
3146
|
+
!!keepStateOptions.keepDirtyValues ||
|
|
3147
|
+
(!_options.shouldUnregister && !isEmptyObject(values));
|
|
3148
|
+
_state.watch = !!_options.shouldUnregister;
|
|
3149
|
+
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
3150
|
+
_state.action = false;
|
|
3151
|
+
if (!keepStateOptions.keepErrors) {
|
|
3152
|
+
_formState.errors = {};
|
|
3153
|
+
}
|
|
3154
|
+
_subjects.state.next({
|
|
3155
|
+
submitCount: keepStateOptions.keepSubmitCount
|
|
3156
|
+
? _formState.submitCount
|
|
3157
|
+
: 0,
|
|
3158
|
+
isDirty: isEmptyResetValues
|
|
3159
|
+
? false
|
|
3160
|
+
: keepStateOptions.keepDirty
|
|
3161
|
+
? _formState.isDirty
|
|
3162
|
+
: keepStateOptions.keepValues
|
|
3163
|
+
? _getDirty()
|
|
3164
|
+
: !!(keepStateOptions.keepDefaultValues &&
|
|
3165
|
+
!deepEqual(formValues, _defaultValues)),
|
|
3166
|
+
isSubmitted: keepStateOptions.keepIsSubmitted
|
|
3167
|
+
? _formState.isSubmitted
|
|
3168
|
+
: false,
|
|
3169
|
+
dirtyFields: isEmptyResetValues
|
|
3170
|
+
? {}
|
|
3171
|
+
: keepStateOptions.keepDirtyValues
|
|
3172
|
+
? keepStateOptions.keepDefaultValues && _formValues
|
|
3173
|
+
? getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)
|
|
3174
|
+
: _formState.dirtyFields
|
|
3175
|
+
: keepStateOptions.keepDefaultValues && formValues
|
|
3176
|
+
? getDirtyFields(_defaultValues, formValues, undefined, fieldRefs)
|
|
3177
|
+
: keepStateOptions.keepDirty
|
|
3178
|
+
? _formState.dirtyFields
|
|
3179
|
+
: {},
|
|
3180
|
+
touchedFields: keepStateOptions.keepTouched
|
|
3181
|
+
? _formState.touchedFields
|
|
3182
|
+
: {},
|
|
3183
|
+
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
|
3184
|
+
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
|
3185
|
+
? _formState.isSubmitSuccessful
|
|
3186
|
+
: false,
|
|
3187
|
+
isSubmitting: false,
|
|
3188
|
+
defaultValues: _defaultValues,
|
|
3189
|
+
});
|
|
3190
|
+
};
|
|
3191
|
+
const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
|
|
3192
|
+
? formValues(_formValues)
|
|
3193
|
+
: formValues, { ..._options.resetOptions, ...keepStateOptions });
|
|
3194
|
+
const setFocus = (name, options = {}) => {
|
|
3195
|
+
const field = get(_fields, name);
|
|
3196
|
+
const fieldReference = field && field._f;
|
|
3197
|
+
if (fieldReference) {
|
|
3198
|
+
const fieldRef = fieldReference.refs
|
|
3199
|
+
? fieldReference.refs[0]
|
|
3200
|
+
: fieldReference.ref;
|
|
3201
|
+
if (fieldRef.focus) {
|
|
3202
|
+
setTimeout(() => {
|
|
3203
|
+
fieldRef.focus();
|
|
3204
|
+
options.shouldSelect &&
|
|
3205
|
+
isFunction(fieldRef.select) &&
|
|
3206
|
+
fieldRef.select();
|
|
3207
|
+
});
|
|
3208
|
+
}
|
|
3209
|
+
}
|
|
3210
|
+
};
|
|
3211
|
+
const _setFormState = (updatedFormState) => {
|
|
3212
|
+
// `name`, `type`, and `values` describe the event that produced this
|
|
3213
|
+
// update, not the form's persisted state (they aren't part of
|
|
3214
|
+
// `FormState`). Merging them in would leak a stale `name`/`type` from
|
|
3215
|
+
// one event into a later, unrelated notification that doesn't specify
|
|
3216
|
+
// its own.
|
|
3217
|
+
const { name, type, values, ...formState } = updatedFormState;
|
|
3218
|
+
_formState = {
|
|
3219
|
+
..._formState,
|
|
3220
|
+
...formState,
|
|
2882
3221
|
};
|
|
2883
|
-
}
|
|
3222
|
+
};
|
|
3223
|
+
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
|
3224
|
+
_options.defaultValues().then((values) => {
|
|
3225
|
+
reset(values, _options.resetOptions);
|
|
3226
|
+
_subjects.state.next({
|
|
3227
|
+
isLoading: false,
|
|
3228
|
+
});
|
|
3229
|
+
});
|
|
3230
|
+
const resetDefaultValues = (values, options = {}) => {
|
|
3231
|
+
_defaultValues = cloneObject(values);
|
|
3232
|
+
if (!options.keepDirty) {
|
|
3233
|
+
const newDirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
3234
|
+
_formState.dirtyFields = newDirtyFields;
|
|
3235
|
+
_formState.isDirty = !isEmptyObject(newDirtyFields);
|
|
3236
|
+
}
|
|
3237
|
+
if (!options.keepIsValid) {
|
|
3238
|
+
_setValid();
|
|
3239
|
+
}
|
|
3240
|
+
_subjects.state.next({
|
|
3241
|
+
..._formState,
|
|
3242
|
+
defaultValues: _defaultValues,
|
|
3243
|
+
});
|
|
3244
|
+
};
|
|
3245
|
+
const methods = {
|
|
3246
|
+
control: {
|
|
3247
|
+
register,
|
|
3248
|
+
unregister,
|
|
3249
|
+
getFieldState,
|
|
3250
|
+
handleSubmit,
|
|
3251
|
+
setError,
|
|
3252
|
+
_subscribe,
|
|
3253
|
+
_runSchema,
|
|
3254
|
+
_updateIsValidating,
|
|
3255
|
+
_focusError,
|
|
3256
|
+
_getWatch,
|
|
3257
|
+
_getDirty,
|
|
3258
|
+
_setValid,
|
|
3259
|
+
_setFieldArray,
|
|
3260
|
+
_setDisabledField,
|
|
3261
|
+
_setErrors,
|
|
3262
|
+
_getFieldArray,
|
|
3263
|
+
_reset,
|
|
3264
|
+
_resetDefaultValues,
|
|
3265
|
+
_removeUnmounted,
|
|
3266
|
+
_disableForm,
|
|
3267
|
+
_subjects,
|
|
3268
|
+
_proxyFormState,
|
|
3269
|
+
get _fields() {
|
|
3270
|
+
return _fields;
|
|
3271
|
+
},
|
|
3272
|
+
get _formValues() {
|
|
3273
|
+
return _formValues;
|
|
3274
|
+
},
|
|
3275
|
+
get _state() {
|
|
3276
|
+
return _state;
|
|
3277
|
+
},
|
|
3278
|
+
set _state(value) {
|
|
3279
|
+
_state = value;
|
|
3280
|
+
},
|
|
3281
|
+
get _defaultValues() {
|
|
3282
|
+
return _defaultValues;
|
|
3283
|
+
},
|
|
3284
|
+
get _names() {
|
|
3285
|
+
return _names;
|
|
3286
|
+
},
|
|
3287
|
+
set _names(value) {
|
|
3288
|
+
_names = value;
|
|
3289
|
+
},
|
|
3290
|
+
get _formState() {
|
|
3291
|
+
return _formState;
|
|
3292
|
+
},
|
|
3293
|
+
get _options() {
|
|
3294
|
+
return _options;
|
|
3295
|
+
},
|
|
3296
|
+
set _options(value) {
|
|
3297
|
+
_options = {
|
|
3298
|
+
..._options,
|
|
3299
|
+
...value,
|
|
3300
|
+
};
|
|
3301
|
+
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
3302
|
+
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
3303
|
+
},
|
|
3304
|
+
},
|
|
3305
|
+
subscribe,
|
|
3306
|
+
trigger,
|
|
3307
|
+
register,
|
|
3308
|
+
handleSubmit,
|
|
3309
|
+
watch,
|
|
3310
|
+
setValue,
|
|
3311
|
+
setValues,
|
|
3312
|
+
getValues,
|
|
3313
|
+
reset,
|
|
3314
|
+
resetField,
|
|
3315
|
+
resetDefaultValues,
|
|
3316
|
+
clearErrors,
|
|
3317
|
+
unregister,
|
|
3318
|
+
setError,
|
|
3319
|
+
setFocus,
|
|
3320
|
+
getFieldState,
|
|
3321
|
+
};
|
|
2884
3322
|
return {
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
prepend: React.useCallback(prepend, [updateValues, name, control]),
|
|
2888
|
-
append: React.useCallback(append, [updateValues, name, control]),
|
|
2889
|
-
remove: React.useCallback(remove, [updateValues, name, control]),
|
|
2890
|
-
insert: React.useCallback(insert$1, [updateValues, name, control]),
|
|
2891
|
-
update: React.useCallback(update, [updateValues, name, control]),
|
|
2892
|
-
replace: React.useCallback(replace, [updateValues, name, control]),
|
|
2893
|
-
fields: React.useMemo(() => fields.map((field, index) => ({
|
|
2894
|
-
...field,
|
|
2895
|
-
[keyName]: ids.current[index] || generateId(),
|
|
2896
|
-
})), [fields, keyName]),
|
|
3323
|
+
...methods,
|
|
3324
|
+
formControl: methods,
|
|
2897
3325
|
};
|
|
2898
3326
|
}
|
|
2899
3327
|
|
|
@@ -2929,26 +3357,19 @@ function useFieldArray(props) {
|
|
|
2929
3357
|
function useForm(props = {}) {
|
|
2930
3358
|
const _formControl = React.useRef(undefined);
|
|
2931
3359
|
const _values = React.useRef(undefined);
|
|
2932
|
-
const
|
|
2933
|
-
|
|
2934
|
-
|
|
3360
|
+
const _formControlProp = React.useRef(props.formControl);
|
|
3361
|
+
const [formState, updateFormState] = React.useState(() => ({
|
|
3362
|
+
...cloneObject(DEFAULT_FORM_STATE),
|
|
2935
3363
|
isLoading: isFunction(props.defaultValues),
|
|
2936
|
-
isSubmitted: false,
|
|
2937
|
-
isSubmitting: false,
|
|
2938
|
-
isSubmitSuccessful: false,
|
|
2939
|
-
isValid: false,
|
|
2940
|
-
submitCount: 0,
|
|
2941
|
-
dirtyFields: {},
|
|
2942
|
-
touchedFields: {},
|
|
2943
|
-
validatingFields: {},
|
|
2944
3364
|
errors: props.errors || {},
|
|
2945
3365
|
disabled: props.disabled || false,
|
|
2946
|
-
isReady: false,
|
|
2947
3366
|
defaultValues: isFunction(props.defaultValues)
|
|
2948
3367
|
? undefined
|
|
2949
3368
|
: props.defaultValues,
|
|
2950
|
-
});
|
|
2951
|
-
if (!_formControl.current
|
|
3369
|
+
}));
|
|
3370
|
+
if (!_formControl.current ||
|
|
3371
|
+
(props.formControl && _formControlProp.current !== props.formControl)) {
|
|
3372
|
+
_formControlProp.current = props.formControl;
|
|
2952
3373
|
if (props.formControl) {
|
|
2953
3374
|
_formControl.current = {
|
|
2954
3375
|
...props.formControl,
|
|
@@ -2971,7 +3392,10 @@ function useForm(props = {}) {
|
|
|
2971
3392
|
useIsomorphicLayoutEffect(() => {
|
|
2972
3393
|
const sub = control._subscribe({
|
|
2973
3394
|
formState: control._proxyFormState,
|
|
2974
|
-
callback: () => updateFormState({
|
|
3395
|
+
callback: () => updateFormState({
|
|
3396
|
+
...control._formState,
|
|
3397
|
+
defaultValues: control._defaultValues,
|
|
3398
|
+
}),
|
|
2975
3399
|
reRenderRoot: true,
|
|
2976
3400
|
});
|
|
2977
3401
|
updateFormState((data) => ({
|
|
@@ -3072,5 +3496,5 @@ function useForm(props = {}) {
|
|
|
3072
3496
|
*/
|
|
3073
3497
|
const Watch = (props) => props.render(useWatch({ name: props.names, ...props }));
|
|
3074
3498
|
|
|
3075
|
-
export { Controller, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
|
3499
|
+
export { Controller, FieldArray, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
|
3076
3500
|
//# sourceMappingURL=index.esm.mjs.map
|