@bombillazo/rhf-plus 7.65.0-plus.0 → 7.68.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"}
@@ -179,7 +179,7 @@ HookFormContext.displayName = 'HookFormContext';
179
179
  */
180
180
  const useFormContext = () => React.useContext(HookFormContext);
181
181
  /**
182
- * A provider component that propagates the `useForm` methods to all children components via [React Context](https://reactjs.org/docs/context.html) API. To be used with {@link useFormContext}.
182
+ * A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
183
183
  *
184
184
  * @remarks
185
185
  * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
@@ -318,7 +318,7 @@ var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
318
318
 
319
319
  function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
320
320
  if (isPrimitive(object1) || isPrimitive(object2)) {
321
- return object1 === object2;
321
+ return Object.is(object1, object2);
322
322
  }
323
323
  if (isDateObject(object1) && isDateObject(object2)) {
324
324
  return object1.getTime() === object2.getTime();
@@ -344,7 +344,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
344
344
  (isObject(val1) && isObject(val2)) ||
345
345
  (Array.isArray(val1) && Array.isArray(val2))
346
346
  ? !deepEqual(val1, val2, _internal_visited)
347
- : val1 !== val2) {
347
+ : !Object.is(val1, val2)) {
348
348
  return false;
349
349
  }
350
350
  }
@@ -374,33 +374,68 @@ function useWatch(props) {
374
374
  const _defaultValue = React.useRef(defaultValue);
375
375
  const _compute = React.useRef(compute);
376
376
  const _computeFormValues = React.useRef(undefined);
377
+ const _prevControl = React.useRef(control);
378
+ const _prevName = React.useRef(name);
377
379
  _compute.current = compute;
378
- const defaultValueMemo = React.useMemo(() => control._getWatch(name, _defaultValue.current), [control, name]);
379
- const [value, updateValue] = React.useState(_compute.current ? _compute.current(defaultValueMemo) : defaultValueMemo);
380
- useIsomorphicLayoutEffect(() => control._subscribe({
381
- name,
382
- formState: {
383
- values: true,
384
- },
385
- exact,
386
- callback: (formState) => {
387
- if (!disabled) {
388
- const formValues = generateWatchOutput(name, control._names, formState.values || control._formValues, false, _defaultValue.current);
389
- if (_compute.current) {
390
- const computedFormValues = _compute.current(formValues);
391
- if (!deepEqual(computedFormValues, _computeFormValues.current)) {
392
- updateValue(computedFormValues);
393
- _computeFormValues.current = computedFormValues;
394
- }
395
- }
396
- else {
397
- updateValue(formValues);
380
+ const [value, updateValue] = React.useState(() => {
381
+ const defaultValue = control._getWatch(name, _defaultValue.current);
382
+ return _compute.current ? _compute.current(defaultValue) : defaultValue;
383
+ });
384
+ const getCurrentOutput = React.useCallback((values) => {
385
+ const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
386
+ return _compute.current ? _compute.current(formValues) : formValues;
387
+ }, [control._formValues, control._names, name]);
388
+ const refreshValue = React.useCallback((values) => {
389
+ if (!disabled) {
390
+ const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current);
391
+ if (_compute.current) {
392
+ const computedFormValues = _compute.current(formValues);
393
+ if (!deepEqual(computedFormValues, _computeFormValues.current)) {
394
+ updateValue(computedFormValues);
395
+ _computeFormValues.current = computedFormValues;
398
396
  }
399
397
  }
400
- },
401
- }), [control, disabled, name, exact]);
398
+ else {
399
+ updateValue(formValues);
400
+ }
401
+ }
402
+ }, [control._formValues, control._names, disabled, name]);
403
+ useIsomorphicLayoutEffect(() => {
404
+ if (_prevControl.current !== control ||
405
+ !deepEqual(_prevName.current, name)) {
406
+ _prevControl.current = control;
407
+ _prevName.current = name;
408
+ refreshValue();
409
+ }
410
+ return control._subscribe({
411
+ name,
412
+ formState: {
413
+ values: true,
414
+ },
415
+ exact,
416
+ callback: (formState) => {
417
+ refreshValue(formState.values);
418
+ },
419
+ });
420
+ }, [control, exact, name, refreshValue]);
402
421
  React.useEffect(() => control._removeUnmounted());
403
- return value;
422
+ // If name or control changed for this render, synchronously reflect the
423
+ // latest value so callers (like useController) see the correct value
424
+ // immediately on the same render.
425
+ // Optimize: Check control reference first before expensive deepEqual
426
+ const controlChanged = _prevControl.current !== control;
427
+ const prevName = _prevName.current;
428
+ // Cache the computed output to avoid duplicate calls within the same render
429
+ // We include shouldReturnImmediate in deps to ensure proper recomputation
430
+ const computedOutput = React.useMemo(() => {
431
+ if (disabled) {
432
+ return null;
433
+ }
434
+ const nameChanged = !controlChanged && !deepEqual(prevName, name);
435
+ const shouldReturnImmediate = controlChanged || nameChanged;
436
+ return shouldReturnImmediate ? getCurrentOutput() : null;
437
+ }, [disabled, controlChanged, name, prevName, getCurrentOutput]);
438
+ return computedOutput !== null ? computedOutput : value;
404
439
  }
405
440
 
406
441
  /**
@@ -429,7 +464,7 @@ function useWatch(props) {
429
464
  */
