@bombillazo/rhf-plus 7.71.2-plus.4 → 7.72.1-plus.1

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.
@@ -19,9 +19,9 @@ var getEventValue = (event) => isObject(event) && event.target
19
19
  : event.target.value
20
20
  : event;
21
21
 
22
- var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
23
-
24
- var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
22
+ var isNameInFieldArray = (names, name) => name
23
+ .split('.')
24
+ .some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
25
25
 
26
26
  var isPlainObject = (tempObject) => {
27
27
  const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
@@ -123,6 +123,9 @@ const EVENTS = {
123
123
  FOCUS: 'focus',
124
124
  FOCUS_IN: 'focusin',
125
125
  CHANGE: 'change',
126
+ SUBMIT: 'submit',
127
+ TRIGGER: 'trigger',
128
+ VALID: 'valid',
126
129
  };
127
130
  const VALIDATION_MODE = {
128
131
  onBlur: 'onBlur',
@@ -140,6 +143,8 @@ const INPUT_VALIDATION_RULES = {
140
143
  required: 'required',
141
144
  validate: 'validate',
142
145
  };
146
+ const FORM_ERROR_TYPE = 'form';
147
+ const ROOT_ERROR_TYPE = 'root';
143
148
 
144
149
  /**
145
150
  * Separate context for `control` to prevent unnecessary rerenders.
@@ -280,8 +285,8 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
280
285
  if (key !== 'ref') {
281
286
  const val2 = object2[key];
282
287
  if ((isDateObject(val1) && isDateObject(val2)) ||
283
- (isObject(val1) && isObject(val2)) ||
284
- (Array.isArray(val1) && Array.isArray(val2))
288
+ ((isObject(val1) || Array.isArray(val1)) &&
289
+ (isObject(val2) || Array.isArray(val2)))
285
290
  ? !deepEqual(val1, val2, _internal_visited)
286
291
  : !Object.is(val1, val2)) {
287
292
  return false;
@@ -735,46 +740,47 @@ const useFormContext = () => React.useContext(HookFormContext);
735
740
  */
736
741
  const FormProvider = (props) => {
737
742
  const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, id, submit, } = props;
738
- return (React.createElement(HookFormContext.Provider, { value: React.useMemo(() => ({
739
- watch,
740
- getValues,
741
- getFieldState,
742
- setError,
743
- clearErrors,
744
- setValue,
745
- trigger,
746
- formState,
747
- resetField,
748
- reset,
749
- handleSubmit,
750
- unregister,
751
- control,
752
- register,
753
- setFocus,
754
- subscribe,
755
- id,
756
- submit,
757
- }), [
758
- clearErrors,
759
- control,
760
- formState,
761
- getFieldState,
762
- getValues,
763
- handleSubmit,
764
- id,
765
- register,
766
- reset,
767
- resetField,
768
- setError,
769
- setFocus,
770
- setValue,
771
- submit,
772
- subscribe,
773
- trigger,
774
- unregister,
775
- watch,
776
- ]) },
777
- React.createElement(HookFormControlContext.Provider, { value: control }, children)));
743
+ const memoizedValue = React.useMemo(() => ({
744
+ watch,
745
+ getValues,
746
+ getFieldState,
747
+ setError,
748
+ clearErrors,
749
+ setValue,
750
+ trigger,
751
+ formState,
752
+ resetField,
753
+ reset,
754
+ handleSubmit,
755
+ unregister,
756
+ control,
757
+ register,
758
+ setFocus,
759
+ subscribe,
760
+ id,
761
+ submit,
762
+ }), [
763
+ clearErrors,
764
+ control,
765
+ formState,
766
+ getFieldState,
767
+ getValues,
768
+ handleSubmit,
769
+ id,
770
+ register,
771
+ reset,
772
+ resetField,
773
+ setError,
774
+ setFocus,
775
+ setValue,
776
+ submit,
777
+ subscribe,
778
+ trigger,
779
+ unregister,
780
+ watch,
781
+ ]);
782
+ return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
783
+ React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
778
784
  };
779
785
 
780
786
  const POST_REQUEST = 'post';
@@ -1155,6 +1161,8 @@ function getFieldValue(_f) {
1155
1161
  return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
1156
1162
  }
1157
1163
 
1164
+ var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
1165
+
1158
1166
  var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
1159
1167
  const fields = {};
1160
1168
  for (const name of fieldsNames) {
@@ -1337,7 +1345,7 @@ var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(re
1337
1345
 
1338
1346
  var updateFieldArrayRootError = (errors, error, name) => {
1339
1347
  const fieldArrayErrors = convertToArrayPayload(get(errors, name));
1340
- set(fieldArrayErrors, 'root', error[name]);
1348
+ set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
1341
1349
  set(errors, name, fieldArrayErrors);
1342
1350
  return errors;
1343
1351
  };
@@ -1594,6 +1602,7 @@ function createFormControl(props = {}) {
1594
1602
  unMount: new Set(),
1595
1603
  array: new Set(),
1596
1604
  watch: new Set(),
1605
+ registerName: new Set(),
1597
1606
  };
1598
1607
  let delayErrorCallback;
1599
1608
  let timer = 0;
@@ -1641,7 +1650,11 @@ function createFormControl(props = {}) {
1641
1650
  _updateIsValidating();
1642
1651
  }
1643
1652
  else {
1644
- isValid = await executeBuiltInValidation(_fields, true);
1653
+ isValid = await executeBuiltInValidation({
1654
+ fields: _fields,
1655
+ onlyCheckValid: true,
1656
+ eventType: EVENTS.VALID,
1657
+ });
1645
1658
  }
1646
1659
  if (isValid !== _formState.isValid) {
1647
1660
  _subjects.state.next({
@@ -1669,6 +1682,11 @@ function createFormControl(props = {}) {
1669
1682
  });
1670
1683
  }
1671
1684
  };
1685
+ const _updateDirtyFields = (name) => {
1686
+ const fullDirtyFields = getDirtyFields(_defaultValues, _formValues);
1687
+ const rootName = getNodeParentName(name);
1688
+ set(_formState.dirtyFields, rootName, get(fullDirtyFields, rootName));
1689
+ };
1672
1690
  const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1673
1691
  if (args && method && !_options.disabled) {
1674
1692
  _state.action = true;
@@ -1690,7 +1708,7 @@ function createFormControl(props = {}) {
1690
1708
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
1691
1709
  }
1692
1710
  if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
1693
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1711
+ _updateDirtyFields(name);
1694
1712
  }
1695
1713
  _subjects.state.next({
1696
1714
  name,
@@ -1837,8 +1855,7 @@ function createFormControl(props = {}) {
1837
1855
  };
1838
1856
  const _runSchema = async (name) => {
1839
1857
  _updateIsValidating(name, true);
1840
- const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1841
- return result;
1858
+ return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1842
1859
  };
1843
1860
  const executeSchemaAndUpdateState = async (names) => {
1844
1861
  const { errors } = await _runSchema(names);
@@ -1856,9 +1873,55 @@ function createFormControl(props = {}) {
1856
1873
  }
1857
1874
  return errors;
1858
1875
  };
1859
- const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
1876
+ const validateForm = async ({ name, eventType, }) => {
1877
+ if (props.validate) {
1878
+ const result = await props.validate({
1879
+ formValues: _formValues,
1880
+ formState: _formState,
1881
+ name,
1882
+ eventType,
1883
+ });
1884
+ if (isObject(result)) {
1885
+ for (const key in result) {
1886
+ const error = result[key];
1887
+ if (error) {
1888
+ setError(`${FORM_ERROR_TYPE}.${key}`, {
1889
+ message: isString(result.message) ? result.message : '',
1890
+ type: INPUT_VALIDATION_RULES.validate,
1891
+ });
1892
+ }
1893
+ }
1894
+ }
1895
+ else if (isString(result) || !result) {
1896
+ setError(FORM_ERROR_TYPE, {
1897
+ message: result || '',
1898
+ type: INPUT_VALIDATION_RULES.validate,
1899
+ });
1900
+ }
1901
+ else {
1902
+ clearErrors(FORM_ERROR_TYPE);
1903
+ }
1904
+ return result;
1905
+ }
1906
+ return true;
1907
+ };
1908
+ const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
1860
1909
  valid: true,
1861
- }) => {
1910
+ runRootValidation: false,
1911
+ }, }) => {
1912
+ if (props.validate) {
1913
+ context.runRootValidation = true;
1914
+ const result = await validateForm({
1915
+ name,
1916
+ eventType,
1917
+ });
1918
+ if (!result) {
1919
+ context.valid = false;
1920
+ if (onlyCheckValid) {
1921
+ return context.valid;
1922
+ }
1923
+ }
1924
+ }
1862
1925
  for (const name in fields) {
1863
1926
  const field = fields[name];
1864
1927
  if (field) {
@@ -1874,25 +1937,34 @@ function createFormControl(props = {}) {
1874
1937
  ..._names.disabled,
1875
1938
  ..._names.readonly,
1876
1939
  ]);
1877
- const fieldError = await validateField(field, skipValidationFields, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1940
+ const fieldError = await validateField(field, skipValidationFields, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1878
1941
  if (isPromiseFunction && _proxyFormState.validatingFields) {
1879
1942
  _updateIsValidating([_f.name]);
1880
1943
  }
1881
1944
  if (fieldError[_f.name]) {
1882
1945
  context.valid = false;
1883
- if (shouldOnlyCheckValid || props.shouldUseNativeValidation) {
1946
+ if (onlyCheckValid) {
1884
1947
  break;
1885
1948
  }
1886
1949
  }
1887
- !shouldOnlyCheckValid &&
1950
+ !onlyCheckValid &&
1888
1951
  (get(fieldError, _f.name)
1889
1952
  ? isFieldArrayRoot
1890
1953
  ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
1891
1954
  : set(_formState.errors, _f.name, fieldError[_f.name])
1892
1955
  : unset(_formState.errors, _f.name));
1956
+ if (props.shouldUseNativeValidation && fieldError[_f.name]) {
1957
+ break;
1958
+ }
1893
1959
  }
1894
1960
  !isEmptyObject(fieldValue) &&
1895
- (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
1961
+ (await executeBuiltInValidation({
1962
+ context,
1963
+ onlyCheckValid,
1964
+ fields: fieldValue,
1965
+ name: name,
1966
+ eventType,
1967
+ }));
1896
1968
  }
1897
1969
  }
1898
1970
  return context.valid;
@@ -2012,9 +2084,10 @@ function createFormControl(props = {}) {
2012
2084
  _proxyFormState.isDirtySinceSubmit ||
2013
2085
  _proxySubscribeFormState.isDirtySinceSubmit) &&
2014
2086
  options.shouldDirty) {
2087
+ _updateDirtyFields(name);
2015
2088
  _subjects.state.next({
2016
2089
  name,
2017
- dirtyFields: getDirtyFields(_defaultValues, _formValues),
2090
+ dirtyFields: _formState.dirtyFields,
2018
2091
  isDirty: _getDirty(name, cloneValue),
2019
2092
  ...((_formState.isSubmitted || _hasBeenSubmitted) &&
2020
2093
  !_formState.isDirtySinceSubmit
@@ -2136,6 +2209,7 @@ function createFormControl(props = {}) {
2136
2209
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
2137
2210
  const isFocusEvent = event.type === EVENTS.FOCUS || event.type === EVENTS.FOCUS_IN;
2138
2211
  const shouldSkipValidation = (!hasValidation(field._f) &&
2212
+ !props.validate &&
2139
2213
  !_options.resolver &&
2140
2214
  !get(_formState.errors, name) &&
2141
2215
  !field._f.deps) ||
@@ -2173,6 +2247,12 @@ function createFormControl(props = {}) {
2173
2247
  return (shouldRender &&
2174
2248
  _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
2175
2249
  }
2250
+ if (!_options.resolver && props.validate) {
2251
+ await validateForm({
2252
+ name: name,
2253
+ eventType: event.type,
2254
+ });
2255
+ }
2176
2256
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
2177
2257
  if (_options.resolver) {
2178
2258
  const { errors } = await _runSchema([name]);
@@ -2202,7 +2282,12 @@ function createFormControl(props = {}) {
2202
2282
  }
2203
2283
  else if (_proxyFormState.isValid ||
2204
2284
  _proxySubscribeFormState.isValid) {
2205
- isValid = await executeBuiltInValidation(_fields, true);
2285
+ isValid = await executeBuiltInValidation({
2286
+ fields: _fields,
2287
+ onlyCheckValid: true,
2288
+ name: name,
2289
+ eventType: event.type,
2290
+ });
2206
2291
  }
2207
2292
  }
2208
2293
  }
@@ -2235,12 +2320,19 @@ function createFormControl(props = {}) {
2235
2320
  else if (name) {
2236
2321
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
2237
2322
  const field = get(_fields, fieldName);
2238
- return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
2323
+ return await executeBuiltInValidation({
2324
+ fields: field && field._f ? { [fieldName]: field } : field,
2325
+ eventType: EVENTS.TRIGGER,
2326
+ });
2239
2327
  }))).every(Boolean);
2240
2328
  !(!validationResult && !_formState.isValid) && _setValid();
2241
2329
  }
2242
2330
  else {
2243
- validationResult = isValid = await executeBuiltInValidation(_fields);
2331
+ validationResult = isValid = await executeBuiltInValidation({
2332
+ fields: _fields,
2333
+ name,
2334
+ eventType: EVENTS.TRIGGER,
2335
+ });
2244
2336
  }
2245
2337
  _subjects.state.next({
2246
2338
  ...(!isString(name) ||
@@ -2389,6 +2481,7 @@ function createFormControl(props = {}) {
2389
2481
  const disabledIsDefined = isBoolean(options.disabled) ||
2390
2482
  isBoolean(_options.disabled) ||
2391
2483
  Array.isArray(_options.disabled);
2484
+ const shouldRevalidateRemount = !_names.registerName.has(name) && field && !field._f.mount;
2392
2485
  set(_fields, name, {
2393
2486
  ...(field || {}),
2394
2487
  _f: {
@@ -2399,7 +2492,7 @@ function createFormControl(props = {}) {
2399
2492
  },
2400
2493
  });
2401
2494
  _names.mount.add(name);
2402
- if (field) {
2495
+ if (field && !shouldRevalidateRemount) {
2403
2496
  _setDisabledField({
2404
2497
  disabled: isBoolean(options.disabled)
2405
2498
  ? options.disabled
@@ -2438,7 +2531,9 @@ function createFormControl(props = {}) {
2438
2531
  onFocus: onChange,
2439
2532
  ref: (ref) => {
2440
2533
  if (ref) {
2534
+ _names.registerName.add(name);
2441
2535
  register(name, options);
2536
+ _names.registerName.delete(name);
2442
2537
  field = get(_fields, name);
2443
2538
  const fieldRef = isUndefined(ref.value)
2444
2539
  ? ref.querySelectorAll
@@ -2547,14 +2642,17 @@ function createFormControl(props = {}) {
2547
2642
  fieldValues = cloneObject(values);
2548
2643
  }
2549
2644
  else {
2550
- await executeBuiltInValidation(_fields);
2645
+ await executeBuiltInValidation({
2646
+ fields: _fields,
2647
+ eventType: EVENTS.SUBMIT,
2648
+ });
2551
2649
  }
2552
2650
  if (_names.disabled.size) {
2553
2651
  for (const name of _names.disabled) {
2554
2652
  unset(fieldValues, name);
2555
2653
  }
2556
2654
  }
2557
- unset(_formState.errors, 'root');
2655
+ unset(_formState.errors, ROOT_ERROR_TYPE);
2558
2656
  if (isEmptyObject(_formState.errors)) {
2559
2657
  _subjects.state.next({
2560
2658
  errors: {},
@@ -2681,6 +2779,7 @@ function createFormControl(props = {}) {
2681
2779
  mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
2682
2780
  unMount: new Set(),
2683
2781
  array: new Set(),
2782
+ registerName: new Set(),
2684
2783
  disabled: new Set(),
2685
2784
  readonly: new Set(),
2686
2785
  watch: new Set(),