react-hook-form 8.0.0-beta.1 → 8.0.0-beta.3

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.
Files changed (281) hide show
  1. package/README.md +16 -40
  2. package/dist/constants.d.ts +5 -0
  3. package/dist/constants.d.ts.map +1 -1
  4. package/dist/fieldArray.d.ts +36 -0
  5. package/dist/fieldArray.d.ts.map +1 -0
  6. package/dist/form.d.ts.map +1 -1
  7. package/dist/index.cjs.js +1 -1
  8. package/dist/index.cjs.js.map +1 -1
  9. package/dist/index.esm.mjs +755 -293
  10. package/dist/index.esm.mjs.map +1 -1
  11. package/dist/index.umd.js +1 -1
  12. package/dist/index.umd.js.map +1 -1
  13. package/dist/logic/createFormControl.d.ts +13 -0
  14. package/dist/logic/createFormControl.d.ts.map +1 -1
  15. package/dist/logic/getDirtyFields.d.ts.map +1 -1
  16. package/dist/logic/getNodeParentName.d.ts.map +1 -1
  17. package/dist/logic/getProxyFormState.d.ts.map +1 -1
  18. package/dist/logic/getResolverOptions.d.ts +2 -2
  19. package/dist/logic/hasPromiseValidation.d.ts.map +1 -1
  20. package/dist/logic/hasValidation.d.ts +1 -1
  21. package/dist/logic/index.d.ts +2 -3
  22. package/dist/logic/index.d.ts.map +1 -1
  23. package/dist/logic/isNameInFieldArray.d.ts.map +1 -1
  24. package/dist/logic/isWatched.d.ts.map +1 -1
  25. package/dist/logic/shouldRenderFormState.d.ts.map +1 -1
  26. package/dist/logic/skipValidation.d.ts +1 -4
  27. package/dist/logic/skipValidation.d.ts.map +1 -1
  28. package/dist/logic/updateFieldArrayRootError.d.ts.map +1 -1
  29. package/dist/logic/validateField.d.ts.map +1 -1
  30. package/dist/react-server.esm.mjs +522 -144
  31. package/dist/react-server.esm.mjs.map +1 -1
  32. package/dist/types/errors.d.ts +1 -0
  33. package/dist/types/errors.d.ts.map +1 -1
  34. package/dist/types/fieldArray.d.ts +25 -1
  35. package/dist/types/fieldArray.d.ts.map +1 -1
  36. package/dist/types/form.d.ts +61 -8
  37. package/dist/types/form.d.ts.map +1 -1
  38. package/dist/types/path/eager.d.ts +1 -1
  39. package/dist/types/path/eager.d.ts.map +1 -1
  40. package/dist/types/utils.d.ts +3 -3
  41. package/dist/types/utils.d.ts.map +1 -1
  42. package/dist/types/validator.d.ts +13 -1
  43. package/dist/types/validator.d.ts.map +1 -1
  44. package/dist/useController.d.ts.map +1 -1
  45. package/dist/useFieldArray.d.ts.map +1 -1
  46. package/dist/useForm.d.ts.map +1 -1
  47. package/dist/useFormContext.d.ts +1 -1
  48. package/dist/useFormContext.d.ts.map +1 -1
  49. package/dist/useFormState.d.ts.map +1 -1
  50. package/dist/useIsomorphicLayoutEffect.d.ts.map +1 -1
  51. package/dist/utils/deepEqual.d.ts +1 -1
  52. package/dist/utils/deepEqual.d.ts.map +1 -1
  53. package/dist/utils/flatten.d.ts.map +1 -1
  54. package/dist/utils/get.d.ts.map +1 -1
  55. package/dist/utils/index.d.ts +2 -3
  56. package/dist/utils/index.d.ts.map +1 -1
  57. package/dist/utils/isKey.d.ts.map +1 -1
  58. package/dist/utils/set.d.ts.map +1 -1
  59. package/dist/utils/stringToPath.d.ts.map +1 -1
  60. package/dist/utils/unset.d.ts.map +1 -1
  61. package/dist/watch.d.ts +1 -1
  62. package/dist/watch.d.ts.map +1 -1
  63. package/package.json +31 -28
  64. package/dist/__tests__/controller.server.test.d.ts +0 -2
  65. package/dist/__tests__/controller.server.test.d.ts.map +0 -1
  66. package/dist/__tests__/controller.test.d.ts +0 -2
  67. package/dist/__tests__/controller.test.d.ts.map +0 -1
  68. package/dist/__tests__/form.test.d.ts +0 -2
  69. package/dist/__tests__/form.test.d.ts.map +0 -1
  70. package/dist/__tests__/formStateSubscribe.server.test.d.ts +0 -2
  71. package/dist/__tests__/formStateSubscribe.server.test.d.ts.map +0 -1
  72. package/dist/__tests__/formStateSubscribe.test.d.ts +0 -2
  73. package/dist/__tests__/formStateSubscribe.test.d.ts.map +0 -1
  74. package/dist/__tests__/isPlainObject.test.d.ts +0 -2
  75. package/dist/__tests__/isPlainObject.test.d.ts.map +0 -1
  76. package/dist/__tests__/logic/appendErrors.test.d.ts +0 -2
  77. package/dist/__tests__/logic/appendErrors.test.d.ts.map +0 -1
  78. package/dist/__tests__/logic/createFormControl.test.d.ts +0 -2
  79. package/dist/__tests__/logic/createFormControl.test.d.ts.map +0 -1
  80. package/dist/__tests__/logic/generateId.test.d.ts +0 -2
  81. package/dist/__tests__/logic/generateId.test.d.ts.map +0 -1
  82. package/dist/__tests__/logic/getCheckboxValue.test.d.ts +0 -2
  83. package/dist/__tests__/logic/getCheckboxValue.test.d.ts.map +0 -1
  84. package/dist/__tests__/logic/getDirtyFields.test.d.ts +0 -2
  85. package/dist/__tests__/logic/getDirtyFields.test.d.ts.map +0 -1
  86. package/dist/__tests__/logic/getEventValue.test.d.ts +0 -2
  87. package/dist/__tests__/logic/getEventValue.test.d.ts.map +0 -1
  88. package/dist/__tests__/logic/getFieldValue.test.d.ts +0 -2
  89. package/dist/__tests__/logic/getFieldValue.test.d.ts.map +0 -1
  90. package/dist/__tests__/logic/getFieldValueAs.test.d.ts +0 -2
  91. package/dist/__tests__/logic/getFieldValueAs.test.d.ts.map +0 -1
  92. package/dist/__tests__/logic/getFocusFieldName.test.d.ts +0 -2
  93. package/dist/__tests__/logic/getFocusFieldName.test.d.ts.map +0 -1
  94. package/dist/__tests__/logic/getNodeParentName.test.d.ts +0 -2
  95. package/dist/__tests__/logic/getNodeParentName.test.d.ts.map +0 -1
  96. package/dist/__tests__/logic/getRadioValue.test.d.ts +0 -2
  97. package/dist/__tests__/logic/getRadioValue.test.d.ts.map +0 -1
  98. package/dist/__tests__/logic/getResolverOptions.test.d.ts +0 -2
  99. package/dist/__tests__/logic/getResolverOptions.test.d.ts.map +0 -1
  100. package/dist/__tests__/logic/getRuleValue.test.d.ts +0 -2
  101. package/dist/__tests__/logic/getRuleValue.test.d.ts.map +0 -1
  102. package/dist/__tests__/logic/getValidateError.test.d.ts +0 -2
  103. package/dist/__tests__/logic/getValidateError.test.d.ts.map +0 -1
  104. package/dist/__tests__/logic/getValidationModes.test.d.ts +0 -2
  105. package/dist/__tests__/logic/getValidationModes.test.d.ts.map +0 -1
  106. package/dist/__tests__/logic/getValueAndMessage.test.d.ts +0 -2
  107. package/dist/__tests__/logic/getValueAndMessage.test.d.ts.map +0 -1
  108. package/dist/__tests__/logic/hasPromiseValidation.test.d.ts +0 -2
  109. package/dist/__tests__/logic/hasPromiseValidation.test.d.ts.map +0 -1
  110. package/dist/__tests__/logic/hasValidation.test.d.ts +0 -2
  111. package/dist/__tests__/logic/hasValidation.test.d.ts.map +0 -1
  112. package/dist/__tests__/logic/isNameInFieldArray.test.d.ts +0 -2
  113. package/dist/__tests__/logic/isNameInFieldArray.test.d.ts.map +0 -1
  114. package/dist/__tests__/logic/isWatched.test.d.ts +0 -2
  115. package/dist/__tests__/logic/isWatched.test.d.ts.map +0 -1
  116. package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts +0 -2
  117. package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts.map +0 -1
  118. package/dist/__tests__/logic/schemaErrorLookup.test.d.ts +0 -2
  119. package/dist/__tests__/logic/schemaErrorLookup.test.d.ts.map +0 -1
  120. package/dist/__tests__/logic/shouldRenderFormState.test.d.ts +0 -2
  121. package/dist/__tests__/logic/shouldRenderFormState.test.d.ts.map +0 -1
  122. package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts +0 -2
  123. package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts.map +0 -1
  124. package/dist/__tests__/logic/skipValidation.test.d.ts +0 -2
  125. package/dist/__tests__/logic/skipValidation.test.d.ts.map +0 -1
  126. package/dist/__tests__/logic/unsetEmptyArray.test.d.ts +0 -2
  127. package/dist/__tests__/logic/unsetEmptyArray.test.d.ts.map +0 -1
  128. package/dist/__tests__/logic/validateField.test.d.ts +0 -2
  129. package/dist/__tests__/logic/validateField.test.d.ts.map +0 -1
  130. package/dist/__tests__/type.test.d.ts +0 -2
  131. package/dist/__tests__/type.test.d.ts.map +0 -1
  132. package/dist/__tests__/useController.test.d.ts +0 -2
  133. package/dist/__tests__/useController.test.d.ts.map +0 -1
  134. package/dist/__tests__/useFieldArray/append.test.d.ts +0 -2
  135. package/dist/__tests__/useFieldArray/append.test.d.ts.map +0 -1
  136. package/dist/__tests__/useFieldArray/focus.test.d.ts +0 -2
  137. package/dist/__tests__/useFieldArray/focus.test.d.ts.map +0 -1
  138. package/dist/__tests__/useFieldArray/insert.test.d.ts +0 -2
  139. package/dist/__tests__/useFieldArray/insert.test.d.ts.map +0 -1
  140. package/dist/__tests__/useFieldArray/move.test.d.ts +0 -2
  141. package/dist/__tests__/useFieldArray/move.test.d.ts.map +0 -1
  142. package/dist/__tests__/useFieldArray/prepend.test.d.ts +0 -2
  143. package/dist/__tests__/useFieldArray/prepend.test.d.ts.map +0 -1
  144. package/dist/__tests__/useFieldArray/remove.test.d.ts +0 -2
  145. package/dist/__tests__/useFieldArray/remove.test.d.ts.map +0 -1
  146. package/dist/__tests__/useFieldArray/replace.test.d.ts +0 -2
  147. package/dist/__tests__/useFieldArray/replace.test.d.ts.map +0 -1
  148. package/dist/__tests__/useFieldArray/swap.test.d.ts +0 -2
  149. package/dist/__tests__/useFieldArray/swap.test.d.ts.map +0 -1
  150. package/dist/__tests__/useFieldArray/update.test.d.ts +0 -2
  151. package/dist/__tests__/useFieldArray/update.test.d.ts.map +0 -1
  152. package/dist/__tests__/useFieldArray.test.d.ts +0 -2
  153. package/dist/__tests__/useFieldArray.test.d.ts.map +0 -1
  154. package/dist/__tests__/useForm/clearErrors.test.d.ts +0 -2
  155. package/dist/__tests__/useForm/clearErrors.test.d.ts.map +0 -1
  156. package/dist/__tests__/useForm/formState.test.d.ts +0 -2
  157. package/dist/__tests__/useForm/formState.test.d.ts.map +0 -1
  158. package/dist/__tests__/useForm/getFieldState.test.d.ts +0 -2
  159. package/dist/__tests__/useForm/getFieldState.test.d.ts.map +0 -1
  160. package/dist/__tests__/useForm/getValues.test.d.ts +0 -2
  161. package/dist/__tests__/useForm/getValues.test.d.ts.map +0 -1
  162. package/dist/__tests__/useForm/handleSubmit.test.d.ts +0 -2
  163. package/dist/__tests__/useForm/handleSubmit.test.d.ts.map +0 -1
  164. package/dist/__tests__/useForm/register.test.d.ts +0 -2
  165. package/dist/__tests__/useForm/register.test.d.ts.map +0 -1
  166. package/dist/__tests__/useForm/reset.test.d.ts +0 -2
  167. package/dist/__tests__/useForm/reset.test.d.ts.map +0 -1
  168. package/dist/__tests__/useForm/resetField.test.d.ts +0 -2
  169. package/dist/__tests__/useForm/resetField.test.d.ts.map +0 -1
  170. package/dist/__tests__/useForm/resolver.test.d.ts +0 -2
  171. package/dist/__tests__/useForm/resolver.test.d.ts.map +0 -1
  172. package/dist/__tests__/useForm/setError.test.d.ts +0 -2
  173. package/dist/__tests__/useForm/setError.test.d.ts.map +0 -1
  174. package/dist/__tests__/useForm/setFocus.test.d.ts +0 -2
  175. package/dist/__tests__/useForm/setFocus.test.d.ts.map +0 -1
  176. package/dist/__tests__/useForm/setValue.test.d.ts +0 -2
  177. package/dist/__tests__/useForm/setValue.test.d.ts.map +0 -1
  178. package/dist/__tests__/useForm/subscribe.test.d.ts +0 -2
  179. package/dist/__tests__/useForm/subscribe.test.d.ts.map +0 -1
  180. package/dist/__tests__/useForm/trigger.test.d.ts +0 -2
  181. package/dist/__tests__/useForm/trigger.test.d.ts.map +0 -1
  182. package/dist/__tests__/useForm/unregister.test.d.ts +0 -2
  183. package/dist/__tests__/useForm/unregister.test.d.ts.map +0 -1
  184. package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts +0 -2
  185. package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts.map +0 -1
  186. package/dist/__tests__/useForm/watch.test.d.ts +0 -2
  187. package/dist/__tests__/useForm/watch.test.d.ts.map +0 -1
  188. package/dist/__tests__/useForm.server.test.d.ts +0 -2
  189. package/dist/__tests__/useForm.server.test.d.ts.map +0 -1
  190. package/dist/__tests__/useForm.test.d.ts +0 -2
  191. package/dist/__tests__/useForm.test.d.ts.map +0 -1
  192. package/dist/__tests__/useFormContext.server.test.d.ts +0 -2
  193. package/dist/__tests__/useFormContext.server.test.d.ts.map +0 -1
  194. package/dist/__tests__/useFormContext.test.d.ts +0 -2
  195. package/dist/__tests__/useFormContext.test.d.ts.map +0 -1
  196. package/dist/__tests__/useFormState.test.d.ts +0 -2
  197. package/dist/__tests__/useFormState.test.d.ts.map +0 -1
  198. package/dist/__tests__/useWatch.test.d.ts +0 -2
  199. package/dist/__tests__/useWatch.test.d.ts.map +0 -1
  200. package/dist/__tests__/utils/append.test.d.ts +0 -2
  201. package/dist/__tests__/utils/append.test.d.ts.map +0 -1
  202. package/dist/__tests__/utils/cloneObject.test.d.ts +0 -2
  203. package/dist/__tests__/utils/cloneObject.test.d.ts.map +0 -1
  204. package/dist/__tests__/utils/compact.test.d.ts +0 -2
  205. package/dist/__tests__/utils/compact.test.d.ts.map +0 -1
  206. package/dist/__tests__/utils/convertToArrayPayload.test.d.ts +0 -2
  207. package/dist/__tests__/utils/convertToArrayPayload.test.d.ts.map +0 -1
  208. package/dist/__tests__/utils/createSubject.test.d.ts +0 -2
  209. package/dist/__tests__/utils/createSubject.test.d.ts.map +0 -1
  210. package/dist/__tests__/utils/deepEqual.test.d.ts +0 -2
  211. package/dist/__tests__/utils/deepEqual.test.d.ts.map +0 -1
  212. package/dist/__tests__/utils/deepMerge.test.d.ts +0 -2
  213. package/dist/__tests__/utils/deepMerge.test.d.ts.map +0 -1
  214. package/dist/__tests__/utils/extractFormValues.test.d.ts +0 -2
  215. package/dist/__tests__/utils/extractFormValues.test.d.ts.map +0 -1
  216. package/dist/__tests__/utils/fillEmptyArray.test.d.ts +0 -2
  217. package/dist/__tests__/utils/fillEmptyArray.test.d.ts.map +0 -1
  218. package/dist/__tests__/utils/flatten.test.d.ts +0 -2
  219. package/dist/__tests__/utils/flatten.test.d.ts.map +0 -1
  220. package/dist/__tests__/utils/get.test.d.ts +0 -2
  221. package/dist/__tests__/utils/get.test.d.ts.map +0 -1
  222. package/dist/__tests__/utils/insert.test.d.ts +0 -2
  223. package/dist/__tests__/utils/insert.test.d.ts.map +0 -1
  224. package/dist/__tests__/utils/isBoolean.test.d.ts +0 -2
  225. package/dist/__tests__/utils/isBoolean.test.d.ts.map +0 -1
  226. package/dist/__tests__/utils/isCheckBoxInput.test.d.ts +0 -2
  227. package/dist/__tests__/utils/isCheckBoxInput.test.d.ts.map +0 -1
  228. package/dist/__tests__/utils/isEmptyObject.test.d.ts +0 -2
  229. package/dist/__tests__/utils/isEmptyObject.test.d.ts.map +0 -1
  230. package/dist/__tests__/utils/isFileInput.test.d.ts +0 -2
  231. package/dist/__tests__/utils/isFileInput.test.d.ts.map +0 -1
  232. package/dist/__tests__/utils/isFunction.test.d.ts +0 -2
  233. package/dist/__tests__/utils/isFunction.test.d.ts.map +0 -1
  234. package/dist/__tests__/utils/isHTMLElement.test.d.ts +0 -2
  235. package/dist/__tests__/utils/isHTMLElement.test.d.ts.map +0 -1
  236. package/dist/__tests__/utils/isKey.test.d.ts +0 -2
  237. package/dist/__tests__/utils/isKey.test.d.ts.map +0 -1
  238. package/dist/__tests__/utils/isMultipleSelect.test.d.ts +0 -2
  239. package/dist/__tests__/utils/isMultipleSelect.test.d.ts.map +0 -1
  240. package/dist/__tests__/utils/isNullOrUndefined.test.d.ts +0 -2
  241. package/dist/__tests__/utils/isNullOrUndefined.test.d.ts.map +0 -1
  242. package/dist/__tests__/utils/isObject.test.d.ts +0 -2
  243. package/dist/__tests__/utils/isObject.test.d.ts.map +0 -1
  244. package/dist/__tests__/utils/isPrimitive.test.d.ts +0 -2
  245. package/dist/__tests__/utils/isPrimitive.test.d.ts.map +0 -1
  246. package/dist/__tests__/utils/isRadioInput.test.d.ts +0 -2
  247. package/dist/__tests__/utils/isRadioInput.test.d.ts.map +0 -1
  248. package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts +0 -2
  249. package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts.map +0 -1
  250. package/dist/__tests__/utils/isRegex.test.d.ts +0 -2
  251. package/dist/__tests__/utils/isRegex.test.d.ts.map +0 -1
  252. package/dist/__tests__/utils/isString.test.d.ts +0 -2
  253. package/dist/__tests__/utils/isString.test.d.ts.map +0 -1
  254. package/dist/__tests__/utils/isUndefined.test.d.ts +0 -2
  255. package/dist/__tests__/utils/isUndefined.test.d.ts.map +0 -1
  256. package/dist/__tests__/utils/live.test.d.ts +0 -2
  257. package/dist/__tests__/utils/live.test.d.ts.map +0 -1
  258. package/dist/__tests__/utils/move.test.d.ts +0 -2
  259. package/dist/__tests__/utils/move.test.d.ts.map +0 -1
  260. package/dist/__tests__/utils/noop.test.d.ts +0 -2
  261. package/dist/__tests__/utils/noop.test.d.ts.map +0 -1
  262. package/dist/__tests__/utils/objectHasFunction.test.d.ts +0 -2
  263. package/dist/__tests__/utils/objectHasFunction.test.d.ts.map +0 -1
  264. package/dist/__tests__/utils/prepend.test.d.ts +0 -2
  265. package/dist/__tests__/utils/prepend.test.d.ts.map +0 -1
  266. package/dist/__tests__/utils/remove.test.d.ts +0 -2
  267. package/dist/__tests__/utils/remove.test.d.ts.map +0 -1
  268. package/dist/__tests__/utils/set.test.d.ts +0 -2
  269. package/dist/__tests__/utils/set.test.d.ts.map +0 -1
  270. package/dist/__tests__/utils/stringToPath.test.d.ts +0 -2
  271. package/dist/__tests__/utils/stringToPath.test.d.ts.map +0 -1
  272. package/dist/__tests__/utils/swap.test.d.ts +0 -2
  273. package/dist/__tests__/utils/swap.test.d.ts.map +0 -1
  274. package/dist/__tests__/utils/unset.test.d.ts +0 -2
  275. package/dist/__tests__/utils/unset.test.d.ts.map +0 -1
  276. package/dist/__tests__/utils/validationModeChecker.test.d.ts +0 -2
  277. package/dist/__tests__/utils/validationModeChecker.test.d.ts.map +0 -1
  278. package/dist/__tests__/watch.server.test.d.ts +0 -2
  279. package/dist/__tests__/watch.server.test.d.ts.map +0 -1
  280. package/dist/__tests__/watch.test.d.ts +0 -2
  281. package/dist/__tests__/watch.test.d.ts.map +0 -1
