react-hook-form 7.17.0 → 7.17.4

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/index.esm.js CHANGED
@@ -65,10 +65,9 @@ var omit = (source, key) => {
65
65
  return copy;
66
66
  };
67
67
 
68
- const FormContext = React.createContext(null);
69
- FormContext.displayName = 'RHFContext';
70
- const useFormContext = () => React.useContext(FormContext);
71
- const FormProvider = (props) => (React.createElement(FormContext.Provider, { value: omit(props, 'children') }, props.children));
68
+ const HookFormContext = React.createContext(null);
69
+ const useFormContext = () => React.useContext(HookFormContext);
70
+ const FormProvider = (props) => (React.createElement(HookFormContext.Provider, { value: omit(props, 'children') }, props.children));
72
71
 
73
72
  var getProxyFormState = (formState, _proxyFormState, localProxyFormState, isRoot = true) => {
74
73
  function createGetter(prop) {
@@ -102,29 +101,41 @@ var shouldRenderFormState = (formStateData, _proxyFormState, isRoot) => {
102
101
  (!isRoot || VALIDATION_MODE.all)));
103
102
  };
104
103
 
105
- var convertToArrayPayload = (value) => Array.isArray(value) ? value : [value];
104
+ var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
106
105
 
107
- function useSubscribe({ disabled, subject, callback }) {
108
- const _subscription = React.useRef(subject);
109
- const _unSubscribe = React.useRef();
110
- if (disabled) {
111
- if (_subscription.current) {
112
- _unSubscribe.current && _unSubscribe.current.unsubscribe();
113
- _subscription.current = _unSubscribe.current = undefined;
114
- }
106
+ var shouldSubscribeByName = (name, signalName) => !name ||
107
+ !signalName ||
108
+ convertToArrayPayload(name).some((currentName) => currentName &&
109
+ (currentName.startsWith(signalName) ||
110
+ signalName.startsWith(currentName)));
111
+
112
+ const tearDown = (_unsubscribe) => {
113
+ if (_unsubscribe.current) {
114
+ _unsubscribe.current.unsubscribe();
115
+ _unsubscribe.current = undefined;
115
116
  }
116
- else {
117
- if (!_subscription.current) {
118
- _subscription.current = subject;
119
- }
120
- if (!_unSubscribe.current && _subscription.current) {
121
- _unSubscribe.current = _subscription.current.subscribe({
122
- next: callback,
123
- });
124
- }
117
+ };
118
+ const updateSubscriptionProps = ({ _unsubscribe, props }) => () => {
119
+ if (props.disabled) {
120
+ tearDown(_unsubscribe);
125
121
  }
126
- React.useEffect(() => () => {
127
- _unSubscribe.current && _unSubscribe.current.unsubscribe();
122
+ else if (!_unsubscribe.current) {
123
+ _unsubscribe.current = props.subject.subscribe({
124
+ next: props.callback,
125
+ });
126
+ }
127
+ };
128
+ function useSubscribe(props) {
129
+ const _unsubscribe = React.useRef();
130
+ const _updateSubscription = React.useRef(() => { });
131
+ _updateSubscription.current = updateSubscriptionProps({
132
+ _unsubscribe,
133
+ props,
134
+ });
135
+ !props.skipEarlySubscription && _updateSubscription.current();
136
+ React.useEffect(() => {
137
+ _updateSubscription.current();
138
+ return () => tearDown(_unsubscribe);
128
139
  }, []);
129
140
  }
130
141
 
@@ -144,9 +155,7 @@ function useFormState(props) {
144
155
  _name.current = name;
145
156
  useSubscribe({
146
157
  disabled,
147
- callback: (formState) => (!_name.current ||
148
- !formState.name ||
149
- convertToArrayPayload(_name.current).includes(formState.name)) &&
158
+ callback: (formState) => shouldSubscribeByName(_name.current, formState.name) &&
150
159
  shouldRenderFormState(formState, _localProxyFormState.current) &&
151
160
  updateFormState(Object.assign(Object.assign({}, control._formState), formState)),
152
161
  subject: control._subjects.state,
@@ -167,7 +176,7 @@ function useController(props) {
167
176
  useSubscribe({
168
177
  subject: control._subjects.control,
169
178
  callback: (data) => (!data.name || _name.current === data.name) &&
170
- setInputStateValue(get(data.values, name)),
179
+ setInputStateValue(get(data.values, _name.current)),
171
180
  });
172
181
  const registerProps = control.register(name, Object.assign(Object.assign({}, props.rules), { value }));
173
182
  const updateMounted = React.useCallback((name, value) => {
@@ -179,7 +188,7 @@ function useController(props) {
179
188
  React.useEffect(() => {
180
189
  updateMounted(name, true);
181
190
  return () => {
182
- const _shouldUnregisterField = control._shouldUnregister || shouldUnregister;
191
+ const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
183
192
  if (isNameInFieldArray(control._names.array, name)
184
193
  ? _shouldUnregisterField && !control._stateFlags.action
185
194
  : _shouldUnregisterField) {
@@ -334,7 +343,7 @@ var moveArrayAt = (data, from, to) => {
334
343
  return [];
335
344
  };
336
345
 
337
- var omitKey = (fields, keyName) => fields.map((field = {}) => omit(field, keyName));
346
+ var omitKeys = (fields, keyName) => fields.map((field = {}) => omit(field, keyName));
338
347
 
339
348
  function prepend(data, value) {
340
349
  return [...convertToArrayPayload(value), ...convertToArrayPayload(data)];
@@ -365,81 +374,84 @@ var updateAt = (fieldValues, index, value) => {
365
374
  const useFieldArray = (props) => {
366
375
  const methods = useFormContext();
367
376
  const { control = methods.control, name, keyName = 'id', shouldUnregister, } = props;
368
- const [fields, setFields] = React.useState(mapIds(control._getFieldArrayValue(name), keyName));
377
+ const [fields, setFields] = React.useState(mapIds(control._getFieldArray(name), keyName));
369
378
  const _fieldIds = React.useRef(fields);
379
+ const _name = React.useRef(name);
380
+ _name.current = name;
381
+ _fieldIds.current = fields;
382
+ control._names.array.add(name);
370
383
  useSubscribe({
371
384
  callback: ({ values, name: fieldArrayName }) => {
372
- if (fieldArrayName === name || !fieldArrayName) {
373
- setFields(mapIds(get(values, name), keyName));
385
+ if (fieldArrayName === _name.current || !fieldArrayName) {
386
+ setFields(mapIds(get(values, _name.current), keyName));
374
387
  }
375
388
  },
376
389
  subject: control._subjects.array,
390
+ skipEarlySubscription: true,
377
391
  });
378
- _fieldIds.current = fields;
379
- control._names.array.add(name);
380
392
  const updateValues = React.useCallback((updatedFieldArrayValuesWithKey) => {
381
- const updatedFieldArrayValues = omitKey(updatedFieldArrayValuesWithKey, keyName);
393
+ const updatedFieldArrayValues = omitKeys(updatedFieldArrayValuesWithKey, keyName);
382
394
  set(control._formValues, name, updatedFieldArrayValues);
383
395
  setFields(updatedFieldArrayValuesWithKey);
384
396
  return updatedFieldArrayValues;
385
397
  }, [control, name, keyName]);
386
398
  const append$1 = (value, options) => {
387
399
  const appendValue = convertToArrayPayload(value);
388
- const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArrayValue(name), _fieldIds, keyName), mapIds(appendValue, keyName));
389
- control._updateFieldArray(keyName, name, append, {
400
+ const updatedFieldArrayValuesWithKey = append(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(appendValue, keyName));
401
+ control._updateFieldArray(name, append, {
390
402
  argA: fillEmptyArray(value),
391
403
  }, updateValues(updatedFieldArrayValuesWithKey));
392
404
  control._names.focus = getFocusFieldName(name, updatedFieldArrayValuesWithKey.length - appendValue.length, options);
393
405
  };
394
406
  const prepend$1 = (value, options) => {
395
- const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArrayValue(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
396
- control._updateFieldArray(keyName, name, prepend, {
407
+ const updatedFieldArrayValuesWithKey = prepend(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), mapIds(convertToArrayPayload(value), keyName));
408
+ control._updateFieldArray(name, prepend, {
397
409
  argA: fillEmptyArray(value),
398
410
  }, updateValues(updatedFieldArrayValuesWithKey));
399
411
  control._names.focus = getFocusFieldName(name, 0, options);
400
412
  };
401
413
  const remove = (index) => {
402
- const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArrayValue(name), _fieldIds, keyName), index);
403
- control._updateFieldArray(keyName, name, removeArrayAt, {
414
+ const updatedFieldArrayValuesWithKey = removeArrayAt(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index);
415
+ control._updateFieldArray(name, removeArrayAt, {
404
416
  argA: index,
405
417
  }, updateValues(updatedFieldArrayValuesWithKey));
406
418
  };
407
419
  const insert$1 = (index, value, options) => {
408
- const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArrayValue(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
409
- control._updateFieldArray(keyName, name, insert, {
420
+ const updatedFieldArrayValuesWithKey = insert(mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName), index, mapIds(convertToArrayPayload(value), keyName));
421
+ control._updateFieldArray(name, insert, {
410
422
  argA: index,
411
423
  argB: fillEmptyArray(value),
412
424
  }, updateValues(updatedFieldArrayValuesWithKey));
413
425
  control._names.focus = getFocusFieldName(name, index, options);
414
426
  };
415
427
  const swap = (indexA, indexB) => {
416
- const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArrayValue(name), _fieldIds, keyName);
428
+ const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
417
429
  swapArrayAt(updatedFieldArrayValuesWithKey, indexA, indexB);
418
- control._updateFieldArray(keyName, name, swapArrayAt, {
430
+ control._updateFieldArray(name, swapArrayAt, {
419
431
  argA: indexA,
420
432
  argB: indexB,
421
433
  }, updateValues(updatedFieldArrayValuesWithKey), false);
422
434
  };
423
435
  const move = (from, to) => {
424
- const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArrayValue(name), _fieldIds, keyName);
436
+ const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
425
437
  moveArrayAt(updatedFieldArrayValuesWithKey, from, to);
426
- control._updateFieldArray(keyName, name, moveArrayAt, {
438
+ control._updateFieldArray(name, moveArrayAt, {
427
439
  argA: from,
428
440
  argB: to,
429
441
  }, updateValues(updatedFieldArrayValuesWithKey), false);
430
442
  };
431
443
  const update = (index, value) => {
432
- const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArrayValue(name), _fieldIds, keyName);
444
+ const updatedFieldArrayValuesWithKey = mapCurrentIds(control._getFieldArray(name), _fieldIds, keyName);
433
445
  const updatedFieldArrayValues = updateAt(updatedFieldArrayValuesWithKey, index, value);
434
446
  _fieldIds.current = mapIds(updatedFieldArrayValues, keyName);
435
- control._updateFieldArray(keyName, name, updateAt, {
447
+ control._updateFieldArray(name, updateAt, {
436
448
  argA: index,
437
449
  argB: value,
438
450
  }, updateValues(_fieldIds.current), true, false);
439
451
  };
440
452
  const replace = (value) => {
441
453
  const updatedFieldArrayValuesWithKey = mapIds(convertToArrayPayload(value), keyName);
442
- control._updateFieldArray(keyName, name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
454
+ control._updateFieldArray(name, () => updatedFieldArrayValuesWithKey, {}, updateValues(updatedFieldArrayValuesWithKey), true, false);
443
455
  };
444
456
  React.useEffect(() => {
445
457
  control._stateFlags.action = false;
@@ -466,7 +478,7 @@ const useFieldArray = (props) => {
466
478
  React.useEffect(() => {
467
479
  !get(control._formValues, name) && set(control._formValues, name, []);
468
480
  return () => {
469
- if (control._shouldUnregister || shouldUnregister) {
481
+ if (control._options.shouldUnregister || shouldUnregister) {
470
482
  control.unregister(name);
471
483
  }
472
484
  };
@@ -484,6 +496,8 @@ const useFieldArray = (props) => {
484
496
  };
485
497
  };
486
498
 
499
+ var isFunction = (value) => typeof value === 'function';
500
+
487
501
  function cloneObject(data) {
488
502
  let copy;
489
503
  const isArray = Array.isArray(data);
@@ -496,6 +510,10 @@ function cloneObject(data) {
496
510
  else if (isArray || isObject(data)) {
497
511
  copy = isArray ? [] : {};
498
512
  for (const key in data) {
513
+ if (isFunction(data[key])) {
514
+ copy = data;
515
+ break;
516
+ }
499
517
  copy[key] = cloneObject(data[key]);
500
518
  }
501
519
  }
@@ -508,12 +526,12 @@ function cloneObject(data) {
508
526
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
509
527
 
510
528
  function deepEqual(object1, object2) {
511
- if (isPrimitive(object1) ||
512
- isPrimitive(object2) ||
513
- isDateObject(object1) ||
514
- isDateObject(object2)) {
529
+ if (isPrimitive(object1) || isPrimitive(object2)) {
515
530
  return object1 === object2;
516
531
  }
532
+ if (isDateObject(object1) && isDateObject(object2)) {
533
+ return object1.getTime() === object2.getTime();
534
+ }
517
535
  const keys1 = Object.keys(object1);
518
536
  const keys2 = Object.keys(object2);
519
537
  if (keys1.length !== keys2.length) {
@@ -526,8 +544,9 @@ function deepEqual(object1, object2) {
526
544
  }
527
545
  if (key !== 'ref') {
528
546
  const val2 = object2[key];
529
- if ((isObject(val1) || Array.isArray(val1)) &&
530
- (isObject(val2) || Array.isArray(val2))
547
+ if ((isDateObject(val1) && isDateObject(val2)) ||
548
+ (isObject(val1) && isObject(val2)) ||
549
+ (Array.isArray(val1) && Array.isArray(val2))
531
550
  ? !deepEqual(val1, val2)
532
551
  : val1 !== val2) {
533
552
  return false;
@@ -547,10 +566,6 @@ var getValidationModes = (mode) => ({
547
566
 
548
567
  var isBoolean = (value) => typeof value === 'boolean';
549
568
 
550
- var isFileInput = (element) => element.type === 'file';
551
-
552
- var isFunction = (value) => typeof value === 'function';
553
-
554
569
  var isHTMLElement = (value) => value instanceof HTMLElement;
555
570
 
556
571
  var isMultipleSelect = (element) => element.type === `select-multiple`;
@@ -565,7 +580,7 @@ var isWeb = typeof window !== 'undefined' &&
565
580
  typeof window.HTMLElement !== 'undefined' &&
566
581
  typeof document !== 'undefined';
567
582
 
568
- var live = (ref) => !isHTMLElement(ref) || !document.contains(ref);
583
+ var live = (ref) => isHTMLElement(ref) && document.contains(ref);
569
584
 
570
585
  class Subscription {
571
586
  constructor() {
@@ -652,6 +667,8 @@ function unset(object, path) {
652
667
  return object;
653
668
  }
654
669
 
670
+ var isFileInput = (element) => element.type === 'file';
671
+
655
672
  const defaultResult = {
656
673
  value: false,
657
674
  isValid: false,
@@ -973,8 +990,7 @@ const defaultOptions = {
973
990
  };
974
991
  const isWindowUndefined = typeof window === 'undefined';
975
992
  function createFormControl(props = {}) {
976
- let formOptions = Object.assign(Object.assign({}, defaultOptions), props);
977
- let _delayCallback;
993
+ let _options = Object.assign(Object.assign({}, defaultOptions), props);
978
994
  let _formState = {
979
995
  isDirty: false,
980
996
  isValidating: false,
@@ -988,8 +1004,8 @@ function createFormControl(props = {}) {
988
1004
  errors: {},
989
1005
  };
990
1006
  let _fields = {};
991
- let _defaultValues = formOptions.defaultValues || {};
992
- let _formValues = formOptions.shouldUnregister
1007
+ let _defaultValues = _options.defaultValues || {};
1008
+ let _formValues = _options.shouldUnregister
993
1009
  ? {}
994
1010
  : cloneObject(_defaultValues);
995
1011
  let _stateFlags = {
@@ -997,14 +1013,15 @@ function createFormControl(props = {}) {
997
1013
  mount: false,
998
1014
  watch: false,
999
1015
  };
1000
- let _timer = 0;
1001
1016
  let _names = {
1002
1017
  mount: new Set(),
1003
1018
  unMount: new Set(),
1004
1019
  array: new Set(),
1005
1020
  watch: new Set(),
1006
1021
  };
1007
- let _validateCount = {};
1022
+ let delayErrorCallback;
1023
+ let timer = 0;
1024
+ let validateFields = {};
1008
1025
  const _proxyFormState = {
1009
1026
  isDirty: false,
1010
1027
  dirtyFields: false,
@@ -1019,37 +1036,125 @@ function createFormControl(props = {}) {
1019
1036
  array: new Subject(),
1020
1037
  state: new Subject(),
1021
1038
  };
1022
- const validationMode = getValidationModes(formOptions.mode);
1023
- const reValidateMode = getValidationModes(formOptions.reValidateMode);
1024
- const isValidateAllFieldCriteria = formOptions.criteriaMode === VALIDATION_MODE.all;
1039
+ const validationModeBeforeSubmit = getValidationModes(_options.mode);
1040
+ const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1041
+ const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
1025
1042
  const debounce = (callback, wait) => (...args) => {
1026
- clearTimeout(_timer);
1027
- _timer = window.setTimeout(() => callback(...args), wait);
1043
+ clearTimeout(timer);
1044
+ timer = window.setTimeout(() => callback(...args), wait);
1028
1045
  };
1029
- const isFieldWatched = (name) => _names.watchAll ||
1030
- _names.watch.has(name) ||
1031
- _names.watch.has((name.match(/\w+/) || [])[0]);
1032
- const updateErrorState = (name, error) => {
1033
- set(_formState.errors, name, error);
1046
+ const isFieldWatched = (name, isBlurEvent) => !isBlurEvent &&
1047
+ (_names.watchAll ||
1048
+ _names.watch.has(name) ||
1049
+ _names.watch.has((name.match(/\w+/) || [])[0]));
1050
+ const _updateValid = async (shouldSkipRender) => {
1051
+ let isValid = false;
1052
+ if (_proxyFormState.isValid) {
1053
+ isValid = _options.resolver
1054
+ ? isEmptyObject((await executeResolver()).errors)
1055
+ : await executeBuildInValidation(_fields, true);
1056
+ if (!shouldSkipRender && isValid !== _formState.isValid) {
1057
+ _formState.isValid = isValid;
1058
+ _subjects.state.next({
1059
+ isValid,
1060
+ });
1061
+ }
1062
+ }
1063
+ return isValid;
1064
+ };
1065
+ const _updateFieldArray = (name, method, args, values = [], shouldSetValues = true, shouldSetFields = true) => {
1066
+ _stateFlags.action = true;
1067
+ if (shouldSetFields && get(_fields, name)) {
1068
+ const fieldValues = method(get(_fields, name), args.argA, args.argB);
1069
+ shouldSetValues && set(_fields, name, fieldValues);
1070
+ }
1071
+ if (Array.isArray(get(_formState.errors, name))) {
1072
+ const errors = method(get(_formState.errors, name), args.argA, args.argB);
1073
+ shouldSetValues && set(_formState.errors, name, errors);
1074
+ unsetEmptyArray(_formState.errors, name);
1075
+ }
1076
+ if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
1077
+ const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
1078
+ shouldSetValues &&
1079
+ set(_formState.touchedFields, name, touchedFields);
1080
+ unsetEmptyArray(_formState.touchedFields, name);
1081
+ }
1082
+ if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
1083
+ updateFieldArrayDirty(name, values);
1084
+ }
1034
1085
  _subjects.state.next({
1086
+ isDirty: _getDirty(name, values),
1087
+ dirtyFields: _formState.dirtyFields,
1035
1088
  errors: _formState.errors,
1089
+ isValid: _formState.isValid,
1036
1090
  });
1037
1091
  };
1038
- const shouldRenderBaseOnError = async (shouldSkipRender, name, isValid, error, fieldState) => {
1039
- const previousError = get(_formState.errors, name);
1092
+ const updateErrors = (name, error) => (set(_formState.errors, name, error),
1093
+ _subjects.state.next({
1094
+ errors: _formState.errors,
1095
+ }));
1096
+ const updateValidAndValue = (name, shouldSkipSetValueAs, ref) => {
1097
+ const field = get(_fields, name);
1098
+ if (field) {
1099
+ const defaultValue = get(_formValues, name, get(_defaultValues, name));
1100
+ isUndefined(defaultValue) ||
1101
+ (ref && ref.defaultChecked) ||
1102
+ shouldSkipSetValueAs
1103
+ ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
1104
+ : setFieldValue(name, defaultValue);
1105
+ }
1106
+ _stateFlags.mount && _updateValid();
1107
+ };
1108
+ const updateTouchAndDirty = (name, fieldValue, isCurrentTouched, shouldRender = true) => {
1109
+ let isFieldDirty = false;
1110
+ const output = {
1111
+ name,
1112
+ };
1113
+ const isPreviousFieldTouched = get(_formState.touchedFields, name);
1114
+ if (_proxyFormState.isDirty) {
1115
+ const isPreviousFormDirty = _formState.isDirty;
1116
+ _formState.isDirty = output.isDirty = _getDirty();
1117
+ isFieldDirty = isPreviousFormDirty !== output.isDirty;
1118
+ }
1119
+ if (_proxyFormState.dirtyFields && !isCurrentTouched) {
1120
+ const isPreviousFieldDirty = get(_formState.dirtyFields, name);
1121
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1122
+ isCurrentFieldPristine
1123
+ ? unset(_formState.dirtyFields, name)
1124
+ : set(_formState.dirtyFields, name, true);
1125
+ output.dirtyFields = _formState.dirtyFields;
1126
+ isFieldDirty =
1127
+ isFieldDirty ||
1128
+ isPreviousFieldDirty !== get(_formState.dirtyFields, name);
1129
+ }
1130
+ if (isCurrentTouched && !isPreviousFieldTouched) {
1131
+ set(_formState.touchedFields, name, isCurrentTouched);
1132
+ output.touchedFields = _formState.touchedFields;
1133
+ isFieldDirty =
1134
+ isFieldDirty ||
1135
+ (_proxyFormState.touchedFields &&
1136
+ isPreviousFieldTouched !== isCurrentTouched);
1137
+ }
1138
+ isFieldDirty && shouldRender && _subjects.state.next(output);
1139
+ return isFieldDirty ? output : {};
1140
+ };
1141
+ const updateFieldArrayDirty = (name, value) => (set(_formState.dirtyFields, name, setFieldArrayDirtyFields(value, get(_defaultValues, name, []), get(_formState.dirtyFields, name, []))),
1142
+ unsetEmptyArray(_formState.dirtyFields, name));
1143
+ const shouldRenderByError = async (shouldSkipRender, name, isValid, error, fieldState) => {
1144
+ const previousFieldError = get(_formState.errors, name);
1040
1145
  const shouldUpdateValid = _proxyFormState.isValid && _formState.isValid !== isValid;
1041
1146
  if (props.delayError && error) {
1042
- _delayCallback =
1043
- _delayCallback || debounce(updateErrorState, props.delayError);
1044
- _delayCallback(name, error);
1147
+ delayErrorCallback =
1148
+ delayErrorCallback || debounce(updateErrors, props.delayError);
1149
+ delayErrorCallback(name, error);
1045
1150
  }
1046
1151
  else {
1047
- clearTimeout(_timer);
1152
+ clearTimeout(timer);
1048
1153
  error
1049
1154
  ? set(_formState.errors, name, error)
1050
1155
  : unset(_formState.errors, name);
1051
1156
  }
1052
- if (((error ? !deepEqual(previousError, error) : previousError) ||
1157
+ if (((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
1053
1158
  !isEmptyObject(fieldState) ||
1054
1159
  shouldUpdateValid) &&
1055
1160
  !shouldSkipRender) {
@@ -1057,138 +1162,171 @@ function createFormControl(props = {}) {
1057
1162
  _formState = Object.assign(Object.assign({}, _formState), updatedFormState);
1058
1163
  _subjects.state.next(updatedFormState);
1059
1164
  }
1060
- _validateCount[name]--;
1061
- if (_proxyFormState.isValidating && !_validateCount[name]) {
1165
+ validateFields[name]--;
1166
+ if (_proxyFormState.isValidating && !validateFields[name]) {
1062
1167
  _subjects.state.next({
1063
1168
  isValidating: false,
1064
1169
  });
1065
- _validateCount = {};
1170
+ validateFields = {};
1066
1171
  }
1067
1172
  };
1173
+ const executeResolver = async (name) => _options.resolver
1174
+ ? await _options.resolver(Object.assign({}, _formValues), _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation))
1175
+ : {};
1176
+ const executeResolverValidation = async (names) => {
1177
+ const { errors } = await executeResolver();
1178
+ if (names) {
1179
+ for (const name of names) {
1180
+ const error = get(errors, name);
1181
+ error
1182
+ ? set(_formState.errors, name, error)
1183
+ : unset(_formState.errors, name);
1184
+ }
1185
+ }
1186
+ else {
1187
+ _formState.errors = errors;
1188
+ }
1189
+ return errors;
1190
+ };
1191
+ const executeBuildInValidation = async (fields, shouldOnlyCheckValid, context = {
1192
+ valid: true,
1193
+ }) => {
1194
+ for (const name in fields) {
1195
+ const field = fields[name];
1196
+ if (field) {
1197
+ const fieldReference = field._f;
1198
+ const fieldValue = omit(field, '_f');
1199
+ if (fieldReference) {
1200
+ const fieldError = await validateField(field, get(_formValues, fieldReference.name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation);
1201
+ if (fieldError[fieldReference.name]) {
1202
+ context.valid = false;
1203
+ if (shouldOnlyCheckValid) {
1204
+ break;
1205
+ }
1206
+ }
1207
+ if (!shouldOnlyCheckValid) {
1208
+ fieldError[fieldReference.name]
1209
+ ? set(_formState.errors, fieldReference.name, fieldError[fieldReference.name])
1210
+ : unset(_formState.errors, fieldReference.name);
1211
+ }
1212
+ }
1213
+ fieldValue &&
1214
+ (await executeBuildInValidation(fieldValue, shouldOnlyCheckValid, context));
1215
+ }
1216
+ }
1217
+ return context.valid;
1218
+ };
1219
+ const _removeUnmounted = () => {
1220
+ for (const name of _names.unMount) {
1221
+ const field = get(_fields, name);
1222
+ field &&
1223
+ (field._f.refs
1224
+ ? field._f.refs.every((ref) => !live(ref))
1225
+ : !live(field._f.ref)) &&
1226
+ unregister(name);
1227
+ }
1228
+ _names.unMount = new Set();
1229
+ };
1230
+ const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
1231
+ !deepEqual(getValues(), _defaultValues));
1232
+ const _getWatch = (names, defaultValue, isGlobal) => {
1233
+ const fieldValues = Object.assign({}, (_stateFlags.mount
1234
+ ? _formValues
1235
+ : isUndefined(defaultValue)
1236
+ ? _defaultValues
1237
+ : isString(names)
1238
+ ? { [names]: defaultValue }
1239
+ : defaultValue));
1240
+ if (names) {
1241
+ const result = convertToArrayPayload(names).map((fieldName) => (isGlobal && _names.watch.add(fieldName),
1242
+ get(fieldValues, fieldName)));
1243
+ return Array.isArray(names) ? result : result[0];
1244
+ }
1245
+ isGlobal && (_names.watchAll = true);
1246
+ return fieldValues;
1247
+ };
1248
+ const _getFieldArray = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, props.shouldUnregister ? get(_defaultValues, name, []) : []);
1068
1249
  const setFieldValue = (name, value, options = {}, shouldRender) => {
1069
1250
  const field = get(_fields, name);
1070
1251
  let fieldValue = value;
1071
1252
  if (field) {
1072
- const _f = field._f;
1073
- if (_f) {
1074
- set(_formValues, name, getFieldValueAs(value, _f));
1253
+ const fieldReference = field._f;
1254
+ if (fieldReference) {
1255
+ set(_formValues, name, getFieldValueAs(value, fieldReference));
1075
1256
  fieldValue =
1076
- isWeb && isHTMLElement(_f.ref) && isNullOrUndefined(value)
1257
+ isWeb && isHTMLElement(fieldReference.ref) && isNullOrUndefined(value)
1077
1258
  ? ''
1078
1259
  : value;
1079
- if (isFileInput(_f.ref) && !isString(fieldValue)) {
1080
- _f.ref.files = fieldValue;
1260
+ if (isMultipleSelect(fieldReference.ref)) {
1261
+ [...fieldReference.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
1081
1262
  }
1082
- else if (isMultipleSelect(_f.ref)) {
1083
- [..._f.ref.options].forEach((selectRef) => (selectRef.selected = fieldValue.includes(selectRef.value)));
1084
- }
1085
- else if (_f.refs) {
1086
- if (isCheckBoxInput(_f.ref)) {
1087
- _f.refs.length > 1
1088
- ? _f.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(fieldValue)
1263
+ else if (fieldReference.refs) {
1264
+ if (isCheckBoxInput(fieldReference.ref)) {
1265
+ fieldReference.refs.length > 1
1266
+ ? fieldReference.refs.forEach((checkboxRef) => (checkboxRef.checked = Array.isArray(fieldValue)
1089
1267
  ? !!fieldValue.find((data) => data === checkboxRef.value)
1090
1268
  : fieldValue === checkboxRef.value))
1091
- : (_f.refs[0].checked = !!fieldValue);
1269
+ : (fieldReference.refs[0].checked = !!fieldValue);
1092
1270
  }
1093
1271
  else {
1094
- _f.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
1272
+ fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue));
1095
1273
  }
1096
1274
  }
1097
1275
  else {
1098
- _f.ref.value = fieldValue;
1276
+ fieldReference.ref.value = fieldValue;
1099
1277
  }
1100
- if (shouldRender) {
1278
+ shouldRender &&
1101
1279
  _subjects.control.next({
1102
1280
  values: _formValues,
1103
1281
  name,
1104
1282
  });
1105
- }
1106
1283
  }
1107
1284
  }
1108
1285
  (options.shouldDirty || options.shouldTouch) &&
1109
- updateTouchAndDirtyState(name, fieldValue, options.shouldTouch);
1286
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch);
1110
1287
  options.shouldValidate && trigger(name);
1111
1288
  };
1112
- const updateTouchAndDirtyState = (name, inputValue, isCurrentTouched, shouldRender = true) => {
1113
- const state = {
1114
- name,
1115
- };
1116
- let isChanged = false;
1117
- if (_proxyFormState.isDirty) {
1118
- const previousIsDirty = _formState.isDirty;
1119
- _formState.isDirty = _getIsDirty();
1120
- state.isDirty = _formState.isDirty;
1121
- isChanged = previousIsDirty !== state.isDirty;
1122
- }
1123
- if (_proxyFormState.dirtyFields && !isCurrentTouched) {
1124
- const isPreviousFieldDirty = get(_formState.dirtyFields, name);
1125
- const isCurrentFieldDirty = !deepEqual(get(_defaultValues, name), inputValue);
1126
- isCurrentFieldDirty
1127
- ? set(_formState.dirtyFields, name, true)
1128
- : unset(_formState.dirtyFields, name);
1129
- state.dirtyFields = _formState.dirtyFields;
1130
- isChanged =
1131
- isChanged || isPreviousFieldDirty !== get(_formState.dirtyFields, name);
1289
+ const setValues = (name, value, options) => {
1290
+ for (const fieldKey in value) {
1291
+ const fieldValue = value[fieldKey];
1292
+ const fieldName = `${name}.${fieldKey}`;
1293
+ const field = get(_fields, fieldName);
1294
+ (_names.array.has(name) ||
1295
+ !isPrimitive(fieldValue) ||
1296
+ (field && !field._f)) &&
1297
+ !isDateObject(fieldValue)
1298
+ ? setValues(fieldName, fieldValue, options)
1299
+ : setFieldValue(fieldName, fieldValue, options, true);
1132
1300
  }
1133
- const isPreviousFieldTouched = get(_formState.touchedFields, name);
1134
- if (isCurrentTouched && !isPreviousFieldTouched) {
1135
- set(_formState.touchedFields, name, isCurrentTouched);
1136
- state.touchedFields = _formState.touchedFields;
1137
- isChanged =
1138
- isChanged ||
1139
- (_proxyFormState.touchedFields &&
1140
- isPreviousFieldTouched !== isCurrentTouched);
1141
- }
1142
- isChanged && shouldRender && _subjects.state.next(state);
1143
- return isChanged ? state : {};
1144
- };
1145
- const executeResolver = async (name) => {
1146
- return formOptions.resolver
1147
- ? await formOptions.resolver(Object.assign({}, _formValues), formOptions.context, getResolverOptions(name || _names.mount, _fields, formOptions.criteriaMode, formOptions.shouldUseNativeValidation))
1148
- : {};
1149
1301
  };
1150
- const executeResolverValidation = async (names) => {
1151
- const { errors } = await executeResolver();
1152
- if (names) {
1153
- for (const name of names) {
1154
- const error = get(errors, name);
1155
- error
1156
- ? set(_formState.errors, name, error)
1157
- : unset(_formState.errors, name);
1302
+ const setValue = (name, value, options = {}) => {
1303
+ const field = get(_fields, name);
1304
+ const isFieldArray = _names.array.has(name);
1305
+ set(_formValues, name, value);
1306
+ if (isFieldArray) {
1307
+ _subjects.array.next({
1308
+ name,
1309
+ values: _formValues,
1310
+ });
1311
+ if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) &&
1312
+ options.shouldDirty) {
1313
+ updateFieldArrayDirty(name, value);
1314
+ _subjects.state.next({
1315
+ name,
1316
+ dirtyFields: _formState.dirtyFields,
1317
+ isDirty: _getDirty(name, value),
1318
+ });
1158
1319
  }
1159
1320
  }
1160
1321
  else {
1161
- _formState.errors = errors;
1162
- }
1163
- return errors;
1164
- };
1165
- const validateForm = async (_fields, shouldCheckValid, context = {
1166
- valid: true,
1167
- }) => {
1168
- for (const name in _fields) {
1169
- const field = _fields[name];
1170
- if (field) {
1171
- const _f = field._f;
1172
- const fieldValue = omit(field, '_f');
1173
- if (_f) {
1174
- const fieldError = await validateField(field, get(_formValues, _f.name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation);
1175
- if (fieldError[_f.name]) {
1176
- context.valid = false;
1177
- if (shouldCheckValid) {
1178
- break;
1179
- }
1180
- }
1181
- if (!shouldCheckValid) {
1182
- fieldError[_f.name]
1183
- ? set(_formState.errors, _f.name, fieldError[_f.name])
1184
- : unset(_formState.errors, _f.name);
1185
- }
1186
- }
1187
- fieldValue &&
1188
- (await validateForm(fieldValue, shouldCheckValid, context));
1189
- }
1322
+ field && !field._f && !isNullOrUndefined(value)
1323
+ ? setValues(name, value, options)
1324
+ : setFieldValue(name, value, options, true);
1190
1325
  }
1191
- return context.valid;
1326
+ isFieldWatched(name) && _subjects.state.next({});
1327
+ _subjects.watch.next({
1328
+ name,
1329
+ });
1192
1330
  };
1193
1331
  const handleChange = async (event) => {
1194
1332
  const target = event.target;
@@ -1197,22 +1335,22 @@ function createFormControl(props = {}) {
1197
1335
  if (field) {
1198
1336
  let error;
1199
1337
  let isValid;
1200
- const inputValue = target.type ? getFieldValue(field._f) : target.value;
1338
+ const fieldValue = target.type ? getFieldValue(field._f) : target.value;
1201
1339
  const isBlurEvent = event.type === EVENTS.BLUR;
1202
- if (isBlurEvent && field._f.onBlur) {
1203
- field._f.onBlur(event);
1340
+ const shouldSkipValidation = (!hasValidation(field._f) &&
1341
+ !_options.resolver &&
1342
+ !get(_formState.errors, name) &&
1343
+ !field._f.deps) ||
1344
+ skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1345
+ const isWatched = isFieldWatched(name, isBlurEvent);
1346
+ if (isBlurEvent) {
1347
+ field._f.onBlur && field._f.onBlur(event);
1204
1348
  }
1205
1349
  else if (field._f.onChange) {
1206
1350
  field._f.onChange(event);
1207
1351
  }
1208
- const shouldSkipValidation = (!hasValidation(field._f) &&
1209
- !formOptions.resolver &&
1210
- !get(_formState.errors, name) &&
1211
- !field._f.deps) ||
1212
- skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, reValidateMode, validationMode);
1213
- const isWatched = !isBlurEvent && isFieldWatched(name);
1214
- set(_formValues, name, inputValue);
1215
- const fieldState = updateTouchAndDirtyState(name, inputValue, isBlurEvent, false);
1352
+ set(_formValues, name, fieldValue);
1353
+ const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, false);
1216
1354
  const shouldRender = !isEmptyObject(fieldState) || isWatched;
1217
1355
  !isBlurEvent &&
1218
1356
  _subjects.watch.next({
@@ -1224,12 +1362,12 @@ function createFormControl(props = {}) {
1224
1362
  _subjects.state.next(Object.assign({ name }, (isWatched ? {} : fieldState))));
1225
1363
  }
1226
1364
  !isBlurEvent && isWatched && _subjects.state.next({});
1227
- _validateCount[name] = _validateCount[name] ? +1 : 1;
1365
+ validateFields[name] = validateFields[name] ? +1 : 1;
1228
1366
  _proxyFormState.isValidating &&
1229
1367
  _subjects.state.next({
1230
1368
  isValidating: true,
1231
1369
  });
1232
- if (formOptions.resolver) {
1370
+ if (_options.resolver) {
1233
1371
  const { errors } = await executeResolver([name]);
1234
1372
  error = get(errors, name);
1235
1373
  if (isCheckBoxInput(target) && !error) {
@@ -1245,169 +1383,41 @@ function createFormControl(props = {}) {
1245
1383
  isValid = isEmptyObject(errors);
1246
1384
  }
1247
1385
  else {
1248
- error = (await validateField(field, get(_formValues, name), isValidateAllFieldCriteria, formOptions.shouldUseNativeValidation))[name];
1386
+ error = (await validateField(field, get(_formValues, name), shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1249
1387
  isValid = await _updateValid(true);
1250
1388
  }
1251
- if (field._f.deps) {
1252
- trigger(field._f.deps);
1253
- }
1254
- shouldRenderBaseOnError(false, name, isValid, error, fieldState);
1255
- }
1256
- };
1257
- const _updateValidAndInputValue = (name, shouldSkipValueAs, ref) => {
1258
- const field = get(_fields, name);
1259
- if (field) {
1260
- const fieldValue = get(_formValues, name);
1261
- const defaultValue = isUndefined(fieldValue)
1262
- ? get(_defaultValues, name)
1263
- : fieldValue;
1264
- if (isUndefined(defaultValue) ||
1265
- (ref && ref.defaultChecked) ||
1266
- shouldSkipValueAs) {
1267
- set(_formValues, name, shouldSkipValueAs ? defaultValue : getFieldValue(field._f));
1268
- }
1269
- else {
1270
- setFieldValue(name, defaultValue);
1271
- }
1272
- }
1273
- _stateFlags.mount && _updateValid();
1274
- };
1275
- const _getIsDirty = (name, data) => {
1276
- name && data && set(_formValues, name, data);
1277
- return !deepEqual(Object.assign({}, getValues()), _defaultValues);
1278
- };
1279
- const _updateValid = async (skipRender) => {
1280
- let isValid = false;
1281
- if (_proxyFormState.isValid) {
1282
- isValid = formOptions.resolver
1283
- ? isEmptyObject((await executeResolver()).errors)
1284
- : await validateForm(_fields, true);
1285
- if (!skipRender && isValid !== _formState.isValid) {
1286
- _formState.isValid = isValid;
1287
- _subjects.state.next({
1288
- isValid,
1289
- });
1290
- }
1291
- }
1292
- return isValid;
1293
- };
1294
- const setValues = (name, value, options) => Object.entries(value).forEach(([fieldKey, fieldValue]) => {
1295
- const fieldName = `${name}.${fieldKey}`;
1296
- const field = get(_fields, fieldName);
1297
- (_names.array.has(name) ||
1298
- !isPrimitive(fieldValue) ||
1299
- (field && !field._f)) &&
1300
- !isDateObject(fieldValue)
1301
- ? setValues(fieldName, fieldValue, options)
1302
- : setFieldValue(fieldName, fieldValue, options, true);
1303
- });
1304
- const _getWatch = (fieldNames, defaultValue, isMounted, isGlobal) => {
1305
- const fieldValues = Object.assign({}, (isMounted || _stateFlags.mount
1306
- ? _formValues
1307
- : isUndefined(defaultValue)
1308
- ? _defaultValues
1309
- : isString(fieldNames)
1310
- ? { [fieldNames]: defaultValue }
1311
- : defaultValue));
1312
- if (!fieldNames) {
1313
- isGlobal && (_names.watchAll = true);
1314
- return fieldValues;
1389
+ field._f.deps && trigger(field._f.deps);
1390
+ shouldRenderByError(false, name, isValid, error, fieldState);
1315
1391
  }
1316
- const result = [];
1317
- for (const fieldName of convertToArrayPayload(fieldNames)) {
1318
- isGlobal && _names.watch.add(fieldName);
1319
- result.push(get(fieldValues, fieldName));
1320
- }
1321
- return Array.isArray(fieldNames) ? result : result[0];
1322
- };
1323
- const _updateFieldArray = (keyName, name, method, args, values = [], shouldSet = true, shouldSetFields = true) => {
1324
- let output;
1325
- _stateFlags.action = true;
1326
- if (shouldSetFields && get(_fields, name)) {
1327
- output = method(get(_fields, name), args.argA, args.argB);
1328
- shouldSet && set(_fields, name, output);
1329
- }
1330
- if (Array.isArray(get(_formState.errors, name))) {
1331
- const output = method(get(_formState.errors, name), args.argA, args.argB);
1332
- shouldSet && set(_formState.errors, name, output);
1333
- unsetEmptyArray(_formState.errors, name);
1334
- }
1335
- if (_proxyFormState.touchedFields && get(_formState.touchedFields, name)) {
1336
- const output = method(get(_formState.touchedFields, name), args.argA, args.argB);
1337
- shouldSet && set(_formState.touchedFields, name, output);
1338
- unsetEmptyArray(_formState.touchedFields, name);
1339
- }
1340
- if (_proxyFormState.dirtyFields || _proxyFormState.isDirty) {
1341
- set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(values, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
1342
- values &&
1343
- set(_formState.dirtyFields, name, setFieldArrayDirtyFields(omitKey(values, keyName), get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
1344
- unsetEmptyArray(_formState.dirtyFields, name);
1345
- }
1346
- _subjects.state.next({
1347
- isDirty: _getIsDirty(name, omitKey(values, keyName)),
1348
- dirtyFields: _formState.dirtyFields,
1349
- errors: _formState.errors,
1350
- isValid: _formState.isValid,
1351
- });
1352
- };
1353
- const _getFieldArrayValue = (name) => get(_stateFlags.mount ? _formValues : _defaultValues, name, []);
1354
- const setValue = (name, value, options = {}) => {
1355
- const field = get(_fields, name);
1356
- const isFieldArray = _names.array.has(name);
1357
- set(_formValues, name, value);
1358
- if (isFieldArray) {
1359
- _subjects.array.next({
1360
- name,
1361
- values: _formValues,
1362
- });
1363
- if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields) &&
1364
- options.shouldDirty) {
1365
- set(_formState.dirtyFields, name, setFieldArrayDirtyFields(value, get(_defaultValues, name, []), get(_formState.dirtyFields, name, [])));
1366
- _subjects.state.next({
1367
- name,
1368
- dirtyFields: _formState.dirtyFields,
1369
- isDirty: _getIsDirty(name, value),
1370
- });
1371
- }
1372
- }
1373
- else {
1374
- field && !field._f && !isNullOrUndefined(value)
1375
- ? setValues(name, value, options)
1376
- : setFieldValue(name, value, options, true);
1377
- }
1378
- isFieldWatched(name) && _subjects.state.next({});
1379
- _subjects.watch.next({
1380
- name,
1381
- });
1382
1392
  };
1383
1393
  const trigger = async (name, options = {}) => {
1384
- const fieldNames = convertToArrayPayload(name);
1385
1394
  let isValid;
1386
1395
  let validationResult;
1396
+ const fieldNames = convertToArrayPayload(name);
1387
1397
  _subjects.state.next({
1388
1398
  isValidating: true,
1389
1399
  });
1390
- if (formOptions.resolver) {
1391
- const schemaResult = await executeResolverValidation(isUndefined(name) ? name : fieldNames);
1392
- isValid = isEmptyObject(schemaResult);
1400
+ if (_options.resolver) {
1401
+ const errors = await executeResolverValidation(isUndefined(name) ? name : fieldNames);
1402
+ isValid = isEmptyObject(errors);
1393
1403
  validationResult = name
1394
- ? !fieldNames.some((name) => get(schemaResult, name))
1404
+ ? !fieldNames.some((name) => get(errors, name))
1395
1405
  : isValid;
1396
1406
  }
1397
1407
  else if (name) {
1398
1408
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1399
1409
  const field = get(_fields, fieldName);
1400
- return await validateForm(field && field._f ? { [fieldName]: field } : field);
1410
+ return await executeBuildInValidation(field && field._f ? { [fieldName]: field } : field);
1401
1411
  }))).every(Boolean);
1402
1412
  _updateValid();
1403
1413
  }
1404
1414
  else {
1405
- validationResult = isValid = await validateForm(_fields);
1415
+ validationResult = isValid = await executeBuildInValidation(_fields);
1406
1416
  }
1407
1417
  _subjects.state.next(Object.assign(Object.assign({}, (!isString(name) || isValid !== _formState.isValid ? {} : { name })), { errors: _formState.errors, isValid, isValidating: false }));
1408
- if (options.shouldFocus && !validationResult) {
1418
+ options.shouldFocus &&
1419
+ !validationResult &&
1409
1420
  focusFieldBy(_fields, (key) => get(_formState.errors, key), name ? fieldNames : _names.mount);
1410
- }
1411
1421
  return validationResult;
1412
1422
  };
1413
1423
  const getValues = (fieldNames) => {
@@ -1436,88 +1446,83 @@ function createFormControl(props = {}) {
1436
1446
  });
1437
1447
  options && options.shouldFocus && ref && ref.focus && ref.focus();
1438
1448
  };
1439
- const watch = (fieldName, defaultValue) => isFunction(fieldName)
1449
+ const watch = (name, defaultValue) => isFunction(name)
1440
1450
  ? _subjects.watch.subscribe({
1441
- next: (info) => fieldName(_getWatch(undefined, defaultValue), info),
1451
+ next: (info) => name(_getWatch(undefined, defaultValue), info),
1442
1452
  })
1443
- : _getWatch(fieldName, defaultValue, false, true);
1453
+ : _getWatch(name, defaultValue, true);
1444
1454
  const unregister = (name, options = {}) => {
1445
- for (const inputName of name ? convertToArrayPayload(name) : _names.mount) {
1446
- _names.mount.delete(inputName);
1447
- _names.array.delete(inputName);
1448
- if (get(_fields, inputName)) {
1455
+ for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
1456
+ _names.mount.delete(fieldName);
1457
+ _names.array.delete(fieldName);
1458
+ if (get(_fields, fieldName)) {
1449
1459
  if (!options.keepValue) {
1450
- unset(_fields, inputName);
1451
- unset(_formValues, inputName);
1460
+ unset(_fields, fieldName);
1461
+ unset(_formValues, fieldName);
1452
1462
  }
1453
- !options.keepError && unset(_formState.errors, inputName);
1454
- !options.keepDirty && unset(_formState.dirtyFields, inputName);
1455
- !options.keepTouched && unset(_formState.touchedFields, inputName);
1456
- !formOptions.shouldUnregister &&
1463
+ !options.keepError && unset(_formState.errors, fieldName);
1464
+ !options.keepDirty && unset(_formState.dirtyFields, fieldName);
1465
+ !options.keepTouched && unset(_formState.touchedFields, fieldName);
1466
+ !_options.shouldUnregister &&
1457
1467
  !options.keepDefaultValue &&
1458
- unset(_defaultValues, inputName);
1468
+ unset(_defaultValues, fieldName);
1459
1469
  }
1460
1470
  }
1461
1471
  _subjects.watch.next({});
1462
- _subjects.state.next(Object.assign(Object.assign({}, _formState), (!options.keepDirty ? {} : { isDirty: _getIsDirty() })));
1472
+ _subjects.state.next(Object.assign(Object.assign({}, _formState), (!options.keepDirty ? {} : { isDirty: _getDirty() })));
1463
1473
  !options.keepIsValid && _updateValid();
1464
1474
  };
1465
- const registerFieldRef = (name, fieldRef, options) => {
1466
- register(name, options);
1467
- let field = get(_fields, name);
1468
- const ref = isUndefined(fieldRef.value)
1469
- ? fieldRef.querySelectorAll
1470
- ? fieldRef.querySelectorAll('input,select,textarea')[0] ||
1471
- fieldRef
1472
- : fieldRef
1473
- : fieldRef;
1474
- const isRadioOrCheckbox = isRadioOrCheckboxFunction(ref);
1475
- if (ref === field._f.ref ||
1476
- (isRadioOrCheckbox &&
1477
- compact(field._f.refs || []).find((option) => option === ref))) {
1478
- return;
1479
- }
1480
- field = {
1481
- _f: isRadioOrCheckbox
1482
- ? Object.assign(Object.assign({}, field._f), { refs: [
1483
- ...compact(field._f.refs || []).filter((ref) => isHTMLElement(ref) && document.contains(ref)),
1484
- ref,
1485
- ], ref: { type: ref.type, name } }) : Object.assign(Object.assign({}, field._f), { ref }),
1486
- };
1487
- set(_fields, name, field);
1488
- (!options || !options.disabled) &&
1489
- _updateValidAndInputValue(name, false, ref);
1490
- };
1491
1475
  const register = (name, options = {}) => {
1492
1476
  const field = get(_fields, name);
1493
1477
  set(_fields, name, {
1494
1478
  _f: Object.assign(Object.assign(Object.assign({}, (field && field._f ? field._f : { ref: { name } })), { name, mount: true }), options),
1495
1479
  });
1496
1480
  _names.mount.add(name);
1497
- if (!isUndefined(options.value)) {
1498
- set(_formValues, name, options.value);
1499
- }
1500
- if (field && isBoolean(options.disabled)) {
1501
- set(_formValues, name, options.disabled
1502
- ? undefined
1503
- : get(_formValues, name, getFieldValue(field._f)));
1504
- }
1505
- !field && _updateValidAndInputValue(name, true);
1481
+ !isUndefined(options.value) && set(_formValues, name, options.value);
1482
+ field
1483
+ ? isBoolean(options.disabled) &&
1484
+ set(_formValues, name, options.disabled
1485
+ ? undefined
1486
+ : get(_formValues, name, getFieldValue(field._f)))
1487
+ : updateValidAndValue(name, true);
1506
1488
  return isWindowUndefined
1507
1489
  ? { name: name }
1508
1490
  : Object.assign(Object.assign({ name }, (isBoolean(options.disabled)
1509
1491
  ? { disabled: options.disabled }
1510
1492
  : {})), { onChange: handleChange, onBlur: handleChange, ref: (ref) => {
1511
1493
  if (ref) {
1512
- registerFieldRef(name, ref, options);
1494
+ register(name, options);
1495
+ let field = get(_fields, name);
1496
+ const fieldRef = isUndefined(ref.value)
1497
+ ? ref.querySelectorAll
1498
+ ? ref.querySelectorAll('input,select,textarea')[0] ||
1499
+ ref
1500
+ : ref
1501
+ : ref;
1502
+ const isRadioOrCheckbox = isRadioOrCheckboxFunction(fieldRef);
1503
+ if (fieldRef === field._f.ref ||
1504
+ (isRadioOrCheckbox &&
1505
+ compact(field._f.refs || []).find((option) => option === fieldRef))) {
1506
+ return;
1507
+ }
1508
+ field = {
1509
+ _f: isRadioOrCheckbox
1510
+ ? Object.assign(Object.assign({}, field._f), { refs: [
1511
+ ...compact(field._f.refs || []).filter(live),
1512
+ fieldRef,
1513
+ ], ref: { type: fieldRef.type, name } }) : Object.assign(Object.assign({}, field._f), { ref: fieldRef }),
1514
+ };
1515
+ set(_fields, name, field);
1516
+ (!options || !options.disabled) &&
1517
+ updateValidAndValue(name, false, fieldRef);
1513
1518
  }
1514
1519
  else {
1515
1520
  const field = get(_fields, name, {});
1516
- const _shouldUnregister = formOptions.shouldUnregister || options.shouldUnregister;
1521
+ const shouldUnregister = _options.shouldUnregister || options.shouldUnregister;
1517
1522
  if (field._f) {
1518
1523
  field._f.mount = false;
1519
1524
  }
1520
- _shouldUnregister &&
1525
+ shouldUnregister &&
1521
1526
  !(isNameInFieldArray(_names.array, name) && _stateFlags.action) &&
1522
1527
  _names.unMount.add(name);
1523
1528
  }
@@ -1534,13 +1539,13 @@ function createFormControl(props = {}) {
1534
1539
  isSubmitting: true,
1535
1540
  });
1536
1541
  try {
1537
- if (formOptions.resolver) {
1542
+ if (_options.resolver) {
1538
1543
  const { errors, values } = await executeResolver();
1539
1544
  _formState.errors = errors;
1540
1545
  fieldValues = values;
1541
1546
  }
1542
1547
  else {
1543
- await validateForm(_fields);
1548
+ await executeBuildInValidation(_fields);
1544
1549
  }
1545
1550
  if (isEmptyObject(_formState.errors) &&
1546
1551
  Object.keys(_formState.errors).every((name) => get(fieldValues, name))) {
@@ -1552,7 +1557,7 @@ function createFormControl(props = {}) {
1552
1557
  }
1553
1558
  else {
1554
1559
  onInvalid && (await onInvalid(_formState.errors, e));
1555
- formOptions.shouldFocusError &&
1560
+ _options.shouldFocusError &&
1556
1561
  focusFieldBy(_fields, (key) => get(_formState.errors, key), _names.mount);
1557
1562
  }
1558
1563
  }
@@ -1572,39 +1577,41 @@ function createFormControl(props = {}) {
1572
1577
  }
1573
1578
  };
1574
1579
  const reset = (formValues, keepStateOptions = {}) => {
1580
+ const hasUpdatedFormValues = !isEmptyObject(formValues);
1575
1581
  const updatedValues = formValues || _defaultValues;
1576
- const values = cloneObject(updatedValues);
1577
- if (!keepStateOptions.keepValues) {
1578
- _formValues = props.shouldUnregister ? {} : values;
1582
+ const cloneUpdatedValues = cloneObject(updatedValues);
1583
+ if (!keepStateOptions.keepDefaultValues) {
1584
+ _defaultValues = updatedValues;
1579
1585
  }
1580
- if (isWeb && !keepStateOptions.keepValues) {
1581
- for (const name of _names.mount) {
1582
- const field = get(_fields, name);
1583
- if (field && field._f) {
1584
- const inputRef = Array.isArray(field._f.refs)
1585
- ? field._f.refs[0]
1586
- : field._f.ref;
1587
- try {
1588
- isHTMLElement(inputRef) && inputRef.closest('form').reset();
1589
- break;
1586
+ if (!keepStateOptions.keepValues) {
1587
+ if (isWeb) {
1588
+ for (const name of _names.mount) {
1589
+ const field = get(_fields, name);
1590
+ if (field && field._f) {
1591
+ const fieldReference = Array.isArray(field._f.refs)
1592
+ ? field._f.refs[0]
1593
+ : field._f.ref;
1594
+ try {
1595
+ isHTMLElement(fieldReference) &&
1596
+ fieldReference.closest('form').reset();
1597
+ break;
1598
+ }
1599
+ catch (_a) { }
1590
1600
  }
1591
- catch (_a) { }
1592
1601
  }
1593
1602
  }
1594
- }
1595
- if (!keepStateOptions.keepDefaultValues) {
1596
- _defaultValues = Object.assign({}, updatedValues);
1597
- }
1598
- if (!keepStateOptions.keepValues) {
1603
+ _formValues = props.shouldUnregister
1604
+ ? keepStateOptions.keepDefaultValues
1605
+ ? _defaultValues
1606
+ : {}
1607
+ : cloneUpdatedValues;
1599
1608
  _fields = {};
1600
1609
  _subjects.control.next({
1601
- values: keepStateOptions.keepDefaultValues
1602
- ? _defaultValues
1603
- : Object.assign({}, updatedValues),
1610
+ values: hasUpdatedFormValues ? cloneUpdatedValues : _defaultValues,
1604
1611
  });
1605
1612
  _subjects.watch.next({});
1606
1613
  _subjects.array.next({
1607
- values,
1614
+ values: cloneUpdatedValues,
1608
1615
  });
1609
1616
  }
1610
1617
  _names = {
@@ -1622,14 +1629,16 @@ function createFormControl(props = {}) {
1622
1629
  isDirty: keepStateOptions.keepDirty
1623
1630
  ? _formState.isDirty
1624
1631
  : keepStateOptions.keepDefaultValues
1625
- ? deepEqual(formValues, _defaultValues)
1632
+ ? !deepEqual(formValues, _defaultValues)
1626
1633
  : false,
1627
1634
  isSubmitted: keepStateOptions.keepIsSubmitted
1628
1635
  ? _formState.isSubmitted
1629
1636
  : false,
1630
1637
  dirtyFields: keepStateOptions.keepDirty
1631
1638
  ? _formState.dirtyFields
1632
- : {},
1639
+ : (keepStateOptions.keepDefaultValues && formValues
1640
+ ? Object.entries(formValues).reduce((previous, [key, value]) => (Object.assign(Object.assign({}, previous), { [key]: value !== get(_defaultValues, key) })), {})
1641
+ : {}),
1633
1642
  touchedFields: keepStateOptions.keepTouched
1634
1643
  ? _formState.touchedFields
1635
1644
  : {},
@@ -1643,28 +1652,21 @@ function createFormControl(props = {}) {
1643
1652
  !_proxyFormState.isValid || !!keepStateOptions.keepIsValid;
1644
1653
  _stateFlags.watch = !!props.shouldUnregister;
1645
1654
  };
1646
- const setFocus = (name) => get(_fields, name)._f.ref.focus();
1647
- const _removeFields = () => {
1648
- for (const name of _names.unMount) {
1649
- const field = get(_fields, name);
1650
- field &&
1651
- (field._f.refs ? field._f.refs.every(live) : live(field._f.ref)) &&
1652
- unregister(name);
1653
- }
1654
- _names.unMount = new Set();
1655
+ const setFocus = (name) => {
1656
+ const field = get(_fields, name)._f;
1657
+ (field.ref.focus ? field.ref : field.refs[0]).focus();
1655
1658
  };
1656
1659
  return {
1657
1660
  control: {
1658
1661
  register,
1659
1662
  unregister,
1660
1663
  _getWatch,
1661
- _getIsDirty,
1664
+ _getDirty,
1662
1665
  _updateValid,
1663
- _removeFields,
1666
+ _removeUnmounted,
1664
1667
  _updateFieldArray,
1665
- _getFieldArrayValue,
1668
+ _getFieldArray,
1666
1669
  _subjects,
1667
- _shouldUnregister: formOptions.shouldUnregister,
1668
1670
  _proxyFormState,
1669
1671
  get _fields() {
1670
1672
  return _fields;
@@ -1702,8 +1704,11 @@ function createFormControl(props = {}) {
1702
1704
  set _formState(value) {
1703
1705
  _formState = value;
1704
1706
  },
1705
- _updateProps: (options) => {
1706
- formOptions = Object.assign(Object.assign({}, defaultOptions), options);
1707
+ get _options() {
1708
+ return _options;
1709
+ },
1710
+ set _options(value) {
1711
+ _options = Object.assign(Object.assign({}, _options), value);
1707
1712
  },
1708
1713
  },
1709
1714
  trigger,
@@ -1735,7 +1740,7 @@ function useForm(props = {}) {
1735
1740
  errors: {},
1736
1741
  });
1737
1742
  if (_formControl.current) {
1738
- _formControl.current.control._updateProps(props);
1743
+ _formControl.current.control._options = props;
1739
1744
  }
1740
1745
  else {
1741
1746
  _formControl.current = Object.assign(Object.assign({}, createFormControl(props)), { formState });
@@ -1759,7 +1764,7 @@ function useForm(props = {}) {
1759
1764
  control._stateFlags.watch = false;
1760
1765
  control._subjects.state.next({});
1761
1766
  }
1762
- control._removeFields();
1767
+ control._removeUnmounted();
1763
1768
  });
1764
1769
  _formControl.current.formState = getProxyFormState(formState, control._proxyFormState);
1765
1770
  return _formControl.current;
@@ -1773,18 +1778,14 @@ function useWatch(props) {
1773
1778
  useSubscribe({
1774
1779
  disabled,
1775
1780
  subject: control._subjects.watch,
1776
- callback: ({ name }) => {
1777
- if (!_name.current ||
1778
- !name ||
1779
- convertToArrayPayload(_name.current).some((currentName) => name &&
1780
- currentName &&
1781
- (name.startsWith(currentName) ||
1782
- currentName.startsWith(name)))) {
1783
- const result = control._getWatch(_name.current, defaultValue, true);
1784
- updateValue(isObject(result)
1785
- ? Object.assign({}, result) : Array.isArray(result)
1786
- ? [...result]
1787
- : result);
1781
+ callback: (formState) => {
1782
+ if (shouldSubscribeByName(_name.current, formState.name)) {
1783
+ control._stateFlags.mount = true;
1784
+ const fieldValues = control._getWatch(_name.current, defaultValue);
1785
+ updateValue(isObject(fieldValues)
1786
+ ? Object.assign({}, fieldValues) : Array.isArray(fieldValues)
1787
+ ? [...fieldValues]
1788
+ : fieldValues);
1788
1789
  }
1789
1790
  },
1790
1791
  });
@@ -1792,7 +1793,7 @@ function useWatch(props) {
1792
1793
  ? control._getWatch(name)
1793
1794
  : defaultValue);
1794
1795
  React.useEffect(() => {
1795
- control._removeFields();
1796
+ control._removeUnmounted();
1796
1797
  });
1797
1798
  return value;
1798
1799
  }