react-hook-form 7.71.1 → 7.72.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAaV,WAAW,EAiBX,YAAY,EAIZ,aAAa,EAUd,MAAM,UAAU,CAAC;AAqDlB,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EAEjC,KAAK,GAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAM,GACnE,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,CAAC;CACH,CAu+CA"}
1
+ {"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAaV,WAAW,EAiBX,YAAY,EAIZ,aAAa,EAWd,MAAM,UAAU,CAAC;AAsDlB,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EAEjC,KAAK,GAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAM,GACnE,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,CAAC;CACH,CAslDA"}
@@ -1 +1 @@
1
- {"version":3,"file":"updateFieldArrayRootError.d.ts","sourceRoot":"","sources":["../../src/logic/updateFieldArrayRootError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,iBAAiB,EAClB,MAAM,UAAU,CAAC;yBAKF,CAAC,SAAS,WAAW,GAAG,WAAW,EACjD,QAAQ,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAC1C,MAAM,iBAAiB,KACtB,WAAW,CAAC,CAAC,CAAC;AAJjB,wBASE"}
1
+ {"version":3,"file":"updateFieldArrayRootError.d.ts","sourceRoot":"","sources":["../../src/logic/updateFieldArrayRootError.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,iBAAiB,EAClB,MAAM,UAAU,CAAC;yBAKF,CAAC,SAAS,WAAW,GAAG,WAAW,EACjD,QAAQ,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAC1C,MAAM,iBAAiB,KACtB,WAAW,CAAC,CAAC,CAAC;AAJjB,wBASE"}
@@ -10,7 +10,11 @@ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => va
10
10
 
11
11
  const EVENTS = {
12
12
  BLUR: 'blur',
13
- FOCUS_OUT: 'focusout'};
13
+ FOCUS_OUT: 'focusout',
14
+ SUBMIT: 'submit',
15
+ TRIGGER: 'trigger',
16
+ VALID: 'valid',
17
+ };
14
18
  const VALIDATION_MODE = {
15
19
  onBlur: 'onBlur',
16
20
  onChange: 'onChange',
@@ -27,6 +31,8 @@ const INPUT_VALIDATION_RULES = {
27
31
  required: 'required',
28
32
  validate: 'validate',
29
33
  };
34
+ const FORM_ERROR_TYPE = 'form';
35
+ const ROOT_ERROR_TYPE = 'root';
30
36
 
31
37
  var isDateObject = (value) => value instanceof Date;
32
38
 
@@ -401,6 +407,8 @@ function getFieldValue(_f) {
401
407
  return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
402
408
  }
403
409
 
410
+ var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
411
+
404
412
  var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
405
413
  const fields = {};
406
414
  for (const name of fieldsNames) {
@@ -452,8 +460,6 @@ var hasValidation = (options) => options.mount &&
452
460
  options.pattern ||
453
461
  options.validate);
454
462
 
455
- var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
456
-
457
463
  var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
458
464
 
459
465
  var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
@@ -563,7 +569,7 @@ var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(re
563
569
 
564
570
  var updateFieldArrayRootError = (errors, error, name) => {
565
571
  const fieldArrayErrors = convertToArrayPayload(get(errors, name));
566
- set(fieldArrayErrors, 'root', error[name]);
572
+ set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
567
573
  set(errors, name, fieldArrayErrors);
568
574
  return errors;
569
575
  };
@@ -852,7 +858,11 @@ function createFormControl(props = {}) {
852
858
  _updateIsValidating();
853
859
  }
854
860
  else {
855
- isValid = await executeBuiltInValidation(_fields, true);
861
+ isValid = await executeBuiltInValidation({
862
+ fields: _fields,
863
+ onlyCheckValid: true,
864
+ eventType: EVENTS.VALID,
865
+ });
856
866
  }
857
867
  if (isValid !== _formState.isValid) {
858
868
  _subjects.state.next({
@@ -901,7 +911,9 @@ function createFormControl(props = {}) {
901
911
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
902
912
  }
903
913
  if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
904
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
914
+ const fullDirtyFields = getDirtyFields(_defaultValues, _formValues);
915
+ const rootName = getNodeParentName(name);
916
+ set(_formState.dirtyFields, rootName, get(fullDirtyFields, rootName));
905
917
  }
906
918
  _subjects.state.next({
907
919
  name,
@@ -1015,8 +1027,7 @@ function createFormControl(props = {}) {
1015
1027
  };
1016
1028
  const _runSchema = async (name) => {
1017
1029
  _updateIsValidating(name, true);
1018
- const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1019
- return result;
1030
+ return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1020
1031
  };
1021
1032
  const executeSchemaAndUpdateState = async (names) => {
1022
1033
  const { errors } = await _runSchema(names);
@@ -1034,9 +1045,55 @@ function createFormControl(props = {}) {
1034
1045
  }
1035
1046
  return errors;
1036
1047
  };
1037
- const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
1048
+ const validateForm = async ({ name, eventType, }) => {
1049
+ if (props.validate) {
1050
+ const result = await props.validate({
1051
+ formValues: _formValues,
1052
+ formState: _formState,
1053
+ name,
1054
+ eventType,
1055
+ });
1056
+ if (isObject(result)) {
1057
+ for (const key in result) {
1058
+ const error = result[key];
1059
+ if (error) {
1060
+ setError(`${FORM_ERROR_TYPE}.${key}`, {
1061
+ message: isString(result.message) ? result.message : '',
1062
+ type: INPUT_VALIDATION_RULES.validate,
1063
+ });
1064
+ }
1065
+ }
1066
+ }
1067
+ else if (isString(result) || !result) {
1068
+ setError(FORM_ERROR_TYPE, {
1069
+ message: result || '',
1070
+ type: INPUT_VALIDATION_RULES.validate,
1071
+ });
1072
+ }
1073
+ else {
1074
+ clearErrors(FORM_ERROR_TYPE);
1075
+ }
1076
+ return result;
1077
+ }
1078
+ return true;
1079
+ };
1080
+ const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
1038
1081
  valid: true,
1039
- }) => {
1082
+ runRootValidation: false,
1083
+ }, }) => {
1084
+ if (props.validate) {
1085
+ context.runRootValidation = true;
1086
+ const result = await validateForm({
1087
+ name,
1088
+ eventType,
1089
+ });
1090
+ if (!result) {
1091
+ context.valid = false;
1092
+ if (onlyCheckValid) {
1093
+ return context.valid;
1094
+ }
1095
+ }
1096
+ }
1040
1097
  for (const name in fields) {
1041
1098
  const field = fields[name];
1042
1099
  if (field) {
@@ -1047,25 +1104,34 @@ function createFormControl(props = {}) {
1047
1104
  if (isPromiseFunction && _proxyFormState.validatingFields) {
1048
1105
  _updateIsValidating([_f.name], true);
1049
1106
  }
1050
- const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1107
+ const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1051
1108
  if (isPromiseFunction && _proxyFormState.validatingFields) {
1052
1109
  _updateIsValidating([_f.name]);
1053
1110
  }
1054
1111
  if (fieldError[_f.name]) {
1055
1112
  context.valid = false;
1056
- if (shouldOnlyCheckValid || props.shouldUseNativeValidation) {
1113
+ if (onlyCheckValid) {
1057
1114
  break;
1058
1115
  }
1059
1116
  }
1060
- !shouldOnlyCheckValid &&
1117
+ !onlyCheckValid &&
1061
1118
  (get(fieldError, _f.name)
1062
1119
  ? isFieldArrayRoot
1063
1120
  ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
1064
1121
  : set(_formState.errors, _f.name, fieldError[_f.name])
1065
1122
  : unset(_formState.errors, _f.name));
1123
+ if (props.shouldUseNativeValidation && fieldError[_f.name]) {
1124
+ break;
1125
+ }
1066
1126
  }
1067
1127
  !isEmptyObject(fieldValue) &&
1068
- (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
1128
+ (await executeBuiltInValidation({
1129
+ context,
1130
+ onlyCheckValid,
1131
+ fields: fieldValue,
1132
+ name: name,
1133
+ eventType,
1134
+ }));
1069
1135
  }
1070
1136
  }
1071
1137
  return context.valid;
@@ -1224,6 +1290,7 @@ function createFormControl(props = {}) {
1224
1290
  : getEventValue(event);
1225
1291
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1226
1292
  const shouldSkipValidation = (!hasValidation(field._f) &&
1293
+ !props.validate &&
1227
1294
  !_options.resolver &&
1228
1295
  !get(_formState.errors, name) &&
1229
1296
  !field._f.deps) ||
@@ -1261,6 +1328,12 @@ function createFormControl(props = {}) {
1261
1328
  return (shouldRender &&
1262
1329
  _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
1263
1330
  }
1331
+ if (!_options.resolver && props.validate) {
1332
+ await validateForm({
1333
+ name: name,
1334
+ eventType: event.type,
1335
+ });
1336
+ }
1264
1337
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
1265
1338
  if (_options.resolver) {
1266
1339
  const { errors } = await _runSchema([name]);
@@ -1285,7 +1358,12 @@ function createFormControl(props = {}) {
1285
1358
  }
1286
1359
  else if (_proxyFormState.isValid ||
1287
1360
  _proxySubscribeFormState.isValid) {
1288
- isValid = await executeBuiltInValidation(_fields, true);
1361
+ isValid = await executeBuiltInValidation({
1362
+ fields: _fields,
1363
+ onlyCheckValid: true,
1364
+ name: name,
1365
+ eventType: event.type,
1366
+ });
1289
1367
  }
1290
1368
  }
1291
1369
  }
@@ -1318,12 +1396,19 @@ function createFormControl(props = {}) {
1318
1396
  else if (name) {
1319
1397
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1320
1398
  const field = get(_fields, fieldName);
1321
- return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
1399
+ return await executeBuiltInValidation({
1400
+ fields: field && field._f ? { [fieldName]: field } : field,
1401
+ eventType: EVENTS.TRIGGER,
1402
+ });
1322
1403
  }))).every(Boolean);
1323
1404
  !(!validationResult && !_formState.isValid) && _setValid();
1324
1405
  }
1325
1406
  else {
1326
- validationResult = isValid = await executeBuiltInValidation(_fields);
1407
+ validationResult = isValid = await executeBuiltInValidation({
1408
+ fields: _fields,
1409
+ name,
1410
+ eventType: EVENTS.TRIGGER,
1411
+ });
1327
1412
  }
1328
1413
  _subjects.state.next({
1329
1414
  ...(!isString(name) ||
@@ -1360,11 +1445,24 @@ function createFormControl(props = {}) {
1360
1445
  isTouched: !!get((formState || _formState).touchedFields, name),
1361
1446
  });
1362
1447
  const clearErrors = (name) => {
1363
- name &&
1364
- convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
1365
- _subjects.state.next({
1366
- errors: name ? _formState.errors : {},
1367
- });
1448
+ const names = name ? convertToArrayPayload(name) : undefined;
1449
+ names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
1450
+ if (names) {
1451
+ // Emit for each cleared field with the field name so that
1452
+ // shouldSubscribeByName can filter and avoid broad re-renders
1453
+ names.forEach((inputName) => {
1454
+ _subjects.state.next({
1455
+ name: inputName,
1456
+ errors: _formState.errors,
1457
+ });
1458
+ });
1459
+ }
1460
+ else {
1461
+ // Clear all errors - emit without name to notify all subscribers
1462
+ _subjects.state.next({
1463
+ errors: {},
1464
+ });
1465
+ }
1368
1466
  };
1369
1467
  const setError = (name, error, options) => {
1370
1468
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
@@ -1575,14 +1673,17 @@ function createFormControl(props = {}) {
1575
1673
  fieldValues = cloneObject(values);
1576
1674
  }
1577
1675
  else {
1578
- await executeBuiltInValidation(_fields);
1676
+ await executeBuiltInValidation({
1677
+ fields: _fields,
1678
+ eventType: EVENTS.SUBMIT,
1679
+ });
1579
1680
  }
1580
1681
  if (_names.disabled.size) {
1581
1682
  for (const name of _names.disabled) {
1582
1683
  unset(fieldValues, name);
1583
1684
  }
1584
1685
  }
1585
- unset(_formState.errors, 'root');
1686
+ unset(_formState.errors, ROOT_ERROR_TYPE);
1586
1687
  if (isEmptyObject(_formState.errors)) {
1587
1688
  _subjects.state.next({
1588
1689
  errors: {},