@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.
- package/README.md +3 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.mjs +135 -9
- package/dist/index.esm.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/dist/logic/createFormControl.d.ts.map +1 -1
- package/dist/logic/validateField.d.ts +1 -1
- package/dist/logic/validateField.d.ts.map +1 -1
- package/dist/react-server.esm.mjs +126 -9
- package/dist/react-server.esm.mjs.map +1 -1
- package/dist/types/form.d.ts +7 -0
- package/dist/types/form.d.ts.map +1 -1
- package/dist/useForm.d.ts.map +1 -1
- package/dist/useFormState.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -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;
|
|
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,
|
|
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,
|
|
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,
|
|
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 ||
|
|
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
|
-
|
|
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
|
-
(
|
|
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
|
-
|
|
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
|
-
|
|
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() {
|