@bombillazo/rhf-plus 7.62.0-plus.5 → 7.62.0-plus.7

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,EACX,YAAY,EAgBZ,YAAY,EAIZ,aAAa,EAUd,MAAM,UAAU,CAAC;AAuDlB,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EACjC,SAAS,SAAS,YAAY,GAAG,GAAG,EAEpC,KAAK,GAAE,YAAY,CACjB,YAAY,EACZ,QAAQ,EACR,kBAAkB,EAClB,SAAS,CACL,GACL,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,CAAC,EACpE,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,CAAC,EACpE,WAAW,CACZ,CAAC;CACH,CAolDA"}
1
+ {"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAaV,WAAW,EACX,YAAY,EAgBZ,YAAY,EAIZ,aAAa,EAUd,MAAM,UAAU,CAAC;AAwDlB,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EACjC,SAAS,SAAS,YAAY,GAAG,GAAG,EAEpC,KAAK,GAAE,YAAY,CACjB,YAAY,EACZ,QAAQ,EACR,kBAAkB,EAClB,SAAS,CACL,GACL,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,CAAC,EACpE,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,SAAS,CAAC,EACpE,WAAW,CACZ,CAAC;CACH,CAovDA"}
@@ -1,4 +1,4 @@
1
1
  import type { Field, FieldValues, InternalFieldErrors, InternalNameSet } from '../types';
2
- declare const _default: <T extends FieldValues>(field: Field, disabledFieldNames: InternalNameSet, formValues: T, validateAllFieldCriteria: boolean, shouldUseNativeValidation?: boolean, isFieldArray?: boolean) => Promise<InternalFieldErrors>;
2
+ declare const _default: <T extends FieldValues>(field: Field, skippedFieldNames: InternalNameSet, formValues: T, validateAllFieldCriteria: boolean, shouldUseNativeValidation?: boolean, isFieldArray?: boolean) => Promise<InternalFieldErrors>;
3
3
  export default _default;
4
4
  //# sourceMappingURL=validateField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validateField.d.ts","sourceRoot":"","sources":["../../src/logic/validateField.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EAEL,WAAW,EACX,mBAAmB,EACnB,eAAe,EAKhB,MAAM,UAAU,CAAC;yBAsBI,CAAC,SAAS,WAAW,EACzC,OAAO,KAAK,EACZ,oBAAoB,eAAe,EACnC,YAAY,CAAC,EACb,0BAA0B,OAAO,EACjC,4BAA4B,OAAO,EACnC,eAAe,OAAO,KACrB,OAAO,CAAC,mBAAmB,CAAC;AAP/B,wBAoQE"}
1
+ {"version":3,"file":"validateField.d.ts","sourceRoot":"","sources":["../../src/logic/validateField.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,KAAK,EAEL,WAAW,EACX,mBAAmB,EACnB,eAAe,EAKhB,MAAM,UAAU,CAAC;yBAsBI,CAAC,SAAS,WAAW,EACzC,OAAO,KAAK,EACZ,mBAAmB,eAAe,EAClC,YAAY,CAAC,EACb,0BAA0B,OAAO,EACjC,4BAA4B,OAAO,EACnC,eAAe,OAAO,KACrB,OAAO,CAAC,mBAAmB,CAAC;AAP/B,wBAqQE"}
@@ -643,10 +643,10 @@ var getValueAndMessage = (validationData) => isObject(validationData) && !isRege
643
643
  message: '',
644
644
  };
645
645
 
