react-hook-form 7.81.0 → 7.82.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.
@@ -1 +1 @@
1
- {"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAcV,WAAW,EAiBX,YAAY,EAKZ,aAAa,EAYd,MAAM,UAAU,CAAC;AA0DlB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAY9B,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EAEjC,KAAK,GAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAM,GACnE,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,CAAC;CACH,CA2zDA"}
1
+ {"version":3,"file":"createFormControl.d.ts","sourceRoot":"","sources":["../../src/logic/createFormControl.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAcV,WAAW,EAkBX,YAAY,EAKZ,aAAa,EAYd,MAAM,UAAU,CAAC;AA0DlB,eAAO,MAAM,kBAAkB;;;;;;;;;;;;CAY9B,CAAC;AAEF,wBAAgB,iBAAiB,CAC/B,YAAY,SAAS,WAAW,GAAG,WAAW,EAC9C,QAAQ,GAAG,GAAG,EACd,kBAAkB,GAAG,YAAY,EAEjC,KAAK,GAAE,YAAY,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAM,GACnE,IAAI,CACL,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,GAAG;IACF,WAAW,EAAE,IAAI,CACf,aAAa,CAAC,YAAY,EAAE,QAAQ,EAAE,kBAAkB,CAAC,EACzD,WAAW,CACZ,CAAC;CACH,CA62DA"}
@@ -1,4 +1,5 @@
1
- declare function markFieldsDirty<T>(data: T, fields?: Record<string, any>): Record<string, any>;
2
- export default function getDirtyFields<T>(data: T, formValues: T, dirtyFieldsFromValues?: Record<Extract<keyof T, string>, ReturnType<typeof markFieldsDirty> | boolean>): Record<Extract<keyof T, string>, boolean | Record<string, any>>;
1
+ import type { FieldRefs } from '../types';
2
+ declare function markFieldsDirty<T>(data: T, fields?: Record<string, any>, fieldRefs?: Record<string, any>): Record<string, any>;
3
+ export default function getDirtyFields<T>(data: T, formValues: T, dirtyFieldsFromValues?: Record<Extract<keyof T, string>, ReturnType<typeof markFieldsDirty> | boolean>, fieldRefs?: FieldRefs): Record<Extract<keyof T, string>, boolean | Record<string, any>>;
3
4
  export {};
4
5
  //# sourceMappingURL=getDirtyFields.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"getDirtyFields.d.ts","sourceRoot":"","sources":["../../src/logic/getDirtyFields.ts"],"names":[],"mappings":"AAWA,iBAAS,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,uBAapE;AAmCD,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,CAAC,EACtC,IAAI,EAAE,CAAC,EACP,UAAU,EAAE,CAAC,EACb,qBAAqB,CAAC,EAAE,MAAM,CAC5B,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EACxB,UAAU,CAAC,OAAO,eAAe,CAAC,GAAG,OAAO,CAC7C,mEA6BF"}
1
+ {"version":3,"file":"getDirtyFields.d.ts","sourceRoot":"","sources":["../../src/logic/getDirtyFields.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AA8B1C,iBAAS,eAAe,CAAC,CAAC,EACxB,IAAI,EAAE,CAAC,EACP,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,EAChC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,uBAsBhC;AAED,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,CAAC,EACtC,IAAI,EAAE,CAAC,EACP,UAAU,EAAE,CAAC,EACb,qBAAqB,CAAC,EAAE,MAAM,CAC5B,OAAO,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EACxB,UAAU,CAAC,OAAO,eAAe,CAAC,GAAG,OAAO,CAC7C,EACD,SAAS,CAAC,EAAE,SAAS,mEAwCtB"}
@@ -353,12 +353,33 @@ var objectHasFunction = (data) => {
353
353
  function isTraversable(value) {
354
354
  return Array.isArray(value) || (isObject(value) && !objectHasFunction(value));
355
355
  }
356
- function markFieldsDirty(data, fields = {}) {
356
+ function isRegisteredLeaf(fieldRef) {
357
+ return !!(fieldRef && '_f' in fieldRef);
358
+ }
359
+ function isEmptyDirtyContainer(value) {
360
+ return Array.isArray(value)
361
+ ? !value.some((item) => !isUndefined(item))
362
+ : !Object.keys(value).length;
363
+ }
364
+ function clearDirtyField(container, key) {
365
+ if (Array.isArray(container)) {
366
+ container[key] = undefined;
367
+ }
368
+ else {
369
+ delete container[key];
370
+ }
371
+ }
372
+ function markFieldsDirty(data, fields = {}, fieldRefs) {
357
373
  for (const key in data) {
358
374
  const value = data[key];
359
- if (isTraversable(value)) {
375
+ const fieldRef = fieldRefs && fieldRefs[key];
376
+ if (isTraversable(value) &&
377
+ (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
360
378
  fields[key] = Array.isArray(value) ? [] : {};
361
- markFieldsDirty(value, fields[key]);
379
+ markFieldsDirty(value, fields[key], fieldRef);
380
+ if (isEmptyDirtyContainer(fields[key])) {
381
+ clearDirtyField(fields, key);
382
+ }
362
383
  }
363
384
  else if (!isUndefined(value)) {
364
385
  fields[key] = true;
@@ -366,49 +387,33 @@ function markFieldsDirty(data, fields = {}) {
366
387
  }
367
388
  return fields;
368
389
  }
369
- function pruneDirtyFields(value) {
370
- if (value === false) {
371
- return undefined;
372
- }
373
- if (value === true) {
374
- return true;
375
- }
376
- if (Array.isArray(value)) {
377
- const result = value.map((value) => pruneDirtyFields(value));
378
- return (result.some((value) => value !== undefined) ? result : undefined);
379
- }
380
- if (isObject(value)) {
381
- const result = {};
382
- for (const key in value) {
383
- const pruned = pruneDirtyFields(value[key]);
384
- if (!isUndefined(pruned)) {
385
- result[key] = pruned;
386
- }
387
- }
388
- return (Object.keys(result).length ? result : undefined);
389
- }
390
- return undefined;
391
- }
392
- function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
390
+ function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
393
391
  if (!dirtyFieldsFromValues) {
394
- dirtyFieldsFromValues = markFieldsDirty(formValues);
392
+ dirtyFieldsFromValues = markFieldsDirty(formValues, {}, fieldRefs);
395
393
  }
396
394
  for (const key in data) {
397
395
  const value = data[key];
398
- if (isTraversable(value)) {
396
+ const fieldRef = fieldRefs && fieldRefs[key];
397
+ if (isTraversable(value) &&
398
+ (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
399
399
  if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
400
- dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {});
400
+ dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}, fieldRef);
401
401
  }
402
402
  else {
403
- getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
403
+ getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key], fieldRef);
404
404
  }
405
+ if (isEmptyDirtyContainer(dirtyFieldsFromValues[key])) {
406
+ clearDirtyField(dirtyFieldsFromValues, key);
407
+ }
408
+ }
409
+ else if (deepEqual(value, formValues[key])) {
410
+ clearDirtyField(dirtyFieldsFromValues, key);
405
411
  }
406
412
  else {
407
- const formValue = formValues[key];
408
- dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
413
+ dirtyFieldsFromValues[key] = true;
409
414
  }
410
415
  }
411
- return pruneDirtyFields(dirtyFieldsFromValues) || {};
416
+ return dirtyFieldsFromValues;
412
417
  }
413
418
 
414
419
  var getEventValue = (event) => isObject(event) && event.target
@@ -926,8 +931,8 @@ function createFormControl(props = {}) {
926
931
  watch: new Set(),
927
932
  registerName: new Set(),
928
933
  };
929
- let delayErrorCallback;
930
- let timer = 0;
934
+ const delayErrorCallbacks = {};
935
+ const timers = {};
931
936
  let _valuesSubscriberCount = 0;
932
937
  let _validationModeBeforeSubmit = getValidationModes(_options.mode);
933
938
  let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
@@ -950,10 +955,11 @@ function createFormControl(props = {}) {
950
955
  array: createSubject(),
951
956
  state: createSubject(),
952
957
  };
958
+ let _setValidCallId = 0;
953
959
  const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
954
- const debounce = (callback) => (wait) => {
955
- clearTimeout(timer);
956
- timer = setTimeout(callback, wait);
960
+ const debounce = (name, callback) => (wait) => {
961
+ clearTimeout(timers[name]);
962
+ timers[name] = setTimeout(callback, wait);
957
963
  };
958
964
  const _setValid = async (shouldUpdateValid) => {
959
965
  if (_state.keepIsValid) {
@@ -963,10 +969,11 @@ function createFormControl(props = {}) {
963
969
  (_proxyFormState.isValid ||
964
970
  _proxySubscribeFormState.isValid ||
965
971
  shouldUpdateValid)) {
972
+ const callId = ++_setValidCallId;
966
973
  let isValid;
967
974
  if (_options.resolver) {
968
975
  isValid = isEmptyObject((await _runSchema()).errors);
969
- _updateIsValidating();
976
+ callId === _setValidCallId && _updateIsValidating();
970
977
  }
971
978
  else {
972
979
  isValid = await executeBuiltInValidation({
@@ -975,7 +982,7 @@ function createFormControl(props = {}) {
975
982
  eventType: EVENTS.VALID,
976
983
  });
977
984
  }
978
- if (isValid !== _formState.isValid) {
985
+ if (callId === _setValidCallId && isValid !== _formState.isValid) {
979
986
  _subjects.state.next({
980
987
  isValid,
981
988
  });
@@ -1002,7 +1009,7 @@ function createFormControl(props = {}) {
1002
1009
  }
1003
1010
  };
1004
1011
  const _updateDirtyFields = () => {
1005
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1012
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
1006
1013
  };
1007
1014
  const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1008
1015
  if (args && method && !_options.disabled) {
@@ -1108,7 +1115,9 @@ function createFormControl(props = {}) {
1108
1115
  const output = {
1109
1116
  name,
1110
1117
  };
1111
- if (!_options.disabled) {
1118
+ // an explicit programmatic update (e.g. setValue with shouldDirty: true)
1119
+ // opts into dirty tracking even when the form is disabled
1120
+ if (!_options.disabled || shouldDirty === true) {
1112
1121
  if (!isBlurEvent || shouldDirty) {
1113
1122
  const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1114
1123
  if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
@@ -1119,7 +1128,7 @@ function createFormControl(props = {}) {
1119
1128
  }
1120
1129
  isPreviousDirty = !!get(_formState.dirtyFields, name);
1121
1130
  if (isCurrentFieldPristine !== _formState.isDirty) {
1122
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1131
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
1123
1132
  }
1124
1133
  else {
1125
1134
  isCurrentFieldPristine
@@ -1155,12 +1164,12 @@ function createFormControl(props = {}) {
1155
1164
  isBoolean(isValid) &&
1156
1165
  _formState.isValid !== isValid;
1157
1166
  if (_options.delayError && error) {
1158
- delayErrorCallback = debounce(() => updateErrors(name, error));
1159
- delayErrorCallback(_options.delayError);
1167
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
1168
+ delayErrorCallbacks[name](_options.delayError);
1160
1169
  }
1161
1170
  else {
1162
- clearTimeout(timer);
1163
- delayErrorCallback = null;
1171
+ clearTimeout(timers[name]);
1172
+ delete delayErrorCallbacks[name];
1164
1173
  error
1165
1174
  ? set(_formState.errors, name, error)
1166
1175
  : unset(_formState.errors, name);
@@ -1313,9 +1322,8 @@ function createFormControl(props = {}) {
1313
1322
  }
1314
1323
  _names.unMount = new Set();
1315
1324
  };
1316
- const _getDirty = (name, data) => !_options.disabled &&
1317
- (name && data && set(_formValues, name, data),
1318
- !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1325
+ const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
1326
+ !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1319
1327
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1320
1328
  ...(_state.mount
1321
1329
  ? _formValues
@@ -1375,7 +1383,10 @@ function createFormControl(props = {}) {
1375
1383
  }
1376
1384
  (options.shouldDirty || options.shouldTouch) &&
1377
1385
  updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
1378
- options.shouldValidate && trigger(name);
1386
+ options.shouldValidate &&
1387
+ trigger(name, {
1388
+ delayError: options.delayError,
1389
+ });
1379
1390
  };
1380
1391
  const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
1381
1392
  for (const fieldKey in value) {
@@ -1500,7 +1511,8 @@ function createFormControl(props = {}) {
1500
1511
  if (isBlurEvent) {
1501
1512
  if (!target || !target.readOnly) {
1502
1513
  field._f.onBlur && field._f.onBlur(event);
1503
- delayErrorCallback && delayErrorCallback(0);
1514
+ const pendingDelayError = delayErrorCallbacks[name];
1515
+ pendingDelayError && pendingDelayError(0);
1504
1516
  }
1505
1517
  }
1506
1518
  else if (field._f.onChange) {
@@ -1615,6 +1627,18 @@ function createFormControl(props = {}) {
1615
1627
  eventType: EVENTS.TRIGGER,
1616
1628
  });
1617
1629
  }
1630
+ if (options.delayError && _options.delayError && isString(name)) {
1631
+ const error = get(_formState.errors, name);
1632
+ if (error) {
1633
+ unset(_formState.errors, name);
1634
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
1635
+ delayErrorCallbacks[name](_options.delayError);
1636
+ }
1637
+ else {
1638
+ clearTimeout(timers[name]);
1639
+ delete delayErrorCallbacks[name];
1640
+ }
1641
+ }
1618
1642
  _subjects.state.next({
1619
1643
  ...(!isString(name) ||
1620
1644
  ((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
@@ -1983,6 +2007,7 @@ function createFormControl(props = {}) {
1983
2007
  const cloneUpdatedValues = cloneObject(updatedValues);
1984
2008
  const isEmptyResetValues = isEmptyObject(formValues);
1985
2009
  const values = cloneUpdatedValues;
2010
+ const fieldRefs = _fields;
1986
2011
  if (!keepStateOptions.keepDefaultValues) {
1987
2012
  _defaultValues = updatedValues;
1988
2013
  }
@@ -1990,7 +2015,7 @@ function createFormControl(props = {}) {
1990
2015
  if (keepStateOptions.keepDirtyValues) {
1991
2016
  const fieldsToCheck = new Set([
1992
2017
  ..._names.mount,
1993
- ...Object.keys(getDirtyFields(_defaultValues, _formValues)),
2018
+ ...Object.keys(getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)),
1994
2019
  ]);
1995
2020
  for (const fieldName of Array.from(fieldsToCheck)) {
1996
2021
  const isDirty = get(_formState.dirtyFields, fieldName);
@@ -2093,10 +2118,10 @@ function createFormControl(props = {}) {
2093
2118
  ? {}
2094
2119
  : keepStateOptions.keepDirtyValues
2095
2120
  ? keepStateOptions.keepDefaultValues && _formValues
2096
- ? getDirtyFields(_defaultValues, _formValues)
2121
+ ? getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)
2097
2122
  : _formState.dirtyFields
2098
2123
  : keepStateOptions.keepDefaultValues && formValues
2099
- ? getDirtyFields(_defaultValues, formValues)
2124
+ ? getDirtyFields(_defaultValues, formValues, undefined, fieldRefs)
2100
2125
  : keepStateOptions.keepDirty
2101
2126
  ? _formState.dirtyFields
2102
2127
  : {},
@@ -2153,7 +2178,7 @@ function createFormControl(props = {}) {
2153
2178
  const resetDefaultValues = (values, options = {}) => {
2154
2179
  _defaultValues = cloneObject(values);
2155
2180
  if (!options.keepDirty) {
2156
- const newDirtyFields = getDirtyFields(_defaultValues, _formValues);
2181
+ const newDirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
2157
2182
  _formState.dirtyFields = newDirtyFields;
2158
2183
  _formState.isDirty = !isEmptyObject(newDirtyFields);
2159
2184
  }