react-hook-form 7.78.0 → 7.80.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/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.mjs +255 -118
- 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/logic/validateField.d.ts.map +1 -1
- package/dist/react-server.esm.mjs +156 -83
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/fieldArray.d.ts +4 -1
- package/dist/types/fieldArray.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/utils/deepEqual.d.ts +1 -1
- package/dist/utils/deepEqual.d.ts.map +1 -1
- package/dist/utils/isKey.d.ts.map +1 -1
- package/dist/utils/stringToPath.d.ts.map +1 -1
- package/package.json +16 -12
package/dist/index.esm.mjs
CHANGED
|
@@ -76,15 +76,16 @@ const INPUT_VALIDATION_RULES = {
|
|
|
76
76
|
required: 'required',
|
|
77
77
|
validate: 'validate',
|
|
78
78
|
};
|
|
79
|
-
const FORM_ERROR_TYPE = 'form';
|
|
80
79
|
const ROOT_ERROR_TYPE = 'root';
|
|
81
80
|
const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
const IS_KEY_RE = /^\w*$/;
|
|
83
|
+
var isKey = (value) => IS_KEY_RE.test(value);
|
|
84
84
|
|
|
85
85
|
var isUndefined = (val) => val === undefined;
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
const FIELD_PATH_RE = /[.[\]'"]/;
|
|
88
|
+
var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
|
|
88
89
|
|
|
89
90
|
var get = (object, path, defaultValue) => {
|
|
90
91
|
if (!path || !isObject(object)) {
|
|
@@ -249,7 +250,7 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
|
|
|
249
250
|
var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
|
|
250
251
|
|
|
251
252
|
const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
|
|
252
|
-
function deepEqual(object1, object2, visited = new
|
|
253
|
+
function deepEqual(object1, object2, visited = new WeakMap()) {
|
|
253
254
|
if (object1 === object2) {
|
|
254
255
|
return true;
|
|
255
256
|
}
|
|
@@ -268,11 +269,21 @@ function deepEqual(object1, object2, visited = new WeakSet()) {
|
|
|
268
269
|
isEmptyObjectWithCustomPrototype(object2, keys2)) {
|
|
269
270
|
return Object.is(object1, object2);
|
|
270
271
|
}
|
|
271
|
-
if (
|
|
272
|
+
if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
|
|
273
|
+
return false;
|
|
274
|
+
}
|
|
275
|
+
const visitedPairs = visited.get(object1);
|
|
276
|
+
if (visitedPairs && visitedPairs.has(object2)) {
|
|
272
277
|
return true;
|
|
273
278
|
}
|
|
274
|
-
|
|
275
|
-
|
|
279
|
+
if (visitedPairs) {
|
|
280
|
+
visitedPairs.add(object2);
|
|
281
|
+
}
|
|
282
|
+
else {
|
|
283
|
+
const ws = new WeakSet();
|
|
284
|
+
ws.add(object2);
|
|
285
|
+
visited.set(object1, ws);
|
|
286
|
+
}
|
|
276
287
|
for (const key of keys1) {
|
|
277
288
|
const val1 = object1[key];
|
|
278
289
|
if (!(key in object2)) {
|
|
@@ -419,6 +430,7 @@ function useController(props) {
|
|
|
419
430
|
exact,
|
|
420
431
|
});
|
|
421
432
|
const _props = React.useRef(props);
|
|
433
|
+
const _proxyRef = React.useRef(null);
|
|
422
434
|
const _registerProps = React.useRef(control.register(name, {
|
|
423
435
|
...props.rules,
|
|
424
436
|
value,
|
|
@@ -455,7 +467,7 @@ function useController(props) {
|
|
|
455
467
|
value,
|
|
456
468
|
});
|
|
457
469
|
}
|
|
458
|
-
_registerProps.current.onChange({
|
|
470
|
+
return _registerProps.current.onChange({
|
|
459
471
|
target: {
|
|
460
472
|
value: getEventValue(event),
|
|
461
473
|
name: name,
|
|
@@ -471,15 +483,18 @@ function useController(props) {
|
|
|
471
483
|
type: EVENTS.BLUR,
|
|
472
484
|
}), [name, control._formValues]);
|
|
473
485
|
const ref = React.useCallback((elm) => {
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
field._f.ref = {
|
|
486
|
+
if (elm) {
|
|
487
|
+
_proxyRef.current = {
|
|
477
488
|
focus: () => isFunction(elm.focus) && elm.focus(),
|
|
478
489
|
select: () => isFunction(elm.select) && elm.select(),
|
|
479
490
|
setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
|
|
480
491
|
reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
|
|
481
492
|
};
|
|
482
493
|
}
|
|
494
|
+
const field = get(control._fields, name);
|
|
495
|
+
if (field && field._f && elm) {
|
|
496
|
+
field._f.ref = _proxyRef.current;
|
|
497
|
+
}
|
|
483
498
|
}, [control._fields, name]);
|
|
484
499
|
const field = React.useMemo(() => ({
|
|
485
500
|
name,
|
|
@@ -516,6 +531,12 @@ function useController(props) {
|
|
|
516
531
|
}
|
|
517
532
|
}
|
|
518
533
|
!isArrayField && control.register(name);
|
|
534
|
+
if (_proxyRef.current) {
|
|
535
|
+
const field = get(control._fields, name);
|
|
536
|
+
if (field && field._f) {
|
|
537
|
+
field._f.ref = _proxyRef.current;
|
|
538
|
+
}
|
|
539
|
+
}
|
|
519
540
|
return () => {
|
|
520
541
|
(isArrayField
|
|
521
542
|
? _shouldUnregisterField && !control._state.action
|
|
@@ -1117,12 +1138,22 @@ var getValidationModes = (mode) => ({
|
|
|
1117
1138
|
});
|
|
1118
1139
|
|
|
1119
1140
|
const ASYNC_FUNCTION = 'AsyncFunction';
|
|
1120
|
-
var hasPromiseValidation = (fieldReference) =>
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1141
|
+
var hasPromiseValidation = (fieldReference) => {
|
|
1142
|
+
if (!fieldReference || !fieldReference.validate)
|
|
1143
|
+
return false;
|
|
1144
|
+
if (isFunction(fieldReference.validate)) {
|
|
1145
|
+
return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
|
|
1146
|
+
}
|
|
1147
|
+
if (isObject(fieldReference.validate)) {
|
|
1148
|
+
for (const key in fieldReference.validate) {
|
|
1149
|
+
if (fieldReference.validate[key].constructor
|
|
1150
|
+
.name === ASYNC_FUNCTION) {
|
|
1151
|
+
return true;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
return false;
|
|
1156
|
+
};
|
|
1126
1157
|
|
|
1127
1158
|
var hasValidation = (options) => options.mount &&
|
|
1128
1159
|
(options.required ||
|
|
@@ -1133,10 +1164,17 @@ var hasValidation = (options) => options.mount &&
|
|
|
1133
1164
|
options.pattern ||
|
|
1134
1165
|
options.validate);
|
|
1135
1166
|
|
|
1136
|
-
var isWatched = (name, _names, isBlurEvent) =>
|
|
1137
|
-
(
|
|
1138
|
-
|
|
1139
|
-
|
|
1167
|
+
var isWatched = (name, _names, isBlurEvent) => {
|
|
1168
|
+
if (isBlurEvent)
|
|
1169
|
+
return false;
|
|
1170
|
+
if (_names.watchAll || _names.watch.has(name))
|
|
1171
|
+
return true;
|
|
1172
|
+
for (const watchName of _names.watch) {
|
|
1173
|
+
if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
|
|
1174
|
+
return true;
|
|
1175
|
+
}
|
|
1176
|
+
return false;
|
|
1177
|
+
};
|
|
1140
1178
|
|
|
1141
1179
|
const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
|
|
1142
1180
|
for (const key of fieldsNames || Object.keys(fields)) {
|
|
@@ -1204,10 +1242,10 @@ function schemaErrorLookup(errors, _fields, name) {
|
|
|
1204
1242
|
var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
|
|
1205
1243
|
updateFormState(formStateData);
|
|
1206
1244
|
const { name, ...formState } = formStateData;
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1245
|
+
const keys = Object.keys(formState);
|
|
1246
|
+
return (!keys.length ||
|
|
1247
|
+
(isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
|
|
1248
|
+
keys.find((key) => _proxyFormState[key] ===
|
|
1211
1249
|
(!isRoot || VALIDATION_MODE.all)));
|
|
1212
1250
|
};
|
|
1213
1251
|
|
|
@@ -1274,7 +1312,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
|
|
|
1274
1312
|
const inputRef = refs ? refs[0] : ref;
|
|
1275
1313
|
const setCustomValidity = (message) => {
|
|
1276
1314
|
if (shouldUseNativeValidation && inputRef.reportValidity) {
|
|
1277
|
-
|
|
1315
|
+
const validityMessage = isBoolean(message) ? '' : message || '';
|
|
1316
|
+
if (refs) {
|
|
1317
|
+
refs.forEach((ref) => ref.setCustomValidity(validityMessage));
|
|
1318
|
+
}
|
|
1319
|
+
else {
|
|
1320
|
+
inputRef.setCustomValidity(validityMessage);
|
|
1321
|
+
}
|
|
1278
1322
|
inputRef.reportValidity();
|
|
1279
1323
|
}
|
|
1280
1324
|
};
|
|
@@ -1449,6 +1493,7 @@ const defaultOptions = {
|
|
|
1449
1493
|
reValidateMode: VALIDATION_MODE.onChange,
|
|
1450
1494
|
shouldFocusError: true,
|
|
1451
1495
|
};
|
|
1496
|
+
const FORM_ERROR_TYPE = 'form';
|
|
1452
1497
|
const DEFAULT_FORM_STATE = {
|
|
1453
1498
|
submitCount: 0,
|
|
1454
1499
|
isDirty: false,
|
|
@@ -1496,6 +1541,9 @@ function createFormControl(props = {}) {
|
|
|
1496
1541
|
};
|
|
1497
1542
|
let delayErrorCallback;
|
|
1498
1543
|
let timer = 0;
|
|
1544
|
+
let _valuesSubscriberCount = 0;
|
|
1545
|
+
let _validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
1546
|
+
let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
1499
1547
|
const defaultProxyFormState = {
|
|
1500
1548
|
isDirty: false,
|
|
1501
1549
|
dirtyFields: false,
|
|
@@ -1606,6 +1654,7 @@ function createFormControl(props = {}) {
|
|
|
1606
1654
|
};
|
|
1607
1655
|
const updateErrors = (name, error) => {
|
|
1608
1656
|
set(_formState.errors, name, error);
|
|
1657
|
+
_formState.errors = { ..._formState.errors };
|
|
1609
1658
|
_subjects.state.next({
|
|
1610
1659
|
errors: _formState.errors,
|
|
1611
1660
|
});
|
|
@@ -1648,12 +1697,6 @@ function createFormControl(props = {}) {
|
|
|
1648
1697
|
: setFieldValue(name, defaultValue);
|
|
1649
1698
|
if (_state.mount && !_state.action) {
|
|
1650
1699
|
_setValid();
|
|
1651
|
-
// Re-registering a field after a prior unregister puts its key back
|
|
1652
|
-
// into _formValues, which can flip isDirty back to false (#13397).
|
|
1653
|
-
// Only run when we are currently dirty, otherwise an initial register
|
|
1654
|
-
// for a field with no defaultValue would flip isDirty to true. Reset
|
|
1655
|
-
// paths repopulate _formValues before re-register, so the key is
|
|
1656
|
-
// present then and this branch is skipped (preserves keepDirty).
|
|
1657
1700
|
if (wasUnsetInFormValues &&
|
|
1658
1701
|
_formState.isDirty &&
|
|
1659
1702
|
(_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
|
|
@@ -1663,6 +1706,12 @@ function createFormControl(props = {}) {
|
|
|
1663
1706
|
_subjects.state.next({ ..._formState });
|
|
1664
1707
|
}
|
|
1665
1708
|
}
|
|
1709
|
+
if (props.shouldUnregister &&
|
|
1710
|
+
wasUnsetInFormValues &&
|
|
1711
|
+
!isUndefined(get(_formValues, name)) &&
|
|
1712
|
+
isWatched(name, _names)) {
|
|
1713
|
+
_state.watch = true;
|
|
1714
|
+
}
|
|
1666
1715
|
}
|
|
1667
1716
|
}
|
|
1668
1717
|
};
|
|
@@ -1674,12 +1723,13 @@ function createFormControl(props = {}) {
|
|
|
1674
1723
|
};
|
|
1675
1724
|
if (!_options.disabled) {
|
|
1676
1725
|
if (!isBlurEvent || shouldDirty) {
|
|
1726
|
+
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
1677
1727
|
if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
|
|
1678
1728
|
isPreviousDirty = _formState.isDirty;
|
|
1679
|
-
_formState.isDirty = output.isDirty =
|
|
1729
|
+
_formState.isDirty = output.isDirty =
|
|
1730
|
+
!isCurrentFieldPristine || _getDirty();
|
|
1680
1731
|
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
|
1681
1732
|
}
|
|
1682
|
-
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
|
1683
1733
|
isPreviousDirty = !!get(_formState.dirtyFields, name);
|
|
1684
1734
|
if (isCurrentFieldPristine !== _formState.isDirty) {
|
|
1685
1735
|
_formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
|
|
@@ -1727,6 +1777,7 @@ function createFormControl(props = {}) {
|
|
|
1727
1777
|
error
|
|
1728
1778
|
? set(_formState.errors, name, error)
|
|
1729
1779
|
: unset(_formState.errors, name);
|
|
1780
|
+
_formState.errors = { ..._formState.errors };
|
|
1730
1781
|
}
|
|
1731
1782
|
if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
|
|
1732
1783
|
!isEmptyObject(fieldState) ||
|
|
@@ -1762,6 +1813,7 @@ function createFormControl(props = {}) {
|
|
|
1762
1813
|
: set(_formState.errors, name, error)
|
|
1763
1814
|
: unset(_formState.errors, name);
|
|
1764
1815
|
}
|
|
1816
|
+
_formState.errors = { ..._formState.errors };
|
|
1765
1817
|
}
|
|
1766
1818
|
else {
|
|
1767
1819
|
_formState.errors = errors;
|
|
@@ -1876,7 +1928,7 @@ function createFormControl(props = {}) {
|
|
|
1876
1928
|
};
|
|
1877
1929
|
const _getDirty = (name, data) => !_options.disabled &&
|
|
1878
1930
|
(name && data && set(_formValues, name, data),
|
|
1879
|
-
!deepEqual(
|
|
1931
|
+
!deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
|
|
1880
1932
|
const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
|
|
1881
1933
|
...(_state.mount
|
|
1882
1934
|
? _formValues
|
|
@@ -1887,7 +1939,7 @@ function createFormControl(props = {}) {
|
|
|
1887
1939
|
: defaultValue),
|
|
1888
1940
|
}, isGlobal, defaultValue);
|
|
1889
1941
|
const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
|
|
1890
|
-
const setFieldValue = (name, value, options = {}, skipClone = false) => {
|
|
1942
|
+
const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
|
|
1891
1943
|
const field = get(_fields, name);
|
|
1892
1944
|
let fieldValue = value;
|
|
1893
1945
|
if (field) {
|
|
@@ -1925,7 +1977,7 @@ function createFormControl(props = {}) {
|
|
|
1925
1977
|
}
|
|
1926
1978
|
else {
|
|
1927
1979
|
fieldReference.ref.value = fieldValue;
|
|
1928
|
-
if (!fieldReference.ref.type) {
|
|
1980
|
+
if (!fieldReference.ref.type && !skipRender) {
|
|
1929
1981
|
_subjects.state.next({
|
|
1930
1982
|
name,
|
|
1931
1983
|
values: skipClone ? _formValues : cloneObject(_formValues),
|
|
@@ -1935,10 +1987,10 @@ function createFormControl(props = {}) {
|
|
|
1935
1987
|
}
|
|
1936
1988
|
}
|
|
1937
1989
|
(options.shouldDirty || options.shouldTouch) &&
|
|
1938
|
-
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty,
|
|
1990
|
+
updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
|
|
1939
1991
|
options.shouldValidate && trigger(name);
|
|
1940
1992
|
};
|
|
1941
|
-
const setFieldValues = (name, value, options, skipClone = false) => {
|
|
1993
|
+
const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
|
|
1942
1994
|
for (const fieldKey in value) {
|
|
1943
1995
|
if (!value.hasOwnProperty(fieldKey)) {
|
|
1944
1996
|
return;
|
|
@@ -1950,11 +2002,11 @@ function createFormControl(props = {}) {
|
|
|
1950
2002
|
isObject(fieldValue) ||
|
|
1951
2003
|
(field && !field._f)) &&
|
|
1952
2004
|
!isDateObject(fieldValue)
|
|
1953
|
-
? setFieldValues(fieldName, fieldValue, options, skipClone)
|
|
1954
|
-
: setFieldValue(fieldName, fieldValue, options, skipClone);
|
|
2005
|
+
? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
|
|
2006
|
+
: setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
|
|
1955
2007
|
}
|
|
1956
2008
|
};
|
|
1957
|
-
const _setValue = (name, value, options, skipClone) => {
|
|
2009
|
+
const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
|
|
1958
2010
|
const field = get(_fields, name);
|
|
1959
2011
|
const isFieldArray = _names.array.has(name);
|
|
1960
2012
|
const cloneValue = skipClone ? value : cloneObject(value);
|
|
@@ -1974,24 +2026,26 @@ function createFormControl(props = {}) {
|
|
|
1974
2026
|
_proxySubscribeFormState.dirtyFields) &&
|
|
1975
2027
|
options.shouldDirty) {
|
|
1976
2028
|
_updateDirtyFields();
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
2029
|
+
if (!skipStateEmit) {
|
|
2030
|
+
_subjects.state.next({
|
|
2031
|
+
name,
|
|
2032
|
+
dirtyFields: _formState.dirtyFields,
|
|
2033
|
+
isDirty: _getDirty(name, cloneValue),
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
1982
2036
|
}
|
|
1983
2037
|
}
|
|
1984
2038
|
else {
|
|
1985
2039
|
const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
|
|
1986
2040
|
isEmptyObject(cloneValue);
|
|
1987
2041
|
if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
|
|
1988
|
-
setFieldValue(name, cloneValue, options, skipClone);
|
|
2042
|
+
setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
|
|
1989
2043
|
}
|
|
1990
2044
|
else {
|
|
1991
|
-
setFieldValues(name, cloneValue, options, skipClone);
|
|
2045
|
+
setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
|
|
1992
2046
|
}
|
|
1993
2047
|
}
|
|
1994
|
-
if (!isValueUnchanged) {
|
|
2048
|
+
if (!isValueUnchanged && !skipStateEmit) {
|
|
1995
2049
|
const watched = isWatched(name, _names);
|
|
1996
2050
|
const values = skipClone ? _formValues : cloneObject(_formValues);
|
|
1997
2051
|
_subjects.state.next({
|
|
@@ -2012,13 +2066,13 @@ function createFormControl(props = {}) {
|
|
|
2012
2066
|
...updatedFormValues,
|
|
2013
2067
|
};
|
|
2014
2068
|
for (const fieldName of _names.mount) {
|
|
2015
|
-
_setValue(fieldName, get(updatedFormValues, fieldName), options, true);
|
|
2069
|
+
_setValue(fieldName, get(updatedFormValues, fieldName), options, true, true);
|
|
2016
2070
|
}
|
|
2017
2071
|
_subjects.state.next({
|
|
2018
2072
|
..._formState,
|
|
2019
2073
|
name: undefined,
|
|
2020
2074
|
type: undefined,
|
|
2021
|
-
values: _formValues,
|
|
2075
|
+
...(_valuesSubscriberCount ? { values: _formValues } : {}),
|
|
2022
2076
|
});
|
|
2023
2077
|
if (options.shouldValidate) {
|
|
2024
2078
|
_setValid();
|
|
@@ -2037,8 +2091,6 @@ function createFormControl(props = {}) {
|
|
|
2037
2091
|
(isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
|
|
2038
2092
|
deepEqual(fieldValue, get(_formValues, name, fieldValue));
|
|
2039
2093
|
};
|
|
2040
|
-
const validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
2041
|
-
const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
2042
2094
|
if (field) {
|
|
2043
2095
|
let error;
|
|
2044
2096
|
let isValid;
|
|
@@ -2046,12 +2098,13 @@ function createFormControl(props = {}) {
|
|
|
2046
2098
|
? getFieldValue(field._f)
|
|
2047
2099
|
: getEventValue(event);
|
|
2048
2100
|
const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
|
|
2049
|
-
const
|
|
2101
|
+
const hasNoValidationEffect = !hasValidation(field._f) &&
|
|
2050
2102
|
!props.validate &&
|
|
2051
2103
|
!_options.resolver &&
|
|
2052
2104
|
!get(_formState.errors, name) &&
|
|
2053
|
-
!field._f.deps
|
|
2054
|
-
|
|
2105
|
+
!field._f.deps;
|
|
2106
|
+
const shouldSkipValidation = hasNoValidationEffect ||
|
|
2107
|
+
skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
|
|
2055
2108
|
const watched = isWatched(name, _names, isBlurEvent);
|
|
2056
2109
|
set(_formValues, name, fieldValue);
|
|
2057
2110
|
if (isBlurEvent) {
|
|
@@ -2069,10 +2122,13 @@ function createFormControl(props = {}) {
|
|
|
2069
2122
|
_subjects.state.next({
|
|
2070
2123
|
name,
|
|
2071
2124
|
type: event.type,
|
|
2072
|
-
|
|
2125
|
+
...(_valuesSubscriberCount
|
|
2126
|
+
? { values: cloneObject(_formValues) }
|
|
2127
|
+
: {}),
|
|
2073
2128
|
});
|
|
2074
2129
|
if (shouldSkipValidation) {
|
|
2075
|
-
if (
|
|
2130
|
+
if ((!hasNoValidationEffect || !_formState.isValid) &&
|
|
2131
|
+
(_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
|
|
2076
2132
|
if (_options.mode === 'onBlur') {
|
|
2077
2133
|
if (isBlurEvent) {
|
|
2078
2134
|
_setValid();
|
|
@@ -2207,8 +2263,6 @@ function createFormControl(props = {}) {
|
|
|
2207
2263
|
const names = name ? convertToArrayPayload(name) : undefined;
|
|
2208
2264
|
names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
|
|
2209
2265
|
if (names) {
|
|
2210
|
-
// Emit for each cleared field with the field name so that
|
|
2211
|
-
// shouldSubscribeByName can filter and avoid broad re-renders
|
|
2212
2266
|
names.forEach((inputName) => {
|
|
2213
2267
|
_subjects.state.next({
|
|
2214
2268
|
name: inputName,
|
|
@@ -2217,7 +2271,6 @@ function createFormControl(props = {}) {
|
|
|
2217
2271
|
});
|
|
2218
2272
|
}
|
|
2219
2273
|
else {
|
|
2220
|
-
// Clear all errors - emit without name to notify all subscribers
|
|
2221
2274
|
_subjects.state.next({
|
|
2222
2275
|
errors: {},
|
|
2223
2276
|
});
|
|
@@ -2226,7 +2279,6 @@ function createFormControl(props = {}) {
|
|
|
2226
2279
|
const setError = (name, error, options) => {
|
|
2227
2280
|
const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
|
|
2228
2281
|
const currentError = get(_formState.errors, name) || {};
|
|
2229
|
-
// Don't override existing error messages elsewhere in the object tree.
|
|
2230
2282
|
const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
|
|
2231
2283
|
set(_formState.errors, name, {
|
|
2232
2284
|
...restOfErrorTree,
|
|
@@ -2240,26 +2292,60 @@ function createFormControl(props = {}) {
|
|
|
2240
2292
|
});
|
|
2241
2293
|
options && options.shouldFocus && ref && ref.focus && ref.focus();
|
|
2242
2294
|
};
|
|
2243
|
-
const watch = (name, defaultValue) =>
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
}
|
|
2295
|
+
const watch = (name, defaultValue) => {
|
|
2296
|
+
if (isFunction(name)) {
|
|
2297
|
+
_valuesSubscriberCount++;
|
|
2298
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2299
|
+
next: (payload) => 'values' in payload &&
|
|
2300
|
+
name(payload.values || _getWatch(undefined, defaultValue), payload),
|
|
2301
|
+
});
|
|
2302
|
+
let called = false;
|
|
2303
|
+
return {
|
|
2304
|
+
unsubscribe: () => {
|
|
2305
|
+
if (called) {
|
|
2306
|
+
return;
|
|
2307
|
+
}
|
|
2308
|
+
called = true;
|
|
2309
|
+
_valuesSubscriberCount--;
|
|
2310
|
+
unsubscribe();
|
|
2311
|
+
},
|
|
2312
|
+
};
|
|
2313
|
+
}
|
|
2314
|
+
return _getWatch(name, defaultValue, true);
|
|
2315
|
+
};
|
|
2316
|
+
const _subscribe = (props) => {
|
|
2317
|
+
var _a;
|
|
2318
|
+
const needsValues = !!((_a = props.formState) === null || _a === void 0 ? void 0 : _a.values);
|
|
2319
|
+
if (needsValues) {
|
|
2320
|
+
_valuesSubscriberCount++;
|
|
2321
|
+
}
|
|
2322
|
+
const { unsubscribe } = _subjects.state.subscribe({
|
|
2323
|
+
next: (formState) => {
|
|
2324
|
+
if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
|
|
2325
|
+
shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
|
|
2326
|
+
const snapshot = { ..._formValues };
|
|
2327
|
+
props.callback({
|
|
2328
|
+
values: snapshot,
|
|
2329
|
+
..._formState,
|
|
2330
|
+
...formState,
|
|
2331
|
+
defaultValues: _defaultValues,
|
|
2332
|
+
});
|
|
2333
|
+
}
|
|
2334
|
+
},
|
|
2335
|
+
});
|
|
2336
|
+
if (!needsValues) {
|
|
2337
|
+
return unsubscribe;
|
|
2338
|
+
}
|
|
2339
|
+
let called = false;
|
|
2340
|
+
return () => {
|
|
2341
|
+
if (called) {
|
|
2342
|
+
return;
|
|
2260
2343
|
}
|
|
2261
|
-
|
|
2262
|
-
|
|
2344
|
+
called = true;
|
|
2345
|
+
_valuesSubscriberCount--;
|
|
2346
|
+
unsubscribe();
|
|
2347
|
+
};
|
|
2348
|
+
};
|
|
2263
2349
|
const subscribe = (props) => {
|
|
2264
2350
|
_state.mount = true;
|
|
2265
2351
|
_proxySubscribeFormState = {
|
|
@@ -2593,9 +2679,6 @@ function createFormControl(props = {}) {
|
|
|
2593
2679
|
_state.watch = !!_options.shouldUnregister;
|
|
2594
2680
|
_state.keepIsValid = !!keepStateOptions.keepIsValid;
|
|
2595
2681
|
_state.action = false;
|
|
2596
|
-
// Clear errors synchronously to prevent validation errors on subsequent submissions
|
|
2597
|
-
// This fixes the issue where form.reset() causes validation errors on subsequent
|
|
2598
|
-
// submissions in Next.js 16 with Server Actions
|
|
2599
2682
|
if (!keepStateOptions.keepErrors) {
|
|
2600
2683
|
_formState.errors = {};
|
|
2601
2684
|
}
|
|
@@ -2647,8 +2730,6 @@ function createFormControl(props = {}) {
|
|
|
2647
2730
|
? fieldReference.refs[0]
|
|
2648
2731
|
: fieldReference.ref;
|
|
2649
2732
|
if (fieldRef.focus) {
|
|
2650
|
-
// Use setTimeout to ensure focus happens after any pending state updates
|
|
2651
|
-
// This fixes the issue where setFocus doesn't work immediately after setError
|
|
2652
2733
|
setTimeout(() => {
|
|
2653
2734
|
fieldRef.focus();
|
|
2654
2735
|
options.shouldSelect &&
|
|
@@ -2742,6 +2823,8 @@ function createFormControl(props = {}) {
|
|
|
2742
2823
|
..._options,
|
|
2743
2824
|
...value,
|
|
2744
2825
|
};
|
|
2826
|
+
_validationModeBeforeSubmit = getValidationModes(_options.mode);
|
|
2827
|
+
_validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
|
|
2745
2828
|
},
|
|
2746
2829
|
},
|
|
2747
2830
|
subscribe,
|
|
@@ -2875,34 +2958,45 @@ var updateAt = (fieldValues, index, value) => {
|
|
|
2875
2958
|
*/
|
|
2876
2959
|
function useFieldArray(props) {
|
|
2877
2960
|
const formControl = useFormControlContext();
|
|
2878
|
-
const { control = formControl, name, keyName = 'id', shouldUnregister, rules, } = props;
|
|
2961
|
+
const { control = formControl, name, keyName = 'id', disabled, shouldUnregister, rules, } = props;
|
|
2879
2962
|
const [fields, setFields] = React.useState(control._getFieldArray(name));
|
|
2880
2963
|
const ids = React.useRef(control._getFieldArray(name).map(generateId));
|
|
2881
2964
|
const _actioned = React.useRef(false);
|
|
2882
|
-
|
|
2883
|
-
|
|
2965
|
+
if (!disabled) {
|
|
2966
|
+
control._names.array.add(name);
|
|
2967
|
+
}
|
|
2968
|
+
React.useMemo(() => !disabled &&
|
|
2969
|
+
rules &&
|
|
2884
2970
|
fields.length >= 0 &&
|
|
2885
|
-
control.register(name, rules), [control, name, fields.length, rules]);
|
|
2886
|
-
useIsomorphicLayoutEffect(() =>
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2971
|
+
control.register(name, rules), [control, name, fields.length, rules, disabled]);
|
|
2972
|
+
useIsomorphicLayoutEffect(() => {
|
|
2973
|
+
if (disabled) {
|
|
2974
|
+
return;
|
|
2975
|
+
}
|
|
2976
|
+
return control._subjects.array.subscribe({
|
|
2977
|
+
next: ({ values, name: fieldArrayName, }) => {
|
|
2978
|
+
if (fieldArrayName === name || !fieldArrayName) {
|
|
2979
|
+
const fieldValues = get(values, name);
|
|
2980
|
+
if (Array.isArray(fieldValues)) {
|
|
2981
|
+
setFields(fieldValues);
|
|
2982
|
+
ids.current = fieldValues.map(generateId);
|
|
2983
|
+
}
|
|
2984
|
+
else if (!fieldArrayName) {
|
|
2985
|
+
setFields([]);
|
|
2986
|
+
ids.current = [];
|
|
2987
|
+
}
|
|
2897
2988
|
}
|
|
2898
|
-
}
|
|
2899
|
-
}
|
|
2900
|
-
}
|
|
2989
|
+
},
|
|
2990
|
+
}).unsubscribe;
|
|
2991
|
+
}, [control, name, disabled]);
|
|
2901
2992
|
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
|
2902
2993
|
_actioned.current = true;
|
|
2903
2994
|
control._setFieldArray(name, updatedFieldArrayValues);
|
|
2904
2995
|
}, [control, name]);
|
|
2905
2996
|
const append = (value, options) => {
|
|
2997
|
+
if (disabled) {
|
|
2998
|
+
return;
|
|
2999
|
+
}
|
|
2906
3000
|
const appendValue = convertToArrayPayload(cloneObject(value));
|
|
2907
3001
|
const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
|
|
2908
3002
|
control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
|
|
@@ -2914,6 +3008,9 @@ function useFieldArray(props) {
|
|
|
2914
3008
|
});
|
|
2915
3009
|
};
|
|
2916
3010
|
const prepend = (value, options) => {
|
|
3011
|
+
if (disabled) {
|
|
3012
|
+
return;
|
|
3013
|
+
}
|
|
2917
3014
|
const prependValue = convertToArrayPayload(cloneObject(value));
|
|
2918
3015
|
const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
|
|
2919
3016
|
control._names.focus = getFocusFieldName(name, 0, options);
|
|
@@ -2925,6 +3022,9 @@ function useFieldArray(props) {
|
|
|
2925
3022
|
});
|
|
2926
3023
|
};
|
|
2927
3024
|
const remove = (index) => {
|
|
3025
|
+
if (disabled) {
|
|
3026
|
+
return;
|
|
3027
|
+
}
|
|
2928
3028
|
const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
|
|
2929
3029
|
ids.current = removeArrayAt(ids.current, index);
|
|
2930
3030
|
updateValues(updatedFieldArrayValues);
|
|
@@ -2936,6 +3036,9 @@ function useFieldArray(props) {
|
|
|
2936
3036
|
});
|
|
2937
3037
|
};
|
|
2938
3038
|
const insert$1 = (index, value, options) => {
|
|
3039
|
+
if (disabled) {
|
|
3040
|
+
return;
|
|
3041
|
+
}
|
|
2939
3042
|
const insertValue = convertToArrayPayload(cloneObject(value));
|
|
2940
3043
|
const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
|
|
2941
3044
|
control._names.focus = getFocusFieldName(name, index, options);
|
|
@@ -2948,6 +3051,9 @@ function useFieldArray(props) {
|
|
|
2948
3051
|
});
|
|
2949
3052
|
};
|
|
2950
3053
|
const swap = (indexA, indexB) => {
|
|
3054
|
+
if (disabled) {
|
|
3055
|
+
return;
|
|
3056
|
+
}
|
|
2951
3057
|
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
2952
3058
|
swapArrayAt(updatedFieldArrayValues, indexA, indexB);
|
|
2953
3059
|
swapArrayAt(ids.current, indexA, indexB);
|
|
@@ -2959,6 +3065,9 @@ function useFieldArray(props) {
|
|
|
2959
3065
|
}, false);
|
|
2960
3066
|
};
|
|
2961
3067
|
const move = (from, to) => {
|
|
3068
|
+
if (disabled) {
|
|
3069
|
+
return;
|
|
3070
|
+
}
|
|
2962
3071
|
const updatedFieldArrayValues = control._getFieldArray(name);
|
|
2963
3072
|
moveArrayAt(updatedFieldArrayValues, from, to);
|
|
2964
3073
|
moveArrayAt(ids.current, from, to);
|
|
@@ -2970,6 +3079,9 @@ function useFieldArray(props) {
|
|
|
2970
3079
|
}, false);
|
|
2971
3080
|
};
|
|
2972
3081
|
const update = (index, value) => {
|
|
3082
|
+
if (disabled) {
|
|
3083
|
+
return;
|
|
3084
|
+
}
|
|
2973
3085
|
const updateValue = cloneObject(value);
|
|
2974
3086
|
const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
|
|
2975
3087
|
ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
|
|
@@ -2981,6 +3093,9 @@ function useFieldArray(props) {
|
|
|
2981
3093
|
}, true, false);
|
|
2982
3094
|
};
|
|
2983
3095
|
const replace = (value) => {
|
|
3096
|
+
if (disabled) {
|
|
3097
|
+
return;
|
|
3098
|
+
}
|
|
2984
3099
|
const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
|
|
2985
3100
|
ids.current = updatedFieldArrayValues.map(generateId);
|
|
2986
3101
|
updateValues([...updatedFieldArrayValues]);
|
|
@@ -2988,6 +3103,9 @@ function useFieldArray(props) {
|
|
|
2988
3103
|
control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
|
|
2989
3104
|
};
|
|
2990
3105
|
React.useEffect(() => {
|
|
3106
|
+
if (disabled) {
|
|
3107
|
+
return;
|
|
3108
|
+
}
|
|
2991
3109
|
control._state.action = false;
|
|
2992
3110
|
isWatched(name, control._names) &&
|
|
2993
3111
|
control._subjects.state.next({
|
|
@@ -3048,10 +3166,15 @@ function useFieldArray(props) {
|
|
|
3048
3166
|
control._names.focus = '';
|
|
3049
3167
|
control._setValid();
|
|
3050
3168
|
_actioned.current = false;
|
|
3051
|
-
}, [fields, name, control]);
|
|
3169
|
+
}, [fields, name, control, disabled]);
|
|
3052
3170
|
React.useEffect(() => {
|
|
3053
|
-
!
|
|
3171
|
+
if (!disabled) {
|
|
3172
|
+
!get(control._formValues, name) && control._setFieldArray(name);
|
|
3173
|
+
}
|
|
3054
3174
|
return () => {
|
|
3175
|
+
if (disabled) {
|
|
3176
|
+
return;
|
|
3177
|
+
}
|
|
3055
3178
|
const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
|
|
3056
3179
|
const updateMounted = (name, value) => {
|
|
3057
3180
|
const field = get(control._fields, name);
|
|
@@ -3069,20 +3192,31 @@ function useFieldArray(props) {
|
|
|
3069
3192
|
? updateMounted(name, false)
|
|
3070
3193
|
: control.unregister(name);
|
|
3071
3194
|
};
|
|
3072
|
-
}, [name, control, keyName, shouldUnregister]);
|
|
3195
|
+
}, [name, control, keyName, shouldUnregister, disabled]);
|
|
3073
3196
|
return {
|
|
3074
|
-
swap: React.useCallback(swap, [updateValues, name, control]),
|
|
3075
|
-
move: React.useCallback(move, [updateValues, name, control]),
|
|
3076
|
-
prepend: React.useCallback(prepend, [
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3197
|
+
swap: React.useCallback(swap, [updateValues, name, control, disabled]),
|
|
3198
|
+
move: React.useCallback(move, [updateValues, name, control, disabled]),
|
|
3199
|
+
prepend: React.useCallback(prepend, [
|
|
3200
|
+
updateValues,
|
|
3201
|
+
name,
|
|
3202
|
+
control,
|
|
3203
|
+
disabled,
|
|
3204
|
+
]),
|
|
3205
|
+
append: React.useCallback(append, [updateValues, name, control, disabled]),
|
|
3206
|
+
remove: React.useCallback(remove, [updateValues, name, control, disabled]),
|
|
3207
|
+
insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
|
|
3208
|
+
update: React.useCallback(update, [updateValues, name, control, disabled]),
|
|
3209
|
+
replace: React.useCallback(replace, [
|
|
3210
|
+
updateValues,
|
|
3211
|
+
name,
|
|
3212
|
+
control,
|
|
3213
|
+
disabled,
|
|
3214
|
+
]),
|
|
3082
3215
|
fields: React.useMemo(() => fields.map((field, index) => ({
|
|
3083
3216
|
...field,
|
|
3217
|
+
...(isBoolean(disabled) ? { disabled } : {}),
|
|
3084
3218
|
[keyName]: ids.current[index] || generateId(),
|
|
3085
|
-
})), [fields, keyName]),
|
|
3219
|
+
})), [fields, keyName, disabled]),
|
|
3086
3220
|
};
|
|
3087
3221
|
}
|
|
3088
3222
|
|
|
@@ -3118,6 +3252,7 @@ function useFieldArray(props) {
|
|
|
3118
3252
|
function useForm(props = {}) {
|
|
3119
3253
|
const _formControl = React.useRef(undefined);
|
|
3120
3254
|
const _values = React.useRef(undefined);
|
|
3255
|
+
const _formControlProp = React.useRef(props.formControl);
|
|
3121
3256
|
const [formState, updateFormState] = React.useState(() => ({
|
|
3122
3257
|
...cloneObject(DEFAULT_FORM_STATE),
|
|
3123
3258
|
isLoading: isFunction(props.defaultValues),
|
|
@@ -3127,7 +3262,9 @@ function useForm(props = {}) {
|
|
|
3127
3262
|
? undefined
|
|
3128
3263
|
: props.defaultValues,
|
|
3129
3264
|
}));
|
|
3130
|
-
if (!_formControl.current
|
|
3265
|
+
if (!_formControl.current ||
|
|
3266
|
+
(props.formControl && _formControlProp.current !== props.formControl)) {
|
|
3267
|
+
_formControlProp.current = props.formControl;
|
|
3131
3268
|
if (props.formControl) {
|
|
3132
3269
|
_formControl.current = {
|
|
3133
3270
|
...props.formControl,
|