react-hook-form 7.39.3 → 7.40.0-next.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/__typetest__/__fixtures__/pathString.d.ts +2 -2
- package/dist/__typetest__/__fixtures__/pathString.d.ts.map +1 -1
- package/dist/__typetest__/__fixtures__/traversable.d.ts +3 -3
- package/dist/__typetest__/__fixtures__/traversable.d.ts.map +1 -1
- package/dist/__typetest__/__fixtures__/tuple.d.ts +2 -2
- package/dist/__typetest__/__fixtures__/tuple.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 +112 -92
- 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/getCheckboxValue.d.ts +1 -1
- package/dist/logic/getCheckboxValue.d.ts.map +1 -1
- package/dist/logic/getRadioValue.d.ts +1 -1
- package/dist/logic/getRadioValue.d.ts.map +1 -1
- package/dist/types/controller.d.ts +5 -5
- package/dist/types/controller.d.ts.map +1 -1
- package/dist/types/errors.d.ts +8 -8
- package/dist/types/errors.d.ts.map +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/fieldArray.d.ts +13 -13
- package/dist/types/fieldArray.d.ts.map +1 -1
- package/dist/types/fields.d.ts +10 -10
- package/dist/types/fields.d.ts.map +1 -1
- package/dist/types/form.d.ts +56 -52
- package/dist/types/form.d.ts.map +1 -1
- package/dist/types/path/common.d.ts +32 -32
- package/dist/types/path/common.d.ts.map +1 -1
- package/dist/types/path/eager.d.ts +11 -11
- package/dist/types/path/eager.d.ts.map +1 -1
- package/dist/types/resolvers.d.ts +4 -4
- package/dist/types/resolvers.d.ts.map +1 -1
- package/dist/types/utils.d.ts +13 -13
- package/dist/types/utils.d.ts.map +1 -1
- package/dist/types/validator.d.ts +6 -6
- package/dist/types/validator.d.ts.map +1 -1
- package/dist/useFieldArray.d.ts.map +1 -1
- package/dist/useForm.d.ts.map +1 -1
- package/dist/useFormState.d.ts.map +1 -1
- package/dist/useSubscribe.d.ts +2 -2
- package/dist/useSubscribe.d.ts.map +1 -1
- package/dist/useWatch.d.ts.map +1 -1
- package/dist/utils/createSubject.d.ts +3 -3
- package/dist/utils/createSubject.d.ts.map +1 -1
- package/dist/utils/isHTMLElement.d.ts.map +1 -1
- package/package.json +3 -3
package/dist/index.esm.mjs
CHANGED
@@ -173,7 +173,7 @@ function useSubscribe(props) {
|
|
173
173
|
React.useEffect(() => {
|
174
174
|
const subscription = !props.disabled &&
|
175
175
|
_props.current.subject.subscribe({
|
176
|
-
next: _props.current.
|
176
|
+
next: _props.current.next,
|
177
177
|
});
|
178
178
|
return () => {
|
179
179
|
subscription && subscription.unsubscribe();
|
@@ -228,21 +228,28 @@ function useFormState(props) {
|
|
228
228
|
_name.current = name;
|
229
229
|
useSubscribe({
|
230
230
|
disabled,
|
231
|
-
|
231
|
+
next: (value) => _mounted.current &&
|
232
232
|
shouldSubscribeByName(_name.current, value.name, exact) &&
|
233
233
|
shouldRenderFormState(value, _localProxyFormState.current) &&
|
234
234
|
updateFormState({
|
235
235
|
...control._formState,
|
236
236
|
...value,
|
237
|
-
}),
|
237
|
+
}),
|
238
238
|
subject: control._subjects.state,
|
239
239
|
});
|
240
240
|
React.useEffect(() => {
|
241
241
|
_mounted.current = true;
|
242
|
+
const isDirty = control._proxyFormState.isDirty && control._getDirty();
|
243
|
+
if (isDirty !== control._formState.isDirty) {
|
244
|
+
control._subjects.state.next({
|
245
|
+
isDirty,
|
246
|
+
});
|
247
|
+
}
|
248
|
+
control._updateValid();
|
242
249
|
return () => {
|
243
250
|
_mounted.current = false;
|
244
251
|
};
|
245
|
-
}, []);
|
252
|
+
}, [control]);
|
246
253
|
return getProxyFormState(formState, control, _localProxyFormState.current, false);
|
247
254
|
}
|
248
255
|
|
@@ -262,16 +269,41 @@ var generateWatchOutput = (names, _names, formValues, isGlobal) => {
|
|
262
269
|
return formValues;
|
263
270
|
};
|
264
271
|
|
265
|
-
var
|
272
|
+
var isPlainObject = (tempObject) => {
|
273
|
+
const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
|
274
|
+
return (isObject(prototypeCopy) && prototypeCopy.hasOwnProperty('isPrototypeOf'));
|
275
|
+
};
|
266
276
|
|
267
|
-
var
|
268
|
-
|
269
|
-
|
270
|
-
|
277
|
+
var isWeb = typeof window !== 'undefined' &&
|
278
|
+
typeof window.HTMLElement !== 'undefined' &&
|
279
|
+
typeof document !== 'undefined';
|
280
|
+
|
281
|
+
function cloneObject(data) {
|
282
|
+
let copy;
|
283
|
+
const isArray = Array.isArray(data);
|
284
|
+
if (data instanceof Date) {
|
285
|
+
copy = new Date(data);
|
286
|
+
}
|
287
|
+
else if (data instanceof Set) {
|
288
|
+
copy = new Set(data);
|
289
|
+
}
|
290
|
+
else if (!(isWeb && (data instanceof Blob || data instanceof FileList)) &&
|
291
|
+
(isArray || isObject(data))) {
|
292
|
+
copy = isArray ? [] : {};
|
293
|
+
if (!Array.isArray(data) && !isPlainObject(data)) {
|
294
|
+
copy = data;
|
295
|
+
}
|
296
|
+
else {
|
297
|
+
for (const key in data) {
|
298
|
+
copy[key] = cloneObject(data[key]);
|
299
|
+
}
|
271
300
|
}
|
272
301
|
}
|
273
|
-
|
274
|
-
|
302
|
+
else {
|
303
|
+
return data;
|
304
|
+
}
|
305
|
+
return copy;
|
306
|
+
}
|
275
307
|
|
276
308
|
/**
|
277
309
|
* Custom hook to subscribe to field change and isolate re-rendering at the component level.
|
@@ -297,19 +329,16 @@ function useWatch(props) {
|
|
297
329
|
useSubscribe({
|
298
330
|
disabled,
|
299
331
|
subject: control._subjects.watch,
|
300
|
-
|
332
|
+
next: (formState) => {
|
301
333
|
if (shouldSubscribeByName(_name.current, formState.name, exact)) {
|
302
334
|
const fieldValues = generateWatchOutput(_name.current, control._names, formState.values || control._formValues);
|
303
|
-
updateValue(isUndefined(_name.current) ||
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
: isUndefined(fieldValues)
|
309
|
-
? defaultValue
|
310
|
-
: fieldValues);
|
335
|
+
updateValue(isUndefined(_name.current) || !isUndefined(fieldValues)
|
336
|
+
? cloneObject(fieldValues)
|
337
|
+
: isUndefined(fieldValues)
|
338
|
+
? defaultValue
|
339
|
+
: fieldValues);
|
311
340
|
}
|
312
|
-
},
|
341
|
+
},
|
313
342
|
});
|
314
343
|
const [value, updateValue] = React.useState(isUndefined(defaultValue)
|
315
344
|
? control._getWatch(name)
|
@@ -562,6 +591,8 @@ var isBoolean = (value) => typeof value === 'boolean';
|
|
562
591
|
|
563
592
|
var isFileInput = (element) => element.type === 'file';
|
564
593
|
|
594
|
+
var isFunction = (value) => typeof value === 'function';
|
595
|
+
|
565
596
|
var isMessage = (value) => isString(value) || React.isValidElement(value);
|
566
597
|
|
567
598
|
var isRadioInput = (element) => element.type === 'radio';
|
@@ -632,8 +663,8 @@ var validateField = async (field, inputValue, validateAllFieldCriteria, shouldUs
|
|
632
663
|
}
|
633
664
|
const inputRef = refs ? refs[0] : ref;
|
634
665
|
const setCustomValidity = (message) => {
|
635
|
-
if (shouldUseNativeValidation &&
|
636
|
-
inputRef.setCustomValidity(message);
|
666
|
+
if (shouldUseNativeValidation && inputRef.reportValidity) {
|
667
|
+
inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
|
637
668
|
inputRef.reportValidity();
|
638
669
|
}
|
639
670
|
};
|
@@ -804,42 +835,6 @@ function append(data, value) {
|
|
804
835
|
return [...data, ...convertToArrayPayload(value)];
|
805
836
|
}
|
806
837
|
|
807
|
-
var isPlainObject = (tempObject) => {
|
808
|
-
const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
|
809
|
-
return (isObject(prototypeCopy) && prototypeCopy.hasOwnProperty('isPrototypeOf'));
|
810
|
-
};
|
811
|
-
|
812
|
-
var isWeb = typeof window !== 'undefined' &&
|
813
|
-
typeof window.HTMLElement !== 'undefined' &&
|
814
|
-
typeof document !== 'undefined';
|
815
|
-
|
816
|
-
function cloneObject(data) {
|
817
|
-
let copy;
|
818
|
-
const isArray = Array.isArray(data);
|
819
|
-
if (data instanceof Date) {
|
820
|
-
copy = new Date(data);
|
821
|
-
}
|
822
|
-
else if (data instanceof Set) {
|
823
|
-
copy = new Set(data);
|
824
|
-
}
|
825
|
-
else if (!(isWeb && (data instanceof Blob || data instanceof FileList)) &&
|
826
|
-
(isArray || isObject(data))) {
|
827
|
-
copy = isArray ? [] : {};
|
828
|
-
if (!Array.isArray(data) && !isPlainObject(data)) {
|
829
|
-
copy = data;
|
830
|
-
}
|
831
|
-
else {
|
832
|
-
for (const key in data) {
|
833
|
-
copy[key] = cloneObject(data[key]);
|
834
|
-
}
|
835
|
-
}
|
836
|
-
}
|
837
|
-
else {
|
838
|
-
return data;
|
839
|
-
}
|
840
|
-
return copy;
|
841
|
-
}
|
842
|
-
|
843
838
|
var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
|
844
839
|
|
845
840
|
var getValidationModes = (mode) => ({
|
@@ -991,17 +986,16 @@ function useFieldArray(props) {
|
|
991
986
|
control._names.array.add(name);
|
992
987
|
props.rules &&
|
993
988
|
control.register(name, props.rules);
|
994
|
-
const callback = React.useCallback(({ values, name: fieldArrayName, }) => {
|
995
|
-
if (fieldArrayName === _name.current || !fieldArrayName) {
|
996
|
-
const fieldValues = get(values, _name.current);
|
997
|
-
if (Array.isArray(fieldValues)) {
|
998
|
-
setFields(fieldValues);
|
999
|
-
ids.current = fieldValues.map(generateId);
|
1000
|
-
}
|
1001
|
-
}
|
1002
|
-
}, []);
|
1003
989
|
useSubscribe({
|
1004
|
-
|
990
|
+
next: ({ values, name: fieldArrayName, }) => {
|
991
|
+
if (fieldArrayName === _name.current || !fieldArrayName) {
|
992
|
+
const fieldValues = get(values, _name.current);
|
993
|
+
if (Array.isArray(fieldValues)) {
|
994
|
+
setFields(fieldValues);
|
995
|
+
ids.current = fieldValues.map(generateId);
|
996
|
+
}
|
997
|
+
}
|
998
|
+
},
|
1005
999
|
subject: control._subjects.array,
|
1006
1000
|
});
|
1007
1001
|
const updateValues = React.useCallback((updatedFieldArrayValues) => {
|
@@ -1216,8 +1210,8 @@ function deepEqual(object1, object2) {
|
|
1216
1210
|
|
1217
1211
|
var isHTMLElement = (value) => {
|
1218
1212
|
const owner = value ? value.ownerDocument : 0;
|
1219
|
-
|
1220
|
-
|
1213
|
+
return (value instanceof
|
1214
|
+
(owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
|
1221
1215
|
};
|
1222
1216
|
|
1223
1217
|
var isMultipleSelect = (element) => element.type === `select-multiple`;
|
@@ -1226,6 +1220,15 @@ var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
|
|
1226
1220
|
|
1227
1221
|
var live = (ref) => isHTMLElement(ref) && ref.isConnected;
|
1228
1222
|
|
1223
|
+
var objectHasFunction = (data) => {
|
1224
|
+
for (const key in data) {
|
1225
|
+
if (isFunction(data[key])) {
|
1226
|
+
return true;
|
1227
|
+
}
|
1228
|
+
}
|
1229
|
+
return false;
|
1230
|
+
};
|
1231
|
+
|
1229
1232
|
function markFieldsDirty(data, fields = {}) {
|
1230
1233
|
const isParentNodeArray = Array.isArray(data);
|
1231
1234
|
if (isObject(data) || isParentNodeArray) {
|
@@ -1406,7 +1409,9 @@ function createFormControl(props = {}) {
|
|
1406
1409
|
errors: {},
|
1407
1410
|
};
|
1408
1411
|
let _fields = {};
|
1409
|
-
let _defaultValues =
|
1412
|
+
let _defaultValues = isObject(_options.defaultValues)
|
1413
|
+
? cloneObject(_options.defaultValues) || {}
|
1414
|
+
: {};
|
1410
1415
|
let _formValues = _options.shouldUnregister
|
1411
1416
|
? {}
|
1412
1417
|
: cloneObject(_defaultValues);
|
@@ -1512,37 +1517,39 @@ function createFormControl(props = {}) {
|
|
1512
1517
|
}
|
1513
1518
|
};
|
1514
1519
|
const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
|
1515
|
-
let
|
1520
|
+
let shouldUpdateField = false;
|
1521
|
+
let isPreviousDirty = false;
|
1516
1522
|
const output = {
|
1517
1523
|
name,
|
1518
1524
|
};
|
1519
|
-
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1520
1525
|
if (_proxyFormState.isDirty) {
|
1521
|
-
|
1526
|
+
isPreviousDirty = _formState.isDirty;
|
1522
1527
|
_formState.isDirty = output.isDirty = _getDirty();
|
1523
|
-
|
1528
|
+
shouldUpdateField = isPreviousDirty !== output.isDirty;
|
1524
1529
|
}
|
1525
1530
|
if (_proxyFormState.dirtyFields && (!isBlurEvent || shouldDirty)) {
|
1526
|
-
|
1531
|
+
isPreviousDirty = get(_formState.dirtyFields, name);
|
1527
1532
|
const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
|
1528
1533
|
isCurrentFieldPristine
|
1529
1534
|
? unset(_formState.dirtyFields, name)
|
1530
1535
|
: set(_formState.dirtyFields, name, true);
|
1531
1536
|
output.dirtyFields = _formState.dirtyFields;
|
1532
|
-
|
1533
|
-
|
1534
|
-
isPreviousFieldDirty !== get(_formState.dirtyFields, name);
|
1537
|
+
shouldUpdateField =
|
1538
|
+
shouldUpdateField || isPreviousDirty !== !isCurrentFieldPristine;
|
1535
1539
|
}
|
1536
|
-
if (isBlurEvent
|
1537
|
-
|
1538
|
-
|
1539
|
-
|
1540
|
-
|
1541
|
-
|
1542
|
-
|
1540
|
+
if (isBlurEvent) {
|
1541
|
+
const isPreviousFieldTouched = get(_formState.touchedFields, name);
|
1542
|
+
if (!isPreviousFieldTouched) {
|
1543
|
+
set(_formState.touchedFields, name, isBlurEvent);
|
1544
|
+
output.touchedFields = _formState.touchedFields;
|
1545
|
+
shouldUpdateField =
|
1546
|
+
shouldUpdateField ||
|
1547
|
+
(_proxyFormState.touchedFields &&
|
1548
|
+
isPreviousFieldTouched !== isBlurEvent);
|
1549
|
+
}
|
1543
1550
|
}
|
1544
|
-
|
1545
|
-
return
|
1551
|
+
shouldUpdateField && shouldRender && _subjects.state.next(output);
|
1552
|
+
return shouldUpdateField ? output : {};
|
1546
1553
|
};
|
1547
1554
|
const shouldRenderByError = (name, isValid, error, fieldState) => {
|
1548
1555
|
const previousFieldError = get(_formState.errors, name);
|
@@ -2168,6 +2175,11 @@ function createFormControl(props = {}) {
|
|
2168
2175
|
}
|
2169
2176
|
}
|
2170
2177
|
};
|
2178
|
+
if (isFunction(_options.defaultValues)) {
|
2179
|
+
_options.defaultValues().then((values) => {
|
2180
|
+
reset(values, _options.resetOptions);
|
2181
|
+
});
|
2182
|
+
}
|
2171
2183
|
return {
|
2172
2184
|
control: {
|
2173
2185
|
register,
|
@@ -2181,6 +2193,7 @@ function createFormControl(props = {}) {
|
|
2181
2193
|
_removeUnmounted,
|
2182
2194
|
_updateFieldArray,
|
2183
2195
|
_getFieldArray,
|
2196
|
+
_reset,
|
2184
2197
|
_subjects,
|
2185
2198
|
_proxyFormState,
|
2186
2199
|
get _fields() {
|
@@ -2278,7 +2291,9 @@ function useForm(props = {}) {
|
|
2278
2291
|
dirtyFields: {},
|
2279
2292
|
touchedFields: {},
|
2280
2293
|
errors: {},
|
2281
|
-
defaultValues: props.defaultValues
|
2294
|
+
defaultValues: isFunction(props.defaultValues)
|
2295
|
+
? undefined
|
2296
|
+
: props.defaultValues,
|
2282
2297
|
});
|
2283
2298
|
if (!_formControl.current) {
|
2284
2299
|
_formControl.current = {
|
@@ -2290,7 +2305,7 @@ function useForm(props = {}) {
|
|
2290
2305
|
control._options = props;
|
2291
2306
|
useSubscribe({
|
2292
2307
|
subject: control._subjects.state,
|
2293
|
-
|
2308
|
+
next: (value) => {
|
2294
2309
|
if (shouldRenderFormState(value, control._proxyFormState, true)) {
|
2295
2310
|
control._formState = {
|
2296
2311
|
...control._formState,
|
@@ -2298,7 +2313,7 @@ function useForm(props = {}) {
|
|
2298
2313
|
};
|
2299
2314
|
updateFormState({ ...control._formState });
|
2300
2315
|
}
|
2301
|
-
},
|
2316
|
+
},
|
2302
2317
|
});
|
2303
2318
|
React.useEffect(() => {
|
2304
2319
|
if (!control._stateFlags.mount) {
|
@@ -2311,6 +2326,11 @@ function useForm(props = {}) {
|
|
2311
2326
|
}
|
2312
2327
|
control._removeUnmounted();
|
2313
2328
|
});
|
2329
|
+
React.useEffect(() => {
|
2330
|
+
if (props.values && !deepEqual(props.values, control._defaultValues)) {
|
2331
|
+
control._reset(props.values, control._options.resetOptions);
|
2332
|
+
}
|
2333
|
+
}, [props.values, control]);
|
2314
2334
|
React.useEffect(() => {
|
2315
2335
|
formState.submitCount && control._focusError();
|
2316
2336
|
}, [control, formState.submitCount]);
|