@bombillazo/rhf-plus 7.67.0-plus.0 → 7.69.0-plus.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.
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './controller';
2
2
  export * from './form';
3
+ export * from './formStateSubscribe';
3
4
  export * from './logic';
4
5
  export * from './types';
5
6
  export * from './useController';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,QAAQ,CAAC;AACvB,cAAc,sBAAsB,CAAC;AACrC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,WAAW,CAAC;AAC1B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,YAAY,CAAC;AAC3B,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
@@ -33,29 +33,23 @@ var isWeb = typeof window !== 'undefined' &&
33
33
  typeof document !== 'undefined';
34
34
 
35
35
  function cloneObject(data) {
36
- let copy;
37
- const isArray = Array.isArray(data);
38
- const isFileListInstance = typeof FileList !== 'undefined' ? data instanceof FileList : false;
39
36
  if (data instanceof Date) {
40
- copy = new Date(data);
37
+ return new Date(data);
41
38
  }
42
- else if (!(isWeb && (data instanceof Blob || isFileListInstance)) &&
43
- (isArray || isObject(data))) {
44
- copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
45
- if (!isArray && !isPlainObject(data)) {
46
- copy = data;
47
- }
48
- else {
49
- for (const key in data) {
50
- if (data.hasOwnProperty(key)) {
51
- copy[key] = cloneObject(data[key]);
52
- }
53
- }
54
- }
39
+ const isFileListInstance = typeof FileList !== 'undefined' && data instanceof FileList;
40
+ if (isWeb && (data instanceof Blob || isFileListInstance)) {
41
+ return data;
55
42
  }
56
- else {
43
+ const isArray = Array.isArray(data);
44
+ if (!isArray && !(isObject(data) && isPlainObject(data))) {
57
45
  return data;
58
46
  }
47
+ const copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
48
+ for (const key in data) {
49
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
50
+ copy[key] = cloneObject(data[key]);
51
+ }
52
+ }
59
53
  return copy;
60
54
  }
61
55
 
@@ -81,6 +75,8 @@ var get = (object, path, defaultValue) => {
81
75
 
82
76
  var isBoolean = (value) => typeof value === 'boolean';
83
77
 
78
+ var isFunction = (value) => typeof value === 'function';
79
+
84
80
  function mergeMissingKeysAsUndefined(oldObject, newObject) {
85
81
  if (!newObject) {
86
82
  return newObject;
@@ -464,7 +460,7 @@ function useWatch(props) {
464
460
  */
465
461
  function useController(props) {
466
462
  const methods = useFormContext();
467
- const { name, disabled, control = methods === null || methods === void 0 ? void 0 : methods.control, shouldUnregister, defaultValue, } = props;
463
+ const { name, disabled, control = methods === null || methods === void 0 ? void 0 : methods.control, shouldUnregister, defaultValue, exact = true, } = props;
468
464
  if (!control) {
469
465
  throw new Error('useController: missing `control`. Pass `control` as a prop or provide it via FormProvider.');
470
466
  }
@@ -474,12 +470,12 @@ function useController(props) {
474
470
  control,
475
471
  name,
476
472
  defaultValue: defaultValueMemo,
477
- exact: true,
473
+ exact,
478
474
  });
479
475
  const formState = useFormState({
480
476
  control,
481
477
  name,
482
- exact: true,
478
+ exact,
483
479
  });
484
480
  const _props = React.useRef(props);
485
481
  const _previousRules = React.useRef(props.rules);
@@ -564,12 +560,12 @@ function useController(props) {
564
560
  const ref = React.useCallback((elm) => {
565
561
  elementRef.current = elm;
566
562
  const field = get(control._fields, name);
567
- if (field && elm) {
563
+ if (field && field._f && elm) {
568
564
  field._f.ref = {
569
- focus: () => { var _a; return (_a = elm.focus) === null || _a === void 0 ? void 0 : _a.call(elm); },
570
- select: () => { var _a; return (_a = elm.select) === null || _a === void 0 ? void 0 : _a.call(elm); },
571
- setCustomValidity: (message) => elm.setCustomValidity(message),
572
- reportValidity: () => elm.reportValidity(),
565
+ focus: () => isFunction(elm.focus) && elm.focus(),
566
+ select: () => isFunction(elm.select) && elm.select(),
567
+ setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
568
+ reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
573
569
  };
574
570
  }
575
571
  }, [control._fields, name]);
@@ -832,6 +828,8 @@ function Form(props) {
832
828
  }))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
833
829
  }
834
830
 
831
+ const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
832
+
835
833
  var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
836
834
  ? {
837
835
  ...errors[name],
@@ -925,8 +923,6 @@ var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
925
923
 
926
924
  var isFileInput = (element) => element.type === 'file';
927
925
 
928
- var isFunction = (value) => typeof value === 'function';
929
-
930
926
  var isHTMLElement = (value) => {
931
927
  if (!isWeb) {
932
928
  return false;
@@ -1539,6 +1535,7 @@ function createFormControl(props = {}) {
1539
1535
  action: false,
1540
1536
  mount: false,
1541
1537
  watch: false,
1538
+ keepIsValid: false,
1542
1539
  };
1543
1540
  let _names = {
1544
1541
  mount: new Set(),
@@ -1550,7 +1547,7 @@ function createFormControl(props = {}) {
1550
1547
  };
1551
1548
  let delayErrorCallback;
1552
1549
  let timer = 0;
1553
- const _proxyFormState = {
1550
+ const defaultProxyFormState = {
1554
1551
  isDirty: false,
1555
1552
  isDirtySinceSubmit: false,
1556
1553
  hasBeenSubmitted: false,
@@ -1562,6 +1559,9 @@ function createFormControl(props = {}) {
1562
1559
  isValid: false,
1563
1560
  errors: false,
1564
1561
  };
1562
+ const _proxyFormState = {
1563
+ ...defaultProxyFormState,
1564
+ };
1565
1565
  let _proxySubscribeFormState = {
1566
1566
  ..._proxyFormState,
1567
1567
  };
@@ -1578,13 +1578,21 @@ function createFormControl(props = {}) {
1578
1578
  timer = setTimeout(callback, wait);
1579
1579
  };
1580
1580
  const _setValid = async (shouldUpdateValid) => {
1581
+ if (_state.keepIsValid) {
1582
+ return;
1583
+ }
1581
1584
  if ((Array.isArray(_options.disabled) || !_options.disabled) &&
1582
1585
  (_proxyFormState.isValid ||
1583
1586
  _proxySubscribeFormState.isValid ||
1584
1587
  shouldUpdateValid)) {
1585
- const isValid = _options.resolver
1586
- ? isEmptyObject((await _runSchema()).errors)
1587
- : await executeBuiltInValidation(_fields, true);
1588
+ let isValid;
1589
+ if (_options.resolver) {
1590
+ isValid = isEmptyObject((await _runSchema()).errors);
1591
+ _updateIsValidating();
1592
+ }
1593
+ else {
1594
+ isValid = await executeBuiltInValidation(_fields, true);
1595
+ }
1588
1596
  if (isValid !== _formState.isValid) {
1589
1597
  _subjects.state.next({
1590
1598
  isValid,
@@ -1780,11 +1788,11 @@ function createFormControl(props = {}) {
1780
1788
  const _runSchema = async (name) => {
1781
1789
  _updateIsValidating(name, true);
1782
1790
  const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1783
- _updateIsValidating(name);
1784
1791
  return result;
1785
1792
  };
1786
1793
  const executeSchemaAndUpdateState = async (names) => {
1787
1794
  const { errors } = await _runSchema(names);
1795
+ _updateIsValidating(names);
1788
1796
  if (names) {
1789
1797
  for (const name of names) {
1790
1798
  const error = get(errors, name);
@@ -2110,6 +2118,7 @@ function createFormControl(props = {}) {
2110
2118
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
2111
2119
  if (_options.resolver) {
2112
2120
  const { errors } = await _runSchema([name]);
2121
+ _updateIsValidating([name]);
2113
2122
  _updateIsFieldValueUpdated(fieldValue);
2114
2123
  if (isFieldValueUpdated) {
2115
2124
  const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
@@ -2261,7 +2270,10 @@ function createFormControl(props = {}) {
2261
2270
  };
2262
2271
  return _subscribe({
2263
2272
  ...props,
2264
- formState: _proxySubscribeFormState,
2273
+ formState: {
2274
+ ...defaultProxyFormState,
2275
+ ...props.formState,
2276
+ },
2265
2277
  });
2266
2278
  };
2267
2279
  const unregister = (name, options = {}) => {
@@ -2455,6 +2467,7 @@ function createFormControl(props = {}) {
2455
2467
  });
2456
2468
  if (_options.resolver) {
2457
2469
  const { errors, values } = await _runSchema();
2470
+ _updateIsValidating();
2458
2471
  _formState.errors = errors;
2459
2472
  fieldValues = cloneObject(values);
2460
2473
  }
@@ -2599,6 +2612,14 @@ function createFormControl(props = {}) {
2599
2612
  !!keepStateOptions.keepDirtyValues ||
2600
2613
  (!_options.shouldUnregister && !isEmptyObject(values));
2601
2614
  _state.watch = !!_options.shouldUnregister;
2615
+ _state.keepIsValid = !!keepStateOptions.keepIsValid;
2616
+ _state.action = false;
2617
+ // Clear errors synchronously to prevent validation errors on subsequent submissions
2618
+ // This fixes the issue where form.reset() causes validation errors on subsequent
2619
+ // submissions in Next.js 16 with Server Actions
2620
+ if (!keepStateOptions.keepErrors) {
2621
+ _formState.errors = {};
2622
+ }
2602
2623
  _subjects.state.next({
2603
2624
  submitCount: keepStateOptions.keepSubmitCount
2604
2625
  ? _formState.submitCount
@@ -2639,7 +2660,7 @@ function createFormControl(props = {}) {
2639
2660
  };
2640
2661
  const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
2641
2662
  ? formValues(_formValues)
2642
- : formValues, keepStateOptions);
2663
+ : formValues, { ..._options.resetOptions, ...keepStateOptions });
2643
2664
  const setFocus = (name, options = {}) => {
2644
2665
  const field = get(_fields, name);
2645
2666
  const fieldReference = field && field._f;
@@ -2648,10 +2669,14 @@ function createFormControl(props = {}) {
2648
2669
  ? fieldReference.refs[0]
2649
2670
  : fieldReference.ref;
2650
2671
  if (fieldRef.focus) {
2651
- fieldRef.focus();
2652
- options.shouldSelect &&
2653
- isFunction(fieldRef.select) &&
2654
- fieldRef.select();
2672
+ // Use setTimeout to ensure focus happens after any pending state updates
2673
+ // This fixes the issue where setFocus doesn't work immediately after setError
2674
+ setTimeout(() => {
2675
+ fieldRef.focus();
2676
+ options.shouldSelect &&
2677
+ isFunction(fieldRef.select) &&
2678
+ fieldRef.select();
2679
+ });
2655
2680
  }
2656
2681
  }
2657
2682
  };
@@ -2742,6 +2767,7 @@ function createFormControl(props = {}) {
2742
2767
  setError,
2743
2768
  _subscribe,
2744
2769
  _runSchema,
2770
+ _updateIsValidating,
2745
2771
  _focusError,
2746
2772
  _getWatch,
2747
2773
  _getDirty,
@@ -2823,7 +2849,7 @@ var generateId = () => {
2823
2849
  }
2824
2850
  const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
2825
2851
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
2826
- const r = (Math.random() * 16 + d) % 16 | 0;
2852
+ const r = ((Math.random() * 16 + d) % 16) | 0;
2827
2853
  return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
2828
2854
  });
2829
2855
  };
@@ -3045,6 +3071,7 @@ function useFieldArray(props) {
3045
3071
  !getValidationModes(control._options.reValidateMode).isOnSubmit) {
3046
3072
  if (control._options.resolver) {
3047
3073
  control._runSchema([name]).then((result) => {
3074
+ control._updateIsValidating([name]);
3048
3075
  const error = get(result.errors, name);
3049
3076
  const existingError = get(control._formState.errors, name);
3050
3077
  if (existingError
@@ -3303,7 +3330,11 @@ function useForm(props = {}) {
3303
3330
  * Watch component that subscribes to form field changes and re-renders when watched fields update.
3304
3331
  *
3305
3332
  * @param control - The form control object from useForm
3306
- * @param names - Array of field names to watch for changes
3333
+ * @param name - Can be field name, array of field names, or undefined to watch the entire form
3334
+ * @param disabled - Disable subscription
3335
+ * @param exact - Whether to watch exact field names or not
3336
+ * @param defaultValue - The default value to use if the field is not yet set
3337
+ * @param compute - Function to compute derived values from watched fields
3307
3338
  * @param render - The function that receives watched values and returns ReactNode
3308
3339
  * @returns The result of calling render function with watched values
3309
3340
  *
@@ -3321,7 +3352,7 @@ function useForm(props = {}) {
3321
3352
  * />
3322
3353
  * ```
3323
3354
  */
3324
- const Watch = ({ control, names, render, }) => render(useWatch({ control, name: names }));
3355
+ const Watch = ({ render, names, ...props }) => render(useWatch({ ...props, name: names }));
3325
3356
 
3326
- export { Controller, Form, FormProvider, Watch, appendErrors, createFormControl, get, set, submitForm as submit, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
3357
+ export { Controller, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, submitForm as submit, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
3327
3358
  //# sourceMappingURL=index.esm.mjs.map