430
465
  function useController(props) {
431
466
  const methods = useFormContext();
432
- const { name, disabled, control = methods === null || methods === void 0 ? void 0 : methods.control, shouldUnregister, defaultValue, } = props;
467
+ const { name, disabled, control = methods === null || methods === void 0 ? void 0 : methods.control, shouldUnregister, defaultValue, exact = true, } = props;
433
468
  if (!control) {
434
469
  throw new Error('useController: missing `control`. Pass `control` as a prop or provide it via FormProvider.');
435
470
  }
@@ -439,12 +474,12 @@ function useController(props) {
439
474
  control,
440
475
  name,
441
476
  defaultValue: defaultValueMemo,
442
- exact: true,
477
+ exact,
443
478
  });
444
479
  const formState = useFormState({
445
480
  control,
446
481
  name,
447
- exact: true,
482
+ exact,
448
483
  });
449
484
  const _props = React.useRef(props);
450
485
  const _previousRules = React.useRef(props.rules);
@@ -797,6 +832,8 @@ function Form(props) {
797
832
  }))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
798
833
  }
799
834
 
835
+ const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
836
+
800
837
  var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
801
838
  ? {
802
839
  ...errors[name],
@@ -972,11 +1009,12 @@ function isTraversable(value) {
972
1009
  }
973
1010
  function markFieldsDirty(data, fields = {}) {
974
1011
  for (const key in data) {
975
- if (isTraversable(data[key])) {
976
- fields[key] = Array.isArray(data[key]) ? [] : {};
977
- markFieldsDirty(data[key], fields[key]);
1012
+ const value = data[key];
1013
+ if (isTraversable(value)) {
1014
+ fields[key] = Array.isArray(value) ? [] : {};
1015
+ markFieldsDirty(value, fields[key]);
978
1016
  }
979
- else if (!isUndefined(data[key])) {
1017
+ else if (!isUndefined(value)) {
980
1018
  fields[key] = true;
981
1019
  }
982
1020
  }
@@ -987,16 +1025,18 @@ function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
987
1025
  dirtyFieldsFromValues = markFieldsDirty(formValues);
988
1026
  }
989
1027
  for (const key in data) {
990
- if (isTraversable(data[key])) {
1028
+ const value = data[key];
1029
+ if (isTraversable(value)) {
991
1030
  if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
992
- dirtyFieldsFromValues[key] = markFieldsDirty(data[key], Array.isArray(data[key]) ? [] : {});
1031
+ dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {});
993
1032
  }
994
1033
  else {
995
- getDirtyFields(data[key], isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
1034
+ getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
996
1035
  }
997
1036
  }
998
1037
  else {
999
- dirtyFieldsFromValues[key] = !deepEqual(data[key], formValues[key]);
1038
+ const formValue = formValues[key];
1039
+ dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
1000
1040
  }
1001
1041
  }
1002
1042
  return dirtyFieldsFromValues;
@@ -1630,7 +1670,7 @@ function createFormControl(props = {}) {
1630
1670
  shouldSkipSetValueAs
1631
1671
  ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
1632
1672
  : setFieldValue(name, defaultValue);
1633
- _state.mount && _setValid();
1673
+ _state.mount && !_state.action && _setValid();
1634
1674
  }
1635
1675
  };
1636
1676
  const updateTouchAndDirty = (name, fieldValue, isBlurEvent, isFocusEvent, shouldDirty, shouldRender) => {
@@ -2558,8 +2598,16 @@ function createFormControl(props = {}) {
2558
2598
  _state.mount =
2559
2599
  !_proxyFormState.isValid ||
2560
2600
  !!keepStateOptions.keepIsValid ||
2561
- !!keepStateOptions.keepDirtyValues;
2601
+ !!keepStateOptions.keepDirtyValues ||
2602
+ (!_options.shouldUnregister && !isEmptyObject(values));
2562
2603
  _state.watch = !!_options.shouldUnregister;
2604
+ _state.action = false;
2605
+ // Clear errors synchronously to prevent validation errors on subsequent submissions
2606
+ // This fixes the issue where form.reset() causes validation errors on subsequent
2607
+ // submissions in Next.js 16 with Server Actions
2608
+ if (!keepStateOptions.keepErrors) {
2609
+ _formState.errors = {};
2610
+ }
2563
2611
  _subjects.state.next({
2564
2612
  submitCount: keepStateOptions.keepSubmitCount
2565
2613
  ? _formState.submitCount
@@ -3217,11 +3265,15 @@ function useForm(props = {}) {
3217
3265
  }
3218
3266
  }, [control, formState.isDirty]);
3219
3267
  React.useEffect(() => {
3268
+ var _a;
3220
3269
  if (props.values && !deepEqual(props.values, _values.current)) {
3221
3270
  control._reset(props.values, {
3222
3271
  keepFieldsRef: true,
3223
3272
  ...control._options.resetOptions,
3224
3273
  });
3274
+ if (!((_a = control._options.resetOptions) === null || _a === void 0 ? void 0 : _a.keepIsValid)) {
3275
+ control._setValid();
3276
+ }
3225
3277
  _values.current = props.values;
3226
3278
  updateFormState((state) => ({ ...state }));
3227
3279
  }
@@ -3280,5 +3332,5 @@ function useForm(props = {}) {
3280
3332
  */
3281
3333
  const Watch = ({ control, names, render, }) => render(useWatch({ control, name: names }));
3282
3334
 
3283
- export { Controller, Form, FormProvider, Watch, appendErrors, createFormControl, get, set, submitForm as submit, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
3335
+ export { Controller, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, submitForm as submit, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
3284
3336
  //# sourceMappingURL=index.esm.mjs.map