@@ -10,7 +10,11 @@ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => va
10
10
 
11
11
  const EVENTS = {
12
12
  BLUR: 'blur',
13
- FOCUS_OUT: 'focusout'};
13
+ FOCUS_OUT: 'focusout',
14
+ SUBMIT: 'submit',
15
+ TRIGGER: 'trigger',
16
+ VALID: 'valid',
17
+ };
14
18
  const VALIDATION_MODE = {
15
19
  onBlur: 'onBlur',
16
20
  onChange: 'onChange',
@@ -27,6 +31,8 @@ const INPUT_VALIDATION_RULES = {
27
31
  required: 'required',
28
32
  validate: 'validate',
29
33
  };
34
+ const ROOT_ERROR_TYPE = 'root';
35
+ const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
30
36
 
31
37
  var isDateObject = (value) => value instanceof Date;
32
38
 
@@ -102,7 +108,11 @@ var createSubject = () => {
102
108
 
103
109
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
104
110
 
105
- function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
111
+ const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
112
+ function deepEqual(object1, object2, visited = new WeakMap()) {
113
+ if (object1 === object2) {
114
+ return true;
115
+ }
106
116
  if (isPrimitive(object1) || isPrimitive(object2)) {
107
117
  return Object.is(object1, object2);
108
118
  }
@@ -114,22 +124,36 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
114
124
  if (keys1.length !== keys2.length) {
115
125
  return false;
116
126
  }
117
- if (_internal_visited.has(object1) || _internal_visited.has(object2)) {
127
+ if (isEmptyObjectWithCustomPrototype(object1, keys1) ||
128
+ isEmptyObjectWithCustomPrototype(object2, keys2)) {
129
+ return Object.is(object1, object2);
130
+ }
131
+ if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
132
+ return false;
133
+ }
134
+ const visitedPairs = visited.get(object1);
135
+ if (visitedPairs && visitedPairs.has(object2)) {
118
136
  return true;
119
137
  }
120
- _internal_visited.add(object1);
121
- _internal_visited.add(object2);
138
+ if (visitedPairs) {
139
+ visitedPairs.add(object2);
140
+ }
141
+ else {
142
+ const ws = new WeakSet();
143
+ ws.add(object2);
144
+ visited.set(object1, ws);
145
+ }
122
146
  for (const key of keys1) {
123
147
  const val1 = object1[key];
124
- if (!keys2.includes(key)) {
148
+ if (!(key in object2)) {
125
149
  return false;
126
150
  }
127
151
  if (key !== 'ref') {
128
152
  const val2 = object2[key];
129
153
  if ((isDateObject(val1) && isDateObject(val2)) ||
130
- (isObject(val1) && isObject(val2)) ||
131
- (Array.isArray(val1) && Array.isArray(val2))
132
- ? !deepEqual(val1, val2, _internal_visited)
154
+ ((isObject(val1) || Array.isArray(val1)) &&
155
+ (isObject(val2) || Array.isArray(val2)))
156
+ ? !deepEqual(val1, val2, visited)
133
157
  : !Object.is(val1, val2)) {
134
158
  return false;
135
159
  }
@@ -158,17 +182,43 @@ function extractFormValues(fieldsState, formValues) {
158
182
  return values;
159
183
  }
160
184
 
161
- var isKey = (value) => /^\w*$/.test(value);
185
+ const flatten = (obj) => {
186
+ const output = {};
187
+ for (const key of Object.keys(obj)) {
188
+ if (isObjectType(obj[key]) &&
189
+ obj[key] !== null &&
190
+ !isDateObject(obj[key])) {
191
+ const nested = flatten(obj[key]);
192
+ for (const nestedKey of Object.keys(nested)) {
193
+ output[`${key}.${nestedKey}`] = nested[nestedKey];
194
+ }
195
+ }
196
+ else {
197
+ output[key] = obj[key];
198
+ }
199
+ }
200
+ return output;
201
+ };
202
+
203
+ const IS_KEY_RE = /^\w*$/;
204
+ var isKey = (value) => IS_KEY_RE.test(value);
162
205
 
163
206
  var isUndefined = (val) => val === undefined;
164
207
 
165
- var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
208
+ const FIELD_PATH_RE = /[.[\]'"]/;
209
+ var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
166
210
 
167
211
  var get = (object, path, defaultValue) => {
168
212
  if (!path || !isObject(object)) {
169
213
  return defaultValue;
170
214
  }
171
- const result = (isKey(path) ? [path] : stringToPath(path)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], object);
215
+ const paths = isKey(path) ? [path] : stringToPath(path);
216
+ if (paths.some((key) => PROTOTYPE_KEYWORDS.includes(key))) {
217
+ return defaultValue;
218
+ }
219
+ const result = paths.reduce((result, key) => {
220
+ return isNullOrUndefined(result) ? undefined : result[key];
221
+ }, object);
172
222
  return isUndefined(result) || result === object
173
223
  ? isUndefined(object[path])
174
224
  ? defaultValue
@@ -222,7 +272,7 @@ var set = (object, path, value) => {
222
272
  ? []
223
273
  : {};
224
274
  }
225
- if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
275
+ if (PROTOTYPE_KEYWORDS.includes(key)) {
226
276
  return;
227
277
  }
228
278
  object[key] = newValue;
@@ -234,7 +284,12 @@ function baseGet(object, updatePath) {
234
284
  const length = updatePath.slice(0, -1).length;
235
285
  let index = 0;
236
286
  while (index < length) {
237
- object = isUndefined(object) ? index++ : object[updatePath[index++]];
287
+ if (isNullOrUndefined(object)) {
288
+ object = undefined;
289
+ break;
290
+ }
291
+ object = object[updatePath[index]];
292
+ index++;
238
293
  }
239
294
  return object;
240
295
  }
@@ -247,11 +302,18 @@ function isEmptyArray(obj) {
247
302
  return true;
248
303
  }
249
304
  function unset(object, path) {
305
+ if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
306
+ delete object[path];
307
+ return object;
308
+ }
250
309
  const paths = Array.isArray(path)
251
310
  ? path
252
311
  : isKey(path)
253
312
  ? [path]
254
313
  : stringToPath(path);
314
+ if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
315
+ return object;
316
+ }
255
317
  const childObject = paths.length === 1 ? object : baseGet(object, paths);
256
318
  const index = paths.length - 1;
257
319
  const key = paths[index];
@@ -304,6 +366,29 @@ function markFieldsDirty(data, fields = {}) {
304
366
  }
305
367
  return fields;
306
368
  }
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
+ }
307
392
  function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
308
393
  if (!dirtyFieldsFromValues) {
309
394
  dirtyFieldsFromValues = markFieldsDirty(formValues);
@@ -323,7 +408,7 @@ function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
323
408
  dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
324
409
  }
325
410
  }
326
- return dirtyFieldsFromValues;
411
+ return pruneDirtyFields(dirtyFieldsFromValues) || {};
327
412
  }
328
413
 
329
414
  var getEventValue = (event) => isObject(event) && event.target
@@ -436,12 +521,22 @@ var getValidationModes = (mode) => ({
436
521
  });
437
522
 
438
523
  const ASYNC_FUNCTION = 'AsyncFunction';
439
- var hasPromiseValidation = (fieldReference) => !!fieldReference &&
440
- !!fieldReference.validate &&
441
- !!((isFunction(fieldReference.validate) &&
442
- fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
443
- (isObject(fieldReference.validate) &&
444
- Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
524
+ var hasPromiseValidation = (fieldReference) => {
525
+ if (!fieldReference || !fieldReference.validate)
526
+ return false;
527
+ if (isFunction(fieldReference.validate)) {
528
+ return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
529
+ }
530
+ if (isObject(fieldReference.validate)) {
531
+ for (const key in fieldReference.validate) {
532
+ if (fieldReference.validate[key].constructor
533
+ .name === ASYNC_FUNCTION) {
534
+ return true;
535
+ }
536
+ }
537
+ }
538
+ return false;
539
+ };
445
540
 
446
541
  var hasValidation = (options) => options.mount &&
447
542
  (options.required ||
@@ -452,15 +547,21 @@ var hasValidation = (options) => options.mount &&
452
547
  options.pattern ||
453
548
  options.validate);
454
549
 
455
- var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
456
-
457
- var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
550
+ var isNameInFieldArray = (names, name) => name
551
+ .split('.')
552
+ .some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
458
553
 
459
- var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
460
- (_names.watchAll ||
461
- _names.watch.has(name) ||
462
- [..._names.watch].some((watchName) => name.startsWith(watchName) &&
463
- /^\.\w+/.test(name.slice(watchName.length))));
554
+ var isWatched = (name, _names, isBlurEvent) => {
555
+ if (isBlurEvent)
556
+ return false;
557
+ if (_names.watchAll || _names.watch.has(name))
558
+ return true;
559
+ for (const watchName of _names.watch) {
560
+ if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
561
+ return true;
562
+ }
563
+ return false;
564
+ };
464
565
 
465
566
  const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
466
567
  for (const key of fieldsNames || Object.keys(fields)) {
@@ -528,9 +629,10 @@ function schemaErrorLookup(errors, _fields, name) {
528
629
  var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
529
630
  updateFormState(formStateData);
530
631
  const { name, ...formState } = formStateData;
531
- return (isEmptyObject(formState) ||
532
- Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
533
- Object.keys(formState).find((key) => _proxyFormState[key] ===
632
+ const keys = Object.keys(formState);
633
+ return (!keys.length ||
634
+ (isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
635
+ keys.find((key) => _proxyFormState[key] ===
534
636
  (!isRoot || VALIDATION_MODE.all)));
535
637
  };
536
638
 
@@ -539,7 +641,7 @@ var shouldSubscribeByName = (name, signalName, exact) => !name ||
539
641
  name === signalName ||
540
642
  convertToArrayPayload(name).some((currentName) => currentName &&
541
643
  (exact
542
- ? currentName === signalName
644
+ ? currentName === signalName || currentName.startsWith(signalName + '.')
543
645
  : currentName.startsWith(signalName) ||
544
646
  signalName.startsWith(currentName)));
545
647
 
@@ -562,8 +664,9 @@ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode)
562
664
  var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
563
665
 
564
666
  var updateFieldArrayRootError = (errors, error, name) => {
565
- const fieldArrayErrors = convertToArrayPayload(get(errors, name));
566
- set(fieldArrayErrors, 'root', error[name]);
667
+ const existingErrors = get(errors, name);
668
+ const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
669
+ set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
567
670
  set(errors, name, fieldArrayErrors);
568
671
  return errors;
569
672
  };
@@ -596,7 +699,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
596
699
  const inputRef = refs ? refs[0] : ref;
597
700
  const setCustomValidity = (message) => {
598
701
  if (shouldUseNativeValidation && inputRef.reportValidity) {
599
- inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
702
+ const validityMessage = isBoolean(message) ? '' : message || '';
703
+ if (refs) {
704
+ refs.forEach((ref) => ref.setCustomValidity(validityMessage));
705
+ }
706
+ else {
707
+ inputRef.setCustomValidity(validityMessage);
708
+ }
600
709
  inputRef.reportValidity();
601
710
  }
602
711
  };
@@ -771,24 +880,28 @@ const defaultOptions = {
771
880
  reValidateMode: VALIDATION_MODE.onChange,
772
881
  shouldFocusError: true,
773
882
  };
883
+ const FORM_ERROR_TYPE = 'form';
884
+ const DEFAULT_FORM_STATE = {
885
+ submitCount: 0,
886
+ isDirty: false,
887
+ isReady: false,
888
+ isValidating: false,
889
+ isSubmitted: false,
890
+ isSubmitting: false,
891
+ isSubmitSuccessful: false,
892
+ isValid: false,
893
+ touchedFields: {},
894
+ dirtyFields: {},
895
+ validatingFields: {},
896
+ };
774
897
  function createFormControl(props = {}) {
775
898
  let _options = {
776
899
  ...defaultOptions,
777
900
  ...props,
778
901
  };
779
902
  let _formState = {
780
- submitCount: 0,
781
- isDirty: false,
782
- isReady: false,
903
+ ...cloneObject(DEFAULT_FORM_STATE),
783
904
  isLoading: isFunction(_options.defaultValues),
784
- isValidating: false,
785
- isSubmitted: false,
786
- isSubmitting: false,
787
- isSubmitSuccessful: false,
788
- isValid: false,
789
- touchedFields: {},
790
- dirtyFields: {},
791
- validatingFields: {},
792
905
  errors: _options.errors || {},
793
906
  disabled: _options.disabled || false,
794
907
  };
@@ -811,9 +924,13 @@ function createFormControl(props = {}) {
811
924
  unMount: new Set(),
812
925
  array: new Set(),
813
926
  watch: new Set(),
927
+ registerName: new Set(),
814
928
  };
815
929
  let delayErrorCallback;
816
930
  let timer = 0;
931
+ let _valuesSubscriberCount = 0;
932
+ let _validationModeBeforeSubmit = getValidationModes(_options.mode);
933
+ let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
817
934
  const defaultProxyFormState = {
818
935
  isDirty: false,
819
936
  dirtyFields: false,
@@ -852,7 +969,11 @@ function createFormControl(props = {}) {
852
969
  _updateIsValidating();
853
970
  }
854
971
  else {
855
- isValid = await executeBuiltInValidation(_fields, true);
972
+ isValid = await executeBuiltInValidation({
973
+ fields: _fields,
974
+ onlyCheckValid: true,
975
+ eventType: EVENTS.VALID,
976
+ });
856
977
  }
857
978
  if (isValid !== _formState.isValid) {
858
979
  _subjects.state.next({
@@ -880,6 +1001,9 @@ function createFormControl(props = {}) {
880
1001
  });
881
1002
  }
882
1003
  };
1004
+ const _updateDirtyFields = () => {
1005
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1006
+ };
883
1007
  const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
884
1008
  if (args && method && !_options.disabled) {
885
1009
  _state.action = true;
@@ -901,7 +1025,7 @@ function createFormControl(props = {}) {
901
1025
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
902
1026
  }
903
1027
  if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
904
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1028
+ _updateDirtyFields();
905
1029
  }
906
1030
  _subjects.state.next({
907
1031
  name,
@@ -917,6 +1041,7 @@ function createFormControl(props = {}) {
917
1041
  };
918
1042
  const updateErrors = (name, error) => {
919
1043
  set(_formState.errors, name, error);
1044
+ _formState.errors = { ..._formState.errors };
920
1045
  _subjects.state.next({
921
1046
  errors: _formState.errors,
922
1047
  });
@@ -928,16 +1053,53 @@ function createFormControl(props = {}) {
928
1053
  isValid: false,
929
1054
  });
930
1055
  };
1056
+ const hasExplicitNullIntermediate = (name) => {
1057
+ const segments = isKey(name) ? [name] : stringToPath(name);
1058
+ let formValues = _formValues;
1059
+ let defaultValues = _defaultValues;
1060
+ for (let i = 0; i < segments.length - 1; i++) {
1061
+ const key = segments[i];
1062
+ formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
1063
+ defaultValues = isNullOrUndefined(defaultValues)
1064
+ ? defaultValues
1065
+ : defaultValues[key];
1066
+ if (formValues === null && defaultValues !== null) {
1067
+ return true;
1068
+ }
1069
+ }
1070
+ return false;
1071
+ };
931
1072
  const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
932
1073
  const field = get(_fields, name);
933
1074
  if (field) {
1075
+ if (hasExplicitNullIntermediate(name)) {
1076
+ return;
1077
+ }
1078
+ const wasUnsetInFormValues = isUndefined(get(_formValues, name));
934
1079
  const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
935
1080
  isUndefined(defaultValue) ||
936
1081
  (ref && ref.defaultChecked) ||
937
1082
  shouldSkipSetValueAs
938
1083
  ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
939
1084
  : setFieldValue(name, defaultValue);
940
- _state.mount && !_state.action && _setValid();
1085
+ if (_state.mount && !_state.action) {
1086
+ _setValid();
1087
+ if (wasUnsetInFormValues &&
1088
+ _formState.isDirty &&
1089
+ (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
1090
+ const isDirty = _getDirty();
1091
+ if (!isDirty) {
1092
+ _formState.isDirty = false;
1093
+ _subjects.state.next({ ..._formState });
1094
+ }
1095
+ }
1096
+ if (props.shouldUnregister &&
1097
+ wasUnsetInFormValues &&
1098
+ !isUndefined(get(_formValues, name)) &&
1099
+ isWatched(name, _names)) {
1100
+ _state.watch = true;
1101
+ }
1102
+ }
941
1103
  }
942
1104
  };
943
1105
  const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
@@ -948,16 +1110,22 @@ function createFormControl(props = {}) {
948
1110
  };
949
1111
  if (!_options.disabled) {
950
1112
  if (!isBlurEvent || shouldDirty) {
1113
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
951
1114
  if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
952
1115
  isPreviousDirty = _formState.isDirty;
953
- _formState.isDirty = output.isDirty = _getDirty();
1116
+ _formState.isDirty = output.isDirty =
1117
+ !isCurrentFieldPristine || _getDirty();
954
1118
  shouldUpdateField = isPreviousDirty !== output.isDirty;
955
1119
  }
956
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
957
1120
  isPreviousDirty = !!get(_formState.dirtyFields, name);
958
- isCurrentFieldPristine
959
- ? unset(_formState.dirtyFields, name)
960
- : set(_formState.dirtyFields, name, true);
1121
+ if (isCurrentFieldPristine !== _formState.isDirty) {
1122
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1123
+ }
1124
+ else {
1125
+ isCurrentFieldPristine
1126
+ ? unset(_formState.dirtyFields, name)
1127
+ : set(_formState.dirtyFields, name, true);
1128
+ }
961
1129
  output.dirtyFields = _formState.dirtyFields;
962
1130
  shouldUpdateField =
963
1131
  shouldUpdateField ||
@@ -996,6 +1164,7 @@ function createFormControl(props = {}) {
996
1164
  error
997
1165
  ? set(_formState.errors, name, error)
998
1166
  : unset(_formState.errors, name);
1167
+ _formState.errors = { ..._formState.errors };
999
1168
  }
1000
1169
  if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
1001
1170
  !isEmptyObject(fieldState) ||
@@ -1015,8 +1184,7 @@ function createFormControl(props = {}) {
1015
1184
  };
1016
1185
  const _runSchema = async (name) => {
1017
1186
  _updateIsValidating(name, true);
1018
- const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1019
- return result;
1187
+ return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1020
1188
  };
1021
1189
  const executeSchemaAndUpdateState = async (names) => {
1022
1190
  const { errors } = await _runSchema(names);
@@ -1025,18 +1193,69 @@ function createFormControl(props = {}) {
1025
1193
  for (const name of names) {
1026
1194
  const error = get(errors, name);
1027
1195
  error
1028
- ? set(_formState.errors, name, error)
1196
+ ? _names.array.has(name) &&
1197
+ isObject(error) &&
1198
+ !Object.keys(error).some((key) => !Number.isNaN(Number(key)))
1199
+ ? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
1200
+ : set(_formState.errors, name, error)
1029
1201
  : unset(_formState.errors, name);
1030
1202
  }
1203
+ _formState.errors = { ..._formState.errors };
1031
1204
  }
1032
1205
  else {
1033
1206
  _formState.errors = errors;
1034
1207
  }
1035
1208
  return errors;
1036
1209
  };
1037
- const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
1210
+ const validateForm = async ({ name, eventType, }) => {
1211
+ if (props.validate) {
1212
+ const result = await props.validate({
1213
+ formValues: _formValues,
1214
+ formState: _formState,
1215
+ name,
1216
+ eventType,
1217
+ });
1218
+ if (isObject(result)) {
1219
+ for (const key in result) {
1220
+ const error = result[key];
1221
+ if (error) {
1222
+ setError(`${FORM_ERROR_TYPE}.${key}`, {
1223
+ message: isString(error.message) ? error.message : '',
1224
+ type: error.type || INPUT_VALIDATION_RULES.validate,
1225
+ });
1226
+ }
1227
+ }
1228
+ }
1229
+ else if (isString(result) || !result) {
1230
+ setError(FORM_ERROR_TYPE, {
1231
+ message: result || '',
1232
+ type: INPUT_VALIDATION_RULES.validate,
1233
+ });
1234
+ }
1235
+ else {
1236
+ clearErrors(FORM_ERROR_TYPE);
1237
+ }
1238
+ return result;
1239
+ }
1240
+ return true;
1241
+ };
1242
+ const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
1038
1243
  valid: true,
1039
- }) => {
1244
+ runRootValidation: false,
1245
+ }, }) => {
1246
+ if (props.validate) {
1247
+ context.runRootValidation = true;
1248
+ const result = await validateForm({
1249
+ name,
1250
+ eventType,
1251
+ });
1252
+ if (!result) {
1253
+ context.valid = false;
1254
+ if (onlyCheckValid) {
1255
+ return context.valid;
1256
+ }
1257
+ }
1258
+ }
1040
1259
  for (const name in fields) {
1041
1260
  const field = fields[name];
1042
1261
  if (field) {
@@ -1044,28 +1263,41 @@ function createFormControl(props = {}) {
1044
1263
  if (_f) {
1045
1264
  const isFieldArrayRoot = _names.array.has(_f.name);
1046
1265
  const isPromiseFunction = field._f && hasPromiseValidation(field._f);
1047
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1266
+ const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
1267
+ _proxyFormState.isValidating ||
1268
+ _proxySubscribeFormState.validatingFields ||
1269
+ _proxySubscribeFormState.isValidating;
1270
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1048
1271
  _updateIsValidating([_f.name], true);
1049
1272
  }
1050
- const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1051
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1273
+ const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1274
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1052
1275
  _updateIsValidating([_f.name]);
1053
1276
  }
1054
1277
  if (fieldError[_f.name]) {
1055
1278
  context.valid = false;
1056
- if (shouldOnlyCheckValid || props.shouldUseNativeValidation) {
1279
+ if (onlyCheckValid) {
1057
1280
  break;
1058
1281
  }
1059
1282
  }
1060
- !shouldOnlyCheckValid &&
1283
+ !onlyCheckValid &&
1061
1284
  (get(fieldError, _f.name)
1062
1285
  ? isFieldArrayRoot
1063
1286
  ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
1064
1287
  : set(_formState.errors, _f.name, fieldError[_f.name])
1065
1288
  : unset(_formState.errors, _f.name));
1289
+ if (props.shouldUseNativeValidation && fieldError[_f.name]) {
1290
+ break;
1291
+ }
1066
1292
  }
1067
1293
  !isEmptyObject(fieldValue) &&
1068
- (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
1294
+ (await executeBuiltInValidation({
1295
+ context,
1296
+ onlyCheckValid,
1297
+ fields: fieldValue,
1298
+ name: name,
1299
+ eventType,
1300
+ }));
1069
1301
  }
1070
1302
  }
1071
1303
  return context.valid;
@@ -1083,7 +1315,7 @@ function createFormControl(props = {}) {
1083
1315
  };
1084
1316
  const _getDirty = (name, data) => !_options.disabled &&
1085
1317
  (name && data && set(_formValues, name, data),
1086
- !deepEqual(getValues(), _defaultValues));
1318
+ !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1087
1319
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1088
1320
  ...(_state.mount
1089
1321
  ? _formValues
@@ -1094,7 +1326,7 @@ function createFormControl(props = {}) {
1094
1326
  : defaultValue),
1095
1327
  }, isGlobal, defaultValue);
1096
1328
  const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1097
- const setFieldValue = (name, value, options = {}) => {
1329
+ const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
1098
1330
  const field = get(_fields, name);
1099
1331
  let fieldValue = value;
1100
1332
  if (field) {
@@ -1132,20 +1364,20 @@ function createFormControl(props = {}) {
1132
1364
  }
1133
1365
  else {
1134
1366
  fieldReference.ref.value = fieldValue;
1135
- if (!fieldReference.ref.type) {
1367
+ if (!fieldReference.ref.type && !skipRender) {
1136
1368
  _subjects.state.next({
1137
1369
  name,
1138
- values: cloneObject(_formValues),
1370
+ values: skipClone ? _formValues : cloneObject(_formValues),
1139
1371
  });
1140
1372
  }
1141
1373
  }
1142
1374
  }
1143
1375
  }
1144
1376
  (options.shouldDirty || options.shouldTouch) &&
1145
- updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1377
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
1146
1378
  options.shouldValidate && trigger(name);
1147
1379
  };
1148
- const setValues = (name, value, options) => {
1380
+ const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
1149
1381
  for (const fieldKey in value) {
1150
1382
  if (!value.hasOwnProperty(fieldKey)) {
1151
1383
  return;
@@ -1157,49 +1389,84 @@ function createFormControl(props = {}) {
1157
1389
  isObject(fieldValue) ||
1158
1390
  (field && !field._f)) &&
1159
1391
  !isDateObject(fieldValue)
1160
- ? setValues(fieldName, fieldValue, options)
1161
- : setFieldValue(fieldName, fieldValue, options);
1392
+ ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
1393
+ : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
1162
1394
  }
1163
1395
  };
1164
- const setValue = (name, value, options = {}) => {
1396
+ const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
1165
1397
  const field = get(_fields, name);
1166
1398
  const isFieldArray = _names.array.has(name);
1167
- const cloneValue = cloneObject(value);
1168
- set(_formValues, name, cloneValue);
1399
+ const cloneValue = skipClone ? value : cloneObject(value);
1400
+ const previousValue = get(_formValues, name);
1401
+ const isValueUnchanged = deepEqual(previousValue, cloneValue);
1402
+ if (!isValueUnchanged) {
1403
+ set(_formValues, name, cloneValue);
1404
+ }
1169
1405
  if (isFieldArray) {
1170
1406
  _subjects.array.next({
1171
1407
  name,
1172
- values: cloneObject(_formValues),
1408
+ values: skipClone ? _formValues : cloneObject(_formValues),
1173
1409
  });
1174
1410
  if ((_proxyFormState.isDirty ||
1175
1411
  _proxyFormState.dirtyFields ||
1176
1412
  _proxySubscribeFormState.isDirty ||
1177
1413
  _proxySubscribeFormState.dirtyFields) &&
1178
1414
  options.shouldDirty) {
1179
- _subjects.state.next({
1180
- name,
1181
- dirtyFields: getDirtyFields(_defaultValues, _formValues),
1182
- isDirty: _getDirty(name, cloneValue),
1183
- });
1415
+ _updateDirtyFields();
1416
+ if (!skipStateEmit) {
1417
+ _subjects.state.next({
1418
+ name,
1419
+ dirtyFields: _formState.dirtyFields,
1420
+ isDirty: _getDirty(name, cloneValue),
1421
+ });
1422
+ }
1184
1423
  }
1185
1424
  }
1186
1425
  else {
1187
- field && !field._f && !isNullOrUndefined(cloneValue)
1188
- ? setValues(name, cloneValue, options)
1189
- : setFieldValue(name, cloneValue, options);
1426
+ const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
1427
+ isEmptyObject(cloneValue);
1428
+ if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
1429
+ setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
1430
+ }
1431
+ else {
1432
+ setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
1433
+ }
1190
1434
  }
1191
- if (isWatched(name, _names)) {
1435
+ if (!isValueUnchanged && !skipStateEmit) {
1436
+ const watched = isWatched(name, _names);
1437
+ const values = skipClone ? _formValues : cloneObject(_formValues);
1192
1438
  _subjects.state.next({
1193
- ..._formState,
1194
- name,
1195
- values: cloneObject(_formValues),
1439
+ ...(watched && _formState),
1440
+ name: _state.mount || watched ? name : undefined,
1441
+ values,
1196
1442
  });
1197
1443
  }
1198
- else {
1444
+ };
1445
+ const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
1446
+ const setValues = (formValues, options = {}) => {
1447
+ const updatedFormValues = isFunction(formValues)
1448
+ ? formValues(_formValues)
1449
+ : formValues;
1450
+ if (!deepEqual(_formValues, updatedFormValues)) {
1451
+ _formValues = {
1452
+ ..._formValues,
1453
+ ...updatedFormValues,
1454
+ };
1455
+ const flattenedUpdates = flatten(updatedFormValues);
1456
+ for (const fieldName of _names.mount) {
1457
+ if (fieldName in flattenedUpdates) {
1458
+ _setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
1459
+ }
1460
+ }
1199
1461
  _subjects.state.next({
1200
- name: _state.mount ? name : undefined,
1201
- values: cloneObject(_formValues),
1462
+ ..._formState,
1463
+ name: undefined,
1464
+ type: undefined,
1465
+ ...(_valuesSubscriberCount ? { values: _formValues } : {}),
1202
1466
  });
1467
+ if (options.shouldValidate) {
1468
+ _setValid();
1469
+ }
1203
1470
  }
1204
1471
  };
1205
1472
  const onChange = async (event) => {
@@ -1214,8 +1481,6 @@ function createFormControl(props = {}) {
1214
1481
  (isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
1215
1482
  deepEqual(fieldValue, get(_formValues, name, fieldValue));
1216
1483
  };
1217
- const validationModeBeforeSubmit = getValidationModes(_options.mode);
1218
- const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1219
1484
  if (field) {
1220
1485
  let error;
1221
1486
  let isValid;
@@ -1223,11 +1488,13 @@ function createFormControl(props = {}) {
1223
1488
  ? getFieldValue(field._f)
1224
1489
  : getEventValue(event);
1225
1490
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1226
- const shouldSkipValidation = (!hasValidation(field._f) &&
1491
+ const hasNoValidationEffect = !hasValidation(field._f) &&
1492
+ !props.validate &&
1227
1493
  !_options.resolver &&
1228
1494
  !get(_formState.errors, name) &&
1229
- !field._f.deps) ||
1230
- skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
1495
+ !field._f.deps;
1496
+ const shouldSkipValidation = hasNoValidationEffect ||
1497
+ skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
1231
1498
  const watched = isWatched(name, _names, isBlurEvent);
1232
1499
  set(_formValues, name, fieldValue);
1233
1500
  if (isBlurEvent) {
@@ -1245,10 +1512,13 @@ function createFormControl(props = {}) {
1245
1512
  _subjects.state.next({
1246
1513
  name,
1247
1514
  type: event.type,
1248
- values: cloneObject(_formValues),
1515
+ ...(_valuesSubscriberCount
1516
+ ? { values: cloneObject(_formValues) }
1517
+ : {}),
1249
1518
  });
1250
1519
  if (shouldSkipValidation) {
1251
- if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
1520
+ if ((!hasNoValidationEffect || !_formState.isValid) &&
1521
+ (_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
1252
1522
  if (_options.mode === 'onBlur') {
1253
1523
  if (isBlurEvent) {
1254
1524
  _setValid();
@@ -1261,18 +1531,26 @@ function createFormControl(props = {}) {
1261
1531
  return (shouldRender &&
1262
1532
  _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
1263
1533
  }
1534
+ if (!_options.resolver && props.validate) {
1535
+ await validateForm({
1536
+ name: name,
1537
+ eventType: event.type,
1538
+ });
1539
+ }
1264
1540
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
1265
1541
  if (_options.resolver) {
1266
1542
  const { errors } = await _runSchema([name]);
1267
1543
  _updateIsValidating([name]);
1268
1544
  _updateIsFieldValueUpdated(fieldValue);
1269
- if (isFieldValueUpdated) {
1270
- const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
1271
- const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
1272
- error = errorLookupResult.error;
1273
- name = errorLookupResult.name;
1274
- isValid = isEmptyObject(errors);
1545
+ if (!isFieldValueUpdated) {
1546
+ !isEmptyObject(fieldState) && _subjects.state.next(fieldState);
1547
+ return;
1275
1548
  }
1549
+ const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
1550
+ const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
1551
+ error = errorLookupResult.error;
1552
+ name = errorLookupResult.name;
1553
+ isValid = isEmptyObject(errors);
1276
1554
  }
1277
1555
  else {
1278
1556
  _updateIsValidating([name], true);
@@ -1285,7 +1563,12 @@ function createFormControl(props = {}) {
1285
1563
  }
1286
1564
  else if (_proxyFormState.isValid ||
1287
1565
  _proxySubscribeFormState.isValid) {
1288
- isValid = await executeBuiltInValidation(_fields, true);
1566
+ isValid = await executeBuiltInValidation({
1567
+ fields: _fields,
1568
+ onlyCheckValid: true,
1569
+ name: name,
1570
+ eventType: event.type,
1571
+ });
1289
1572
  }
1290
1573
  }
1291
1574
  }
@@ -1318,12 +1601,19 @@ function createFormControl(props = {}) {
1318
1601
  else if (name) {
1319
1602
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1320
1603
  const field = get(_fields, fieldName);
1321
- return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
1604
+ return await executeBuiltInValidation({
1605
+ fields: field && field._f ? { [fieldName]: field } : field,
1606
+ eventType: EVENTS.TRIGGER,
1607
+ });
1322
1608
  }))).every(Boolean);
1323
1609
  !(!validationResult && !_formState.isValid) && _setValid();
1324
1610
  }
1325
1611
  else {
1326
- validationResult = isValid = await executeBuiltInValidation(_fields);
1612
+ validationResult = isValid = await executeBuiltInValidation({
1613
+ fields: _fields,
1614
+ name,
1615
+ eventType: EVENTS.TRIGGER,
1616
+ });
1327
1617
  }
1328
1618
  _subjects.state.next({
1329
1619
  ...(!isString(name) ||
@@ -1360,16 +1650,25 @@ function createFormControl(props = {}) {
1360
1650
  isTouched: !!get((formState || _formState).touchedFields, name),
1361
1651
  });
1362
1652
  const clearErrors = (name) => {
1363
- name &&
1364
- convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
1365
- _subjects.state.next({
1366
- errors: name ? _formState.errors : {},
1367
- });
1653
+ const names = name ? convertToArrayPayload(name) : undefined;
1654
+ names?.forEach((inputName) => unset(_formState.errors, inputName));
1655
+ if (names) {
1656
+ names.forEach((inputName) => {
1657
+ _subjects.state.next({
1658
+ name: inputName,
1659
+ errors: _formState.errors,
1660
+ });
1661
+ });
1662
+ }
1663
+ else {
1664
+ _subjects.state.next({
1665
+ errors: {},
1666
+ });
1667
+ }
1368
1668
  };
1369
1669
  const setError = (name, error, options) => {
1370
1670
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
1371
1671
  const currentError = get(_formState.errors, name) || {};
1372
- // Don't override existing error messages elsewhere in the object tree.
1373
1672
  const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
1374
1673
  set(_formState.errors, name, {
1375
1674
  ...restOfErrorTree,
@@ -1383,20 +1682,59 @@ function createFormControl(props = {}) {
1383
1682
  });
1384
1683
  options && options.shouldFocus && ref && ref.focus && ref.focus();
1385
1684
  };
1386
- const watch = (name, defaultValue) => _getWatch(name, defaultValue, true);
1387
- const _subscribe = (props) => _subjects.state.subscribe({
1388
- next: (formState) => {
1389
- if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
1390
- shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
1391
- props.callback({
1392
- values: { ..._formValues },
1393
- ..._formState,
1394
- ...formState,
1395
- defaultValues: _defaultValues,
1396
- });
1685
+ const watch = (name, defaultValue) => {
1686
+ if (isFunction(name)) {
1687
+ _valuesSubscriberCount++;
1688
+ const { unsubscribe } = _subjects.state.subscribe({
1689
+ next: (payload) => 'values' in payload &&
1690
+ name(payload.values || _getWatch(undefined, defaultValue), payload),
1691
+ });
1692
+ let called = false;
1693
+ return {
1694
+ unsubscribe: () => {
1695
+ if (called) {
1696
+ return;
1697
+ }
1698
+ called = true;
1699
+ _valuesSubscriberCount--;
1700
+ unsubscribe();
1701
+ },
1702
+ };
1703
+ }
1704
+ return _getWatch(name, defaultValue, true);
1705
+ };
1706
+ const _subscribe = (props) => {
1707
+ const needsValues = !!props.formState?.values;
1708
+ if (needsValues) {
1709
+ _valuesSubscriberCount++;
1710
+ }
1711
+ const { unsubscribe } = _subjects.state.subscribe({
1712
+ next: (formState) => {
1713
+ if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
1714
+ shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
1715
+ const snapshot = { ..._formValues };
1716
+ props.callback({
1717
+ values: snapshot,
1718
+ ..._formState,
1719
+ ...formState,
1720
+ defaultValues: _defaultValues,
1721
+ });
1722
+ }
1723
+ },
1724
+ });
1725
+ if (!needsValues) {
1726
+ return unsubscribe;
1727
+ }
1728
+ let called = false;
1729
+ return () => {
1730
+ if (called) {
1731
+ return;
1397
1732
  }
1398
- },
1399
- }).unsubscribe;
1733
+ called = true;
1734
+ _valuesSubscriberCount--;
1735
+ unsubscribe();
1736
+ };
1737
+ };
1400
1738
  const subscribe = (props) => {
1401
1739
  _state.mount = true;
1402
1740
  _proxySubscribeFormState = {
@@ -1451,6 +1789,7 @@ function createFormControl(props = {}) {
1451
1789
  const register = (name, options = {}) => {
1452
1790
  let field = get(_fields, name);
1453
1791
  const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
1792
+ const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
1454
1793
  set(_fields, name, {
1455
1794
  ...(field || {}),
1456
1795
  _f: {
@@ -1461,7 +1800,7 @@ function createFormControl(props = {}) {
1461
1800
  },
1462
1801
  });
1463
1802
  _names.mount.add(name);
1464
- if (field) {
1803
+ if (field && !shouldRevalidateRemount) {
1465
1804
  _setDisabledField({
1466
1805
  disabled: isBoolean(options.disabled)
1467
1806
  ? options.disabled
@@ -1491,7 +1830,9 @@ function createFormControl(props = {}) {
1491
1830
  onBlur: onChange,
1492
1831
  ref: (ref) => {
1493
1832
  if (ref) {
1833
+ _names.registerName.add(name);
1494
1834
  register(name, options);
1835
+ _names.registerName.delete(name);
1495
1836
  field = get(_fields, name);
1496
1837
  const fieldRef = isUndefined(ref.value)
1497
1838
  ? ref.querySelectorAll
@@ -1535,6 +1876,7 @@ function createFormControl(props = {}) {
1535
1876
  };
1536
1877
  };
1537
1878
  const _focusError = () => _options.shouldFocusError &&
1879
+ !_options.shouldUseNativeValidation &&
1538
1880
  iterateFieldsByAction(_fields, _focusInput, _names.mount);
1539
1881
  const _disableForm = (disabled) => {
1540
1882
  if (isBoolean(disabled)) {
@@ -1570,14 +1912,17 @@ function createFormControl(props = {}) {
1570
1912
  fieldValues = cloneObject(values);
1571
1913
  }
1572
1914
  else {
1573
- await executeBuiltInValidation(_fields);
1915
+ await executeBuiltInValidation({
1916
+ fields: _fields,
1917
+ eventType: EVENTS.SUBMIT,
1918
+ });
1574
1919
  }
1575
1920
  if (_names.disabled.size) {
1576
1921
  for (const name of _names.disabled) {
1577
1922
  unset(fieldValues, name);
1578
1923
  }
1579
1924
  }
1580
- unset(_formState.errors, 'root');
1925
+ unset(_formState.errors, ROOT_ERROR_TYPE);
1581
1926
  if (isEmptyObject(_formState.errors)) {
1582
1927
  _subjects.state.next({
1583
1928
  errors: {},
@@ -1636,7 +1981,7 @@ function createFormControl(props = {}) {
1636
1981
  const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
1637
1982
  const cloneUpdatedValues = cloneObject(updatedValues);
1638
1983
  const isEmptyResetValues = isEmptyObject(formValues);
1639
- const values = isEmptyResetValues ? _defaultValues : cloneUpdatedValues;
1984
+ const values = cloneUpdatedValues;
1640
1985
  if (!keepStateOptions.keepDefaultValues) {
1641
1986
  _defaultValues = updatedValues;
1642
1987
  }
@@ -1685,15 +2030,25 @@ function createFormControl(props = {}) {
1685
2030
  _fields = {};
1686
2031
  }
1687
2032
  }
1688
- _formValues = _options.shouldUnregister
1689
- ? keepStateOptions.keepDefaultValues
2033
+ if (_options.shouldUnregister) {
2034
+ _formValues = keepStateOptions.keepDefaultValues
1690
2035
  ? cloneObject(_defaultValues)
1691
- : {}
1692
- : cloneObject(values);
2036
+ : {};
2037
+ if (keepStateOptions.keepFieldsRef) {
2038
+ for (const fieldName of _names.mount) {
2039
+ set(_formValues, fieldName, get(values, fieldName));
2040
+ }
2041
+ }
2042
+ }
2043
+ else {
2044
+ _formValues = cloneObject(values);
2045
+ }
1693
2046
  _subjects.array.next({
1694
2047
  values: { ...values },
1695
2048
  });
1696
2049
  _subjects.state.next({
2050
+ name: undefined,
2051
+ type: undefined,
1697
2052
  values: { ...values },
1698
2053
  });
1699
2054
  }
@@ -1701,6 +2056,7 @@ function createFormControl(props = {}) {
1701
2056
  mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
1702
2057
  unMount: new Set(),
1703
2058
  array: new Set(),
2059
+ registerName: new Set(),
1704
2060
  disabled: new Set(),
1705
2061
  watch: new Set(),
1706
2062
  watchAll: false,
@@ -1714,9 +2070,6 @@ function createFormControl(props = {}) {
1714
2070
  _state.watch = !!_options.shouldUnregister;
1715
2071
  _state.keepIsValid = !!keepStateOptions.keepIsValid;
1716
2072
  _state.action = false;
1717
- // Clear errors synchronously to prevent validation errors on subsequent submissions
1718
- // This fixes the issue where form.reset() causes validation errors on subsequent
1719
- // submissions in Next.js 16 with Server Actions
1720
2073
  if (!keepStateOptions.keepErrors) {
1721
2074
  _formState.errors = {};
1722
2075
  }
@@ -1728,8 +2081,10 @@ function createFormControl(props = {}) {
1728
2081
  ? false
1729
2082
  : keepStateOptions.keepDirty
1730
2083
  ? _formState.isDirty
1731
- : !!(keepStateOptions.keepDefaultValues &&
1732
- !deepEqual(formValues, _defaultValues)),
2084
+ : keepStateOptions.keepValues
2085
+ ? _getDirty()
2086
+ : !!(keepStateOptions.keepDefaultValues &&
2087
+ !deepEqual(formValues, _defaultValues)),
1733
2088
  isSubmitted: keepStateOptions.keepIsSubmitted
1734
2089
  ? _formState.isSubmitted
1735
2090
  : false,
@@ -1766,8 +2121,6 @@ function createFormControl(props = {}) {
1766
2121
  ? fieldReference.refs[0]
1767
2122
  : fieldReference.ref;
1768
2123
  if (fieldRef.focus) {
1769
- // Use setTimeout to ensure focus happens after any pending state updates
1770
- // This fixes the issue where setFocus doesn't work immediately after setError
1771
2124
  setTimeout(() => {
1772
2125
  fieldRef.focus();
1773
2126
  options.shouldSelect &&
@@ -1778,9 +2131,15 @@ function createFormControl(props = {}) {
1778
2131
  }
1779
2132
  };
1780
2133
  const _setFormState = (updatedFormState) => {
2134
+ // `name`, `type`, and `values` describe the event that produced this
2135
+ // update, not the form's persisted state (they aren't part of
2136
+ // `FormState`). Merging them in would leak a stale `name`/`type` from
2137
+ // one event into a later, unrelated notification that doesn't specify
2138
+ // its own.
2139
+ const { name, type, values, ...formState } = updatedFormState;
1781
2140
  _formState = {
1782
2141
  ..._formState,
1783
- ...updatedFormState,
2142
+ ...formState,
1784
2143
  };
1785
2144
  };
1786
2145
  const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
@@ -1790,6 +2149,21 @@ function createFormControl(props = {}) {
1790
2149
  isLoading: false,
1791
2150
  });
1792
2151
  });
2152
+ const resetDefaultValues = (values, options = {}) => {
2153
+ _defaultValues = cloneObject(values);
2154
+ if (!options.keepDirty) {
2155
+ const newDirtyFields = getDirtyFields(_defaultValues, _formValues);
2156
+ _formState.dirtyFields = newDirtyFields;
2157
+ _formState.isDirty = !isEmptyObject(newDirtyFields);
2158
+ }
2159
+ if (!options.keepIsValid) {
2160
+ _setValid();
2161
+ }
2162
+ _subjects.state.next({
2163
+ ..._formState,
2164
+ defaultValues: _defaultValues,
2165
+ });
2166
+ };
1793
2167
  const methods = {
1794
2168
  control: {
1795
2169
  register,
@@ -1846,6 +2220,8 @@ function createFormControl(props = {}) {
1846
2220
  ..._options,
1847
2221
  ...value,
1848
2222
  };
2223
+ _validationModeBeforeSubmit = getValidationModes(_options.mode);
2224
+ _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1849
2225
  },
1850
2226
  },
1851
2227
  subscribe,
@@ -1854,9 +2230,11 @@ function createFormControl(props = {}) {
1854
2230
  handleSubmit,
1855
2231
  watch,
1856
2232
  setValue,
2233
+ setValues,
1857
2234
  getValues,
1858
2235
  reset,
1859
2236
  resetField,
2237
+ resetDefaultValues,
1860
2238
  clearErrors,
1861
2239
  unregister,
1862
2240
  setError,