646
- var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
646
+ var validateField = async (field, skippedFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => {
647
647
  const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f;
648
648
  const inputValue = get(formValues, name);
649
- if (!mount || disabledFieldNames.has(name)) {
649
+ if (!mount || skippedFieldNames.has(name)) {
650
650
  return {};
651
651
  }
652
652
  const inputRef = refs ? refs[0] : ref;
@@ -835,6 +835,7 @@ const defaultOptions = {
835
835
  mode: VALIDATION_MODE.onSubmit,
836
836
  reValidateMode: VALIDATION_MODE.onChange,
837
837
  shouldFocusError: true,
838
+ shouldSkipReadOnlyValidation: false,
838
839
  };
839
840
  function createFormControl(props = {}) {
840
841
  let _options = {
@@ -845,6 +846,8 @@ function createFormControl(props = {}) {
845
846
  let _formState = {
846
847
  submitCount: 0,
847
848
  isDirty: false,
849
+ isDirtySinceSubmit: false,
850
+ hasBeenSubmitted: false,
848
851
  isReady: false,
849
852
  isLoading: _internalLoading,
850
853
  isValidating: false,
@@ -877,6 +880,7 @@ function createFormControl(props = {}) {
877
880
  let _names = {
878
881
  mount: new Set(),
879
882
  disabled: new Set(),
883
+ readonly: new Set(),
880
884
  unMount: new Set(),
881
885
  array: new Set(),
882
886
  watch: new Set(),
@@ -885,6 +889,8 @@ function createFormControl(props = {}) {
885
889
  let timer = 0;
886
890
  const _proxyFormState = {
887
891
  isDirty: false,
892
+ isDirtySinceSubmit: false,
893
+ hasBeenSubmitted: false,
888
894
  dirtyFields: false,
889
895
  validatingFields: false,
890
896
  touchedFields: false,
@@ -902,6 +908,8 @@ function createFormControl(props = {}) {
902
908
  };
903
909
  const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
904
910
  const id = createId(props.id);
911
+ // Track if form was ever submitted (persists through resets)
912
+ let _hasBeenSubmitted = false;
905
913
  const debounce = (callback) => (wait) => {
906
914
  clearTimeout(timer);
907
915
  timer = setTimeout(callback, wait);
@@ -1025,6 +1033,20 @@ function createFormControl(props = {}) {
1025
1033
  _proxySubscribeFormState.dirtyFields) &&
1026
1034
  isPreviousDirty !== !isCurrentFieldPristine);
1027
1035
  }
1036
+ // Set isDirtySinceSubmit to true if form was ever submitted and a field value is being changed
1037
+ // For change events (not blur/focus), always set if form was ever submitted
1038
+ // shouldDirty is true for onChange events, false for blur
1039
+ if ((_formState.isSubmitted || _hasBeenSubmitted) &&
1040
+ !_formState.isDirtySinceSubmit &&
1041
+ !isBlurEvent &&
1042
+ !isFocusEvent &&
1043
+ shouldDirty) {
1044
+ _formState.isDirtySinceSubmit = output.isDirtySinceSubmit = true;
1045
+ shouldUpdateField =
1046
+ shouldUpdateField ||
1047
+ !!(_proxyFormState.isDirtySinceSubmit ||
1048
+ _proxySubscribeFormState.isDirtySinceSubmit);
1049
+ }
1028
1050
  if (isBlurEvent) {
1029
1051
  const isPreviousFieldTouched = get(_formState.touchedFields, name);
1030
1052
  if (!isPreviousFieldTouched) {
@@ -1126,7 +1148,12 @@ function createFormControl(props = {}) {
1126
1148
  if (isPromiseFunction && _proxyFormState.validatingFields) {
1127
1149
  _updateIsValidating([name], true);
1128
1150
  }
1129
- const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1151
+ // Combine disabled and readonly field names for validation skipping
1152
+ const skipValidationFields = new Set([
1153
+ ..._names.disabled,
1154
+ ..._names.readonly,
1155
+ ]);
1156
+ const fieldError = await validateField(field, skipValidationFields, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1130
1157
  if (isPromiseFunction && _proxyFormState.validatingFields) {
1131
1158
  _updateIsValidating([name]);
1132
1159
  }
@@ -1220,9 +1247,15 @@ function createFormControl(props = {}) {
1220
1247
  }
1221
1248
  }
1222
1249
  }
1223
- (options.shouldDirty || options.shouldTouch) &&
1250
+ const isSubmittedAndDirty = (_formState.isSubmitted || _hasBeenSubmitted) &&
1251
+ !deepEqual(get(_defaultValues, name), fieldValue);
1252
+ // If the form was submitted, track value changes for isDirtySinceSubmit
1253
+ // only when the value actually differs from the default value,
1254
+ // even if shouldDirty is not explicitly set
1255
+ const shouldTrackChange = options.shouldDirty || options.shouldTouch || isSubmittedAndDirty;
1256
+ shouldTrackChange &&
1224
1257
  updateTouchAndDirty(name, fieldValue, options.shouldTouch, false, // isFocusEvent - not applicable for setValue
1225
- options.shouldDirty, true);
1258
+ options.shouldDirty || isSubmittedAndDirty, true);
1226
1259
  options.shouldValidate && trigger(name);
1227
1260
  };
1228
1261
  const setValues = (name, value, options) => {
@@ -1254,12 +1287,25 @@ function createFormControl(props = {}) {
1254
1287
  if ((_proxyFormState.isDirty ||
1255
1288
  _proxyFormState.dirtyFields ||
1256
1289
  _proxySubscribeFormState.isDirty ||
1257
- _proxySubscribeFormState.dirtyFields) &&
1290
+ _proxySubscribeFormState.dirtyFields ||
1291
+ _proxyFormState.isDirtySinceSubmit ||
1292
+ _proxySubscribeFormState.isDirtySinceSubmit) &&
1258
1293
  options.shouldDirty) {
1259
1294
  _subjects.state.next({
1260
1295
  name,
1261
1296
  dirtyFields: getDirtyFields(_defaultValues, _formValues),
1262
1297
  isDirty: _getDirty(name, cloneValue),
1298
+ ...((_formState.isSubmitted || _hasBeenSubmitted) &&
1299
+ !_formState.isDirtySinceSubmit
1300
+ ? { isDirtySinceSubmit: true }
1301
+ : {}),
1302
+ });
1303
+ }
1304
+ else if ((_formState.isSubmitted || _hasBeenSubmitted) &&
1305
+ !_formState.isDirtySinceSubmit) {
1306
+ _subjects.state.next({
1307
+ name,
1308
+ isDirtySinceSubmit: true,
1263
1309
  });
1264
1310
  }
1265
1311
  }
@@ -1313,6 +1359,36 @@ function createFormControl(props = {}) {
1313
1359
  }
1314
1360
  return;
1315
1361
  }
1362
+ // Check if field is readonly and should skip validation (only when flag is enabled)
1363
+ if (_options.shouldSkipReadOnlyValidation && target && target.readOnly) {
1364
+ // Add to readonly fields set for validation skipping
1365
+ _names.readonly.add(name);
1366
+ // For readonly fields, we still want to update the form values
1367
+ // but skip validation (similar to disabled fields behavior)
1368
+ const fieldValue = target.type
1369
+ ? getFieldValue(field._f)
1370
+ : getEventValue(event);
1371
+ const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1372
+ const isFocusEvent = event.type === EVENTS.FOCUS || event.type === EVENTS.FOCUS_IN;
1373
+ const watched = isWatched(name, _names, isBlurEvent || isFocusEvent);
1374
+ // Update form values but skip validation and error handling
1375
+ set(_formValues, name, fieldValue);
1376
+ // Update touch and dirty state
1377
+ const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, isFocusEvent, !isBlurEvent);
1378
+ const shouldRender = !isEmptyObject(fieldState) || watched;
1379
+ !isBlurEvent &&
1380
+ _subjects.state.next({
1381
+ name,
1382
+ type: event.type,
1383
+ values: cloneObject(_formValues),
1384
+ });
1385
+ return (shouldRender &&
1386
+ _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
1387
+ }
1388
+ else if (_options.shouldSkipReadOnlyValidation) {
1389
+ // Remove from readonly fields set if not readonly anymore (only when flag is enabled)
1390
+ _names.readonly.delete(name);
1391
+ }
1316
1392
  let error;
1317
1393
  let isValid;
1318
1394
  const fieldValue = target.type
@@ -1336,7 +1412,7 @@ function createFormControl(props = {}) {
1336
1412
  else if (field._f.onChange) {
1337
1413
  field._f.onChange(event);
1338
1414
  }
1339
- const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, isFocusEvent);
1415
+ const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent, isFocusEvent, !isBlurEvent);
1340
1416
  const shouldRender = !isEmptyObject(fieldState) || watched;
1341
1417
  !isBlurEvent &&
1342
1418
  _subjects.state.next({
@@ -1372,7 +1448,12 @@ function createFormControl(props = {}) {
1372
1448
  }
1373
1449
  else {
1374
1450
  _updateIsValidating([name], true);
1375
- error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name];
1451
+ // Combine disabled and readonly field names for validation skipping
1452
+ const skipValidationFields = new Set([
1453
+ ..._names.disabled,
1454
+ ..._names.readonly,
1455
+ ]);
1456
+ error = (await validateField(field, skipValidationFields, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation, false))[name];
1376
1457
  _updateIsValidating([name]);
1377
1458
  _updateIsFieldValueUpdated(fieldValue);
1378
1459
  if (isFieldValueUpdated) {
@@ -1623,6 +1704,13 @@ function createFormControl(props = {}) {
1623
1704
  },
1624
1705
  });
1625
1706
  updateValidAndValue(name, false, undefined, fieldRef);
1707
+ // Check if field is readonly and should skip validation (only when flag is enabled)
1708
+ if (_options.shouldSkipReadOnlyValidation &&
1709
+ fieldRef &&
1710
+ 'readOnly' in fieldRef &&
1711
+ fieldRef.readOnly) {
1712
+ _names.readonly.add(name);
1713
+ }
1626
1714
  }
1627
1715
  else {
1628
1716
  field = get(_fields, name, {});
@@ -1720,11 +1808,14 @@ function createFormControl(props = {}) {
1720
1808
  _focusError();
1721
1809
  setTimeout(_focusError);
1722
1810
  }
1811
+ _hasBeenSubmitted = true; // Mark that form was submitted at least once
1723
1812
  _subjects.state.next({
1724
1813
  isSubmitted: true,
1725
1814
  isSubmitting: false,
1726
1815
  isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
1727
1816
  submitCount: _formState.submitCount + 1,
1817
+ isDirtySinceSubmit: false,
1818
+ hasBeenSubmitted: _hasBeenSubmitted,
1728
1819
  errors: _formState.errors,
1729
1820
  });
1730
1821
  if (onValidError) {
@@ -1787,7 +1878,7 @@ function createFormControl(props = {}) {
1787
1878
  if (isHTMLElement(fieldReference)) {
1788
1879
  const form = fieldReference.closest('form');
1789
1880
  if (form) {
1790
- form.reset();
1881
+ HTMLFormElement.prototype.reset.call(form);
1791
1882
  break;
1792
1883
  }
1793
1884
  }
@@ -1820,6 +1911,7 @@ function createFormControl(props = {}) {
1820
1911
  unMount: new Set(),
1821
1912
  array: new Set(),
1822
1913
  disabled: new Set(),
1914
+ readonly: new Set(),
1823
1915
  watch: new Set(),
1824
1916
  watchAll: false,
1825
1917
  focus: '',
@@ -1839,6 +1931,8 @@ function createFormControl(props = {}) {
1839
1931
  ? _formState.isDirty
1840
1932
  : !!(keepStateOptions.keepDefaultValues &&
1841
1933
  !deepEqual(formValues, _defaultValues)),
1934
+ isDirtySinceSubmit: false,
1935
+ hasBeenSubmitted: _hasBeenSubmitted, // Persist the hasBeenSubmitted flag
1842
1936
  isSubmitted: keepStateOptions.keepIsSubmitted
1843
1937
  ? _formState.isSubmitted
1844
1938
  : false,
@@ -1917,6 +2011,28 @@ function createFormControl(props = {}) {
1917
2011
  });
1918
2012
  }
1919
2013
  };
2014
+ const _updateReadonlyFieldTracking = () => {
2015
+ // Re-evaluate all registered fields and update readonly tracking
2016
+ // based on current shouldSkipReadOnlyValidation flag and field readonly state
2017
+ Object.keys(_fields).forEach((fieldName) => {
2018
+ const field = get(_fields, fieldName);
2019
+ if (field && field._f) {
2020
+ // Get the actual DOM element reference
2021
+ const fieldRef = field._f.refs ? field._f.refs[0] : field._f.ref;
2022
+ if (fieldRef && 'readOnly' in fieldRef) {
2023
+ const isFieldReadonly = Boolean(fieldRef.readOnly);
2024
+ const shouldTrackAsReadonly = _options.shouldSkipReadOnlyValidation && isFieldReadonly;
2025
+ // Update readonly tracking set
2026
+ if (shouldTrackAsReadonly) {
2027
+ _names.readonly.add(fieldName);
2028
+ }
2029
+ else {
2030
+ _names.readonly.delete(fieldName);
2031
+ }
2032
+ }
2033
+ }
2034
+ });
2035
+ };
1920
2036
  const setMetadata = (metadata) => {
1921
2037
  let _metadata;
1922
2038
  if (!metadata) {
@@ -1961,6 +2077,7 @@ function createFormControl(props = {}) {
1961
2077
  _removeUnmounted,
1962
2078
  _disableForm,
1963
2079
  _updateIsLoading,
2080
+ _updateReadonlyFieldTracking,
1964
2081
  _subjects,
1965
2082
  _proxyFormState,
1966
2083
  get _fields() {