react-hook-form 7.85.0 → 7.87.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.
Files changed (55) hide show
  1. package/dist/controller.d.ts +1 -2
  2. package/dist/controller.d.ts.map +1 -1
  3. package/dist/form.d.ts +1 -2
  4. package/dist/form.d.ts.map +1 -1
  5. package/dist/{formStateSubscribe.d.ts → formState.d.ts} +1 -1
  6. package/dist/formState.d.ts.map +1 -0
  7. package/dist/index.cjs.js +1 -1
  8. package/dist/index.cjs.js.map +1 -1
  9. package/dist/index.d.ts +2 -2
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.esm.mjs +185 -102
  12. package/dist/index.esm.mjs.map +1 -1
  13. package/dist/index.umd.js +1 -1
  14. package/dist/index.umd.js.map +1 -1
  15. package/dist/logic/createFormControl.d.ts.map +1 -1
  16. package/dist/logic/generateId.d.ts.map +1 -1
  17. package/dist/logic/getCheckboxValue.d.ts.map +1 -1
  18. package/dist/logic/getFieldArrayItemNames.d.ts +4 -0
  19. package/dist/logic/getFieldArrayItemNames.d.ts.map +1 -0
  20. package/dist/logic/getNullAncestorValue.d.ts +5 -0
  21. package/dist/logic/getNullAncestorValue.d.ts.map +1 -0
  22. package/dist/logic/getProxyFormState.d.ts +1 -1
  23. package/dist/logic/getProxyFormState.d.ts.map +1 -1
  24. package/dist/logic/hasValidation.d.ts +1 -1
  25. package/dist/logic/hasValidation.d.ts.map +1 -1
  26. package/dist/logic/validateField.d.ts.map +1 -1
  27. package/dist/types/errors.d.ts +3 -3
  28. package/dist/types/errors.d.ts.map +1 -1
  29. package/dist/types/form.d.ts +49 -3
  30. package/dist/types/form.d.ts.map +1 -1
  31. package/dist/types/path/eager.d.ts +3 -3
  32. package/dist/types/path/eager.d.ts.map +1 -1
  33. package/dist/types/utils.d.ts +29 -4
  34. package/dist/types/utils.d.ts.map +1 -1
  35. package/dist/useController.d.ts.map +1 -1
  36. package/dist/useFieldArray.d.ts.map +1 -1
  37. package/dist/useFormContext.d.ts +1 -1
  38. package/dist/useFormContext.d.ts.map +1 -1
  39. package/dist/useFormState.d.ts.map +1 -1
  40. package/dist/useResyncOnReconnect.d.ts +1 -1
  41. package/dist/useResyncOnReconnect.d.ts.map +1 -1
  42. package/dist/utils/cloneObject.d.ts.map +1 -1
  43. package/dist/utils/deepEqual.d.ts +1 -1
  44. package/dist/utils/deepEqual.d.ts.map +1 -1
  45. package/dist/utils/flatten.d.ts.map +1 -1
  46. package/dist/utils/has.d.ts +3 -0
  47. package/dist/utils/has.d.ts.map +1 -0
  48. package/dist/utils/json.d.ts +2 -2
  49. package/dist/utils/json.d.ts.map +1 -1
  50. package/package.json +1 -2
  51. package/dist/formStateSubscribe.d.ts.map +0 -1
  52. package/dist/index.react-server.d.ts +0 -3
  53. package/dist/index.react-server.d.ts.map +0 -1
  54. package/dist/react-server.esm.mjs +0 -2367
  55. package/dist/react-server.esm.mjs.map +0 -1
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  export * from './controller';
2
2
  export { FieldArray } from './fieldArray';
3
3
  export * from './form';
4
- export type { FormStateProps, FormStateSubscribeProps, } from './formStateSubscribe';
5
- export { FormState, FormStateSubscribe } from './formStateSubscribe';
4
+ export type { FormStateProps, FormStateSubscribeProps } from './formState';
5
+ export { FormState, FormStateSubscribe } from './formState';
6
6
  export * from './logic';
