@bombillazo/rhf-plus 7.64.0-plus.0 → 7.64.0-plus.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.
@@ -453,6 +453,8 @@ function useController(props) {
453
453
  ...props.rules,
454
454
  value,
455
455
  ...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
456
+ ...(props.mode ? { mode: props.mode } : {}),
457
+ ...(props.reValidateMode ? { reValidateMode: props.reValidateMode } : {}),
456
458
  }));
457
459
  const mergedRules = React.useMemo(() => mergeMissingKeysAsUndefined(_previousRules.current, props.rules), [props.rules]);
458
460
  // Update register props when rules change
@@ -461,9 +463,20 @@ function useController(props) {
461
463
  ...mergedRules,
462
464
  value,
463
465
  ...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}),
466
+ ...(props.mode ? { mode: props.mode } : {}),
467
+ ...(props.reValidateMode ? { reValidateMode: props.reValidateMode } : {}),
464
468
  });
465
469
  _previousRules.current = props.rules;
466
- }, [mergedRules, props.rules, value, props.disabled, control, name]);
470
+ }, [
471
+ mergedRules,
472
+ props.rules,
473
+ value,
474
+ props.disabled,
475
+ props.mode,
476
+ props.reValidateMode,
477
+ control,
478
+ name,
479
+ ]);
467
480
  _props.current = props;
