react-hook-form 7.16.1 → 7.17.2

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