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