7
7
  export * from './types';
8
8
  export * from './useController';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,YAAY,EACV,cAAc,EACd,uBAAuB,GACxB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AACrE,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,cAAc,QAAQ,CAAC;AACvB,YAAY,EAAE,cAAc,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAC5D,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
@@ -22,20 +22,36 @@ var getEventValue = (event) => isObject(event) && event.target
22
22
  : event.target.value
23
23
  : event;
24
24
 
25
+ const FIELD_PATH_RE = /[.[\]'"]/;
26
+ var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
27
+
28
+ function getNullAncestorValue(control, name) {
29
+ const segments = stringToPath(name);
30
+ let formValues = control._formValues;
31
+ let defaultValues = control._defaultValues;
32
+ for (let i = 0; i < segments.length - 1; i++) {
33
+ const key = segments[i];
34
+ formValues = formValues == null ? formValues : formValues[key];
35
+ defaultValues = defaultValues == null ? defaultValues : defaultValues[key];
36
+ if (formValues === null || defaultValues === null) {
37
+ return null;
38
+ }
39
+ }
40
+ return undefined;
41
+ }
42
+
25
43
  var isNameInFieldArray = (names, name) => name
26
44
  .split('.')
27
45
  .some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
28
46
 
29
- var isPlainObject = (tempObject) => {
30
- const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
31
- return (isObject(prototypeCopy) && prototypeCopy.hasOwnProperty('isPrototypeOf'));
32
- };
33
-
34
47
  var isWeb = typeof window !== 'undefined' &&
35
48
  typeof window.HTMLElement !== 'undefined' &&
36
49
  typeof document !== 'undefined';
37
50
 
38
51
  function cloneObject(data) {
52
+ if (data === null || typeof data !== 'object') {
53
+ return data;
54
+ }
39
55
  if (data instanceof Date) {
40
56
  return new Date(data);
41
57
  }
@@ -44,7 +60,7 @@ function cloneObject(data) {
44
60
  return data;
45
61
  }
46
62
  const isArray = Array.isArray(data);
47
- if (!isArray && !(isObject(data) && isPlainObject(data))) {
63
+ if (!isArray && data.constructor !== Object) {
48
64
  return data;
49
65
  }
50
66
  const copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
@@ -88,9 +104,6 @@ var isKey = (value) => IS_KEY_RE.test(value);
88
104
 
89
105
  var isUndefined = (val) => val === undefined;
90
106
 
91
- const FIELD_PATH_RE = /[.[\]'"]/;
92
- var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
93
-
94
107
  var get = (object, path, defaultValue) => {
95
108
  if (!path || !isObject(object)) {
96
109
  return defaultValue;
@@ -170,6 +183,11 @@ const useIsomorphicLayoutEffect = isWeb
170
183
  ? React.useLayoutEffect
171
184
  : React.useEffect;
172
185
 
186
+ var isPlainObject = (tempObject) => {
187
+ const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
188
+ return (isObject(prototypeCopy) && prototypeCopy.hasOwnProperty('isPrototypeOf'));
189
+ };
190
+
173
191
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
174
192
 
175
193
  const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
@@ -226,11 +244,20 @@ function deepEqual(object1, object2, visited = new WeakMap()) {
226
244
  return true;
227
245
  }
228
246
 
229
- function useResyncOnReconnect() {
247
+ function useResyncOnReconnect(getInitialValue) {
230
248
  const _connected = React.useRef(false);
249
+ const _initialized = React.useRef(false);
231
250
  const _prevValue = React.useRef(undefined);
251
+ const _renderCount = React.useRef(0);
252
+ _renderCount.current++;
253
+ if (!_initialized.current && getInitialValue) {
254
+ _initialized.current = true;
255
+ _prevValue.current = cloneObject(getInitialValue());
256
+ }
232
257
  const resyncIfNeeded = React.useCallback((enabled, getCurrentValue, setValue) => {
233
- if (enabled && _connected.current) {
258
+ if (enabled &&
259
+ (_connected.current ||
260
+ (_initialized.current && _renderCount.current > 1))) {
234
261
  const currentValue = getCurrentValue();
235
262
  if (!deepEqual(_prevValue.current, currentValue)) {
236
263
  setValue(currentValue);
@@ -279,10 +306,11 @@ function useResyncOnReconnect() {
279
306
  function useFormState(props) {
280
307
  const formControl = useFormControlContext();
281
308
  const { control = formControl, disabled, name, exact } = props || {};
282
- const [formState, updateFormState] = React.useState(() => ({
309
+ const getCurrentFormState = () => ({
283
310
  ...control._formState,
284
311
  defaultValues: control._defaultValues,
285
- }));
312
+ });
313
+ const [formState, updateFormState] = React.useState(getCurrentFormState);
286
314
  const _localProxyFormState = React.useRef({
287
315
  isDirty: false,
288
316
  isLoading: false,
@@ -293,12 +321,8 @@ function useFormState(props) {
293
321
  isValid: false,
294
322
  errors: false,
295
323
  });
296
- const { resyncIfNeeded, snapshot } = useResyncOnReconnect();
324
+ const { resyncIfNeeded, snapshot } = useResyncOnReconnect(getCurrentFormState);
297
325
  useIsomorphicLayoutEffect(() => {
298
- const getCurrentFormState = () => ({
299
- ...control._formState,
300
- defaultValues: control._defaultValues,
301
- });
302
326
  resyncIfNeeded(!disabled, getCurrentFormState, updateFormState);
303
327
  const unsubscribe = control._subscribe({
304
328
  name,
@@ -333,7 +357,7 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
333
357
  }
334
358
  if (Array.isArray(names)) {
335
359
  return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName),
336
- get(formValues, fieldName)));
360
+ get(formValues, fieldName, get(defaultValue, fieldName))));
337
361
  }
338
362
  isGlobal && (_names.watchAll = true);
339
363
  return formValues;
@@ -364,10 +388,11 @@ function useWatch(props) {
364
388
  const _prevControl = React.useRef(control);
365
389
  const _prevName = React.useRef(name);
366
390
  _compute.current = compute;
367
- const [value, updateValue] = React.useState(() => {
391
+ const getInitialOutput = () => {
368
392
  const defaultValue = control._getWatch(name, _defaultValue.current);
369
393
  return _compute.current ? _compute.current(defaultValue) : defaultValue;
370
- });
394
+ };
395
+ const [value, updateValue] = React.useState(getInitialOutput);
371
396
  const getCurrentOutput = React.useCallback((values) => {
372
397
  const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
373
398
  return _compute.current ? _compute.current(formValues) : formValues;
@@ -387,7 +412,7 @@ function useWatch(props) {
387
412
  }
388
413
  }
389
414
  }, [control._formValues, control._names, disabled, name]);
390
- const { resyncIfNeeded, snapshot } = useResyncOnReconnect();
415
+ const { resyncIfNeeded, snapshot } = useResyncOnReconnect(getInitialOutput);
391
416
  const _refreshValue = React.useRef(refreshValue);
392
417
  _refreshValue.current = refreshValue;
393
418
  const _getCurrentOutput = React.useRef(getCurrentOutput);
@@ -427,17 +452,17 @@ function useWatch(props) {
427
452
  // Optimize: Check control reference first before expensive deepEqual
428
453
  const controlChanged = _prevControl.current !== control;
429
454
  const prevName = _prevName.current;
430
- // Cache the computed output to avoid duplicate calls within the same render
431
- // We include shouldReturnImmediate in deps to ensure proper recomputation
432
- const computedOutput = React.useMemo(() => {
455
+ // `null`/`undefined` are valid watched values, so a boolean flag (rather
456
+ // than a sentinel return value) decides whether to return the freshly
457
+ // computed output instead of the possibly-stale state value.
458
+ const shouldReturnImmediate = React.useMemo(() => {
433
459
  if (disabled) {
434
- return null;
460
+ return false;
435
461
  }
436
462
  const nameChanged = !controlChanged && !deepEqual(prevName, name);
437
- const shouldReturnImmediate = controlChanged || nameChanged;
438
- return shouldReturnImmediate ? getCurrentOutput() : null;
439
- }, [disabled, controlChanged, name, prevName, getCurrentOutput]);
440
- return computedOutput !== null ? computedOutput : value;
463
+ return controlChanged || nameChanged;
464
+ }, [disabled, controlChanged, name, prevName]);
465
+ return shouldReturnImmediate ? getCurrentOutput() : value;
441
466
  }
442
467
 
443
468
  /**
@@ -468,7 +493,12 @@ function useController(props) {
468
493
  const formControl = useFormControlContext();
469
494
  const { name, disabled, control = formControl, shouldUnregister, defaultValue, exact = true, } = props;
470
495
  const isArrayField = isNameInFieldArray(control._names.array, name);
471
- const defaultValueMemo = React.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]);
496
+ const defaultValueMemo = React.useMemo(() => {
497
+ const resolved = get(control._formValues, name, get(control._defaultValues, name, defaultValue));
498
+ return isUndefined(resolved)
499
+ ? getNullAncestorValue(control, name)
500
+ : resolved;
501
+ }, [control, name, defaultValue]);
472
502
  const value = useWatch({
473
503
  control,
474
504
  name,
@@ -653,16 +683,12 @@ function useController(props) {
653
683
  */
654
684
  const Controller = (props) => props.render(useController(props));
655
685
 
656
- var generateId = () => {
657
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
658
- return crypto.randomUUID();
659
- }
660
- const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
661
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
662
- const r = ((Math.random() * 16 + d) % 16) | 0;
663
- return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
686
+ var generateId = () => typeof crypto !== 'undefined' && crypto.randomUUID
687
+ ? crypto.randomUUID()
688
+ : 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
689
+ const r = (Math.random() * 16) | 0;
690
+ return (c === 'x' ? r : (r & 0x3) | 0x8).toString(16);
664
691
  });
665
- };
666
692
 
667
693
  var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
668
694
  ? options.focusName ||
@@ -759,23 +785,25 @@ const defaultResult = {
759
785
  };
760
786
  const validResult = { value: true, isValid: true };
761
787
  var getCheckboxValue = (options) => {
762
- if (Array.isArray(options)) {
763
- if (options.length > 1) {
764
- const values = options
765
- .filter((option) => option && option.checked && !option.disabled)
766
- .map((option) => option.value);
767
- return { value: values, isValid: !!values.length };
768
- }
769
- return options[0].checked && !options[0].disabled
770
- ? // @ts-expect-error expected to work in the browser
771
- options[0].attributes && !isUndefined(options[0].attributes.value)
772
- ? isUndefined(options[0].value) || options[0].value === ''
773
- ? validResult
774
- : { value: options[0].value, isValid: true }
775
- : validResult
776
- : defaultResult;
777
- }
778
- return defaultResult;
788
+ if (!Array.isArray(options)) {
789
+ return defaultResult;
790
+ }
791
+ if (options.length > 1) {
792
+ const values = options
793
+ .filter((option) => option && option.checked && !option.disabled)
794
+ .map((option) => option.value);
795
+ return { value: values, isValid: !!values.length };
796
+ }
797
+ const option = options[0];
798
+ if (!option || !option.checked || option.disabled) {
799
+ return defaultResult;
800
+ }
801
+ if (!option.attributes || !('value' in option.attributes)) {
802
+ return validResult;
803
+ }
804
+ return isUndefined(option.value) || option.value === ''
805
+ ? validResult
806
+ : { value: option.value, isValid: true };
779
807
  };
780
808
 
781
809
  const defaultReturn = {
@@ -993,7 +1021,8 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
993
1021
  }
994
1022
  }
995
1023
  }
996
- setCustomValidity(true);
1024
+ const fieldError = error[name];
1025
+ setCustomValidity(fieldError ? fieldError.message : true);
997
1026
  return error;
998
1027
  };
999
1028
 
@@ -1272,8 +1301,8 @@ function useFieldArray(props) {
1272
1301
  setFields([...updatedFieldArrayValues]);
1273
1302
  control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
1274
1303
  argA: index,
1275
- argB: updateValue,
1276
- }, true, false);
1304
+ argB: fillEmptyArray(value),
1305
+ });
1277
1306
  };
1278
1307
  const replace = (value) => {
1279
1308
  if (disabled) {
@@ -1333,10 +1362,7 @@ function useFieldArray(props) {
1333
1362
  }
1334
1363
  else {
1335
1364
  const field = get(control._fields, name);
1336
- if (field &&
1337
- field._f &&
1338
- !(getValidationModes(control._options.reValidateMode).isOnSubmit &&
1339
- getValidationModes(control._options.mode).isOnSubmit)) {
1365
+ if (field && field._f) {
1340
1366
  validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
1341
1367
  control._subjects.state.next({
1342
1368
  errors: updateFieldArrayRootError(control._formState.errors, error, name),
@@ -1454,12 +1480,15 @@ function useFieldArray(props) {
1454
1480
  */
1455
1481
  const FieldArray = (props) => props.render(useFieldArray(props));
1456
1482
 
1483
+ const isFileLike = (value) => (typeof Blob !== 'undefined' && value instanceof Blob) ||
1484
+ (typeof File !== 'undefined' && value instanceof File);
1457
1485
  const flatten = (obj) => {
1458
1486
  const output = {};
1459
1487
  for (const key of Object.keys(obj)) {
1460
1488
  if (isObjectType(obj[key]) &&
1461
1489
  obj[key] !== null &&
1462
- !isDateObject(obj[key])) {
1490
+ !isDateObject(obj[key]) &&
1491
+ !isFileLike(obj[key])) {
1463
1492
  const nested = flatten(obj[key]);
1464
1493
  for (const nestedKey of Object.keys(nested)) {
1465
1494
  output[`${key}.${nestedKey}`] = nested[nestedKey];
@@ -1555,10 +1584,11 @@ const useFormContext = () => React.useContext(HookFormContext);
1555
1584
  * }
1556
1585
  * ```
1557
1586
  */
1558
- const FormProvider = ({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
1587
+ const FormProvider = ({ children, watch, getValues, getErrors, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
1559
1588
  const memoizedValue = React.useMemo(() => ({
1560
1589
  watch,
1561
1590
  getValues,
1591
+ getErrors,
1562
1592
  getFieldState,
1563
1593
  setError,
1564
1594
  clearErrors,
@@ -1579,6 +1609,7 @@ const FormProvider = ({ children, watch, getValues, getFieldState, setError, cle
1579
1609
  clearErrors,
1580
1610
  control,
1581
1611
  formState,
1612
+ getErrors,
1582
1613
  getFieldState,
1583
1614
  getValues,
1584
1615
  handleSubmit,
@@ -1766,6 +1797,24 @@ function extractFormValues(fieldsState, formValues) {
1766
1797
  return values;
1767
1798
  }
1768
1799
 
1800
+ const hasOwn = (value, key) => value !== null &&
1801
+ isObjectType(value) &&
1802
+ Object.prototype.hasOwnProperty.call(value, key);
1803
+ var has = (object, path) => {
1804
+ if (!path) {
1805
+ return false;
1806
+ }
1807
+ let result = object;
1808
+ for (const key of isKey(path) ? [path] : stringToPath(path)) {
1809
+ if (!hasOwn(result, key)) {
1810
+ // `get` also resolves a path held as a single literal key, eg `{ 'a.b': 1 }`
1811
+ return hasOwn(object, path);
1812
+ }
1813
+ result = result[key];
1814
+ }
1815
+ return true;
1816
+ };
1817
+
1769
1818
  var isMultipleSelect = (element) => element.type === `select-multiple`;
1770
1819
 
1771
1820
  var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
@@ -1865,6 +1914,18 @@ function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
1865
1914
  return dirtyFieldsFromValues;
1866
1915
  }
1867
1916
 
1917
+ var getFieldArrayItemNames = (names, name) => {
1918
+ const segments = name.split('.');
1919
+ const matches = [];
1920
+ let prefix = segments[0];
1921
+ for (let i = 1; i < segments.length; prefix += '.' + segments[i++]) {
1922
+ if (!isNaN(+segments[i]) && names.has(prefix)) {
1923
+ matches.push(`${prefix}.${segments[i]}`);
1924
+ }
1925
+ }
1926
+ return matches;
1927
+ };
1928
+
1868
1929
  var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
1869
1930
  ? value
1870
1931
  : valueAsNumber
@@ -1940,10 +2001,11 @@ var hasPromiseValidation = (fieldReference) => {
1940
2001
 
1941
2002
  var hasValidation = (options) => options.mount &&
1942
2003
  (options.required ||
1943
- options.min ||
1944
- options.max ||
1945
- options.maxLength ||
1946
- options.minLength ||
2004
+ (!isUndefined(options.required) && options.required !== false) ||
2005
+ !isUndefined(options.min) ||
2006
+ !isUndefined(options.max) ||
2007
+ !isUndefined(options.maxLength) ||
2008
+ !isUndefined(options.minLength) ||
1947
2009
  options.pattern ||
1948
2010
  options.validate);
1949
2011
 
@@ -2147,7 +2209,7 @@ function createFormControl(props = {}) {
2147
2209
  _proxyFormState.validatingFields ||
2148
2210
  _proxySubscribeFormState.isValidating ||
2149
2211
  _proxySubscribeFormState.validatingFields)) {
2150
- (names || Array.from(_names.mount)).forEach((name) => {
2212
+ (names || _names.mount).forEach((name) => {
2151
2213
  if (name) {
2152
2214
  isValidating
2153
2215
  ? set(_formState.validatingFields, name, isValidating)
@@ -2166,17 +2228,16 @@ function createFormControl(props = {}) {
2166
2228
  const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
2167
2229
  if (args && method && !_options.disabled) {
2168
2230
  _state.action = true;
2231
+ const fields = get(_fields, name);
2169
2232
  if (!_state.actionArrayLengths.has(name)) {
2170
- const preActionFields = get(_fields, name);
2171
- _state.actionArrayLengths.set(name, Array.isArray(preActionFields) ? preActionFields.length : 0);
2233
+ _state.actionArrayLengths.set(name, Array.isArray(fields) ? fields.length : 0);
2172
2234
  }
2173
- if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
2174
- const fieldValues = method(get(_fields, name), args.argA, args.argB);
2235
+ if (shouldUpdateFieldsAndState && Array.isArray(fields)) {
2236
+ const fieldValues = method(fields, args.argA, args.argB);
2175
2237
  shouldSetValues && set(_fields, name, fieldValues);
2176
2238
  }
2177
- if (shouldUpdateFieldsAndState &&
2178
- Array.isArray(get(_formState.errors, name))) {
2179
- const fieldArrayErrors = get(_formState.errors, name);
2239
+ const fieldArrayErrors = get(_formState.errors, name);
2240
+ if (shouldUpdateFieldsAndState && Array.isArray(fieldArrayErrors)) {
2180
2241
  const rootError = fieldArrayErrors.root;
2181
2242
  const errors = method(fieldArrayErrors, args.argA, args.argB) || fieldArrayErrors;
2182
2243
  if (rootError) {
@@ -2185,11 +2246,12 @@ function createFormControl(props = {}) {
2185
2246
  shouldSetValues && set(_formState.errors, name, errors);
2186
2247
  unsetEmptyArray(_formState.errors, name);
2187
2248
  }
2249
+ const touchedFieldsArray = get(_formState.touchedFields, name);
2188
2250
  if ((_proxyFormState.touchedFields ||
2189
2251
  _proxySubscribeFormState.touchedFields) &&
2190
2252
  shouldUpdateFieldsAndState &&
2191
- Array.isArray(get(_formState.touchedFields, name))) {
2192
- const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
2253
+ Array.isArray(touchedFieldsArray)) {
2254
+ const touchedFields = method(touchedFieldsArray, args.argA, args.argB);
2193
2255
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
2194
2256
  }
2195
2257
  if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
@@ -2375,10 +2437,6 @@ function createFormControl(props = {}) {
2375
2437
  errors: _formState.errors,
2376
2438
  name,
2377
2439
  };
2378
- _formState = {
2379
- ..._formState,
2380
- ...updatedFormState,
2381
- };
2382
2440
  _subjects.state.next(updatedFormState);
2383
2441
  }
2384
2442
  };
@@ -2586,7 +2644,7 @@ function createFormControl(props = {}) {
2586
2644
  }
2587
2645
  for (const fieldKey in value) {
2588
2646
  if (!value.hasOwnProperty(fieldKey)) {
2589
- return;
2647
+ continue;
2590
2648
  }
2591
2649
  const fieldValue = value[fieldKey];
2592
2650
  const fieldName = name + '.' + fieldKey;
@@ -2647,6 +2705,11 @@ function createFormControl(props = {}) {
2647
2705
  name: _state.mount || watched ? name : undefined,
2648
2706
  values,
2649
2707
  });
2708
+ if (!isFieldArray) {
2709
+ for (const itemName of getFieldArrayItemNames(_names.array, name)) {
2710
+ _subjects.state.next({ name: itemName, values });
2711
+ }
2712
+ }
2650
2713
  }
2651
2714
  };
2652
2715
  const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
@@ -2659,10 +2722,9 @@ function createFormControl(props = {}) {
2659
2722
  ..._formValues,
2660
2723
  ...updatedFormValues,
2661
2724
  };
2662
- const flattenedUpdates = flatten(updatedFormValues);
2663
2725
  for (const fieldName of _names.mount) {
2664
- if (fieldName in flattenedUpdates) {
2665
- _setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
2726
+ if (has(updatedFormValues, fieldName)) {
2727
+ _setValue(fieldName, get(updatedFormValues, fieldName), options, true, true);
2666
2728
  }
2667
2729
  }
2668
2730
  _subjects.state.next({
@@ -2703,7 +2765,7 @@ function createFormControl(props = {}) {
2703
2765
  const shouldSkipValidation = hasNoValidationEffect ||
2704
2766
  skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
2705
2767
  const watched = isWatched(name, _names, isBlurEvent);
2706
- set(_formValues, name, fieldValue);
2768
+ set(_formValues, name, cloneObject(fieldValue));
2707
2769
  if (isBlurEvent) {
2708
2770
  if (!target || !target.readOnly) {
2709
2771
  field._f.onBlur && field._f.onBlur(event);
@@ -2835,6 +2897,12 @@ function createFormControl(props = {}) {
2835
2897
  delete delayErrorCallbacks[name];
2836
2898
  }
2837
2899
  }
2900
+ if (options.shouldTouch) {
2901
+ for (const fieldName of name ? fieldNames : _names.mount) {
2902
+ !_names.array.has(fieldName) &&
2903
+ set(_formState.touchedFields, fieldName, true);
2904
+ }
2905
+ }
2838
2906
  _subjects.state.next({
2839
2907
  ...(!isString(name) ||
2840
2908
  ((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
@@ -2842,6 +2910,10 @@ function createFormControl(props = {}) {
2842
2910
  ? {}
2843
2911
  : { name }),
2844
2912
  ...(_options.resolver || !name ? { isValid } : {}),
2913
+ ...(options.shouldTouch &&
2914
+ (_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields)
2915
+ ? { touchedFields: _formState.touchedFields }
2916
+ : {}),
2845
2917
  errors: _formState.errors,
2846
2918
  });
2847
2919
  options.shouldFocus &&
@@ -2862,13 +2934,22 @@ function createFormControl(props = {}) {
2862
2934
  ? get(values, fieldNames)
2863
2935
  : fieldNames.map((name) => get(values, name));
2864
2936
  };
2865
- const getFieldState = (name, formState) => ({
2866
- invalid: !!get((formState || _formState).errors, name),
2867
- isDirty: !!get((formState || _formState).dirtyFields, name),
2868
- error: get((formState || _formState).errors, name),
2869
- isValidating: !!get(_formState.validatingFields, name),
2870
- isTouched: !!get((formState || _formState).touchedFields, name),
2871
- });
2937
+ const getErrors = (fieldNames) => isUndefined(fieldNames)
2938
+ ? { ..._formState.errors }
2939
+ : isString(fieldNames)
2940
+ ? get(_formState.errors, fieldNames)
2941
+ : fieldNames.map((name) => get(_formState.errors, name));
2942
+ const getFieldState = (name, formState) => {
2943
+ const targetFormState = formState || _formState;
2944
+ const error = get(targetFormState.errors, name);
2945
+ return {
2946
+ invalid: !!error,
2947
+ isDirty: !!get(targetFormState.dirtyFields, name),
2948
+ error,
2949
+ isValidating: !!get(_formState.validatingFields, name),
2950
+ isTouched: !!get(targetFormState.touchedFields, name),
2951
+ };
2952
+ };
2872
2953
  const clearErrors = (name) => {
2873
2954
  const names = name ? convertToArrayPayload(name) : undefined;
2874
2955
  names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
@@ -2988,12 +3069,13 @@ function createFormControl(props = {}) {
2988
3069
  !options.keepDefaultValue &&
2989
3070
  unset(_defaultValues, fieldName);
2990
3071
  }
2991
- _subjects.state.next({
2992
- values: cloneObject(_formValues),
2993
- });
3072
+ _valuesSubscriberCount &&
3073
+ _subjects.state.next({
3074
+ values: cloneObject(_formValues),
3075
+ });
2994
3076
  _subjects.state.next({
2995
3077
  ..._formState,
2996
- ...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
3078
+ ...(options.keepDirty ? {} : { isDirty: _getDirty() }),
2997
3079
  });
2998
3080
  !options.keepIsValid && _setValid();
2999
3081
  };
@@ -3199,7 +3281,7 @@ function createFormControl(props = {}) {
3199
3281
  }
3200
3282
  if (!options.keepError) {
3201
3283
  unset(_formState.errors, name);
3202
- _proxyFormState.isValid && _setValid();
3284
+ _setValid();
3203
3285
  }
3204
3286
  _subjects.state.next({ ..._formState });
3205
3287
  }
@@ -3219,7 +3301,7 @@ function createFormControl(props = {}) {
3219
3301
  ..._names.mount,
3220
3302
  ...collectDirtyFieldNames(getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs), _formState.dirtyFields),
3221
3303
  ]);
3222
- for (const fieldName of Array.from(fieldsToCheck)) {
3304
+ for (const fieldName of fieldsToCheck) {
3223
3305
  const isDirty = get(_formState.dirtyFields, fieldName);
3224
3306
  const existingValue = get(_formValues, fieldName);
3225
3307
  const newValue = get(values, fieldName);
@@ -3462,6 +3544,7 @@ function createFormControl(props = {}) {
3462
3544
  setValue,
3463
3545
  setValues,
3464
3546
  getValues,
3547
+ getErrors,
3465
3548
  reset,
3466
3549
  resetField,
3467
3550
  resetDefaultValues,