react-hook-form 8.0.0-beta.1 → 8.0.0-beta.3
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 +16 -40
- package/dist/constants.d.ts +5 -0
- 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.esm.mjs +755 -293
- 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.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/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 +522 -144
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/errors.d.ts +1 -0
- 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 +61 -8
- package/dist/types/form.d.ts.map +1 -1
- package/dist/types/path/eager.d.ts +1 -1
- package/dist/types/path/eager.d.ts.map +1 -1
- package/dist/types/utils.d.ts +3 -3
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/validator.d.ts +13 -1
- package/dist/types/validator.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.map +1 -1
- package/dist/useIsomorphicLayoutEffect.d.ts.map +1 -1
- 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 +31 -28
- package/dist/__tests__/controller.server.test.d.ts +0 -2
- package/dist/__tests__/controller.server.test.d.ts.map +0 -1
- package/dist/__tests__/controller.test.d.ts +0 -2
- package/dist/__tests__/controller.test.d.ts.map +0 -1
- package/dist/__tests__/form.test.d.ts +0 -2
- package/dist/__tests__/form.test.d.ts.map +0 -1
- package/dist/__tests__/formStateSubscribe.server.test.d.ts +0 -2
- package/dist/__tests__/formStateSubscribe.server.test.d.ts.map +0 -1
- package/dist/__tests__/formStateSubscribe.test.d.ts +0 -2
- package/dist/__tests__/formStateSubscribe.test.d.ts.map +0 -1
- package/dist/__tests__/isPlainObject.test.d.ts +0 -2
- package/dist/__tests__/isPlainObject.test.d.ts.map +0 -1
- package/dist/__tests__/logic/appendErrors.test.d.ts +0 -2
- package/dist/__tests__/logic/appendErrors.test.d.ts.map +0 -1
- package/dist/__tests__/logic/createFormControl.test.d.ts +0 -2
- package/dist/__tests__/logic/createFormControl.test.d.ts.map +0 -1
- package/dist/__tests__/logic/generateId.test.d.ts +0 -2
- package/dist/__tests__/logic/generateId.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getCheckboxValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getCheckboxValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getDirtyFields.test.d.ts +0 -2
- package/dist/__tests__/logic/getDirtyFields.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getEventValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getEventValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getFieldValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getFieldValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getFieldValueAs.test.d.ts +0 -2
- package/dist/__tests__/logic/getFieldValueAs.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getFocusFieldName.test.d.ts +0 -2
- package/dist/__tests__/logic/getFocusFieldName.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getNodeParentName.test.d.ts +0 -2
- package/dist/__tests__/logic/getNodeParentName.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getRadioValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getRadioValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getResolverOptions.test.d.ts +0 -2
- package/dist/__tests__/logic/getResolverOptions.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getRuleValue.test.d.ts +0 -2
- package/dist/__tests__/logic/getRuleValue.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getValidateError.test.d.ts +0 -2
- package/dist/__tests__/logic/getValidateError.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getValidationModes.test.d.ts +0 -2
- package/dist/__tests__/logic/getValidationModes.test.d.ts.map +0 -1
- package/dist/__tests__/logic/getValueAndMessage.test.d.ts +0 -2
- package/dist/__tests__/logic/getValueAndMessage.test.d.ts.map +0 -1
- package/dist/__tests__/logic/hasPromiseValidation.test.d.ts +0 -2
- package/dist/__tests__/logic/hasPromiseValidation.test.d.ts.map +0 -1
- package/dist/__tests__/logic/hasValidation.test.d.ts +0 -2
- package/dist/__tests__/logic/hasValidation.test.d.ts.map +0 -1
- package/dist/__tests__/logic/isNameInFieldArray.test.d.ts +0 -2
- package/dist/__tests__/logic/isNameInFieldArray.test.d.ts.map +0 -1
- package/dist/__tests__/logic/isWatched.test.d.ts +0 -2
- package/dist/__tests__/logic/isWatched.test.d.ts.map +0 -1
- package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts +0 -2
- package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts.map +0 -1
- package/dist/__tests__/logic/schemaErrorLookup.test.d.ts +0 -2
- package/dist/__tests__/logic/schemaErrorLookup.test.d.ts.map +0 -1
- package/dist/__tests__/logic/shouldRenderFormState.test.d.ts +0 -2
- package/dist/__tests__/logic/shouldRenderFormState.test.d.ts.map +0 -1
- package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts +0 -2
- package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts.map +0 -1
- package/dist/__tests__/logic/skipValidation.test.d.ts +0 -2
- package/dist/__tests__/logic/skipValidation.test.d.ts.map +0 -1
- package/dist/__tests__/logic/unsetEmptyArray.test.d.ts +0 -2
- package/dist/__tests__/logic/unsetEmptyArray.test.d.ts.map +0 -1
- package/dist/__tests__/logic/validateField.test.d.ts +0 -2
- package/dist/__tests__/logic/validateField.test.d.ts.map +0 -1
- package/dist/__tests__/type.test.d.ts +0 -2
- package/dist/__tests__/type.test.d.ts.map +0 -1
- package/dist/__tests__/useController.test.d.ts +0 -2
- package/dist/__tests__/useController.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/append.test.d.ts +0 -2
- package/dist/__tests__/useFieldArray/append.test.d.ts.map +0 -1
- package/dist/__tests__/useFieldArray/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/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
|
@@ -10,7 +10,11 @@ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => va
|
|
|
10
10
|
|
|
11
11
|
const EVENTS = {
|
|
12
12
|
BLUR: 'blur',
|
|
13
|
-
FOCUS_OUT: 'focusout'
|
|
13
|
+
FOCUS_OUT: 'focusout',
|
|
14
|
+
SUBMIT: 'submit',
|
|
15
|
+
TRIGGER: 'trigger',
|
|
16
|
+
VALID: 'valid',
|
|
17
|
+
};
|
|
14
18
|
const VALIDATION_MODE = {
|
|
15
19
|
onBlur: 'onBlur',
|
|
16
20
|
onChange: 'onChange',
|
|
@@ -27,6 +31,8 @@ const INPUT_VALIDATION_RULES = {
|
|
|
27
31
|
required: 'required',
|
|
28
32
|
validate: 'validate',
|
|
29
33
|
};
|
|
34
|
+
const ROOT_ERROR_TYPE = 'root';
|
|
35
|
+
const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
|
|
30
36
|
|
|
31
37
|
var isDateObject = (value) => value instanceof Date;
|
|
32
38
|
|
|
@@ -102,7 +108,11 @@ var createSubject = () => {
|
|
|
102
108
|
|
|
103
109
|
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
|
104
110
|
|
|
105
|
-
|
|
111
|
+
const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
|
|
112
|
+
function deepEqual(object1, object2, visited = new WeakMap()) {
|
|
113
|
+
if (object1 === object2) {
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
106
116
|
if (isPrimitive(object1) || isPrimitive(object2)) {
|
|
107
117
|
return Object.is(object1, object2);
|
|
108
118
|
}
|
|
@@ -114,22 +124,36 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
|
|
|
114
124
|
if (keys1.length !== keys2.length) {
|
|
115
125
|
return false;
|
|
116
126
|
}
|
|
117
|
-
if (
|
|
127
|
+
if (isEmptyObjectWithCustomPrototype(object1, keys1) ||
|
|
128
|
+
isEmptyObjectWithCustomPrototype(object2, keys2)) {
|
|
129
|
+
return Object.is(object1, object2);
|
|
130
|
+
}
|
|
131
|
+
if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
const visitedPairs = visited.get(object1);
|
|
135
|
+
if (visitedPairs && visitedPairs.has(object2)) {
|
|
118
136
|
return true;
|
|
119
137
|
}
|
|
120
|
-
|
|
121
|
-
|
|
138
|
+
if (visitedPairs) {
|
|
139
|
+
visitedPairs.add(object2);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
const ws = new WeakSet();
|
|
143
|
+
ws.add(object2);
|
|
144
|
+
visited.set(object1, ws);
|
|
145
|
+
}
|
|
122
146
|
for (const key of keys1) {
|
|
123
147
|
const val1 = object1[key];
|
|
124
|
-
if (!
|
|
148
|
+
if (!(key in object2)) {
|
|
125
149
|
return false;
|
|
126
150
|
}
|
|
127
151
|
if (key !== 'ref') {
|
|
128
152
|
const val2 = object2[key];
|
|
129
153
|
if ((isDateObject(val1) && isDateObject(val2)) ||
|
|
130
|
-
(isObject(val1)
|
|
131
|
-
|
|
132
|
-
? !deepEqual(val1, val2,
|
|
154
|
+
((isObject(val1) || Array.isArray(val1)) &&
|
|
155
|
+
(isObject(val2) || Array.isArray(val2)))
|
|
156
|
+
? !deepEqual(val1, val2, visited)
|
|
133
157
|
: !Object.is(val1, val2)) {
|
|
134
158
|
return false;
|
|
135
159
|
}
|
|
@@ -158,17 +182,43 @@ function extractFormValues(fieldsState, formValues) {
|
|
|
158
182
|
return values;
|
|
159
183
|
}
|
|
160
184
|
|
|
161
|
-
|
|
185
|
+
const flatten = (obj) => {
|
|
186
|
+
const output = {};
|
|
187
|
+
for (const key of Object.keys(obj)) {
|
|
188
|
+
if (isObjectType(obj[key]) &&
|
|
189
|
+
obj[key] !== null &&
|
|
190
|
+
!isDateObject(obj[key])) {
|
|
191
|
+
const nested = flatten(obj[key]);
|
|
192
|
+
for (const nestedKey of Object.keys(nested)) {
|
|
193
|
+
output[`${key}.${nestedKey}`] = nested[nestedKey];
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
output[key] = obj[key];
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return output;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const IS_KEY_RE = /^\w*$/;
|
|
204
|
+
var isKey = (value) => IS_KEY_RE.test(value);
|
|
162
205
|
|
|
163
206
|
var isUndefined = (val) => val === undefined;
|
|
164
207
|
|
|
165
|
-
|
|
208
|
+
const FIELD_PATH_RE = /[.[\]'"]/;
|
|
209
|
+
var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
|
|
166
210
|
|
|
167
211
|
var get = (object, path, defaultValue) => {
|
|
168
212
|
if (!path || !isObject(object)) {
|
|
169
213
|
return defaultValue;
|
|
170
214
|
}
|
|
171
|
-
const
|
|
215
|
+
const paths = isKey(path) ? [path] : stringToPath(path);
|
|
216
|
+
if (paths.some((key) => PROTOTYPE_KEYWORDS.includes(key))) {
|
|
217
|
+
return defaultValue;
|
|
218
|
+
}
|
|
219
|
+
const result = paths.reduce((result, key) => {
|
|
220
|
+
return isNullOrUndefined(result) ? undefined : result[key];
|
|
221
|
+
}, object);
|
|
172
222
|
return isUndefined(result) || result === object
|
|
173
223
|
? isUndefined(object[path])
|
|
174
224
|
? defaultValue
|
|
@@ -222,7 +272,7 @@ var set = (object, path, value) => {
|
|
|
222
272
|
? []
|
|
223
273
|
: {};
|
|
224
274
|
}
|
|
225
|
-
if (key
|
|
275
|
+
if (PROTOTYPE_KEYWORDS.includes(key)) {
|
|
226
276
|
return;
|
|
227
277
|
}
|
|
228
278
|
object[key] = newValue;
|
|
@@ -234,7 +284,12 @@ function baseGet(object, updatePath) {
|
|
|
234
284
|
const length = updatePath.slice(0, -1).length;
|
|
235
285
|
let index = 0;
|
|
236
286
|
while (index < length) {
|
|
237
|
-
|
|
287
|
+
if (isNullOrUndefined(object)) {
|
|
288
|
+
object = undefined;
|
|
289
|
+
break;
|
|
290
|
+
}
|
|
291
|
+
object = object[updatePath[index]];
|
|
292
|
+
index++;
|
|
238
293
|
}
|
|
239
294
|
return object;
|
|
240
295
|
}
|
|
@@ -247,11 +302,18 @@ function isEmptyArray(obj) {
|
|
|
247
302
|
return true;
|
|
248
303
|
}
|
|
249
304
|
function unset(object, path) {
|
|
305
|
+
if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
|
|
306
|
+
delete object[path];
|
|
307
|
+
return object;
|
|
308
|
+
}
|
|
250
309
|
const paths = Array.isArray(path)
|
|
251
310
|
? path
|
|
252
311
|
: isKey(path)
|
|
253
312
|
? [path]
|
|
254
313
|
: stringToPath(path);
|
|
314
|
+
if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
|
|
315
|
+
return object;
|
|
316
|
+
}
|
|
255
317
|
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
|
256
318
|
const index = paths.length - 1;
|
|
257
319
|
const key = paths[index];
|
|
@@ -304,6 +366,29 @@ function markFieldsDirty(data, fields = {}) {
|
|
|
304
366
|
}
|
|
305
367
|
return fields;
|
|
306
368
|
}
|
|
369
|
+
function pruneDirtyFields(value) {
|
|
370
|
+
if (value === false) {
|
|
371
|
+
return undefined;
|
|
372
|
+
}
|
|
373
|
+
if (value === true) {
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
if (Array.isArray(value)) {
|
|
377
|
+
const result = value.map((value) => pruneDirtyFields(value));
|
|
378
|
+
return (result.some((value) => value !== undefined) ? result : undefined);
|
|
379
|
+
}
|
|
380
|
+
if (isObject(value)) {
|
|
381
|
+
const result = {};
|
|
382
|
+
for (const key in value) {
|
|
383
|
+
const pruned = pruneDirtyFields(value[key]);
|
|
384
|
+
if (!isUndefined(pruned)) {
|
|
385
|
+
result[key] = pruned;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
return (Object.keys(result).length ? result : undefined);
|
|
389
|
+
}
|
|
390
|
+
return undefined;
|
|
391
|
+
}
|
|
307
392
|
function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
|
|
308
393
|
if (!dirtyFieldsFromValues) {
|
|
309
394
|
dirtyFieldsFromValues = markFieldsDirty(formValues);
|
|
@@ -323,7 +408,7 @@ function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
|
|
|
323
408
|
dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
|
|
324
409
|
}
|
|
325
410
|
}
|
|
326
|
-
return dirtyFieldsFromValues;
|
|
411
|
+
return pruneDirtyFields(dirtyFieldsFromValues) || {};
|
|
327
412
|
}
|
|
328
413
|
|
|
329
414
|
var getEventValue = (event) => isObject(event) && event.target
|
|
@@ -436,12 +521,22 @@ var getValidationModes = (mode) => ({
|
|
|
436
521
|
});
|
|
437
522
|
|
|
438
523
|
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
439
|
-
var hasPromiseValidation = (fieldReference) =>
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
524
|
+
var hasPromiseValidation = (fieldReference) => {
|
|
525
|
+
if (!fieldReference || !fieldReference.validate)
|
|
526
|
+
return false;
|
|
527
|
+
if (isFunction(fieldReference.validate)) {
|
|
528
|
+
return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
|
|
529
|
+
}
|
|
530
|
+
if (isObject(fieldReference.validate)) {
|
|
531
|
+
for (const key in fieldReference.validate) {
|
|
532
|
+
if (fieldReference.validate[key].constructor
|
|
533
|
+
.name === ASYNC_FUNCTION) {
|
|
534
|
+
return true;
|
|
535
|
+
}
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
return false;
|
|
539
|
+
};
|
|
445
540
|
|
|
446
541
|
var hasValidation = (options) => options.mount &&
|
|
447
542
|
(options.required ||
|
|
@@ -452,15 +547,21 @@ var hasValidation = (options) => options.mount &&
|
|
|
452
547
|
options.pattern ||
|
|
453
548
|
options.validate);
|
|
454
549
|
|
|
455
|
-
var
|
|
456
|
-
|
|
457
|
-
|
|
550
|
+
var isNameInFieldArray = (names, name) => name
|
|
551
|
+
.split('.')
|
|
552
|
+
.some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
|
|
458
553
|
|
|
459
|
-
var isWatched = (name, _names, isBlurEvent) =>
|
|
460
|
-
(
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
554
|
+
var isWatched = (name, _names, isBlurEvent) => {
|
|
555
|
+
if (isBlurEvent)
|
|
556
|
+
return false;
|
|
557
|
+
if (_names.watchAll || _names.watch.has(name))
|
|
558
|
+
return true;
|
|
559
|
+
for (const watchName of _names.watch) {
|
|
560
|
+
if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
|
|
561
|
+
return true;
|
|
562
|
+
}
|
|
563
|
+
return false;
|
|
564
|
+
};
|
|
464
565
|
|
|
465
566
|
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
|
466
567
|
for (const key of fieldsNames || Object.keys(fields)) {
|
|
@@ -528,9 +629,10 @@ function schemaErrorLookup(errors, _fields, name) {
|
|
|
528
629
|
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
529
630
|
updateFormState(formStateData);
|
|
530
631
|
const { name, ...formState } = formStateData;
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
Object.keys(
|
|
632
|
+
const keys = Object.keys(formState);
|
|
633
|
+
return (!keys.length ||
|
|
634
|
+
(isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
|
|
635
|
+
keys.find((key) => _proxyFormState[key] ===
|
|
534
636
|
(!isRoot || VALIDATION_MODE.all)));
|
|
535
637
|
};
|
|
536
638
|
|
|
@@ -539,7 +641,7 @@ var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
|
|
539
641
|
name === signalName ||
|
|
540
642
|
convertToArrayPayload(name).some((currentName) => currentName &&
|
|
541
643
|
(exact
|
|
542
|
-
? currentName === signalName
|
|
644
|
+
? currentName === signalName || currentName.startsWith(signalName + '.')
|
|
543
645
|
: currentName.startsWith(signalName) ||
|
|
544
646
|
signalName.startsWith(currentName)));
|
|
545
647
|
|
|
@@ -562,8 +664,9 @@ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode)
|
|
|
562
664
|
var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
|
|
563
665
|
|
|
564
666
|
var updateFieldArrayRootError = (errors, error, name) => {
|
|
565
|
-
const
|
|
566
|
-
|
|
667
|
+
const existingErrors = get(errors, name);
|
|
668
|
+
const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
|
|
669
|
+
set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
|
|
567
670
|
set(errors, name, fieldArrayErrors);
|
|
568
671
|
return errors;
|
|
569
672
|
};
|
|
@@ -596,7 +699,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
|
|
|
596
699
|
const inputRef = refs ? refs[0] : ref;
|
|
597
700
|
const setCustomValidity = (message) => {
|
|
598
701
|
if (shouldUseNativeValidation && inputRef.reportValidity) {
|
|
599
|
-
|
|
702
|
+
const validityMessage = isBoolean(message) ? '' : message || '';
|
|
703
|
+
if (refs) {
|
|
704
|
+
refs.forEach((ref) => ref.setCustomValidity(validityMessage));
|
|
705
|
+
}
|
|
706
|
+
else {
|
|
707
|
+
inputRef.setCustomValidity(validityMessage);
|
|
708
|
+
}
|
|
600
709
|
inputRef.reportValidity();
|
|
601
710
|
}
|
|
602
711
|
};
|
|
@@ -771,24 +880,28 @@ const defaultOptions = {
|
|
|
771
880
|
reValidateMode: VALIDATION_MODE.onChange,
|
|
772
881
|
shouldFocusError: true,
|
|
773
882
|
};
|
|
883
|
+
const FORM_ERROR_TYPE = 'form';
|
|
884
|
+
const DEFAULT_FORM_STATE = {
|
|
885
|
+
submitCount: 0,
|
|
886
|
+
isDirty: false,
|
|
887
|
+
isReady: false,
|
|
888
|
+
isValidating: false,
|
|
889
|
+
isSubmitted: false,
|
|
890
|
+
isSubmitting: false,
|
|
891
|
+
isSubmitSuccessful: false,
|
|
892
|
+
isValid: false,
|
|
893
|
+
touchedFields: {},
|
|
894
|
+
dirtyFields: {},
|
|
895
|
+
validatingFields: {},
|
|
896
|
+
};
|
|
774
897
|
function createFormControl(props = {}) {
|
|
775
898
|
let _options = {
|
|
776
899
|
...defaultOptions,
|
|
777
900
|
...props,
|
|
778
901
|
};
|
|
779
902
|
let _formState = {
|
|
780
|
-
|
|
781
|
-
isDirty: false,
|
|
782
|
-
isReady: false,
|
|
903
|
+
...cloneObject(DEFAULT_FORM_STATE),
|
|
783
904
|
isLoading: isFunction(_options.defaultValues),
|
|
784
|
-
isValidating: false,
|
|
785
|
-
isSubmitted: false,
|
|
786
|
-
isSubmitting: false,
|
|
787
|
-
isSubmitSuccessful: false,
|
|
788
|
-
isValid: false,
|
|
789
|
-
touchedFields: {},
|
|
790
|
-
dirtyFields: {},
|
|
791
|
-
validatingFields: {},
|
|
792
905
|
errors: _options.errors || {},
|
|
793
906
|
disabled: _options.disabled || false,
|
|
794
907
|
};
|
|
@@ -811,9 +924,13 @@ function createFormControl(props = {}) {
|
|
|
811
924
|
unMount: new Set(),
|
|
812
925
|
array: new Set(),
|
|
813
926
|
watch: new Set(),
|
|
927
|
+
registerName: new Set(),
|
|
814
928
|
};
|
|
815
929
|
let delayErrorCallback;
|
|
816
930
|
let timer = 0;
|
|
931
|
+
let _valuesSubscriberCount = 0;
|
|
932
|
+
let _validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
933
|
+
let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
817
934
|
const defaultProxyFormState = {
|
|
818
935
|
isDirty: false,
|
|
819
936
|
dirtyFields: false,
|
|
@@ -852,7 +969,11 @@ function createFormControl(props = {}) {
|
|
|
852
969
|
_updateIsValidating();
|
|
853
970
|
}
|
|
854
971
|
else {
|
|
855
|
-
isValid = await executeBuiltInValidation(
|
|
972
|
+
isValid = await executeBuiltInValidation({
|
|
973
|
+
fields: _fields,
|
|
974
|
+
onlyCheckValid: true,
|
|
975
|
+
eventType: EVENTS.VALID,
|
|
976
|
+
});
|
|
856
977
|
}
|
|
857
978
|
if (isValid !== _formState.isValid) {
|
|
858
979
|
_subjects.state.next({
|
|
@@ -880,6 +1001,9 @@ function createFormControl(props = {}) {
|
|
|
880
1001
|
});
|
|
881
1002
|
}
|
|
882
1003
|
};
|
|
1004
|
+
const _updateDirtyFields = () => {
|
|
1005
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
|
|
1006
|
+
};
|
|
883
1007
|
const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
|
|
884
1008
|
if (args && method && !_options.disabled) {
|
|
885
1009
|
_state.action = true;
|
|
@@ -901,7 +1025,7 @@ function createFormControl(props = {}) {
|
|
|
901
1025
|
shouldSetValues && set(_formState.touchedFields, name, touchedFields);
|
|
902
1026
|
}
|
|
903
1027
|
if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
|
|
904
|
-
|
|
1028
|
+
_updateDirtyFields();
|
|
905
1029
|
}
|
|
906
1030
|
_subjects.state.next({
|
|
907
1031
|
name,
|
|
@@ -917,6 +1041,7 @@ function createFormControl(props = {}) {
|
|
|
917
1041
|
};
|
|
918
1042
|
const updateErrors = (name, error) => {
|
|
919
1043
|
set(_formState.errors, name, error);
|
|
1044
|
+
_formState.errors = { ..._formState.errors };
|
|
920
1045
|
_subjects.state.next({
|
|
921
1046
|
errors: _formState.errors,
|
|
922
1047
|
});
|
|
@@ -928,16 +1053,53 @@ function createFormControl(props = {}) {
|
|
|
928
1053
|
isValid: false,
|
|
929
1054
|
});
|
|
930
1055
|
};
|
|
1056
|
+
const hasExplicitNullIntermediate = (name) => {
|
|
1057
|
+
const segments = isKey(name) ? [name] : stringToPath(name);
|
|
1058
|
+
let formValues = _formValues;
|
|
1059
|
+
let defaultValues = _defaultValues;
|
|
1060
|
+
for (let i = 0; i < segments.length - 1; i++) {
|
|
1061
|
+
const key = segments[i];
|
|
1062
|
+
formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
|
|
1063
|
+
defaultValues = isNullOrUndefined(defaultValues)
|
|
1064
|
+
? defaultValues
|
|
1065
|
+
: defaultValues[key];
|
|
1066
|
+
if (formValues === null && defaultValues !== null) {
|
|
1067
|
+
return true;
|
|
1068
|
+
}
|
|
1069
|
+
}
|
|
1070
|
+
return false;
|
|
1071
|
+
};
|
|
931
1072
|
const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
|
|
932
1073
|
const field = get(_fields, name);
|
|
933
1074
|
if (field) {
|
|
1075
|
+
if (hasExplicitNullIntermediate(name)) {
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
const wasUnsetInFormValues = isUndefined(get(_formValues, name));
|
|
934
1079
|
const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
|
|
935
1080
|
isUndefined(defaultValue) ||
|
|
936
1081
|
(ref && ref.defaultChecked) ||
|
|
937
1082
|
shouldSkipSetValueAs
|
|
938
1083
|
? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
|
|
939
1084
|
: setFieldValue(name, defaultValue);
|
|
940
|
-
_state.mount && !_state.action
|
|
1085
|
+
if (_state.mount && !_state.action) {
|
|
1086
|
+
_setValid();
|
|
1087
|
+
if (wasUnsetInFormValues &&
|
|
1088
|
+
_formState.isDirty &&
|
|
1089
|
+
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
|
|
1090
|
+
const isDirty = _getDirty();
|
|
1091
|
+
if (!isDirty) {
|
|
1092
|
+
_formState.isDirty = false;
|
|
1093
|
+
_subjects.state.next({ ..._formState });
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
if (props.shouldUnregister &&
|
|
1097
|
+
wasUnsetInFormValues &&
|
|
1098
|
+
!isUndefined(get(_formValues, name)) &&
|
|
1099
|
+
isWatched(name, _names)) {
|
|
1100
|
+
_state.watch = true;
|
|
1101
|
+
}
|
|
1102
|
+
}
|
|
941
1103
|
}
|
|
942
1104
|
};
|
|
943
1105
|
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
|
@@ -948,16 +1110,22 @@ function createFormControl(props = {}) {
|
|
|
948
1110
|
};
|
|
949
1111
|
if (!_options.disabled) {
|
|
950
1112
|
if (!isBlurEvent || shouldDirty) {
|
|
1113
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
951
1114
|
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
952
1115
|
isPreviousDirty = _formState.isDirty;
|
|
953
|
-
_formState.isDirty = output.isDirty =
|
|
1116
|
+
_formState.isDirty = output.isDirty =
|
|
1117
|
+
!isCurrentFieldPristine || _getDirty();
|
|
954
1118
|
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
955
1119
|
}
|
|
956
|
-
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
957
1120
|
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
958
|
-
isCurrentFieldPristine
|
|
959
|
-
|
|
960
|
-
|
|
1121
|
+
if (isCurrentFieldPristine !== _formState.isDirty) {
|
|
1122
|
+
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
|
|
1123
|
+
}
|
|
1124
|
+
else {
|
|
1125
|
+
isCurrentFieldPristine
|
|
1126
|
+
? unset(_formState.dirtyFields, name)
|
|
1127
|
+
: set(_formState.dirtyFields, name, true);
|
|
1128
|
+
}
|
|
961
1129
|
output.dirtyFields = _formState.dirtyFields;
|
|
962
1130
|
shouldUpdateField =
|
|
963
1131
|
shouldUpdateField ||
|
|
@@ -996,6 +1164,7 @@ function createFormControl(props = {}) {
|
|
|
996
1164
|
error
|
|
997
1165
|
? set(_formState.errors, name, error)
|
|
998
1166
|
: unset(_formState.errors, name);
|
|
1167
|
+
_formState.errors = { ..._formState.errors };
|
|
999
1168
|
}
|
|
1000
1169
|
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
|
1001
1170
|
!isEmptyObject(fieldState) ||
|
|
@@ -1015,8 +1184,7 @@ function createFormControl(props = {}) {
|
|
|
1015
1184
|
};
|
|
1016
1185
|
const _runSchema = async (name) => {
|
|
1017
1186
|
_updateIsValidating(name, true);
|
|
1018
|
-
|
|
1019
|
-
return result;
|
|
1187
|
+
return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
|
|
1020
1188
|
};
|
|
1021
1189
|
const executeSchemaAndUpdateState = async (names) => {
|
|
1022
1190
|
const { errors } = await _runSchema(names);
|
|
@@ -1025,18 +1193,69 @@ function createFormControl(props = {}) {
|
|
|
1025
1193
|
for (const name of names) {
|
|
1026
1194
|
const error = get(errors, name);
|
|
1027
1195
|
error
|
|
1028
|
-
?
|
|
1196
|
+
? _names.array.has(name) &&
|
|
1197
|
+
isObject(error) &&
|
|
1198
|
+
!Object.keys(error).some((key) => !Number.isNaN(Number(key)))
|
|
1199
|
+
? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
|
|
1200
|
+
: set(_formState.errors, name, error)
|
|
1029
1201
|
: unset(_formState.errors, name);
|
|
1030
1202
|
}
|
|
1203
|
+
_formState.errors = { ..._formState.errors };
|
|
1031
1204
|
}
|
|
1032
1205
|
else {
|
|
1033
1206
|
_formState.errors = errors;
|
|
1034
1207
|
}
|
|
1035
1208
|
return errors;
|
|
1036
1209
|
};
|
|
1037
|
-
const
|
|
1210
|
+
const validateForm = async ({ name, eventType, }) => {
|
|
1211
|
+
if (props.validate) {
|
|
1212
|
+
const result = await props.validate({
|
|
1213
|
+
formValues: _formValues,
|
|
1214
|
+
formState: _formState,
|
|
1215
|
+
name,
|
|
1216
|
+
eventType,
|
|
1217
|
+
});
|
|
1218
|
+
if (isObject(result)) {
|
|
1219
|
+
for (const key in result) {
|
|
1220
|
+
const error = result[key];
|
|
1221
|
+
if (error) {
|
|
1222
|
+
setError(`${FORM_ERROR_TYPE}.${key}`, {
|
|
1223
|
+
message: isString(error.message) ? error.message : '',
|
|
1224
|
+
type: error.type || INPUT_VALIDATION_RULES.validate,
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
else if (isString(result) || !result) {
|
|
1230
|
+
setError(FORM_ERROR_TYPE, {
|
|
1231
|
+
message: result || '',
|
|
1232
|
+
type: INPUT_VALIDATION_RULES.validate,
|
|
1233
|
+
});
|
|
1234
|
+
}
|
|
1235
|
+
else {
|
|
1236
|
+
clearErrors(FORM_ERROR_TYPE);
|
|
1237
|
+
}
|
|
1238
|
+
return result;
|
|
1239
|
+
}
|
|
1240
|
+
return true;
|
|
1241
|
+
};
|
|
1242
|
+
const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
|
|
1038
1243
|
valid: true,
|
|
1039
|
-
|
|
1244
|
+
runRootValidation: false,
|
|
1245
|
+
}, }) => {
|
|
1246
|
+
if (props.validate) {
|
|
1247
|
+
context.runRootValidation = true;
|
|
1248
|
+
const result = await validateForm({
|
|
1249
|
+
name,
|
|
1250
|
+
eventType,
|
|
1251
|
+
});
|
|
1252
|
+
if (!result) {
|
|
1253
|
+
context.valid = false;
|
|
1254
|
+
if (onlyCheckValid) {
|
|
1255
|
+
return context.valid;
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1040
1259
|
for (const name in fields) {
|
|
1041
1260
|
const field = fields[name];
|
|
1042
1261
|
if (field) {
|
|
@@ -1044,28 +1263,41 @@ function createFormControl(props = {}) {
|
|
|
1044
1263
|
if (_f) {
|
|
1045
1264
|
const isFieldArrayRoot = _names.array.has(_f.name);
|
|
1046
1265
|
const isPromiseFunction = field._f && hasPromiseValidation(field._f);
|
|
1047
|
-
|
|
1266
|
+
const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
|
|
1267
|
+
_proxyFormState.isValidating ||
|
|
1268
|
+
_proxySubscribeFormState.validatingFields ||
|
|
1269
|
+
_proxySubscribeFormState.isValidating;
|
|
1270
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
1048
1271
|
_updateIsValidating([_f.name], true);
|
|
1049
1272
|
}
|
|
1050
|
-
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !
|
|
1051
|
-
if (isPromiseFunction &&
|
|
1273
|
+
const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
|
|
1274
|
+
if (isPromiseFunction && shouldTrackIsValidatingState) {
|
|
1052
1275
|
_updateIsValidating([_f.name]);
|
|
1053
1276
|
}
|
|
1054
1277
|
if (fieldError[_f.name]) {
|
|
1055
1278
|
context.valid = false;
|
|
1056
|
-
if (
|
|
1279
|
+
if (onlyCheckValid) {
|
|
1057
1280
|
break;
|
|
1058
1281
|
}
|
|
1059
1282
|
}
|
|
1060
|
-
!
|
|
1283
|
+
!onlyCheckValid &&
|
|
1061
1284
|
(get(fieldError, _f.name)
|
|
1062
1285
|
? isFieldArrayRoot
|
|
1063
1286
|
? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
|
|
1064
1287
|
: set(_formState.errors, _f.name, fieldError[_f.name])
|
|
1065
1288
|
: unset(_formState.errors, _f.name));
|
|
1289
|
+
if (props.shouldUseNativeValidation && fieldError[_f.name]) {
|
|
1290
|
+
break;
|
|
1291
|
+
}
|
|
1066
1292
|
}
|
|
1067
1293
|
!isEmptyObject(fieldValue) &&
|
|
1068
|
-
(await executeBuiltInValidation(
|
|
1294
|
+
(await executeBuiltInValidation({
|
|
1295
|
+
context,
|
|
1296
|
+
onlyCheckValid,
|
|
1297
|
+
fields: fieldValue,
|
|
1298
|
+
name: name,
|
|
1299
|
+
eventType,
|
|
1300
|
+
}));
|
|
1069
1301
|
}
|
|
1070
1302
|
}
|
|
1071
1303
|
return context.valid;
|
|
@@ -1083,7 +1315,7 @@ function createFormControl(props = {}) {
|
|
|
1083
1315
|
};
|
|
1084
1316
|
const _getDirty = (name, data) => !_options.disabled &&
|
|
1085
1317
|
(name && data && set(_formValues, name, data),
|
|
1086
|
-
!deepEqual(
|
|
1318
|
+
!deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
|
|
1087
1319
|
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
|
1088
1320
|
...(_state.mount
|
|
1089
1321
|
? _formValues
|
|
@@ -1094,7 +1326,7 @@ function createFormControl(props = {}) {
|
|
|
1094
1326
|
: defaultValue),
|
|
1095
1327
|
}, isGlobal, defaultValue);
|
|
1096
1328
|
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
|
1097
|
-
const setFieldValue = (name, value, options = {}) => {
|
|
1329
|
+
const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
|
|
1098
1330
|
const field = get(_fields, name);
|
|
1099
1331
|
let fieldValue = value;
|
|
1100
1332
|
if (field) {
|
|
@@ -1132,20 +1364,20 @@ function createFormControl(props = {}) {
|
|
|
1132
1364
|
}
|
|
1133
1365
|
else {
|
|
1134
1366
|
fieldReference.ref.value = fieldValue;
|
|
1135
|
-
if (!fieldReference.ref.type) {
|
|
1367
|
+
if (!fieldReference.ref.type && !skipRender) {
|
|
1136
1368
|
_subjects.state.next({
|
|
1137
1369
|
name,
|
|
1138
|
-
values: cloneObject(_formValues),
|
|
1370
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
1139
1371
|
});
|
|
1140
1372
|
}
|
|
1141
1373
|
}
|
|
1142
1374
|
}
|
|
1143
1375
|
}
|
|
1144
1376
|
(options.shouldDirty || options.shouldTouch) &&
|
|
1145
|
-
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty,
|
|
1377
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
|
|
1146
1378
|
options.shouldValidate && trigger(name);
|
|
1147
1379
|
};
|
|
1148
|
-
const
|
|
1380
|
+
const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
|
|
1149
1381
|
for (const fieldKey in value) {
|
|
1150
1382
|
if (!value.hasOwnProperty(fieldKey)) {
|
|
1151
1383
|
return;
|
|
@@ -1157,49 +1389,84 @@ function createFormControl(props = {}) {
|
|
|
1157
1389
|
isObject(fieldValue) ||
|
|
1158
1390
|
(field && !field._f)) &&
|
|
1159
1391
|
!isDateObject(fieldValue)
|
|
1160
|
-
?
|
|
1161
|
-
: setFieldValue(fieldName, fieldValue, options);
|
|
1392
|
+
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
1393
|
+
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
1162
1394
|
}
|
|
1163
1395
|
};
|
|
1164
|
-
const
|
|
1396
|
+
const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
|
|
1165
1397
|
const field = get(_fields, name);
|
|
1166
1398
|
const isFieldArray = _names.array.has(name);
|
|
1167
|
-
const cloneValue = cloneObject(value);
|
|
1168
|
-
|
|
1399
|
+
const cloneValue = skipClone ? value : cloneObject(value);
|
|
1400
|
+
const previousValue = get(_formValues, name);
|
|
1401
|
+
const isValueUnchanged = deepEqual(previousValue, cloneValue);
|
|
1402
|
+
if (!isValueUnchanged) {
|
|
1403
|
+
set(_formValues, name, cloneValue);
|
|
1404
|
+
}
|
|
1169
1405
|
if (isFieldArray) {
|
|
1170
1406
|
_subjects.array.next({
|
|
1171
1407
|
name,
|
|
1172
|
-
values: cloneObject(_formValues),
|
|
1408
|
+
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
1173
1409
|
});
|
|
1174
1410
|
if ((_proxyFormState.isDirty ||
|
|
1175
1411
|
_proxyFormState.dirtyFields ||
|
|
1176
1412
|
_proxySubscribeFormState.isDirty ||
|
|
1177
1413
|
_proxySubscribeFormState.dirtyFields) &&
|
|
1178
1414
|
options.shouldDirty) {
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1415
|
+
_updateDirtyFields();
|
|
1416
|
+
if (!skipStateEmit) {
|
|
1417
|
+
_subjects.state.next({
|
|
1418
|
+
name,
|
|
1419
|
+
dirtyFields: _formState.dirtyFields,
|
|
1420
|
+
isDirty: _getDirty(name, cloneValue),
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1184
1423
|
}
|
|
1185
1424
|
}
|
|
1186
1425
|
else {
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1426
|
+
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
1427
|
+
isEmptyObject(cloneValue);
|
|
1428
|
+
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
1429
|
+
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
1430
|
+
}
|
|
1431
|
+
else {
|
|
1432
|
+
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
1433
|
+
}
|
|
1190
1434
|
}
|
|
1191
|
-
if (
|
|
1435
|
+
if (!isValueUnchanged && !skipStateEmit) {
|
|
1436
|
+
const watched = isWatched(name, _names);
|
|
1437
|
+
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
1192
1438
|
_subjects.state.next({
|
|
1193
|
-
..._formState,
|
|
1194
|
-
name,
|
|
1195
|
-
values
|
|
1439
|
+
...(watched && _formState),
|
|
1440
|
+
name: _state.mount || watched ? name : undefined,
|
|
1441
|
+
values,
|
|
1196
1442
|
});
|
|
1197
1443
|
}
|
|
1198
|
-
|
|
1444
|
+
};
|
|
1445
|
+
const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
|
|
1446
|
+
const setValues = (formValues, options = {}) => {
|
|
1447
|
+
const updatedFormValues = isFunction(formValues)
|
|
1448
|
+
? formValues(_formValues)
|
|
1449
|
+
: formValues;
|
|
1450
|
+
if (!deepEqual(_formValues, updatedFormValues)) {
|
|
1451
|
+
_formValues = {
|
|
1452
|
+
..._formValues,
|
|
1453
|
+
...updatedFormValues,
|
|
1454
|
+
};
|
|
1455
|
+
const flattenedUpdates = flatten(updatedFormValues);
|
|
1456
|
+
for (const fieldName of _names.mount) {
|
|
1457
|
+
if (fieldName in flattenedUpdates) {
|
|
1458
|
+
_setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1199
1461
|
_subjects.state.next({
|
|
1200
|
-
|
|
1201
|
-
|
|
1462
|
+
..._formState,
|
|
1463
|
+
name: undefined,
|
|
1464
|
+
type: undefined,
|
|
1465
|
+
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
1202
1466
|
});
|
|
1467
|
+
if (options.shouldValidate) {
|
|
1468
|
+
_setValid();
|
|
1469
|
+
}
|
|
1203
1470
|
}
|
|
1204
1471
|
};
|
|
1205
1472
|
const onChange = async (event) => {
|
|
@@ -1214,8 +1481,6 @@ function createFormControl(props = {}) {
|
|
|
1214
1481
|
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
1215
1482
|
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
1216
1483
|
};
|
|
1217
|
-
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
1218
|
-
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1219
1484
|
if (field) {
|
|
1220
1485
|
let error;
|
|
1221
1486
|
let isValid;
|
|
@@ -1223,11 +1488,13 @@ function createFormControl(props = {}) {
|
|
|
1223
1488
|
? getFieldValue(field._f)
|
|
1224
1489
|
: getEventValue(event);
|
|
1225
1490
|
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
1226
|
-
const
|
|
1491
|
+
const hasNoValidationEffect = !hasValidation(field._f) &&
|
|
1492
|
+
!props.validate &&
|
|
1227
1493
|
!_options.resolver &&
|
|
1228
1494
|
!get(_formState.errors, name) &&
|
|
1229
|
-
!field._f.deps
|
|
1230
|
-
|
|
1495
|
+
!field._f.deps;
|
|
1496
|
+
const shouldSkipValidation = hasNoValidationEffect ||
|
|
1497
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
|
|
1231
1498
|
const watched = isWatched(name, _names, isBlurEvent);
|
|
1232
1499
|
set(_formValues, name, fieldValue);
|
|
1233
1500
|
if (isBlurEvent) {
|
|
@@ -1245,10 +1512,13 @@ function createFormControl(props = {}) {
|
|
|
1245
1512
|
_subjects.state.next({
|
|
1246
1513
|
name,
|
|
1247
1514
|
type: event.type,
|
|
1248
|
-
|
|
1515
|
+
...(_valuesSubscriberCount
|
|
1516
|
+
? { values: cloneObject(_formValues) }
|
|
1517
|
+
: {}),
|
|
1249
1518
|
});
|
|
1250
1519
|
if (shouldSkipValidation) {
|
|
1251
|
-
if (
|
|
1520
|
+
if ((!hasNoValidationEffect || !_formState.isValid) &&
|
|
1521
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
|
|
1252
1522
|
if (_options.mode === 'onBlur') {
|
|
1253
1523
|
if (isBlurEvent) {
|
|
1254
1524
|
_setValid();
|
|
@@ -1261,18 +1531,26 @@ function createFormControl(props = {}) {
|
|
|
1261
1531
|
return (shouldRender &&
|
|
1262
1532
|
_subjects.state.next({ name, ...(watched ? {} : fieldState) }));
|
|
1263
1533
|
}
|
|
1534
|
+
if (!_options.resolver && props.validate) {
|
|
1535
|
+
await validateForm({
|
|
1536
|
+
name: name,
|
|
1537
|
+
eventType: event.type,
|
|
1538
|
+
});
|
|
1539
|
+
}
|
|
1264
1540
|
!isBlurEvent && watched && _subjects.state.next({ ..._formState });
|
|
1265
1541
|
if (_options.resolver) {
|
|
1266
1542
|
const { errors } = await _runSchema([name]);
|
|
1267
1543
|
_updateIsValidating([name]);
|
|
1268
1544
|
_updateIsFieldValueUpdated(fieldValue);
|
|
1269
|
-
if (isFieldValueUpdated) {
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
error = errorLookupResult.error;
|
|
1273
|
-
name = errorLookupResult.name;
|
|
1274
|
-
isValid = isEmptyObject(errors);
|
|
1545
|
+
if (!isFieldValueUpdated) {
|
|
1546
|
+
!isEmptyObject(fieldState) && _subjects.state.next(fieldState);
|
|
1547
|
+
return;
|
|
1275
1548
|
}
|
|
1549
|
+
const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
|
|
1550
|
+
const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
|
|
1551
|
+
error = errorLookupResult.error;
|
|
1552
|
+
name = errorLookupResult.name;
|
|
1553
|
+
isValid = isEmptyObject(errors);
|
|
1276
1554
|
}
|
|
1277
1555
|
else {
|
|
1278
1556
|
_updateIsValidating([name], true);
|
|
@@ -1285,7 +1563,12 @@ function createFormControl(props = {}) {
|
|
|
1285
1563
|
}
|
|
1286
1564
|
else if (_proxyFormState.isValid ||
|
|
1287
1565
|
_proxySubscribeFormState.isValid) {
|
|
1288
|
-
isValid = await executeBuiltInValidation(
|
|
1566
|
+
isValid = await executeBuiltInValidation({
|
|
1567
|
+
fields: _fields,
|
|
1568
|
+
onlyCheckValid: true,
|
|
1569
|
+
name: name,
|
|
1570
|
+
eventType: event.type,
|
|
1571
|
+
});
|
|
1289
1572
|
}
|
|
1290
1573
|
}
|
|
1291
1574
|
}
|
|
@@ -1318,12 +1601,19 @@ function createFormControl(props = {}) {
|
|
|
1318
1601
|
else if (name) {
|
|
1319
1602
|
validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
|
|
1320
1603
|
const field = get(_fields, fieldName);
|
|
1321
|
-
return await executeBuiltInValidation(
|
|
1604
|
+
return await executeBuiltInValidation({
|
|
1605
|
+
fields: field && field._f ? { [fieldName]: field } : field,
|
|
1606
|
+
eventType: EVENTS.TRIGGER,
|
|
1607
|
+
});
|
|
1322
1608
|
}))).every(Boolean);
|
|
1323
1609
|
!(!validationResult && !_formState.isValid) && _setValid();
|
|
1324
1610
|
}
|
|
1325
1611
|
else {
|
|
1326
|
-
validationResult = isValid = await executeBuiltInValidation(
|
|
1612
|
+
validationResult = isValid = await executeBuiltInValidation({
|
|
1613
|
+
fields: _fields,
|
|
1614
|
+
name,
|
|
1615
|
+
eventType: EVENTS.TRIGGER,
|
|
1616
|
+
});
|
|
1327
1617
|
}
|
|
1328
1618
|
_subjects.state.next({
|
|
1329
1619
|
...(!isString(name) ||
|
|
@@ -1360,16 +1650,25 @@ function createFormControl(props = {}) {
|
|
|
1360
1650
|
isTouched: !!get((formState || _formState).touchedFields, name),
|
|
1361
1651
|
});
|
|
1362
1652
|
const clearErrors = (name) => {
|
|
1363
|
-
name
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1653
|
+
const names = name ? convertToArrayPayload(name) : undefined;
|
|
1654
|
+
names?.forEach((inputName) => unset(_formState.errors, inputName));
|
|
1655
|
+
if (names) {
|
|
1656
|
+
names.forEach((inputName) => {
|
|
1657
|
+
_subjects.state.next({
|
|
1658
|
+
name: inputName,
|
|
1659
|
+
errors: _formState.errors,
|
|
1660
|
+
});
|
|
1661
|
+
});
|
|
1662
|
+
}
|
|
1663
|
+
else {
|
|
1664
|
+
_subjects.state.next({
|
|
1665
|
+
errors: {},
|
|
1666
|
+
});
|
|
1667
|
+
}
|
|
1368
1668
|
};
|
|
1369
1669
|
const setError = (name, error, options) => {
|
|
1370
1670
|
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
1371
1671
|
const currentError = get(_formState.errors, name) || {};
|
|
1372
|
-
// Don't override existing error messages elsewhere in the object tree.
|
|
1373
1672
|
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
1374
1673
|
set(_formState.errors, name, {
|
|
1375
1674
|
...restOfErrorTree,
|
|
@@ -1383,20 +1682,59 @@ function createFormControl(props = {}) {
|
|
|
1383
1682
|
});
|
|
1384
1683
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
1385
1684
|
};
|
|
1386
|
-
const watch = (name, defaultValue) =>
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1685
|
+
const watch = (name, defaultValue) => {
|
|
1686
|
+
if (isFunction(name)) {
|
|
1687
|
+
_valuesSubscriberCount++;
|
|
1688
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
1689
|
+
next: (payload) => 'values' in payload &&
|
|
1690
|
+
name(payload.values || _getWatch(undefined, defaultValue), payload),
|
|
1691
|
+
});
|
|
1692
|
+
let called = false;
|
|
1693
|
+
return {
|
|
1694
|
+
unsubscribe: () => {
|
|
1695
|
+
if (called) {
|
|
1696
|
+
return;
|
|
1697
|
+
}
|
|
1698
|
+
called = true;
|
|
1699
|
+
_valuesSubscriberCount--;
|
|
1700
|
+
unsubscribe();
|
|
1701
|
+
},
|
|
1702
|
+
};
|
|
1703
|
+
}
|
|
1704
|
+
return _getWatch(name, defaultValue, true);
|
|
1705
|
+
};
|
|
1706
|
+
const _subscribe = (props) => {
|
|
1707
|
+
const needsValues = !!props.formState?.values;
|
|
1708
|
+
if (needsValues) {
|
|
1709
|
+
_valuesSubscriberCount++;
|
|
1710
|
+
}
|
|
1711
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
1712
|
+
next: (formState) => {
|
|
1713
|
+
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
1714
|
+
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
1715
|
+
const snapshot = { ..._formValues };
|
|
1716
|
+
props.callback({
|
|
1717
|
+
values: snapshot,
|
|
1718
|
+
..._formState,
|
|
1719
|
+
...formState,
|
|
1720
|
+
defaultValues: _defaultValues,
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
},
|
|
1724
|
+
});
|
|
1725
|
+
if (!needsValues) {
|
|
1726
|
+
return unsubscribe;
|
|
1727
|
+
}
|
|
1728
|
+
let called = false;
|
|
1729
|
+
return () => {
|
|
1730
|
+
if (called) {
|
|
1731
|
+
return;
|
|
1397
1732
|
}
|
|
1398
|
-
|
|
1399
|
-
|
|
1733
|
+
called = true;
|
|
1734
|
+
_valuesSubscriberCount--;
|
|
1735
|
+
unsubscribe();
|
|
1736
|
+
};
|
|
1737
|
+
};
|
|
1400
1738
|
const subscribe = (props) => {
|
|
1401
1739
|
_state.mount = true;
|
|
1402
1740
|
_proxySubscribeFormState = {
|
|
@@ -1451,6 +1789,7 @@ function createFormControl(props = {}) {
|
|
|
1451
1789
|
const register = (name, options = {}) => {
|
|
1452
1790
|
let field = get(_fields, name);
|
|
1453
1791
|
const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
|
|
1792
|
+
const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
|
|
1454
1793
|
set(_fields, name, {
|
|
1455
1794
|
...(field || {}),
|
|
1456
1795
|
_f: {
|
|
@@ -1461,7 +1800,7 @@ function createFormControl(props = {}) {
|
|
|
1461
1800
|
},
|
|
1462
1801
|
});
|
|
1463
1802
|
_names.mount.add(name);
|
|
1464
|
-
if (field) {
|
|
1803
|
+
if (field && !shouldRevalidateRemount) {
|
|
1465
1804
|
_setDisabledField({
|
|
1466
1805
|
disabled: isBoolean(options.disabled)
|
|
1467
1806
|
? options.disabled
|
|
@@ -1491,7 +1830,9 @@ function createFormControl(props = {}) {
|
|
|
1491
1830
|
onBlur: onChange,
|
|
1492
1831
|
ref: (ref) => {
|
|
1493
1832
|
if (ref) {
|
|
1833
|
+
_names.registerName.add(name);
|
|
1494
1834
|
register(name, options);
|
|
1835
|
+
_names.registerName.delete(name);
|
|
1495
1836
|
field = get(_fields, name);
|
|
1496
1837
|
const fieldRef = isUndefined(ref.value)
|
|
1497
1838
|
? ref.querySelectorAll
|
|
@@ -1535,6 +1876,7 @@ function createFormControl(props = {}) {
|
|
|
1535
1876
|
};
|
|
1536
1877
|
};
|
|
1537
1878
|
const _focusError = () => _options.shouldFocusError &&
|
|
1879
|
+
!_options.shouldUseNativeValidation &&
|
|
1538
1880
|
iterateFieldsByAction(_fields, _focusInput, _names.mount);
|
|
1539
1881
|
const _disableForm = (disabled) => {
|
|
1540
1882
|
if (isBoolean(disabled)) {
|
|
@@ -1570,14 +1912,17 @@ function createFormControl(props = {}) {
|
|
|
1570
1912
|
fieldValues = cloneObject(values);
|
|
1571
1913
|
}
|
|
1572
1914
|
else {
|
|
1573
|
-
await executeBuiltInValidation(
|
|
1915
|
+
await executeBuiltInValidation({
|
|
1916
|
+
fields: _fields,
|
|
1917
|
+
eventType: EVENTS.SUBMIT,
|
|
1918
|
+
});
|
|
1574
1919
|
}
|
|
1575
1920
|
if (_names.disabled.size) {
|
|
1576
1921
|
for (const name of _names.disabled) {
|
|
1577
1922
|
unset(fieldValues, name);
|
|
1578
1923
|
}
|
|
1579
1924
|
}
|
|
1580
|
-
unset(_formState.errors,
|
|
1925
|
+
unset(_formState.errors, ROOT_ERROR_TYPE);
|
|
1581
1926
|
if (isEmptyObject(_formState.errors)) {
|
|
1582
1927
|
_subjects.state.next({
|
|
1583
1928
|
errors: {},
|
|
@@ -1636,7 +1981,7 @@ function createFormControl(props = {}) {
|
|
|
1636
1981
|
const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
|
|
1637
1982
|
const cloneUpdatedValues = cloneObject(updatedValues);
|
|
1638
1983
|
const isEmptyResetValues = isEmptyObject(formValues);
|
|
1639
|
-
const values =
|
|
1984
|
+
const values = cloneUpdatedValues;
|
|
1640
1985
|
if (!keepStateOptions.keepDefaultValues) {
|
|
1641
1986
|
_defaultValues = updatedValues;
|
|
1642
1987
|
}
|
|
@@ -1685,15 +2030,25 @@ function createFormControl(props = {}) {
|
|
|
1685
2030
|
_fields = {};
|
|
1686
2031
|
}
|
|
1687
2032
|
}
|
|
1688
|
-
|
|
1689
|
-
|
|
2033
|
+
if (_options.shouldUnregister) {
|
|
2034
|
+
_formValues = keepStateOptions.keepDefaultValues
|
|
1690
2035
|
? cloneObject(_defaultValues)
|
|
1691
|
-
: {}
|
|
1692
|
-
|
|
2036
|
+
: {};
|
|
2037
|
+
if (keepStateOptions.keepFieldsRef) {
|
|
2038
|
+
for (const fieldName of _names.mount) {
|
|
2039
|
+
set(_formValues, fieldName, get(values, fieldName));
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
}
|
|
2043
|
+
else {
|
|
2044
|
+
_formValues = cloneObject(values);
|
|
2045
|
+
}
|
|
1693
2046
|
_subjects.array.next({
|
|
1694
2047
|
values: { ...values },
|
|
1695
2048
|
});
|
|
1696
2049
|
_subjects.state.next({
|
|
2050
|
+
name: undefined,
|
|
2051
|
+
type: undefined,
|
|
1697
2052
|
values: { ...values },
|
|
1698
2053
|
});
|
|
1699
2054
|
}
|
|
@@ -1701,6 +2056,7 @@ function createFormControl(props = {}) {
|
|
|
1701
2056
|
mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
|
|
1702
2057
|
unMount: new Set(),
|
|
1703
2058
|
array: new Set(),
|
|
2059
|
+
registerName: new Set(),
|
|
1704
2060
|
disabled: new Set(),
|
|
1705
2061
|
watch: new Set(),
|
|
1706
2062
|
watchAll: false,
|
|
@@ -1714,9 +2070,6 @@ function createFormControl(props = {}) {
|
|
|
1714
2070
|
_state.watch = !!_options.shouldUnregister;
|
|
1715
2071
|
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
1716
2072
|
_state.action = false;
|
|
1717
|
-
// Clear errors synchronously to prevent validation errors on subsequent submissions
|
|
1718
|
-
// This fixes the issue where form.reset() causes validation errors on subsequent
|
|
1719
|
-
// submissions in Next.js 16 with Server Actions
|
|
1720
2073
|
if (!keepStateOptions.keepErrors) {
|
|
1721
2074
|
_formState.errors = {};
|
|
1722
2075
|
}
|
|
@@ -1728,8 +2081,10 @@ function createFormControl(props = {}) {
|
|
|
1728
2081
|
? false
|
|
1729
2082
|
: keepStateOptions.keepDirty
|
|
1730
2083
|
? _formState.isDirty
|
|
1731
|
-
:
|
|
1732
|
-
|
|
2084
|
+
: keepStateOptions.keepValues
|
|
2085
|
+
? _getDirty()
|
|
2086
|
+
: !!(keepStateOptions.keepDefaultValues &&
|
|
2087
|
+
!deepEqual(formValues, _defaultValues)),
|
|
1733
2088
|
isSubmitted: keepStateOptions.keepIsSubmitted
|
|
1734
2089
|
? _formState.isSubmitted
|
|
1735
2090
|
: false,
|
|
@@ -1766,8 +2121,6 @@ function createFormControl(props = {}) {
|
|
|
1766
2121
|
? fieldReference.refs[0]
|
|
1767
2122
|
: fieldReference.ref;
|
|
1768
2123
|
if (fieldRef.focus) {
|
|
1769
|
-
// Use setTimeout to ensure focus happens after any pending state updates
|
|
1770
|
-
// This fixes the issue where setFocus doesn't work immediately after setError
|
|
1771
2124
|
setTimeout(() => {
|
|
1772
2125
|
fieldRef.focus();
|
|
1773
2126
|
options.shouldSelect &&
|
|
@@ -1778,9 +2131,15 @@ function createFormControl(props = {}) {
|
|
|
1778
2131
|
}
|
|
1779
2132
|
};
|
|
1780
2133
|
const _setFormState = (updatedFormState) => {
|
|
2134
|
+
// `name`, `type`, and `values` describe the event that produced this
|
|
2135
|
+
// update, not the form's persisted state (they aren't part of
|
|
2136
|
+
// `FormState`). Merging them in would leak a stale `name`/`type` from
|
|
2137
|
+
// one event into a later, unrelated notification that doesn't specify
|
|
2138
|
+
// its own.
|
|
2139
|
+
const { name, type, values, ...formState } = updatedFormState;
|
|
1781
2140
|
_formState = {
|
|
1782
2141
|
..._formState,
|
|
1783
|
-
...
|
|
2142
|
+
...formState,
|
|
1784
2143
|
};
|
|
1785
2144
|
};
|
|
1786
2145
|
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
|
@@ -1790,6 +2149,21 @@ function createFormControl(props = {}) {
|
|
|
1790
2149
|
isLoading: false,
|
|
1791
2150
|
});
|
|
1792
2151
|
});
|
|
2152
|
+
const resetDefaultValues = (values, options = {}) => {
|
|
2153
|
+
_defaultValues = cloneObject(values);
|
|
2154
|
+
if (!options.keepDirty) {
|
|
2155
|
+
const newDirtyFields = getDirtyFields(_defaultValues, _formValues);
|
|
2156
|
+
_formState.dirtyFields = newDirtyFields;
|
|
2157
|
+
_formState.isDirty = !isEmptyObject(newDirtyFields);
|
|
2158
|
+
}
|
|
2159
|
+
if (!options.keepIsValid) {
|
|
2160
|
+
_setValid();
|
|
2161
|
+
}
|
|
2162
|
+
_subjects.state.next({
|
|
2163
|
+
..._formState,
|
|
2164
|
+
defaultValues: _defaultValues,
|
|
2165
|
+
});
|
|
2166
|
+
};
|
|
1793
2167
|
const methods = {
|
|
1794
2168
|
control: {
|
|
1795
2169
|
register,
|
|
@@ -1846,6 +2220,8 @@ function createFormControl(props = {}) {
|
|
|
1846
2220
|
..._options,
|
|
1847
2221
|
...value,
|
|
1848
2222
|
};
|
|
2223
|
+
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
2224
|
+
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1849
2225
|
},
|
|
1850
2226
|
},
|
|
1851
2227
|
subscribe,
|
|
@@ -1854,9 +2230,11 @@ function createFormControl(props = {}) {
|
|
|
1854
2230
|
handleSubmit,
|
|
1855
2231
|
watch,
|
|
1856
2232
|
setValue,
|
|
2233
|
+
setValues,
|
|
1857
2234
|
getValues,
|
|
1858
2235
|
reset,
|
|
1859
2236
|
resetField,
|
|
2237
|
+
resetDefaultValues,
|
|
1860
2238
|
clearErrors,
|
|
1861
2239
|
unregister,
|
|
1862
2240
|
setError,
|