468
481
  const fieldState = React.useMemo(() => Object.defineProperties({}, {
469
482
  invalid: {
@@ -577,6 +590,10 @@ function useController(props) {
577
590
  ...(isBoolean(_props.current.disabled)
578
591
  ? { disabled: _props.current.disabled }
579
592
  : {}),
593
+ ...(_props.current.mode ? { mode: _props.current.mode } : {}),
594
+ ...(_props.current.reValidateMode
595
+ ? { reValidateMode: _props.current.reValidateMode }
596
+ : {}),
580
597
  });
581
598
  const updateMounted = (name, value) => {
582
599
  const field = get(control._fields, name);
@@ -1196,21 +1213,37 @@ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode,
1196
1213
  /**
1197
1214
  * Need to keep this order of parameters for backward compatibility
1198
1215
  */
1199
- isFocusEvent) => {
1216
+ isFocusEvent,
1217
+ /**
1218
+ * Optional field-level validation mode that overrides form-level mode.
1219
+ * When provided, this field's mode takes precedence over the form's mode.
1220
+ * Partial because only the relevant flags (e.g., isOnChange, isOnBlur) need to be checked.
1221
+ */
1222
+ fieldMode,
1223
+ /**
1224
+ * Optional field-level revalidation mode that overrides form-level reValidateMode.
1225
+ * When provided, this field's reValidateMode takes precedence after form submission.
1226
+ * Only includes isOnBlur and isOnChange as these are the only valid revalidation modes.
1227
+ */
1228
+ fieldReValidateMode) => {
1229
+ // Use field-level modes if provided, otherwise fallback to form-level modes
1230
+ // This allows individual fields to have different validation timing than the form
1231
+ const effectiveMode = fieldMode || mode;
1232
+ const effectiveReValidateMode = fieldReValidateMode || reValidateMode;
1200
1233
  // Focus events should always skip validation
1201
1234
  if (isFocusEvent) {
1202
1235
  return true;
1203
1236
  }
1204
- if (mode.isOnAll) {
1237
+ if (effectiveMode.isOnAll) {
1205
1238
  return false;
1206
1239
  }
1207
- else if (!isSubmitted && mode.isOnTouch) {
1240
+ else if (!isSubmitted && effectiveMode.isOnTouch) {
1208
1241
  return !(isTouched || isBlurEvent);
1209
1242
  }
1210
- else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
1243
+ else if (isSubmitted ? effectiveReValidateMode.isOnBlur : effectiveMode.isOnBlur) {
1211
1244
  return !isBlurEvent;
1212
1245
  }
1213
- else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
1246
+ else if (isSubmitted ? effectiveReValidateMode.isOnChange : effectiveMode.isOnChange) {
1214
1247
  return isBlurEvent;
1215
1248
  }
1216
1249
  return true;
@@ -1225,25 +1258,13 @@ var updateFieldArrayRootError = (errors, error, name) => {
1225
1258
  return errors;
1226
1259
  };
1227
1260
 
1228
- var isMessage = (value) => {
1229
- // Support strings (existing functionality)
1230
- if (isString(value)) {
1231
- return true;
1232
- }
1233
- // Support React elements only (not primitives like null, undefined, numbers)
1234
- if (React.isValidElement(value)) {
1235
- return true;
1236
- }
1237
- return false;
1238
- };
1239
-
1240
1261
  function getValidateError(result, ref, type = 'validate') {
1241
- if (isMessage(result) ||
1242
- (Array.isArray(result) && result.every(isMessage)) ||
1262
+ if (isString(result) ||
1263
+ (Array.isArray(result) && result.every(isString)) ||
1243
1264
  (isBoolean(result) && !result)) {
1244
1265
  return {
1245
1266
  type,
1246
- message: isMessage(result) ? result : '',
1267
+ message: isString(result) ? result : '',
1247
1268
  ref,
1248
1269
  };
1249
1270
  }
@@ -1265,16 +1286,7 @@ var validateField = async (field, skippedFieldNames, formValues, validateAllFiel
1265
1286
  const inputRef = refs ? refs[0] : ref;
1266
1287
  const setCustomValidity = (message) => {
1267
1288
  if (shouldUseNativeValidation && inputRef.reportValidity) {
1268
- if (isBoolean(message)) {
1269
- inputRef.setCustomValidity('');
1270
- }
1271
- else if (typeof message === 'string') {
1272
- inputRef.setCustomValidity(message || '');
1273
- }
1274
- else {
1275
- // For ReactNode messages, convert to string or use empty string for native validation
1276
- inputRef.setCustomValidity('');
1277
- }
1289
+ inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
1278
1290
  inputRef.reportValidity();
1279
1291
  }
1280
1292
  };
@@ -1305,7 +1317,7 @@ var validateField = async (field, skippedFieldNames, formValues, validateAllFiel
1305
1317
  (isBoolean(inputValue) && !inputValue) ||
1306
1318
  (isCheckBox && !getCheckboxValue(refs).isValid) ||
1307
1319
  (isRadio && !getRadioValue(refs).isValid))) {
1308
- const { value, message } = isMessage(required)
1320
+ const { value, message } = isString(required)
1309
1321
  ? { value: !!required, message: required }
1310
1322
  : getValueAndMessage(required);
1311
1323
  if (value) {
@@ -1955,6 +1967,16 @@ function createFormControl(props = {}) {
1955
1967
  };
1956
1968
  const validationModeBeforeSubmit = getValidationModes(_options.mode);
1957
1969
  const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1970
+ // Extract field-level validation modes if they exist
1971
+ // Field-level modes take precedence over form-level modes, allowing
1972
+ // individual fields to override when they validate (mode) and when they
1973
+ // revalidate after form submission (reValidateMode)
1974
+ const fieldMode = (field === null || field === void 0 ? void 0 : field._f.mode)
1975
+ ? getValidationModes(field._f.mode)
1976
+ : undefined;
1977
+ const fieldReValidateMode = (field === null || field === void 0 ? void 0 : field._f.reValidateMode)
1978
+ ? getValidationModes(field._f.reValidateMode)
1979
+ : undefined;
1958
1980
  if (field) {
1959
1981
  // Check if field is disabled and should not process events
1960
1982
  const isFieldDisabled = isBoolean(field._f.disabled)
@@ -2013,7 +2035,7 @@ function createFormControl(props = {}) {
2013
2035
  !_options.resolver &&
2014
2036
  !get(_formState.errors, name) &&
2015
2037
  !field._f.deps) ||
2016
- skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit, isFocusEvent);
2038
+ skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit, isFocusEvent, fieldMode, fieldReValidateMode);
2017
2039
  const watched = isWatched(name, _names, isBlurEvent || isFocusEvent);
2018
2040
  set(_formValues, name, fieldValue);
2019
2041
  if (isBlurEvent) {