react-hook-form 7.79.0 → 7.81.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/dist/constants.d.ts +0 -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/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.mjs +179 -98
- 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.map +1 -1
- package/dist/logic/getNodeParentName.d.ts.map +1 -1
- package/dist/logic/hasPromiseValidation.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/react-server.esm.mjs +166 -84
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/fieldArray.d.ts +24 -1
- package/dist/types/fieldArray.d.ts.map +1 -1
- package/dist/useFieldArray.d.ts.map +1 -1
- package/dist/utils/deepEqual.d.ts.map +1 -1
- package/dist/utils/flatten.d.ts.map +1 -1
- package/dist/utils/isKey.d.ts.map +1 -1
- package/dist/utils/stringToPath.d.ts.map +1 -1
- package/dist/utils/unset.d.ts.map +1 -1
- package/package.json +17 -13
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAcV,WAAW,EAiBX,YAAY,EAKZ,aAAa,EAYd,MAAM,UAAU,CAAC;AA0DlB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAY9B,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EAEjC,KAAK,GAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAM,GACnE,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,CAAC;CACH,CA2zDA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getNodeParentName.d.ts","sourceRoot":"","sources":["../../src/logic/getNodeParentName.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getNodeParentName.d.ts","sourceRoot":"","sources":["../../src/logic/getNodeParentName.ts"],"names":[],"mappings":"yBAEgB,MAAM,MAAM;AAA5B,wBACyD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hasPromiseValidation.d.ts","sourceRoot":"","sources":["../../src/logic/hasPromiseValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAY,MAAM,UAAU,CAAC;yBAMhC,gBAAgB,KAAK,CAAC,IAAI,CAAC;AAA3C,
|
|
1
|
+
{"version":3,"file":"hasPromiseValidation.d.ts","sourceRoot":"","sources":["../../src/logic/hasPromiseValidation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAY,MAAM,UAAU,CAAC;yBAMhC,gBAAgB,KAAK,CAAC,IAAI,CAAC;AAA3C,wBAmBE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"isWatched.d.ts","sourceRoot":"","sources":["../../src/logic/isWatched.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;yBAGvD,MAAM,iBAAiB,EACvB,QAAQ,KAAK,EACb,cAAc,OAAO;AAHvB,
|
|
1
|
+
{"version":3,"file":"isWatched.d.ts","sourceRoot":"","sources":["../../src/logic/isWatched.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;yBAGvD,MAAM,iBAAiB,EACvB,QAAQ,KAAK,EACb,cAAc,OAAO;AAHvB,wBAYE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shouldRenderFormState.d.ts","sourceRoot":"","sources":["../../src/logic/shouldRenderFormState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,aAAa,EACd,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"shouldRenderFormState.d.ts","sourceRoot":"","sources":["../../src/logic/shouldRenderFormState.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,WAAW,EACX,SAAS,EACT,iBAAiB,EACjB,aAAa,EACd,MAAM,UAAU,CAAC;yBAEF,CAAC,SAAS,WAAW,EAAE,CAAC,SAAS,aAAa,EAC5D,eAAe,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG;IACrC,IAAI,CAAC,EAAE,iBAAiB,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,CAAC;CACZ,EACD,iBAAiB,CAAC,EAClB,iBAAiB,CAAC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,EAC3D,SAAS,OAAO;AAPlB,wBAsBE"}
|
|
@@ -31,7 +31,6 @@ const INPUT_VALIDATION_RULES = {
|
|
|
31
31
|
required: 'required',
|
|
32
32
|
validate: 'validate',
|
|
33
33
|
};
|
|
34
|
-
const FORM_ERROR_TYPE = 'form';
|
|
35
34
|
const ROOT_ERROR_TYPE = 'root';
|
|
36
35
|
const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
|
|
37
36
|
|
|
@@ -129,6 +128,9 @@ function deepEqual(object1, object2, visited = new WeakMap()) {
|
|
|
129
128
|
isEmptyObjectWithCustomPrototype(object2, keys2)) {
|
|
130
129
|
return Object.is(object1, object2);
|
|
131
130
|
}
|
|
131
|
+
if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
132
134
|
const visitedPairs = visited.get(object1);
|
|
133
135
|
if (visitedPairs && visitedPairs.has(object2)) {
|
|
134
136
|
return true;
|
|
@@ -137,7 +139,9 @@ function deepEqual(object1, object2, visited = new WeakMap()) {
|
|
|
137
139
|
visitedPairs.add(object2);
|
|
138
140
|
}
|
|
139
141
|
else {
|
|
140
|
-
|
|
142
|
+
const ws = new WeakSet();
|
|
143
|
+
ws.add(object2);
|
|
144
|
+
visited.set(object1, ws);
|
|
141
145
|
}
|
|
142
146
|
for (const key of keys1) {
|
|
143
147
|
const val1 = object1[key];
|
|
@@ -178,11 +182,31 @@ function extractFormValues(fieldsState, formValues) {
|
|
|
178
182
|
return values;
|
|
179
183
|
}
|
|
180
184
|
|
|
181
|
-
|
|
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);
|
|
182
205
|
|
|
183
206
|
var isUndefined = (val) => val === undefined;
|
|
184
207
|
|
|
185
|
-
|
|
208
|
+
const FIELD_PATH_RE = /[.[\]'"]/;
|
|
209
|
+
var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
|
|
186
210
|
|
|
187
211
|
var get = (object, path, defaultValue) => {
|
|
188
212
|
if (!path || !isObject(object)) {
|
|
@@ -287,6 +311,9 @@ function unset(object, path) {
|
|
|
287
311
|
: isKey(path)
|
|
288
312
|
? [path]
|
|
289
313
|
: stringToPath(path);
|
|
314
|
+
if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
|
|
315
|
+
return object;
|
|
316
|
+
}
|
|
290
317
|
const childObject = paths.length === 1 ? object : baseGet(object, paths);
|
|
291
318
|
const index = paths.length - 1;
|
|
292
319
|
const key = paths[index];
|
|
@@ -494,12 +521,22 @@ var getValidationModes = (mode) => ({
|
|
|
494
521
|
});
|
|
495
522
|
|
|
496
523
|
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
497
|
-
var hasPromiseValidation = (fieldReference) =>
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
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
|
+
};
|
|
503
540
|
|
|
504
541
|
var hasValidation = (options) => options.mount &&
|
|
505
542
|
(options.required ||
|
|
@@ -514,10 +551,17 @@ var isNameInFieldArray = (names, name) => name
|
|
|
514
551
|
.split('.')
|
|
515
552
|
.some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
|
|
516
553
|
|
|
517
|
-
var isWatched = (name, _names, isBlurEvent) =>
|
|
518
|
-
(
|
|
519
|
-
|
|
520
|
-
|
|
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
|
+
};
|
|
521
565
|
|
|
522
566
|
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
|
523
567
|
for (const key of fieldsNames || Object.keys(fields)) {
|
|
@@ -585,10 +629,10 @@ function schemaErrorLookup(errors, _fields, name) {
|
|
|
585
629
|
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
586
630
|
updateFormState(formStateData);
|
|
587
631
|
const { name, ...formState } = formStateData;
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
632
|
+
const keys = Object.keys(formState);
|
|
633
|
+
return (!keys.length ||
|
|
634
|
+
(isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
|
|
635
|
+
keys.find((key) => _proxyFormState[key] ===
|
|
592
636
|
(!isRoot || VALIDATION_MODE.all)));
|
|
593
637
|
};
|
|
594
638
|
|
|
@@ -597,7 +641,7 @@ var shouldSubscribeByName = (name, signalName, exact) => !name ||
|
|
|
597
641
|
name === signalName ||
|
|
598
642
|
convertToArrayPayload(name).some((currentName) => currentName &&
|
|
599
643
|
(exact
|
|
600
|
-
? currentName === signalName
|
|
644
|
+
? currentName === signalName || currentName.startsWith(signalName + '.')
|
|
601
645
|
: currentName.startsWith(signalName) ||
|
|
602
646
|
signalName.startsWith(currentName)));
|
|
603
647
|
|
|
@@ -836,6 +880,7 @@ const defaultOptions = {
|
|
|
836
880
|
reValidateMode: VALIDATION_MODE.onChange,
|
|
837
881
|
shouldFocusError: true,
|
|
838
882
|
};
|
|
883
|
+
const FORM_ERROR_TYPE = 'form';
|
|
839
884
|
const DEFAULT_FORM_STATE = {
|
|
840
885
|
submitCount: 0,
|
|
841
886
|
isDirty: false,
|
|
@@ -883,6 +928,9 @@ function createFormControl(props = {}) {
|
|
|
883
928
|
};
|
|
884
929
|
let delayErrorCallback;
|
|
885
930
|
let timer = 0;
|
|
931
|
+
let _valuesSubscriberCount = 0;
|
|
932
|
+
let _validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
933
|
+
let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
886
934
|
const defaultProxyFormState = {
|
|
887
935
|
isDirty: false,
|
|
888
936
|
dirtyFields: false,
|
|
@@ -1036,12 +1084,6 @@ function createFormControl(props = {}) {
|
|
|
1036
1084
|
: setFieldValue(name, defaultValue);
|
|
1037
1085
|
if (_state.mount && !_state.action) {
|
|
1038
1086
|
_setValid();
|
|
1039
|
-
// Re-registering a field after a prior unregister puts its key back
|
|
1040
|
-
// into _formValues, which can flip isDirty back to false (#13397).
|
|
1041
|
-
// Only run when we are currently dirty, otherwise an initial register
|
|
1042
|
-
// for a field with no defaultValue would flip isDirty to true. Reset
|
|
1043
|
-
// paths repopulate _formValues before re-register, so the key is
|
|
1044
|
-
// present then and this branch is skipped (preserves keepDirty).
|
|
1045
1087
|
if (wasUnsetInFormValues &&
|
|
1046
1088
|
_formState.isDirty &&
|
|
1047
1089
|
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
|
|
@@ -1051,9 +1093,6 @@ function createFormControl(props = {}) {
|
|
|
1051
1093
|
_subjects.state.next({ ..._formState });
|
|
1052
1094
|
}
|
|
1053
1095
|
}
|
|
1054
|
-
// When a watched field is re-registered after being unregistered and
|
|
1055
|
-
// its value is restored, trigger a deferred watch broadcast so that
|
|
1056
|
-
// components using watch() re-render with the new value.
|
|
1057
1096
|
if (props.shouldUnregister &&
|
|
1058
1097
|
wasUnsetInFormValues &&
|
|
1059
1098
|
!isUndefined(get(_formValues, name)) &&
|
|
@@ -1071,12 +1110,13 @@ function createFormControl(props = {}) {
|
|
|
1071
1110
|
};
|
|
1072
1111
|
if (!_options.disabled) {
|
|
1073
1112
|
if (!isBlurEvent || shouldDirty) {
|
|
1113
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
1074
1114
|
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
1075
1115
|
isPreviousDirty = _formState.isDirty;
|
|
1076
|
-
_formState.isDirty = output.isDirty =
|
|
1116
|
+
_formState.isDirty = output.isDirty =
|
|
1117
|
+
!isCurrentFieldPristine || _getDirty();
|
|
1077
1118
|
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
1078
1119
|
}
|
|
1079
|
-
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
1080
1120
|
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
1081
1121
|
if (isCurrentFieldPristine !== _formState.isDirty) {
|
|
1082
1122
|
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
|
|
@@ -1275,7 +1315,7 @@ function createFormControl(props = {}) {
|
|
|
1275
1315
|
};
|
|
1276
1316
|
const _getDirty = (name, data) => !_options.disabled &&
|
|
1277
1317
|
(name && data && set(_formValues, name, data),
|
|
1278
|
-
!deepEqual(
|
|
1318
|
+
!deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
|
|
1279
1319
|
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
|
1280
1320
|
...(_state.mount
|
|
1281
1321
|
? _formValues
|
|
@@ -1286,7 +1326,7 @@ function createFormControl(props = {}) {
|
|
|
1286
1326
|
: defaultValue),
|
|
1287
1327
|
}, isGlobal, defaultValue);
|
|
1288
1328
|
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
|
1289
|
-
const setFieldValue = (name, value, options = {}, skipClone = false) => {
|
|
1329
|
+
const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
|
|
1290
1330
|
const field = get(_fields, name);
|
|
1291
1331
|
let fieldValue = value;
|
|
1292
1332
|
if (field) {
|
|
@@ -1324,7 +1364,7 @@ function createFormControl(props = {}) {
|
|
|
1324
1364
|
}
|
|
1325
1365
|
else {
|
|
1326
1366
|
fieldReference.ref.value = fieldValue;
|
|
1327
|
-
if (!fieldReference.ref.type) {
|
|
1367
|
+
if (!fieldReference.ref.type && !skipRender) {
|
|
1328
1368
|
_subjects.state.next({
|
|
1329
1369
|
name,
|
|
1330
1370
|
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
@@ -1334,10 +1374,10 @@ function createFormControl(props = {}) {
|
|
|
1334
1374
|
}
|
|
1335
1375
|
}
|
|
1336
1376
|
(options.shouldDirty || options.shouldTouch) &&
|
|
1337
|
-
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty,
|
|
1377
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
|
|
1338
1378
|
options.shouldValidate && trigger(name);
|
|
1339
1379
|
};
|
|
1340
|
-
const setFieldValues = (name, value, options, skipClone = false) => {
|
|
1380
|
+
const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
|
|
1341
1381
|
for (const fieldKey in value) {
|
|
1342
1382
|
if (!value.hasOwnProperty(fieldKey)) {
|
|
1343
1383
|
return;
|
|
@@ -1349,11 +1389,11 @@ function createFormControl(props = {}) {
|
|
|
1349
1389
|
isObject(fieldValue) ||
|
|
1350
1390
|
(field && !field._f)) &&
|
|
1351
1391
|
!isDateObject(fieldValue)
|
|
1352
|
-
? setFieldValues(fieldName, fieldValue, options, skipClone)
|
|
1353
|
-
: setFieldValue(fieldName, fieldValue, options, skipClone);
|
|
1392
|
+
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
1393
|
+
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
1354
1394
|
}
|
|
1355
1395
|
};
|
|
1356
|
-
const _setValue = (name, value, options, skipClone) => {
|
|
1396
|
+
const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
|
|
1357
1397
|
const field = get(_fields, name);
|
|
1358
1398
|
const isFieldArray = _names.array.has(name);
|
|
1359
1399
|
const cloneValue = skipClone ? value : cloneObject(value);
|
|
@@ -1373,24 +1413,26 @@ function createFormControl(props = {}) {
|
|
|
1373
1413
|
_proxySubscribeFormState.dirtyFields) &&
|
|
1374
1414
|
options.shouldDirty) {
|
|
1375
1415
|
_updateDirtyFields();
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1416
|
+
if (!skipStateEmit) {
|
|
1417
|
+
_subjects.state.next({
|
|
1418
|
+
name,
|
|
1419
|
+
dirtyFields: _formState.dirtyFields,
|
|
1420
|
+
isDirty: _getDirty(name, cloneValue),
|
|
1421
|
+
});
|
|
1422
|
+
}
|
|
1381
1423
|
}
|
|
1382
1424
|
}
|
|
1383
1425
|
else {
|
|
1384
1426
|
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
1385
1427
|
isEmptyObject(cloneValue);
|
|
1386
1428
|
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
1387
|
-
setFieldValue(name, cloneValue, options, skipClone);
|
|
1429
|
+
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
1388
1430
|
}
|
|
1389
1431
|
else {
|
|
1390
|
-
setFieldValues(name, cloneValue, options, skipClone);
|
|
1432
|
+
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
1391
1433
|
}
|
|
1392
1434
|
}
|
|
1393
|
-
if (!isValueUnchanged) {
|
|
1435
|
+
if (!isValueUnchanged && !skipStateEmit) {
|
|
1394
1436
|
const watched = isWatched(name, _names);
|
|
1395
1437
|
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
1396
1438
|
_subjects.state.next({
|
|
@@ -1410,14 +1452,17 @@ function createFormControl(props = {}) {
|
|
|
1410
1452
|
..._formValues,
|
|
1411
1453
|
...updatedFormValues,
|
|
1412
1454
|
};
|
|
1455
|
+
const flattenedUpdates = flatten(updatedFormValues);
|
|
1413
1456
|
for (const fieldName of _names.mount) {
|
|
1414
|
-
|
|
1457
|
+
if (fieldName in flattenedUpdates) {
|
|
1458
|
+
_setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
|
|
1459
|
+
}
|
|
1415
1460
|
}
|
|
1416
1461
|
_subjects.state.next({
|
|
1417
1462
|
..._formState,
|
|
1418
1463
|
name: undefined,
|
|
1419
1464
|
type: undefined,
|
|
1420
|
-
values: _formValues,
|
|
1465
|
+
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
1421
1466
|
});
|
|
1422
1467
|
if (options.shouldValidate) {
|
|
1423
1468
|
_setValid();
|
|
@@ -1436,8 +1481,6 @@ function createFormControl(props = {}) {
|
|
|
1436
1481
|
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
1437
1482
|
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
1438
1483
|
};
|
|
1439
|
-
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
1440
|
-
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1441
1484
|
if (field) {
|
|
1442
1485
|
let error;
|
|
1443
1486
|
let isValid;
|
|
@@ -1445,12 +1488,13 @@ function createFormControl(props = {}) {
|
|
|
1445
1488
|
? getFieldValue(field._f)
|
|
1446
1489
|
: getEventValue(event);
|
|
1447
1490
|
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
1448
|
-
const
|
|
1491
|
+
const hasNoValidationEffect = !hasValidation(field._f) &&
|
|
1449
1492
|
!props.validate &&
|
|
1450
1493
|
!_options.resolver &&
|
|
1451
1494
|
!get(_formState.errors, name) &&
|
|
1452
|
-
!field._f.deps
|
|
1453
|
-
|
|
1495
|
+
!field._f.deps;
|
|
1496
|
+
const shouldSkipValidation = hasNoValidationEffect ||
|
|
1497
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
|
|
1454
1498
|
const watched = isWatched(name, _names, isBlurEvent);
|
|
1455
1499
|
set(_formValues, name, fieldValue);
|
|
1456
1500
|
if (isBlurEvent) {
|
|
@@ -1468,10 +1512,13 @@ function createFormControl(props = {}) {
|
|
|
1468
1512
|
_subjects.state.next({
|
|
1469
1513
|
name,
|
|
1470
1514
|
type: event.type,
|
|
1471
|
-
|
|
1515
|
+
...(_valuesSubscriberCount
|
|
1516
|
+
? { values: cloneObject(_formValues) }
|
|
1517
|
+
: {}),
|
|
1472
1518
|
});
|
|
1473
1519
|
if (shouldSkipValidation) {
|
|
1474
|
-
if (
|
|
1520
|
+
if ((!hasNoValidationEffect || !_formState.isValid) &&
|
|
1521
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
|
|
1475
1522
|
if (_options.mode === 'onBlur') {
|
|
1476
1523
|
if (isBlurEvent) {
|
|
1477
1524
|
_setValid();
|
|
@@ -1606,8 +1653,6 @@ function createFormControl(props = {}) {
|
|
|
1606
1653
|
const names = name ? convertToArrayPayload(name) : undefined;
|
|
1607
1654
|
names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
|
|
1608
1655
|
if (names) {
|
|
1609
|
-
// Emit for each cleared field with the field name so that
|
|
1610
|
-
// shouldSubscribeByName can filter and avoid broad re-renders
|
|
1611
1656
|
names.forEach((inputName) => {
|
|
1612
1657
|
_subjects.state.next({
|
|
1613
1658
|
name: inputName,
|
|
@@ -1616,7 +1661,6 @@ function createFormControl(props = {}) {
|
|
|
1616
1661
|
});
|
|
1617
1662
|
}
|
|
1618
1663
|
else {
|
|
1619
|
-
// Clear all errors - emit without name to notify all subscribers
|
|
1620
1664
|
_subjects.state.next({
|
|
1621
1665
|
errors: {},
|
|
1622
1666
|
});
|
|
@@ -1625,7 +1669,6 @@ function createFormControl(props = {}) {
|
|
|
1625
1669
|
const setError = (name, error, options) => {
|
|
1626
1670
|
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
1627
1671
|
const currentError = get(_formState.errors, name) || {};
|
|
1628
|
-
// Don't override existing error messages elsewhere in the object tree.
|
|
1629
1672
|
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
1630
1673
|
set(_formState.errors, name, {
|
|
1631
1674
|
...restOfErrorTree,
|
|
@@ -1639,26 +1682,60 @@ function createFormControl(props = {}) {
|
|
|
1639
1682
|
});
|
|
1640
1683
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
1641
1684
|
};
|
|
1642
|
-
const watch = (name, defaultValue) =>
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
}
|
|
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
|
+
var _a;
|
|
1708
|
+
const needsValues = !!((_a = props.formState) === null || _a === void 0 ? void 0 : _a.values);
|
|
1709
|
+
if (needsValues) {
|
|
1710
|
+
_valuesSubscriberCount++;
|
|
1711
|
+
}
|
|
1712
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
1713
|
+
next: (formState) => {
|
|
1714
|
+
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
1715
|
+
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
1716
|
+
const snapshot = { ..._formValues };
|
|
1717
|
+
props.callback({
|
|
1718
|
+
values: snapshot,
|
|
1719
|
+
..._formState,
|
|
1720
|
+
...formState,
|
|
1721
|
+
defaultValues: _defaultValues,
|
|
1722
|
+
});
|
|
1723
|
+
}
|
|
1724
|
+
},
|
|
1725
|
+
});
|
|
1726
|
+
if (!needsValues) {
|
|
1727
|
+
return unsubscribe;
|
|
1728
|
+
}
|
|
1729
|
+
let called = false;
|
|
1730
|
+
return () => {
|
|
1731
|
+
if (called) {
|
|
1732
|
+
return;
|
|
1659
1733
|
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1734
|
+
called = true;
|
|
1735
|
+
_valuesSubscriberCount--;
|
|
1736
|
+
unsubscribe();
|
|
1737
|
+
};
|
|
1738
|
+
};
|
|
1662
1739
|
const subscribe = (props) => {
|
|
1663
1740
|
_state.mount = true;
|
|
1664
1741
|
_proxySubscribeFormState = {
|
|
@@ -1971,6 +2048,8 @@ function createFormControl(props = {}) {
|
|
|
1971
2048
|
values: { ...values },
|
|
1972
2049
|
});
|
|
1973
2050
|
_subjects.state.next({
|
|
2051
|
+
name: undefined,
|
|
2052
|
+
type: undefined,
|
|
1974
2053
|
values: { ...values },
|
|
1975
2054
|
});
|
|
1976
2055
|
}
|
|
@@ -1992,9 +2071,6 @@ function createFormControl(props = {}) {
|
|
|
1992
2071
|
_state.watch = !!_options.shouldUnregister;
|
|
1993
2072
|
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
1994
2073
|
_state.action = false;
|
|
1995
|
-
// Clear errors synchronously to prevent validation errors on subsequent submissions
|
|
1996
|
-
// This fixes the issue where form.reset() causes validation errors on subsequent
|
|
1997
|
-
// submissions in Next.js 16 with Server Actions
|
|
1998
2074
|
if (!keepStateOptions.keepErrors) {
|
|
1999
2075
|
_formState.errors = {};
|
|
2000
2076
|
}
|
|
@@ -2046,8 +2122,6 @@ function createFormControl(props = {}) {
|
|
|
2046
2122
|
? fieldReference.refs[0]
|
|
2047
2123
|
: fieldReference.ref;
|
|
2048
2124
|
if (fieldRef.focus) {
|
|
2049
|
-
// Use setTimeout to ensure focus happens after any pending state updates
|
|
2050
|
-
// This fixes the issue where setFocus doesn't work immediately after setError
|
|
2051
2125
|
setTimeout(() => {
|
|
2052
2126
|
fieldRef.focus();
|
|
2053
2127
|
options.shouldSelect &&
|
|
@@ -2058,9 +2132,15 @@ function createFormControl(props = {}) {
|
|
|
2058
2132
|
}
|
|
2059
2133
|
};
|
|
2060
2134
|
const _setFormState = (updatedFormState) => {
|
|
2135
|
+
// `name`, `type`, and `values` describe the event that produced this
|
|
2136
|
+
// update, not the form's persisted state (they aren't part of
|
|
2137
|
+
// `FormState`). Merging them in would leak a stale `name`/`type` from
|
|
2138
|
+
// one event into a later, unrelated notification that doesn't specify
|
|
2139
|
+
// its own.
|
|
2140
|
+
const { name, type, values, ...formState } = updatedFormState;
|
|
2061
2141
|
_formState = {
|
|
2062
2142
|
..._formState,
|
|
2063
|
-
...
|
|
2143
|
+
...formState,
|
|
2064
2144
|
};
|
|
2065
2145
|
};
|
|
2066
2146
|
const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
|
|
@@ -2141,6 +2221,8 @@ function createFormControl(props = {}) {
|
|
|
2141
2221
|
..._options,
|
|
2142
2222
|
...value,
|
|
2143
2223
|
};
|
|
2224
|
+
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
2225
|
+
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
2144
2226
|
},
|
|
2145
2227
|
},
|
|
2146
2228
|
subscribe,
|