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
@@ -18,9 +18,9 @@ var getEventValue = (event) => isObject(event) && event.target
18
18
  : event.target.value
19
19
  : event;
20
20
 
21
- var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
22
-
23
- var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name));
21
+ var isNameInFieldArray = (names, name) => name
22
+ .split('.')
23
+ .some((part, index, arr) => !isNaN(Number(part)) && names.has(arr.slice(0, index).join('.')));
24
24
 
25
25
  var isPlainObject = (tempObject) => {
26
26
  const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype;
@@ -52,19 +52,52 @@ function cloneObject(data) {
52
52
  return copy;
53
53
  }
54
54
 
55
- var isKey = (value) => /^\w*$/.test(value);
55
+ const EVENTS = {
56
+ BLUR: 'blur',
57
+ FOCUS_OUT: 'focusout',
58
+ CHANGE: 'change',
59
+ SUBMIT: 'submit',
60
+ TRIGGER: 'trigger',
61
+ VALID: 'valid',
62
+ };
63
+ const VALIDATION_MODE = {
64
+ onBlur: 'onBlur',
65
+ onChange: 'onChange',
66
+ onSubmit: 'onSubmit',
67
+ onTouched: 'onTouched',
68
+ all: 'all',
69
+ };
70
+ const INPUT_VALIDATION_RULES = {
71
+ max: 'max',
72
+ min: 'min',
73
+ maxLength: 'maxLength',
74
+ minLength: 'minLength',
75
+ pattern: 'pattern',
76
+ required: 'required',
77
+ validate: 'validate',
78
+ };
79
+ const ROOT_ERROR_TYPE = 'root';
80
+ const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
81
+
82
+ const IS_KEY_RE = /^\w*$/;
83
+ var isKey = (value) => IS_KEY_RE.test(value);
56
84
 
57
85
  var isUndefined = (val) => val === undefined;
58
86
 
59
- var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
60
-
61
- var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
87
+ const FIELD_PATH_RE = /[.[\]'"]/;
88
+ var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
62
89
 
63
90
  var get = (object, path, defaultValue) => {
64
91
  if (!path || !isObject(object)) {
65
92
  return defaultValue;
66
93
  }
67
- const result = (isKey(path) ? [path] : stringToPath(path)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], object);
94
+ const paths = isKey(path) ? [path] : stringToPath(path);
95
+ if (paths.some((key) => PROTOTYPE_KEYWORDS.includes(key))) {
96
+ return defaultValue;
97
+ }
98
+ const result = paths.reduce((result, key) => {
99
+ return isNullOrUndefined(result) ? undefined : result[key];
100
+ }, object);
68
101
  return isUndefined(result) || result === object
69
102
  ? isUndefined(object[path])
70
103
  ? defaultValue
@@ -91,7 +124,7 @@ var set = (object, path, value) => {
91
124
  ? []
92
125
  : {};
93
126
  }
94
- if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
127
+ if (PROTOTYPE_KEYWORDS.includes(key)) {
95
128
  return;
96
129
  }
97
130
  object[key] = newValue;
@@ -99,28 +132,6 @@ var set = (object, path, value) => {
99
132
  }
100
133
  };
101
134
 
102
- const EVENTS = {
103
- BLUR: 'blur',
104
- FOCUS_OUT: 'focusout',
105
- CHANGE: 'change',
106
- };
107
- const VALIDATION_MODE = {
108
- onBlur: 'onBlur',
109
- onChange: 'onChange',
110
- onSubmit: 'onSubmit',
111
- onTouched: 'onTouched',
112
- all: 'all',
113
- };
114
- const INPUT_VALIDATION_RULES = {
115
- max: 'max',
116
- min: 'min',
117
- maxLength: 'maxLength',
118
- minLength: 'minLength',
119
- pattern: 'pattern',
120
- required: 'required',
121
- validate: 'validate',
122
- };
123
-
124
135
  /**
125
136
  * Separate context for `control` to prevent unnecessary rerenders.
126
137
  * Internal hooks that only need control use this instead of full form context.
@@ -133,10 +144,7 @@ HookFormControlContext.displayName = 'HookFormControlContext';
133
144
  const useFormControlContext = () => React.useContext(HookFormControlContext);
134
145
 
135
146
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
136
- const result = {
137
- ...formState,
138
- defaultValues: control._defaultValues,
139
- };
147
+ const result = {};
140
148
  for (const key in formState) {
141
149
  Object.defineProperty(result, key, {
142
150
  get: () => {
@@ -152,7 +160,9 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
152
160
  return result;
153
161
  };
154
162
 
155
- const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
163
+ const useIsomorphicLayoutEffect = isWeb
164
+ ? React.useLayoutEffect
165
+ : React.useEffect;
156
166
 
157
167
  /**
158
168
  * This custom hook allows you to subscribe to each form state, and isolate the re-render at the custom hook level. It has its scope in terms of form state subscription, so it would not affect other useFormState and useForm. Using this hook can reduce the re-render impact on large and complex form application.
@@ -187,7 +197,10 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayou
187
197
  function useFormState(props) {
188
198
  const formControl = useFormControlContext();
189
199
  const { control = formControl, disabled, name, exact } = props || {};
190
- const [formState, updateFormState] = React.useState(control._formState);
200
+ const [formState, updateFormState] = React.useState(() => ({
201
+ ...control._formState,
202
+ defaultValues: control._defaultValues,
203
+ }));
191
204
  const _localProxyFormState = React.useRef({
192
205
  isDirty: false,
193
206
  isLoading: false,
@@ -207,6 +220,7 @@ function useFormState(props) {
207
220
  updateFormState({
208
221
  ...control._formState,
209
222
  ...formState,
223
+ defaultValues: control._defaultValues,
210
224
  });
211
225
  },
212
226
  }), [name, disabled, exact]);
@@ -233,7 +247,11 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
233
247
 
234
248
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
235
249
 
236
- function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
250
+ const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
251
+ function deepEqual(object1, object2, visited = new WeakMap()) {
252
+ if (object1 === object2) {
253
+ return true;
254
+ }
237
255
  if (isPrimitive(object1) || isPrimitive(object2)) {
238
256
  return Object.is(object1, object2);
239
257
  }
@@ -245,22 +263,36 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
245
263
  if (keys1.length !== keys2.length) {
246
264
  return false;
247
265
  }
248
- if (_internal_visited.has(object1) || _internal_visited.has(object2)) {
266
+ if (isEmptyObjectWithCustomPrototype(object1, keys1) ||
267
+ isEmptyObjectWithCustomPrototype(object2, keys2)) {
268
+ return Object.is(object1, object2);
269
+ }
270
+ if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
271
+ return false;
272
+ }
273
+ const visitedPairs = visited.get(object1);
274
+ if (visitedPairs && visitedPairs.has(object2)) {
249
275
  return true;
250
276
  }
251
- _internal_visited.add(object1);
252
- _internal_visited.add(object2);
277
+ if (visitedPairs) {
278
+ visitedPairs.add(object2);
279
+ }
280
+ else {
281
+ const ws = new WeakSet();
282
+ ws.add(object2);
283
+ visited.set(object1, ws);
284
+ }
253
285
  for (const key of keys1) {
254
286
  const val1 = object1[key];
255
- if (!keys2.includes(key)) {
287
+ if (!(key in object2)) {
256
288
  return false;
257
289
  }
258
290
  if (key !== 'ref') {
259
291
  const val2 = object2[key];
260
292
  if ((isDateObject(val1) && isDateObject(val2)) ||
261
- (isObject(val1) && isObject(val2)) ||
262
- (Array.isArray(val1) && Array.isArray(val2))
263
- ? !deepEqual(val1, val2, _internal_visited)
293
+ ((isObject(val1) || Array.isArray(val1)) &&
294
+ (isObject(val2) || Array.isArray(val2)))
295
+ ? !deepEqual(val1, val2, visited)
264
296
  : !Object.is(val1, val2)) {
265
297
  return false;
266
298
  }
@@ -396,7 +428,7 @@ function useController(props) {
396
428
  exact,
397
429
  });
398
430
  const _props = React.useRef(props);
399
- const _previousNameRef = React.useRef(undefined);
431
+ const _proxyRef = React.useRef(null);
400
432
  const _registerProps = React.useRef(control.register(name, {
401
433
  ...props.rules,
402
434
  value,
@@ -425,13 +457,22 @@ function useController(props) {
425
457
  get: () => get(formState.errors, name),
426
458
  },
427
459
  }), [formState, name]);
428
- const onChange = React.useCallback((event) => _registerProps.current.onChange({
429
- target: {
430
- value: getEventValue(event),
431
- name: name,
432
- },
433
- type: EVENTS.CHANGE,
434
- }), [name]);
460
+ const onChange = React.useCallback((event) => {
461
+ const value = getEventValue(event);
462
+ if (!get(control._fields, name)) {
463
+ _registerProps.current = control.register(name, {
464
+ ..._props.current.rules,
465
+ value,
466
+ });
467
+ }
468
+ return _registerProps.current.onChange({
469
+ target: {
470
+ value: getEventValue(event),
471
+ name: name,
472
+ },
473
+ type: EVENTS.CHANGE,
474
+ });
475
+ }, [name, control]);
435
476
  const onBlur = React.useCallback(() => _registerProps.current.onBlur({
436
477
  target: {
437
478
  value: get(control._formValues, name),
@@ -440,9 +481,12 @@ function useController(props) {
440
481
  type: EVENTS.BLUR,
441
482
  }), [name, control._formValues]);
442
483
  const ref = React.useCallback((elm) => {
484
+ if (elm) {
485
+ _proxyRef.current = elm;
486
+ }
443
487
  const field = get(control._fields, name);
444
488
  if (field && field._f && elm) {
445
- field._f.ref = elm;
489
+ field._f.ref = _proxyRef.current;
446
490
  }
447
491
  }, [control._fields, name]);
448
492
  const field = React.useMemo(() => ({
@@ -457,10 +501,6 @@ function useController(props) {
457
501
  }), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
458
502
  React.useEffect(() => {
459
503
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
460
- const previousName = _previousNameRef.current;
461
- if (previousName && previousName !== name && !isArrayField) {
462
- control.unregister(previousName);
463
- }
464
504
  control.register(name, {
465
505
  ..._props.current.rules,
466
506
  ...(isBoolean(_props.current.disabled)
@@ -475,14 +515,21 @@ function useController(props) {
475
515
  };
476
516
  updateMounted(name, true);
477
517
  if (_shouldUnregisterField) {
478
- const value = cloneObject(get(control._options.defaultValues, name, _props.current.defaultValue));
518
+ const value = cloneObject(get(shouldUnregister
519
+ ? control._defaultValues
520
+ : control._options.values || control._defaultValues, name, get(control._options.defaultValues, name, _props.current.defaultValue)));
479
521
  set(control._defaultValues, name, value);
480
522
  if (isUndefined(get(control._formValues, name))) {
481
523
  set(control._formValues, name, value);
482
524
  }
483
525
  }
484
526
  !isArrayField && control.register(name);
485
- _previousNameRef.current = name;
527
+ if (_proxyRef.current) {
528
+ const field = get(control._fields, name);
529
+ if (field && field._f) {
530
+ field._f.ref = _proxyRef.current;
531
+ }
532
+ }
486
533
  return () => {
487
534
  (isArrayField
488
535
  ? _shouldUnregisterField && !control._state.action
@@ -551,7 +598,9 @@ const Controller = (props) => props.render(useController(props));
551
598
  const flatten = (obj) => {
552
599
  const output = {};
553
600
  for (const key of Object.keys(obj)) {
554
- if (isObjectType(obj[key]) && obj[key] !== null) {
601
+ if (isObjectType(obj[key]) &&
602
+ obj[key] !== null &&
603
+ !isDateObject(obj[key])) {
555
604
  const nested = flatten(obj[key]);
556
605
  for (const nestedKey of Object.keys(nested)) {
557
606
  output[`${key}.${nestedKey}`] = nested[nestedKey];
@@ -627,44 +676,46 @@ const useFormContext = () => React.useContext(HookFormContext);
627
676
  * }
628
677
  * ```
629
678
  */
630
- const FormProvider = (props) => {
631
- const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, } = props;
632
- return (React.createElement(HookFormContext.Provider, { value: React.useMemo(() => ({
633
- watch,
634
- getValues,
635
- getFieldState,
636
- setError,
637
- clearErrors,
638
- setValue,
639
- trigger,
640
- formState,
641
- resetField,
642
- reset,
643
- handleSubmit,
644
- unregister,
645
- control,
646
- register,
647
- setFocus,
648
- subscribe,
649
- }), [
650
- clearErrors,
651
- control,
652
- formState,
653
- getFieldState,
654
- getValues,
655
- handleSubmit,
656
- register,
657
- reset,
658
- resetField,
659
- setError,
660
- setFocus,
661
- setValue,
662
- subscribe,
663
- trigger,
664
- unregister,
665
- watch,
666
- ]) },
667
- React.createElement(HookFormControlContext.Provider, { value: control }, children)));
679
+ const FormProvider = ({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
680
+ const memoizedValue = React.useMemo(() => ({
681
+ watch,
682
+ getValues,
683
+ getFieldState,
684
+ setError,
685
+ clearErrors,
686
+ setValue,
687
+ setValues,
688
+ trigger,
689
+ formState,
690
+ resetField,
691
+ reset,
692
+ handleSubmit,
693
+ unregister,
694
+ control,
695
+ register,
696
+ setFocus,
697
+ subscribe,
698
+ }), [
699
+ clearErrors,
700
+ control,
701
+ formState,
702
+ getFieldState,
703
+ getValues,
704
+ handleSubmit,
705
+ register,
706
+ reset,
707
+ resetField,
708
+ setError,
709
+ setFocus,
710
+ setValue,
711
+ setValues,
712
+ subscribe,
713
+ trigger,
714
+ unregister,
715
+ watch,
716
+ ]);
717
+ return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
718
+ React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
668
719
  };
669
720
 
670
721
  const POST_REQUEST = 'post';
@@ -694,7 +745,7 @@ function Form(props) {
694
745
  const methods = useFormContext();
695
746
  const [mounted, setMounted] = React.useState(false);
696
747
  const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
697
- const submit = async (event) => {
748
+ const submit = React.useCallback(async (event) => {
698
749
  let hasError = false;
699
750
  let type = '';
700
751
  await control.handleSubmit(async (data) => {
@@ -703,8 +754,8 @@ function Form(props) {
703
754
  try {
704
755
  formDataJson = JSON.stringify(data);
705
756
  }
706
- catch (_a) { }
707
- const flattenFormValues = flatten(control._formValues);
757
+ catch { }
758
+ const flattenFormValues = flatten(data);
708
759
  for (const key in flattenFormValues) {
709
760
  formData.append(key, flattenFormValues[key]);
710
761
  }
@@ -751,15 +802,25 @@ function Form(props) {
751
802
  }
752
803
  }
753
804
  })(event);
754
- if (hasError && props.control) {
755
- props.control._subjects.state.next({
805
+ if (hasError && control) {
806
+ control._subjects.state.next({
756
807
  isSubmitSuccessful: false,
757
808
  });
758
- props.control.setError('root.server', {
809
+ control.setError('root.server', {
759
810
  type,
760
811
  });
761
812
  }
762
- };
813
+ }, [
814
+ control,
815
+ onSubmit,
816
+ method,
817
+ action,
818
+ headers,
819
+ encType,
820
+ validateStatus,
821
+ onError,
822
+ onSuccess,
823
+ ]);
763
824
  React.useEffect(() => {
764
825
  setMounted(true);
765
826
  }, []);
@@ -780,6 +841,8 @@ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => va
780
841
  }
781
842
  : {};
782
843
 
844
+ var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
845
+
783
846
  var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
784
847
 
785
848
  var createSubject = () => {
@@ -857,7 +920,12 @@ function baseGet(object, updatePath) {
857
920
  const length = updatePath.slice(0, -1).length;
858
921
  let index = 0;
859
922
  while (index < length) {
860
- object = isUndefined(object) ? index++ : object[updatePath[index++]];
923
+ if (isNullOrUndefined(object)) {
924
+ object = undefined;
925
+ break;
926
+ }
927
+ object = object[updatePath[index]];
928
+ index++;
861
929
  }
862
930
  return object;
863
931
  }
@@ -870,11 +938,18 @@ function isEmptyArray(obj) {
870
938
  return true;
871
939
  }
872
940
  function unset(object, path) {
941
+ if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
942
+ delete object[path];
943
+ return object;
944
+ }
873
945
  const paths = Array.isArray(path)
874
946
  ? path
875
947
  : isKey(path)
876
948
  ? [path]
877
949
  : stringToPath(path);
950
+ if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
951
+ return object;
952
+ }
878
953
  const childObject = paths.length === 1 ? object : baseGet(object, paths);
879
954
  const index = paths.length - 1;
880
955
  const key = paths[index];
@@ -914,6 +989,29 @@ function markFieldsDirty(data, fields = {}) {
914
989
  }
915
990
  return fields;
916
991
  }
992
+ function pruneDirtyFields(value) {
993
+ if (value === false) {
994
+ return undefined;
995
+ }
996
+ if (value === true) {
997
+ return true;
998
+ }
999
+ if (Array.isArray(value)) {
1000
+ const result = value.map((value) => pruneDirtyFields(value));
1001
+ return (result.some((value) => value !== undefined) ? result : undefined);
1002
+ }
1003
+ if (isObject(value)) {
1004
+ const result = {};
1005
+ for (const key in value) {
1006
+ const pruned = pruneDirtyFields(value[key]);
1007
+ if (!isUndefined(pruned)) {
1008
+ result[key] = pruned;
1009
+ }
1010
+ }
1011
+ return (Object.keys(result).length ? result : undefined);
1012
+ }
1013
+ return undefined;
1014
+ }
917
1015
  function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
918
1016
  if (!dirtyFieldsFromValues) {
919
1017
  dirtyFieldsFromValues = markFieldsDirty(formValues);
@@ -933,7 +1031,7 @@ function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
933
1031
  dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
934
1032
  }
935
1033
  }
936
- return dirtyFieldsFromValues;
1034
+ return pruneDirtyFields(dirtyFieldsFromValues) || {};
937
1035
  }
938
1036
 
939
1037
  const defaultResult = {
@@ -1040,12 +1138,22 @@ var getValidationModes = (mode) => ({
1040
1138
  });
1041
1139
 
1042
1140
  const ASYNC_FUNCTION = 'AsyncFunction';
1043
- var hasPromiseValidation = (fieldReference) => !!fieldReference &&
1044
- !!fieldReference.validate &&
1045
- !!((isFunction(fieldReference.validate) &&
1046
- fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
1047
- (isObject(fieldReference.validate) &&
1048
- Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
1141
+ var hasPromiseValidation = (fieldReference) => {
1142
+ if (!fieldReference || !fieldReference.validate)
1143
+ return false;
1144
+ if (isFunction(fieldReference.validate)) {
1145
+ return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
1146
+ }
1147
+ if (isObject(fieldReference.validate)) {
1148
+ for (const key in fieldReference.validate) {
1149
+ if (fieldReference.validate[key].constructor
1150
+ .name === ASYNC_FUNCTION) {
1151
+ return true;
1152
+ }
1153
+ }
1154
+ }
1155
+ return false;
1156
+ };
1049
1157
 
1050
1158
  var hasValidation = (options) => options.mount &&
1051
1159
  (options.required ||
@@ -1056,11 +1164,17 @@ var hasValidation = (options) => options.mount &&
1056
1164
  options.pattern ||
1057
1165
  options.validate);
1058
1166
 
1059
- var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
1060
- (_names.watchAll ||
1061
- _names.watch.has(name) ||
1062
- [..._names.watch].some((watchName) => name.startsWith(watchName) &&
1063
- /^\.\w+/.test(name.slice(watchName.length))));
1167
+ var isWatched = (name, _names, isBlurEvent) => {
1168
+ if (isBlurEvent)
1169
+ return false;
1170
+ if (_names.watchAll || _names.watch.has(name))
1171
+ return true;
1172
+ for (const watchName of _names.watch) {
1173
+ if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
1174
+ return true;
1175
+ }
1176
+ return false;
1177
+ };
1064
1178
 
1065
1179
  const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
1066
1180
  for (const key of fieldsNames || Object.keys(fields)) {
@@ -1128,9 +1242,10 @@ function schemaErrorLookup(errors, _fields, name) {
1128
1242
  var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
1129
1243
  updateFormState(formStateData);
1130
1244
  const { name, ...formState } = formStateData;
1131
- return (isEmptyObject(formState) ||
1132
- Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
1133
- Object.keys(formState).find((key) => _proxyFormState[key] ===
1245
+ const keys = Object.keys(formState);
1246
+ return (!keys.length ||
1247
+ (isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
1248
+ keys.find((key) => _proxyFormState[key] ===
1134
1249
  (!isRoot || VALIDATION_MODE.all)));
1135
1250
  };
1136
1251
 
@@ -1139,7 +1254,7 @@ var shouldSubscribeByName = (name, signalName, exact) => !name ||
1139
1254
  name === signalName ||
1140
1255
  convertToArrayPayload(name).some((currentName) => currentName &&
1141
1256
  (exact
1142
- ? currentName === signalName
1257
+ ? currentName === signalName || currentName.startsWith(signalName + '.')
1143
1258
  : currentName.startsWith(signalName) ||
1144
1259
  signalName.startsWith(currentName)));
1145
1260
 
@@ -1162,8 +1277,9 @@ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode)
1162
1277
  var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
1163
1278
 
1164
1279
  var updateFieldArrayRootError = (errors, error, name) => {
1165
- const fieldArrayErrors = convertToArrayPayload(get(errors, name));
1166
- set(fieldArrayErrors, 'root', error[name]);
1280
+ const existingErrors = get(errors, name);
1281
+ const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
1282
+ set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
1167
1283
  set(errors, name, fieldArrayErrors);
1168
1284
  return errors;
1169
1285
  };
@@ -1196,7 +1312,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
1196
1312
  const inputRef = refs ? refs[0] : ref;
1197
1313
  const setCustomValidity = (message) => {
1198
1314
  if (shouldUseNativeValidation && inputRef.reportValidity) {
1199
- inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
1315
+ const validityMessage = isBoolean(message) ? '' : message || '';
1316
+ if (refs) {
1317
+ refs.forEach((ref) => ref.setCustomValidity(validityMessage));
1318
+ }
1319
+ else {
1320
+ inputRef.setCustomValidity(validityMessage);
1321
+ }
1200
1322
  inputRef.reportValidity();
1201
1323
  }
1202
1324
  };
@@ -1371,24 +1493,28 @@ const defaultOptions = {
1371
1493
  reValidateMode: VALIDATION_MODE.onChange,
1372
1494
  shouldFocusError: true,
1373
1495
  };
1496
+ const FORM_ERROR_TYPE = 'form';
1497
+ const DEFAULT_FORM_STATE = {
1498
+ submitCount: 0,
1499
+ isDirty: false,
1500
+ isReady: false,
1501
+ isValidating: false,
1502
+ isSubmitted: false,
1503
+ isSubmitting: false,
1504
+ isSubmitSuccessful: false,
1505
+ isValid: false,
1506
+ touchedFields: {},
1507
+ dirtyFields: {},
1508
+ validatingFields: {},
1509
+ };
1374
1510
  function createFormControl(props = {}) {
1375
1511
  let _options = {
1376
1512
  ...defaultOptions,
1377
1513
  ...props,
1378
1514
  };
1379
1515
  let _formState = {
1380
- submitCount: 0,
1381
- isDirty: false,
1382
- isReady: false,
1516
+ ...cloneObject(DEFAULT_FORM_STATE),
1383
1517
  isLoading: isFunction(_options.defaultValues),
1384
- isValidating: false,
1385
- isSubmitted: false,
1386
- isSubmitting: false,
1387
- isSubmitSuccessful: false,
1388
- isValid: false,
1389
- touchedFields: {},
1390
- dirtyFields: {},
1391
- validatingFields: {},
1392
1518
  errors: _options.errors || {},
1393
1519
  disabled: _options.disabled || false,
1394
1520
  };
@@ -1411,9 +1537,13 @@ function createFormControl(props = {}) {
1411
1537
  unMount: new Set(),
1412
1538
  array: new Set(),
1413
1539
  watch: new Set(),
1540
+ registerName: new Set(),
1414
1541
  };
1415
1542
  let delayErrorCallback;
1416
1543
  let timer = 0;
1544
+ let _valuesSubscriberCount = 0;
1545
+ let _validationModeBeforeSubmit = getValidationModes(_options.mode);
1546
+ let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1417
1547
  const defaultProxyFormState = {
1418
1548
  isDirty: false,
1419
1549
  dirtyFields: false,
@@ -1452,7 +1582,11 @@ function createFormControl(props = {}) {
1452
1582
  _updateIsValidating();
1453
1583
  }
1454
1584
  else {
1455
- isValid = await executeBuiltInValidation(_fields, true);
1585
+ isValid = await executeBuiltInValidation({
1586
+ fields: _fields,
1587
+ onlyCheckValid: true,
1588
+ eventType: EVENTS.VALID,
1589
+ });
1456
1590
  }
1457
1591
  if (isValid !== _formState.isValid) {
1458
1592
  _subjects.state.next({
@@ -1480,6 +1614,9 @@ function createFormControl(props = {}) {
1480
1614
  });
1481
1615
  }
1482
1616
  };
1617
+ const _updateDirtyFields = () => {
1618
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1619
+ };
1483
1620
  const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1484
1621
  if (args && method && !_options.disabled) {
1485
1622
  _state.action = true;
@@ -1501,7 +1638,7 @@ function createFormControl(props = {}) {
1501
1638
  shouldSetValues && set(_formState.touchedFields, name, touchedFields);
1502
1639
  }
1503
1640
  if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
1504
- _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1641
+ _updateDirtyFields();
1505
1642
  }
1506
1643
  _subjects.state.next({
1507
1644
  name,
@@ -1517,6 +1654,7 @@ function createFormControl(props = {}) {
1517
1654
  };
1518
1655
  const updateErrors = (name, error) => {
1519
1656
  set(_formState.errors, name, error);
1657
+ _formState.errors = { ..._formState.errors };
1520
1658
  _subjects.state.next({
1521
1659
  errors: _formState.errors,
1522
1660
  });
@@ -1528,16 +1666,53 @@ function createFormControl(props = {}) {
1528
1666
  isValid: false,
1529
1667
  });
1530
1668
  };
1669
+ const hasExplicitNullIntermediate = (name) => {
1670
+ const segments = isKey(name) ? [name] : stringToPath(name);
1671
+ let formValues = _formValues;
1672
+ let defaultValues = _defaultValues;
1673
+ for (let i = 0; i < segments.length - 1; i++) {
1674
+ const key = segments[i];
1675
+ formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
1676
+ defaultValues = isNullOrUndefined(defaultValues)
1677
+ ? defaultValues
1678
+ : defaultValues[key];
1679
+ if (formValues === null && defaultValues !== null) {
1680
+ return true;
1681
+ }
1682
+ }
1683
+ return false;
1684
+ };
1531
1685
  const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
1532
1686
  const field = get(_fields, name);
1533
1687
  if (field) {
1688
+ if (hasExplicitNullIntermediate(name)) {
1689
+ return;
1690
+ }
1691
+ const wasUnsetInFormValues = isUndefined(get(_formValues, name));
1534
1692
  const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
1535
1693
  isUndefined(defaultValue) ||
1536
1694
  (ref && ref.defaultChecked) ||
1537
1695
  shouldSkipSetValueAs
1538
1696
  ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
1539
1697
  : setFieldValue(name, defaultValue);
1540
- _state.mount && !_state.action && _setValid();
1698
+ if (_state.mount && !_state.action) {
1699
+ _setValid();
1700
+ if (wasUnsetInFormValues &&
1701
+ _formState.isDirty &&
1702
+ (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
1703
+ const isDirty = _getDirty();
1704
+ if (!isDirty) {
1705
+ _formState.isDirty = false;
1706
+ _subjects.state.next({ ..._formState });
1707
+ }
1708
+ }
1709
+ if (props.shouldUnregister &&
1710
+ wasUnsetInFormValues &&
1711
+ !isUndefined(get(_formValues, name)) &&
1712
+ isWatched(name, _names)) {
1713
+ _state.watch = true;
1714
+ }
1715
+ }
1541
1716
  }
1542
1717
  };
1543
1718
  const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
@@ -1548,16 +1723,22 @@ function createFormControl(props = {}) {
1548
1723
  };
1549
1724
  if (!_options.disabled) {
1550
1725
  if (!isBlurEvent || shouldDirty) {
1726
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1551
1727
  if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
1552
1728
  isPreviousDirty = _formState.isDirty;
1553
- _formState.isDirty = output.isDirty = _getDirty();
1729
+ _formState.isDirty = output.isDirty =
1730
+ !isCurrentFieldPristine || _getDirty();
1554
1731
  shouldUpdateField = isPreviousDirty !== output.isDirty;
1555
1732
  }
1556
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1557
1733
  isPreviousDirty = !!get(_formState.dirtyFields, name);
1558
- isCurrentFieldPristine
1559
- ? unset(_formState.dirtyFields, name)
1560
- : set(_formState.dirtyFields, name, true);
1734
+ if (isCurrentFieldPristine !== _formState.isDirty) {
1735
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues);
1736
+ }
1737
+ else {
1738
+ isCurrentFieldPristine
1739
+ ? unset(_formState.dirtyFields, name)
1740
+ : set(_formState.dirtyFields, name, true);
1741
+ }
1561
1742
  output.dirtyFields = _formState.dirtyFields;
1562
1743
  shouldUpdateField =
1563
1744
  shouldUpdateField ||
@@ -1596,6 +1777,7 @@ function createFormControl(props = {}) {
1596
1777
  error
1597
1778
  ? set(_formState.errors, name, error)
1598
1779
  : unset(_formState.errors, name);
1780
+ _formState.errors = { ..._formState.errors };
1599
1781
  }
1600
1782
  if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
1601
1783
  !isEmptyObject(fieldState) ||
@@ -1615,8 +1797,7 @@ function createFormControl(props = {}) {
1615
1797
  };
1616
1798
  const _runSchema = async (name) => {
1617
1799
  _updateIsValidating(name, true);
1618
- const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1619
- return result;
1800
+ return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1620
1801
  };
1621
1802
  const executeSchemaAndUpdateState = async (names) => {
1622
1803
  const { errors } = await _runSchema(names);
@@ -1625,18 +1806,69 @@ function createFormControl(props = {}) {
1625
1806
  for (const name of names) {
1626
1807
  const error = get(errors, name);
1627
1808
  error
1628
- ? set(_formState.errors, name, error)
1809
+ ? _names.array.has(name) &&
1810
+ isObject(error) &&
1811
+ !Object.keys(error).some((key) => !Number.isNaN(Number(key)))
1812
+ ? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
1813
+ : set(_formState.errors, name, error)
1629
1814
  : unset(_formState.errors, name);
1630
1815
  }
1816
+ _formState.errors = { ..._formState.errors };
1631
1817
  }
1632
1818
  else {
1633
1819
  _formState.errors = errors;
1634
1820
  }
1635
1821
  return errors;
1636
1822
  };
1637
- const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = {
1823
+ const validateForm = async ({ name, eventType, }) => {
1824
+ if (props.validate) {
1825
+ const result = await props.validate({
1826
+ formValues: _formValues,
1827
+ formState: _formState,
1828
+ name,
1829
+ eventType,
1830
+ });
1831
+ if (isObject(result)) {
1832
+ for (const key in result) {
1833
+ const error = result[key];
1834
+ if (error) {
1835
+ setError(`${FORM_ERROR_TYPE}.${key}`, {
1836
+ message: isString(error.message) ? error.message : '',
1837
+ type: error.type || INPUT_VALIDATION_RULES.validate,
1838
+ });
1839
+ }
1840
+ }
1841
+ }
1842
+ else if (isString(result) || !result) {
1843
+ setError(FORM_ERROR_TYPE, {
1844
+ message: result || '',
1845
+ type: INPUT_VALIDATION_RULES.validate,
1846
+ });
1847
+ }
1848
+ else {
1849
+ clearErrors(FORM_ERROR_TYPE);
1850
+ }
1851
+ return result;
1852
+ }
1853
+ return true;
1854
+ };
1855
+ const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
1638
1856
  valid: true,
1639
- }) => {
1857
+ runRootValidation: false,
1858
+ }, }) => {
1859
+ if (props.validate) {
1860
+ context.runRootValidation = true;
1861
+ const result = await validateForm({
1862
+ name,
1863
+ eventType,
1864
+ });
1865
+ if (!result) {
1866
+ context.valid = false;
1867
+ if (onlyCheckValid) {
1868
+ return context.valid;
1869
+ }
1870
+ }
1871
+ }
1640
1872
  for (const name in fields) {
1641
1873
  const field = fields[name];
1642
1874
  if (field) {
@@ -1644,28 +1876,41 @@ function createFormControl(props = {}) {
1644
1876
  if (_f) {
1645
1877
  const isFieldArrayRoot = _names.array.has(_f.name);
1646
1878
  const isPromiseFunction = field._f && hasPromiseValidation(field._f);
1647
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1879
+ const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
1880
+ _proxyFormState.isValidating ||
1881
+ _proxySubscribeFormState.validatingFields ||
1882
+ _proxySubscribeFormState.isValidating;
1883
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1648
1884
  _updateIsValidating([_f.name], true);
1649
1885
  }
1650
- const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot);
1651
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1886
+ const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1887
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
1652
1888
  _updateIsValidating([_f.name]);
1653
1889
  }
1654
1890
  if (fieldError[_f.name]) {
1655
1891
  context.valid = false;
1656
- if (shouldOnlyCheckValid || props.shouldUseNativeValidation) {
1892
+ if (onlyCheckValid) {
1657
1893
  break;
1658
1894
  }
1659
1895
  }
1660
- !shouldOnlyCheckValid &&
1896
+ !onlyCheckValid &&
1661
1897
  (get(fieldError, _f.name)
1662
1898
  ? isFieldArrayRoot
1663
1899
  ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
1664
1900
  : set(_formState.errors, _f.name, fieldError[_f.name])
1665
1901
  : unset(_formState.errors, _f.name));
1902
+ if (props.shouldUseNativeValidation && fieldError[_f.name]) {
1903
+ break;
1904
+ }
1666
1905
  }
1667
1906
  !isEmptyObject(fieldValue) &&
1668
- (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context));
1907
+ (await executeBuiltInValidation({
1908
+ context,
1909
+ onlyCheckValid,
1910
+ fields: fieldValue,
1911
+ name: name,
1912
+ eventType,
1913
+ }));
1669
1914
  }
1670
1915
  }
1671
1916
  return context.valid;
@@ -1683,7 +1928,7 @@ function createFormControl(props = {}) {
1683
1928
  };
1684
1929
  const _getDirty = (name, data) => !_options.disabled &&
1685
1930
  (name && data && set(_formValues, name, data),
1686
- !deepEqual(getValues(), _defaultValues));
1931
+ !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1687
1932
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1688
1933
  ...(_state.mount
1689
1934
  ? _formValues
@@ -1694,7 +1939,7 @@ function createFormControl(props = {}) {
1694
1939
  : defaultValue),
1695
1940
  }, isGlobal, defaultValue);
1696
1941
  const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1697
- const setFieldValue = (name, value, options = {}) => {
1942
+ const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
1698
1943
  const field = get(_fields, name);
1699
1944
  let fieldValue = value;
1700
1945
  if (field) {
@@ -1732,20 +1977,20 @@ function createFormControl(props = {}) {
1732
1977
  }
1733
1978
  else {
1734
1979
  fieldReference.ref.value = fieldValue;
1735
- if (!fieldReference.ref.type) {
1980
+ if (!fieldReference.ref.type && !skipRender) {
1736
1981
  _subjects.state.next({
1737
1982
  name,
1738
- values: cloneObject(_formValues),
1983
+ values: skipClone ? _formValues : cloneObject(_formValues),
1739
1984
  });
1740
1985
  }
1741
1986
  }
1742
1987
  }
1743
1988
  }
1744
1989
  (options.shouldDirty || options.shouldTouch) &&
1745
- updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1990
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
1746
1991
  options.shouldValidate && trigger(name);
1747
1992
  };
1748
- const setValues = (name, value, options) => {
1993
+ const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
1749
1994
  for (const fieldKey in value) {
1750
1995
  if (!value.hasOwnProperty(fieldKey)) {
1751
1996
  return;
@@ -1757,49 +2002,84 @@ function createFormControl(props = {}) {
1757
2002
  isObject(fieldValue) ||
1758
2003
  (field && !field._f)) &&
1759
2004
  !isDateObject(fieldValue)
1760
- ? setValues(fieldName, fieldValue, options)
1761
- : setFieldValue(fieldName, fieldValue, options);
2005
+ ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
2006
+ : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
1762
2007
  }
1763
2008
  };
1764
- const setValue = (name, value, options = {}) => {
2009
+ const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
1765
2010
  const field = get(_fields, name);
1766
2011
  const isFieldArray = _names.array.has(name);
1767
- const cloneValue = cloneObject(value);
1768
- set(_formValues, name, cloneValue);
2012
+ const cloneValue = skipClone ? value : cloneObject(value);
2013
+ const previousValue = get(_formValues, name);
2014
+ const isValueUnchanged = deepEqual(previousValue, cloneValue);
2015
+ if (!isValueUnchanged) {
2016
+ set(_formValues, name, cloneValue);
2017
+ }
1769
2018
  if (isFieldArray) {
1770
2019
  _subjects.array.next({
1771
2020
  name,
1772
- values: cloneObject(_formValues),
2021
+ values: skipClone ? _formValues : cloneObject(_formValues),
1773
2022
  });
1774
2023
  if ((_proxyFormState.isDirty ||
1775
2024
  _proxyFormState.dirtyFields ||
1776
2025
  _proxySubscribeFormState.isDirty ||
1777
2026
  _proxySubscribeFormState.dirtyFields) &&
1778
2027
  options.shouldDirty) {
1779
- _subjects.state.next({
1780
- name,
1781
- dirtyFields: getDirtyFields(_defaultValues, _formValues),
1782
- isDirty: _getDirty(name, cloneValue),
1783
- });
2028
+ _updateDirtyFields();
2029
+ if (!skipStateEmit) {
2030
+ _subjects.state.next({
2031
+ name,
2032
+ dirtyFields: _formState.dirtyFields,
2033
+ isDirty: _getDirty(name, cloneValue),
2034
+ });
2035
+ }
1784
2036
  }
1785
2037
  }
1786
2038
  else {
1787
- field && !field._f && !isNullOrUndefined(cloneValue)
1788
- ? setValues(name, cloneValue, options)
1789
- : setFieldValue(name, cloneValue, options);
2039
+ const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
2040
+ isEmptyObject(cloneValue);
2041
+ if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
2042
+ setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
2043
+ }
2044
+ else {
2045
+ setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
2046
+ }
1790
2047
  }
1791
- if (isWatched(name, _names)) {
2048
+ if (!isValueUnchanged && !skipStateEmit) {
2049
+ const watched = isWatched(name, _names);
2050
+ const values = skipClone ? _formValues : cloneObject(_formValues);
1792
2051
  _subjects.state.next({
1793
- ..._formState,
1794
- name,
1795
- values: cloneObject(_formValues),
2052
+ ...(watched && _formState),
2053
+ name: _state.mount || watched ? name : undefined,
2054
+ values,
1796
2055
  });
1797
2056
  }
1798
- else {
2057
+ };
2058
+ const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
2059
+ const setValues = (formValues, options = {}) => {
2060
+ const updatedFormValues = isFunction(formValues)
2061
+ ? formValues(_formValues)
2062
+ : formValues;
2063
+ if (!deepEqual(_formValues, updatedFormValues)) {
2064
+ _formValues = {
2065
+ ..._formValues,
2066
+ ...updatedFormValues,
2067
+ };
2068
+ const flattenedUpdates = flatten(updatedFormValues);
2069
+ for (const fieldName of _names.mount) {
2070
+ if (fieldName in flattenedUpdates) {
2071
+ _setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
2072
+ }
2073
+ }
1799
2074
  _subjects.state.next({
1800
- name: _state.mount ? name : undefined,
1801
- values: cloneObject(_formValues),
2075
+ ..._formState,
2076
+ name: undefined,
2077
+ type: undefined,
2078
+ ...(_valuesSubscriberCount ? { values: _formValues } : {}),
1802
2079
  });
2080
+ if (options.shouldValidate) {
2081
+ _setValid();
2082
+ }
1803
2083
  }
1804
2084
  };
1805
2085
  const onChange = async (event) => {
@@ -1814,8 +2094,6 @@ function createFormControl(props = {}) {
1814
2094
  (isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
1815
2095
  deepEqual(fieldValue, get(_formValues, name, fieldValue));
1816
2096
  };
1817
- const validationModeBeforeSubmit = getValidationModes(_options.mode);
1818
- const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1819
2097
  if (field) {
1820
2098
  let error;
1821
2099
  let isValid;
@@ -1823,11 +2101,13 @@ function createFormControl(props = {}) {
1823
2101
  ? getFieldValue(field._f)
1824
2102
  : getEventValue(event);
1825
2103
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1826
- const shouldSkipValidation = (!hasValidation(field._f) &&
2104
+ const hasNoValidationEffect = !hasValidation(field._f) &&
2105
+ !props.validate &&
1827
2106
  !_options.resolver &&
1828
2107
  !get(_formState.errors, name) &&
1829
- !field._f.deps) ||
1830
- skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
2108
+ !field._f.deps;
2109
+ const shouldSkipValidation = hasNoValidationEffect ||
2110
+ skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
1831
2111
  const watched = isWatched(name, _names, isBlurEvent);
1832
2112
  set(_formValues, name, fieldValue);
1833
2113
  if (isBlurEvent) {
@@ -1845,10 +2125,13 @@ function createFormControl(props = {}) {
1845
2125
  _subjects.state.next({
1846
2126
  name,
1847
2127
  type: event.type,
1848
- values: cloneObject(_formValues),
2128
+ ...(_valuesSubscriberCount
2129
+ ? { values: cloneObject(_formValues) }
2130
+ : {}),
1849
2131
  });
1850
2132
  if (shouldSkipValidation) {
1851
- if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
2133
+ if ((!hasNoValidationEffect || !_formState.isValid) &&
2134
+ (_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
1852
2135
  if (_options.mode === 'onBlur') {
1853
2136
  if (isBlurEvent) {
1854
2137
  _setValid();
@@ -1861,18 +2144,26 @@ function createFormControl(props = {}) {
1861
2144
  return (shouldRender &&
1862
2145
  _subjects.state.next({ name, ...(watched ? {} : fieldState) }));
1863
2146
  }
2147
+ if (!_options.resolver && props.validate) {
2148
+ await validateForm({
2149
+ name: name,
2150
+ eventType: event.type,
2151
+ });
2152
+ }
1864
2153
  !isBlurEvent && watched && _subjects.state.next({ ..._formState });
1865
2154
  if (_options.resolver) {
1866
2155
  const { errors } = await _runSchema([name]);
1867
2156
  _updateIsValidating([name]);
1868
2157
  _updateIsFieldValueUpdated(fieldValue);
1869
- if (isFieldValueUpdated) {
1870
- const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
1871
- const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
1872
- error = errorLookupResult.error;
1873
- name = errorLookupResult.name;
1874
- isValid = isEmptyObject(errors);
2158
+ if (!isFieldValueUpdated) {
2159
+ !isEmptyObject(fieldState) && _subjects.state.next(fieldState);
2160
+ return;
1875
2161
  }
2162
+ const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
2163
+ const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
2164
+ error = errorLookupResult.error;
2165
+ name = errorLookupResult.name;
2166
+ isValid = isEmptyObject(errors);
1876
2167
  }
1877
2168
  else {
1878
2169
  _updateIsValidating([name], true);
@@ -1885,7 +2176,12 @@ function createFormControl(props = {}) {
1885
2176
  }
1886
2177
  else if (_proxyFormState.isValid ||
1887
2178
  _proxySubscribeFormState.isValid) {
1888
- isValid = await executeBuiltInValidation(_fields, true);
2179
+ isValid = await executeBuiltInValidation({
2180
+ fields: _fields,
2181
+ onlyCheckValid: true,
2182
+ name: name,
2183
+ eventType: event.type,
2184
+ });
1889
2185
  }
1890
2186
  }
1891
2187
  }
@@ -1918,12 +2214,19 @@ function createFormControl(props = {}) {
1918
2214
  else if (name) {
1919
2215
  validationResult = (await Promise.all(fieldNames.map(async (fieldName) => {
1920
2216
  const field = get(_fields, fieldName);
1921
- return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field);
2217
+ return await executeBuiltInValidation({
2218
+ fields: field && field._f ? { [fieldName]: field } : field,
2219
+ eventType: EVENTS.TRIGGER,
2220
+ });
1922
2221
  }))).every(Boolean);
1923
2222
  !(!validationResult && !_formState.isValid) && _setValid();
1924
2223
  }
1925
2224
  else {
1926
- validationResult = isValid = await executeBuiltInValidation(_fields);
2225
+ validationResult = isValid = await executeBuiltInValidation({
2226
+ fields: _fields,
2227
+ name,
2228
+ eventType: EVENTS.TRIGGER,
2229
+ });
1927
2230
  }
1928
2231
  _subjects.state.next({
1929
2232
  ...(!isString(name) ||
@@ -1960,16 +2263,25 @@ function createFormControl(props = {}) {
1960
2263
  isTouched: !!get((formState || _formState).touchedFields, name),
1961
2264
  });
1962
2265
  const clearErrors = (name) => {
1963
- name &&
1964
- convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName));
1965
- _subjects.state.next({
1966
- errors: name ? _formState.errors : {},
1967
- });
2266
+ const names = name ? convertToArrayPayload(name) : undefined;
2267
+ names?.forEach((inputName) => unset(_formState.errors, inputName));
2268
+ if (names) {
2269
+ names.forEach((inputName) => {
2270
+ _subjects.state.next({
2271
+ name: inputName,
2272
+ errors: _formState.errors,
2273
+ });
2274
+ });
2275
+ }
2276
+ else {
2277
+ _subjects.state.next({
2278
+ errors: {},
2279
+ });
2280
+ }
1968
2281
  };
1969
2282
  const setError = (name, error, options) => {
1970
2283
  const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
1971
2284
  const currentError = get(_formState.errors, name) || {};
1972
- // Don't override existing error messages elsewhere in the object tree.
1973
2285
  const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
1974
2286
  set(_formState.errors, name, {
1975
2287
  ...restOfErrorTree,
@@ -1983,20 +2295,59 @@ function createFormControl(props = {}) {
1983
2295
  });
1984
2296
  options && options.shouldFocus && ref && ref.focus && ref.focus();
1985
2297
  };
1986
- const watch = (name, defaultValue) => _getWatch(name, defaultValue, true);
1987
- const _subscribe = (props) => _subjects.state.subscribe({
1988
- next: (formState) => {
1989
- if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
1990
- shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
1991
- props.callback({
1992
- values: { ..._formValues },
1993
- ..._formState,
1994
- ...formState,
1995
- defaultValues: _defaultValues,
1996
- });
2298
+ const watch = (name, defaultValue) => {
2299
+ if (isFunction(name)) {
2300
+ _valuesSubscriberCount++;
2301
+ const { unsubscribe } = _subjects.state.subscribe({
2302
+ next: (payload) => 'values' in payload &&
2303
+ name(payload.values || _getWatch(undefined, defaultValue), payload),
2304
+ });
2305
+ let called = false;
2306
+ return {
2307
+ unsubscribe: () => {
2308
+ if (called) {
2309
+ return;
2310
+ }
2311
+ called = true;
2312
+ _valuesSubscriberCount--;
2313
+ unsubscribe();
2314
+ },
2315
+ };
2316
+ }
2317
+ return _getWatch(name, defaultValue, true);
2318
+ };
2319
+ const _subscribe = (props) => {
2320
+ const needsValues = !!props.formState?.values;
2321
+ if (needsValues) {
2322
+ _valuesSubscriberCount++;
2323
+ }
2324
+ const { unsubscribe } = _subjects.state.subscribe({
2325
+ next: (formState) => {
2326
+ if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
2327
+ shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
2328
+ const snapshot = { ..._formValues };
2329
+ props.callback({
2330
+ values: snapshot,
2331
+ ..._formState,
2332
+ ...formState,
2333
+ defaultValues: _defaultValues,
2334
+ });
2335
+ }
2336
+ },
2337
+ });
2338
+ if (!needsValues) {
2339
+ return unsubscribe;
2340
+ }
2341
+ let called = false;
2342
+ return () => {
2343
+ if (called) {
2344
+ return;
1997
2345
  }
1998
- },
1999
- }).unsubscribe;
2346
+ called = true;
2347
+ _valuesSubscriberCount--;
2348
+ unsubscribe();
2349
+ };
2350
+ };
2000
2351
  const subscribe = (props) => {
2001
2352
  _state.mount = true;
2002
2353
  _proxySubscribeFormState = {
@@ -2051,6 +2402,7 @@ function createFormControl(props = {}) {
2051
2402
  const register = (name, options = {}) => {
2052
2403
  let field = get(_fields, name);
2053
2404
  const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
2405
+ const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
2054
2406
  set(_fields, name, {
2055
2407
  ...(field || {}),
2056
2408
  _f: {
@@ -2061,7 +2413,7 @@ function createFormControl(props = {}) {
2061
2413
  },
2062
2414
  });
2063
2415
  _names.mount.add(name);
2064
- if (field) {
2416
+ if (field && !shouldRevalidateRemount) {
2065
2417
  _setDisabledField({
2066
2418
  disabled: isBoolean(options.disabled)
2067
2419
  ? options.disabled
@@ -2091,7 +2443,9 @@ function createFormControl(props = {}) {
2091
2443
  onBlur: onChange,
2092
2444
  ref: (ref) => {
2093
2445
  if (ref) {
2446
+ _names.registerName.add(name);
2094
2447
  register(name, options);
2448
+ _names.registerName.delete(name);
2095
2449
  field = get(_fields, name);
2096
2450
  const fieldRef = isUndefined(ref.value)
2097
2451
  ? ref.querySelectorAll
@@ -2135,6 +2489,7 @@ function createFormControl(props = {}) {
2135
2489
  };
2136
2490
  };
2137
2491
  const _focusError = () => _options.shouldFocusError &&
2492
+ !_options.shouldUseNativeValidation &&
2138
2493
  iterateFieldsByAction(_fields, _focusInput, _names.mount);
2139
2494
  const _disableForm = (disabled) => {
2140
2495
  if (isBoolean(disabled)) {
@@ -2170,14 +2525,17 @@ function createFormControl(props = {}) {
2170
2525
  fieldValues = cloneObject(values);
2171
2526
  }
2172
2527
  else {
2173
- await executeBuiltInValidation(_fields);
2528
+ await executeBuiltInValidation({
2529
+ fields: _fields,
2530
+ eventType: EVENTS.SUBMIT,
2531
+ });
2174
2532
  }
2175
2533
  if (_names.disabled.size) {
2176
2534
  for (const name of _names.disabled) {
2177
2535
  unset(fieldValues, name);
2178
2536
  }
2179
2537
  }
2180
- unset(_formState.errors, 'root');
2538
+ unset(_formState.errors, ROOT_ERROR_TYPE);
2181
2539
  if (isEmptyObject(_formState.errors)) {
2182
2540
  _subjects.state.next({
2183
2541
  errors: {},
@@ -2236,7 +2594,7 @@ function createFormControl(props = {}) {
2236
2594
  const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
2237
2595
  const cloneUpdatedValues = cloneObject(updatedValues);
2238
2596
  const isEmptyResetValues = isEmptyObject(formValues);
2239
- const values = isEmptyResetValues ? _defaultValues : cloneUpdatedValues;
2597
+ const values = cloneUpdatedValues;
2240
2598
  if (!keepStateOptions.keepDefaultValues) {
2241
2599
  _defaultValues = updatedValues;
2242
2600
  }
@@ -2285,15 +2643,25 @@ function createFormControl(props = {}) {
2285
2643
  _fields = {};
2286
2644
  }
2287
2645
  }
2288
- _formValues = _options.shouldUnregister
2289
- ? keepStateOptions.keepDefaultValues
2646
+ if (_options.shouldUnregister) {
2647
+ _formValues = keepStateOptions.keepDefaultValues
2290
2648
  ? cloneObject(_defaultValues)
2291
- : {}
2292
- : cloneObject(values);
2649
+ : {};
2650
+ if (keepStateOptions.keepFieldsRef) {
2651
+ for (const fieldName of _names.mount) {
2652
+ set(_formValues, fieldName, get(values, fieldName));
2653
+ }
2654
+ }
2655
+ }
2656
+ else {
2657
+ _formValues = cloneObject(values);
2658
+ }
2293
2659
  _subjects.array.next({
2294
2660
  values: { ...values },
2295
2661
  });
2296
2662
  _subjects.state.next({
2663
+ name: undefined,
2664
+ type: undefined,
2297
2665
  values: { ...values },
2298
2666
  });
2299
2667
  }
@@ -2301,6 +2669,7 @@ function createFormControl(props = {}) {
2301
2669
  mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
2302
2670
  unMount: new Set(),
2303
2671
  array: new Set(),
2672
+ registerName: new Set(),
2304
2673
  disabled: new Set(),
2305
2674
  watch: new Set(),
2306
2675
  watchAll: false,
@@ -2314,9 +2683,6 @@ function createFormControl(props = {}) {
2314
2683
  _state.watch = !!_options.shouldUnregister;
2315
2684
  _state.keepIsValid = !!keepStateOptions.keepIsValid;
2316
2685
  _state.action = false;
2317
- // Clear errors synchronously to prevent validation errors on subsequent submissions
2318
- // This fixes the issue where form.reset() causes validation errors on subsequent
2319
- // submissions in Next.js 16 with Server Actions
2320
2686
  if (!keepStateOptions.keepErrors) {
2321
2687
  _formState.errors = {};
2322
2688
  }
@@ -2328,8 +2694,10 @@ function createFormControl(props = {}) {
2328
2694
  ? false
2329
2695
  : keepStateOptions.keepDirty
2330
2696
  ? _formState.isDirty
2331
- : !!(keepStateOptions.keepDefaultValues &&
2332
- !deepEqual(formValues, _defaultValues)),
2697
+ : keepStateOptions.keepValues
2698
+ ? _getDirty()
2699
+ : !!(keepStateOptions.keepDefaultValues &&
2700
+ !deepEqual(formValues, _defaultValues)),
2333
2701
  isSubmitted: keepStateOptions.keepIsSubmitted
2334
2702
  ? _formState.isSubmitted
2335
2703
  : false,
@@ -2366,8 +2734,6 @@ function createFormControl(props = {}) {
2366
2734
  ? fieldReference.refs[0]
2367
2735
  : fieldReference.ref;
2368
2736
  if (fieldRef.focus) {
2369
- // Use setTimeout to ensure focus happens after any pending state updates
2370
- // This fixes the issue where setFocus doesn't work immediately after setError
2371
2737
  setTimeout(() => {
2372
2738
  fieldRef.focus();
2373
2739
  options.shouldSelect &&
@@ -2378,9 +2744,15 @@ function createFormControl(props = {}) {
2378
2744
  }
2379
2745
  };
2380
2746
  const _setFormState = (updatedFormState) => {
2747
+ // `name`, `type`, and `values` describe the event that produced this
2748
+ // update, not the form's persisted state (they aren't part of
2749
+ // `FormState`). Merging them in would leak a stale `name`/`type` from
2750
+ // one event into a later, unrelated notification that doesn't specify
2751
+ // its own.
2752
+ const { name, type, values, ...formState } = updatedFormState;
2381
2753
  _formState = {
2382
2754
  ..._formState,
2383
- ...updatedFormState,
2755
+ ...formState,
2384
2756
  };
2385
2757
  };
2386
2758
  const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
@@ -2390,6 +2762,21 @@ function createFormControl(props = {}) {
2390
2762
  isLoading: false,
2391
2763
  });
2392
2764
  });
2765
+ const resetDefaultValues = (values, options = {}) => {
2766
+ _defaultValues = cloneObject(values);
2767
+ if (!options.keepDirty) {
2768
+ const newDirtyFields = getDirtyFields(_defaultValues, _formValues);
2769
+ _formState.dirtyFields = newDirtyFields;
2770
+ _formState.isDirty = !isEmptyObject(newDirtyFields);
2771
+ }
2772
+ if (!options.keepIsValid) {
2773
+ _setValid();
2774
+ }
2775
+ _subjects.state.next({
2776
+ ..._formState,
2777
+ defaultValues: _defaultValues,
2778
+ });
2779
+ };
2393
2780
  const methods = {
2394
2781
  control: {
2395
2782
  register,
@@ -2446,6 +2833,8 @@ function createFormControl(props = {}) {
2446
2833
  ..._options,
2447
2834
  ...value,
2448
2835
  };
2836
+ _validationModeBeforeSubmit = getValidationModes(_options.mode);
2837
+ _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
2449
2838
  },
2450
2839
  },
2451
2840
  subscribe,
@@ -2454,9 +2843,11 @@ function createFormControl(props = {}) {
2454
2843
  handleSubmit,
2455
2844
  watch,
2456
2845
  setValue,
2846
+ setValues,
2457
2847
  getValues,
2458
2848
  reset,
2459
2849
  resetField,
2850
+ resetDefaultValues,
2460
2851
  clearErrors,
2461
2852
  unregister,
2462
2853
  setError,
@@ -2577,30 +2968,45 @@ var updateAt = (fieldValues, index, value) => {
2577
2968
  */
2578
2969
  function useFieldArray(props) {
2579
2970
  const formControl = useFormControlContext();
2580
- const { control = formControl, name, shouldUnregister, rules } = props;
2971
+ const { control = formControl, name, shouldUnregister, rules, disabled, } = props;
2581
2972
  const [fields, setFields] = React.useState(control._getFieldArray(name));
2582
2973
  const ids = React.useRef(control._getFieldArray(name).map(generateId));
2583
2974
  const _actioned = React.useRef(false);
2584
- control._names.array.add(name);
2585
- React.useMemo(() => rules &&
2975
+ if (!disabled) {
2976
+ control._names.array.add(name);
2977
+ }
2978
+ React.useMemo(() => !disabled &&
2979
+ rules &&
2586
2980
  fields.length >= 0 &&
2587
- control.register(name, rules), [control, name, fields.length, rules]);
2588
- useIsomorphicLayoutEffect(() => control._subjects.array.subscribe({
2589
- next: ({ values, name: fieldArrayName, }) => {
2590
- if (fieldArrayName === name || !fieldArrayName) {
2591
- const fieldValues = get(values, name);
2592
- if (Array.isArray(fieldValues)) {
2593
- setFields(fieldValues);
2594
- ids.current = fieldValues.map(generateId);
2981
+ control.register(name, rules), [control, name, fields.length, rules, disabled]);
2982
+ useIsomorphicLayoutEffect(() => {
2983
+ if (disabled) {
2984
+ return;
2985
+ }
2986
+ return control._subjects.array.subscribe({
2987
+ next: ({ values, name: fieldArrayName, }) => {
2988
+ if (fieldArrayName === name || !fieldArrayName) {
2989
+ const fieldValues = get(values, name);
2990
+ if (Array.isArray(fieldValues)) {
2991
+ setFields(fieldValues);
2992
+ ids.current = fieldValues.map(generateId);
2993
+ }
2994
+ else if (!fieldArrayName) {
2995
+ setFields([]);
2996
+ ids.current = [];
2997
+ }
2595
2998
  }
2596
- }
2597
- },
2598
- }).unsubscribe, [control, name]);
2999
+ },
3000
+ }).unsubscribe;
3001
+ }, [control, name, disabled]);
2599
3002
  const updateValues = React.useCallback((updatedFieldArrayValues) => {
2600
3003
  _actioned.current = true;
2601
3004
  control._setFieldArray(name, updatedFieldArrayValues);
2602
3005
  }, [control, name]);
2603
3006
  const append = (value, options) => {
3007
+ if (disabled) {
3008
+ return;
3009
+ }
2604
3010
  const appendValue = convertToArrayPayload(cloneObject(value));
2605
3011
  const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
2606
3012
  control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
@@ -2612,6 +3018,9 @@ function useFieldArray(props) {
2612
3018
  });
2613
3019
  };
2614
3020
  const prepend = (value, options) => {
3021
+ if (disabled) {
3022
+ return;
3023
+ }
2615
3024
  const prependValue = convertToArrayPayload(cloneObject(value));
2616
3025
  const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
2617
3026
  control._names.focus = getFocusFieldName(name, 0, options);
@@ -2623,6 +3032,9 @@ function useFieldArray(props) {
2623
3032
  });
2624
3033
  };
2625
3034
  const remove = (index) => {
3035
+ if (disabled) {
3036
+ return;
3037
+ }
2626
3038
  const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
2627
3039
  ids.current = removeArrayAt(ids.current, index);
2628
3040
  updateValues(updatedFieldArrayValues);
@@ -2634,6 +3046,9 @@ function useFieldArray(props) {
2634
3046
  });
2635
3047
  };
2636
3048
  const insert$1 = (index, value, options) => {
3049
+ if (disabled) {
3050
+ return;
3051
+ }
2637
3052
  const insertValue = convertToArrayPayload(cloneObject(value));
2638
3053
  const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
2639
3054
  control._names.focus = getFocusFieldName(name, index, options);
@@ -2646,6 +3061,9 @@ function useFieldArray(props) {
2646
3061
  });
2647
3062
  };
2648
3063
  const swap = (indexA, indexB) => {
3064
+ if (disabled) {
3065
+ return;
3066
+ }
2649
3067
  const updatedFieldArrayValues = control._getFieldArray(name);
2650
3068
  swapArrayAt(updatedFieldArrayValues, indexA, indexB);
2651
3069
  swapArrayAt(ids.current, indexA, indexB);
@@ -2657,6 +3075,9 @@ function useFieldArray(props) {
2657
3075
  }, false);
2658
3076
  };
2659
3077
  const move = (from, to) => {
3078
+ if (disabled) {
3079
+ return;
3080
+ }
2660
3081
  const updatedFieldArrayValues = control._getFieldArray(name);
2661
3082
  moveArrayAt(updatedFieldArrayValues, from, to);
2662
3083
  moveArrayAt(ids.current, from, to);
@@ -2668,6 +3089,9 @@ function useFieldArray(props) {
2668
3089
  }, false);
2669
3090
  };
2670
3091
  const update = (index, value) => {
3092
+ if (disabled) {
3093
+ return;
3094
+ }
2671
3095
  const updateValue = cloneObject(value);
2672
3096
  const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
2673
3097
  ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
@@ -2679,6 +3103,9 @@ function useFieldArray(props) {
2679
3103
  }, true, false);
2680
3104
  };
2681
3105
  const replace = (value) => {
3106
+ if (disabled) {
3107
+ return;
3108
+ }
2682
3109
  const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
2683
3110
  ids.current = updatedFieldArrayValues.map(generateId);
2684
3111
  updateValues([...updatedFieldArrayValues]);
@@ -2686,29 +3113,42 @@ function useFieldArray(props) {
2686
3113
  control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
2687
3114
  };
2688
3115
  React.useEffect(() => {
3116
+ if (disabled) {
3117
+ return;
3118
+ }
2689
3119
  control._state.action = false;
2690
3120
  isWatched(name, control._names) &&
2691
3121
  control._subjects.state.next({
2692
3122
  ...control._formState,
2693
3123
  });
3124
+ const validationModes = getValidationModes(control._options.mode);
2694
3125
  if (_actioned.current &&
2695
- (!getValidationModes(control._options.mode).isOnSubmit ||
2696
- control._formState.isSubmitted) &&
2697
- !getValidationModes(control._options.reValidateMode).isOnSubmit) {
3126
+ (!validationModes.isOnSubmit || control._formState.isSubmitted) &&
3127
+ !getValidationModes(control._options.reValidateMode).isOnSubmit &&
3128
+ !validationModes.isOnBlur) {
2698
3129
  if (control._options.resolver) {
2699
3130
  control._runSchema([name]).then((result) => {
2700
3131
  control._updateIsValidating([name]);
2701
3132
  const error = get(result.errors, name);
2702
3133
  const existingError = get(control._formState.errors, name);
3134
+ const existingErrorType = existingError && (existingError.type || existingError.root?.type);
3135
+ const existingErrorMessage = existingError &&
3136
+ (existingError.message || existingError.root?.message);
2703
3137
  if (existingError
2704
- ? (!error && existingError.type) ||
3138
+ ? (!error && existingErrorType) ||
2705
3139
  (error &&
2706
- (existingError.type !== error.type ||
2707
- existingError.message !== error.message))
3140
+ (existingErrorType !== error.type ||
3141
+ existingErrorMessage !== error.message))
2708
3142
  : error && error.type) {
2709
- error
2710
- ? set(control._formState.errors, name, error)
2711
- : unset(control._formState.errors, name);
3143
+ if (error) {
3144
+ isObject(error) &&
3145
+ !Object.keys(error).some((key) => !Number.isNaN(+key))
3146
+ ? updateFieldArrayRootError(control._formState.errors, { [name]: error }, name)
3147
+ : set(control._formState.errors, name, error);
3148
+ }
3149
+ else {
3150
+ unset(control._formState.errors, name);
3151
+ }
2712
3152
  control._subjects.state.next({
2713
3153
  errors: control._formState.errors,
2714
3154
  });
@@ -2728,10 +3168,14 @@ function useFieldArray(props) {
2728
3168
  }
2729
3169
  }
2730
3170
  }
2731
- control._subjects.state.next({
2732
- name,
2733
- values: cloneObject(control._formValues),
2734
- });
3171
+ // External updates that change `fields` (e.g. reset() or setValue() on
3172
+ // the array) already notify subscribers with the up-to-date values
3173
+ // themselves, so only re-broadcast here for genuine array method calls.
3174
+ _actioned.current &&
3175
+ control._subjects.state.next({
3176
+ name,
3177
+ values: cloneObject(control._formValues),
3178
+ });
2735
3179
  control._names.focus &&
2736
3180
  iterateFieldsByAction(control._fields, (ref, key) => {
2737
3181
  if (control._names.focus &&
@@ -2745,34 +3189,57 @@ function useFieldArray(props) {
2745
3189
  control._names.focus = '';
2746
3190
  control._setValid();
2747
3191
  _actioned.current = false;
2748
- }, [fields, name, control]);
3192
+ }, [fields, name, control, disabled]);
2749
3193
  React.useEffect(() => {
2750
- !get(control._formValues, name) && control._setFieldArray(name);
3194
+ if (!disabled) {
3195
+ !get(control._formValues, name) && control._setFieldArray(name);
3196
+ }
2751
3197
  return () => {
3198
+ if (disabled) {
3199
+ return;
3200
+ }
3201
+ const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
2752
3202
  const updateMounted = (name, value) => {
2753
3203
  const field = get(control._fields, name);
2754
3204
  if (field && field._f) {
2755
3205
  field._f.mount = value;
2756
3206
  }
2757
3207
  };
2758
- control._options.shouldUnregister || shouldUnregister
2759
- ? control.unregister(name)
2760
- : updateMounted(name, false);
3208
+ if (_actioned.current && shouldKeepFieldArrayValues) {
3209
+ control._subjects.state.next({
3210
+ name,
3211
+ values: cloneObject(control._formValues),
3212
+ });
3213
+ }
3214
+ shouldKeepFieldArrayValues
3215
+ ? updateMounted(name, false)
3216
+ : control.unregister(name);
2761
3217
  };
2762
- }, [name, control, shouldUnregister]);
3218
+ }, [name, control, shouldUnregister, disabled]);
2763
3219
  return {
2764
- swap: React.useCallback(swap, [updateValues, name, control]),
2765
- move: React.useCallback(move, [updateValues, name, control]),
2766
- prepend: React.useCallback(prepend, [updateValues, name, control]),
2767
- append: React.useCallback(append, [updateValues, name, control]),
2768
- remove: React.useCallback(remove, [updateValues, name, control]),
2769
- insert: React.useCallback(insert$1, [updateValues, name, control]),
2770
- update: React.useCallback(update, [updateValues, name, control]),
2771
- replace: React.useCallback(replace, [updateValues, name, control]),
3220
+ swap: React.useCallback(swap, [updateValues, name, control, disabled]),
3221
+ move: React.useCallback(move, [updateValues, name, control, disabled]),
3222
+ prepend: React.useCallback(prepend, [
3223
+ updateValues,
3224
+ name,
3225
+ control,
3226
+ disabled,
3227
+ ]),
3228
+ append: React.useCallback(append, [updateValues, name, control, disabled]),
3229
+ remove: React.useCallback(remove, [updateValues, name, control, disabled]),
3230
+ insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
3231
+ update: React.useCallback(update, [updateValues, name, control, disabled]),
3232
+ replace: React.useCallback(replace, [
3233
+ updateValues,
3234
+ name,
3235
+ control,
3236
+ disabled,
3237
+ ]),
2772
3238
  fields: React.useMemo(() => fields.map((field, index) => ({
2773
3239
  ...field,
3240
+ ...(isBoolean(disabled) ? { disabled } : {}),
2774
3241
  key: ids.current[index] || generateId(),
2775
- })), [fields]),
3242
+ })), [fields, disabled]),
2776
3243
  };
2777
3244
  }
2778
3245
 
@@ -2819,26 +3286,19 @@ function updateMethodsReference(_formControl) {
2819
3286
  function useForm(props = {}) {
2820
3287
  const _formControl = React.useRef(undefined);
2821
3288
  const _values = React.useRef(undefined);
2822
- const [formState, updateFormState] = React.useState({
2823
- isDirty: false,
2824
- isValidating: false,
3289
+ const _formControlProp = React.useRef(props.formControl);
3290
+ const [formState, updateFormState] = React.useState(() => ({
3291
+ ...cloneObject(DEFAULT_FORM_STATE),
2825
3292
  isLoading: isFunction(props.defaultValues),
2826
- isSubmitted: false,
2827
- isSubmitting: false,
2828
- isSubmitSuccessful: false,
2829
- isValid: false,
2830
- submitCount: 0,
2831
- dirtyFields: {},
2832
- touchedFields: {},
2833
- validatingFields: {},
2834
3293
  errors: props.errors || {},
2835
3294
  disabled: props.disabled || false,
2836
- isReady: false,
2837
3295
  defaultValues: isFunction(props.defaultValues)
2838
3296
  ? undefined
2839
3297
  : props.defaultValues,
2840
- });
2841
- if (!_formControl.current) {
3298
+ }));
3299
+ if (!_formControl.current ||
3300
+ (props.formControl && _formControlProp.current !== props.formControl)) {
3301
+ _formControlProp.current = props.formControl;
2842
3302
  if (props.formControl) {
2843
3303
  _formControl.current = {
2844
3304
  ...props.formControl,
@@ -2861,7 +3321,10 @@ function useForm(props = {}) {
2861
3321
  useIsomorphicLayoutEffect(() => {
2862
3322
  const sub = control._subscribe({
2863
3323
  formState: control._proxyFormState,
2864
- callback: () => updateFormState({ ...control._formState }),
3324
+ callback: () => updateFormState({
3325
+ ...control._formState,
3326
+ defaultValues: control._defaultValues,
3327
+ }),
2865
3328
  reRenderRoot: true,
2866
3329
  });
2867
3330
  updateFormState((data) => ({
@@ -2903,14 +3366,13 @@ function useForm(props = {}) {
2903
3366
  }
2904
3367
  }, [control, formState.isDirty]);
2905
3368
  React.useEffect(() => {
2906
- var _a;
2907
3369
  if (props.values && !deepEqual(props.values, _values.current)) {
2908
3370
  updateMethodsReference(_formControl);
2909
3371
  control._reset(props.values, {
2910
3372
  keepFieldsRef: true,
2911
3373
  ...control._options.resetOptions,
2912
3374
  });
2913
- if (!((_a = control._options.resetOptions) === null || _a === void 0 ? void 0 : _a.keepIsValid)) {
3375
+ if (!control._options.resetOptions?.keepIsValid) {
2914
3376
  control._setValid();
2915
3377
  }
2916
3378
  _values.current = props.values;