react-hook-form 7.67.0 → 7.69.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"}
@@ -32,29 +32,23 @@ var isWeb = typeof window !== 'undefined' &&
32
32
  typeof document !== 'undefined';
33
33
 
34
34
  function cloneObject(data) {
35
- let copy;
36
- const isArray = Array.isArray(data);
37
- const isFileListInstance = typeof FileList !== 'undefined' ? data instanceof FileList : false;
38
35
  if (data instanceof Date) {
39
- copy = new Date(data);
36
+ return new Date(data);
40
37
  }
41
- else if (!(isWeb && (data instanceof Blob || isFileListInstance)) &&
42
- (isArray || isObject(data))) {
43
- copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
44
- if (!isArray && !isPlainObject(data)) {
45
- copy = data;
46
- }
47
- else {
48
- for (const key in data) {
49
- if (data.hasOwnProperty(key)) {
50
- copy[key] = cloneObject(data[key]);
51
- }
52
- }
53
- }
38
+ const isFileListInstance = typeof FileList !== 'undefined' && data instanceof FileList;
39
+ if (isWeb && (data instanceof Blob || isFileListInstance)) {
40
+ return data;
54
41
  }
55
- else {
42
+ const isArray = Array.isArray(data);
43
+ if (!isArray && !(isObject(data) && isPlainObject(data))) {
56
44
  return data;
57
45
  }
46
+ const copy = isArray ? [] : Object.create(Object.getPrototypeOf(data));
47
+ for (const key in data) {
48
+ if (Object.prototype.hasOwnProperty.call(data, key)) {
49
+ copy[key] = cloneObject(data[key]);
50
+ }
51
+ }
58
52
  return copy;
59
53
  }
60
54
 
@@ -80,6 +74,8 @@ var get = (object, path, defaultValue) => {
80
74
 
81
75
  var isBoolean = (value) => typeof value === 'boolean';
82
76
 
77
+ var isFunction = (value) => typeof value === 'function';
78
+
83
79
  var set = (object, path, value) => {
84
80
  let index = -1;
85
81
  const tempPath = isKey(path) ? [path] : stringToPath(path);
@@ -503,12 +499,12 @@ function useController(props) {
503
499
  }), [name, control._formValues]);
504
500
  const ref = React.useCallback((elm) => {
505
501
  const field = get(control._fields, name);
506
- if (field && elm) {
502
+ if (field && field._f && elm) {
507
503
  field._f.ref = {
508
- focus: () => elm.focus && elm.focus(),
509
- select: () => elm.select && elm.select(),
510
- setCustomValidity: (message) => elm.setCustomValidity(message),
511
- reportValidity: () => elm.reportValidity(),
504
+ focus: () => isFunction(elm.focus) && elm.focus(),
505
+ select: () => isFunction(elm.select) && elm.select(),
506
+ setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
507
+ reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
512
508
  };
513
509
  }
514
510
  }, [control._fields, name]);
@@ -732,6 +728,8 @@ function Form(props) {
732
728
  }))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
733
729
  }
734
730
 
731
+ const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
732
+
735
733
  var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
