@depup/react-hook-form 7.72.1-depup.0 → 7.84.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 +37 -0
- package/dist/fieldArray.d.ts.map +1 -0
- package/dist/form.d.ts +1 -1
- package/dist/form.d.ts.map +1 -1
- package/dist/formStateSubscribe.d.ts +8 -3
- package/dist/formStateSubscribe.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 +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.mjs +2537 -2059
- 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/collectDirtyFieldNames.d.ts +3 -0
- package/dist/logic/collectDirtyFieldNames.d.ts.map +1 -0
- 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/getFieldValue.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/iterateFieldsByAction.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 +517 -188
- 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 +85 -60
- 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/formData.d.ts +3 -0
- package/dist/utils/formData.d.ts.map +1 -0
- 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/json.d.ts +9 -0
- package/dist/utils/json.d.ts.map +1 -0
- 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 -28
- 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,83 @@ function useController(props) {
|
|
|
559
606
|
*/
|
|
560
607
|
const Controller = (props) => props.render(useController(props));
|
|
561
608
|
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
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
|
+
if (key === '_f') {
|
|
648
|
+
continue;
|
|
570
649
|
}
|
|
571
|
-
|
|
572
|
-
|
|
650
|
+
const field = fieldsNames ? get(fields, key) : fields[key];
|
|
651
|
+
if (field) {
|
|
652
|
+
const { _f } = field;
|
|
653
|
+
if (_f) {
|
|
654
|
+
if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
|
|
655
|
+
return true;
|
|
656
|
+
}
|
|
657
|
+
else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
|
|
658
|
+
return true;
|
|
659
|
+
}
|
|
660
|
+
else {
|
|
661
|
+
if (iterateFieldsByAction(field, action)) {
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
else if (isObject(field) || Array.isArray(field)) {
|
|
667
|
+
if (iterateFieldsByAction(field, action)) {
|
|
668
|
+
break;
|
|
669
|
+
}
|
|
670
|
+
}
|
|
573
671
|
}
|
|
574
672
|
}
|
|
575
|
-
return
|
|
673
|
+
return;
|
|
576
674
|
};
|
|
577
675
|
|
|
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)));
|
|
676
|
+
var updateFieldArrayRootError = (errors, error, name) => {
|
|
677
|
+
const existingErrors = get(errors, name);
|
|
678
|
+
const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
|
|
679
|
+
set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
|
|
680
|
+
set(errors, name, fieldArrayErrors);
|
|
681
|
+
return errors;
|
|
680
682
|
};
|
|
681
683
|
|
|
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
684
|
var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
|
|
846
685
|
|
|
847
|
-
var isFileInput = (element) => element.type === 'file';
|
|
848
|
-
|
|
849
686
|
var isHTMLElement = (value) => {
|
|
850
687
|
if (!isWeb) {
|
|
851
688
|
return false;
|
|
@@ -855,96 +692,19 @@ var isHTMLElement = (value) => {
|
|
|
855
692
|
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
|
|
856
693
|
};
|
|
857
694
|
|
|
858
|
-
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
|
859
|
-
|
|
860
695
|
var isRadioInput = (element) => element.type === 'radio';
|
|
861
696
|
|
|
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
|
-
};
|
|
697
|
+
var isRegex = (value) => value instanceof RegExp;
|
|
910
698
|
|
|
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
|
-
}
|
|
699
|
+
var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
|
|
700
|
+
? {
|
|
701
|
+
...errors[name],
|
|
702
|
+
types: {
|
|
703
|
+
...(errors[name] && errors[name].types ? errors[name].types : {}),
|
|
704
|
+
[type]: message || true,
|
|
705
|
+
},
|
|
945
706
|
}
|
|
946
|
-
|
|
947
|
-
}
|
|
707
|
+
: {};
|
|
948
708
|
|
|
949
709
|
const defaultResult = {
|
|
950
710
|
value: false,
|
|
@@ -971,20 +731,6 @@ var getCheckboxValue = (options) => {
|
|
|
971
731
|
return defaultResult;
|
|
972
732
|
};
|
|
973
733
|
|
|
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
734
|
const defaultReturn = {
|
|
989
735
|
isValid: false,
|
|
990
736
|
value: null,
|
|
@@ -998,217 +744,41 @@ var getRadioValue = (options) => Array.isArray(options)
|
|
|
998
744
|
: previous, defaultReturn)
|
|
999
745
|
: defaultReturn;
|
|
1000
746
|
|
|
1001
|
-
function
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
return [...ref.selectedOptions].map(({ value }) => value);
|
|
1011
|
-
}
|
|
1012
|
-
if (isCheckBoxInput(ref)) {
|
|
1013
|
-
return getCheckboxValue(_f.refs).value;
|
|
747
|
+
function getValidateError(result, ref, type = 'validate') {
|
|
748
|
+
if (isString(result) ||
|
|
749
|
+
(Array.isArray(result) && result.every(isString)) ||
|
|
750
|
+
(isBoolean(result) && !result)) {
|
|
751
|
+
return {
|
|
752
|
+
type,
|
|
753
|
+
message: isString(result) ? result : '',
|
|
754
|
+
ref,
|
|
755
|
+
};
|
|
1014
756
|
}
|
|
1015
|
-
return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
|
|
1016
757
|
}
|
|
1017
758
|
|
|
1018
|
-
var
|
|
759
|
+
var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
|
|
760
|
+
? validationData
|
|
761
|
+
: {
|
|
762
|
+
value: validationData,
|
|
763
|
+
message: '',
|
|
764
|
+
};
|
|
1019
765
|
|
|
1020
|
-
var
|
|
1021
|
-
const
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
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
|
-
function getValidateError(result, ref, type = 'validate') {
|
|
1184
|
-
if (isString(result) ||
|
|
1185
|
-
(Array.isArray(result) && result.every(isString)) ||
|
|
1186
|
-
(isBoolean(result) && !result)) {
|
|
1187
|
-
return {
|
|
1188
|
-
type,
|
|
1189
|
-
message: isString(result) ? result : '',
|
|
1190
|
-
ref,
|
|
1191
|
-
};
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
|
|
1195
|
-
var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData)
|
|
1196
|
-
? validationData
|
|
1197
|
-
: {
|
|
1198
|
-
value: validationData,
|
|
1199
|
-
message: '',
|
|
1200
|
-
};
|
|
1201
|
-
|
|
1202
|
-
var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
|
|
1203
|
-
const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f;
|
|
1204
|
-
const inputValue = get(formValues, name);
|
|
1205
|
-
if (!mount || disabledFieldNames.has(name)) {
|
|
1206
|
-
return {};
|
|
766
|
+
var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
|
|
767
|
+
const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f;
|
|
768
|
+
const inputValue = get(formValues, name);
|
|
769
|
+
if (!mount || disabledFieldNames.has(name)) {
|
|
770
|
+
return {};
|
|
1207
771
|
}
|
|
1208
772
|
const inputRef = refs ? refs[0] : ref;
|
|
1209
773
|
const setCustomValidity = (message) => {
|
|
1210
774
|
if (shouldUseNativeValidation && inputRef.reportValidity) {
|
|
1211
|
-
|
|
775
|
+
const validityMessage = isBoolean(message) ? '' : message || '';
|
|
776
|
+
if (refs) {
|
|
777
|
+
refs.forEach((ref) => ref.setCustomValidity(validityMessage));
|
|
778
|
+
}
|
|
779
|
+
else {
|
|
780
|
+
inputRef.setCustomValidity(validityMessage);
|
|
781
|
+
}
|
|
1212
782
|
inputRef.reportValidity();
|
|
1213
783
|
}
|
|
1214
784
|
};
|
|
@@ -1378,1522 +948,2434 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
|
|
|
1378
948
|
return error;
|
|
1379
949
|
};
|
|
1380
950
|
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
951
|
+
var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
|
|
952
|
+
|
|
953
|
+
var appendAt = (data, value) => [
|
|
954
|
+
...data,
|
|
955
|
+
...convertToArrayPayload(value),
|
|
956
|
+
];
|
|
957
|
+
|
|
958
|
+
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
|
|
959
|
+
|
|
960
|
+
function insert(data, index, value) {
|
|
961
|
+
return [
|
|
962
|
+
...data.slice(0, index),
|
|
963
|
+
...convertToArrayPayload(value),
|
|
964
|
+
...data.slice(index),
|
|
965
|
+
];
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
var moveArrayAt = (data, from, to) => {
|
|
969
|
+
if (!Array.isArray(data)) {
|
|
970
|
+
return [];
|
|
971
|
+
}
|
|
972
|
+
if (isUndefined(data[to])) {
|
|
973
|
+
data[to] = undefined;
|
|
974
|
+
}
|
|
975
|
+
data.splice(to, 0, data.splice(from, 1)[0]);
|
|
976
|
+
return data;
|
|
1385
977
|
};
|
|
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;
|
|
1457
|
-
}
|
|
1458
|
-
if (!_options.disabled &&
|
|
1459
|
-
(_proxyFormState.isValid ||
|
|
1460
|
-
_proxySubscribeFormState.isValid ||
|
|
1461
|
-
shouldUpdateValid)) {
|
|
1462
|
-
let isValid;
|
|
1463
|
-
if (_options.resolver) {
|
|
1464
|
-
isValid = isEmptyObject((await _runSchema()).errors);
|
|
1465
|
-
_updateIsValidating();
|
|
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
|
-
}
|
|
978
|
+
|
|
979
|
+
var prependAt = (data, value) => [
|
|
980
|
+
...convertToArrayPayload(value),
|
|
981
|
+
...convertToArrayPayload(data),
|
|
982
|
+
];
|
|
983
|
+
|
|
984
|
+
var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
|
|
985
|
+
|
|
986
|
+
function removeAtIndexes(data, indexes) {
|
|
987
|
+
let i = 0;
|
|
988
|
+
const temp = [...data];
|
|
989
|
+
for (const index of indexes) {
|
|
990
|
+
temp.splice(index - i, 1);
|
|
991
|
+
i++;
|
|
992
|
+
}
|
|
993
|
+
return compact(temp).length ? temp : [];
|
|
994
|
+
}
|
|
995
|
+
var removeArrayAt = (data, index) => isUndefined(index)
|
|
996
|
+
? []
|
|
997
|
+
: removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
|
|
998
|
+
|
|
999
|
+
var swapArrayAt = (data, indexA, indexB) => {
|
|
1000
|
+
[data[indexA], data[indexB]] = [data[indexB], data[indexA]];
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
function baseGet(object, updatePath) {
|
|
1004
|
+
const length = updatePath.length - 1;
|
|
1005
|
+
let index = 0;
|
|
1006
|
+
while (index < length) {
|
|
1007
|
+
if (isNullOrUndefined(object)) {
|
|
1008
|
+
object = undefined;
|
|
1009
|
+
break;
|
|
1479
1010
|
}
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
isValidating
|
|
1490
|
-
? set(_formState.validatingFields, name, isValidating)
|
|
1491
|
-
: unset(_formState.validatingFields, name);
|
|
1492
|
-
}
|
|
1493
|
-
});
|
|
1494
|
-
_subjects.state.next({
|
|
1495
|
-
validatingFields: _formState.validatingFields,
|
|
1496
|
-
isValidating: !isEmptyObject(_formState.validatingFields),
|
|
1497
|
-
});
|
|
1011
|
+
object = object[updatePath[index]];
|
|
1012
|
+
index++;
|
|
1013
|
+
}
|
|
1014
|
+
return object;
|
|
1015
|
+
}
|
|
1016
|
+
function isEmptyArray(obj) {
|
|
1017
|
+
for (const key in obj) {
|
|
1018
|
+
if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
|
|
1019
|
+
return false;
|
|
1498
1020
|
}
|
|
1499
|
-
}
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1021
|
+
}
|
|
1022
|
+
return true;
|
|
1023
|
+
}
|
|
1024
|
+
function unset(object, path) {
|
|
1025
|
+
if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
|
|
1026
|
+
delete object[path];
|
|
1027
|
+
return object;
|
|
1028
|
+
}
|
|
1029
|
+
const paths = Array.isArray(path)
|
|
1030
|
+
? path
|
|
1031
|
+
: isKey(path)
|
|
1032
|
+
? [path]
|
|
1033
|
+
: stringToPath(path);
|
|
1034
|
+
if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
|
|
1035
|
+
return object;
|
|
1036
|
+
}
|
|
1037
|
+
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
|
1038
|
+
const index = paths.length - 1;
|
|
1039
|
+
const key = paths[index];
|
|
1040
|
+
if (childObject) {
|
|
1041
|
+
delete childObject[key];
|
|
1042
|
+
}
|
|
1043
|
+
if (index !== 0 &&
|
|
1044
|
+
((isObject(childObject) && isEmptyObject(childObject)) ||
|
|
1045
|
+
(Array.isArray(childObject) && isEmptyArray(childObject)))) {
|
|
1046
|
+
unset(object, paths.slice(0, -1));
|
|
1047
|
+
}
|
|
1048
|
+
return object;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
var updateAt = (fieldValues, index, value) => {
|
|
1052
|
+
fieldValues[index] = value;
|
|
1053
|
+
return fieldValues;
|
|
1054
|
+
};
|
|
1055
|
+
|
|
1056
|
+
/**
|
|
1057
|
+
* 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)
|
|
1058
|
+
*
|
|
1059
|
+
* @remarks
|
|
1060
|
+
* [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
|
|
1061
|
+
*
|
|
1062
|
+
* @param props - useFieldArray props
|
|
1063
|
+
*
|
|
1064
|
+
* @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
|
|
1065
|
+
*
|
|
1066
|
+
* @example
|
|
1067
|
+
* ```tsx
|
|
1068
|
+
* function App() {
|
|
1069
|
+
* const { register, control, handleSubmit, reset, trigger, setError } = useForm({
|
|
1070
|
+
* defaultValues: {
|
|
1071
|
+
* test: []
|
|
1072
|
+
* }
|
|
1073
|
+
* });
|
|
1074
|
+
* const { fields, append } = useFieldArray({
|
|
1075
|
+
* control,
|
|
1076
|
+
* name: "test"
|
|
1077
|
+
* });
|
|
1078
|
+
*
|
|
1079
|
+
* return (
|
|
1080
|
+
* <form onSubmit={handleSubmit(data => console.log(data))}>
|
|
1081
|
+
* {fields.map((item, index) => (
|
|
1082
|
+
* <input key={item.id} {...register(`test.${index}.firstName`)} />
|
|
1083
|
+
* ))}
|
|
1084
|
+
* <button type="button" onClick={() => append({ firstName: "bill" })}>
|
|
1085
|
+
* append
|
|
1086
|
+
* </button>
|
|
1087
|
+
* <input type="submit" />
|
|
1088
|
+
* </form>
|
|
1089
|
+
* );
|
|
1090
|
+
* }
|
|
1091
|
+
* ```
|
|
1092
|
+
*/
|
|
1093
|
+
function useFieldArray(props) {
|
|
1094
|
+
const formControl = useFormControlContext();
|
|
1095
|
+
const { control = formControl, name, keyName = 'id', disabled, shouldUnregister, rules, } = props;
|
|
1096
|
+
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
|
1097
|
+
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
|
1098
|
+
const _actioned = React.useRef(false);
|
|
1099
|
+
if (!disabled) {
|
|
1100
|
+
control._names.array.add(name);
|
|
1101
|
+
}
|
|
1102
|
+
React.useMemo(() => !disabled &&
|
|
1103
|
+
rules &&
|
|
1104
|
+
fields.length >= 0 &&
|
|
1105
|
+
control.register(name, rules), [control, name, fields.length, rules, disabled]);
|
|
1106
|
+
useIsomorphicLayoutEffect(() => {
|
|
1107
|
+
if (disabled) {
|
|
1108
|
+
return;
|
|
1535
1109
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1110
|
+
return control._subjects.array.subscribe({
|
|
1111
|
+
next: ({ values, name: fieldArrayName, }) => {
|
|
1112
|
+
if (fieldArrayName === name || !fieldArrayName) {
|
|
1113
|
+
const fieldValues = get(values, name);
|
|
1114
|
+
if (Array.isArray(fieldValues)) {
|
|
1115
|
+
setFields(fieldValues);
|
|
1116
|
+
ids.current = fieldValues.map(generateId);
|
|
1117
|
+
}
|
|
1118
|
+
else if (!fieldArrayName) {
|
|
1119
|
+
setFields([]);
|
|
1120
|
+
ids.current = [];
|
|
1121
|
+
}
|
|
1122
|
+
}
|
|
1123
|
+
},
|
|
1124
|
+
}).unsubscribe;
|
|
1125
|
+
}, [control, name, disabled]);
|
|
1126
|
+
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
|
1127
|
+
_actioned.current = true;
|
|
1128
|
+
control._setFieldArray(name, updatedFieldArrayValues);
|
|
1129
|
+
}, [control, name]);
|
|
1130
|
+
const append = (value, options) => {
|
|
1131
|
+
if (disabled) {
|
|
1132
|
+
return;
|
|
1538
1133
|
}
|
|
1134
|
+
const appendValue = convertToArrayPayload(cloneObject(value));
|
|
1135
|
+
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
|
|
1136
|
+
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
|
|
1137
|
+
ids.current = appendAt(ids.current, appendValue.map(generateId));
|
|
1138
|
+
updateValues(updatedFieldArrayValues);
|
|
1139
|
+
setFields(updatedFieldArrayValues);
|
|
1140
|
+
control._setFieldArray(name, updatedFieldArrayValues, appendAt, {
|
|
1141
|
+
argA: fillEmptyArray(value),
|
|
1142
|
+
});
|
|
1539
1143
|
};
|
|
1540
|
-
const
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1144
|
+
const prepend = (value, options) => {
|
|
1145
|
+
if (disabled) {
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
const prependValue = convertToArrayPayload(cloneObject(value));
|
|
1149
|
+
const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
|
|
1150
|
+
control._names.focus = getFocusFieldName(name, 0, options);
|
|
1151
|
+
ids.current = prependAt(ids.current, prependValue.map(generateId));
|
|
1152
|
+
updateValues(updatedFieldArrayValues);
|
|
1153
|
+
setFields(updatedFieldArrayValues);
|
|
1154
|
+
control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
|
|
1155
|
+
argA: fillEmptyArray(value),
|
|
1544
1156
|
});
|
|
1545
1157
|
};
|
|
1546
|
-
const
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1158
|
+
const remove = (index) => {
|
|
1159
|
+
if (disabled) {
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
|
|
1163
|
+
ids.current = removeArrayAt(ids.current, index);
|
|
1164
|
+
updateValues(updatedFieldArrayValues);
|
|
1165
|
+
setFields(updatedFieldArrayValues);
|
|
1166
|
+
!Array.isArray(get(control._fields, name)) &&
|
|
1167
|
+
set(control._fields, name, undefined);
|
|
1168
|
+
control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
|
|
1169
|
+
argA: index,
|
|
1551
1170
|
});
|
|
1552
1171
|
};
|
|
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();
|
|
1172
|
+
const insert$1 = (index, value, options) => {
|
|
1173
|
+
if (disabled) {
|
|
1174
|
+
return;
|
|
1563
1175
|
}
|
|
1176
|
+
const insertValue = convertToArrayPayload(cloneObject(value));
|
|
1177
|
+
const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
|
|
1178
|
+
control._names.focus = getFocusFieldName(name, index, options);
|
|
1179
|
+
ids.current = insert(ids.current, index, insertValue.map(generateId));
|
|
1180
|
+
updateValues(updatedFieldArrayValues);
|
|
1181
|
+
setFields(updatedFieldArrayValues);
|
|
1182
|
+
control._setFieldArray(name, updatedFieldArrayValues, insert, {
|
|
1183
|
+
argA: index,
|
|
1184
|
+
argB: fillEmptyArray(value),
|
|
1185
|
+
});
|
|
1564
1186
|
};
|
|
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);
|
|
1187
|
+
const swap = (indexA, indexB) => {
|
|
1188
|
+
if (disabled) {
|
|
1189
|
+
return;
|
|
1603
1190
|
}
|
|
1604
|
-
|
|
1191
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
1192
|
+
swapArrayAt(updatedFieldArrayValues, indexA, indexB);
|
|
1193
|
+
swapArrayAt(ids.current, indexA, indexB);
|
|
1194
|
+
updateValues(updatedFieldArrayValues);
|
|
1195
|
+
setFields(updatedFieldArrayValues);
|
|
1196
|
+
control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
|
|
1197
|
+
argA: indexA,
|
|
1198
|
+
argB: indexB,
|
|
1199
|
+
}, false);
|
|
1605
1200
|
};
|
|
1606
|
-
const
|
|
1607
|
-
|
|
1608
|
-
|
|
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);
|
|
1201
|
+
const move = (from, to) => {
|
|
1202
|
+
if (disabled) {
|
|
1203
|
+
return;
|
|
1636
1204
|
}
|
|
1205
|
+
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
1206
|
+
moveArrayAt(updatedFieldArrayValues, from, to);
|
|
1207
|
+
moveArrayAt(ids.current, from, to);
|
|
1208
|
+
updateValues(updatedFieldArrayValues);
|
|
1209
|
+
setFields(updatedFieldArrayValues);
|
|
1210
|
+
control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
|
|
1211
|
+
argA: from,
|
|
1212
|
+
argB: to,
|
|
1213
|
+
}, false);
|
|
1637
1214
|
};
|
|
1638
|
-
const
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
};
|
|
1642
|
-
const executeSchemaAndUpdateState = async (names) => {
|
|
1643
|
-
const { errors } = await _runSchema(names);
|
|
1644
|
-
_updateIsValidating(names);
|
|
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
|
-
}
|
|
1215
|
+
const update = (index, value) => {
|
|
1216
|
+
if (disabled) {
|
|
1217
|
+
return;
|
|
1652
1218
|
}
|
|
1653
|
-
|
|
1654
|
-
|
|
1219
|
+
const updateValue = cloneObject(value);
|
|
1220
|
+
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
|
|
1221
|
+
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
|
1222
|
+
updateValues(updatedFieldArrayValues);
|
|
1223
|
+
setFields([...updatedFieldArrayValues]);
|
|
1224
|
+
control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
|
|
1225
|
+
argA: index,
|
|
1226
|
+
argB: updateValue,
|
|
1227
|
+
}, true, false);
|
|
1228
|
+
};
|
|
1229
|
+
const replace = (value) => {
|
|
1230
|
+
if (disabled) {
|
|
1231
|
+
return;
|
|
1655
1232
|
}
|
|
1656
|
-
|
|
1233
|
+
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
|
|
1234
|
+
ids.current = updatedFieldArrayValues.map(generateId);
|
|
1235
|
+
updateValues([...updatedFieldArrayValues]);
|
|
1236
|
+
setFields([...updatedFieldArrayValues]);
|
|
1237
|
+
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
|
1657
1238
|
};
|
|
1658
|
-
|
|
1659
|
-
if (
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1239
|
+
React.useEffect(() => {
|
|
1240
|
+
if (disabled) {
|
|
1241
|
+
return;
|
|
1242
|
+
}
|
|
1243
|
+
control._state.action = false;
|
|
1244
|
+
isWatched(name, control._names) &&
|
|
1245
|
+
control._subjects.state.next({
|
|
1246
|
+
...control._formState,
|
|
1665
1247
|
});
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1248
|
+
const validationModes = getValidationModes(control._options.mode);
|
|
1249
|
+
if (_actioned.current &&
|
|
1250
|
+
(!validationModes.isOnSubmit || control._formState.isSubmitted) &&
|
|
1251
|
+
!getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
|
1252
|
+
!validationModes.isOnBlur) {
|
|
1253
|
+
if (control._options.resolver) {
|
|
1254
|
+
control._runSchema([name]).then((result) => {
|
|
1255
|
+
var _a, _b;
|
|
1256
|
+
control._updateIsValidating([name]);
|
|
1257
|
+
const error = get(result.errors, name);
|
|
1258
|
+
const existingError = get(control._formState.errors, name);
|
|
1259
|
+
const existingErrorType = existingError && (existingError.type || ((_a = existingError.root) === null || _a === void 0 ? void 0 : _a.type));
|
|
1260
|
+
const existingErrorMessage = existingError &&
|
|
1261
|
+
(existingError.message || ((_b = existingError.root) === null || _b === void 0 ? void 0 : _b.message));
|
|
1262
|
+
if (existingError
|
|
1263
|
+
? (!error && existingErrorType) ||
|
|
1264
|
+
(error &&
|
|
1265
|
+
(existingErrorType !== error.type ||
|
|
1266
|
+
existingErrorMessage !== error.message))
|
|
1267
|
+
: error && error.type) {
|
|
1268
|
+
if (error) {
|
|
1269
|
+
isObject(error) &&
|
|
1270
|
+
!Object.keys(error).some((key) => !Number.isNaN(+key))
|
|
1271
|
+
? updateFieldArrayRootError(control._formState.errors, { [name]: error }, name)
|
|
1272
|
+
: set(control._formState.errors, name, error);
|
|
1273
|
+
}
|
|
1274
|
+
else {
|
|
1275
|
+
unset(control._formState.errors, name);
|
|
1276
|
+
}
|
|
1277
|
+
control._subjects.state.next({
|
|
1278
|
+
errors: control._formState.errors,
|
|
1673
1279
|
});
|
|
1674
1280
|
}
|
|
1675
|
-
}
|
|
1676
|
-
}
|
|
1677
|
-
else if (isString(result) || !result) {
|
|
1678
|
-
setError(FORM_ERROR_TYPE, {
|
|
1679
|
-
message: result || '',
|
|
1680
|
-
type: INPUT_VALIDATION_RULES.validate,
|
|
1681
1281
|
});
|
|
1682
1282
|
}
|
|
1683
1283
|
else {
|
|
1684
|
-
|
|
1284
|
+
const field = get(control._fields, name);
|
|
1285
|
+
if (field &&
|
|
1286
|
+
field._f &&
|
|
1287
|
+
!(getValidationModes(control._options.reValidateMode).isOnSubmit &&
|
|
1288
|
+
getValidationModes(control._options.mode).isOnSubmit)) {
|
|
1289
|
+
validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
|
|
1290
|
+
control._subjects.state.next({
|
|
1291
|
+
errors: updateFieldArrayRootError(control._formState.errors, error, name),
|
|
1292
|
+
}));
|
|
1293
|
+
}
|
|
1685
1294
|
}
|
|
1686
|
-
return result;
|
|
1687
1295
|
}
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
}, }) => {
|
|
1694
|
-
if (props.validate) {
|
|
1695
|
-
context.runRootValidation = true;
|
|
1696
|
-
const result = await validateForm({
|
|
1296
|
+
// External updates that change `fields` (e.g. reset() or setValue() on
|
|
1297
|
+
// the array) already notify subscribers with the up-to-date values
|
|
1298
|
+
// themselves, so only re-broadcast here for genuine array method calls.
|
|
1299
|
+
_actioned.current &&
|
|
1300
|
+
control._subjects.state.next({
|
|
1697
1301
|
name,
|
|
1698
|
-
|
|
1302
|
+
values: cloneObject(control._formValues),
|
|
1699
1303
|
});
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
if (
|
|
1703
|
-
|
|
1304
|
+
control._names.focus &&
|
|
1305
|
+
iterateFieldsByAction(control._fields, (ref, key) => {
|
|
1306
|
+
if (control._names.focus &&
|
|
1307
|
+
key.startsWith(control._names.focus) &&
|
|
1308
|
+
ref.focus) {
|
|
1309
|
+
ref.focus();
|
|
1310
|
+
return 1;
|
|
1704
1311
|
}
|
|
1705
|
-
|
|
1312
|
+
return;
|
|
1313
|
+
});
|
|
1314
|
+
control._names.focus = '';
|
|
1315
|
+
control._setValid();
|
|
1316
|
+
_actioned.current = false;
|
|
1317
|
+
}, [fields, name, control, disabled]);
|
|
1318
|
+
React.useEffect(() => {
|
|
1319
|
+
if (!disabled) {
|
|
1320
|
+
!get(control._formValues, name) && control._setFieldArray(name);
|
|
1706
1321
|
}
|
|
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
|
-
}
|
|
1322
|
+
return () => {
|
|
1323
|
+
if (disabled) {
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
|
|
1327
|
+
const updateMounted = (name, value) => {
|
|
1328
|
+
const field = get(control._fields, name);
|
|
1329
|
+
if (field && field._f) {
|
|
1330
|
+
field._f.mount = value;
|
|
1736
1331
|
}
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
eventType,
|
|
1744
|
-
}));
|
|
1332
|
+
};
|
|
1333
|
+
if (_actioned.current && shouldKeepFieldArrayValues) {
|
|
1334
|
+
control._subjects.state.next({
|
|
1335
|
+
name,
|
|
1336
|
+
values: cloneObject(control._formValues),
|
|
1337
|
+
});
|
|
1745
1338
|
}
|
|
1746
|
-
|
|
1747
|
-
|
|
1339
|
+
shouldKeepFieldArrayValues
|
|
1340
|
+
? updateMounted(name, false)
|
|
1341
|
+
: control.unregister(name);
|
|
1342
|
+
};
|
|
1343
|
+
}, [name, control, keyName, shouldUnregister, disabled]);
|
|
1344
|
+
return {
|
|
1345
|
+
swap: React.useCallback(swap, [updateValues, name, control, disabled]),
|
|
1346
|
+
move: React.useCallback(move, [updateValues, name, control, disabled]),
|
|
1347
|
+
prepend: React.useCallback(prepend, [
|
|
1348
|
+
updateValues,
|
|
1349
|
+
name,
|
|
1350
|
+
control,
|
|
1351
|
+
disabled,
|
|
1352
|
+
]),
|
|
1353
|
+
append: React.useCallback(append, [updateValues, name, control, disabled]),
|
|
1354
|
+
remove: React.useCallback(remove, [updateValues, name, control, disabled]),
|
|
1355
|
+
insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
|
|
1356
|
+
update: React.useCallback(update, [updateValues, name, control, disabled]),
|
|
1357
|
+
replace: React.useCallback(replace, [
|
|
1358
|
+
updateValues,
|
|
1359
|
+
name,
|
|
1360
|
+
control,
|
|
1361
|
+
disabled,
|
|
1362
|
+
]),
|
|
1363
|
+
fields: React.useMemo(() => fields.map((field, index) => ({
|
|
1364
|
+
...field,
|
|
1365
|
+
...(isBoolean(disabled) ? { disabled } : {}),
|
|
1366
|
+
[keyName]: ids.current[index] || generateId(),
|
|
1367
|
+
})), [fields, keyName, disabled]),
|
|
1748
1368
|
};
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
/**
|
|
1372
|
+
* Component based on `useFieldArray` hook to work with controlled component.
|
|
1373
|
+
*
|
|
1374
|
+
* @example
|
|
1375
|
+
* ```tsx
|
|
1376
|
+
* function App() {
|
|
1377
|
+
* const { control, register } = useForm<FormValues>({
|
|
1378
|
+
* defaultValues: {
|
|
1379
|
+
* test: [
|
|
1380
|
+
* {
|
|
1381
|
+
* value: '',
|
|
1382
|
+
* },
|
|
1383
|
+
* ],
|
|
1384
|
+
* },
|
|
1385
|
+
* });
|
|
1386
|
+
*
|
|
1387
|
+
* return (
|
|
1388
|
+
* <form>
|
|
1389
|
+
* <FieldArray
|
|
1390
|
+
* control={control}
|
|
1391
|
+
* name="test"
|
|
1392
|
+
* render={({ fields }) =>
|
|
1393
|
+
* fields.map((field, index) => (
|
|
1394
|
+
* <input key={field.id} {...register(`test.${index}.value`)} />
|
|
1395
|
+
* ))
|
|
1396
|
+
* }
|
|
1397
|
+
* />
|
|
1398
|
+
* </form>
|
|
1399
|
+
* );
|
|
1400
|
+
* }
|
|
1401
|
+
* ```
|
|
1402
|
+
*/
|
|
1403
|
+
const FieldArray = (props) => props.render(useFieldArray(props));
|
|
1404
|
+
|
|
1405
|
+
const flatten = (obj) => {
|
|
1406
|
+
const output = {};
|
|
1407
|
+
for (const key of Object.keys(obj)) {
|
|
1408
|
+
if (isObjectType(obj[key]) &&
|
|
1409
|
+
obj[key] !== null &&
|
|
1410
|
+
!isDateObject(obj[key])) {
|
|
1411
|
+
const nested = flatten(obj[key]);
|
|
1412
|
+
for (const nestedKey of Object.keys(nested)) {
|
|
1413
|
+
output[`${key}.${nestedKey}`] = nested[nestedKey];
|
|
1414
|
+
}
|
|
1757
1415
|
}
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1416
|
+
else {
|
|
1417
|
+
output[key] = obj[key];
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
return output;
|
|
1421
|
+
};
|
|
1422
|
+
|
|
1423
|
+
function jsonToFormData(json) {
|
|
1424
|
+
const result = new FormData();
|
|
1425
|
+
const flattenFormValues = flatten(json);
|
|
1426
|
+
for (const key in flattenFormValues) {
|
|
1427
|
+
result.append(key, flattenFormValues[key]);
|
|
1428
|
+
}
|
|
1429
|
+
return result;
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
function safeJSONStringify(value) {
|
|
1433
|
+
try {
|
|
1434
|
+
return JSON.stringify(value);
|
|
1435
|
+
}
|
|
1436
|
+
catch (_a) {
|
|
1437
|
+
return '';
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
function noop() { }
|
|
1442
|
+
|
|
1443
|
+
const HookFormContext = React.createContext(null);
|
|
1444
|
+
HookFormContext.displayName = 'HookFormContext';
|
|
1445
|
+
/**
|
|
1446
|
+
* 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}.
|
|
1447
|
+
*
|
|
1448
|
+
* @remarks
|
|
1449
|
+
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
1450
|
+
*
|
|
1451
|
+
* @returns return all useForm methods
|
|
1452
|
+
*
|
|
1453
|
+
* @example
|
|
1454
|
+
* ```tsx
|
|
1455
|
+
* function App() {
|
|
1456
|
+
* const methods = useForm();
|
|
1457
|
+
* const onSubmit = data => console.log(data);
|
|
1458
|
+
*
|
|
1459
|
+
* return (
|
|
1460
|
+
* <FormProvider {...methods} >
|
|
1461
|
+
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
1462
|
+
* <NestedInput />
|
|
1463
|
+
* <input type="submit" />
|
|
1464
|
+
* </form>
|
|
1465
|
+
* </FormProvider>
|
|
1466
|
+
* );
|
|
1467
|
+
* }
|
|
1468
|
+
*
|
|
1469
|
+
* function NestedInput() {
|
|
1470
|
+
* const { register } = useFormContext(); // retrieve all hook methods
|
|
1471
|
+
* return <input {...register("test")} />;
|
|
1472
|
+
* }
|
|
1473
|
+
* ```
|
|
1474
|
+
*/
|
|
1475
|
+
const useFormContext = () => React.useContext(HookFormContext);
|
|
1476
|
+
/**
|
|
1477
|
+
* 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}.
|
|
1478
|
+
*
|
|
1479
|
+
* @remarks
|
|
1480
|
+
* [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
|
|
1481
|
+
*
|
|
1482
|
+
* @param props - all useForm methods
|
|
1483
|
+
*
|
|
1484
|
+
* @example
|
|
1485
|
+
* ```tsx
|
|
1486
|
+
* function App() {
|
|
1487
|
+
* const methods = useForm();
|
|
1488
|
+
* const onSubmit = data => console.log(data);
|
|
1489
|
+
*
|
|
1490
|
+
* return (
|
|
1491
|
+
* <FormProvider {...methods} >
|
|
1492
|
+
* <form onSubmit={methods.handleSubmit(onSubmit)}>
|
|
1493
|
+
* <NestedInput />
|
|
1494
|
+
* <input type="submit" />
|
|
1495
|
+
* </form>
|
|
1496
|
+
* </FormProvider>
|
|
1497
|
+
* );
|
|
1498
|
+
* }
|
|
1499
|
+
*
|
|
1500
|
+
* function NestedInput() {
|
|
1501
|
+
* const { register } = useFormContext(); // retrieve all hook methods
|
|
1502
|
+
* return <input {...register("test")} />;
|
|
1503
|
+
* }
|
|
1504
|
+
* ```
|
|
1505
|
+
*/
|
|
1506
|
+
const FormProvider = ({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
|
|
1507
|
+
const memoizedValue = React.useMemo(() => ({
|
|
1508
|
+
watch,
|
|
1509
|
+
getValues,
|
|
1510
|
+
getFieldState,
|
|
1511
|
+
setError,
|
|
1512
|
+
clearErrors,
|
|
1513
|
+
setValue,
|
|
1514
|
+
setValues,
|
|
1515
|
+
trigger,
|
|
1516
|
+
formState,
|
|
1517
|
+
resetField,
|
|
1518
|
+
reset,
|
|
1519
|
+
resetDefaultValues,
|
|
1520
|
+
handleSubmit,
|
|
1521
|
+
unregister,
|
|
1522
|
+
control,
|
|
1523
|
+
register,
|
|
1524
|
+
setFocus,
|
|
1525
|
+
subscribe,
|
|
1526
|
+
}), [
|
|
1527
|
+
clearErrors,
|
|
1528
|
+
control,
|
|
1529
|
+
formState,
|
|
1530
|
+
getFieldState,
|
|
1531
|
+
getValues,
|
|
1532
|
+
handleSubmit,
|
|
1533
|
+
register,
|
|
1534
|
+
reset,
|
|
1535
|
+
resetDefaultValues,
|
|
1536
|
+
resetField,
|
|
1537
|
+
setError,
|
|
1538
|
+
setFocus,
|
|
1539
|
+
setValue,
|
|
1540
|
+
setValues,
|
|
1541
|
+
subscribe,
|
|
1542
|
+
trigger,
|
|
1543
|
+
unregister,
|
|
1544
|
+
watch,
|
|
1545
|
+
]);
|
|
1546
|
+
return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
|
|
1547
|
+
React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
|
|
1548
|
+
};
|
|
1549
|
+
|
|
1550
|
+
const POST_REQUEST = 'post';
|
|
1551
|
+
function defaultValidateStatus(status) {
|
|
1552
|
+
return status >= 200 && status < 300;
|
|
1553
|
+
}
|
|
1554
|
+
/**
|
|
1555
|
+
* Form component to manage submission.
|
|
1556
|
+
*
|
|
1557
|
+
* @param props - to setup submission detail. {@link FormProps}
|
|
1558
|
+
*
|
|
1559
|
+
* @returns form component or headless render prop.
|
|
1560
|
+
*
|
|
1561
|
+
* @example
|
|
1562
|
+
* ```tsx
|
|
1563
|
+
* function App() {
|
|
1564
|
+
* const { control, formState: { errors } } = useForm();
|
|
1565
|
+
*
|
|
1566
|
+
* return (
|
|
1567
|
+
* <Form action="/api" control={control}>
|
|
1568
|
+
* <input {...register("name")} />
|
|
1569
|
+
* <p>{errors?.root?.server && 'Server error'}</p>
|
|
1570
|
+
* <button>Submit</button>
|
|
1571
|
+
* </Form>
|
|
1572
|
+
* );
|
|
1573
|
+
* }
|
|
1574
|
+
* ```
|
|
1575
|
+
*/
|
|
1576
|
+
function Form(props) {
|
|
1577
|
+
const methods = useFormContext();
|
|
1578
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1579
|
+
const { control = methods.control, onSubmit = noop, children, action, method = POST_REQUEST, headers, encType, onError = noop, render, onSuccess = noop, validateStatus = defaultValidateStatus, ...rest } = props;
|
|
1580
|
+
const handleSubmit = React.useMemo(() => {
|
|
1581
|
+
return control.handleSubmit(async (data, event) => {
|
|
1582
|
+
const formData = jsonToFormData(data);
|
|
1583
|
+
const formDataJson = safeJSONStringify(data);
|
|
1584
|
+
if (onSubmit) {
|
|
1585
|
+
await onSubmit({
|
|
1586
|
+
data,
|
|
1587
|
+
event,
|
|
1588
|
+
method,
|
|
1589
|
+
formData,
|
|
1590
|
+
formDataJson,
|
|
1591
|
+
});
|
|
1592
|
+
}
|
|
1593
|
+
if (isString(action)) {
|
|
1594
|
+
try {
|
|
1595
|
+
const shouldStringifySubmissionData = (headers &&
|
|
1596
|
+
headers['Content-Type'] &&
|
|
1597
|
+
headers['Content-Type'].includes('json')) ||
|
|
1598
|
+
(encType && encType.includes('json'));
|
|
1599
|
+
const response = await fetch(action, {
|
|
1600
|
+
method,
|
|
1601
|
+
headers: {
|
|
1602
|
+
...headers,
|
|
1603
|
+
...(encType &&
|
|
1604
|
+
encType !== 'multipart/form-data' && {
|
|
1605
|
+
'Content-Type': encType,
|
|
1606
|
+
}),
|
|
1607
|
+
},
|
|
1608
|
+
body: shouldStringifySubmissionData ? formDataJson : formData,
|
|
1609
|
+
});
|
|
1610
|
+
if (response && !validateStatus(response.status)) {
|
|
1611
|
+
onError({ response });
|
|
1612
|
+
return { type: String(response.status) };
|
|
1801
1613
|
}
|
|
1802
1614
|
else {
|
|
1803
|
-
|
|
1615
|
+
onSuccess({ response });
|
|
1804
1616
|
}
|
|
1805
1617
|
}
|
|
1806
|
-
|
|
1807
|
-
|
|
1618
|
+
catch (error) {
|
|
1619
|
+
onError({ error });
|
|
1620
|
+
return { type: '' };
|
|
1808
1621
|
}
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
}
|
|
1622
|
+
}
|
|
1623
|
+
if (isFunction(action)) {
|
|
1624
|
+
try {
|
|
1625
|
+
await action(formData);
|
|
1626
|
+
}
|
|
1627
|
+
catch (error) {
|
|
1628
|
+
onError({ error });
|
|
1629
|
+
return { type: '' };
|
|
1817
1630
|
}
|
|
1818
1631
|
}
|
|
1632
|
+
// Return nothing when successful.
|
|
1633
|
+
return;
|
|
1634
|
+
});
|
|
1635
|
+
}, [
|
|
1636
|
+
control,
|
|
1637
|
+
onSubmit,
|
|
1638
|
+
method,
|
|
1639
|
+
action,
|
|
1640
|
+
headers,
|
|
1641
|
+
encType,
|
|
1642
|
+
validateStatus,
|
|
1643
|
+
onError,
|
|
1644
|
+
onSuccess,
|
|
1645
|
+
]);
|
|
1646
|
+
const submit = React.useCallback(async (event) => {
|
|
1647
|
+
const err = await handleSubmit(event);
|
|
1648
|
+
if (err && control) {
|
|
1649
|
+
control._subjects.state.next({ isSubmitSuccessful: false });
|
|
1650
|
+
control.setError('root.server', err);
|
|
1819
1651
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
};
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1652
|
+
}, [handleSubmit, control]);
|
|
1653
|
+
React.useEffect(() => {
|
|
1654
|
+
setMounted(true);
|
|
1655
|
+
}, []);
|
|
1656
|
+
if (render) {
|
|
1657
|
+
return render({ submit });
|
|
1658
|
+
}
|
|
1659
|
+
// React forbids passing `method`/`encType` alongside a function `action`
|
|
1660
|
+
// (a Server-Action-style submission) -- it manages those itself and warns
|
|
1661
|
+
// if they're present, so they're only rendered for string/URL actions.
|
|
1662
|
+
return (React.createElement("form", { noValidate: mounted, action: action, ...(!isFunction(action) && { method, encType }), onSubmit: submit, ...rest }, children));
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
const FormState = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
|
|
1666
|
+
/** @deprecated Use `FormState` instead. Kept as an alias for backward compatibility. */
|
|
1667
|
+
const FormStateSubscribe = FormState;
|
|
1668
|
+
|
|
1669
|
+
var createSubject = () => {
|
|
1670
|
+
let _observers = [];
|
|
1671
|
+
const next = (value) => {
|
|
1672
|
+
for (const observer of _observers) {
|
|
1673
|
+
observer.next && observer.next(value);
|
|
1838
1674
|
}
|
|
1839
1675
|
};
|
|
1840
|
-
const
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1676
|
+
const subscribe = (observer) => {
|
|
1677
|
+
_observers.push(observer);
|
|
1678
|
+
return {
|
|
1679
|
+
unsubscribe: () => {
|
|
1680
|
+
_observers = _observers.filter((o) => o !== observer);
|
|
1681
|
+
},
|
|
1682
|
+
};
|
|
1683
|
+
};
|
|
1684
|
+
const unsubscribe = () => {
|
|
1685
|
+
_observers = [];
|
|
1686
|
+
};
|
|
1687
|
+
return {
|
|
1688
|
+
get observers() {
|
|
1689
|
+
return _observers;
|
|
1690
|
+
},
|
|
1691
|
+
next,
|
|
1692
|
+
subscribe,
|
|
1693
|
+
unsubscribe,
|
|
1694
|
+
};
|
|
1695
|
+
};
|
|
1696
|
+
|
|
1697
|
+
function extractFormValues(fieldsState, formValues) {
|
|
1698
|
+
const values = {};
|
|
1699
|
+
for (const key in fieldsState) {
|
|
1700
|
+
if (fieldsState.hasOwnProperty(key)) {
|
|
1701
|
+
const fieldState = fieldsState[key];
|
|
1702
|
+
const fieldValue = formValues[key];
|
|
1703
|
+
if (fieldState && isObject(fieldState) && fieldValue) {
|
|
1704
|
+
const nestedFieldsState = extractFormValues(fieldState, fieldValue);
|
|
1705
|
+
if (isObject(nestedFieldsState)) {
|
|
1706
|
+
values[key] = nestedFieldsState;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
else if (fieldsState[key]) {
|
|
1710
|
+
values[key] = fieldValue;
|
|
1861
1711
|
}
|
|
1862
1712
|
}
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1713
|
+
}
|
|
1714
|
+
return values;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
|
1718
|
+
|
|
1719
|
+
var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
|
1720
|
+
|
|
1721
|
+
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
|
1722
|
+
|
|
1723
|
+
function isDirtyContainer(value) {
|
|
1724
|
+
return Array.isArray(value) || isObject(value);
|
|
1725
|
+
}
|
|
1726
|
+
function collectDirtyFieldNames(dirtyTree, cachedDirtyFields, prefix = '', names = []) {
|
|
1727
|
+
for (const key in dirtyTree) {
|
|
1728
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
1729
|
+
const value = dirtyTree[key];
|
|
1730
|
+
if (isDirtyContainer(value) &&
|
|
1731
|
+
isDirtyContainer(get(cachedDirtyFields, path))) {
|
|
1732
|
+
collectDirtyFieldNames(value, cachedDirtyFields, path, names);
|
|
1874
1733
|
}
|
|
1875
1734
|
else {
|
|
1876
|
-
|
|
1877
|
-
name: _state.mount ? name : undefined,
|
|
1878
|
-
values: cloneObject(_formValues),
|
|
1879
|
-
});
|
|
1735
|
+
names.push(path);
|
|
1880
1736
|
}
|
|
1881
|
-
}
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
}
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
_subjects.state.next({
|
|
1924
|
-
name,
|
|
1925
|
-
type: event.type,
|
|
1926
|
-
values: cloneObject(_formValues),
|
|
1927
|
-
});
|
|
1928
|
-
if (shouldSkipValidation) {
|
|
1929
|
-
if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
|
|
1930
|
-
if (_options.mode === 'onBlur') {
|
|
1931
|
-
if (isBlurEvent) {
|
|
1932
|
-
_setValid();
|
|
1933
|
-
}
|
|
1934
|
-
}
|
|
1935
|
-
else if (!isBlurEvent) {
|
|
1936
|
-
_setValid();
|
|
1937
|
-
}
|
|
1938
|
-
}
|
|
1939
|
-
return (shouldRender &&
|
|
1940
|
-
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
|
|
1941
|
-
}
|
|
1942
|
-
if (!_options.resolver && props.validate) {
|
|
1943
|
-
await validateForm({
|
|
1944
|
-
name: name,
|
|
1945
|
-
eventType: event.type,
|
|
1946
|
-
});
|
|
1737
|
+
}
|
|
1738
|
+
return names;
|
|
1739
|
+
}
|
|
1740
|
+
|
|
1741
|
+
var objectHasFunction = (data) => {
|
|
1742
|
+
for (const key in data) {
|
|
1743
|
+
if (isFunction(data[key])) {
|
|
1744
|
+
return true;
|
|
1745
|
+
}
|
|
1746
|
+
}
|
|
1747
|
+
return false;
|
|
1748
|
+
};
|
|
1749
|
+
|
|
1750
|
+
function isTraversable(value) {
|
|
1751
|
+
return Array.isArray(value) || (isObject(value) && !objectHasFunction(value));
|
|
1752
|
+
}
|
|
1753
|
+
function isRegisteredLeaf(fieldRef) {
|
|
1754
|
+
return !!(fieldRef && '_f' in fieldRef);
|
|
1755
|
+
}
|
|
1756
|
+
function isEmptyDirtyContainer(value) {
|
|
1757
|
+
return Array.isArray(value)
|
|
1758
|
+
? !value.some((item) => !isUndefined(item))
|
|
1759
|
+
: !Object.keys(value).length;
|
|
1760
|
+
}
|
|
1761
|
+
function clearDirtyField(container, key) {
|
|
1762
|
+
if (Array.isArray(container)) {
|
|
1763
|
+
container[key] = undefined;
|
|
1764
|
+
}
|
|
1765
|
+
else {
|
|
1766
|
+
delete container[key];
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
function markFieldsDirty(data, fields = {}, fieldRefs) {
|
|
1770
|
+
for (const key in data) {
|
|
1771
|
+
const value = data[key];
|
|
1772
|
+
const fieldRef = fieldRefs && fieldRefs[key];
|
|
1773
|
+
if (isTraversable(value) &&
|
|
1774
|
+
(!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
|
|
1775
|
+
fields[key] = Array.isArray(value) ? [] : {};
|
|
1776
|
+
markFieldsDirty(value, fields[key], fieldRef);
|
|
1777
|
+
if (isEmptyDirtyContainer(fields[key])) {
|
|
1778
|
+
clearDirtyField(fields, key);
|
|
1947
1779
|
}
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1780
|
+
}
|
|
1781
|
+
else if (!isUndefined(value)) {
|
|
1782
|
+
fields[key] = true;
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
return fields;
|
|
1786
|
+
}
|
|
1787
|
+
function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
|
|
1788
|
+
if (!dirtyFieldsFromValues) {
|
|
1789
|
+
dirtyFieldsFromValues = markFieldsDirty(formValues, {}, fieldRefs);
|
|
1790
|
+
}
|
|
1791
|
+
for (const key in data) {
|
|
1792
|
+
const value = data[key];
|
|
1793
|
+
const fieldRef = fieldRefs && fieldRefs[key];
|
|
1794
|
+
if (isTraversable(value) &&
|
|
1795
|
+
(!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
|
|
1796
|
+
if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
|
|
1797
|
+
dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}, fieldRef);
|
|
1960
1798
|
}
|
|
1961
1799
|
else {
|
|
1962
|
-
|
|
1963
|
-
error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
|
|
1964
|
-
_updateIsValidating([name]);
|
|
1965
|
-
_updateIsFieldValueUpdated(fieldValue);
|
|
1966
|
-
if (isFieldValueUpdated) {
|
|
1967
|
-
if (error) {
|
|
1968
|
-
isValid = false;
|
|
1969
|
-
}
|
|
1970
|
-
else if (_proxyFormState.isValid ||
|
|
1971
|
-
_proxySubscribeFormState.isValid) {
|
|
1972
|
-
isValid = await executeBuiltInValidation({
|
|
1973
|
-
fields: _fields,
|
|
1974
|
-
onlyCheckValid: true,
|
|
1975
|
-
name: name,
|
|
1976
|
-
eventType: event.type,
|
|
1977
|
-
});
|
|
1978
|
-
}
|
|
1979
|
-
}
|
|
1800
|
+
getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key], fieldRef);
|
|
1980
1801
|
}
|
|
1981
|
-
if (
|
|
1982
|
-
|
|
1983
|
-
(!Array.isArray(field._f.deps) || field._f.deps.length > 0) &&
|
|
1984
|
-
trigger(field._f.deps);
|
|
1985
|
-
shouldRenderByError(name, isValid, error, fieldState);
|
|
1802
|
+
if (isEmptyDirtyContainer(dirtyFieldsFromValues[key])) {
|
|
1803
|
+
clearDirtyField(dirtyFieldsFromValues, key);
|
|
1986
1804
|
}
|
|
1987
1805
|
}
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
if (get(_formState.errors, key) && ref.focus) {
|
|
1991
|
-
ref.focus();
|
|
1992
|
-
return 1;
|
|
1993
|
-
}
|
|
1994
|
-
return;
|
|
1995
|
-
};
|
|
1996
|
-
const trigger = async (name, options = {}) => {
|
|
1997
|
-
let isValid;
|
|
1998
|
-
let validationResult;
|
|
1999
|
-
const fieldNames = convertToArrayPayload(name);
|
|
2000
|
-
if (_options.resolver) {
|
|
2001
|
-
const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
|
|
2002
|
-
isValid = isEmptyObject(errors);
|
|
2003
|
-
validationResult = name
|
|
2004
|
-
? !fieldNames.some((name) => get(errors, name))
|
|
2005
|
-
: isValid;
|
|
2006
|
-
}
|
|
2007
|
-
else if (name) {
|
|
2008
|
-
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
|
|
2009
|
-
const field = get(_fields, fieldName);
|
|
2010
|
-
return await executeBuiltInValidation({
|
|
2011
|
-
fields: field && field._f ? { [fieldName]: field } : field,
|
|
2012
|
-
eventType: EVENTS.TRIGGER,
|
|
2013
|
-
});
|
|
2014
|
-
}))).every(Boolean);
|
|
2015
|
-
!(!validationResult && !_formState.isValid) && _setValid();
|
|
1806
|
+
else if (deepEqual(value, formValues[key])) {
|
|
1807
|
+
clearDirtyField(dirtyFieldsFromValues, key);
|
|
2016
1808
|
}
|
|
2017
1809
|
else {
|
|
2018
|
-
|
|
2019
|
-
fields: _fields,
|
|
2020
|
-
name,
|
|
2021
|
-
eventType: EVENTS.TRIGGER,
|
|
2022
|
-
});
|
|
1810
|
+
dirtyFieldsFromValues[key] = true;
|
|
2023
1811
|
}
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
return
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
1812
|
+
}
|
|
1813
|
+
return dirtyFieldsFromValues;
|
|
1814
|
+
}
|
|
1815
|
+
|
|
1816
|
+
var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
|
|
1817
|
+
? value
|
|
1818
|
+
: valueAsNumber
|
|
1819
|
+
? value === ''
|
|
1820
|
+
? NaN
|
|
1821
|
+
: value
|
|
1822
|
+
? +value
|
|
1823
|
+
: value
|
|
1824
|
+
: valueAsDate && isString(value)
|
|
1825
|
+
? new Date(value)
|
|
1826
|
+
: setValueAs
|
|
1827
|
+
? setValueAs(value)
|
|
1828
|
+
: value;
|
|
1829
|
+
|
|
1830
|
+
function getFieldValue(_f) {
|
|
1831
|
+
const ref = _f.ref;
|
|
1832
|
+
if (isFileInput(ref)) {
|
|
1833
|
+
return ref.files;
|
|
1834
|
+
}
|
|
1835
|
+
if (isRadioInput(ref)) {
|
|
1836
|
+
return getRadioValue(_f.refs).value;
|
|
1837
|
+
}
|
|
1838
|
+
if (isMultipleSelect(ref)) {
|
|
1839
|
+
return [...ref.selectedOptions].map(({ value }) => value);
|
|
1840
|
+
}
|
|
1841
|
+
if (isCheckBoxInput(ref)) {
|
|
1842
|
+
return getCheckboxValue(_f.refs).value;
|
|
1843
|
+
}
|
|
1844
|
+
return getFieldValueAs(ref.value, _f);
|
|
1845
|
+
}
|
|
1846
|
+
|
|
1847
|
+
var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
|
|
1848
|
+
const fields = {};
|
|
1849
|
+
for (const name of fieldsNames) {
|
|
1850
|
+
const field = get(_fields, name);
|
|
1851
|
+
field && set(fields, name, field._f);
|
|
1852
|
+
}
|
|
1853
|
+
return {
|
|
1854
|
+
criteriaMode,
|
|
1855
|
+
names: [...fieldsNames],
|
|
1856
|
+
fields,
|
|
1857
|
+
shouldUseNativeValidation,
|
|
2050
1858
|
};
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
}
|
|
1859
|
+
};
|
|
1860
|
+
|
|
1861
|
+
var getRuleValue = (rule) => isUndefined(rule)
|
|
1862
|
+
? rule
|
|
1863
|
+
: isRegex(rule)
|
|
1864
|
+
? rule.source
|
|
1865
|
+
: isObject(rule)
|
|
1866
|
+
? isRegex(rule.value)
|
|
1867
|
+
? rule.value.source
|
|
1868
|
+
: rule.value
|
|
1869
|
+
: rule;
|
|
1870
|
+
|
|
1871
|
+
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
1872
|
+
var hasPromiseValidation = (fieldReference) => {
|
|
1873
|
+
if (!fieldReference || !fieldReference.validate)
|
|
1874
|
+
return false;
|
|
1875
|
+
if (isFunction(fieldReference.validate)) {
|
|
1876
|
+
return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
|
|
1877
|
+
}
|
|
1878
|
+
if (isObject(fieldReference.validate)) {
|
|
1879
|
+
for (const key in fieldReference.validate) {
|
|
1880
|
+
if (fieldReference.validate[key].constructor
|
|
1881
|
+
.name === ASYNC_FUNCTION) {
|
|
1882
|
+
return true;
|
|
1883
|
+
}
|
|
2076
1884
|
}
|
|
2077
|
-
}
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
1885
|
+
}
|
|
1886
|
+
return false;
|
|
1887
|
+
};
|
|
1888
|
+
|
|
1889
|
+
var hasValidation = (options) => options.mount &&
|
|
1890
|
+
(options.required ||
|
|
1891
|
+
options.min ||
|
|
1892
|
+
options.max ||
|
|
1893
|
+
options.maxLength ||
|
|
1894
|
+
options.minLength ||
|
|
1895
|
+
options.pattern ||
|
|
1896
|
+
options.validate);
|
|
1897
|
+
|
|
1898
|
+
function schemaErrorLookup(errors, _fields, name) {
|
|
1899
|
+
const error = get(errors, name);
|
|
1900
|
+
if (error || isKey(name)) {
|
|
1901
|
+
return {
|
|
1902
|
+
error,
|
|
2089
1903
|
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
1904
|
};
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
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);
|
|
1905
|
+
}
|
|
1906
|
+
const names = name.split('.');
|
|
1907
|
+
while (names.length) {
|
|
1908
|
+
const fieldName = names.join('.');
|
|
1909
|
+
const field = get(_fields, fieldName);
|
|
1910
|
+
const foundError = get(errors, fieldName);
|
|
1911
|
+
if (field && !Array.isArray(field) && name !== fieldName) {
|
|
1912
|
+
return { name };
|
|
2144
1913
|
}
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
|
|
2152
|
-
|
|
1914
|
+
if (foundError && foundError.type) {
|
|
1915
|
+
return {
|
|
1916
|
+
name: fieldName,
|
|
1917
|
+
error: foundError,
|
|
1918
|
+
};
|
|
1919
|
+
}
|
|
1920
|
+
if (foundError && foundError.root && foundError.root.type) {
|
|
1921
|
+
return {
|
|
1922
|
+
name: `${fieldName}.root`,
|
|
1923
|
+
error: foundError.root,
|
|
1924
|
+
};
|
|
1925
|
+
}
|
|
1926
|
+
names.pop();
|
|
1927
|
+
}
|
|
1928
|
+
return {
|
|
1929
|
+
name,
|
|
2153
1930
|
};
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
1931
|
+
}
|
|
1932
|
+
|
|
1933
|
+
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
1934
|
+
updateFormState(formStateData);
|
|
1935
|
+
const keys = Object.keys(formStateData).filter((key) => key !== 'name');
|
|
1936
|
+
return (!keys.length ||
|
|
1937
|
+
(isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
|
|
1938
|
+
keys.find((key) => _proxyFormState[key] ===
|
|
1939
|
+
(!isRoot || VALIDATION_MODE.all)));
|
|
1940
|
+
};
|
|
1941
|
+
|
|
1942
|
+
var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
|
1943
|
+
!signalName ||
|
|
1944
|
+
name === signalName ||
|
|
1945
|
+
convertToArrayPayload(name).some((currentName) => currentName &&
|
|
1946
|
+
(exact
|
|
1947
|
+
? currentName === signalName || currentName.startsWith(signalName + '.')
|
|
1948
|
+
: currentName.startsWith(signalName) ||
|
|
1949
|
+
signalName.startsWith(currentName)));
|
|
1950
|
+
|
|
1951
|
+
var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
|
|
1952
|
+
if (mode.isOnAll) {
|
|
1953
|
+
return false;
|
|
1954
|
+
}
|
|
1955
|
+
else if (!isSubmitted && mode.isOnTouch) {
|
|
1956
|
+
return !(isTouched || isBlurEvent);
|
|
1957
|
+
}
|
|
1958
|
+
else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
|
|
1959
|
+
return !isBlurEvent;
|
|
1960
|
+
}
|
|
1961
|
+
else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
|
|
1962
|
+
return isBlurEvent;
|
|
1963
|
+
}
|
|
1964
|
+
return true;
|
|
1965
|
+
};
|
|
1966
|
+
|
|
1967
|
+
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
|
1968
|
+
|
|
1969
|
+
const defaultOptions = {
|
|
1970
|
+
mode: VALIDATION_MODE.onSubmit,
|
|
1971
|
+
reValidateMode: VALIDATION_MODE.onChange,
|
|
1972
|
+
shouldFocusError: true,
|
|
1973
|
+
};
|
|
1974
|
+
const FORM_ERROR_TYPE = 'form';
|
|
1975
|
+
const updateDirtyFields = (dirtyFields, nextDirtyFields) => {
|
|
1976
|
+
for (const key in dirtyFields) {
|
|
1977
|
+
if (!(key in nextDirtyFields)) {
|
|
1978
|
+
delete dirtyFields[key];
|
|
2163
1979
|
}
|
|
1980
|
+
}
|
|
1981
|
+
Object.assign(dirtyFields, nextDirtyFields);
|
|
1982
|
+
};
|
|
1983
|
+
const DEFAULT_FORM_STATE = {
|
|
1984
|
+
submitCount: 0,
|
|
1985
|
+
isDirty: false,
|
|
1986
|
+
isReady: false,
|
|
1987
|
+
isValidating: false,
|
|
1988
|
+
isSubmitted: false,
|
|
1989
|
+
isSubmitting: false,
|
|
1990
|
+
isSubmitSuccessful: false,
|
|
1991
|
+
isValid: false,
|
|
1992
|
+
touchedFields: {},
|
|
1993
|
+
dirtyFields: {},
|
|
1994
|
+
validatingFields: {},
|
|
1995
|
+
};
|
|
1996
|
+
function createFormControl(props = {}) {
|
|
1997
|
+
let _options = {
|
|
1998
|
+
...defaultOptions,
|
|
1999
|
+
...props,
|
|
2164
2000
|
};
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
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
|
-
};
|
|
2001
|
+
let _formState = {
|
|
2002
|
+
...cloneObject(DEFAULT_FORM_STATE),
|
|
2003
|
+
isLoading: isFunction(_options.defaultValues),
|
|
2004
|
+
errors: _options.errors || {},
|
|
2005
|
+
disabled: _options.disabled || false,
|
|
2253
2006
|
};
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
});
|
|
2267
|
-
}
|
|
2268
|
-
}
|
|
2269
|
-
}, 0, false);
|
|
2270
|
-
}
|
|
2007
|
+
let _fields = {};
|
|
2008
|
+
let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
|
|
2009
|
+
? cloneObject(_options.defaultValues || _options.values) || {}
|
|
2010
|
+
: {};
|
|
2011
|
+
let _formValues = _options.shouldUnregister
|
|
2012
|
+
? {}
|
|
2013
|
+
: cloneObject(_defaultValues);
|
|
2014
|
+
let _state = {
|
|
2015
|
+
action: false,
|
|
2016
|
+
mount: false,
|
|
2017
|
+
watch: false,
|
|
2018
|
+
keepIsValid: false,
|
|
2271
2019
|
};
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2020
|
+
let _names = {
|
|
2021
|
+
mount: new Set(),
|
|
2022
|
+
disabled: new Set(),
|
|
2023
|
+
unMount: new Set(),
|
|
2024
|
+
array: new Set(),
|
|
2025
|
+
watch: new Set(),
|
|
2026
|
+
registerName: new Set(),
|
|
2027
|
+
};
|
|
2028
|
+
const delayErrorCallbacks = {};
|
|
2029
|
+
const timers = {};
|
|
2030
|
+
let _valuesSubscriberCount = 0;
|
|
2031
|
+
let _validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
2032
|
+
let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
2033
|
+
const defaultProxyFormState = {
|
|
2034
|
+
isDirty: false,
|
|
2035
|
+
dirtyFields: false,
|
|
2036
|
+
validatingFields: false,
|
|
2037
|
+
touchedFields: false,
|
|
2038
|
+
isValidating: false,
|
|
2039
|
+
isValid: false,
|
|
2040
|
+
errors: false,
|
|
2041
|
+
};
|
|
2042
|
+
const _proxyFormState = {
|
|
2043
|
+
...defaultProxyFormState,
|
|
2044
|
+
};
|
|
2045
|
+
let _proxySubscribeFormState = {
|
|
2046
|
+
..._proxyFormState,
|
|
2047
|
+
};
|
|
2048
|
+
const _subjects = {
|
|
2049
|
+
array: createSubject(),
|
|
2050
|
+
state: createSubject(),
|
|
2051
|
+
};
|
|
2052
|
+
let _setValidCallId = 0;
|
|
2053
|
+
const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
|
|
2054
|
+
const debounce = (name, callback) => (wait) => {
|
|
2055
|
+
clearTimeout(timers[name]);
|
|
2056
|
+
timers[name] = setTimeout(callback, wait);
|
|
2057
|
+
};
|
|
2058
|
+
const _setValid = async (shouldUpdateValid) => {
|
|
2059
|
+
if (_state.keepIsValid) {
|
|
2060
|
+
return;
|
|
2294
2061
|
}
|
|
2295
|
-
if (
|
|
2296
|
-
|
|
2297
|
-
|
|
2062
|
+
if (!_options.disabled &&
|
|
2063
|
+
(_proxyFormState.isValid ||
|
|
2064
|
+
_proxySubscribeFormState.isValid ||
|
|
2065
|
+
shouldUpdateValid)) {
|
|
2066
|
+
const callId = ++_setValidCallId;
|
|
2067
|
+
let isValid;
|
|
2068
|
+
if (_options.resolver) {
|
|
2069
|
+
isValid = isEmptyObject((await _runSchema()).errors);
|
|
2070
|
+
callId === _setValidCallId && _updateIsValidating();
|
|
2071
|
+
}
|
|
2072
|
+
else {
|
|
2073
|
+
isValid = await executeBuiltInValidation({
|
|
2074
|
+
fields: _fields,
|
|
2075
|
+
onlyCheckValid: true,
|
|
2076
|
+
eventType: EVENTS.VALID,
|
|
2077
|
+
});
|
|
2078
|
+
}
|
|
2079
|
+
if (callId === _setValidCallId && isValid !== _formState.isValid) {
|
|
2080
|
+
_subjects.state.next({
|
|
2081
|
+
isValid,
|
|
2082
|
+
});
|
|
2298
2083
|
}
|
|
2299
2084
|
}
|
|
2300
|
-
|
|
2301
|
-
|
|
2085
|
+
};
|
|
2086
|
+
const _updateIsValidating = (names, isValidating) => {
|
|
2087
|
+
if (!_options.disabled &&
|
|
2088
|
+
(_proxyFormState.isValidating ||
|
|
2089
|
+
_proxyFormState.validatingFields ||
|
|
2090
|
+
_proxySubscribeFormState.isValidating ||
|
|
2091
|
+
_proxySubscribeFormState.validatingFields)) {
|
|
2092
|
+
(names || Array.from(_names.mount)).forEach((name) => {
|
|
2093
|
+
if (name) {
|
|
2094
|
+
isValidating
|
|
2095
|
+
? set(_formState.validatingFields, name, isValidating)
|
|
2096
|
+
: unset(_formState.validatingFields, name);
|
|
2097
|
+
}
|
|
2098
|
+
});
|
|
2302
2099
|
_subjects.state.next({
|
|
2303
|
-
|
|
2100
|
+
validatingFields: _formState.validatingFields,
|
|
2101
|
+
isValidating: !isEmptyObject(_formState.validatingFields),
|
|
2304
2102
|
});
|
|
2305
|
-
|
|
2306
|
-
|
|
2103
|
+
}
|
|
2104
|
+
};
|
|
2105
|
+
const _updateDirtyFields = () => {
|
|
2106
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
2107
|
+
};
|
|
2108
|
+
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
|
2109
|
+
if (args && method && !_options.disabled) {
|
|
2110
|
+
_state.action = true;
|
|
2111
|
+
if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
|
|
2112
|
+
const fieldValues = method(get(_fields, name), args.argA, args.argB);
|
|
2113
|
+
shouldSetValues && set(_fields, name, fieldValues);
|
|
2307
2114
|
}
|
|
2308
|
-
|
|
2309
|
-
|
|
2115
|
+
if (shouldUpdateFieldsAndState &&
|
|
2116
|
+
Array.isArray(get(_formState.errors, name))) {
|
|
2117
|
+
const errors = method(get(_formState.errors, name), args.argA, args.argB);
|
|
2118
|
+
shouldSetValues && set(_formState.errors, name, errors);
|
|
2119
|
+
unsetEmptyArray(_formState.errors, name);
|
|
2120
|
+
}
|
|
2121
|
+
if ((_proxyFormState.touchedFields ||
|
|
2122
|
+
_proxySubscribeFormState.touchedFields) &&
|
|
2123
|
+
shouldUpdateFieldsAndState &&
|
|
2124
|
+
Array.isArray(get(_formState.touchedFields, name))) {
|
|
2125
|
+
const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
|
|
2126
|
+
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
|
2127
|
+
}
|
|
2128
|
+
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
|
2129
|
+
_updateDirtyFields();
|
|
2310
2130
|
}
|
|
2131
|
+
_subjects.state.next({
|
|
2132
|
+
name,
|
|
2133
|
+
isDirty: _getDirty(name, values),
|
|
2134
|
+
dirtyFields: _formState.dirtyFields,
|
|
2135
|
+
errors: _formState.errors,
|
|
2136
|
+
isValid: _formState.isValid,
|
|
2137
|
+
});
|
|
2311
2138
|
}
|
|
2312
2139
|
else {
|
|
2313
|
-
|
|
2314
|
-
await onInvalid({ ..._formState.errors }, e);
|
|
2315
|
-
}
|
|
2316
|
-
_focusError();
|
|
2317
|
-
setTimeout(_focusError);
|
|
2140
|
+
set(_formValues, name, values);
|
|
2318
2141
|
}
|
|
2142
|
+
};
|
|
2143
|
+
const updateErrors = (name, error) => {
|
|
2144
|
+
set(_formState.errors, name, error);
|
|
2145
|
+
_formState.errors = { ..._formState.errors };
|
|
2319
2146
|
_subjects.state.next({
|
|
2320
|
-
isSubmitted: true,
|
|
2321
|
-
isSubmitting: false,
|
|
2322
|
-
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
|
2323
|
-
submitCount: _formState.submitCount + 1,
|
|
2324
2147
|
errors: _formState.errors,
|
|
2325
2148
|
});
|
|
2326
|
-
if (onValidError) {
|
|
2327
|
-
throw onValidError;
|
|
2328
|
-
}
|
|
2329
2149
|
};
|
|
2330
|
-
const
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
unset(_formState.errors, name);
|
|
2350
|
-
_proxyFormState.isValid && _setValid();
|
|
2150
|
+
const _setErrors = (errors) => {
|
|
2151
|
+
_formState.errors = errors;
|
|
2152
|
+
_subjects.state.next({
|
|
2153
|
+
errors: _formState.errors,
|
|
2154
|
+
isValid: false,
|
|
2155
|
+
});
|
|
2156
|
+
};
|
|
2157
|
+
const hasExplicitNullIntermediate = (name) => {
|
|
2158
|
+
const segments = isKey(name) ? [name] : stringToPath(name);
|
|
2159
|
+
let formValues = _formValues;
|
|
2160
|
+
let defaultValues = _defaultValues;
|
|
2161
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
2162
|
+
const key = segments[i];
|
|
2163
|
+
formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
|
|
2164
|
+
defaultValues = isNullOrUndefined(defaultValues)
|
|
2165
|
+
? defaultValues
|
|
2166
|
+
: defaultValues[key];
|
|
2167
|
+
if (formValues === null && defaultValues !== null) {
|
|
2168
|
+
return true;
|
|
2351
2169
|
}
|
|
2352
|
-
_subjects.state.next({ ..._formState });
|
|
2353
2170
|
}
|
|
2171
|
+
return false;
|
|
2354
2172
|
};
|
|
2355
|
-
const
|
|
2356
|
-
const
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
setValue(fieldName, newValue);
|
|
2173
|
+
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
|
|
2174
|
+
const field = get(_fields, name);
|
|
2175
|
+
if (field) {
|
|
2176
|
+
if (hasExplicitNullIntermediate(name)) {
|
|
2177
|
+
return;
|
|
2178
|
+
}
|
|
2179
|
+
const wasUnsetInFormValues = isUndefined(get(_formValues, name));
|
|
2180
|
+
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
|
|
2181
|
+
isUndefined(defaultValue) ||
|
|
2182
|
+
(ref && ref.defaultChecked) ||
|
|
2183
|
+
shouldSkipSetValueAs
|
|
2184
|
+
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
|
2185
|
+
: setFieldValue(name, defaultValue);
|
|
2186
|
+
if (_state.mount && !_state.action) {
|
|
2187
|
+
_setValid();
|
|
2188
|
+
if (wasUnsetInFormValues &&
|
|
2189
|
+
_formState.isDirty &&
|
|
2190
|
+
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
|
|
2191
|
+
const isDirty = _getDirty();
|
|
2192
|
+
if (!isDirty) {
|
|
2193
|
+
_formState.isDirty = false;
|
|
2194
|
+
_subjects.state.next({ ..._formState });
|
|
2378
2195
|
}
|
|
2379
2196
|
}
|
|
2197
|
+
if (props.shouldUnregister &&
|
|
2198
|
+
wasUnsetInFormValues &&
|
|
2199
|
+
!isUndefined(get(_formValues, name)) &&
|
|
2200
|
+
isWatched(name, _names)) {
|
|
2201
|
+
_state.watch = true;
|
|
2202
|
+
}
|
|
2380
2203
|
}
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2204
|
+
}
|
|
2205
|
+
};
|
|
2206
|
+
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
|
2207
|
+
let shouldUpdateField = false;
|
|
2208
|
+
let isPreviousDirty = false;
|
|
2209
|
+
const output = {
|
|
2210
|
+
name,
|
|
2211
|
+
};
|
|
2212
|
+
// an explicit programmatic update (e.g. setValue with shouldDirty: true)
|
|
2213
|
+
// opts into dirty tracking even when the form is disabled
|
|
2214
|
+
if (!_options.disabled || shouldDirty === true) {
|
|
2215
|
+
if (!isBlurEvent || shouldDirty) {
|
|
2216
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
2217
|
+
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
2218
|
+
isPreviousDirty = _formState.isDirty;
|
|
2219
|
+
_formState.isDirty = output.isDirty =
|
|
2220
|
+
!isCurrentFieldPristine || _getDirty();
|
|
2221
|
+
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
2398
2222
|
}
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
}
|
|
2223
|
+
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
2224
|
+
if (isCurrentFieldPristine !== _formState.isDirty) {
|
|
2225
|
+
updateDirtyFields(_formState.dirtyFields, getDirtyFields(_defaultValues, _formValues, undefined, _fields));
|
|
2403
2226
|
}
|
|
2404
2227
|
else {
|
|
2405
|
-
|
|
2228
|
+
isCurrentFieldPristine
|
|
2229
|
+
? unset(_formState.dirtyFields, name)
|
|
2230
|
+
: set(_formState.dirtyFields, name, true);
|
|
2231
|
+
}
|
|
2232
|
+
output.dirtyFields = _formState.dirtyFields;
|
|
2233
|
+
shouldUpdateField =
|
|
2234
|
+
shouldUpdateField ||
|
|
2235
|
+
((_proxyFormState.dirtyFields ||
|
|
2236
|
+
_proxySubscribeFormState.dirtyFields) &&
|
|
2237
|
+
isPreviousDirty !== !isCurrentFieldPristine);
|
|
2238
|
+
}
|
|
2239
|
+
if (isBlurEvent) {
|
|
2240
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
|
2241
|
+
if (!isPreviousFieldTouched) {
|
|
2242
|
+
set(_formState.touchedFields, name, isBlurEvent);
|
|
2243
|
+
output.touchedFields = _formState.touchedFields;
|
|
2244
|
+
shouldUpdateField =
|
|
2245
|
+
shouldUpdateField ||
|
|
2246
|
+
((_proxyFormState.touchedFields ||
|
|
2247
|
+
_proxySubscribeFormState.touchedFields) &&
|
|
2248
|
+
isPreviousFieldTouched !== isBlurEvent);
|
|
2406
2249
|
}
|
|
2407
2250
|
}
|
|
2408
|
-
|
|
2409
|
-
? keepStateOptions.keepDefaultValues
|
|
2410
|
-
? cloneObject(_defaultValues)
|
|
2411
|
-
: {}
|
|
2412
|
-
: cloneObject(values);
|
|
2413
|
-
_subjects.array.next({
|
|
2414
|
-
values: { ...values },
|
|
2415
|
-
});
|
|
2416
|
-
_subjects.state.next({
|
|
2417
|
-
values: { ...values },
|
|
2418
|
-
});
|
|
2251
|
+
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
|
2419
2252
|
}
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2253
|
+
return shouldUpdateField ? output : {};
|
|
2254
|
+
};
|
|
2255
|
+
const shouldRenderByError = (name, isValid, error, fieldState) => {
|
|
2256
|
+
const previousFieldError = get(_formState.errors, name);
|
|
2257
|
+
const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
2258
|
+
isBoolean(isValid) &&
|
|
2259
|
+
_formState.isValid !== isValid;
|
|
2260
|
+
if (_options.delayError && error) {
|
|
2261
|
+
delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
|
|
2262
|
+
delayErrorCallbacks[name](_options.delayError);
|
|
2263
|
+
}
|
|
2264
|
+
else {
|
|
2265
|
+
clearTimeout(timers[name]);
|
|
2266
|
+
delete delayErrorCallbacks[name];
|
|
2267
|
+
error
|
|
2268
|
+
? set(_formState.errors, name, error)
|
|
2269
|
+
: unset(_formState.errors, name);
|
|
2270
|
+
_formState.errors = { ..._formState.errors };
|
|
2271
|
+
}
|
|
2272
|
+
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
|
2273
|
+
!isEmptyObject(fieldState) ||
|
|
2274
|
+
shouldUpdateValid) {
|
|
2275
|
+
const updatedFormState = {
|
|
2276
|
+
...fieldState,
|
|
2277
|
+
...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
|
|
2278
|
+
errors: _formState.errors,
|
|
2279
|
+
name,
|
|
2280
|
+
};
|
|
2281
|
+
_formState = {
|
|
2282
|
+
..._formState,
|
|
2283
|
+
...updatedFormState,
|
|
2284
|
+
};
|
|
2285
|
+
_subjects.state.next(updatedFormState);
|
|
2443
2286
|
}
|
|
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,
|
|
2477
|
-
});
|
|
2478
2287
|
};
|
|
2479
|
-
const
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2483
|
-
|
|
2484
|
-
const
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
fieldRef.select();
|
|
2497
|
-
});
|
|
2288
|
+
const _runSchema = async (name) => {
|
|
2289
|
+
_updateIsValidating(name, true);
|
|
2290
|
+
return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
|
|
2291
|
+
};
|
|
2292
|
+
const executeSchemaAndUpdateState = async (names) => {
|
|
2293
|
+
const { errors } = await _runSchema(names);
|
|
2294
|
+
_updateIsValidating(names);
|
|
2295
|
+
if (names) {
|
|
2296
|
+
for (const name of names) {
|
|
2297
|
+
const error = get(errors, name);
|
|
2298
|
+
error
|
|
2299
|
+
? _names.array.has(name) &&
|
|
2300
|
+
isObject(error) &&
|
|
2301
|
+
!Object.keys(error).some((key) => !Number.isNaN(Number(key)))
|
|
2302
|
+
? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
|
|
2303
|
+
: set(_formState.errors, name, error)
|
|
2304
|
+
: unset(_formState.errors, name);
|
|
2498
2305
|
}
|
|
2306
|
+
_formState.errors = { ..._formState.errors };
|
|
2499
2307
|
}
|
|
2308
|
+
else {
|
|
2309
|
+
_formState.errors = errors;
|
|
2310
|
+
}
|
|
2311
|
+
return errors;
|
|
2500
2312
|
};
|
|
2501
|
-
const
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
_options.defaultValues().then((values) => {
|
|
2509
|
-
reset(values, _options.resetOptions);
|
|
2510
|
-
_subjects.state.next({
|
|
2511
|
-
isLoading: false,
|
|
2313
|
+
const validateForm = async ({ name, eventType, }) => {
|
|
2314
|
+
if (props.validate) {
|
|
2315
|
+
const result = await props.validate({
|
|
2316
|
+
formValues: _formValues,
|
|
2317
|
+
formState: _formState,
|
|
2318
|
+
name,
|
|
2319
|
+
eventType,
|
|
2512
2320
|
});
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
}
|
|
2547
|
-
|
|
2548
|
-
|
|
2549
|
-
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
}
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2321
|
+
if (isObject(result)) {
|
|
2322
|
+
for (const key in result) {
|
|
2323
|
+
const error = result[key];
|
|
2324
|
+
if (error) {
|
|
2325
|
+
setError(`${FORM_ERROR_TYPE}.${key}`, {
|
|
2326
|
+
message: isString(error.message) ? error.message : '',
|
|
2327
|
+
type: error.type || INPUT_VALIDATION_RULES.validate,
|
|
2328
|
+
});
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
else if (isString(result) || !result) {
|
|
2333
|
+
setError(FORM_ERROR_TYPE, {
|
|
2334
|
+
message: result || '',
|
|
2335
|
+
type: INPUT_VALIDATION_RULES.validate,
|
|
2336
|
+
});
|
|
2337
|
+
}
|
|
2338
|
+
else {
|
|
2339
|
+
clearErrors(FORM_ERROR_TYPE);
|
|
2340
|
+
}
|
|
2341
|
+
return result;
|
|
2342
|
+
}
|
|
2343
|
+
return true;
|
|
2344
|
+
};
|
|
2345
|
+
const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
|
|
2346
|
+
valid: true,
|
|
2347
|
+
runRootValidation: false,
|
|
2348
|
+
}, }) => {
|
|
2349
|
+
if (props.validate) {
|
|
2350
|
+
context.runRootValidation = true;
|
|
2351
|
+
const result = await validateForm({
|
|
2352
|
+
name,
|
|
2353
|
+
eventType,
|
|
2354
|
+
});
|
|
2355
|
+
if (!result) {
|
|
2356
|
+
context.valid = false;
|
|
2357
|
+
if (onlyCheckValid) {
|
|
2358
|
+
return context.valid;
|
|
2359
|
+
}
|
|
2360
|
+
}
|
|
2361
|
+
}
|
|
2362
|
+
for (const name in fields) {
|
|
2363
|
+
const field = fields[name];
|
|
2364
|
+
if (field) {
|
|
2365
|
+
const { _f, ...fieldValue } = field;
|
|
2366
|
+
if (_f) {
|
|
2367
|
+
const isFieldArrayRoot = _names.array.has(_f.name);
|
|
2368
|
+
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
|
|
2369
|
+
const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
|
|
2370
|
+
_proxyFormState.isValidating ||
|
|
2371
|
+
_proxySubscribeFormState.validatingFields ||
|
|
2372
|
+
_proxySubscribeFormState.isValidating;
|
|
2373
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
2374
|
+
_updateIsValidating([_f.name], true);
|
|
2375
|
+
}
|
|
2376
|
+
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
|
|
2377
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
2378
|
+
_updateIsValidating([_f.name]);
|
|
2379
|
+
}
|
|
2380
|
+
if (fieldError[_f.name]) {
|
|
2381
|
+
context.valid = false;
|
|
2382
|
+
if (onlyCheckValid) {
|
|
2383
|
+
break;
|
|
2384
|
+
}
|
|
2385
|
+
}
|
|
2386
|
+
!onlyCheckValid &&
|
|
2387
|
+
(get(fieldError, _f.name)
|
|
2388
|
+
? isFieldArrayRoot
|
|
2389
|
+
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
|
2390
|
+
: set(_formState.errors, _f.name, fieldError[_f.name])
|
|
2391
|
+
: unset(_formState.errors, _f.name));
|
|
2392
|
+
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
|
|
2393
|
+
break;
|
|
2394
|
+
}
|
|
2395
|
+
}
|
|
2396
|
+
!isEmptyObject(fieldValue) &&
|
|
2397
|
+
(await executeBuiltInValidation({
|
|
2398
|
+
context,
|
|
2399
|
+
onlyCheckValid,
|
|
2400
|
+
fields: fieldValue,
|
|
2401
|
+
name: name,
|
|
2402
|
+
eventType,
|
|
2403
|
+
}));
|
|
2404
|
+
}
|
|
2405
|
+
}
|
|
2406
|
+
return context.valid;
|
|
2407
|
+
};
|
|
2408
|
+
const _removeUnmounted = () => {
|
|
2409
|
+
for (const name of _names.unMount) {
|
|
2410
|
+
const field = get(_fields, name);
|
|
2411
|
+
field &&
|
|
2412
|
+
(field._f.refs
|
|
2413
|
+
? field._f.refs.every((ref) => !live(ref))
|
|
2414
|
+
: !live(field._f.ref)) &&
|
|
2415
|
+
unregister(name);
|
|
2416
|
+
}
|
|
2417
|
+
_names.unMount = new Set();
|
|
2418
|
+
};
|
|
2419
|
+
const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
|
|
2420
|
+
!deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
|
|
2421
|
+
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
|
2422
|
+
...(_state.mount
|
|
2423
|
+
? _formValues
|
|
2424
|
+
: isUndefined(defaultValue)
|
|
2425
|
+
? _defaultValues
|
|
2426
|
+
: isString(names)
|
|
2427
|
+
? { [names]: defaultValue }
|
|
2428
|
+
: defaultValue),
|
|
2429
|
+
}, isGlobal, defaultValue);
|
|
2430
|
+
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
|
2431
|
+
const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
|
|
2432
|
+
const field = get(_fields, name);
|
|
2433
|
+
let fieldValue = value;
|
|
2434
|
+
if (field) {
|
|
2435
|
+
const fieldReference = field._f;
|
|
2436
|
+
if (fieldReference) {
|
|
2437
|
+
!fieldReference.disabled &&
|
|
2438
|
+
set(_formValues, name, getFieldValueAs(value, fieldReference));
|
|
2439
|
+
fieldValue =
|
|
2440
|
+
isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
|
|
2441
|
+
? ''
|
|
2442
|
+
: value;
|
|
2443
|
+
if (isMultipleSelect(fieldReference.ref)) {
|
|
2444
|
+
[...fieldReference.ref.options].forEach((optionRef) => (optionRef.selected = fieldValue.includes(optionRef.value)));
|
|
2445
|
+
}
|
|
2446
|
+
else if (fieldReference.refs) {
|
|
2447
|
+
if (isCheckBoxInput(fieldReference.ref)) {
|
|
2448
|
+
fieldReference.refs.forEach((checkboxRef) => {
|
|
2449
|
+
if (!checkboxRef.defaultChecked || !checkboxRef.disabled) {
|
|
2450
|
+
if (Array.isArray(fieldValue)) {
|
|
2451
|
+
checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value);
|
|
2452
|
+
}
|
|
2453
|
+
else {
|
|
2454
|
+
checkboxRef.checked =
|
|
2455
|
+
fieldValue === checkboxRef.value || !!fieldValue;
|
|
2456
|
+
}
|
|
2457
|
+
}
|
|
2458
|
+
});
|
|
2459
|
+
}
|
|
2460
|
+
else {
|
|
2461
|
+
fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
|
|
2462
|
+
}
|
|
2463
|
+
}
|
|
2464
|
+
else if (isFileInput(fieldReference.ref)) {
|
|
2465
|
+
fieldReference.ref.value = '';
|
|
2466
|
+
}
|
|
2467
|
+
else {
|
|
2468
|
+
fieldReference.ref.value = fieldValue;
|
|
2469
|
+
if (!fieldReference.ref.type && !skipRender) {
|
|
2470
|
+
_subjects.state.next({
|
|
2471
|
+
name,
|
|
2472
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
2473
|
+
});
|
|
2474
|
+
}
|
|
2475
|
+
}
|
|
2476
|
+
}
|
|
2477
|
+
}
|
|
2478
|
+
(options.shouldDirty || options.shouldTouch) &&
|
|
2479
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
|
|
2480
|
+
options.shouldValidate &&
|
|
2481
|
+
trigger(name, {
|
|
2482
|
+
delayError: options.delayError,
|
|
2483
|
+
});
|
|
2484
|
+
};
|
|
2485
|
+
const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
|
|
2486
|
+
if (_names.array.has(name)) {
|
|
2487
|
+
_subjects.array.next({
|
|
2488
|
+
name,
|
|
2489
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
2490
|
+
});
|
|
2491
|
+
}
|
|
2492
|
+
for (const fieldKey in value) {
|
|
2493
|
+
if (!value.hasOwnProperty(fieldKey)) {
|
|
2494
|
+
return;
|
|
2495
|
+
}
|
|
2496
|
+
const fieldValue = value[fieldKey];
|
|
2497
|
+
const fieldName = name + '.' + fieldKey;
|
|
2498
|
+
const field = get(_fields, fieldName);
|
|
2499
|
+
(_names.array.has(name) ||
|
|
2500
|
+
isObject(fieldValue) ||
|
|
2501
|
+
(field && !field._f)) &&
|
|
2502
|
+
!isDateObject(fieldValue)
|
|
2503
|
+
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
2504
|
+
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
2505
|
+
}
|
|
2506
|
+
};
|
|
2507
|
+
const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
|
|
2508
|
+
const field = get(_fields, name);
|
|
2509
|
+
const isFieldArray = _names.array.has(name);
|
|
2510
|
+
const cloneValue = skipClone ? value : cloneObject(value);
|
|
2511
|
+
const previousValue = get(_formValues, name);
|
|
2512
|
+
const isValueUnchanged = deepEqual(previousValue, cloneValue);
|
|
2513
|
+
if (!isValueUnchanged) {
|
|
2514
|
+
set(_formValues, name, cloneValue);
|
|
2515
|
+
}
|
|
2516
|
+
if (isFieldArray) {
|
|
2517
|
+
_subjects.array.next({
|
|
2518
|
+
name,
|
|
2519
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
2520
|
+
});
|
|
2521
|
+
if ((_proxyFormState.isDirty ||
|
|
2522
|
+
_proxyFormState.dirtyFields ||
|
|
2523
|
+
_proxySubscribeFormState.isDirty ||
|
|
2524
|
+
_proxySubscribeFormState.dirtyFields) &&
|
|
2525
|
+
options.shouldDirty) {
|
|
2526
|
+
_updateDirtyFields();
|
|
2527
|
+
if (!skipStateEmit) {
|
|
2528
|
+
_subjects.state.next({
|
|
2529
|
+
name,
|
|
2530
|
+
dirtyFields: _formState.dirtyFields,
|
|
2531
|
+
isDirty: _getDirty(name, cloneValue),
|
|
2532
|
+
});
|
|
2533
|
+
}
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
else {
|
|
2537
|
+
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
2538
|
+
isEmptyObject(cloneValue);
|
|
2539
|
+
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
2540
|
+
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2541
|
+
}
|
|
2542
|
+
else {
|
|
2543
|
+
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
2544
|
+
}
|
|
2545
|
+
}
|
|
2546
|
+
if (!isValueUnchanged && !skipStateEmit) {
|
|
2547
|
+
const watched = isWatched(name, _names);
|
|
2548
|
+
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
2549
|
+
_subjects.state.next({
|
|
2550
|
+
...(watched && _formState),
|
|
2551
|
+
name: _state.mount || watched ? name : undefined,
|
|
2552
|
+
values,
|
|
2553
|
+
});
|
|
2554
|
+
}
|
|
2555
|
+
};
|
|
2556
|
+
const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
|
|
2557
|
+
const setValues = (formValues, options = {}) => {
|
|
2558
|
+
const updatedFormValues = isFunction(formValues)
|
|
2559
|
+
? formValues(_formValues)
|
|
2560
|
+
: formValues;
|
|
2561
|
+
if (!deepEqual(_formValues, updatedFormValues)) {
|
|
2562
|
+
_formValues = {
|
|
2563
|
+
..._formValues,
|
|
2564
|
+
...updatedFormValues,
|
|
2565
|
+
};
|
|
2566
|
+
const flattenedUpdates = flatten(updatedFormValues);
|
|
2567
|
+
for (const fieldName of _names.mount) {
|
|
2568
|
+
if (fieldName in flattenedUpdates) {
|
|
2569
|
+
_setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
_subjects.state.next({
|
|
2573
|
+
..._formState,
|
|
2574
|
+
name: undefined,
|
|
2575
|
+
type: undefined,
|
|
2576
|
+
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
2577
|
+
});
|
|
2578
|
+
if (options.shouldValidate) {
|
|
2579
|
+
_setValid();
|
|
2580
|
+
}
|
|
2581
|
+
}
|
|
2582
|
+
};
|
|
2583
|
+
const onChange = async (event) => {
|
|
2584
|
+
_state.mount = true;
|
|
2585
|
+
const target = event.target;
|
|
2586
|
+
let name = target.name;
|
|
2587
|
+
let isFieldValueUpdated = true;
|
|
2588
|
+
const field = get(_fields, name);
|
|
2589
|
+
const _updateIsFieldValueUpdated = (fieldValue) => {
|
|
2590
|
+
isFieldValueUpdated =
|
|
2591
|
+
Number.isNaN(fieldValue) ||
|
|
2592
|
+
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
2593
|
+
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
2594
|
+
};
|
|
2595
|
+
if (field) {
|
|
2596
|
+
let error;
|
|
2597
|
+
let isValid;
|
|
2598
|
+
const fieldValue = target.type
|
|
2599
|
+
? getFieldValue(field._f)
|
|
2600
|
+
: getEventValue(event);
|
|
2601
|
+
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
2602
|
+
const hasNoValidationEffect = !hasValidation(field._f) &&
|
|
2603
|
+
!props.validate &&
|
|
2604
|
+
!_options.resolver &&
|
|
2605
|
+
!get(_formState.errors, name) &&
|
|
2606
|
+
!field._f.deps;
|
|
2607
|
+
const shouldSkipValidation = hasNoValidationEffect ||
|
|
2608
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
|
|
2609
|
+
const watched = isWatched(name, _names, isBlurEvent);
|
|
2610
|
+
set(_formValues, name, fieldValue);
|
|
2611
|
+
if (isBlurEvent) {
|
|
2612
|
+
if (!target || !target.readOnly) {
|
|
2613
|
+
field._f.onBlur && field._f.onBlur(event);
|
|
2614
|
+
const pendingDelayError = delayErrorCallbacks[name];
|
|
2615
|
+
pendingDelayError && pendingDelayError(0);
|
|
2616
|
+
}
|
|
2617
|
+
}
|
|
2618
|
+
else if (field._f.onChange) {
|
|
2619
|
+
field._f.onChange(event);
|
|
2620
|
+
}
|
|
2621
|
+
const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent);
|
|
2622
|
+
const shouldRender = !isEmptyObject(fieldState) || watched;
|
|
2623
|
+
!isBlurEvent &&
|
|
2624
|
+
_subjects.state.next({
|
|
2625
|
+
name,
|
|
2626
|
+
type: event.type,
|
|
2627
|
+
...(_valuesSubscriberCount
|
|
2628
|
+
? { values: cloneObject(_formValues) }
|
|
2629
|
+
: {}),
|
|
2630
|
+
});
|
|
2631
|
+
if (shouldSkipValidation) {
|
|
2632
|
+
if ((!hasNoValidationEffect || !_formState.isValid) &&
|
|
2633
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
|
|
2634
|
+
if (_options.mode === 'onBlur') {
|
|
2635
|
+
if (isBlurEvent) {
|
|
2636
|
+
_setValid();
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
else if (!isBlurEvent) {
|
|
2640
|
+
_setValid();
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
return (shouldRender &&
|
|
2644
|
+
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
|
|
2645
|
+
}
|
|
2646
|
+
if (!_options.resolver && props.validate) {
|
|
2647
|
+
await validateForm({
|
|
2648
|
+
name: name,
|
|
2649
|
+
eventType: event.type,
|
|
2650
|
+
});
|
|
2651
|
+
}
|
|
2652
|
+
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
|
|
2653
|
+
if (_options.resolver) {
|
|
2654
|
+
const { errors } = await _runSchema([name]);
|
|
2655
|
+
_updateIsValidating([name]);
|
|
2656
|
+
_updateIsFieldValueUpdated(fieldValue);
|
|
2657
|
+
if (!isFieldValueUpdated) {
|
|
2658
|
+
!isEmptyObject(fieldState) && _subjects.state.next(fieldState);
|
|
2659
|
+
return;
|
|
2660
|
+
}
|
|
2661
|
+
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
|
2662
|
+
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
|
2663
|
+
error = errorLookupResult.error;
|
|
2664
|
+
name = errorLookupResult.name;
|
|
2665
|
+
isValid = isEmptyObject(errors);
|
|
2666
|
+
}
|
|
2667
|
+
else {
|
|
2668
|
+
_updateIsValidating([name], true);
|
|
2669
|
+
error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
|
|
2670
|
+
_updateIsValidating([name]);
|
|
2671
|
+
_updateIsFieldValueUpdated(fieldValue);
|
|
2672
|
+
if (isFieldValueUpdated) {
|
|
2673
|
+
if (error) {
|
|
2674
|
+
isValid = false;
|
|
2675
|
+
}
|
|
2676
|
+
else if (_proxyFormState.isValid ||
|
|
2677
|
+
_proxySubscribeFormState.isValid) {
|
|
2678
|
+
isValid = await executeBuiltInValidation({
|
|
2679
|
+
fields: _fields,
|
|
2680
|
+
onlyCheckValid: true,
|
|
2681
|
+
name: name,
|
|
2682
|
+
eventType: event.type,
|
|
2683
|
+
});
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
}
|
|
2687
|
+
if (isFieldValueUpdated) {
|
|
2688
|
+
field._f.deps &&
|
|
2689
|
+
(!Array.isArray(field._f.deps) || field._f.deps.length > 0) &&
|
|
2690
|
+
trigger(field._f.deps);
|
|
2691
|
+
shouldRenderByError(name, isValid, error, fieldState);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
};
|
|
2695
|
+
const _focusInput = (ref, key) => {
|
|
2696
|
+
if (get(_formState.errors, key) && ref.focus) {
|
|
2697
|
+
ref.focus();
|
|
2698
|
+
return 1;
|
|
2699
|
+
}
|
|
2700
|
+
return;
|
|
2701
|
+
};
|
|
2702
|
+
const trigger = async (name, options = {}) => {
|
|
2703
|
+
let isValid;
|
|
2704
|
+
let validationResult;
|
|
2705
|
+
const fieldNames = convertToArrayPayload(name);
|
|
2706
|
+
if (_options.resolver) {
|
|
2707
|
+
const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames);
|
|
2708
|
+
isValid = isEmptyObject(errors);
|
|
2709
|
+
validationResult = name
|
|
2710
|
+
? !fieldNames.some((name) => get(errors, name))
|
|
2711
|
+
: isValid;
|
|
2712
|
+
}
|
|
2713
|
+
else if (name) {
|
|
2714
|
+
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
|
|
2715
|
+
const field = get(_fields, fieldName);
|
|
2716
|
+
return await executeBuiltInValidation({
|
|
2717
|
+
fields: field && field._f ? { [fieldName]: field } : field,
|
|
2718
|
+
eventType: EVENTS.TRIGGER,
|
|
2719
|
+
});
|
|
2720
|
+
}))).every(Boolean);
|
|
2721
|
+
!(!validationResult && !_formState.isValid) && _setValid();
|
|
2722
|
+
}
|
|
2723
|
+
else {
|
|
2724
|
+
validationResult = isValid = await executeBuiltInValidation({
|
|
2725
|
+
fields: _fields,
|
|
2726
|
+
name,
|
|
2727
|
+
eventType: EVENTS.TRIGGER,
|
|
2728
|
+
});
|
|
2729
|
+
}
|
|
2730
|
+
if (options.delayError && _options.delayError && isString(name)) {
|
|
2731
|
+
const error = get(_formState.errors, name);
|
|
2732
|
+
if (error) {
|
|
2733
|
+
unset(_formState.errors, name);
|
|
2734
|
+
delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
|
|
2735
|
+
delayErrorCallbacks[name](_options.delayError);
|
|
2736
|
+
}
|
|
2737
|
+
else {
|
|
2738
|
+
clearTimeout(timers[name]);
|
|
2739
|
+
delete delayErrorCallbacks[name];
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
_subjects.state.next({
|
|
2743
|
+
...(!isString(name) ||
|
|
2744
|
+
((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
|
|
2745
|
+
isValid !== _formState.isValid)
|
|
2746
|
+
? {}
|
|
2747
|
+
: { name }),
|
|
2748
|
+
...(_options.resolver || !name ? { isValid } : {}),
|
|
2749
|
+
errors: _formState.errors,
|
|
2750
|
+
});
|
|
2751
|
+
options.shouldFocus &&
|
|
2752
|
+
!validationResult &&
|
|
2753
|
+
iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
|
|
2754
|
+
return validationResult;
|
|
2755
|
+
};
|
|
2756
|
+
const getValues = (fieldNames, config) => {
|
|
2757
|
+
let values = {
|
|
2758
|
+
...(_state.mount ? _formValues : _defaultValues),
|
|
2759
|
+
};
|
|
2760
|
+
if (config) {
|
|
2761
|
+
values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
|
|
2762
|
+
}
|
|
2763
|
+
return isUndefined(fieldNames)
|
|
2764
|
+
? values
|
|
2765
|
+
: isString(fieldNames)
|
|
2766
|
+
? get(values, fieldNames)
|
|
2767
|
+
: fieldNames.map((name) => get(values, name));
|
|
2768
|
+
};
|
|
2769
|
+
const getFieldState = (name, formState) => ({
|
|
2770
|
+
invalid: !!get((formState || _formState).errors, name),
|
|
2771
|
+
isDirty: !!get((formState || _formState).dirtyFields, name),
|
|
2772
|
+
error: get((formState || _formState).errors, name),
|
|
2773
|
+
isValidating: !!get(_formState.validatingFields, name),
|
|
2774
|
+
isTouched: !!get((formState || _formState).touchedFields, name),
|
|
2775
|
+
});
|
|
2776
|
+
const clearErrors = (name) => {
|
|
2777
|
+
const names = name ? convertToArrayPayload(name) : undefined;
|
|
2778
|
+
names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
|
|
2779
|
+
if (names) {
|
|
2780
|
+
names.forEach((inputName) => {
|
|
2781
|
+
_subjects.state.next({
|
|
2782
|
+
name: inputName,
|
|
2783
|
+
errors: _formState.errors,
|
|
2784
|
+
});
|
|
2785
|
+
});
|
|
2786
|
+
}
|
|
2787
|
+
else {
|
|
2788
|
+
_formState.errors = {};
|
|
2789
|
+
_subjects.state.next({
|
|
2790
|
+
errors: _formState.errors,
|
|
2791
|
+
});
|
|
2792
|
+
}
|
|
2793
|
+
};
|
|
2794
|
+
const setError = (name, error, options) => {
|
|
2795
|
+
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
2796
|
+
const currentError = get(_formState.errors, name) || {};
|
|
2797
|
+
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
2798
|
+
set(_formState.errors, name, {
|
|
2799
|
+
...restOfErrorTree,
|
|
2800
|
+
...error,
|
|
2801
|
+
ref,
|
|
2802
|
+
});
|
|
2803
|
+
_subjects.state.next({
|
|
2804
|
+
name,
|
|
2805
|
+
errors: _formState.errors,
|
|
2806
|
+
isValid: false,
|
|
2807
|
+
});
|
|
2808
|
+
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
2809
|
+
};
|
|
2810
|
+
const watch = (name, defaultValue) => {
|
|
2811
|
+
if (isFunction(name)) {
|
|
2812
|
+
_valuesSubscriberCount++;
|
|
2813
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2814
|
+
next: (payload) => 'values' in payload &&
|
|
2815
|
+
name(payload.values || _getWatch(undefined, defaultValue), payload),
|
|
2816
|
+
});
|
|
2817
|
+
let called = false;
|
|
2818
|
+
return {
|
|
2819
|
+
unsubscribe: () => {
|
|
2820
|
+
if (called) {
|
|
2821
|
+
return;
|
|
2822
|
+
}
|
|
2823
|
+
called = true;
|
|
2824
|
+
_valuesSubscriberCount--;
|
|
2825
|
+
unsubscribe();
|
|
2826
|
+
},
|
|
2827
|
+
};
|
|
2828
|
+
}
|
|
2829
|
+
return _getWatch(name, defaultValue, true);
|
|
2830
|
+
};
|
|
2831
|
+
const _subscribe = (props) => {
|
|
2832
|
+
var _a;
|
|
2833
|
+
const needsValues = !!((_a = props.formState) === null || _a === void 0 ? void 0 : _a.values);
|
|
2834
|
+
if (needsValues) {
|
|
2835
|
+
_valuesSubscriberCount++;
|
|
2836
|
+
}
|
|
2837
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2838
|
+
next: (formState) => {
|
|
2839
|
+
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
2840
|
+
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
2841
|
+
const snapshot = { ..._formValues };
|
|
2842
|
+
props.callback({
|
|
2843
|
+
values: snapshot,
|
|
2844
|
+
..._formState,
|
|
2845
|
+
...formState,
|
|
2846
|
+
defaultValues: _defaultValues,
|
|
2847
|
+
});
|
|
2848
|
+
}
|
|
2564
2849
|
},
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2850
|
+
});
|
|
2851
|
+
if (!needsValues) {
|
|
2852
|
+
return unsubscribe;
|
|
2853
|
+
}
|
|
2854
|
+
let called = false;
|
|
2855
|
+
return () => {
|
|
2856
|
+
if (called) {
|
|
2857
|
+
return;
|
|
2858
|
+
}
|
|
2859
|
+
called = true;
|
|
2860
|
+
_valuesSubscriberCount--;
|
|
2861
|
+
unsubscribe();
|
|
2862
|
+
};
|
|
2863
|
+
};
|
|
2864
|
+
const subscribe = (props) => {
|
|
2865
|
+
_state.mount = true;
|
|
2866
|
+
_proxySubscribeFormState = {
|
|
2867
|
+
..._proxySubscribeFormState,
|
|
2868
|
+
...props.formState,
|
|
2869
|
+
};
|
|
2870
|
+
return _subscribe({
|
|
2871
|
+
...props,
|
|
2872
|
+
formState: {
|
|
2873
|
+
...defaultProxyFormState,
|
|
2874
|
+
...props.formState,
|
|
2570
2875
|
},
|
|
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,
|
|
2876
|
+
});
|
|
2586
2877
|
};
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
|
|
2878
|
+
const unregister = (name, options = {}) => {
|
|
2879
|
+
for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
|
|
2880
|
+
_names.mount.delete(fieldName);
|
|
2881
|
+
_names.array.delete(fieldName);
|
|
2882
|
+
if (!options.keepValue) {
|
|
2883
|
+
unset(_fields, fieldName);
|
|
2884
|
+
unset(_formValues, fieldName);
|
|
2885
|
+
}
|
|
2886
|
+
!options.keepError && unset(_formState.errors, fieldName);
|
|
2887
|
+
!options.keepDirty && unset(_formState.dirtyFields, fieldName);
|
|
2888
|
+
!options.keepTouched && unset(_formState.touchedFields, fieldName);
|
|
2889
|
+
!options.keepIsValidating &&
|
|
2890
|
+
unset(_formState.validatingFields, fieldName);
|
|
2891
|
+
!_options.shouldUnregister &&
|
|
2892
|
+
!options.keepDefaultValue &&
|
|
2893
|
+
unset(_defaultValues, fieldName);
|
|
2894
|
+
}
|
|
2895
|
+
_subjects.state.next({
|
|
2896
|
+
values: cloneObject(_formValues),
|
|
2897
|
+
});
|
|
2898
|
+
_subjects.state.next({
|
|
2899
|
+
..._formState,
|
|
2900
|
+
...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
|
|
2901
|
+
});
|
|
2902
|
+
!options.keepIsValid && _setValid();
|
|
2590
2903
|
};
|
|
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
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
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);
|
|
2904
|
+
const _setDisabledField = ({ disabled, name, }) => {
|
|
2905
|
+
if ((isBoolean(disabled) && _state.mount) ||
|
|
2906
|
+
!!disabled ||
|
|
2907
|
+
_names.disabled.has(name)) {
|
|
2908
|
+
const wasDisabled = _names.disabled.has(name);
|
|
2909
|
+
const isDisabled = !!disabled;
|
|
2910
|
+
const disabledStateChanged = wasDisabled !== isDisabled;
|
|
2911
|
+
disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
|
|
2912
|
+
disabledStateChanged && _state.mount && !_state.action && _setValid();
|
|
2913
|
+
}
|
|
2914
|
+
};
|
|
2915
|
+
const register = (name, options = {}) => {
|
|
2916
|
+
let field = get(_fields, name);
|
|
2917
|
+
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
|
2918
|
+
const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
|
|
2919
|
+
set(_fields, name, {
|
|
2920
|
+
...(field || {}),
|
|
2921
|
+
_f: {
|
|
2922
|
+
...(field && field._f ? field._f : { ref: { name } }),
|
|
2923
|
+
name,
|
|
2924
|
+
mount: true,
|
|
2925
|
+
...options,
|
|
2926
|
+
},
|
|
2927
|
+
});
|
|
2928
|
+
_names.mount.add(name);
|
|
2929
|
+
if (field && !shouldRevalidateRemount) {
|
|
2930
|
+
_setDisabledField({
|
|
2931
|
+
disabled: isBoolean(options.disabled)
|
|
2932
|
+
? options.disabled
|
|
2933
|
+
: _options.disabled,
|
|
2934
|
+
name,
|
|
2935
|
+
});
|
|
2936
|
+
}
|
|
2937
|
+
else {
|
|
2938
|
+
updateValidAndValue(name, true, options.value);
|
|
2939
|
+
}
|
|
2940
|
+
return {
|
|
2941
|
+
...(disabledIsDefined
|
|
2942
|
+
? { disabled: options.disabled || _options.disabled }
|
|
2943
|
+
: {}),
|
|
2944
|
+
...(_options.progressive
|
|
2945
|
+
? {
|
|
2946
|
+
required: !!options.required,
|
|
2947
|
+
min: getRuleValue(options.min),
|
|
2948
|
+
max: getRuleValue(options.max),
|
|
2949
|
+
minLength: getRuleValue(options.minLength),
|
|
2950
|
+
maxLength: getRuleValue(options.maxLength),
|
|
2951
|
+
pattern: getRuleValue(options.pattern),
|
|
2716
2952
|
}
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2953
|
+
: {}),
|
|
2954
|
+
name,
|
|
2955
|
+
onChange,
|
|
2956
|
+
onBlur: onChange,
|
|
2957
|
+
ref: (ref) => {
|
|
2958
|
+
if (ref) {
|
|
2959
|
+
_names.registerName.add(name);
|
|
2960
|
+
register(name, options);
|
|
2961
|
+
_names.registerName.delete(name);
|
|
2962
|
+
field = get(_fields, name);
|
|
2963
|
+
const fieldRef = isUndefined(ref.value)
|
|
2964
|
+
? ref.querySelectorAll
|
|
2965
|
+
? ref.querySelectorAll('input,select,textarea')[0] || ref
|
|
2966
|
+
: ref
|
|
2967
|
+
: ref;
|
|
2968
|
+
const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
|
|
2969
|
+
const refs = field._f.refs || [];
|
|
2970
|
+
if (radioOrCheckbox
|
|
2971
|
+
? refs.find((option) => option === fieldRef)
|
|
2972
|
+
: fieldRef === field._f.ref) {
|
|
2973
|
+
return;
|
|
2974
|
+
}
|
|
2975
|
+
const newField = {
|
|
2976
|
+
...field._f,
|
|
2977
|
+
};
|
|
2978
|
+
if (radioOrCheckbox) {
|
|
2979
|
+
newField.refs = [
|
|
2980
|
+
...refs.filter(live),
|
|
2981
|
+
fieldRef,
|
|
2982
|
+
...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
|
|
2983
|
+
];
|
|
2984
|
+
newField.ref = { type: fieldRef.type, name };
|
|
2985
|
+
}
|
|
2986
|
+
else {
|
|
2987
|
+
newField.ref = fieldRef;
|
|
2988
|
+
delete newField.refs;
|
|
2989
|
+
}
|
|
2990
|
+
set(_fields, name, {
|
|
2991
|
+
_f: newField,
|
|
2992
|
+
});
|
|
2993
|
+
updateValidAndValue(name, false, undefined, fieldRef);
|
|
2994
|
+
}
|
|
2995
|
+
else {
|
|
2996
|
+
field = get(_fields, name, {});
|
|
2997
|
+
if (field._f) {
|
|
2998
|
+
field._f.mount = false;
|
|
2999
|
+
}
|
|
3000
|
+
(_options.shouldUnregister || options.shouldUnregister) &&
|
|
3001
|
+
!(isNameInFieldArray(_names.array, name) && _state.action) &&
|
|
3002
|
+
_names.unMount.add(name);
|
|
3003
|
+
}
|
|
3004
|
+
},
|
|
3005
|
+
};
|
|
2734
3006
|
};
|
|
2735
|
-
const
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
|
|
3007
|
+
const _focusError = () => _options.shouldFocusError &&
|
|
3008
|
+
!_options.shouldUseNativeValidation &&
|
|
3009
|
+
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
|
3010
|
+
const _disableForm = (disabled) => {
|
|
3011
|
+
if (isBoolean(disabled)) {
|
|
3012
|
+
_subjects.state.next({ disabled });
|
|
3013
|
+
iterateFieldsByAction(_fields, (ref, name) => {
|
|
3014
|
+
const currentField = get(_fields, name);
|
|
3015
|
+
if (currentField) {
|
|
3016
|
+
ref.disabled = currentField._f.disabled || disabled;
|
|
3017
|
+
if (Array.isArray(currentField._f.refs)) {
|
|
3018
|
+
currentField._f.refs.forEach((inputRef) => {
|
|
3019
|
+
inputRef.disabled = currentField._f.disabled || disabled;
|
|
3020
|
+
});
|
|
3021
|
+
}
|
|
3022
|
+
}
|
|
3023
|
+
}, 0, false);
|
|
3024
|
+
}
|
|
2745
3025
|
};
|
|
2746
|
-
const
|
|
2747
|
-
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
3026
|
+
const handleSubmit = (onValid, onInvalid) => async (e) => {
|
|
3027
|
+
let result = undefined;
|
|
3028
|
+
let onValidError = undefined;
|
|
3029
|
+
if (e) {
|
|
3030
|
+
e.preventDefault && e.preventDefault();
|
|
3031
|
+
e.persist &&
|
|
3032
|
+
e.persist();
|
|
3033
|
+
}
|
|
3034
|
+
let fieldValues = cloneObject(_formValues);
|
|
3035
|
+
_subjects.state.next({
|
|
3036
|
+
isSubmitting: true,
|
|
2755
3037
|
});
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
|
|
2761
|
-
|
|
2762
|
-
|
|
2763
|
-
|
|
2764
|
-
|
|
2765
|
-
|
|
2766
|
-
|
|
3038
|
+
if (_options.resolver) {
|
|
3039
|
+
const { errors, values } = await _runSchema();
|
|
3040
|
+
_updateIsValidating();
|
|
3041
|
+
_formState.errors = errors;
|
|
3042
|
+
fieldValues = cloneObject(values);
|
|
3043
|
+
}
|
|
3044
|
+
else {
|
|
3045
|
+
await executeBuiltInValidation({
|
|
3046
|
+
fields: _fields,
|
|
3047
|
+
eventType: EVENTS.SUBMIT,
|
|
3048
|
+
});
|
|
3049
|
+
}
|
|
3050
|
+
if (_names.disabled.size) {
|
|
3051
|
+
for (const name of _names.disabled) {
|
|
3052
|
+
unset(fieldValues, name);
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
unset(_formState.errors, ROOT_ERROR_TYPE);
|
|
3056
|
+
if (isEmptyObject(_formState.errors)) {
|
|
3057
|
+
_subjects.state.next({
|
|
3058
|
+
errors: {},
|
|
3059
|
+
});
|
|
3060
|
+
try {
|
|
3061
|
+
result = await onValid(fieldValues, e);
|
|
3062
|
+
}
|
|
3063
|
+
catch (error) {
|
|
3064
|
+
onValidError = error;
|
|
3065
|
+
}
|
|
3066
|
+
}
|
|
3067
|
+
else {
|
|
3068
|
+
if (onInvalid) {
|
|
3069
|
+
await onInvalid({ ..._formState.errors }, e);
|
|
3070
|
+
}
|
|
3071
|
+
_focusError();
|
|
3072
|
+
setTimeout(_focusError);
|
|
3073
|
+
}
|
|
3074
|
+
_subjects.state.next({
|
|
3075
|
+
isSubmitted: true,
|
|
3076
|
+
isSubmitting: false,
|
|
3077
|
+
isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
|
|
3078
|
+
submitCount: _formState.submitCount + 1,
|
|
3079
|
+
errors: _formState.errors,
|
|
2767
3080
|
});
|
|
3081
|
+
if (onValidError) {
|
|
3082
|
+
throw onValidError;
|
|
3083
|
+
}
|
|
3084
|
+
return result;
|
|
2768
3085
|
};
|
|
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);
|
|
3086
|
+
const resetField = (name, options = {}) => {
|
|
3087
|
+
if (get(_fields, name)) {
|
|
3088
|
+
if (isUndefined(options.defaultValue)) {
|
|
3089
|
+
setValue(name, cloneObject(get(_defaultValues, name)));
|
|
3090
|
+
}
|
|
3091
|
+
else {
|
|
3092
|
+
setValue(name, options.defaultValue);
|
|
3093
|
+
set(_defaultValues, name, cloneObject(options.defaultValue));
|
|
3094
|
+
}
|
|
3095
|
+
if (!options.keepTouched) {
|
|
3096
|
+
unset(_formState.touchedFields, name);
|
|
3097
|
+
}
|
|
3098
|
+
if (!options.keepDirty) {
|
|
3099
|
+
unset(_formState.dirtyFields, name);
|
|
3100
|
+
_formState.isDirty = options.defaultValue
|
|
3101
|
+
? _getDirty(name, cloneObject(get(_defaultValues, name)))
|
|
3102
|
+
: _getDirty();
|
|
3103
|
+
}
|
|
3104
|
+
if (!options.keepError) {
|
|
3105
|
+
unset(_formState.errors, name);
|
|
3106
|
+
_proxyFormState.isValid && _setValid();
|
|
3107
|
+
}
|
|
3108
|
+
_subjects.state.next({ ..._formState });
|
|
3109
|
+
}
|
|
2808
3110
|
};
|
|
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
|
-
});
|
|
3111
|
+
const _reset = (formValues, keepStateOptions = {}) => {
|
|
3112
|
+
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
|
|
3113
|
+
const cloneUpdatedValues = cloneObject(updatedValues);
|
|
3114
|
+
const isEmptyResetValues = isEmptyObject(formValues);
|
|
3115
|
+
const values = cloneUpdatedValues;
|
|
3116
|
+
const fieldRefs = _fields;
|
|
3117
|
+
if (!keepStateOptions.keepDefaultValues) {
|
|
3118
|
+
_defaultValues = updatedValues;
|
|
3119
|
+
}
|
|
3120
|
+
if (!keepStateOptions.keepValues) {
|
|
3121
|
+
if (keepStateOptions.keepDirtyValues) {
|
|
3122
|
+
const fieldsToCheck = new Set([
|
|
3123
|
+
..._names.mount,
|
|
3124
|
+
...collectDirtyFieldNames(getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs), _formState.dirtyFields),
|
|
3125
|
+
]);
|
|
3126
|
+
for (const fieldName of Array.from(fieldsToCheck)) {
|
|
3127
|
+
const isDirty = get(_formState.dirtyFields, fieldName);
|
|
3128
|
+
const existingValue = get(_formValues, fieldName);
|
|
3129
|
+
const newValue = get(values, fieldName);
|
|
3130
|
+
if (isDirty && !isUndefined(existingValue)) {
|
|
3131
|
+
set(values, fieldName, existingValue);
|
|
2836
3132
|
}
|
|
2837
|
-
|
|
3133
|
+
else if (!isDirty && !isUndefined(newValue)) {
|
|
3134
|
+
setValue(fieldName, newValue);
|
|
3135
|
+
}
|
|
3136
|
+
}
|
|
2838
3137
|
}
|
|
2839
3138
|
else {
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
2846
|
-
|
|
2847
|
-
|
|
2848
|
-
|
|
3139
|
+
if (isWeb && isUndefined(formValues)) {
|
|
3140
|
+
for (const name of _names.mount) {
|
|
3141
|
+
const field = get(_fields, name);
|
|
3142
|
+
if (field && field._f) {
|
|
3143
|
+
const fieldReference = Array.isArray(field._f.refs)
|
|
3144
|
+
? field._f.refs[0]
|
|
3145
|
+
: field._f.ref;
|
|
3146
|
+
if (isHTMLElement(fieldReference)) {
|
|
3147
|
+
const form = fieldReference.closest('form');
|
|
3148
|
+
if (form) {
|
|
3149
|
+
form.reset();
|
|
3150
|
+
break;
|
|
3151
|
+
}
|
|
3152
|
+
}
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
3157
|
+
for (const fieldName of _names.mount) {
|
|
3158
|
+
setValue(fieldName, get(values, fieldName));
|
|
3159
|
+
}
|
|
3160
|
+
}
|
|
3161
|
+
else {
|
|
3162
|
+
_fields = {};
|
|
2849
3163
|
}
|
|
2850
3164
|
}
|
|
2851
|
-
|
|
2852
|
-
|
|
2853
|
-
|
|
2854
|
-
|
|
2855
|
-
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
key.startsWith(control._names.focus) &&
|
|
2860
|
-
ref.focus) {
|
|
2861
|
-
ref.focus();
|
|
2862
|
-
return 1;
|
|
3165
|
+
if (_options.shouldUnregister) {
|
|
3166
|
+
_formValues = keepStateOptions.keepDefaultValues
|
|
3167
|
+
? cloneObject(_defaultValues)
|
|
3168
|
+
: {};
|
|
3169
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
3170
|
+
for (const fieldName of _names.mount) {
|
|
3171
|
+
set(_formValues, fieldName, get(values, fieldName));
|
|
3172
|
+
}
|
|
2863
3173
|
}
|
|
2864
|
-
|
|
3174
|
+
}
|
|
3175
|
+
else {
|
|
3176
|
+
_formValues = cloneObject(values);
|
|
3177
|
+
}
|
|
3178
|
+
_subjects.array.next({
|
|
3179
|
+
values: { ...values },
|
|
2865
3180
|
});
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
|
|
2873
|
-
|
|
2874
|
-
|
|
2875
|
-
|
|
2876
|
-
|
|
2877
|
-
|
|
2878
|
-
|
|
2879
|
-
|
|
2880
|
-
|
|
2881
|
-
|
|
3181
|
+
_subjects.state.next({
|
|
3182
|
+
name: undefined,
|
|
3183
|
+
type: undefined,
|
|
3184
|
+
values: { ...values },
|
|
3185
|
+
});
|
|
3186
|
+
}
|
|
3187
|
+
_names = {
|
|
3188
|
+
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
|
|
3189
|
+
unMount: new Set(),
|
|
3190
|
+
array: new Set(),
|
|
3191
|
+
registerName: new Set(),
|
|
3192
|
+
disabled: new Set(),
|
|
3193
|
+
watch: new Set(),
|
|
3194
|
+
watchAll: false,
|
|
3195
|
+
focus: '',
|
|
3196
|
+
};
|
|
3197
|
+
_state.mount =
|
|
3198
|
+
!_proxyFormState.isValid ||
|
|
3199
|
+
!!keepStateOptions.keepIsValid ||
|
|
3200
|
+
!!keepStateOptions.keepDirtyValues ||
|
|
3201
|
+
(!_options.shouldUnregister && !isEmptyObject(values));
|
|
3202
|
+
_state.watch = !!_options.shouldUnregister;
|
|
3203
|
+
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
3204
|
+
_state.action = false;
|
|
3205
|
+
if (!keepStateOptions.keepErrors) {
|
|
3206
|
+
_formState.errors = {};
|
|
3207
|
+
}
|
|
3208
|
+
_subjects.state.next({
|
|
3209
|
+
submitCount: keepStateOptions.keepSubmitCount
|
|
3210
|
+
? _formState.submitCount
|
|
3211
|
+
: 0,
|
|
3212
|
+
isDirty: isEmptyResetValues
|
|
3213
|
+
? false
|
|
3214
|
+
: keepStateOptions.keepDirty
|
|
3215
|
+
? _formState.isDirty
|
|
3216
|
+
: keepStateOptions.keepValues
|
|
3217
|
+
? _getDirty()
|
|
3218
|
+
: !!(keepStateOptions.keepDefaultValues &&
|
|
3219
|
+
!deepEqual(formValues, _defaultValues)),
|
|
3220
|
+
isSubmitted: keepStateOptions.keepIsSubmitted
|
|
3221
|
+
? _formState.isSubmitted
|
|
3222
|
+
: false,
|
|
3223
|
+
dirtyFields: isEmptyResetValues
|
|
3224
|
+
? {}
|
|
3225
|
+
: keepStateOptions.keepDirtyValues
|
|
3226
|
+
? keepStateOptions.keepDefaultValues && _formValues
|
|
3227
|
+
? getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)
|
|
3228
|
+
: _formState.dirtyFields
|
|
3229
|
+
: keepStateOptions.keepDefaultValues && formValues
|
|
3230
|
+
? getDirtyFields(_defaultValues, formValues, undefined, fieldRefs)
|
|
3231
|
+
: keepStateOptions.keepDirty
|
|
3232
|
+
? _formState.dirtyFields
|
|
3233
|
+
: {},
|
|
3234
|
+
touchedFields: keepStateOptions.keepTouched
|
|
3235
|
+
? _formState.touchedFields
|
|
3236
|
+
: {},
|
|
3237
|
+
errors: keepStateOptions.keepErrors ? _formState.errors : {},
|
|
3238
|
+
isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
|
|
3239
|
+
? _formState.isSubmitSuccessful
|
|
3240
|
+
: false,
|
|
3241
|
+
isSubmitting: false,
|
|
3242
|
+
defaultValues: _defaultValues,
|
|
3243
|
+
});
|
|
3244
|
+
};
|
|
3245
|
+
const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
|
|
3246
|
+
? formValues(_formValues)
|
|
3247
|
+
: formValues, { ..._options.resetOptions, ...keepStateOptions });
|
|
3248
|
+
const setFocus = (name, options = {}) => {
|
|
3249
|
+
const field = get(_fields, name);
|
|
3250
|
+
const fieldReference = field && field._f;
|
|
3251
|
+
if (fieldReference) {
|
|
3252
|
+
const fieldRef = fieldReference.refs
|
|
3253
|
+
? fieldReference.refs[0]
|
|
3254
|
+
: fieldReference.ref;
|
|
3255
|
+
if (fieldRef.focus) {
|
|
3256
|
+
setTimeout(() => {
|
|
3257
|
+
fieldRef.focus();
|
|
3258
|
+
options.shouldSelect &&
|
|
3259
|
+
isFunction(fieldRef.select) &&
|
|
3260
|
+
fieldRef.select();
|
|
3261
|
+
});
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
};
|
|
3265
|
+
const _setFormState = (updatedFormState) => {
|
|
3266
|
+
// `name`, `type`, and `values` describe the event that produced this
|
|
3267
|
+
// update, not the form's persisted state (they aren't part of
|
|
3268
|
+
// `FormState`). Merging them in would leak a stale `name`/`type` from
|
|
3269
|
+
// one event into a later, unrelated notification that doesn't specify
|
|
3270
|
+
// its own.
|
|
3271
|
+
const { name, type, values, ...formState } = updatedFormState;
|
|
3272
|
+
_formState = {
|
|
3273
|
+
..._formState,
|
|
3274
|
+
...formState,
|
|
2882
3275
|
};
|
|
2883
|
-
}
|
|
3276
|
+
};
|
|
3277
|
+
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
|
3278
|
+
_options.defaultValues().then((values) => {
|
|
3279
|
+
reset(values, _options.resetOptions);
|
|
3280
|
+
_subjects.state.next({
|
|
3281
|
+
isLoading: false,
|
|
3282
|
+
});
|
|
3283
|
+
});
|
|
3284
|
+
const resetDefaultValues = (values, options = {}) => {
|
|
3285
|
+
_defaultValues = cloneObject(values);
|
|
3286
|
+
if (!options.keepDirty) {
|
|
3287
|
+
const newDirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
|
|
3288
|
+
_formState.dirtyFields = newDirtyFields;
|
|
3289
|
+
_formState.isDirty = !isEmptyObject(newDirtyFields);
|
|
3290
|
+
}
|
|
3291
|
+
if (!options.keepIsValid) {
|
|
3292
|
+
_setValid();
|
|
3293
|
+
}
|
|
3294
|
+
_subjects.state.next({
|
|
3295
|
+
..._formState,
|
|
3296
|
+
defaultValues: _defaultValues,
|
|
3297
|
+
});
|
|
3298
|
+
};
|
|
3299
|
+
const methods = {
|
|
3300
|
+
control: {
|
|
3301
|
+
register,
|
|
3302
|
+
unregister,
|
|
3303
|
+
getFieldState,
|
|
3304
|
+
handleSubmit,
|
|
3305
|
+
setError,
|
|
3306
|
+
_subscribe,
|
|
3307
|
+
_runSchema,
|
|
3308
|
+
_updateIsValidating,
|
|
3309
|
+
_focusError,
|
|
3310
|
+
_getWatch,
|
|
3311
|
+
_getDirty,
|
|
3312
|
+
_setValid,
|
|
3313
|
+
_setFieldArray,
|
|
3314
|
+
_setDisabledField,
|
|
3315
|
+
_setErrors,
|
|
3316
|
+
_getFieldArray,
|
|
3317
|
+
_reset,
|
|
3318
|
+
_resetDefaultValues,
|
|
3319
|
+
_removeUnmounted,
|
|
3320
|
+
_disableForm,
|
|
3321
|
+
_subjects,
|
|
3322
|
+
_proxyFormState,
|
|
3323
|
+
get _fields() {
|
|
3324
|
+
return _fields;
|
|
3325
|
+
},
|
|
3326
|
+
get _formValues() {
|
|
3327
|
+
return _formValues;
|
|
3328
|
+
},
|
|
3329
|
+
get _state() {
|
|
3330
|
+
return _state;
|
|
3331
|
+
},
|
|
3332
|
+
set _state(value) {
|
|
3333
|
+
_state = value;
|
|
3334
|
+
},
|
|
3335
|
+
get _defaultValues() {
|
|
3336
|
+
return _defaultValues;
|
|
3337
|
+
},
|
|
3338
|
+
get _names() {
|
|
3339
|
+
return _names;
|
|
3340
|
+
},
|
|
3341
|
+
set _names(value) {
|
|
3342
|
+
_names = value;
|
|
3343
|
+
},
|
|
3344
|
+
get _formState() {
|
|
3345
|
+
return _formState;
|
|
3346
|
+
},
|
|
3347
|
+
get _options() {
|
|
3348
|
+
return _options;
|
|
3349
|
+
},
|
|
3350
|
+
set _options(value) {
|
|
3351
|
+
_options = {
|
|
3352
|
+
..._options,
|
|
3353
|
+
...value,
|
|
3354
|
+
};
|
|
3355
|
+
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
3356
|
+
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
3357
|
+
},
|
|
3358
|
+
},
|
|
3359
|
+
subscribe,
|
|
3360
|
+
trigger,
|
|
3361
|
+
register,
|
|
3362
|
+
handleSubmit,
|
|
3363
|
+
watch,
|
|
3364
|
+
setValue,
|
|
3365
|
+
setValues,
|
|
3366
|
+
getValues,
|
|
3367
|
+
reset,
|
|
3368
|
+
resetField,
|
|
3369
|
+
resetDefaultValues,
|
|
3370
|
+
clearErrors,
|
|
3371
|
+
unregister,
|
|
3372
|
+
setError,
|
|
3373
|
+
setFocus,
|
|
3374
|
+
getFieldState,
|
|
3375
|
+
};
|
|
2884
3376
|
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]),
|
|
3377
|
+
...methods,
|
|
3378
|
+
formControl: methods,
|
|
2897
3379
|
};
|
|
2898
3380
|
}
|
|
2899
3381
|
|
|
@@ -2929,26 +3411,19 @@ function useFieldArray(props) {
|
|
|
2929
3411
|
function useForm(props = {}) {
|
|
2930
3412
|
const _formControl = React.useRef(undefined);
|
|
2931
3413
|
const _values = React.useRef(undefined);
|
|
2932
|
-
const
|
|
2933
|
-
|
|
2934
|
-
|
|
3414
|
+
const _formControlProp = React.useRef(props.formControl);
|
|
3415
|
+
const [formState, updateFormState] = React.useState(() => ({
|
|
3416
|
+
...cloneObject(DEFAULT_FORM_STATE),
|
|
2935
3417
|
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
3418
|
errors: props.errors || {},
|
|
2945
3419
|
disabled: props.disabled || false,
|
|
2946
|
-
isReady: false,
|
|
2947
3420
|
defaultValues: isFunction(props.defaultValues)
|
|
2948
3421
|
? undefined
|
|
2949
3422
|
: props.defaultValues,
|
|
2950
|
-
});
|
|
2951
|
-
if (!_formControl.current
|
|
3423
|
+
}));
|
|
3424
|
+
if (!_formControl.current ||
|
|
3425
|
+
(props.formControl && _formControlProp.current !== props.formControl)) {
|
|
3426
|
+
_formControlProp.current = props.formControl;
|
|
2952
3427
|
if (props.formControl) {
|
|
2953
3428
|
_formControl.current = {
|
|
2954
3429
|
...props.formControl,
|
|
@@ -2971,7 +3446,10 @@ function useForm(props = {}) {
|
|
|
2971
3446
|
useIsomorphicLayoutEffect(() => {
|
|
2972
3447
|
const sub = control._subscribe({
|
|
2973
3448
|
formState: control._proxyFormState,
|
|
2974
|
-
callback: () => updateFormState({
|
|
3449
|
+
callback: () => updateFormState({
|
|
3450
|
+
...control._formState,
|
|
3451
|
+
defaultValues: control._defaultValues,
|
|
3452
|
+
}),
|
|
2975
3453
|
reRenderRoot: true,
|
|
2976
3454
|
});
|
|
2977
3455
|
updateFormState((data) => ({
|
|
@@ -3072,5 +3550,5 @@ function useForm(props = {}) {
|
|
|
3072
3550
|
*/
|
|
3073
3551
|
const Watch = (props) => props.render(useWatch({ name: props.names, ...props }));
|
|
3074
3552
|
|
|
3075
|
-
export { Controller, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
|
3553
|
+
export { Controller, FieldArray, Form, FormProvider, FormState, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
|
|
3076
3554
|
//# sourceMappingURL=index.esm.mjs.map
|