736
734
  ? {
737
735
  ...errors[name],
@@ -796,8 +794,6 @@ var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
796
794
 
797
795
  var isFileInput = (element) => element.type === 'file';
798
796
 
799
- var isFunction = (value) => typeof value === 'function';
800
-
801
797
  var isHTMLElement = (value) => {
802
798
  if (!isWeb) {
803
799
  return false;
@@ -1365,6 +1361,7 @@ function createFormControl(props = {}) {
1365
1361
  action: false,
1366
1362
  mount: false,
1367
1363
  watch: false,
1364
+ keepIsValid: false,
1368
1365
  };
1369
1366
  let _names = {
1370
1367
  mount: new Set(),
@@ -1375,7 +1372,7 @@ function createFormControl(props = {}) {
1375
1372
  };
1376
1373
  let delayErrorCallback;
1377
1374
  let timer = 0;
1378
- const _proxyFormState = {
1375
+ const defaultProxyFormState = {
1379
1376
  isDirty: false,
1380
1377
  dirtyFields: false,
1381
1378
  validatingFields: false,
@@ -1384,6 +1381,9 @@ function createFormControl(props = {}) {
1384
1381
  isValid: false,
1385
1382
  errors: false,
1386
1383
  };
1384
+ const _proxyFormState = {
1385
+ ...defaultProxyFormState,
1386
+ };
1387
1387
  let _proxySubscribeFormState = {
1388
1388
  ..._proxyFormState,
1389
1389
  };
@@ -1397,13 +1397,21 @@ function createFormControl(props = {}) {
1397
1397
  timer = setTimeout(callback, wait);
1398
1398
  };
1399
1399
  const _setValid = async (shouldUpdateValid) => {
1400
+ if (_state.keepIsValid) {
1401
+ return;
1402
+ }
1400
1403
  if (!_options.disabled &&
1401
1404
  (_proxyFormState.isValid ||
1402
1405
  _proxySubscribeFormState.isValid ||
1403
1406
  shouldUpdateValid)) {
1404
- const isValid = _options.resolver
1405
- ? isEmptyObject((await _runSchema()).errors)
1406
- : await executeBuiltInValidation(_fields, true);
1407
+ let isValid;
1408
+ if (_options.resolver) {
1409
+ isValid = isEmptyObject((await _runSchema()).errors);
1410
+ _updateIsValidating();
1411
+ }
1412
+ else {
1413
+ isValid = await executeBuiltInValidation(_fields, true);
1414
+ }
1407
1415
  if (isValid !== _formState.isValid) {
1408
1416
  _subjects.state.next({
1409
1417
  isValid,
@@ -1566,11 +1574,11 @@ function createFormControl(props = {}) {
1566
1574
  const _runSchema = async (name) => {
1567
1575
  _updateIsValidating(name, true);
1568
1576
  const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1569
- _updateIsValidating(name);
1570
1577
  return result;
1571
1578
  };
1572
1579
  const executeSchemaAndUpdateState = async (names) => {
1573
1580
  const { errors } = await _runSchema(names);
1581
+ _updateIsValidating(names);
1574
1582
  if (names) {
1575
1583
  for (const name of names) {
1576
1584
  const error = get(errors, name);
@@ -1806,6 +1814,7 @@ function createFormControl(props = {}) {
1806
1814
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
1807
1815
  if (_options.resolver) {
1808
1816
  const { errors } = await _runSchema([name]);
1817
+ _updateIsValidating([name]);
1809
1818
  _updateIsFieldValueUpdated(fieldValue);
1810
1819
  if (isFieldValueUpdated) {
1811
1820
  const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
@@ -1951,7 +1960,10 @@ function createFormControl(props = {}) {
1951
1960
  };
1952
1961
  return _subscribe({
1953
1962
  ...props,
1954
- formState: _proxySubscribeFormState,
1963
+ formState: {
1964
+ ...defaultProxyFormState,
1965
+ ...props.formState,
1966
+ },
1955
1967
  });
1956
1968
  };
1957
1969
  const unregister = (name, options = {}) => {
@@ -2104,6 +2116,7 @@ function createFormControl(props = {}) {
2104
2116
  });
2105
2117
  if (_options.resolver) {
2106
2118
  const { errors, values } = await _runSchema();
2119
+ _updateIsValidating();
2107
2120
  _formState.errors = errors;
2108
2121
  fieldValues = cloneObject(values);
2109
2122
  }
@@ -2244,6 +2257,14 @@ function createFormControl(props = {}) {
2244
2257
  !!keepStateOptions.keepDirtyValues ||
2245
2258
  (!_options.shouldUnregister && !isEmptyObject(values));
2246
2259
  _state.watch = !!_options.shouldUnregister;
2260
+ _state.keepIsValid = !!keepStateOptions.keepIsValid;
2261
+ _state.action = false;
2262
+ // Clear errors synchronously to prevent validation errors on subsequent submissions
2263
+ // This fixes the issue where form.reset() causes validation errors on subsequent
2264
+ // submissions in Next.js 16 with Server Actions
2265
+ if (!keepStateOptions.keepErrors) {
2266
+ _formState.errors = {};
2267
+ }
2247
2268
  _subjects.state.next({
2248
2269
  submitCount: keepStateOptions.keepSubmitCount
2249
2270
  ? _formState.submitCount
@@ -2281,7 +2302,7 @@ function createFormControl(props = {}) {
2281
2302
  };
2282
2303
  const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
2283
2304
  ? formValues(_formValues)
2284
- : formValues, keepStateOptions);
2305
+ : formValues, { ..._options.resetOptions, ...keepStateOptions });
2285
2306
  const setFocus = (name, options = {}) => {
2286
2307
  const field = get(_fields, name);
2287
2308
  const fieldReference = field && field._f;
@@ -2290,10 +2311,14 @@ function createFormControl(props = {}) {
2290
2311
  ? fieldReference.refs[0]
2291
2312
  : fieldReference.ref;
2292
2313
  if (fieldRef.focus) {
2293
- fieldRef.focus();
2294
- options.shouldSelect &&
2295
- isFunction(fieldRef.select) &&
2296
- fieldRef.select();
2314
+ // Use setTimeout to ensure focus happens after any pending state updates
2315
+ // This fixes the issue where setFocus doesn't work immediately after setError
2316
+ setTimeout(() => {
2317
+ fieldRef.focus();
2318
+ options.shouldSelect &&
2319
+ isFunction(fieldRef.select) &&
2320
+ fieldRef.select();
2321
+ });
2297
2322
  }
2298
2323
  }
2299
2324
  };
@@ -2319,6 +2344,7 @@ function createFormControl(props = {}) {
2319
2344
  setError,
2320
2345
  _subscribe,
2321
2346
  _runSchema,
2347
+ _updateIsValidating,
2322
2348
  _focusError,
2323
2349
  _getWatch,
2324
2350
  _getDirty,
@@ -2394,7 +2420,7 @@ var generateId = () => {
2394
2420
  }
2395
2421
  const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
2396
2422
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
2397
- const r = (Math.random() * 16 + d) % 16 | 0;
2423
+ const r = ((Math.random() * 16 + d) % 16) | 0;
2398
2424
  return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
2399
2425
  });
2400
2426
  };
@@ -2616,6 +2642,7 @@ function useFieldArray(props) {
2616
2642
  !getValidationModes(control._options.reValidateMode).isOnSubmit) {
2617
2643
  if (control._options.resolver) {
2618
2644
  control._runSchema([name]).then((result) => {
2645
+ control._updateIsValidating([name]);
2619
2646
  const error = get(result.errors, name);
2620
2647
  const existingError = get(control._formState.errors, name);
2621
2648
  if (existingError
@@ -2845,7 +2872,11 @@ function useForm(props = {}) {
2845
2872
  * Watch component that subscribes to form field changes and re-renders when watched fields update.
2846
2873
  *
2847
2874
  * @param control - The form control object from useForm
2848
- * @param names - Array of field names to watch for changes
2875
+ * @param name - Can be field name, array of field names, or undefined to watch the entire form
2876
+ * @param disabled - Disable subscription
2877
+ * @param exact - Whether to watch exact field names or not
2878
+ * @param defaultValue - The default value to use if the field is not yet set
2879
+ * @param compute - Function to compute derived values from watched fields
2849
2880
  * @param render - The function that receives watched values and returns ReactNode
2850
2881
  * @returns The result of calling render function with watched values
2851
2882
  *
@@ -2863,7 +2894,7 @@ function useForm(props = {}) {
2863
2894
  * />
2864
2895
  * ```
2865
2896
  */
2866
- const Watch = ({ control, names, render, }) => render(useWatch({ control, name: names }));
2897
+ const Watch = ({ render, names, ...props }) => render(useWatch({ ...props, name: names }));
2867
2898
 
2868
- export { Controller, Form, FormProvider, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
2899
+ export { Controller, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
2869
2900
  //# sourceMappingURL=index.esm.mjs.map