@depup/react-hook-form 7.72.1-depup.0 → 7.83.0-depup.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (297) hide show
  1. package/README.md +2 -2
  2. package/changes.json +1 -1
  3. package/dist/constants.d.ts +1 -1
  4. package/dist/constants.d.ts.map +1 -1
  5. package/dist/fieldArray.d.ts +36 -0
  6. package/dist/fieldArray.d.ts.map +1 -0
  7. package/dist/form.d.ts.map +1 -1
  8. package/dist/index.cjs.js +1 -1
  9. package/dist/index.cjs.js.map +1 -1
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.esm.mjs +2271 -1847
  13. package/dist/index.esm.mjs.map +1 -1
  14. package/dist/index.umd.js +1 -1
  15. package/dist/index.umd.js.map +1 -1
  16. package/dist/logic/createFormControl.d.ts +13 -0
  17. package/dist/logic/createFormControl.d.ts.map +1 -1
  18. package/dist/logic/getDirtyFields.d.ts +3 -2
  19. package/dist/logic/getDirtyFields.d.ts.map +1 -1
  20. package/dist/logic/getEventValue.d.ts.map +1 -1
  21. package/dist/logic/getNodeParentName.d.ts.map +1 -1
  22. package/dist/logic/getProxyFormState.d.ts.map +1 -1
  23. package/dist/logic/getResolverOptions.d.ts +2 -2
  24. package/dist/logic/getValueAndMessage.d.ts +1 -4
  25. package/dist/logic/getValueAndMessage.d.ts.map +1 -1
  26. package/dist/logic/hasPromiseValidation.d.ts.map +1 -1
  27. package/dist/logic/hasValidation.d.ts +1 -1
  28. package/dist/logic/index.d.ts +2 -3
  29. package/dist/logic/index.d.ts.map +1 -1
  30. package/dist/logic/isWatched.d.ts.map +1 -1
  31. package/dist/logic/shouldRenderFormState.d.ts.map +1 -1
  32. package/dist/logic/skipValidation.d.ts +1 -4
  33. package/dist/logic/skipValidation.d.ts.map +1 -1
  34. package/dist/logic/updateFieldArrayRootError.d.ts.map +1 -1
  35. package/dist/logic/validateField.d.ts.map +1 -1
  36. package/dist/react-server.esm.mjs +480 -179
  37. package/dist/react-server.esm.mjs.map +1 -1
  38. package/dist/types/errors.d.ts +2 -2
  39. package/dist/types/errors.d.ts.map +1 -1
  40. package/dist/types/fieldArray.d.ts +25 -1
  41. package/dist/types/fieldArray.d.ts.map +1 -1
  42. package/dist/types/form.d.ts +80 -56
  43. package/dist/types/form.d.ts.map +1 -1
  44. package/dist/types/path/common.d.ts +6 -0
  45. package/dist/types/path/common.d.ts.map +1 -1
  46. package/dist/types/path/eager.d.ts +15 -11
  47. package/dist/types/path/eager.d.ts.map +1 -1
  48. package/dist/types/utils.d.ts +4 -4
  49. package/dist/types/utils.d.ts.map +1 -1
  50. package/dist/types/validator.d.ts +1 -1
  51. package/dist/types/validator.d.ts.map +1 -1
  52. package/dist/types/watch.d.ts +1 -1
  53. package/dist/types/watch.d.ts.map +1 -1
  54. package/dist/useController.d.ts.map +1 -1
  55. package/dist/useFieldArray.d.ts.map +1 -1
  56. package/dist/useForm.d.ts.map +1 -1
  57. package/dist/useFormContext.d.ts +1 -1
  58. package/dist/useFormContext.d.ts.map +1 -1
  59. package/dist/useFormState.d.ts +2 -2
  60. package/dist/useFormState.d.ts.map +1 -1
  61. package/dist/useIsomorphicLayoutEffect.d.ts.map +1 -1
  62. package/dist/useWatch.d.ts +14 -14
  63. package/dist/utils/deepEqual.d.ts +1 -1
  64. package/dist/utils/deepEqual.d.ts.map +1 -1
  65. package/dist/utils/flatten.d.ts.map +1 -1
  66. package/dist/utils/get.d.ts.map +1 -1
  67. package/dist/utils/index.d.ts +2 -3
  68. package/dist/utils/index.d.ts.map +1 -1
  69. package/dist/utils/isKey.d.ts.map +1 -1
  70. package/dist/utils/set.d.ts.map +1 -1
  71. package/dist/utils/stringToPath.d.ts.map +1 -1
  72. package/dist/utils/unset.d.ts.map +1 -1
  73. package/dist/watch.d.ts +1 -1
  74. package/dist/watch.d.ts.map +1 -1
  75. package/package.json +29 -26
  76. package/dist/__tests__/controller.server.test.d.ts +0 -2
  77. package/dist/__tests__/controller.server.test.d.ts.map +0 -1
  78. package/dist/__tests__/controller.test.d.ts +0 -2
  79. package/dist/__tests__/controller.test.d.ts.map +0 -1
  80. package/dist/__tests__/form.test.d.ts +0 -2
  81. package/dist/__tests__/form.test.d.ts.map +0 -1
  82. package/dist/__tests__/formStateSubscribe.server.test.d.ts +0 -2
  83. package/dist/__tests__/formStateSubscribe.server.test.d.ts.map +0 -1
  84. package/dist/__tests__/formStateSubscribe.test.d.ts +0 -2
  85. package/dist/__tests__/formStateSubscribe.test.d.ts.map +0 -1
  86. package/dist/__tests__/isPlainObject.test.d.ts +0 -2
  87. package/dist/__tests__/isPlainObject.test.d.ts.map +0 -1
  88. package/dist/__tests__/logic/appendErrors.test.d.ts +0 -2
  89. package/dist/__tests__/logic/appendErrors.test.d.ts.map +0 -1
  90. package/dist/__tests__/logic/createFormControl.test.d.ts +0 -2
  91. package/dist/__tests__/logic/createFormControl.test.d.ts.map +0 -1
  92. package/dist/__tests__/logic/generateId.test.d.ts +0 -2
  93. package/dist/__tests__/logic/generateId.test.d.ts.map +0 -1
  94. package/dist/__tests__/logic/getCheckboxValue.test.d.ts +0 -2
  95. package/dist/__tests__/logic/getCheckboxValue.test.d.ts.map +0 -1
  96. package/dist/__tests__/logic/getDirtyFields.test.d.ts +0 -2
  97. package/dist/__tests__/logic/getDirtyFields.test.d.ts.map +0 -1
  98. package/dist/__tests__/logic/getEventValue.test.d.ts +0 -2
  99. package/dist/__tests__/logic/getEventValue.test.d.ts.map +0 -1
  100. package/dist/__tests__/logic/getFieldValue.test.d.ts +0 -2
  101. package/dist/__tests__/logic/getFieldValue.test.d.ts.map +0 -1
  102. package/dist/__tests__/logic/getFieldValueAs.test.d.ts +0 -2
  103. package/dist/__tests__/logic/getFieldValueAs.test.d.ts.map +0 -1
  104. package/dist/__tests__/logic/getFocusFieldName.test.d.ts +0 -2
  105. package/dist/__tests__/logic/getFocusFieldName.test.d.ts.map +0 -1
  106. package/dist/__tests__/logic/getNodeParentName.test.d.ts +0 -2
  107. package/dist/__tests__/logic/getNodeParentName.test.d.ts.map +0 -1
  108. package/dist/__tests__/logic/getRadioValue.test.d.ts +0 -2
  109. package/dist/__tests__/logic/getRadioValue.test.d.ts.map +0 -1
  110. package/dist/__tests__/logic/getResolverOptions.test.d.ts +0 -2
  111. package/dist/__tests__/logic/getResolverOptions.test.d.ts.map +0 -1
  112. package/dist/__tests__/logic/getRuleValue.test.d.ts +0 -2
  113. package/dist/__tests__/logic/getRuleValue.test.d.ts.map +0 -1
  114. package/dist/__tests__/logic/getValidateError.test.d.ts +0 -2
  115. package/dist/__tests__/logic/getValidateError.test.d.ts.map +0 -1
  116. package/dist/__tests__/logic/getValidationModes.test.d.ts +0 -2
  117. package/dist/__tests__/logic/getValidationModes.test.d.ts.map +0 -1
  118. package/dist/__tests__/logic/getValueAndMessage.test.d.ts +0 -2
  119. package/dist/__tests__/logic/getValueAndMessage.test.d.ts.map +0 -1
  120. package/dist/__tests__/logic/hasPromiseValidation.test.d.ts +0 -2
  121. package/dist/__tests__/logic/hasPromiseValidation.test.d.ts.map +0 -1
  122. package/dist/__tests__/logic/hasValidation.test.d.ts +0 -2
  123. package/dist/__tests__/logic/hasValidation.test.d.ts.map +0 -1
  124. package/dist/__tests__/logic/isNameInFieldArray.test.d.ts +0 -2
  125. package/dist/__tests__/logic/isNameInFieldArray.test.d.ts.map +0 -1
  126. package/dist/__tests__/logic/isWatched.test.d.ts +0 -2
  127. package/dist/__tests__/logic/isWatched.test.d.ts.map +0 -1
  128. package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts +0 -2
  129. package/dist/__tests__/logic/iterateFieldsByAction.test.d.ts.map +0 -1
  130. package/dist/__tests__/logic/schemaErrorLookup.test.d.ts +0 -2
  131. package/dist/__tests__/logic/schemaErrorLookup.test.d.ts.map +0 -1
  132. package/dist/__tests__/logic/shouldRenderFormState.test.d.ts +0 -2
  133. package/dist/__tests__/logic/shouldRenderFormState.test.d.ts.map +0 -1
  134. package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts +0 -2
  135. package/dist/__tests__/logic/shouldSubscribeByName.test.d.ts.map +0 -1
  136. package/dist/__tests__/logic/skipValidation.test.d.ts +0 -2
  137. package/dist/__tests__/logic/skipValidation.test.d.ts.map +0 -1
  138. package/dist/__tests__/logic/unsetEmptyArray.test.d.ts +0 -2
  139. package/dist/__tests__/logic/unsetEmptyArray.test.d.ts.map +0 -1
  140. package/dist/__tests__/logic/validateField.test.d.ts +0 -2
  141. package/dist/__tests__/logic/validateField.test.d.ts.map +0 -1
  142. package/dist/__tests__/type.test.d.ts +0 -2
  143. package/dist/__tests__/type.test.d.ts.map +0 -1
  144. package/dist/__tests__/useController.test.d.ts +0 -2
  145. package/dist/__tests__/useController.test.d.ts.map +0 -1
  146. package/dist/__tests__/useFieldArray/append.test.d.ts +0 -2
  147. package/dist/__tests__/useFieldArray/append.test.d.ts.map +0 -1
  148. package/dist/__tests__/useFieldArray/dirtyFields.test.d.ts +0 -2
  149. package/dist/__tests__/useFieldArray/dirtyFields.test.d.ts.map +0 -1
  150. package/dist/__tests__/useFieldArray/focus.test.d.ts +0 -2
  151. package/dist/__tests__/useFieldArray/focus.test.d.ts.map +0 -1
  152. package/dist/__tests__/useFieldArray/insert.test.d.ts +0 -2
  153. package/dist/__tests__/useFieldArray/insert.test.d.ts.map +0 -1
  154. package/dist/__tests__/useFieldArray/move.test.d.ts +0 -2
  155. package/dist/__tests__/useFieldArray/move.test.d.ts.map +0 -1
  156. package/dist/__tests__/useFieldArray/prepend.test.d.ts +0 -2
  157. package/dist/__tests__/useFieldArray/prepend.test.d.ts.map +0 -1
  158. package/dist/__tests__/useFieldArray/remove.test.d.ts +0 -2
  159. package/dist/__tests__/useFieldArray/remove.test.d.ts.map +0 -1
  160. package/dist/__tests__/useFieldArray/replace.test.d.ts +0 -2
  161. package/dist/__tests__/useFieldArray/replace.test.d.ts.map +0 -1
  162. package/dist/__tests__/useFieldArray/swap.test.d.ts +0 -2
  163. package/dist/__tests__/useFieldArray/swap.test.d.ts.map +0 -1
  164. package/dist/__tests__/useFieldArray/update.test.d.ts +0 -2
  165. package/dist/__tests__/useFieldArray/update.test.d.ts.map +0 -1
  166. package/dist/__tests__/useFieldArray.test.d.ts +0 -2
  167. package/dist/__tests__/useFieldArray.test.d.ts.map +0 -1
  168. package/dist/__tests__/useForm/clearErrors.test.d.ts +0 -2
  169. package/dist/__tests__/useForm/clearErrors.test.d.ts.map +0 -1
  170. package/dist/__tests__/useForm/formState.test.d.ts +0 -2
  171. package/dist/__tests__/useForm/formState.test.d.ts.map +0 -1
  172. package/dist/__tests__/useForm/getFieldState.test.d.ts +0 -2
  173. package/dist/__tests__/useForm/getFieldState.test.d.ts.map +0 -1
  174. package/dist/__tests__/useForm/getValues.test.d.ts +0 -2
  175. package/dist/__tests__/useForm/getValues.test.d.ts.map +0 -1
  176. package/dist/__tests__/useForm/handleSubmit.test.d.ts +0 -2
  177. package/dist/__tests__/useForm/handleSubmit.test.d.ts.map +0 -1
  178. package/dist/__tests__/useForm/register.test.d.ts +0 -2
  179. package/dist/__tests__/useForm/register.test.d.ts.map +0 -1
  180. package/dist/__tests__/useForm/reset.test.d.ts +0 -2
  181. package/dist/__tests__/useForm/reset.test.d.ts.map +0 -1
  182. package/dist/__tests__/useForm/resetField.test.d.ts +0 -2
  183. package/dist/__tests__/useForm/resetField.test.d.ts.map +0 -1
  184. package/dist/__tests__/useForm/resolver.test.d.ts +0 -2
  185. package/dist/__tests__/useForm/resolver.test.d.ts.map +0 -1
  186. package/dist/__tests__/useForm/setError.test.d.ts +0 -2
  187. package/dist/__tests__/useForm/setError.test.d.ts.map +0 -1
  188. package/dist/__tests__/useForm/setFocus.test.d.ts +0 -2
  189. package/dist/__tests__/useForm/setFocus.test.d.ts.map +0 -1
  190. package/dist/__tests__/useForm/setValue.test.d.ts +0 -2
  191. package/dist/__tests__/useForm/setValue.test.d.ts.map +0 -1
  192. package/dist/__tests__/useForm/subscribe.test.d.ts +0 -2
  193. package/dist/__tests__/useForm/subscribe.test.d.ts.map +0 -1
  194. package/dist/__tests__/useForm/trigger.test.d.ts +0 -2
  195. package/dist/__tests__/useForm/trigger.test.d.ts.map +0 -1
  196. package/dist/__tests__/useForm/unregister.test.d.ts +0 -2
  197. package/dist/__tests__/useForm/unregister.test.d.ts.map +0 -1
  198. package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts +0 -2
  199. package/dist/__tests__/useForm/useFormWithNullValues.test.d.ts.map +0 -1
  200. package/dist/__tests__/useForm/watch.test.d.ts +0 -2
  201. package/dist/__tests__/useForm/watch.test.d.ts.map +0 -1
  202. package/dist/__tests__/useForm.server.test.d.ts +0 -2
  203. package/dist/__tests__/useForm.server.test.d.ts.map +0 -1
  204. package/dist/__tests__/useForm.test.d.ts +0 -2
  205. package/dist/__tests__/useForm.test.d.ts.map +0 -1
  206. package/dist/__tests__/useFormContext.server.test.d.ts +0 -2
  207. package/dist/__tests__/useFormContext.server.test.d.ts.map +0 -1
  208. package/dist/__tests__/useFormContext.test.d.ts +0 -2
  209. package/dist/__tests__/useFormContext.test.d.ts.map +0 -1
  210. package/dist/__tests__/useFormState.test.d.ts +0 -2
  211. package/dist/__tests__/useFormState.test.d.ts.map +0 -1
  212. package/dist/__tests__/useWatch.test.d.ts +0 -2
  213. package/dist/__tests__/useWatch.test.d.ts.map +0 -1
  214. package/dist/__tests__/utils/append.test.d.ts +0 -2
  215. package/dist/__tests__/utils/append.test.d.ts.map +0 -1
  216. package/dist/__tests__/utils/cloneObject.test.d.ts +0 -2
  217. package/dist/__tests__/utils/cloneObject.test.d.ts.map +0 -1
  218. package/dist/__tests__/utils/compact.test.d.ts +0 -2
  219. package/dist/__tests__/utils/compact.test.d.ts.map +0 -1
  220. package/dist/__tests__/utils/convertToArrayPayload.test.d.ts +0 -2
  221. package/dist/__tests__/utils/convertToArrayPayload.test.d.ts.map +0 -1
  222. package/dist/__tests__/utils/createSubject.test.d.ts +0 -2
  223. package/dist/__tests__/utils/createSubject.test.d.ts.map +0 -1
  224. package/dist/__tests__/utils/deepEqual.test.d.ts +0 -2
  225. package/dist/__tests__/utils/deepEqual.test.d.ts.map +0 -1
  226. package/dist/__tests__/utils/deepMerge.test.d.ts +0 -2
  227. package/dist/__tests__/utils/deepMerge.test.d.ts.map +0 -1
  228. package/dist/__tests__/utils/extractFormValues.test.d.ts +0 -2
  229. package/dist/__tests__/utils/extractFormValues.test.d.ts.map +0 -1
  230. package/dist/__tests__/utils/fillEmptyArray.test.d.ts +0 -2
  231. package/dist/__tests__/utils/fillEmptyArray.test.d.ts.map +0 -1
  232. package/dist/__tests__/utils/flatten.test.d.ts +0 -2
  233. package/dist/__tests__/utils/flatten.test.d.ts.map +0 -1
  234. package/dist/__tests__/utils/get.test.d.ts +0 -2
  235. package/dist/__tests__/utils/get.test.d.ts.map +0 -1
  236. package/dist/__tests__/utils/insert.test.d.ts +0 -2
  237. package/dist/__tests__/utils/insert.test.d.ts.map +0 -1
  238. package/dist/__tests__/utils/isBoolean.test.d.ts +0 -2
  239. package/dist/__tests__/utils/isBoolean.test.d.ts.map +0 -1
  240. package/dist/__tests__/utils/isCheckBoxInput.test.d.ts +0 -2
  241. package/dist/__tests__/utils/isCheckBoxInput.test.d.ts.map +0 -1
  242. package/dist/__tests__/utils/isEmptyObject.test.d.ts +0 -2
  243. package/dist/__tests__/utils/isEmptyObject.test.d.ts.map +0 -1
  244. package/dist/__tests__/utils/isFileInput.test.d.ts +0 -2
  245. package/dist/__tests__/utils/isFileInput.test.d.ts.map +0 -1
  246. package/dist/__tests__/utils/isFunction.test.d.ts +0 -2
  247. package/dist/__tests__/utils/isFunction.test.d.ts.map +0 -1
  248. package/dist/__tests__/utils/isHTMLElement.test.d.ts +0 -2
  249. package/dist/__tests__/utils/isHTMLElement.test.d.ts.map +0 -1
  250. package/dist/__tests__/utils/isKey.test.d.ts +0 -2
  251. package/dist/__tests__/utils/isKey.test.d.ts.map +0 -1
  252. package/dist/__tests__/utils/isMultipleSelect.test.d.ts +0 -2
  253. package/dist/__tests__/utils/isMultipleSelect.test.d.ts.map +0 -1
  254. package/dist/__tests__/utils/isNullOrUndefined.test.d.ts +0 -2
  255. package/dist/__tests__/utils/isNullOrUndefined.test.d.ts.map +0 -1
  256. package/dist/__tests__/utils/isObject.test.d.ts +0 -2
  257. package/dist/__tests__/utils/isObject.test.d.ts.map +0 -1
  258. package/dist/__tests__/utils/isPrimitive.test.d.ts +0 -2
  259. package/dist/__tests__/utils/isPrimitive.test.d.ts.map +0 -1
  260. package/dist/__tests__/utils/isRadioInput.test.d.ts +0 -2
  261. package/dist/__tests__/utils/isRadioInput.test.d.ts.map +0 -1
  262. package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts +0 -2
  263. package/dist/__tests__/utils/isRadioOrCheckbox.test.d.ts.map +0 -1
  264. package/dist/__tests__/utils/isRegex.test.d.ts +0 -2
  265. package/dist/__tests__/utils/isRegex.test.d.ts.map +0 -1
  266. package/dist/__tests__/utils/isString.test.d.ts +0 -2
  267. package/dist/__tests__/utils/isString.test.d.ts.map +0 -1
  268. package/dist/__tests__/utils/isUndefined.test.d.ts +0 -2
  269. package/dist/__tests__/utils/isUndefined.test.d.ts.map +0 -1
  270. package/dist/__tests__/utils/live.test.d.ts +0 -2
  271. package/dist/__tests__/utils/live.test.d.ts.map +0 -1
  272. package/dist/__tests__/utils/move.test.d.ts +0 -2
  273. package/dist/__tests__/utils/move.test.d.ts.map +0 -1
  274. package/dist/__tests__/utils/noop.test.d.ts +0 -2
  275. package/dist/__tests__/utils/noop.test.d.ts.map +0 -1
  276. package/dist/__tests__/utils/objectHasFunction.test.d.ts +0 -2
  277. package/dist/__tests__/utils/objectHasFunction.test.d.ts.map +0 -1
  278. package/dist/__tests__/utils/prepend.test.d.ts +0 -2
  279. package/dist/__tests__/utils/prepend.test.d.ts.map +0 -1
  280. package/dist/__tests__/utils/remove.test.d.ts +0 -2
  281. package/dist/__tests__/utils/remove.test.d.ts.map +0 -1
  282. package/dist/__tests__/utils/set.test.d.ts +0 -2
  283. package/dist/__tests__/utils/set.test.d.ts.map +0 -1
  284. package/dist/__tests__/utils/stringToPath.test.d.ts +0 -2
  285. package/dist/__tests__/utils/stringToPath.test.d.ts.map +0 -1
  286. package/dist/__tests__/utils/swap.test.d.ts +0 -2
  287. package/dist/__tests__/utils/swap.test.d.ts.map +0 -1
  288. package/dist/__tests__/utils/unset.test.d.ts +0 -2
  289. package/dist/__tests__/utils/unset.test.d.ts.map +0 -1
  290. package/dist/__tests__/utils/update.test.d.ts +0 -2
  291. package/dist/__tests__/utils/update.test.d.ts.map +0 -1
  292. package/dist/__tests__/utils/validationModeChecker.test.d.ts +0 -2
  293. package/dist/__tests__/utils/validationModeChecker.test.d.ts.map +0 -1
  294. package/dist/__tests__/watch.server.test.d.ts +0 -2
  295. package/dist/__tests__/watch.server.test.d.ts.map +0 -1
  296. package/dist/__tests__/watch.test.d.ts +0 -2
  297. package/dist/__tests__/watch.test.d.ts.map +0 -1
@@ -2,6 +2,8 @@ import React from 'react';
2
2
 
3
3
  var isCheckBoxInput = (element) => element.type === 'checkbox';
4
4
 
5
+ var isFileInput = (element) => element.type === 'file';
6
+
5
7
  var isDateObject = (value) => value instanceof Date;
6
8
 
7
9
  var isNullOrUndefined = (value) => value == null;
@@ -15,7 +17,9 @@ var isObject = (value) => !isNullOrUndefined(value) &&
15
17
  var getEventValue = (event) => isObject(event) && event.target
16
18
  ? isCheckBoxInput(event.target)
17
19
  ? event.target.checked
18
- : event.target.value
20
+ : isFileInput(event.target)
21
+ ? event.target.files
22
+ : event.target.value
19
23
  : event;
20
24
 
21
25
  var isNameInFieldArray = (names, name) => name
@@ -52,19 +56,52 @@ function cloneObject(data) {
52
56
  return copy;
53
57
  }
54
58
 
55
- var isKey = (value) => /^\w*$/.test(value);
59
+ const EVENTS = {
60
+ BLUR: 'blur',
61
+ FOCUS_OUT: 'focusout',
62
+ CHANGE: 'change',
63
+ SUBMIT: 'submit',
64
+ TRIGGER: 'trigger',
65
+ VALID: 'valid',
66
+ };
67
+ const VALIDATION_MODE = {
68
+ onBlur: 'onBlur',
69
+ onChange: 'onChange',
70
+ onSubmit: 'onSubmit',
71
+ onTouched: 'onTouched',
72
+ all: 'all',
73
+ };
74
+ const INPUT_VALIDATION_RULES = {
75
+ max: 'max',
76
+ min: 'min',
77
+ maxLength: 'maxLength',
78
+ minLength: 'minLength',
79
+ pattern: 'pattern',
80
+ required: 'required',
81
+ validate: 'validate',
82
+ };
83
+ const ROOT_ERROR_TYPE = 'root';
84
+ const PROTOTYPE_KEYWORDS = ['__proto__', 'constructor', 'prototype'];
85
+
86
+ const IS_KEY_RE = /^\w*$/;
87
+ var isKey = (value) => IS_KEY_RE.test(value);
56
88
 
57
89
  var isUndefined = (val) => val === undefined;
58
90
 
59
- var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
60
-
61
- var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/));
91
+ const FIELD_PATH_RE = /[.[\]'"]/;
92
+ var stringToPath = (input) => input.split(FIELD_PATH_RE).filter(Boolean);
62
93
 
63
94
  var get = (object, path, defaultValue) => {
64
95
  if (!path || !isObject(object)) {
65
96
  return defaultValue;
66
97
  }
67
- const result = (isKey(path) ? [path] : stringToPath(path)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], object);
98
+ const paths = isKey(path) ? [path] : stringToPath(path);
99
+ if (paths.some((key) => PROTOTYPE_KEYWORDS.includes(key))) {
100
+ return defaultValue;
101
+ }
102
+ const result = paths.reduce((result, key) => {
103
+ return isNullOrUndefined(result) ? undefined : result[key];
104
+ }, object);
68
105
  return isUndefined(result) || result === object
69
106
  ? isUndefined(object[path])
70
107
  ? defaultValue
@@ -93,7 +130,7 @@ var set = (object, path, value) => {
93
130
  ? []
94
131
  : {};
95
132
  }
96
- if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
133
+ if (PROTOTYPE_KEYWORDS.includes(key)) {
97
134
  return;
98
135
  }
99
136
  object[key] = newValue;
@@ -101,33 +138,6 @@ var set = (object, path, value) => {
101
138
  }
102
139
  };
103
140
 
104
- const EVENTS = {
105
- BLUR: 'blur',
106
- FOCUS_OUT: 'focusout',
107
- CHANGE: 'change',
108
- SUBMIT: 'submit',
109
- TRIGGER: 'trigger',
110
- VALID: 'valid',
111
- };
112
- const VALIDATION_MODE = {
113
- onBlur: 'onBlur',
114
- onChange: 'onChange',
115
- onSubmit: 'onSubmit',
116
- onTouched: 'onTouched',
117
- all: 'all',
118
- };
119
- const INPUT_VALIDATION_RULES = {
120
- max: 'max',
121
- min: 'min',
122
- maxLength: 'maxLength',
123
- minLength: 'minLength',
124
- pattern: 'pattern',
125
- required: 'required',
126
- validate: 'validate',
127
- };
128
- const FORM_ERROR_TYPE = 'form';
129
- const ROOT_ERROR_TYPE = 'root';
130
-
131
141
  /**
132
142
  * Separate context for `control` to prevent unnecessary rerenders.
133
143
  * Internal hooks that only need control use this instead of full form context.
@@ -140,9 +150,7 @@ HookFormControlContext.displayName = 'HookFormControlContext';
140
150
  const useFormControlContext = () => React.useContext(HookFormControlContext);
141
151
 
142
152
  var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => {
143
- const result = {
144
- defaultValues: control._defaultValues,
145
- };
153
+ const result = {};
146
154
  for (const key in formState) {
147
155
  Object.defineProperty(result, key, {
148
156
  get: () => {
@@ -158,15 +166,17 @@ var getProxyFormState = (formState, control, localProxyFormState, isRoot = true)
158
166
  return result;
159
167
  };
160
168
 
161
- const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
169
+ const useIsomorphicLayoutEffect = isWeb
170
+ ? React.useLayoutEffect
171
+ : React.useEffect;
162
172
 
163
173
  /**
164
- * 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.
174
+ * Subscribes to each form state and isolates re-renders at the custom hook level. It has its own scope for form state subscriptions, so it will not affect other useFormState or useForm instances. Using this hook can reduce the re-render impact on large and complex form applications.
165
175
  *
166
176
  * @remarks
167
177
  * [API](https://react-hook-form.com/docs/useformstate) • [Demo](https://codesandbox.io/s/useformstate-75xly)
168
178
  *
169
- * @param props - include options on specify fields to subscribe. {@link UseFormStateReturn}
179
+ * @param props - Include options to specify fields to subscribe to. {@link UseFormStateReturn}
170
180
  *
171
181
  * @example
172
182
  * ```tsx
@@ -193,7 +203,10 @@ const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? React.useLayou
193
203
  function useFormState(props) {
194
204
  const formControl = useFormControlContext();
195
205
  const { control = formControl, disabled, name, exact } = props || {};
196
- const [formState, updateFormState] = React.useState(control._formState);
206
+ const [formState, updateFormState] = React.useState(() => ({
207
+ ...control._formState,
208
+ defaultValues: control._defaultValues,
209
+ }));
197
210
  const _localProxyFormState = React.useRef({
198
211
  isDirty: false,
199
212
  isLoading: false,
@@ -213,6 +226,7 @@ function useFormState(props) {
213
226
  updateFormState({
214
227
  ...control._formState,
215
228
  ...formState,
229
+ defaultValues: control._defaultValues,
216
230
  });
217
231
  },
218
232
  }), [name, disabled, exact]);
@@ -239,7 +253,11 @@ var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) =>
239
253
 
240
254
  var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value);
241
255
 
242
- function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
256
+ const isEmptyObjectWithCustomPrototype = (object, keys) => keys.length === 0 && !Array.isArray(object) && !isPlainObject(object);
257
+ function deepEqual(object1, object2, visited = new WeakMap()) {
258
+ if (object1 === object2) {
259
+ return true;
260
+ }
243
261
  if (isPrimitive(object1) || isPrimitive(object2)) {
244
262
  return Object.is(object1, object2);
245
263
  }
@@ -251,14 +269,28 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
251
269
  if (keys1.length !== keys2.length) {
252
270
  return false;
253
271
  }
254
- if (_internal_visited.has(object1) || _internal_visited.has(object2)) {
272
+ if (isEmptyObjectWithCustomPrototype(object1, keys1) ||
273
+ isEmptyObjectWithCustomPrototype(object2, keys2)) {
274
+ return Object.is(object1, object2);
275
+ }
276
+ if (!keys1.length && Array.isArray(object1) !== Array.isArray(object2)) {
277
+ return false;
278
+ }
279
+ const visitedPairs = visited.get(object1);
280
+ if (visitedPairs && visitedPairs.has(object2)) {
255
281
  return true;
256
282
  }
257
- _internal_visited.add(object1);
258
- _internal_visited.add(object2);
283
+ if (visitedPairs) {
284
+ visitedPairs.add(object2);
285
+ }
286
+ else {
287
+ const ws = new WeakSet();
288
+ ws.add(object2);
289
+ visited.set(object1, ws);
290
+ }
259
291
  for (const key of keys1) {
260
292
  const val1 = object1[key];
261
- if (!keys2.includes(key)) {
293
+ if (!(key in object2)) {
262
294
  return false;
263
295
  }
264
296
  if (key !== 'ref') {
@@ -266,7 +298,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
266
298
  if ((isDateObject(val1) && isDateObject(val2)) ||
267
299
  ((isObject(val1) || Array.isArray(val1)) &&
268
300
  (isObject(val2) || Array.isArray(val2)))
269
- ? !deepEqual(val1, val2, _internal_visited)
301
+ ? !deepEqual(val1, val2, visited)
270
302
  : !Object.is(val1, val2)) {
271
303
  return false;
272
304
  }
@@ -276,7 +308,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
276
308
  }
277
309
 
278
310
  /**
279
- * Custom hook to subscribe to field change and isolate re-rendering at the component level.
311
+ * Custom hook to subscribe to field changes and isolate re-rendering at the component level.
280
312
  *
281
313
  * @remarks
282
314
  *
@@ -286,7 +318,7 @@ function deepEqual(object1, object2, _internal_visited = new WeakSet()) {
286
318
  * ```tsx
287
319
  * const { control } = useForm();
288
320
  * const values = useWatch({
289
- * name: "fieldName"
321
+ * name: "fieldName",
290
322
  * control,
291
323
  * })
292
324
  * ```
@@ -402,7 +434,7 @@ function useController(props) {
402
434
  exact,
403
435
  });
404
436
  const _props = React.useRef(props);
405
- const _previousNameRef = React.useRef(undefined);
437
+ const _proxyRef = React.useRef(null);
406
438
  const _registerProps = React.useRef(control.register(name, {
407
439
  ...props.rules,
408
440
  value,
@@ -431,13 +463,22 @@ function useController(props) {
431
463
  get: () => get(formState.errors, name),
432
464
  },
433
465
  }), [formState, name]);
434
- const onChange = React.useCallback((event) => _registerProps.current.onChange({
435
- target: {
436
- value: getEventValue(event),
437
- name: name,
438
- },
439
- type: EVENTS.CHANGE,
440
- }), [name]);
466
+ const onChange = React.useCallback((event) => {
467
+ const value = getEventValue(event);
468
+ if (!get(control._fields, name)) {
469
+ _registerProps.current = control.register(name, {
470
+ ..._props.current.rules,
471
+ value,
472
+ });
473
+ }
474
+ return _registerProps.current.onChange({
475
+ target: {
476
+ value: getEventValue(event),
477
+ name: name,
478
+ },
479
+ type: EVENTS.CHANGE,
480
+ });
481
+ }, [name, control]);
441
482
  const onBlur = React.useCallback(() => _registerProps.current.onBlur({
442
483
  target: {
443
484
  value: get(control._formValues, name),
@@ -446,15 +487,18 @@ function useController(props) {
446
487
  type: EVENTS.BLUR,
447
488
  }), [name, control._formValues]);
448
489
  const ref = React.useCallback((elm) => {
449
- const field = get(control._fields, name);
450
- if (field && field._f && elm) {
451
- field._f.ref = {
490
+ if (elm) {
491
+ _proxyRef.current = {
452
492
  focus: () => isFunction(elm.focus) && elm.focus(),
453
493
  select: () => isFunction(elm.select) && elm.select(),
454
494
  setCustomValidity: (message) => isFunction(elm.setCustomValidity) && elm.setCustomValidity(message),
455
495
  reportValidity: () => isFunction(elm.reportValidity) && elm.reportValidity(),
456
496
  };
457
497
  }
498
+ const field = get(control._fields, name);
499
+ if (field && field._f && elm) {
500
+ field._f.ref = _proxyRef.current;
501
+ }
458
502
  }, [control._fields, name]);
459
503
  const field = React.useMemo(() => ({
460
504
  name,
@@ -468,11 +512,7 @@ function useController(props) {
468
512
  }), [name, disabled, formState.disabled, onChange, onBlur, ref, value]);
469
513
  React.useEffect(() => {
470
514
  const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister;
471
- const previousName = _previousNameRef.current;
472
- if (previousName && previousName !== name && !isArrayField) {
473
- control.unregister(previousName);
474
- }
475
- control.register(name, {
515
+ _registerProps.current = control.register(name, {
476
516
  ..._props.current.rules,
477
517
  ...(isBoolean(_props.current.disabled)
478
518
  ? { disabled: _props.current.disabled }
@@ -486,14 +526,21 @@ function useController(props) {
486
526
  };
487
527
  updateMounted(name, true);
488
528
  if (_shouldUnregisterField) {
489
- const value = cloneObject(get(control._options.defaultValues, name, _props.current.defaultValue));
529
+ const value = cloneObject(get(shouldUnregister
530
+ ? control._defaultValues
531
+ : control._options.values || control._defaultValues, name, get(control._options.defaultValues, name, _props.current.defaultValue)));
490
532
  set(control._defaultValues, name, value);
491
533
  if (isUndefined(get(control._formValues, name))) {
492
534
  set(control._formValues, name, value);
493
535
  }
494
536
  }
495
537
  !isArrayField && control.register(name);
496
- _previousNameRef.current = name;
538
+ if (_proxyRef.current) {
539
+ const field = get(control._fields, name);
540
+ if (field && field._f) {
541
+ field._f.ref = _proxyRef.current;
542
+ }
543
+ }
497
544
  return () => {
498
545
  (isArrayField
499
546
  ? _shouldUnregisterField && !control._state.action
@@ -559,293 +606,80 @@ function useController(props) {
559
606
  */
560
607
  const Controller = (props) => props.render(useController(props));
561
608
 
562
- const flatten = (obj) => {
563
- const output = {};
564
- for (const key of Object.keys(obj)) {
565
- if (isObjectType(obj[key]) && obj[key] !== null) {
566
- const nested = flatten(obj[key]);
567
- for (const nestedKey of Object.keys(nested)) {
568
- output[`${key}.${nestedKey}`] = nested[nestedKey];
609
+ var generateId = () => {
610
+ if (typeof crypto !== 'undefined' && crypto.randomUUID) {
611
+ return crypto.randomUUID();
612
+ }
613
+ const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
614
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
615
+ const r = ((Math.random() * 16 + d) % 16) | 0;
616
+ return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
617
+ });
618
+ };
619
+
620
+ var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
621
+ ? options.focusName ||
622
+ `${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
623
+ : '';
624
+
625
+ var getValidationModes = (mode) => ({
626
+ isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
627
+ isOnBlur: mode === VALIDATION_MODE.onBlur,
628
+ isOnChange: mode === VALIDATION_MODE.onChange,
629
+ isOnAll: mode === VALIDATION_MODE.all,
630
+ isOnTouch: mode === VALIDATION_MODE.onTouched,
631
+ });
632
+
633
+ var isWatched = (name, _names, isBlurEvent) => {
634
+ if (isBlurEvent)
635
+ return false;
636
+ if (_names.watchAll || _names.watch.has(name))
637
+ return true;
638
+ for (const watchName of _names.watch) {
639
+ if (name.startsWith(watchName) && name.charAt(watchName.length) === '.')
640
+ return true;
641
+ }
642
+ return false;
643
+ };
644
+
645
+ const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
646
+ for (const key of fieldsNames || Object.keys(fields)) {
647
+ const field = get(fields, key);
648
+ if (field) {
649
+ const { _f, ...currentField } = field;
650
+ if (_f) {
651
+ if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
652
+ return true;
653
+ }
654
+ else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
655
+ return true;
656
+ }
657
+ else {
658
+ if (iterateFieldsByAction(currentField, action)) {
659
+ break;
660
+ }
661
+ }
662
+ }
663
+ else if (isObject(currentField)) {
664
+ if (iterateFieldsByAction(currentField, action)) {
665
+ break;
666
+ }
569
667
  }
570
- }
571
- else {
572
- output[key] = obj[key];
573
668
  }
574
669
  }
575
- return output;
670
+ return;
576
671
  };
577
672
 
578
- const HookFormContext = React.createContext(null);
579
- HookFormContext.displayName = 'HookFormContext';
580
- /**
581
- * This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
582
- *
583
- * @remarks
584
- * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
585
- *
586
- * @returns return all useForm methods
587
- *
588
- * @example
589
- * ```tsx
590
- * function App() {
591
- * const methods = useForm();
592
- * const onSubmit = data => console.log(data);
593
- *
594
- * return (
595
- * <FormProvider {...methods} >
596
- * <form onSubmit={methods.handleSubmit(onSubmit)}>
597
- * <NestedInput />
598
- * <input type="submit" />
599
- * </form>
600
- * </FormProvider>
601
- * );
602
- * }
603
- *
604
- * function NestedInput() {
605
- * const { register } = useFormContext(); // retrieve all hook methods
606
- * return <input {...register("test")} />;
607
- * }
608
- * ```
609
- */
610
- const useFormContext = () => React.useContext(HookFormContext);
611
- /**
612
- * A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
613
- *
614
- * @remarks
615
- * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
616
- *
617
- * @param props - all useForm methods
618
- *
619
- * @example
620
- * ```tsx
621
- * function App() {
622
- * const methods = useForm();
623
- * const onSubmit = data => console.log(data);
624
- *
625
- * return (
626
- * <FormProvider {...methods} >
627
- * <form onSubmit={methods.handleSubmit(onSubmit)}>
628
- * <NestedInput />
629
- * <input type="submit" />
630
- * </form>
631
- * </FormProvider>
632
- * );
633
- * }
634
- *
635
- * function NestedInput() {
636
- * const { register } = useFormContext(); // retrieve all hook methods
637
- * return <input {...register("test")} />;
638
- * }
639
- * ```
640
- */
641
- const FormProvider = (props) => {
642
- const { children, watch, getValues, getFieldState, setError, clearErrors, setValue, trigger, formState, resetField, reset, handleSubmit, unregister, control, register, setFocus, subscribe, } = props;
643
- const memoizedValue = React.useMemo(() => ({
644
- watch,
645
- getValues,
646
- getFieldState,
647
- setError,
648
- clearErrors,
649
- setValue,
650
- trigger,
651
- formState,
652
- resetField,
653
- reset,
654
- handleSubmit,
655
- unregister,
656
- control,
657
- register,
658
- setFocus,
659
- subscribe,
660
- }), [
661
- clearErrors,
662
- control,
663
- formState,
664
- getFieldState,
665
- getValues,
666
- handleSubmit,
667
- register,
668
- reset,
669
- resetField,
670
- setError,
671
- setFocus,
672
- setValue,
673
- subscribe,
674
- trigger,
675
- unregister,
676
- watch,
677
- ]);
678
- return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
679
- React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
673
+ var updateFieldArrayRootError = (errors, error, name) => {
674
+ const existingErrors = get(errors, name);
675
+ const fieldArrayErrors = Array.isArray(existingErrors) ? existingErrors : [];
676
+ set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
677
+ set(errors, name, fieldArrayErrors);
678
+ return errors;
680
679
  };
681
680
 
682
- const POST_REQUEST = 'post';
683
- /**
684
- * Form component to manage submission.
685
- *
686
- * @param props - to setup submission detail. {@link FormProps}
687
- *
688
- * @returns form component or headless render prop.
689
- *
690
- * @example
691
- * ```tsx
692
- * function App() {
693
- * const { control, formState: { errors } } = useForm();
694
- *
695
- * return (
696
- * <Form action="/api" control={control}>
697
- * <input {...register("name")} />
698
- * <p>{errors?.root?.server && 'Server error'}</p>
699
- * <button>Submit</button>
700
- * </Form>
701
- * );
702
- * }
703
- * ```
704
- */
705
- function Form(props) {
706
- const methods = useFormContext();
707
- const [mounted, setMounted] = React.useState(false);
708
- const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
709
- const submit = async (event) => {
710
- let hasError = false;
711
- let type = '';
712
- await control.handleSubmit(async (data) => {
713
- const formData = new FormData();
714
- let formDataJson = '';
715
- try {
716
- formDataJson = JSON.stringify(data);
717
- }
718
- catch (_a) { }
719
- const flattenFormValues = flatten(control._formValues);
720
- for (const key in flattenFormValues) {
721
- formData.append(key, flattenFormValues[key]);
722
- }
723
- if (onSubmit) {
724
- await onSubmit({
725
- data,
726
- event,
727
- method,
728
- formData,
729
- formDataJson,
730
- });
731
- }
732
- if (action) {
733
- try {
734
- const shouldStringifySubmissionData = [
735
- headers && headers['Content-Type'],
736
- encType,
737
- ].some((value) => value && value.includes('json'));
738
- const response = await fetch(String(action), {
739
- method,
740
- headers: {
741
- ...headers,
742
- ...(encType && encType !== 'multipart/form-data'
743
- ? { 'Content-Type': encType }
744
- : {}),
745
- },
746
- body: shouldStringifySubmissionData ? formDataJson : formData,
747
- });
748
- if (response &&
749
- (validateStatus
750
- ? !validateStatus(response.status)
751
- : response.status < 200 || response.status >= 300)) {
752
- hasError = true;
753
- onError && onError({ response });
754
- type = String(response.status);
755
- }
756
- else {
757
- onSuccess && onSuccess({ response });
758
- }
759
- }
760
- catch (error) {
761
- hasError = true;
762
- onError && onError({ error });
763
- }
764
- }
765
- })(event);
766
- if (hasError && props.control) {
767
- props.control._subjects.state.next({
768
- isSubmitSuccessful: false,
769
- });
770
- props.control.setError('root.server', {
771
- type,
772
- });
773
- }
774
- };
775
- React.useEffect(() => {
776
- setMounted(true);
777
- }, []);
778
- return render ? (React.createElement(React.Fragment, null, render({
779
- submit,
780
- }))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
781
- }
782
-
783
- const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
784
-
785
- var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
786
- ? {
787
- ...errors[name],
788
- types: {
789
- ...(errors[name] && errors[name].types ? errors[name].types : {}),
790
- [type]: message || true,
791
- },
792
- }
793
- : {};
794
-
795
- var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
796
-
797
- var createSubject = () => {
798
- let _observers = [];
799
- const next = (value) => {
800
- for (const observer of _observers) {
801
- observer.next && observer.next(value);
802
- }
803
- };
804
- const subscribe = (observer) => {
805
- _observers.push(observer);
806
- return {
807
- unsubscribe: () => {
808
- _observers = _observers.filter((o) => o !== observer);
809
- },
810
- };
811
- };
812
- const unsubscribe = () => {
813
- _observers = [];
814
- };
815
- return {
816
- get observers() {
817
- return _observers;
818
- },
819
- next,
820
- subscribe,
821
- unsubscribe,
822
- };
823
- };
824
-
825
- function extractFormValues(fieldsState, formValues) {
826
- const values = {};
827
- for (const key in fieldsState) {
828
- if (fieldsState.hasOwnProperty(key)) {
829
- const fieldState = fieldsState[key];
830
- const fieldValue = formValues[key];
831
- if (fieldState && isObject(fieldState) && fieldValue) {
832
- const nestedFieldsState = extractFormValues(fieldState, fieldValue);
833
- if (isObject(nestedFieldsState)) {
834
- values[key] = nestedFieldsState;
835
- }
836
- }
837
- else if (fieldsState[key]) {
838
- values[key] = fieldValue;
839
- }
840
- }
841
- }
842
- return values;
843
- }
844
-
845
681
  var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length;
846
682
 
847
- var isFileInput = (element) => element.type === 'file';
848
-
849
683
  var isHTMLElement = (value) => {
850
684
  if (!isWeb) {
851
685
  return false;
@@ -855,96 +689,19 @@ var isHTMLElement = (value) => {
855
689
  (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement));
856
690
  };
857
691
 
858
- var isMultipleSelect = (element) => element.type === `select-multiple`;
859
-
860
692
  var isRadioInput = (element) => element.type === 'radio';
861
693
 
862
- var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
863
-
864
- var live = (ref) => isHTMLElement(ref) && ref.isConnected;
865
-
866
- function baseGet(object, updatePath) {
867
- const length = updatePath.slice(0, -1).length;
868
- let index = 0;
869
- while (index < length) {
870
- object = isUndefined(object) ? index++ : object[updatePath[index++]];
871
- }
872
- return object;
873
- }
874
- function isEmptyArray(obj) {
875
- for (const key in obj) {
876
- if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
877
- return false;
878
- }
879
- }
880
- return true;
881
- }
882
- function unset(object, path) {
883
- const paths = Array.isArray(path)
884
- ? path
885
- : isKey(path)
886
- ? [path]
887
- : stringToPath(path);
888
- const childObject = paths.length === 1 ? object : baseGet(object, paths);
889
- const index = paths.length - 1;
890
- const key = paths[index];
891
- if (childObject) {
892
- delete childObject[key];
893
- }
894
- if (index !== 0 &&
895
- ((isObject(childObject) && isEmptyObject(childObject)) ||
896
- (Array.isArray(childObject) && isEmptyArray(childObject)))) {
897
- unset(object, paths.slice(0, -1));
898
- }
899
- return object;
900
- }
901
-
902
- var objectHasFunction = (data) => {
903
- for (const key in data) {
904
- if (isFunction(data[key])) {
905
- return true;
906
- }
907
- }
908
- return false;
909
- };
694
+ var isRegex = (value) => value instanceof RegExp;
910
695
 
911
- function isTraversable(value) {
912
- return Array.isArray(value) || (isObject(value) && !objectHasFunction(value));
913
- }
914
- function markFieldsDirty(data, fields = {}) {
915
- for (const key in data) {
916
- const value = data[key];
917
- if (isTraversable(value)) {
918
- fields[key] = Array.isArray(value) ? [] : {};
919
- markFieldsDirty(value, fields[key]);
920
- }
921
- else if (!isUndefined(value)) {
922
- fields[key] = true;
923
- }
924
- }
925
- return fields;
926
- }
927
- function getDirtyFields(data, formValues, dirtyFieldsFromValues) {
928
- if (!dirtyFieldsFromValues) {
929
- dirtyFieldsFromValues = markFieldsDirty(formValues);
930
- }
931
- for (const key in data) {
932
- const value = data[key];
933
- if (isTraversable(value)) {
934
- if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
935
- dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {});
936
- }
937
- else {
938
- getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]);
939
- }
940
- }
941
- else {
942
- const formValue = formValues[key];
943
- dirtyFieldsFromValues[key] = !deepEqual(value, formValue);
944
- }
696
+ var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria
697
+ ? {
698
+ ...errors[name],
699
+ types: {
700
+ ...(errors[name] && errors[name].types ? errors[name].types : {}),
701
+ [type]: message || true,
702
+ },
945
703
  }
946
- return dirtyFieldsFromValues;
947
- }
704
+ : {};
948
705
 
949
706
  const defaultResult = {
950
707
  value: false,
@@ -971,20 +728,6 @@ var getCheckboxValue = (options) => {
971
728
  return defaultResult;
972
729
  };
973
730
 
974
- var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
975
- ? value
976
- : valueAsNumber
977
- ? value === ''
978
- ? NaN
979
- : value
980
- ? +value
981
- : value
982
- : valueAsDate && isString(value)
983
- ? new Date(value)
984
- : setValueAs
985
- ? setValueAs(value)
986
- : value;
987
-
988
731
  const defaultReturn = {
989
732
  isValid: false,
990
733
  value: null,
@@ -998,188 +741,6 @@ var getRadioValue = (options) => Array.isArray(options)
998
741
  : previous, defaultReturn)
999
742
  : defaultReturn;
1000
743
 
1001
- function getFieldValue(_f) {
1002
- const ref = _f.ref;
1003
- if (isFileInput(ref)) {
1004
- return ref.files;
1005
- }
1006
- if (isRadioInput(ref)) {
1007
- return getRadioValue(_f.refs).value;
1008
- }
1009
- if (isMultipleSelect(ref)) {
1010
- return [...ref.selectedOptions].map(({ value }) => value);
1011
- }
1012
- if (isCheckBoxInput(ref)) {
1013
- return getCheckboxValue(_f.refs).value;
1014
- }
1015
- return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
1016
- }
1017
-
1018
- var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name;
1019
-
1020
- var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
1021
- const fields = {};
1022
- for (const name of fieldsNames) {
1023
- const field = get(_fields, name);
1024
- field && set(fields, name, field._f);
1025
- }
1026
- return {
1027
- criteriaMode,
1028
- names: [...fieldsNames],
1029
- fields,
1030
- shouldUseNativeValidation,
1031
- };
1032
- };
1033
-
1034
- var isRegex = (value) => value instanceof RegExp;
1035
-
1036
- var getRuleValue = (rule) => isUndefined(rule)
1037
- ? rule
1038
- : isRegex(rule)
1039
- ? rule.source
1040
- : isObject(rule)
1041
- ? isRegex(rule.value)
1042
- ? rule.value.source
1043
- : rule.value
1044
- : rule;
1045
-
1046
- var getValidationModes = (mode) => ({
1047
- isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit,
1048
- isOnBlur: mode === VALIDATION_MODE.onBlur,
1049
- isOnChange: mode === VALIDATION_MODE.onChange,
1050
- isOnAll: mode === VALIDATION_MODE.all,
1051
- isOnTouch: mode === VALIDATION_MODE.onTouched,
1052
- });
1053
-
1054
- const ASYNC_FUNCTION = 'AsyncFunction';
1055
- var hasPromiseValidation = (fieldReference) => !!fieldReference &&
1056
- !!fieldReference.validate &&
1057
- !!((isFunction(fieldReference.validate) &&
1058
- fieldReference.validate.constructor.name === ASYNC_FUNCTION) ||
1059
- (isObject(fieldReference.validate) &&
1060
- Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION)));
1061
-
1062
- var hasValidation = (options) => options.mount &&
1063
- (options.required ||
1064
- options.min ||
1065
- options.max ||
1066
- options.maxLength ||
1067
- options.minLength ||
1068
- options.pattern ||
1069
- options.validate);
1070
-
1071
- var isWatched = (name, _names, isBlurEvent) => !isBlurEvent &&
1072
- (_names.watchAll ||
1073
- _names.watch.has(name) ||
1074
- [..._names.watch].some((watchName) => name.startsWith(watchName) &&
1075
- /^\.\w+/.test(name.slice(watchName.length))));
1076
-
1077
- const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => {
1078
- for (const key of fieldsNames || Object.keys(fields)) {
1079
- const field = get(fields, key);
1080
- if (field) {
1081
- const { _f, ...currentField } = field;
1082
- if (_f) {
1083
- if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) {
1084
- return true;
1085
- }
1086
- else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) {
1087
- return true;
1088
- }
1089
- else {
1090
- if (iterateFieldsByAction(currentField, action)) {
1091
- break;
1092
- }
1093
- }
1094
- }
1095
- else if (isObject(currentField)) {
1096
- if (iterateFieldsByAction(currentField, action)) {
1097
- break;
1098
- }
1099
- }
1100
- }
1101
- }
1102
- return;
1103
- };
1104
-
1105
- function schemaErrorLookup(errors, _fields, name) {
1106
- const error = get(errors, name);
1107
- if (error || isKey(name)) {
1108
- return {
1109
- error,
1110
- name,
1111
- };
1112
- }
1113
- const names = name.split('.');
1114
- while (names.length) {
1115
- const fieldName = names.join('.');
1116
- const field = get(_fields, fieldName);
1117
- const foundError = get(errors, fieldName);
1118
- if (field && !Array.isArray(field) && name !== fieldName) {
1119
- return { name };
1120
- }
1121
- if (foundError && foundError.type) {
1122
- return {
1123
- name: fieldName,
1124
- error: foundError,
1125
- };
1126
- }
1127
- if (foundError && foundError.root && foundError.root.type) {
1128
- return {
1129
- name: `${fieldName}.root`,
1130
- error: foundError.root,
1131
- };
1132
- }
1133
- names.pop();
1134
- }
1135
- return {
1136
- name,
1137
- };
1138
- }
1139
-
1140
- var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
1141
- updateFormState(formStateData);
1142
- const { name, ...formState } = formStateData;
1143
- return (isEmptyObject(formState) ||
1144
- Object.keys(formState).length >= Object.keys(_proxyFormState).length ||
1145
- Object.keys(formState).find((key) => _proxyFormState[key] ===
1146
- (!isRoot || VALIDATION_MODE.all)));
1147
- };
1148
-
1149
- var shouldSubscribeByName = (name, signalName, exact) => !name ||
1150
- !signalName ||
1151
- name === signalName ||
1152
- convertToArrayPayload(name).some((currentName) => currentName &&
1153
- (exact
1154
- ? currentName === signalName
1155
- : currentName.startsWith(signalName) ||
1156
- signalName.startsWith(currentName)));
1157
-
1158
- var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
1159
- if (mode.isOnAll) {
1160
- return false;
1161
- }
1162
- else if (!isSubmitted && mode.isOnTouch) {
1163
- return !(isTouched || isBlurEvent);
1164
- }
1165
- else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
1166
- return !isBlurEvent;
1167
- }
1168
- else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
1169
- return isBlurEvent;
1170
- }
1171
- return true;
1172
- };
1173
-
1174
- var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
1175
-
1176
- var updateFieldArrayRootError = (errors, error, name) => {
1177
- const fieldArrayErrors = convertToArrayPayload(get(errors, name));
1178
- set(fieldArrayErrors, ROOT_ERROR_TYPE, error[name]);
1179
- set(errors, name, fieldArrayErrors);
1180
- return errors;
1181
- };
1182
-
1183
744
  function getValidateError(result, ref, type = 'validate') {
1184
745
  if (isString(result) ||
1185
746
  (Array.isArray(result) && result.every(isString)) ||
@@ -1208,7 +769,13 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
1208
769
  const inputRef = refs ? refs[0] : ref;
1209
770
  const setCustomValidity = (message) => {
1210
771
  if (shouldUseNativeValidation && inputRef.reportValidity) {
1211
- inputRef.setCustomValidity(isBoolean(message) ? '' : message || '');
772
+ const validityMessage = isBoolean(message) ? '' : message || '';
773
+ if (refs) {
774
+ refs.forEach((ref) => ref.setCustomValidity(validityMessage));
775
+ }
776
+ else {
777
+ inputRef.setCustomValidity(validityMessage);
778
+ }
1212
779
  inputRef.reportValidity();
1213
780
  }
1214
781
  };
@@ -1378,374 +945,1420 @@ var validateField = async (field, disabledFieldNames, formValues, validateAllFie
1378
945
  return error;
1379
946
  };
1380
947
 
1381
- const defaultOptions = {
1382
- mode: VALIDATION_MODE.onSubmit,
1383
- reValidateMode: VALIDATION_MODE.onChange,
1384
- shouldFocusError: true,
948
+ var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]);
949
+
950
+ var appendAt = (data, value) => [
951
+ ...data,
952
+ ...convertToArrayPayload(value),
953
+ ];
954
+
955
+ var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
956
+
957
+ function insert(data, index, value) {
958
+ return [
959
+ ...data.slice(0, index),
960
+ ...convertToArrayPayload(value),
961
+ ...data.slice(index),
962
+ ];
963
+ }
964
+
965
+ var moveArrayAt = (data, from, to) => {
966
+ if (!Array.isArray(data)) {
967
+ return [];
968
+ }
969
+ if (isUndefined(data[to])) {
970
+ data[to] = undefined;
971
+ }
972
+ data.splice(to, 0, data.splice(from, 1)[0]);
973
+ return data;
1385
974
  };
1386
- function createFormControl(props = {}) {
1387
- let _options = {
1388
- ...defaultOptions,
1389
- ...props,
1390
- };
1391
- let _formState = {
1392
- submitCount: 0,
1393
- isDirty: false,
1394
- isReady: false,
1395
- isLoading: isFunction(_options.defaultValues),
1396
- isValidating: false,
1397
- isSubmitted: false,
1398
- isSubmitting: false,
1399
- isSubmitSuccessful: false,
1400
- isValid: false,
1401
- touchedFields: {},
1402
- dirtyFields: {},
1403
- validatingFields: {},
1404
- errors: _options.errors || {},
1405
- disabled: _options.disabled || false,
1406
- };
1407
- let _fields = {};
1408
- let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
1409
- ? cloneObject(_options.defaultValues || _options.values) || {}
1410
- : {};
1411
- let _formValues = _options.shouldUnregister
1412
- ? {}
1413
- : cloneObject(_defaultValues);
1414
- let _state = {
1415
- action: false,
1416
- mount: false,
1417
- watch: false,
1418
- keepIsValid: false,
1419
- };
1420
- let _names = {
1421
- mount: new Set(),
1422
- disabled: new Set(),
1423
- unMount: new Set(),
1424
- array: new Set(),
1425
- watch: new Set(),
1426
- registerName: new Set(),
1427
- };
1428
- let delayErrorCallback;
1429
- let timer = 0;
1430
- const defaultProxyFormState = {
1431
- isDirty: false,
1432
- dirtyFields: false,
1433
- validatingFields: false,
1434
- touchedFields: false,
1435
- isValidating: false,
1436
- isValid: false,
1437
- errors: false,
1438
- };
1439
- const _proxyFormState = {
1440
- ...defaultProxyFormState,
1441
- };
1442
- let _proxySubscribeFormState = {
1443
- ..._proxyFormState,
1444
- };
1445
- const _subjects = {
1446
- array: createSubject(),
1447
- state: createSubject(),
1448
- };
1449
- const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
1450
- const debounce = (callback) => (wait) => {
1451
- clearTimeout(timer);
1452
- timer = setTimeout(callback, wait);
1453
- };
1454
- const _setValid = async (shouldUpdateValid) => {
1455
- if (_state.keepIsValid) {
1456
- return;
975
+
976
+ var prependAt = (data, value) => [
977
+ ...convertToArrayPayload(value),
978
+ ...convertToArrayPayload(data),
979
+ ];
980
+
981
+ var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : [];
982
+
983
+ function removeAtIndexes(data, indexes) {
984
+ let i = 0;
985
+ const temp = [...data];
986
+ for (const index of indexes) {
987
+ temp.splice(index - i, 1);
988
+ i++;
989
+ }
990
+ return compact(temp).length ? temp : [];
991
+ }
992
+ var removeArrayAt = (data, index) => isUndefined(index)
993
+ ? []
994
+ : removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
995
+
996
+ var swapArrayAt = (data, indexA, indexB) => {
997
+ [data[indexA], data[indexB]] = [data[indexB], data[indexA]];
998
+ };
999
+
1000
+ function baseGet(object, updatePath) {
1001
+ const length = updatePath.slice(0, -1).length;
1002
+ let index = 0;
1003
+ while (index < length) {
1004
+ if (isNullOrUndefined(object)) {
1005
+ object = undefined;
1006
+ break;
1457
1007
  }
1458
- if (!_options.disabled &&
1459
- (_proxyFormState.isValid ||
1460
- _proxySubscribeFormState.isValid ||
1461
- shouldUpdateValid)) {
1462
- let isValid;
1463
- if (_options.resolver) {
1464
- isValid = isEmptyObject((await _runSchema()).errors);
1465
- _updateIsValidating();
1466
- }
1467
- else {
1468
- isValid = await executeBuiltInValidation({
1469
- fields: _fields,
1470
- onlyCheckValid: true,
1471
- eventType: EVENTS.VALID,
1472
- });
1473
- }
1474
- if (isValid !== _formState.isValid) {
1475
- _subjects.state.next({
1476
- isValid,
1477
- });
1478
- }
1008
+ object = object[updatePath[index]];
1009
+ index++;
1010
+ }
1011
+ return object;
1012
+ }
1013
+ function isEmptyArray(obj) {
1014
+ for (const key in obj) {
1015
+ if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) {
1016
+ return false;
1479
1017
  }
1480
- };
1481
- const _updateIsValidating = (names, isValidating) => {
1482
- if (!_options.disabled &&
1483
- (_proxyFormState.isValidating ||
1484
- _proxyFormState.validatingFields ||
1485
- _proxySubscribeFormState.isValidating ||
1486
- _proxySubscribeFormState.validatingFields)) {
1487
- (names || Array.from(_names.mount)).forEach((name) => {
1488
- if (name) {
1489
- isValidating
1490
- ? set(_formState.validatingFields, name, isValidating)
1491
- : unset(_formState.validatingFields, name);
1018
+ }
1019
+ return true;
1020
+ }
1021
+ function unset(object, path) {
1022
+ if (isString(path) && Object.prototype.hasOwnProperty.call(object, path)) {
1023
+ delete object[path];
1024
+ return object;
1025
+ }
1026
+ const paths = Array.isArray(path)
1027
+ ? path
1028
+ : isKey(path)
1029
+ ? [path]
1030
+ : stringToPath(path);
1031
+ if (paths.some((segment) => PROTOTYPE_KEYWORDS.includes(String(segment)))) {
1032
+ return object;
1033
+ }
1034
+ const childObject = paths.length === 1 ? object : baseGet(object, paths);
1035
+ const index = paths.length - 1;
1036
+ const key = paths[index];
1037
+ if (childObject) {
1038
+ delete childObject[key];
1039
+ }
1040
+ if (index !== 0 &&
1041
+ ((isObject(childObject) && isEmptyObject(childObject)) ||
1042
+ (Array.isArray(childObject) && isEmptyArray(childObject)))) {
1043
+ unset(object, paths.slice(0, -1));
1044
+ }
1045
+ return object;
1046
+ }
1047
+
1048
+ var updateAt = (fieldValues, index, value) => {
1049
+ fieldValues[index] = value;
1050
+ return fieldValues;
1051
+ };
1052
+
1053
+ /**
1054
+ * A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A)
1055
+ *
1056
+ * @remarks
1057
+ * [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
1058
+ *
1059
+ * @param props - useFieldArray props
1060
+ *
1061
+ * @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
1062
+ *
1063
+ * @example
1064
+ * ```tsx
1065
+ * function App() {
1066
+ * const { register, control, handleSubmit, reset, trigger, setError } = useForm({
1067
+ * defaultValues: {
1068
+ * test: []
1069
+ * }
1070
+ * });
1071
+ * const { fields, append } = useFieldArray({
1072
+ * control,
1073
+ * name: "test"
1074
+ * });
1075
+ *
1076
+ * return (
1077
+ * <form onSubmit={handleSubmit(data => console.log(data))}>
1078
+ * {fields.map((item, index) => (
1079
+ * <input key={item.id} {...register(`test.${index}.firstName`)} />
1080
+ * ))}
1081
+ * <button type="button" onClick={() => append({ firstName: "bill" })}>
1082
+ * append
1083
+ * </button>
1084
+ * <input type="submit" />
1085
+ * </form>
1086
+ * );
1087
+ * }
1088
+ * ```
1089
+ */
1090
+ function useFieldArray(props) {
1091
+ const formControl = useFormControlContext();
1092
+ const { control = formControl, name, keyName = 'id', disabled, shouldUnregister, rules, } = props;
1093
+ const [fields, setFields] = React.useState(control._getFieldArray(name));
1094
+ const ids = React.useRef(control._getFieldArray(name).map(generateId));
1095
+ const _actioned = React.useRef(false);
1096
+ if (!disabled) {
1097
+ control._names.array.add(name);
1098
+ }
1099
+ React.useMemo(() => !disabled &&
1100
+ rules &&
1101
+ fields.length >= 0 &&
1102
+ control.register(name, rules), [control, name, fields.length, rules, disabled]);
1103
+ useIsomorphicLayoutEffect(() => {
1104
+ if (disabled) {
1105
+ return;
1106
+ }
1107
+ return control._subjects.array.subscribe({
1108
+ next: ({ values, name: fieldArrayName, }) => {
1109
+ if (fieldArrayName === name || !fieldArrayName) {
1110
+ const fieldValues = get(values, name);
1111
+ if (Array.isArray(fieldValues)) {
1112
+ setFields(fieldValues);
1113
+ ids.current = fieldValues.map(generateId);
1114
+ }
1115
+ else if (!fieldArrayName) {
1116
+ setFields([]);
1117
+ ids.current = [];
1118
+ }
1492
1119
  }
1493
- });
1494
- _subjects.state.next({
1495
- validatingFields: _formState.validatingFields,
1496
- isValidating: !isEmptyObject(_formState.validatingFields),
1497
- });
1120
+ },
1121
+ }).unsubscribe;
1122
+ }, [control, name, disabled]);
1123
+ const updateValues = React.useCallback((updatedFieldArrayValues) => {
1124
+ _actioned.current = true;
1125
+ control._setFieldArray(name, updatedFieldArrayValues);
1126
+ }, [control, name]);
1127
+ const append = (value, options) => {
1128
+ if (disabled) {
1129
+ return;
1498
1130
  }
1131
+ const appendValue = convertToArrayPayload(cloneObject(value));
1132
+ const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
1133
+ control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
1134
+ ids.current = appendAt(ids.current, appendValue.map(generateId));
1135
+ updateValues(updatedFieldArrayValues);
1136
+ setFields(updatedFieldArrayValues);
1137
+ control._setFieldArray(name, updatedFieldArrayValues, appendAt, {
1138
+ argA: fillEmptyArray(value),
1139
+ });
1499
1140
  };
1500
- const _updateDirtyFields = (name) => {
1501
- const fullDirtyFields = getDirtyFields(_defaultValues, _formValues);
1502
- const rootName = getNodeParentName(name);
1503
- set(_formState.dirtyFields, rootName, get(fullDirtyFields, rootName));
1504
- };
1505
- const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
1506
- if (args && method && !_options.disabled) {
1507
- _state.action = true;
1508
- if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
1509
- const fieldValues = method(get(_fields, name), args.argA, args.argB);
1510
- shouldSetValues && set(_fields, name, fieldValues);
1511
- }
1512
- if (shouldUpdateFieldsAndState &&
1513
- Array.isArray(get(_formState.errors, name))) {
1514
- const errors = method(get(_formState.errors, name), args.argA, args.argB);
1515
- shouldSetValues && set(_formState.errors, name, errors);
1516
- unsetEmptyArray(_formState.errors, name);
1517
- }
1518
- if ((_proxyFormState.touchedFields ||
1519
- _proxySubscribeFormState.touchedFields) &&
1520
- shouldUpdateFieldsAndState &&
1521
- Array.isArray(get(_formState.touchedFields, name))) {
1522
- const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
1523
- shouldSetValues && set(_formState.touchedFields, name, touchedFields);
1524
- }
1525
- if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
1526
- _updateDirtyFields(name);
1527
- }
1528
- _subjects.state.next({
1529
- name,
1530
- isDirty: _getDirty(name, values),
1531
- dirtyFields: _formState.dirtyFields,
1532
- errors: _formState.errors,
1533
- isValid: _formState.isValid,
1534
- });
1535
- }
1536
- else {
1537
- set(_formValues, name, values);
1141
+ const prepend = (value, options) => {
1142
+ if (disabled) {
1143
+ return;
1538
1144
  }
1539
- };
1540
- const updateErrors = (name, error) => {
1541
- set(_formState.errors, name, error);
1542
- _subjects.state.next({
1543
- errors: _formState.errors,
1145
+ const prependValue = convertToArrayPayload(cloneObject(value));
1146
+ const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
1147
+ control._names.focus = getFocusFieldName(name, 0, options);
1148
+ ids.current = prependAt(ids.current, prependValue.map(generateId));
1149
+ updateValues(updatedFieldArrayValues);
1150
+ setFields(updatedFieldArrayValues);
1151
+ control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
1152
+ argA: fillEmptyArray(value),
1544
1153
  });
1545
1154
  };
1546
- const _setErrors = (errors) => {
1547
- _formState.errors = errors;
1548
- _subjects.state.next({
1549
- errors: _formState.errors,
1550
- isValid: false,
1155
+ const remove = (index) => {
1156
+ if (disabled) {
1157
+ return;
1158
+ }
1159
+ const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
1160
+ ids.current = removeArrayAt(ids.current, index);
1161
+ updateValues(updatedFieldArrayValues);
1162
+ setFields(updatedFieldArrayValues);
1163
+ !Array.isArray(get(control._fields, name)) &&
1164
+ set(control._fields, name, undefined);
1165
+ control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
1166
+ argA: index,
1551
1167
  });
1552
1168
  };
1553
- const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
1554
- const field = get(_fields, name);
1555
- if (field) {
1556
- const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
1557
- isUndefined(defaultValue) ||
1558
- (ref && ref.defaultChecked) ||
1559
- shouldSkipSetValueAs
1560
- ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
1561
- : setFieldValue(name, defaultValue);
1562
- _state.mount && !_state.action && _setValid();
1169
+ const insert$1 = (index, value, options) => {
1170
+ if (disabled) {
1171
+ return;
1563
1172
  }
1173
+ const insertValue = convertToArrayPayload(cloneObject(value));
1174
+ const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
1175
+ control._names.focus = getFocusFieldName(name, index, options);
1176
+ ids.current = insert(ids.current, index, insertValue.map(generateId));
1177
+ updateValues(updatedFieldArrayValues);
1178
+ setFields(updatedFieldArrayValues);
1179
+ control._setFieldArray(name, updatedFieldArrayValues, insert, {
1180
+ argA: index,
1181
+ argB: fillEmptyArray(value),
1182
+ });
1564
1183
  };
1565
- const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
1566
- let shouldUpdateField = false;
1567
- let isPreviousDirty = false;
1568
- const output = {
1569
- name,
1570
- };
1571
- if (!_options.disabled) {
1572
- if (!isBlurEvent || shouldDirty) {
1573
- if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
1574
- isPreviousDirty = _formState.isDirty;
1575
- _formState.isDirty = output.isDirty = _getDirty();
1576
- shouldUpdateField = isPreviousDirty !== output.isDirty;
1577
- }
1578
- const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
1579
- isPreviousDirty = !!get(_formState.dirtyFields, name);
1580
- isCurrentFieldPristine
1581
- ? unset(_formState.dirtyFields, name)
1582
- : set(_formState.dirtyFields, name, true);
1583
- output.dirtyFields = _formState.dirtyFields;
1584
- shouldUpdateField =
1585
- shouldUpdateField ||
1586
- ((_proxyFormState.dirtyFields ||
1587
- _proxySubscribeFormState.dirtyFields) &&
1588
- isPreviousDirty !== !isCurrentFieldPristine);
1589
- }
1590
- if (isBlurEvent) {
1591
- const isPreviousFieldTouched = get(_formState.touchedFields, name);
1592
- if (!isPreviousFieldTouched) {
1593
- set(_formState.touchedFields, name, isBlurEvent);
1594
- output.touchedFields = _formState.touchedFields;
1595
- shouldUpdateField =
1596
- shouldUpdateField ||
1597
- ((_proxyFormState.touchedFields ||
1598
- _proxySubscribeFormState.touchedFields) &&
1599
- isPreviousFieldTouched !== isBlurEvent);
1600
- }
1601
- }
1602
- shouldUpdateField && shouldRender && _subjects.state.next(output);
1603
- }
1604
- return shouldUpdateField ? output : {};
1605
- };
1606
- const shouldRenderByError = (name, isValid, error, fieldState) => {
1607
- const previousFieldError = get(_formState.errors, name);
1608
- const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
1609
- isBoolean(isValid) &&
1610
- _formState.isValid !== isValid;
1611
- if (_options.delayError && error) {
1612
- delayErrorCallback = debounce(() => updateErrors(name, error));
1613
- delayErrorCallback(_options.delayError);
1614
- }
1615
- else {
1616
- clearTimeout(timer);
1617
- delayErrorCallback = null;
1618
- error
1619
- ? set(_formState.errors, name, error)
1620
- : unset(_formState.errors, name);
1621
- }
1622
- if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
1623
- !isEmptyObject(fieldState) ||
1624
- shouldUpdateValid) {
1625
- const updatedFormState = {
1626
- ...fieldState,
1627
- ...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
1628
- errors: _formState.errors,
1629
- name,
1630
- };
1631
- _formState = {
1632
- ..._formState,
1633
- ...updatedFormState,
1634
- };
1635
- _subjects.state.next(updatedFormState);
1184
+ const swap = (indexA, indexB) => {
1185
+ if (disabled) {
1186
+ return;
1636
1187
  }
1188
+ const updatedFieldArrayValues = control._getFieldArray(name);
1189
+ swapArrayAt(updatedFieldArrayValues, indexA, indexB);
1190
+ swapArrayAt(ids.current, indexA, indexB);
1191
+ updateValues(updatedFieldArrayValues);
1192
+ setFields(updatedFieldArrayValues);
1193
+ control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
1194
+ argA: indexA,
1195
+ argB: indexB,
1196
+ }, false);
1637
1197
  };
1638
- const _runSchema = async (name) => {
1639
- _updateIsValidating(name, true);
1640
- return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
1198
+ const move = (from, to) => {
1199
+ if (disabled) {
1200
+ return;
1201
+ }
1202
+ const updatedFieldArrayValues = control._getFieldArray(name);
1203
+ moveArrayAt(updatedFieldArrayValues, from, to);
1204
+ moveArrayAt(ids.current, from, to);
1205
+ updateValues(updatedFieldArrayValues);
1206
+ setFields(updatedFieldArrayValues);
1207
+ control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
1208
+ argA: from,
1209
+ argB: to,
1210
+ }, false);
1641
1211
  };
1642
- const executeSchemaAndUpdateState = async (names) => {
1643
- const { errors } = await _runSchema(names);
1644
- _updateIsValidating(names);
1645
- if (names) {
1646
- for (const name of names) {
1647
- const error = get(errors, name);
1648
- error
1649
- ? set(_formState.errors, name, error)
1650
- : unset(_formState.errors, name);
1651
- }
1212
+ const update = (index, value) => {
1213
+ if (disabled) {
1214
+ return;
1652
1215
  }
1653
- else {
1654
- _formState.errors = errors;
1216
+ const updateValue = cloneObject(value);
1217
+ const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
1218
+ ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
1219
+ updateValues(updatedFieldArrayValues);
1220
+ setFields([...updatedFieldArrayValues]);
1221
+ control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
1222
+ argA: index,
1223
+ argB: updateValue,
1224
+ }, true, false);
1225
+ };
1226
+ const replace = (value) => {
1227
+ if (disabled) {
1228
+ return;
1655
1229
  }
1656
- return errors;
1230
+ const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
1231
+ ids.current = updatedFieldArrayValues.map(generateId);
1232
+ updateValues([...updatedFieldArrayValues]);
1233
+ setFields([...updatedFieldArrayValues]);
1234
+ control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
1657
1235
  };
1658
- const validateForm = async ({ name, eventType, }) => {
1659
- if (props.validate) {
1660
- const result = await props.validate({
1661
- formValues: _formValues,
1662
- formState: _formState,
1663
- name,
1664
- eventType,
1236
+ React.useEffect(() => {
1237
+ if (disabled) {
1238
+ return;
1239
+ }
1240
+ control._state.action = false;
1241
+ isWatched(name, control._names) &&
1242
+ control._subjects.state.next({
1243
+ ...control._formState,
1665
1244
  });
1666
- if (isObject(result)) {
1667
- for (const key in result) {
1668
- const error = result[key];
1669
- if (error) {
1670
- setError(`${FORM_ERROR_TYPE}.${key}`, {
1671
- message: isString(result.message) ? result.message : '',
1672
- type: INPUT_VALIDATION_RULES.validate,
1245
+ const validationModes = getValidationModes(control._options.mode);
1246
+ if (_actioned.current &&
1247
+ (!validationModes.isOnSubmit || control._formState.isSubmitted) &&
1248
+ !getValidationModes(control._options.reValidateMode).isOnSubmit &&
1249
+ !validationModes.isOnBlur) {
1250
+ if (control._options.resolver) {
1251
+ control._runSchema([name]).then((result) => {
1252
+ var _a, _b;
1253
+ control._updateIsValidating([name]);
1254
+ const error = get(result.errors, name);
1255
+ const existingError = get(control._formState.errors, name);
1256
+ const existingErrorType = existingError && (existingError.type || ((_a = existingError.root) === null || _a === void 0 ? void 0 : _a.type));
1257
+ const existingErrorMessage = existingError &&
1258
+ (existingError.message || ((_b = existingError.root) === null || _b === void 0 ? void 0 : _b.message));
1259
+ if (existingError
1260
+ ? (!error && existingErrorType) ||
1261
+ (error &&
1262
+ (existingErrorType !== error.type ||
1263
+ existingErrorMessage !== error.message))
1264
+ : error && error.type) {
1265
+ if (error) {
1266
+ isObject(error) &&
1267
+ !Object.keys(error).some((key) => !Number.isNaN(+key))
1268
+ ? updateFieldArrayRootError(control._formState.errors, { [name]: error }, name)
1269
+ : set(control._formState.errors, name, error);
1270
+ }
1271
+ else {
1272
+ unset(control._formState.errors, name);
1273
+ }
1274
+ control._subjects.state.next({
1275
+ errors: control._formState.errors,
1673
1276
  });
1674
1277
  }
1675
- }
1676
- }
1677
- else if (isString(result) || !result) {
1678
- setError(FORM_ERROR_TYPE, {
1679
- message: result || '',
1680
- type: INPUT_VALIDATION_RULES.validate,
1681
1278
  });
1682
1279
  }
1683
1280
  else {
1684
- clearErrors(FORM_ERROR_TYPE);
1281
+ const field = get(control._fields, name);
1282
+ if (field &&
1283
+ field._f &&
1284
+ !(getValidationModes(control._options.reValidateMode).isOnSubmit &&
1285
+ getValidationModes(control._options.mode).isOnSubmit)) {
1286
+ validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
1287
+ control._subjects.state.next({
1288
+ errors: updateFieldArrayRootError(control._formState.errors, error, name),
1289
+ }));
1290
+ }
1685
1291
  }
1686
- return result;
1687
1292
  }
1688
- return true;
1689
- };
1690
- const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
1691
- valid: true,
1692
- runRootValidation: false,
1693
- }, }) => {
1694
- if (props.validate) {
1695
- context.runRootValidation = true;
1696
- const result = await validateForm({
1293
+ // External updates that change `fields` (e.g. reset() or setValue() on
1294
+ // the array) already notify subscribers with the up-to-date values
1295
+ // themselves, so only re-broadcast here for genuine array method calls.
1296
+ _actioned.current &&
1297
+ control._subjects.state.next({
1697
1298
  name,
1698
- eventType,
1299
+ values: cloneObject(control._formValues),
1699
1300
  });
1700
- if (!result) {
1701
- context.valid = false;
1702
- if (onlyCheckValid) {
1703
- return context.valid;
1301
+ control._names.focus &&
1302
+ iterateFieldsByAction(control._fields, (ref, key) => {
1303
+ if (control._names.focus &&
1304
+ key.startsWith(control._names.focus) &&
1305
+ ref.focus) {
1306
+ ref.focus();
1307
+ return 1;
1704
1308
  }
1705
- }
1309
+ return;
1310
+ });
1311
+ control._names.focus = '';
1312
+ control._setValid();
1313
+ _actioned.current = false;
1314
+ }, [fields, name, control, disabled]);
1315
+ React.useEffect(() => {
1316
+ if (!disabled) {
1317
+ !get(control._formValues, name) && control._setFieldArray(name);
1706
1318
  }
1707
- for (const name in fields) {
1708
- const field = fields[name];
1709
- if (field) {
1710
- const { _f, ...fieldValue } = field;
1711
- if (_f) {
1712
- const isFieldArrayRoot = _names.array.has(_f.name);
1713
- const isPromiseFunction = field._f && hasPromiseValidation(field._f);
1714
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1715
- _updateIsValidating([_f.name], true);
1716
- }
1717
- const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
1718
- if (isPromiseFunction && _proxyFormState.validatingFields) {
1719
- _updateIsValidating([_f.name]);
1720
- }
1721
- if (fieldError[_f.name]) {
1722
- context.valid = false;
1723
- if (onlyCheckValid) {
1724
- break;
1725
- }
1726
- }
1727
- !onlyCheckValid &&
1728
- (get(fieldError, _f.name)
1729
- ? isFieldArrayRoot
1730
- ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
1731
- : set(_formState.errors, _f.name, fieldError[_f.name])
1732
- : unset(_formState.errors, _f.name));
1733
- if (props.shouldUseNativeValidation && fieldError[_f.name]) {
1734
- break;
1735
- }
1319
+ return () => {
1320
+ if (disabled) {
1321
+ return;
1322
+ }
1323
+ const shouldKeepFieldArrayValues = !(control._options.shouldUnregister || shouldUnregister);
1324
+ const updateMounted = (name, value) => {
1325
+ const field = get(control._fields, name);
1326
+ if (field && field._f) {
1327
+ field._f.mount = value;
1736
1328
  }
1737
- !isEmptyObject(fieldValue) &&
1738
- (await executeBuiltInValidation({
1739
- context,
1740
- onlyCheckValid,
1741
- fields: fieldValue,
1742
- name: name,
1743
- eventType,
1744
- }));
1329
+ };
1330
+ if (_actioned.current && shouldKeepFieldArrayValues) {
1331
+ control._subjects.state.next({
1332
+ name,
1333
+ values: cloneObject(control._formValues),
1334
+ });
1745
1335
  }
1746
- }
1747
- return context.valid;
1748
- };
1336
+ shouldKeepFieldArrayValues
1337
+ ? updateMounted(name, false)
1338
+ : control.unregister(name);
1339
+ };
1340
+ }, [name, control, keyName, shouldUnregister, disabled]);
1341
+ return {
1342
+ swap: React.useCallback(swap, [updateValues, name, control, disabled]),
1343
+ move: React.useCallback(move, [updateValues, name, control, disabled]),
1344
+ prepend: React.useCallback(prepend, [
1345
+ updateValues,
1346
+ name,
1347
+ control,
1348
+ disabled,
1349
+ ]),
1350
+ append: React.useCallback(append, [updateValues, name, control, disabled]),
1351
+ remove: React.useCallback(remove, [updateValues, name, control, disabled]),
1352
+ insert: React.useCallback(insert$1, [updateValues, name, control, disabled]),
1353
+ update: React.useCallback(update, [updateValues, name, control, disabled]),
1354
+ replace: React.useCallback(replace, [
1355
+ updateValues,
1356
+ name,
1357
+ control,
1358
+ disabled,
1359
+ ]),
1360
+ fields: React.useMemo(() => fields.map((field, index) => ({
1361
+ ...field,
1362
+ ...(isBoolean(disabled) ? { disabled } : {}),
1363
+ [keyName]: ids.current[index] || generateId(),
1364
+ })), [fields, keyName, disabled]),
1365
+ };
1366
+ }
1367
+
1368
+ /**
1369
+ * Component based on `useFieldArray` hook to work with controlled component.
1370
+ *
1371
+ * @example
1372
+ * ```tsx
1373
+ * function App() {
1374
+ * const { control, register } = useForm<FormValues>({
1375
+ * defaultValues: {
1376
+ * test: [
1377
+ * {
1378
+ * value: '',
1379
+ * },
1380
+ * ],
1381
+ * },
1382
+ * });
1383
+ *
1384
+ * return (
1385
+ * <form>
1386
+ * <FieldArray
1387
+ * control={control}
1388
+ * name="test"
1389
+ * render={({ fields }) =>
1390
+ * fields.map((field, index) => (
1391
+ * <input key={field.id} {...register(`test.${index}.value`)} />
1392
+ * ))
1393
+ * }
1394
+ * />
1395
+ * </form>
1396
+ * );
1397
+ * }
1398
+ * ```
1399
+ */
1400
+ const FieldArray = (props) => props.render(useFieldArray(props));
1401
+
1402
+ const flatten = (obj) => {
1403
+ const output = {};
1404
+ for (const key of Object.keys(obj)) {
1405
+ if (isObjectType(obj[key]) &&
1406
+ obj[key] !== null &&
1407
+ !isDateObject(obj[key])) {
1408
+ const nested = flatten(obj[key]);
1409
+ for (const nestedKey of Object.keys(nested)) {
1410
+ output[`${key}.${nestedKey}`] = nested[nestedKey];
1411
+ }
1412
+ }
1413
+ else {
1414
+ output[key] = obj[key];
1415
+ }
1416
+ }
1417
+ return output;
1418
+ };
1419
+
1420
+ const HookFormContext = React.createContext(null);
1421
+ HookFormContext.displayName = 'HookFormContext';
1422
+ /**
1423
+ * This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}.
1424
+ *
1425
+ * @remarks
1426
+ * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
1427
+ *
1428
+ * @returns return all useForm methods
1429
+ *
1430
+ * @example
1431
+ * ```tsx
1432
+ * function App() {
1433
+ * const methods = useForm();
1434
+ * const onSubmit = data => console.log(data);
1435
+ *
1436
+ * return (
1437
+ * <FormProvider {...methods} >
1438
+ * <form onSubmit={methods.handleSubmit(onSubmit)}>
1439
+ * <NestedInput />
1440
+ * <input type="submit" />
1441
+ * </form>
1442
+ * </FormProvider>
1443
+ * );
1444
+ * }
1445
+ *
1446
+ * function NestedInput() {
1447
+ * const { register } = useFormContext(); // retrieve all hook methods
1448
+ * return <input {...register("test")} />;
1449
+ * }
1450
+ * ```
1451
+ */
1452
+ const useFormContext = () => React.useContext(HookFormContext);
1453
+ /**
1454
+ * A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}.
1455
+ *
1456
+ * @remarks
1457
+ * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi)
1458
+ *
1459
+ * @param props - all useForm methods
1460
+ *
1461
+ * @example
1462
+ * ```tsx
1463
+ * function App() {
1464
+ * const methods = useForm();
1465
+ * const onSubmit = data => console.log(data);
1466
+ *
1467
+ * return (
1468
+ * <FormProvider {...methods} >
1469
+ * <form onSubmit={methods.handleSubmit(onSubmit)}>
1470
+ * <NestedInput />
1471
+ * <input type="submit" />
1472
+ * </form>
1473
+ * </FormProvider>
1474
+ * );
1475
+ * }
1476
+ *
1477
+ * function NestedInput() {
1478
+ * const { register } = useFormContext(); // retrieve all hook methods
1479
+ * return <input {...register("test")} />;
1480
+ * }
1481
+ * ```
1482
+ */
1483
+ const FormProvider = ({ children, watch, getValues, getFieldState, setError, clearErrors, setValue, setValues, trigger, formState, resetField, reset, resetDefaultValues, handleSubmit, unregister, control, register, setFocus, subscribe, }) => {
1484
+ const memoizedValue = React.useMemo(() => ({
1485
+ watch,
1486
+ getValues,
1487
+ getFieldState,
1488
+ setError,
1489
+ clearErrors,
1490
+ setValue,
1491
+ setValues,
1492
+ trigger,
1493
+ formState,
1494
+ resetField,
1495
+ reset,
1496
+ resetDefaultValues,
1497
+ handleSubmit,
1498
+ unregister,
1499
+ control,
1500
+ register,
1501
+ setFocus,
1502
+ subscribe,
1503
+ }), [
1504
+ clearErrors,
1505
+ control,
1506
+ formState,
1507
+ getFieldState,
1508
+ getValues,
1509
+ handleSubmit,
1510
+ register,
1511
+ reset,
1512
+ resetDefaultValues,
1513
+ resetField,
1514
+ setError,
1515
+ setFocus,
1516
+ setValue,
1517
+ setValues,
1518
+ subscribe,
1519
+ trigger,
1520
+ unregister,
1521
+ watch,
1522
+ ]);
1523
+ return (React.createElement(HookFormContext.Provider, { value: memoizedValue },
1524
+ React.createElement(HookFormControlContext.Provider, { value: memoizedValue.control }, children)));
1525
+ };
1526
+
1527
+ const POST_REQUEST = 'post';
1528
+ /**
1529
+ * Form component to manage submission.
1530
+ *
1531
+ * @param props - to setup submission detail. {@link FormProps}
1532
+ *
1533
+ * @returns form component or headless render prop.
1534
+ *
1535
+ * @example
1536
+ * ```tsx
1537
+ * function App() {
1538
+ * const { control, formState: { errors } } = useForm();
1539
+ *
1540
+ * return (
1541
+ * <Form action="/api" control={control}>
1542
+ * <input {...register("name")} />
1543
+ * <p>{errors?.root?.server && 'Server error'}</p>
1544
+ * <button>Submit</button>
1545
+ * </Form>
1546
+ * );
1547
+ * }
1548
+ * ```
1549
+ */
1550
+ function Form(props) {
1551
+ const methods = useFormContext();
1552
+ const [mounted, setMounted] = React.useState(false);
1553
+ const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props;
1554
+ const submit = React.useCallback(async (event) => {
1555
+ let hasError = false;
1556
+ let type = '';
1557
+ await control.handleSubmit(async (data) => {
1558
+ const formData = new FormData();
1559
+ let formDataJson = '';
1560
+ try {
1561
+ formDataJson = JSON.stringify(data);
1562
+ }
1563
+ catch (_a) { }
1564
+ const flattenFormValues = flatten(data);
1565
+ for (const key in flattenFormValues) {
1566
+ formData.append(key, flattenFormValues[key]);
1567
+ }
1568
+ if (onSubmit) {
1569
+ await onSubmit({
1570
+ data,
1571
+ event,
1572
+ method,
1573
+ formData,
1574
+ formDataJson,
1575
+ });
1576
+ }
1577
+ if (action) {
1578
+ try {
1579
+ const shouldStringifySubmissionData = [
1580
+ headers && headers['Content-Type'],
1581
+ encType,
1582
+ ].some((value) => value && value.includes('json'));
1583
+ const response = await fetch(String(action), {
1584
+ method,
1585
+ headers: {
1586
+ ...headers,
1587
+ ...(encType && encType !== 'multipart/form-data'
1588
+ ? { 'Content-Type': encType }
1589
+ : {}),
1590
+ },
1591
+ body: shouldStringifySubmissionData ? formDataJson : formData,
1592
+ });
1593
+ if (response &&
1594
+ (validateStatus
1595
+ ? !validateStatus(response.status)
1596
+ : response.status < 200 || response.status >= 300)) {
1597
+ hasError = true;
1598
+ onError && onError({ response });
1599
+ type = String(response.status);
1600
+ }
1601
+ else {
1602
+ onSuccess && onSuccess({ response });
1603
+ }
1604
+ }
1605
+ catch (error) {
1606
+ hasError = true;
1607
+ onError && onError({ error });
1608
+ }
1609
+ }
1610
+ })(event);
1611
+ if (hasError && control) {
1612
+ control._subjects.state.next({
1613
+ isSubmitSuccessful: false,
1614
+ });
1615
+ control.setError('root.server', {
1616
+ type,
1617
+ });
1618
+ }
1619
+ }, [
1620
+ control,
1621
+ onSubmit,
1622
+ method,
1623
+ action,
1624
+ headers,
1625
+ encType,
1626
+ validateStatus,
1627
+ onError,
1628
+ onSuccess,
1629
+ ]);
1630
+ React.useEffect(() => {
1631
+ setMounted(true);
1632
+ }, []);
1633
+ return render ? (React.createElement(React.Fragment, null, render({
1634
+ submit,
1635
+ }))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children));
1636
+ }
1637
+
1638
+ const FormStateSubscribe = ({ control, disabled, exact, name, render, }) => render(useFormState({ control, name, disabled, exact }));
1639
+
1640
+ var createSubject = () => {
1641
+ let _observers = [];
1642
+ const next = (value) => {
1643
+ for (const observer of _observers) {
1644
+ observer.next && observer.next(value);
1645
+ }
1646
+ };
1647
+ const subscribe = (observer) => {
1648
+ _observers.push(observer);
1649
+ return {
1650
+ unsubscribe: () => {
1651
+ _observers = _observers.filter((o) => o !== observer);
1652
+ },
1653
+ };
1654
+ };
1655
+ const unsubscribe = () => {
1656
+ _observers = [];
1657
+ };
1658
+ return {
1659
+ get observers() {
1660
+ return _observers;
1661
+ },
1662
+ next,
1663
+ subscribe,
1664
+ unsubscribe,
1665
+ };
1666
+ };
1667
+
1668
+ function extractFormValues(fieldsState, formValues) {
1669
+ const values = {};
1670
+ for (const key in fieldsState) {
1671
+ if (fieldsState.hasOwnProperty(key)) {
1672
+ const fieldState = fieldsState[key];
1673
+ const fieldValue = formValues[key];
1674
+ if (fieldState && isObject(fieldState) && fieldValue) {
1675
+ const nestedFieldsState = extractFormValues(fieldState, fieldValue);
1676
+ if (isObject(nestedFieldsState)) {
1677
+ values[key] = nestedFieldsState;
1678
+ }
1679
+ }
1680
+ else if (fieldsState[key]) {
1681
+ values[key] = fieldValue;
1682
+ }
1683
+ }
1684
+ }
1685
+ return values;
1686
+ }
1687
+
1688
+ var isMultipleSelect = (element) => element.type === `select-multiple`;
1689
+
1690
+ var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref);
1691
+
1692
+ var live = (ref) => isHTMLElement(ref) && ref.isConnected;
1693
+
1694
+ var objectHasFunction = (data) => {
1695
+ for (const key in data) {
1696
+ if (isFunction(data[key])) {
1697
+ return true;
1698
+ }
1699
+ }
1700
+ return false;
1701
+ };
1702
+
1703
+ function isTraversable(value) {
1704
+ return Array.isArray(value) || (isObject(value) && !objectHasFunction(value));
1705
+ }
1706
+ function isRegisteredLeaf(fieldRef) {
1707
+ return !!(fieldRef && '_f' in fieldRef);
1708
+ }
1709
+ function isEmptyDirtyContainer(value) {
1710
+ return Array.isArray(value)
1711
+ ? !value.some((item) => !isUndefined(item))
1712
+ : !Object.keys(value).length;
1713
+ }
1714
+ function clearDirtyField(container, key) {
1715
+ if (Array.isArray(container)) {
1716
+ container[key] = undefined;
1717
+ }
1718
+ else {
1719
+ delete container[key];
1720
+ }
1721
+ }
1722
+ function markFieldsDirty(data, fields = {}, fieldRefs) {
1723
+ for (const key in data) {
1724
+ const value = data[key];
1725
+ const fieldRef = fieldRefs && fieldRefs[key];
1726
+ if (isTraversable(value) &&
1727
+ (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
1728
+ fields[key] = Array.isArray(value) ? [] : {};
1729
+ markFieldsDirty(value, fields[key], fieldRef);
1730
+ if (isEmptyDirtyContainer(fields[key])) {
1731
+ clearDirtyField(fields, key);
1732
+ }
1733
+ }
1734
+ else if (!isUndefined(value)) {
1735
+ fields[key] = true;
1736
+ }
1737
+ }
1738
+ return fields;
1739
+ }
1740
+ function getDirtyFields(data, formValues, dirtyFieldsFromValues, fieldRefs) {
1741
+ if (!dirtyFieldsFromValues) {
1742
+ dirtyFieldsFromValues = markFieldsDirty(formValues, {}, fieldRefs);
1743
+ }
1744
+ for (const key in data) {
1745
+ const value = data[key];
1746
+ const fieldRef = fieldRefs && fieldRefs[key];
1747
+ if (isTraversable(value) &&
1748
+ (!Array.isArray(value) || !isRegisteredLeaf(fieldRef))) {
1749
+ if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) {
1750
+ dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}, fieldRef);
1751
+ }
1752
+ else {
1753
+ getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key], fieldRef);
1754
+ }
1755
+ if (isEmptyDirtyContainer(dirtyFieldsFromValues[key])) {
1756
+ clearDirtyField(dirtyFieldsFromValues, key);
1757
+ }
1758
+ }
1759
+ else if (deepEqual(value, formValues[key])) {
1760
+ clearDirtyField(dirtyFieldsFromValues, key);
1761
+ }
1762
+ else {
1763
+ dirtyFieldsFromValues[key] = true;
1764
+ }
1765
+ }
1766
+ return dirtyFieldsFromValues;
1767
+ }
1768
+
1769
+ var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value)
1770
+ ? value
1771
+ : valueAsNumber
1772
+ ? value === ''
1773
+ ? NaN
1774
+ : value
1775
+ ? +value
1776
+ : value
1777
+ : valueAsDate && isString(value)
1778
+ ? new Date(value)
1779
+ : setValueAs
1780
+ ? setValueAs(value)
1781
+ : value;
1782
+
1783
+ function getFieldValue(_f) {
1784
+ const ref = _f.ref;
1785
+ if (isFileInput(ref)) {
1786
+ return ref.files;
1787
+ }
1788
+ if (isRadioInput(ref)) {
1789
+ return getRadioValue(_f.refs).value;
1790
+ }
1791
+ if (isMultipleSelect(ref)) {
1792
+ return [...ref.selectedOptions].map(({ value }) => value);
1793
+ }
1794
+ if (isCheckBoxInput(ref)) {
1795
+ return getCheckboxValue(_f.refs).value;
1796
+ }
1797
+ return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f);
1798
+ }
1799
+
1800
+ var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => {
1801
+ const fields = {};
1802
+ for (const name of fieldsNames) {
1803
+ const field = get(_fields, name);
1804
+ field && set(fields, name, field._f);
1805
+ }
1806
+ return {
1807
+ criteriaMode,
1808
+ names: [...fieldsNames],
1809
+ fields,
1810
+ shouldUseNativeValidation,
1811
+ };
1812
+ };
1813
+
1814
+ var getRuleValue = (rule) => isUndefined(rule)
1815
+ ? rule
1816
+ : isRegex(rule)
1817
+ ? rule.source
1818
+ : isObject(rule)
1819
+ ? isRegex(rule.value)
1820
+ ? rule.value.source
1821
+ : rule.value
1822
+ : rule;
1823
+
1824
+ const ASYNC_FUNCTION = 'AsyncFunction';
1825
+ var hasPromiseValidation = (fieldReference) => {
1826
+ if (!fieldReference || !fieldReference.validate)
1827
+ return false;
1828
+ if (isFunction(fieldReference.validate)) {
1829
+ return fieldReference.validate.constructor.name === ASYNC_FUNCTION;
1830
+ }
1831
+ if (isObject(fieldReference.validate)) {
1832
+ for (const key in fieldReference.validate) {
1833
+ if (fieldReference.validate[key].constructor
1834
+ .name === ASYNC_FUNCTION) {
1835
+ return true;
1836
+ }
1837
+ }
1838
+ }
1839
+ return false;
1840
+ };
1841
+
1842
+ var hasValidation = (options) => options.mount &&
1843
+ (options.required ||
1844
+ options.min ||
1845
+ options.max ||
1846
+ options.maxLength ||
1847
+ options.minLength ||
1848
+ options.pattern ||
1849
+ options.validate);
1850
+
1851
+ function schemaErrorLookup(errors, _fields, name) {
1852
+ const error = get(errors, name);
1853
+ if (error || isKey(name)) {
1854
+ return {
1855
+ error,
1856
+ name,
1857
+ };
1858
+ }
1859
+ const names = name.split('.');
1860
+ while (names.length) {
1861
+ const fieldName = names.join('.');
1862
+ const field = get(_fields, fieldName);
1863
+ const foundError = get(errors, fieldName);
1864
+ if (field && !Array.isArray(field) && name !== fieldName) {
1865
+ return { name };
1866
+ }
1867
+ if (foundError && foundError.type) {
1868
+ return {
1869
+ name: fieldName,
1870
+ error: foundError,
1871
+ };
1872
+ }
1873
+ if (foundError && foundError.root && foundError.root.type) {
1874
+ return {
1875
+ name: `${fieldName}.root`,
1876
+ error: foundError.root,
1877
+ };
1878
+ }
1879
+ names.pop();
1880
+ }
1881
+ return {
1882
+ name,
1883
+ };
1884
+ }
1885
+
1886
+ var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => {
1887
+ updateFormState(formStateData);
1888
+ const { name, ...formState } = formStateData;
1889
+ const keys = Object.keys(formState);
1890
+ return (!keys.length ||
1891
+ (isRoot && keys.length >= Object.keys(_proxyFormState).length) ||
1892
+ keys.find((key) => _proxyFormState[key] ===
1893
+ (!isRoot || VALIDATION_MODE.all)));
1894
+ };
1895
+
1896
+ var shouldSubscribeByName = (name, signalName, exact) => !name ||
1897
+ !signalName ||
1898
+ name === signalName ||
1899
+ convertToArrayPayload(name).some((currentName) => currentName &&
1900
+ (exact
1901
+ ? currentName === signalName || currentName.startsWith(signalName + '.')
1902
+ : currentName.startsWith(signalName) ||
1903
+ signalName.startsWith(currentName)));
1904
+
1905
+ var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => {
1906
+ if (mode.isOnAll) {
1907
+ return false;
1908
+ }
1909
+ else if (!isSubmitted && mode.isOnTouch) {
1910
+ return !(isTouched || isBlurEvent);
1911
+ }
1912
+ else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) {
1913
+ return !isBlurEvent;
1914
+ }
1915
+ else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) {
1916
+ return isBlurEvent;
1917
+ }
1918
+ return true;
1919
+ };
1920
+
1921
+ var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name);
1922
+
1923
+ const defaultOptions = {
1924
+ mode: VALIDATION_MODE.onSubmit,
1925
+ reValidateMode: VALIDATION_MODE.onChange,
1926
+ shouldFocusError: true,
1927
+ };
1928
+ const FORM_ERROR_TYPE = 'form';
1929
+ const updateDirtyFields = (dirtyFields, nextDirtyFields) => {
1930
+ for (const key in dirtyFields) {
1931
+ if (!(key in nextDirtyFields)) {
1932
+ delete dirtyFields[key];
1933
+ }
1934
+ }
1935
+ Object.assign(dirtyFields, nextDirtyFields);
1936
+ };
1937
+ const DEFAULT_FORM_STATE = {
1938
+ submitCount: 0,
1939
+ isDirty: false,
1940
+ isReady: false,
1941
+ isValidating: false,
1942
+ isSubmitted: false,
1943
+ isSubmitting: false,
1944
+ isSubmitSuccessful: false,
1945
+ isValid: false,
1946
+ touchedFields: {},
1947
+ dirtyFields: {},
1948
+ validatingFields: {},
1949
+ };
1950
+ function createFormControl(props = {}) {
1951
+ let _options = {
1952
+ ...defaultOptions,
1953
+ ...props,
1954
+ };
1955
+ let _formState = {
1956
+ ...cloneObject(DEFAULT_FORM_STATE),
1957
+ isLoading: isFunction(_options.defaultValues),
1958
+ errors: _options.errors || {},
1959
+ disabled: _options.disabled || false,
1960
+ };
1961
+ let _fields = {};
1962
+ let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values)
1963
+ ? cloneObject(_options.defaultValues || _options.values) || {}
1964
+ : {};
1965
+ let _formValues = _options.shouldUnregister
1966
+ ? {}
1967
+ : cloneObject(_defaultValues);
1968
+ let _state = {
1969
+ action: false,
1970
+ mount: false,
1971
+ watch: false,
1972
+ keepIsValid: false,
1973
+ };
1974
+ let _names = {
1975
+ mount: new Set(),
1976
+ disabled: new Set(),
1977
+ unMount: new Set(),
1978
+ array: new Set(),
1979
+ watch: new Set(),
1980
+ registerName: new Set(),
1981
+ };
1982
+ const delayErrorCallbacks = {};
1983
+ const timers = {};
1984
+ let _valuesSubscriberCount = 0;
1985
+ let _validationModeBeforeSubmit = getValidationModes(_options.mode);
1986
+ let _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1987
+ const defaultProxyFormState = {
1988
+ isDirty: false,
1989
+ dirtyFields: false,
1990
+ validatingFields: false,
1991
+ touchedFields: false,
1992
+ isValidating: false,
1993
+ isValid: false,
1994
+ errors: false,
1995
+ };
1996
+ const _proxyFormState = {
1997
+ ...defaultProxyFormState,
1998
+ };
1999
+ let _proxySubscribeFormState = {
2000
+ ..._proxyFormState,
2001
+ };
2002
+ const _subjects = {
2003
+ array: createSubject(),
2004
+ state: createSubject(),
2005
+ };
2006
+ let _setValidCallId = 0;
2007
+ const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all;
2008
+ const debounce = (name, callback) => (wait) => {
2009
+ clearTimeout(timers[name]);
2010
+ timers[name] = setTimeout(callback, wait);
2011
+ };
2012
+ const _setValid = async (shouldUpdateValid) => {
2013
+ if (_state.keepIsValid) {
2014
+ return;
2015
+ }
2016
+ if (!_options.disabled &&
2017
+ (_proxyFormState.isValid ||
2018
+ _proxySubscribeFormState.isValid ||
2019
+ shouldUpdateValid)) {
2020
+ const callId = ++_setValidCallId;
2021
+ let isValid;
2022
+ if (_options.resolver) {
2023
+ isValid = isEmptyObject((await _runSchema()).errors);
2024
+ callId === _setValidCallId && _updateIsValidating();
2025
+ }
2026
+ else {
2027
+ isValid = await executeBuiltInValidation({
2028
+ fields: _fields,
2029
+ onlyCheckValid: true,
2030
+ eventType: EVENTS.VALID,
2031
+ });
2032
+ }
2033
+ if (callId === _setValidCallId && isValid !== _formState.isValid) {
2034
+ _subjects.state.next({
2035
+ isValid,
2036
+ });
2037
+ }
2038
+ }
2039
+ };
2040
+ const _updateIsValidating = (names, isValidating) => {
2041
+ if (!_options.disabled &&
2042
+ (_proxyFormState.isValidating ||
2043
+ _proxyFormState.validatingFields ||
2044
+ _proxySubscribeFormState.isValidating ||
2045
+ _proxySubscribeFormState.validatingFields)) {
2046
+ (names || Array.from(_names.mount)).forEach((name) => {
2047
+ if (name) {
2048
+ isValidating
2049
+ ? set(_formState.validatingFields, name, isValidating)
2050
+ : unset(_formState.validatingFields, name);
2051
+ }
2052
+ });
2053
+ _subjects.state.next({
2054
+ validatingFields: _formState.validatingFields,
2055
+ isValidating: !isEmptyObject(_formState.validatingFields),
2056
+ });
2057
+ }
2058
+ };
2059
+ const _updateDirtyFields = () => {
2060
+ _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
2061
+ };
2062
+ const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => {
2063
+ if (args && method && !_options.disabled) {
2064
+ _state.action = true;
2065
+ if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) {
2066
+ const fieldValues = method(get(_fields, name), args.argA, args.argB);
2067
+ shouldSetValues && set(_fields, name, fieldValues);
2068
+ }
2069
+ if (shouldUpdateFieldsAndState &&
2070
+ Array.isArray(get(_formState.errors, name))) {
2071
+ const errors = method(get(_formState.errors, name), args.argA, args.argB);
2072
+ shouldSetValues && set(_formState.errors, name, errors);
2073
+ unsetEmptyArray(_formState.errors, name);
2074
+ }
2075
+ if ((_proxyFormState.touchedFields ||
2076
+ _proxySubscribeFormState.touchedFields) &&
2077
+ shouldUpdateFieldsAndState &&
2078
+ Array.isArray(get(_formState.touchedFields, name))) {
2079
+ const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB);
2080
+ shouldSetValues && set(_formState.touchedFields, name, touchedFields);
2081
+ }
2082
+ if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) {
2083
+ _updateDirtyFields();
2084
+ }
2085
+ _subjects.state.next({
2086
+ name,
2087
+ isDirty: _getDirty(name, values),
2088
+ dirtyFields: _formState.dirtyFields,
2089
+ errors: _formState.errors,
2090
+ isValid: _formState.isValid,
2091
+ });
2092
+ }
2093
+ else {
2094
+ set(_formValues, name, values);
2095
+ }
2096
+ };
2097
+ const updateErrors = (name, error) => {
2098
+ set(_formState.errors, name, error);
2099
+ _formState.errors = { ..._formState.errors };
2100
+ _subjects.state.next({
2101
+ errors: _formState.errors,
2102
+ });
2103
+ };
2104
+ const _setErrors = (errors) => {
2105
+ _formState.errors = errors;
2106
+ _subjects.state.next({
2107
+ errors: _formState.errors,
2108
+ isValid: false,
2109
+ });
2110
+ };
2111
+ const hasExplicitNullIntermediate = (name) => {
2112
+ const segments = isKey(name) ? [name] : stringToPath(name);
2113
+ let formValues = _formValues;
2114
+ let defaultValues = _defaultValues;
2115
+ for (let i = 0; i < segments.length - 1; i++) {
2116
+ const key = segments[i];
2117
+ formValues = isNullOrUndefined(formValues) ? formValues : formValues[key];
2118
+ defaultValues = isNullOrUndefined(defaultValues)
2119
+ ? defaultValues
2120
+ : defaultValues[key];
2121
+ if (formValues === null && defaultValues !== null) {
2122
+ return true;
2123
+ }
2124
+ }
2125
+ return false;
2126
+ };
2127
+ const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => {
2128
+ const field = get(_fields, name);
2129
+ if (field) {
2130
+ if (hasExplicitNullIntermediate(name)) {
2131
+ return;
2132
+ }
2133
+ const wasUnsetInFormValues = isUndefined(get(_formValues, name));
2134
+ const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value);
2135
+ isUndefined(defaultValue) ||
2136
+ (ref && ref.defaultChecked) ||
2137
+ shouldSkipSetValueAs
2138
+ ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f))
2139
+ : setFieldValue(name, defaultValue);
2140
+ if (_state.mount && !_state.action) {
2141
+ _setValid();
2142
+ if (wasUnsetInFormValues &&
2143
+ _formState.isDirty &&
2144
+ (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty)) {
2145
+ const isDirty = _getDirty();
2146
+ if (!isDirty) {
2147
+ _formState.isDirty = false;
2148
+ _subjects.state.next({ ..._formState });
2149
+ }
2150
+ }
2151
+ if (props.shouldUnregister &&
2152
+ wasUnsetInFormValues &&
2153
+ !isUndefined(get(_formValues, name)) &&
2154
+ isWatched(name, _names)) {
2155
+ _state.watch = true;
2156
+ }
2157
+ }
2158
+ }
2159
+ };
2160
+ const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => {
2161
+ let shouldUpdateField = false;
2162
+ let isPreviousDirty = false;
2163
+ const output = {
2164
+ name,
2165
+ };
2166
+ // an explicit programmatic update (e.g. setValue with shouldDirty: true)
2167
+ // opts into dirty tracking even when the form is disabled
2168
+ if (!_options.disabled || shouldDirty === true) {
2169
+ if (!isBlurEvent || shouldDirty) {
2170
+ const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue);
2171
+ if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) {
2172
+ isPreviousDirty = _formState.isDirty;
2173
+ _formState.isDirty = output.isDirty =
2174
+ !isCurrentFieldPristine || _getDirty();
2175
+ shouldUpdateField = isPreviousDirty !== output.isDirty;
2176
+ }
2177
+ isPreviousDirty = !!get(_formState.dirtyFields, name);
2178
+ if (isCurrentFieldPristine !== _formState.isDirty) {
2179
+ updateDirtyFields(_formState.dirtyFields, getDirtyFields(_defaultValues, _formValues, undefined, _fields));
2180
+ }
2181
+ else {
2182
+ isCurrentFieldPristine
2183
+ ? unset(_formState.dirtyFields, name)
2184
+ : set(_formState.dirtyFields, name, true);
2185
+ }
2186
+ output.dirtyFields = _formState.dirtyFields;
2187
+ shouldUpdateField =
2188
+ shouldUpdateField ||
2189
+ ((_proxyFormState.dirtyFields ||
2190
+ _proxySubscribeFormState.dirtyFields) &&
2191
+ isPreviousDirty !== !isCurrentFieldPristine);
2192
+ }
2193
+ if (isBlurEvent) {
2194
+ const isPreviousFieldTouched = get(_formState.touchedFields, name);
2195
+ if (!isPreviousFieldTouched) {
2196
+ set(_formState.touchedFields, name, isBlurEvent);
2197
+ output.touchedFields = _formState.touchedFields;
2198
+ shouldUpdateField =
2199
+ shouldUpdateField ||
2200
+ ((_proxyFormState.touchedFields ||
2201
+ _proxySubscribeFormState.touchedFields) &&
2202
+ isPreviousFieldTouched !== isBlurEvent);
2203
+ }
2204
+ }
2205
+ shouldUpdateField && shouldRender && _subjects.state.next(output);
2206
+ }
2207
+ return shouldUpdateField ? output : {};
2208
+ };
2209
+ const shouldRenderByError = (name, isValid, error, fieldState) => {
2210
+ const previousFieldError = get(_formState.errors, name);
2211
+ const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
2212
+ isBoolean(isValid) &&
2213
+ _formState.isValid !== isValid;
2214
+ if (_options.delayError && error) {
2215
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
2216
+ delayErrorCallbacks[name](_options.delayError);
2217
+ }
2218
+ else {
2219
+ clearTimeout(timers[name]);
2220
+ delete delayErrorCallbacks[name];
2221
+ error
2222
+ ? set(_formState.errors, name, error)
2223
+ : unset(_formState.errors, name);
2224
+ _formState.errors = { ..._formState.errors };
2225
+ }
2226
+ if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) ||
2227
+ !isEmptyObject(fieldState) ||
2228
+ shouldUpdateValid) {
2229
+ const updatedFormState = {
2230
+ ...fieldState,
2231
+ ...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}),
2232
+ errors: _formState.errors,
2233
+ name,
2234
+ };
2235
+ _formState = {
2236
+ ..._formState,
2237
+ ...updatedFormState,
2238
+ };
2239
+ _subjects.state.next(updatedFormState);
2240
+ }
2241
+ };
2242
+ const _runSchema = async (name) => {
2243
+ _updateIsValidating(name, true);
2244
+ return await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation));
2245
+ };
2246
+ const executeSchemaAndUpdateState = async (names) => {
2247
+ const { errors } = await _runSchema(names);
2248
+ _updateIsValidating(names);
2249
+ if (names) {
2250
+ for (const name of names) {
2251
+ const error = get(errors, name);
2252
+ error
2253
+ ? _names.array.has(name) &&
2254
+ isObject(error) &&
2255
+ !Object.keys(error).some((key) => !Number.isNaN(Number(key)))
2256
+ ? updateFieldArrayRootError(_formState.errors, { [name]: error }, name)
2257
+ : set(_formState.errors, name, error)
2258
+ : unset(_formState.errors, name);
2259
+ }
2260
+ _formState.errors = { ..._formState.errors };
2261
+ }
2262
+ else {
2263
+ _formState.errors = errors;
2264
+ }
2265
+ return errors;
2266
+ };
2267
+ const validateForm = async ({ name, eventType, }) => {
2268
+ if (props.validate) {
2269
+ const result = await props.validate({
2270
+ formValues: _formValues,
2271
+ formState: _formState,
2272
+ name,
2273
+ eventType,
2274
+ });
2275
+ if (isObject(result)) {
2276
+ for (const key in result) {
2277
+ const error = result[key];
2278
+ if (error) {
2279
+ setError(`${FORM_ERROR_TYPE}.${key}`, {
2280
+ message: isString(error.message) ? error.message : '',
2281
+ type: error.type || INPUT_VALIDATION_RULES.validate,
2282
+ });
2283
+ }
2284
+ }
2285
+ }
2286
+ else if (isString(result) || !result) {
2287
+ setError(FORM_ERROR_TYPE, {
2288
+ message: result || '',
2289
+ type: INPUT_VALIDATION_RULES.validate,
2290
+ });
2291
+ }
2292
+ else {
2293
+ clearErrors(FORM_ERROR_TYPE);
2294
+ }
2295
+ return result;
2296
+ }
2297
+ return true;
2298
+ };
2299
+ const executeBuiltInValidation = async ({ fields, onlyCheckValid, name, eventType, context = {
2300
+ valid: true,
2301
+ runRootValidation: false,
2302
+ }, }) => {
2303
+ if (props.validate) {
2304
+ context.runRootValidation = true;
2305
+ const result = await validateForm({
2306
+ name,
2307
+ eventType,
2308
+ });
2309
+ if (!result) {
2310
+ context.valid = false;
2311
+ if (onlyCheckValid) {
2312
+ return context.valid;
2313
+ }
2314
+ }
2315
+ }
2316
+ for (const name in fields) {
2317
+ const field = fields[name];
2318
+ if (field) {
2319
+ const { _f, ...fieldValue } = field;
2320
+ if (_f) {
2321
+ const isFieldArrayRoot = _names.array.has(_f.name);
2322
+ const isPromiseFunction = field._f && hasPromiseValidation(field._f);
2323
+ const shouldTrackIsValidatingState = _proxyFormState.validatingFields ||
2324
+ _proxyFormState.isValidating ||
2325
+ _proxySubscribeFormState.validatingFields ||
2326
+ _proxySubscribeFormState.isValidating;
2327
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
2328
+ _updateIsValidating([_f.name], true);
2329
+ }
2330
+ const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !onlyCheckValid, isFieldArrayRoot);
2331
+ if (isPromiseFunction && shouldTrackIsValidatingState) {
2332
+ _updateIsValidating([_f.name]);
2333
+ }
2334
+ if (fieldError[_f.name]) {
2335
+ context.valid = false;
2336
+ if (onlyCheckValid) {
2337
+ break;
2338
+ }
2339
+ }
2340
+ !onlyCheckValid &&
2341
+ (get(fieldError, _f.name)
2342
+ ? isFieldArrayRoot
2343
+ ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name)
2344
+ : set(_formState.errors, _f.name, fieldError[_f.name])
2345
+ : unset(_formState.errors, _f.name));
2346
+ if (props.shouldUseNativeValidation && fieldError[_f.name]) {
2347
+ break;
2348
+ }
2349
+ }
2350
+ !isEmptyObject(fieldValue) &&
2351
+ (await executeBuiltInValidation({
2352
+ context,
2353
+ onlyCheckValid,
2354
+ fields: fieldValue,
2355
+ name: name,
2356
+ eventType,
2357
+ }));
2358
+ }
2359
+ }
2360
+ return context.valid;
2361
+ };
1749
2362
  const _removeUnmounted = () => {
1750
2363
  for (const name of _names.unMount) {
1751
2364
  const field = get(_fields, name);
@@ -1757,9 +2370,8 @@ function createFormControl(props = {}) {
1757
2370
  }
1758
2371
  _names.unMount = new Set();
1759
2372
  };
1760
- const _getDirty = (name, data) => !_options.disabled &&
1761
- (name && data && set(_formValues, name, data),
1762
- !deepEqual(getValues(), _defaultValues));
2373
+ const _getDirty = (name, data) => (name && data && set(_formValues, name, data),
2374
+ !deepEqual(_state.mount ? _formValues : _defaultValues, _defaultValues));
1763
2375
  const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, {
1764
2376
  ...(_state.mount
1765
2377
  ? _formValues
@@ -1770,7 +2382,7 @@ function createFormControl(props = {}) {
1770
2382
  : defaultValue),
1771
2383
  }, isGlobal, defaultValue);
1772
2384
  const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : []));
1773
- const setFieldValue = (name, value, options = {}) => {
2385
+ const setFieldValue = (name, value, options = {}, skipClone = false, skipRender = false) => {
1774
2386
  const field = get(_fields, name);
1775
2387
  let fieldValue = value;
1776
2388
  if (field) {
@@ -1808,20 +2420,23 @@ function createFormControl(props = {}) {
1808
2420
  }
1809
2421
  else {
1810
2422
  fieldReference.ref.value = fieldValue;
1811
- if (!fieldReference.ref.type) {
2423
+ if (!fieldReference.ref.type && !skipRender) {
1812
2424
  _subjects.state.next({
1813
2425
  name,
1814
- values: cloneObject(_formValues),
2426
+ values: skipClone ? _formValues : cloneObject(_formValues),
1815
2427
  });
1816
2428
  }
1817
2429
  }
1818
2430
  }
1819
2431
  }
1820
2432
  (options.shouldDirty || options.shouldTouch) &&
1821
- updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true);
1822
- options.shouldValidate && trigger(name);
2433
+ updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, !skipRender);
2434
+ options.shouldValidate &&
2435
+ trigger(name, {
2436
+ delayError: options.delayError,
2437
+ });
1823
2438
  };
1824
- const setValues = (name, value, options) => {
2439
+ const setFieldValues = (name, value, options, skipClone = false, skipRender = false) => {
1825
2440
  for (const fieldKey in value) {
1826
2441
  if (!value.hasOwnProperty(fieldKey)) {
1827
2442
  return;
@@ -1833,50 +2448,84 @@ function createFormControl(props = {}) {
1833
2448
  isObject(fieldValue) ||
1834
2449
  (field && !field._f)) &&
1835
2450
  !isDateObject(fieldValue)
1836
- ? setValues(fieldName, fieldValue, options)
1837
- : setFieldValue(fieldName, fieldValue, options);
2451
+ ? setFieldValues(fieldName, fieldValue, options, skipClone, skipRender)
2452
+ : setFieldValue(fieldName, fieldValue, options, skipClone, skipRender);
1838
2453
  }
1839
2454
  };
1840
- const setValue = (name, value, options = {}) => {
2455
+ const _setValue = (name, value, options, skipClone, skipStateEmit = false) => {
1841
2456
  const field = get(_fields, name);
1842
2457
  const isFieldArray = _names.array.has(name);
1843
- const cloneValue = cloneObject(value);
1844
- set(_formValues, name, cloneValue);
2458
+ const cloneValue = skipClone ? value : cloneObject(value);
2459
+ const previousValue = get(_formValues, name);
2460
+ const isValueUnchanged = deepEqual(previousValue, cloneValue);
2461
+ if (!isValueUnchanged) {
2462
+ set(_formValues, name, cloneValue);
2463
+ }
1845
2464
  if (isFieldArray) {
1846
2465
  _subjects.array.next({
1847
2466
  name,
1848
- values: cloneObject(_formValues),
2467
+ values: skipClone ? _formValues : cloneObject(_formValues),
1849
2468
  });
1850
2469
  if ((_proxyFormState.isDirty ||
1851
2470
  _proxyFormState.dirtyFields ||
1852
2471
  _proxySubscribeFormState.isDirty ||
1853
2472
  _proxySubscribeFormState.dirtyFields) &&
1854
2473
  options.shouldDirty) {
1855
- _updateDirtyFields(name);
1856
- _subjects.state.next({
1857
- name,
1858
- dirtyFields: _formState.dirtyFields,
1859
- isDirty: _getDirty(name, cloneValue),
1860
- });
2474
+ _updateDirtyFields();
2475
+ if (!skipStateEmit) {
2476
+ _subjects.state.next({
2477
+ name,
2478
+ dirtyFields: _formState.dirtyFields,
2479
+ isDirty: _getDirty(name, cloneValue),
2480
+ });
2481
+ }
1861
2482
  }
1862
2483
  }
1863
2484
  else {
1864
- field && !field._f && !isNullOrUndefined(cloneValue)
1865
- ? setValues(name, cloneValue, options)
1866
- : setFieldValue(name, cloneValue, options);
2485
+ const isEmpty = (Array.isArray(cloneValue) && !cloneValue.length) ||
2486
+ isEmptyObject(cloneValue);
2487
+ if (!field || field._f || isNullOrUndefined(cloneValue) || isEmpty) {
2488
+ setFieldValue(name, cloneValue, options, skipClone, skipStateEmit);
2489
+ }
2490
+ else {
2491
+ setFieldValues(name, cloneValue, options, skipClone, skipStateEmit);
2492
+ }
1867
2493
  }
1868
- if (isWatched(name, _names)) {
2494
+ if (!isValueUnchanged && !skipStateEmit) {
2495
+ const watched = isWatched(name, _names);
2496
+ const values = skipClone ? _formValues : cloneObject(_formValues);
1869
2497
  _subjects.state.next({
1870
- ..._formState,
1871
- name,
1872
- values: cloneObject(_formValues),
2498
+ ...(watched && _formState),
2499
+ name: _state.mount || watched ? name : undefined,
2500
+ values,
1873
2501
  });
1874
2502
  }
1875
- else {
2503
+ };
2504
+ const setValue = (name, value, options = {}) => _setValue(name, value, options, false);
2505
+ const setValues = (formValues, options = {}) => {
2506
+ const updatedFormValues = isFunction(formValues)
2507
+ ? formValues(_formValues)
2508
+ : formValues;
2509
+ if (!deepEqual(_formValues, updatedFormValues)) {
2510
+ _formValues = {
2511
+ ..._formValues,
2512
+ ...updatedFormValues,
2513
+ };
2514
+ const flattenedUpdates = flatten(updatedFormValues);
2515
+ for (const fieldName of _names.mount) {
2516
+ if (fieldName in flattenedUpdates) {
2517
+ _setValue(fieldName, flattenedUpdates[fieldName], options, true, true);
2518
+ }
2519
+ }
1876
2520
  _subjects.state.next({
1877
- name: _state.mount ? name : undefined,
1878
- values: cloneObject(_formValues),
2521
+ ..._formState,
2522
+ name: undefined,
2523
+ type: undefined,
2524
+ ...(_valuesSubscriberCount ? { values: _formValues } : {}),
1879
2525
  });
2526
+ if (options.shouldValidate) {
2527
+ _setValid();
2528
+ }
1880
2529
  }
1881
2530
  };
1882
2531
  const onChange = async (event) => {
@@ -1891,8 +2540,6 @@ function createFormControl(props = {}) {
1891
2540
  (isDateObject(fieldValue) && isNaN(fieldValue.getTime())) ||
1892
2541
  deepEqual(fieldValue, get(_formValues, name, fieldValue));
1893
2542
  };
1894
- const validationModeBeforeSubmit = getValidationModes(_options.mode);
1895
- const validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
1896
2543
  if (field) {
1897
2544
  let error;
1898
2545
  let isValid;
@@ -1900,18 +2547,20 @@ function createFormControl(props = {}) {
1900
2547
  ? getFieldValue(field._f)
1901
2548
  : getEventValue(event);
1902
2549
  const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT;
1903
- const shouldSkipValidation = (!hasValidation(field._f) &&
2550
+ const hasNoValidationEffect = !hasValidation(field._f) &&
1904
2551
  !props.validate &&
1905
2552
  !_options.resolver &&
1906
2553
  !get(_formState.errors, name) &&
1907
- !field._f.deps) ||
1908
- skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit);
2554
+ !field._f.deps;
2555
+ const shouldSkipValidation = hasNoValidationEffect ||
2556
+ skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, _validationModeAfterSubmit, _validationModeBeforeSubmit);
1909
2557
  const watched = isWatched(name, _names, isBlurEvent);
1910
2558
  set(_formValues, name, fieldValue);
1911
2559
  if (isBlurEvent) {
1912
2560
  if (!target || !target.readOnly) {
1913
2561
  field._f.onBlur && field._f.onBlur(event);
1914
- delayErrorCallback && delayErrorCallback(0);
2562
+ const pendingDelayError = delayErrorCallbacks[name];
2563
+ pendingDelayError && pendingDelayError(0);
1915
2564
  }
1916
2565
  }
1917
2566
  else if (field._f.onChange) {
@@ -1923,10 +2572,13 @@ function createFormControl(props = {}) {
1923
2572
  _subjects.state.next({
1924
2573
  name,
1925
2574
  type: event.type,
1926
- values: cloneObject(_formValues),
2575
+ ...(_valuesSubscriberCount
2576
+ ? { values: cloneObject(_formValues) }
2577
+ : {}),
1927
2578
  });
1928
2579
  if (shouldSkipValidation) {
1929
- if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) {
2580
+ if ((!hasNoValidationEffect || !_formState.isValid) &&
2581
+ (_proxyFormState.isValid || _proxySubscribeFormState.isValid)) {
1930
2582
  if (_options.mode === 'onBlur') {
1931
2583
  if (isBlurEvent) {
1932
2584
  _setValid();
@@ -1950,13 +2602,15 @@ function createFormControl(props = {}) {
1950
2602
  const { errors } = await _runSchema([name]);
1951
2603
  _updateIsValidating([name]);
1952
2604
  _updateIsFieldValueUpdated(fieldValue);
1953
- if (isFieldValueUpdated) {
1954
- const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
1955
- const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
1956
- error = errorLookupResult.error;
1957
- name = errorLookupResult.name;
1958
- isValid = isEmptyObject(errors);
2605
+ if (!isFieldValueUpdated) {
2606
+ !isEmptyObject(fieldState) && _subjects.state.next(fieldState);
2607
+ return;
1959
2608
  }
2609
+ const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name);
2610
+ const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name);
2611
+ error = errorLookupResult.error;
2612
+ name = errorLookupResult.name;
2613
+ isValid = isEmptyObject(errors);
1960
2614
  }
1961
2615
  else {
1962
2616
  _updateIsValidating([name], true);
@@ -2021,6 +2675,18 @@ function createFormControl(props = {}) {
2021
2675
  eventType: EVENTS.TRIGGER,
2022
2676
  });
2023
2677
  }
2678
+ if (options.delayError && _options.delayError && isString(name)) {
2679
+ const error = get(_formState.errors, name);
2680
+ if (error) {
2681
+ unset(_formState.errors, name);
2682
+ delayErrorCallbacks[name] = debounce(name, () => updateErrors(name, error));
2683
+ delayErrorCallbacks[name](_options.delayError);
2684
+ }
2685
+ else {
2686
+ clearTimeout(timers[name]);
2687
+ delete delayErrorCallbacks[name];
2688
+ }
2689
+ }
2024
2690
  _subjects.state.next({
2025
2691
  ...(!isString(name) ||
2026
2692
  ((_proxyFormState.isValid || _proxySubscribeFormState.isValid) &&
@@ -2032,868 +2698,630 @@ function createFormControl(props = {}) {
2032
2698
  });
2033
2699
  options.shouldFocus &&
2034
2700
  !validationResult &&
2035
- iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
2036
- return validationResult;
2037
- };
2038
- const getValues = (fieldNames, config) => {
2039
- let values = {
2040
- ...(_state.mount ? _formValues : _defaultValues),
2041
- };
2042
- if (config) {
2043
- values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
2044
- }
2045
- return isUndefined(fieldNames)
2046
- ? values
2047
- : isString(fieldNames)
2048
- ? get(values, fieldNames)
2049
- : fieldNames.map((name) => get(values, name));
2050
- };
2051
- const getFieldState = (name, formState) => ({
2052
- invalid: !!get((formState || _formState).errors, name),
2053
- isDirty: !!get((formState || _formState).dirtyFields, name),
2054
- error: get((formState || _formState).errors, name),
2055
- isValidating: !!get(_formState.validatingFields, name),
2056
- isTouched: !!get((formState || _formState).touchedFields, name),
2057
- });
2058
- const clearErrors = (name) => {
2059
- const names = name ? convertToArrayPayload(name) : undefined;
2060
- names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
2061
- if (names) {
2062
- // Emit for each cleared field with the field name so that
2063
- // shouldSubscribeByName can filter and avoid broad re-renders
2064
- names.forEach((inputName) => {
2065
- _subjects.state.next({
2066
- name: inputName,
2067
- errors: _formState.errors,
2068
- });
2069
- });
2070
- }
2071
- else {
2072
- // Clear all errors - emit without name to notify all subscribers
2073
- _subjects.state.next({
2074
- errors: {},
2075
- });
2076
- }
2077
- };
2078
- const setError = (name, error, options) => {
2079
- const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
2080
- const currentError = get(_formState.errors, name) || {};
2081
- // Don't override existing error messages elsewhere in the object tree.
2082
- const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
2083
- set(_formState.errors, name, {
2084
- ...restOfErrorTree,
2085
- ...error,
2086
- ref,
2087
- });
2088
- _subjects.state.next({
2089
- name,
2090
- errors: _formState.errors,
2091
- isValid: false,
2092
- });
2093
- options && options.shouldFocus && ref && ref.focus && ref.focus();
2094
- };
2095
- const watch = (name, defaultValue) => isFunction(name)
2096
- ? _subjects.state.subscribe({
2097
- next: (payload) => 'values' in payload &&
2098
- name(_getWatch(undefined, defaultValue), payload),
2099
- })
2100
- : _getWatch(name, defaultValue, true);
2101
- const _subscribe = (props) => _subjects.state.subscribe({
2102
- next: (formState) => {
2103
- if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
2104
- shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
2105
- props.callback({
2106
- values: { ..._formValues },
2107
- ..._formState,
2108
- ...formState,
2109
- defaultValues: _defaultValues,
2110
- });
2111
- }
2112
- },
2113
- }).unsubscribe;
2114
- const subscribe = (props) => {
2115
- _state.mount = true;
2116
- _proxySubscribeFormState = {
2117
- ..._proxySubscribeFormState,
2118
- ...props.formState,
2119
- };
2120
- return _subscribe({
2121
- ...props,
2122
- formState: {
2123
- ...defaultProxyFormState,
2124
- ...props.formState,
2125
- },
2126
- });
2127
- };
2128
- const unregister = (name, options = {}) => {
2129
- for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
2130
- _names.mount.delete(fieldName);
2131
- _names.array.delete(fieldName);
2132
- if (!options.keepValue) {
2133
- unset(_fields, fieldName);
2134
- unset(_formValues, fieldName);
2135
- }
2136
- !options.keepError && unset(_formState.errors, fieldName);
2137
- !options.keepDirty && unset(_formState.dirtyFields, fieldName);
2138
- !options.keepTouched && unset(_formState.touchedFields, fieldName);
2139
- !options.keepIsValidating &&
2140
- unset(_formState.validatingFields, fieldName);
2141
- !_options.shouldUnregister &&
2142
- !options.keepDefaultValue &&
2143
- unset(_defaultValues, fieldName);
2144
- }
2145
- _subjects.state.next({
2146
- values: cloneObject(_formValues),
2147
- });
2148
- _subjects.state.next({
2149
- ..._formState,
2150
- ...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
2151
- });
2152
- !options.keepIsValid && _setValid();
2153
- };
2154
- const _setDisabledField = ({ disabled, name, }) => {
2155
- if ((isBoolean(disabled) && _state.mount) ||
2156
- !!disabled ||
2157
- _names.disabled.has(name)) {
2158
- const wasDisabled = _names.disabled.has(name);
2159
- const isDisabled = !!disabled;
2160
- const disabledStateChanged = wasDisabled !== isDisabled;
2161
- disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
2162
- disabledStateChanged && _state.mount && !_state.action && _setValid();
2163
- }
2164
- };
2165
- const register = (name, options = {}) => {
2166
- let field = get(_fields, name);
2167
- const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
2168
- const shouldRevalidateRemount = !_names.registerName.has(name) && field && !field._f.mount;
2169
- set(_fields, name, {
2170
- ...(field || {}),
2171
- _f: {
2172
- ...(field && field._f ? field._f : { ref: { name } }),
2173
- name,
2174
- mount: true,
2175
- ...options,
2176
- },
2177
- });
2178
- _names.mount.add(name);
2179
- if (field && !shouldRevalidateRemount) {
2180
- _setDisabledField({
2181
- disabled: isBoolean(options.disabled)
2182
- ? options.disabled
2183
- : _options.disabled,
2184
- name,
2185
- });
2186
- }
2187
- else {
2188
- updateValidAndValue(name, true, options.value);
2189
- }
2190
- return {
2191
- ...(disabledIsDefined
2192
- ? { disabled: options.disabled || _options.disabled }
2193
- : {}),
2194
- ...(_options.progressive
2195
- ? {
2196
- required: !!options.required,
2197
- min: getRuleValue(options.min),
2198
- max: getRuleValue(options.max),
2199
- minLength: getRuleValue(options.minLength),
2200
- maxLength: getRuleValue(options.maxLength),
2201
- pattern: getRuleValue(options.pattern),
2202
- }
2203
- : {}),
2204
- name,
2205
- onChange,
2206
- onBlur: onChange,
2207
- ref: (ref) => {
2208
- if (ref) {
2209
- _names.registerName.add(name);
2210
- register(name, options);
2211
- _names.registerName.delete(name);
2212
- field = get(_fields, name);
2213
- const fieldRef = isUndefined(ref.value)
2214
- ? ref.querySelectorAll
2215
- ? ref.querySelectorAll('input,select,textarea')[0] || ref
2216
- : ref
2217
- : ref;
2218
- const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
2219
- const refs = field._f.refs || [];
2220
- if (radioOrCheckbox
2221
- ? refs.find((option) => option === fieldRef)
2222
- : fieldRef === field._f.ref) {
2223
- return;
2224
- }
2225
- set(_fields, name, {
2226
- _f: {
2227
- ...field._f,
2228
- ...(radioOrCheckbox
2229
- ? {
2230
- refs: [
2231
- ...refs.filter(live),
2232
- fieldRef,
2233
- ...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
2234
- ],
2235
- ref: { type: fieldRef.type, name },
2236
- }
2237
- : { ref: fieldRef }),
2238
- },
2239
- });
2240
- updateValidAndValue(name, false, undefined, fieldRef);
2241
- }
2242
- else {
2243
- field = get(_fields, name, {});
2244
- if (field._f) {
2245
- field._f.mount = false;
2246
- }
2247
- (_options.shouldUnregister || options.shouldUnregister) &&
2248
- !(isNameInFieldArray(_names.array, name) && _state.action) &&
2249
- _names.unMount.add(name);
2250
- }
2251
- },
2252
- };
2253
- };
2254
- const _focusError = () => _options.shouldFocusError &&
2255
- iterateFieldsByAction(_fields, _focusInput, _names.mount);
2256
- const _disableForm = (disabled) => {
2257
- if (isBoolean(disabled)) {
2258
- _subjects.state.next({ disabled });
2259
- iterateFieldsByAction(_fields, (ref, name) => {
2260
- const currentField = get(_fields, name);
2261
- if (currentField) {
2262
- ref.disabled = currentField._f.disabled || disabled;
2263
- if (Array.isArray(currentField._f.refs)) {
2264
- currentField._f.refs.forEach((inputRef) => {
2265
- inputRef.disabled = currentField._f.disabled || disabled;
2266
- });
2267
- }
2268
- }
2269
- }, 0, false);
2270
- }
2271
- };
2272
- const handleSubmit = (onValid, onInvalid) => async (e) => {
2273
- let onValidError = undefined;
2274
- if (e) {
2275
- e.preventDefault && e.preventDefault();
2276
- e.persist &&
2277
- e.persist();
2278
- }
2279
- let fieldValues = cloneObject(_formValues);
2280
- _subjects.state.next({
2281
- isSubmitting: true,
2282
- });
2283
- if (_options.resolver) {
2284
- const { errors, values } = await _runSchema();
2285
- _updateIsValidating();
2286
- _formState.errors = errors;
2287
- fieldValues = cloneObject(values);
2701
+ iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount);
2702
+ return validationResult;
2703
+ };
2704
+ const getValues = (fieldNames, config) => {
2705
+ let values = {
2706
+ ...(_state.mount ? _formValues : _defaultValues),
2707
+ };
2708
+ if (config) {
2709
+ values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values);
2288
2710
  }
2289
- else {
2290
- await executeBuiltInValidation({
2291
- fields: _fields,
2292
- eventType: EVENTS.SUBMIT,
2711
+ return isUndefined(fieldNames)
2712
+ ? values
2713
+ : isString(fieldNames)
2714
+ ? get(values, fieldNames)
2715
+ : fieldNames.map((name) => get(values, name));
2716
+ };
2717
+ const getFieldState = (name, formState) => ({
2718
+ invalid: !!get((formState || _formState).errors, name),
2719
+ isDirty: !!get((formState || _formState).dirtyFields, name),
2720
+ error: get((formState || _formState).errors, name),
2721
+ isValidating: !!get(_formState.validatingFields, name),
2722
+ isTouched: !!get((formState || _formState).touchedFields, name),
2723
+ });
2724
+ const clearErrors = (name) => {
2725
+ const names = name ? convertToArrayPayload(name) : undefined;
2726
+ names === null || names === void 0 ? void 0 : names.forEach((inputName) => unset(_formState.errors, inputName));
2727
+ if (names) {
2728
+ names.forEach((inputName) => {
2729
+ _subjects.state.next({
2730
+ name: inputName,
2731
+ errors: _formState.errors,
2732
+ });
2293
2733
  });
2294
2734
  }
2295
- if (_names.disabled.size) {
2296
- for (const name of _names.disabled) {
2297
- unset(fieldValues, name);
2298
- }
2299
- }
2300
- unset(_formState.errors, ROOT_ERROR_TYPE);
2301
- if (isEmptyObject(_formState.errors)) {
2735
+ else {
2736
+ _formState.errors = {};
2302
2737
  _subjects.state.next({
2303
- errors: {},
2738
+ errors: _formState.errors,
2304
2739
  });
2305
- try {
2306
- await onValid(fieldValues, e);
2307
- }
2308
- catch (error) {
2309
- onValidError = error;
2310
- }
2311
- }
2312
- else {
2313
- if (onInvalid) {
2314
- await onInvalid({ ..._formState.errors }, e);
2315
- }
2316
- _focusError();
2317
- setTimeout(_focusError);
2318
2740
  }
2741
+ };
2742
+ const setError = (name, error, options) => {
2743
+ const ref = (get(_fields, name, { _f: {} })._f || {}).ref;
2744
+ const currentError = get(_formState.errors, name) || {};
2745
+ const { ref: currentRef, message, type, ...restOfErrorTree } = currentError;
2746
+ set(_formState.errors, name, {
2747
+ ...restOfErrorTree,
2748
+ ...error,
2749
+ ref,
2750
+ });
2319
2751
  _subjects.state.next({
2320
- isSubmitted: true,
2321
- isSubmitting: false,
2322
- isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
2323
- submitCount: _formState.submitCount + 1,
2752
+ name,
2324
2753
  errors: _formState.errors,
2754
+ isValid: false,
2325
2755
  });
2326
- if (onValidError) {
2327
- throw onValidError;
2328
- }
2756
+ options && options.shouldFocus && ref && ref.focus && ref.focus();
2329
2757
  };
2330
- const resetField = (name, options = {}) => {
2331
- if (get(_fields, name)) {
2332
- if (isUndefined(options.defaultValue)) {
2333
- setValue(name, cloneObject(get(_defaultValues, name)));
2334
- }
2335
- else {
2336
- setValue(name, options.defaultValue);
2337
- set(_defaultValues, name, cloneObject(options.defaultValue));
2338
- }
2339
- if (!options.keepTouched) {
2340
- unset(_formState.touchedFields, name);
2341
- }
2342
- if (!options.keepDirty) {
2343
- unset(_formState.dirtyFields, name);
2344
- _formState.isDirty = options.defaultValue
2345
- ? _getDirty(name, cloneObject(get(_defaultValues, name)))
2346
- : _getDirty();
2347
- }
2348
- if (!options.keepError) {
2349
- unset(_formState.errors, name);
2350
- _proxyFormState.isValid && _setValid();
2351
- }
2352
- _subjects.state.next({ ..._formState });
2758
+ const watch = (name, defaultValue) => {
2759
+ if (isFunction(name)) {
2760
+ _valuesSubscriberCount++;
2761
+ const { unsubscribe } = _subjects.state.subscribe({
2762
+ next: (payload) => 'values' in payload &&
2763
+ name(payload.values || _getWatch(undefined, defaultValue), payload),
2764
+ });
2765
+ let called = false;
2766
+ return {
2767
+ unsubscribe: () => {
2768
+ if (called) {
2769
+ return;
2770
+ }
2771
+ called = true;
2772
+ _valuesSubscriberCount--;
2773
+ unsubscribe();
2774
+ },
2775
+ };
2353
2776
  }
2777
+ return _getWatch(name, defaultValue, true);
2354
2778
  };
2355
- const _reset = (formValues, keepStateOptions = {}) => {
2356
- const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
2357
- const cloneUpdatedValues = cloneObject(updatedValues);
2358
- const isEmptyResetValues = isEmptyObject(formValues);
2359
- const values = isEmptyResetValues ? _defaultValues : cloneUpdatedValues;
2360
- if (!keepStateOptions.keepDefaultValues) {
2361
- _defaultValues = updatedValues;
2362
- }
2363
- if (!keepStateOptions.keepValues) {
2364
- if (keepStateOptions.keepDirtyValues) {
2365
- const fieldsToCheck = new Set([
2366
- ..._names.mount,
2367
- ...Object.keys(getDirtyFields(_defaultValues, _formValues)),
2368
- ]);
2369
- for (const fieldName of Array.from(fieldsToCheck)) {
2370
- const isDirty = get(_formState.dirtyFields, fieldName);
2371
- const existingValue = get(_formValues, fieldName);
2372
- const newValue = get(values, fieldName);
2373
- if (isDirty && !isUndefined(existingValue)) {
2374
- set(values, fieldName, existingValue);
2375
- }
2376
- else if (!isDirty && !isUndefined(newValue)) {
2377
- setValue(fieldName, newValue);
2378
- }
2379
- }
2380
- }
2381
- else {
2382
- if (isWeb && isUndefined(formValues)) {
2383
- for (const name of _names.mount) {
2384
- const field = get(_fields, name);
2385
- if (field && field._f) {
2386
- const fieldReference = Array.isArray(field._f.refs)
2387
- ? field._f.refs[0]
2388
- : field._f.ref;
2389
- if (isHTMLElement(fieldReference)) {
2390
- const form = fieldReference.closest('form');
2391
- if (form) {
2392
- form.reset();
2393
- break;
2394
- }
2395
- }
2396
- }
2397
- }
2398
- }
2399
- if (keepStateOptions.keepFieldsRef) {
2400
- for (const fieldName of _names.mount) {
2401
- setValue(fieldName, get(values, fieldName));
2402
- }
2403
- }
2404
- else {
2405
- _fields = {};
2779
+ const _subscribe = (props) => {
2780
+ var _a;
2781
+ const needsValues = !!((_a = props.formState) === null || _a === void 0 ? void 0 : _a.values);
2782
+ if (needsValues) {
2783
+ _valuesSubscriberCount++;
2784
+ }
2785
+ const { unsubscribe } = _subjects.state.subscribe({
2786
+ next: (formState) => {
2787
+ if (shouldSubscribeByName(props.name, formState.name, props.exact) &&
2788
+ shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) {
2789
+ const snapshot = { ..._formValues };
2790
+ props.callback({
2791
+ values: snapshot,
2792
+ ..._formState,
2793
+ ...formState,
2794
+ defaultValues: _defaultValues,
2795
+ });
2406
2796
  }
2407
- }
2408
- _formValues = _options.shouldUnregister
2409
- ? keepStateOptions.keepDefaultValues
2410
- ? cloneObject(_defaultValues)
2411
- : {}
2412
- : cloneObject(values);
2413
- _subjects.array.next({
2414
- values: { ...values },
2415
- });
2416
- _subjects.state.next({
2417
- values: { ...values },
2418
- });
2797
+ },
2798
+ });
2799
+ if (!needsValues) {
2800
+ return unsubscribe;
2419
2801
  }
2420
- _names = {
2421
- mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
2422
- unMount: new Set(),
2423
- array: new Set(),
2424
- registerName: new Set(),
2425
- disabled: new Set(),
2426
- watch: new Set(),
2427
- watchAll: false,
2428
- focus: '',
2802
+ let called = false;
2803
+ return () => {
2804
+ if (called) {
2805
+ return;
2806
+ }
2807
+ called = true;
2808
+ _valuesSubscriberCount--;
2809
+ unsubscribe();
2429
2810
  };
2430
- _state.mount =
2431
- !_proxyFormState.isValid ||
2432
- !!keepStateOptions.keepIsValid ||
2433
- !!keepStateOptions.keepDirtyValues ||
2434
- (!_options.shouldUnregister && !isEmptyObject(values));
2435
- _state.watch = !!_options.shouldUnregister;
2436
- _state.keepIsValid = !!keepStateOptions.keepIsValid;
2437
- _state.action = false;
2438
- // Clear errors synchronously to prevent validation errors on subsequent submissions
2439
- // This fixes the issue where form.reset() causes validation errors on subsequent
2440
- // submissions in Next.js 16 with Server Actions
2441
- if (!keepStateOptions.keepErrors) {
2442
- _formState.errors = {};
2443
- }
2444
- _subjects.state.next({
2445
- submitCount: keepStateOptions.keepSubmitCount
2446
- ? _formState.submitCount
2447
- : 0,
2448
- isDirty: isEmptyResetValues
2449
- ? false
2450
- : keepStateOptions.keepDirty
2451
- ? _formState.isDirty
2452
- : !!(keepStateOptions.keepDefaultValues &&
2453
- !deepEqual(formValues, _defaultValues)),
2454
- isSubmitted: keepStateOptions.keepIsSubmitted
2455
- ? _formState.isSubmitted
2456
- : false,
2457
- dirtyFields: isEmptyResetValues
2458
- ? {}
2459
- : keepStateOptions.keepDirtyValues
2460
- ? keepStateOptions.keepDefaultValues && _formValues
2461
- ? getDirtyFields(_defaultValues, _formValues)
2462
- : _formState.dirtyFields
2463
- : keepStateOptions.keepDefaultValues && formValues
2464
- ? getDirtyFields(_defaultValues, formValues)
2465
- : keepStateOptions.keepDirty
2466
- ? _formState.dirtyFields
2467
- : {},
2468
- touchedFields: keepStateOptions.keepTouched
2469
- ? _formState.touchedFields
2470
- : {},
2471
- errors: keepStateOptions.keepErrors ? _formState.errors : {},
2472
- isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
2473
- ? _formState.isSubmitSuccessful
2474
- : false,
2475
- isSubmitting: false,
2476
- defaultValues: _defaultValues,
2811
+ };
2812
+ const subscribe = (props) => {
2813
+ _state.mount = true;
2814
+ _proxySubscribeFormState = {
2815
+ ..._proxySubscribeFormState,
2816
+ ...props.formState,
2817
+ };
2818
+ return _subscribe({
2819
+ ...props,
2820
+ formState: {
2821
+ ...defaultProxyFormState,
2822
+ ...props.formState,
2823
+ },
2477
2824
  });
2478
2825
  };
2479
- const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
2480
- ? formValues(_formValues)
2481
- : formValues, { ..._options.resetOptions, ...keepStateOptions });
2482
- const setFocus = (name, options = {}) => {
2483
- const field = get(_fields, name);
2484
- const fieldReference = field && field._f;
2485
- if (fieldReference) {
2486
- const fieldRef = fieldReference.refs
2487
- ? fieldReference.refs[0]
2488
- : fieldReference.ref;
2489
- if (fieldRef.focus) {
2490
- // Use setTimeout to ensure focus happens after any pending state updates
2491
- // This fixes the issue where setFocus doesn't work immediately after setError
2492
- setTimeout(() => {
2493
- fieldRef.focus();
2494
- options.shouldSelect &&
2495
- isFunction(fieldRef.select) &&
2496
- fieldRef.select();
2497
- });
2826
+ const unregister = (name, options = {}) => {
2827
+ for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) {
2828
+ _names.mount.delete(fieldName);
2829
+ _names.array.delete(fieldName);
2830
+ if (!options.keepValue) {
2831
+ unset(_fields, fieldName);
2832
+ unset(_formValues, fieldName);
2498
2833
  }
2834
+ !options.keepError && unset(_formState.errors, fieldName);
2835
+ !options.keepDirty && unset(_formState.dirtyFields, fieldName);
2836
+ !options.keepTouched && unset(_formState.touchedFields, fieldName);
2837
+ !options.keepIsValidating &&
2838
+ unset(_formState.validatingFields, fieldName);
2839
+ !_options.shouldUnregister &&
2840
+ !options.keepDefaultValue &&
2841
+ unset(_defaultValues, fieldName);
2499
2842
  }
2500
- };
2501
- const _setFormState = (updatedFormState) => {
2502
- _formState = {
2843
+ _subjects.state.next({
2844
+ values: cloneObject(_formValues),
2845
+ });
2846
+ _subjects.state.next({
2503
2847
  ..._formState,
2504
- ...updatedFormState,
2505
- };
2506
- };
2507
- const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
2508
- _options.defaultValues().then((values) => {
2509
- reset(values, _options.resetOptions);
2510
- _subjects.state.next({
2511
- isLoading: false,
2512
- });
2848
+ ...(!options.keepDirty ? {} : { isDirty: _getDirty() }),
2513
2849
  });
2514
- const methods = {
2515
- control: {
2516
- register,
2517
- unregister,
2518
- getFieldState,
2519
- handleSubmit,
2520
- setError,
2521
- _subscribe,
2522
- _runSchema,
2523
- _updateIsValidating,
2524
- _focusError,
2525
- _getWatch,
2526
- _getDirty,
2527
- _setValid,
2528
- _setFieldArray,
2529
- _setDisabledField,
2530
- _setErrors,
2531
- _getFieldArray,
2532
- _reset,
2533
- _resetDefaultValues,
2534
- _removeUnmounted,
2535
- _disableForm,
2536
- _subjects,
2537
- _proxyFormState,
2538
- get _fields() {
2539
- return _fields;
2540
- },
2541
- get _formValues() {
2542
- return _formValues;
2543
- },
2544
- get _state() {
2545
- return _state;
2546
- },
2547
- set _state(value) {
2548
- _state = value;
2549
- },
2550
- get _defaultValues() {
2551
- return _defaultValues;
2552
- },
2553
- get _names() {
2554
- return _names;
2555
- },
2556
- set _names(value) {
2557
- _names = value;
2558
- },
2559
- get _formState() {
2560
- return _formState;
2561
- },
2562
- get _options() {
2563
- return _options;
2564
- },
2565
- set _options(value) {
2566
- _options = {
2567
- ..._options,
2568
- ...value,
2569
- };
2570
- },
2571
- },
2572
- subscribe,
2573
- trigger,
2574
- register,
2575
- handleSubmit,
2576
- watch,
2577
- setValue,
2578
- getValues,
2579
- reset,
2580
- resetField,
2581
- clearErrors,
2582
- unregister,
2583
- setError,
2584
- setFocus,
2585
- getFieldState,
2850
+ !options.keepIsValid && _setValid();
2586
2851
  };
2587
- return {
2588
- ...methods,
2589
- formControl: methods,
2852
+ const _setDisabledField = ({ disabled, name, }) => {
2853
+ if ((isBoolean(disabled) && _state.mount) ||
2854
+ !!disabled ||
2855
+ _names.disabled.has(name)) {
2856
+ const wasDisabled = _names.disabled.has(name);
2857
+ const isDisabled = !!disabled;
2858
+ const disabledStateChanged = wasDisabled !== isDisabled;
2859
+ disabled ? _names.disabled.add(name) : _names.disabled.delete(name);
2860
+ disabledStateChanged && _state.mount && !_state.action && _setValid();
2861
+ }
2590
2862
  };
2591
- }
2592
-
2593
- var generateId = () => {
2594
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
2595
- return crypto.randomUUID();
2596
- }
2597
- const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000;
2598
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
2599
- const r = ((Math.random() * 16 + d) % 16) | 0;
2600
- return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16);
2601
- });
2602
- };
2603
-
2604
- var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus)
2605
- ? options.focusName ||
2606
- `${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.`
2607
- : '';
2608
-
2609
- var appendAt = (data, value) => [
2610
- ...data,
2611
- ...convertToArrayPayload(value),
2612
- ];
2613
-
2614
- var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined;
2615
-
2616
- function insert(data, index, value) {
2617
- return [
2618
- ...data.slice(0, index),
2619
- ...convertToArrayPayload(value),
2620
- ...data.slice(index),
2621
- ];
2622
- }
2623
-
2624
- var moveArrayAt = (data, from, to) => {
2625
- if (!Array.isArray(data)) {
2626
- return [];
2627
- }
2628
- if (isUndefined(data[to])) {
2629
- data[to] = undefined;
2630
- }
2631
- data.splice(to, 0, data.splice(from, 1)[0]);
2632
- return data;
2633
- };
2634
-
2635
- var prependAt = (data, value) => [
2636
- ...convertToArrayPayload(value),
2637
- ...convertToArrayPayload(data),
2638
- ];
2639
-
2640
- function removeAtIndexes(data, indexes) {
2641
- let i = 0;
2642
- const temp = [...data];
2643
- for (const index of indexes) {
2644
- temp.splice(index - i, 1);
2645
- i++;
2646
- }
2647
- return compact(temp).length ? temp : [];
2648
- }
2649
- var removeArrayAt = (data, index) => isUndefined(index)
2650
- ? []
2651
- : removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b));
2652
-
2653
- var swapArrayAt = (data, indexA, indexB) => {
2654
- [data[indexA], data[indexB]] = [data[indexB], data[indexA]];
2655
- };
2656
-
2657
- var updateAt = (fieldValues, index, value) => {
2658
- fieldValues[index] = value;
2659
- return fieldValues;
2660
- };
2661
-
2662
- /**
2663
- * A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A)
2664
- *
2665
- * @remarks
2666
- * [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn)
2667
- *
2668
- * @param props - useFieldArray props
2669
- *
2670
- * @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn}
2671
- *
2672
- * @example
2673
- * ```tsx
2674
- * function App() {
2675
- * const { register, control, handleSubmit, reset, trigger, setError } = useForm({
2676
- * defaultValues: {
2677
- * test: []
2678
- * }
2679
- * });
2680
- * const { fields, append } = useFieldArray({
2681
- * control,
2682
- * name: "test"
2683
- * });
2684
- *
2685
- * return (
2686
- * <form onSubmit={handleSubmit(data => console.log(data))}>
2687
- * {fields.map((item, index) => (
2688
- * <input key={item.id} {...register(`test.${index}.firstName`)} />
2689
- * ))}
2690
- * <button type="button" onClick={() => append({ firstName: "bill" })}>
2691
- * append
2692
- * </button>
2693
- * <input type="submit" />
2694
- * </form>
2695
- * );
2696
- * }
2697
- * ```
2698
- */
2699
- function useFieldArray(props) {
2700
- const formControl = useFormControlContext();
2701
- const { control = formControl, name, keyName = 'id', shouldUnregister, rules, } = props;
2702
- const [fields, setFields] = React.useState(control._getFieldArray(name));
2703
- const ids = React.useRef(control._getFieldArray(name).map(generateId));
2704
- const _actioned = React.useRef(false);
2705
- control._names.array.add(name);
2706
- React.useMemo(() => rules &&
2707
- fields.length >= 0 &&
2708
- control.register(name, rules), [control, name, fields.length, rules]);
2709
- useIsomorphicLayoutEffect(() => control._subjects.array.subscribe({
2710
- next: ({ values, name: fieldArrayName, }) => {
2711
- if (fieldArrayName === name || !fieldArrayName) {
2712
- const fieldValues = get(values, name);
2713
- if (Array.isArray(fieldValues)) {
2714
- setFields(fieldValues);
2715
- ids.current = fieldValues.map(generateId);
2863
+ const register = (name, options = {}) => {
2864
+ let field = get(_fields, name);
2865
+ const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled);
2866
+ const shouldRevalidateRemount = !_names.registerName.has(name) && field && field._f && !field._f.mount;
2867
+ set(_fields, name, {
2868
+ ...(field || {}),
2869
+ _f: {
2870
+ ...(field && field._f ? field._f : { ref: { name } }),
2871
+ name,
2872
+ mount: true,
2873
+ ...options,
2874
+ },
2875
+ });
2876
+ _names.mount.add(name);
2877
+ if (field && !shouldRevalidateRemount) {
2878
+ _setDisabledField({
2879
+ disabled: isBoolean(options.disabled)
2880
+ ? options.disabled
2881
+ : _options.disabled,
2882
+ name,
2883
+ });
2884
+ }
2885
+ else {
2886
+ updateValidAndValue(name, true, options.value);
2887
+ }
2888
+ return {
2889
+ ...(disabledIsDefined
2890
+ ? { disabled: options.disabled || _options.disabled }
2891
+ : {}),
2892
+ ...(_options.progressive
2893
+ ? {
2894
+ required: !!options.required,
2895
+ min: getRuleValue(options.min),
2896
+ max: getRuleValue(options.max),
2897
+ minLength: getRuleValue(options.minLength),
2898
+ maxLength: getRuleValue(options.maxLength),
2899
+ pattern: getRuleValue(options.pattern),
2716
2900
  }
2717
- }
2718
- },
2719
- }).unsubscribe, [control, name]);
2720
- const updateValues = React.useCallback((updatedFieldArrayValues) => {
2721
- _actioned.current = true;
2722
- control._setFieldArray(name, updatedFieldArrayValues);
2723
- }, [control, name]);
2724
- const append = (value, options) => {
2725
- const appendValue = convertToArrayPayload(cloneObject(value));
2726
- const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue);
2727
- control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options);
2728
- ids.current = appendAt(ids.current, appendValue.map(generateId));
2729
- updateValues(updatedFieldArrayValues);
2730
- setFields(updatedFieldArrayValues);
2731
- control._setFieldArray(name, updatedFieldArrayValues, appendAt, {
2732
- argA: fillEmptyArray(value),
2733
- });
2901
+ : {}),
2902
+ name,
2903
+ onChange,
2904
+ onBlur: onChange,
2905
+ ref: (ref) => {
2906
+ if (ref) {
2907
+ _names.registerName.add(name);
2908
+ register(name, options);
2909
+ _names.registerName.delete(name);
2910
+ field = get(_fields, name);
2911
+ const fieldRef = isUndefined(ref.value)
2912
+ ? ref.querySelectorAll
2913
+ ? ref.querySelectorAll('input,select,textarea')[0] || ref
2914
+ : ref
2915
+ : ref;
2916
+ const radioOrCheckbox = isRadioOrCheckbox(fieldRef);
2917
+ const refs = field._f.refs || [];
2918
+ if (radioOrCheckbox
2919
+ ? refs.find((option) => option === fieldRef)
2920
+ : fieldRef === field._f.ref) {
2921
+ return;
2922
+ }
2923
+ const newField = {
2924
+ ...field._f,
2925
+ };
2926
+ if (radioOrCheckbox) {
2927
+ newField.refs = [
2928
+ ...refs.filter(live),
2929
+ fieldRef,
2930
+ ...(Array.isArray(get(_defaultValues, name)) ? [{}] : []),
2931
+ ];
2932
+ newField.ref = { type: fieldRef.type, name };
2933
+ }
2934
+ else {
2935
+ newField.ref = fieldRef;
2936
+ delete newField.refs;
2937
+ }
2938
+ set(_fields, name, {
2939
+ _f: newField,
2940
+ });
2941
+ updateValidAndValue(name, false, undefined, fieldRef);
2942
+ }
2943
+ else {
2944
+ field = get(_fields, name, {});
2945
+ if (field._f) {
2946
+ field._f.mount = false;
2947
+ }
2948
+ (_options.shouldUnregister || options.shouldUnregister) &&
2949
+ !(isNameInFieldArray(_names.array, name) && _state.action) &&
2950
+ _names.unMount.add(name);
2951
+ }
2952
+ },
2953
+ };
2734
2954
  };
2735
- const prepend = (value, options) => {
2736
- const prependValue = convertToArrayPayload(cloneObject(value));
2737
- const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue);
2738
- control._names.focus = getFocusFieldName(name, 0, options);
2739
- ids.current = prependAt(ids.current, prependValue.map(generateId));
2740
- updateValues(updatedFieldArrayValues);
2741
- setFields(updatedFieldArrayValues);
2742
- control._setFieldArray(name, updatedFieldArrayValues, prependAt, {
2743
- argA: fillEmptyArray(value),
2744
- });
2955
+ const _focusError = () => _options.shouldFocusError &&
2956
+ !_options.shouldUseNativeValidation &&
2957
+ iterateFieldsByAction(_fields, _focusInput, _names.mount);
2958
+ const _disableForm = (disabled) => {
2959
+ if (isBoolean(disabled)) {
2960
+ _subjects.state.next({ disabled });
2961
+ iterateFieldsByAction(_fields, (ref, name) => {
2962
+ const currentField = get(_fields, name);
2963
+ if (currentField) {
2964
+ ref.disabled = currentField._f.disabled || disabled;
2965
+ if (Array.isArray(currentField._f.refs)) {
2966
+ currentField._f.refs.forEach((inputRef) => {
2967
+ inputRef.disabled = currentField._f.disabled || disabled;
2968
+ });
2969
+ }
2970
+ }
2971
+ }, 0, false);
2972
+ }
2745
2973
  };
2746
- const remove = (index) => {
2747
- const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index);
2748
- ids.current = removeArrayAt(ids.current, index);
2749
- updateValues(updatedFieldArrayValues);
2750
- setFields(updatedFieldArrayValues);
2751
- !Array.isArray(get(control._fields, name)) &&
2752
- set(control._fields, name, undefined);
2753
- control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, {
2754
- argA: index,
2974
+ const handleSubmit = (onValid, onInvalid) => async (e) => {
2975
+ let onValidError = undefined;
2976
+ if (e) {
2977
+ e.preventDefault && e.preventDefault();
2978
+ e.persist &&
2979
+ e.persist();
2980
+ }
2981
+ let fieldValues = cloneObject(_formValues);
2982
+ _subjects.state.next({
2983
+ isSubmitting: true,
2755
2984
  });
2756
- };
2757
- const insert$1 = (index, value, options) => {
2758
- const insertValue = convertToArrayPayload(cloneObject(value));
2759
- const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue);
2760
- control._names.focus = getFocusFieldName(name, index, options);
2761
- ids.current = insert(ids.current, index, insertValue.map(generateId));
2762
- updateValues(updatedFieldArrayValues);
2763
- setFields(updatedFieldArrayValues);
2764
- control._setFieldArray(name, updatedFieldArrayValues, insert, {
2765
- argA: index,
2766
- argB: fillEmptyArray(value),
2985
+ if (_options.resolver) {
2986
+ const { errors, values } = await _runSchema();
2987
+ _updateIsValidating();
2988
+ _formState.errors = errors;
2989
+ fieldValues = cloneObject(values);
2990
+ }
2991
+ else {
2992
+ await executeBuiltInValidation({
2993
+ fields: _fields,
2994
+ eventType: EVENTS.SUBMIT,
2995
+ });
2996
+ }
2997
+ if (_names.disabled.size) {
2998
+ for (const name of _names.disabled) {
2999
+ unset(fieldValues, name);
3000
+ }
3001
+ }
3002
+ unset(_formState.errors, ROOT_ERROR_TYPE);
3003
+ if (isEmptyObject(_formState.errors)) {
3004
+ _subjects.state.next({
3005
+ errors: {},
3006
+ });
3007
+ try {
3008
+ await onValid(fieldValues, e);
3009
+ }
3010
+ catch (error) {
3011
+ onValidError = error;
3012
+ }
3013
+ }
3014
+ else {
3015
+ if (onInvalid) {
3016
+ await onInvalid({ ..._formState.errors }, e);
3017
+ }
3018
+ _focusError();
3019
+ setTimeout(_focusError);
3020
+ }
3021
+ _subjects.state.next({
3022
+ isSubmitted: true,
3023
+ isSubmitting: false,
3024
+ isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError,
3025
+ submitCount: _formState.submitCount + 1,
3026
+ errors: _formState.errors,
2767
3027
  });
3028
+ if (onValidError) {
3029
+ throw onValidError;
3030
+ }
2768
3031
  };
2769
- const swap = (indexA, indexB) => {
2770
- const updatedFieldArrayValues = control._getFieldArray(name);
2771
- swapArrayAt(updatedFieldArrayValues, indexA, indexB);
2772
- swapArrayAt(ids.current, indexA, indexB);
2773
- updateValues(updatedFieldArrayValues);
2774
- setFields(updatedFieldArrayValues);
2775
- control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, {
2776
- argA: indexA,
2777
- argB: indexB,
2778
- }, false);
2779
- };
2780
- const move = (from, to) => {
2781
- const updatedFieldArrayValues = control._getFieldArray(name);
2782
- moveArrayAt(updatedFieldArrayValues, from, to);
2783
- moveArrayAt(ids.current, from, to);
2784
- updateValues(updatedFieldArrayValues);
2785
- setFields(updatedFieldArrayValues);
2786
- control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, {
2787
- argA: from,
2788
- argB: to,
2789
- }, false);
2790
- };
2791
- const update = (index, value) => {
2792
- const updateValue = cloneObject(value);
2793
- const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue);
2794
- ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]);
2795
- updateValues(updatedFieldArrayValues);
2796
- setFields([...updatedFieldArrayValues]);
2797
- control._setFieldArray(name, updatedFieldArrayValues, updateAt, {
2798
- argA: index,
2799
- argB: updateValue,
2800
- }, true, false);
2801
- };
2802
- const replace = (value) => {
2803
- const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value));
2804
- ids.current = updatedFieldArrayValues.map(generateId);
2805
- updateValues([...updatedFieldArrayValues]);
2806
- setFields([...updatedFieldArrayValues]);
2807
- control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false);
3032
+ const resetField = (name, options = {}) => {
3033
+ if (get(_fields, name)) {
3034
+ if (isUndefined(options.defaultValue)) {
3035
+ setValue(name, cloneObject(get(_defaultValues, name)));
3036
+ }
3037
+ else {
3038
+ setValue(name, options.defaultValue);
3039
+ set(_defaultValues, name, cloneObject(options.defaultValue));
3040
+ }
3041
+ if (!options.keepTouched) {
3042
+ unset(_formState.touchedFields, name);
3043
+ }
3044
+ if (!options.keepDirty) {
3045
+ unset(_formState.dirtyFields, name);
3046
+ _formState.isDirty = options.defaultValue
3047
+ ? _getDirty(name, cloneObject(get(_defaultValues, name)))
3048
+ : _getDirty();
3049
+ }
3050
+ if (!options.keepError) {
3051
+ unset(_formState.errors, name);
3052
+ _proxyFormState.isValid && _setValid();
3053
+ }
3054
+ _subjects.state.next({ ..._formState });
3055
+ }
2808
3056
  };
2809
- React.useEffect(() => {
2810
- control._state.action = false;
2811
- isWatched(name, control._names) &&
2812
- control._subjects.state.next({
2813
- ...control._formState,
2814
- });
2815
- if (_actioned.current &&
2816
- (!getValidationModes(control._options.mode).isOnSubmit ||
2817
- control._formState.isSubmitted) &&
2818
- !getValidationModes(control._options.reValidateMode).isOnSubmit) {
2819
- if (control._options.resolver) {
2820
- control._runSchema([name]).then((result) => {
2821
- control._updateIsValidating([name]);
2822
- const error = get(result.errors, name);
2823
- const existingError = get(control._formState.errors, name);
2824
- if (existingError
2825
- ? (!error && existingError.type) ||
2826
- (error &&
2827
- (existingError.type !== error.type ||
2828
- existingError.message !== error.message))
2829
- : error && error.type) {
2830
- error
2831
- ? set(control._formState.errors, name, error)
2832
- : unset(control._formState.errors, name);
2833
- control._subjects.state.next({
2834
- errors: control._formState.errors,
2835
- });
3057
+ const _reset = (formValues, keepStateOptions = {}) => {
3058
+ const updatedValues = formValues ? cloneObject(formValues) : _defaultValues;
3059
+ const cloneUpdatedValues = cloneObject(updatedValues);
3060
+ const isEmptyResetValues = isEmptyObject(formValues);
3061
+ const values = cloneUpdatedValues;
3062
+ const fieldRefs = _fields;
3063
+ if (!keepStateOptions.keepDefaultValues) {
3064
+ _defaultValues = updatedValues;
3065
+ }
3066
+ if (!keepStateOptions.keepValues) {
3067
+ if (keepStateOptions.keepDirtyValues) {
3068
+ const fieldsToCheck = new Set([
3069
+ ..._names.mount,
3070
+ ...Object.keys(getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)),
3071
+ ]);
3072
+ for (const fieldName of Array.from(fieldsToCheck)) {
3073
+ const isDirty = get(_formState.dirtyFields, fieldName);
3074
+ const existingValue = get(_formValues, fieldName);
3075
+ const newValue = get(values, fieldName);
3076
+ if (isDirty && !isUndefined(existingValue)) {
3077
+ set(values, fieldName, existingValue);
2836
3078
  }
2837
- });
3079
+ else if (!isDirty && !isUndefined(newValue)) {
3080
+ setValue(fieldName, newValue);
3081
+ }
3082
+ }
2838
3083
  }
2839
3084
  else {
2840
- const field = get(control._fields, name);
2841
- if (field &&
2842
- field._f &&
2843
- !(getValidationModes(control._options.reValidateMode).isOnSubmit &&
2844
- getValidationModes(control._options.mode).isOnSubmit)) {
2845
- validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) &&
2846
- control._subjects.state.next({
2847
- errors: updateFieldArrayRootError(control._formState.errors, error, name),
2848
- }));
3085
+ if (isWeb && isUndefined(formValues)) {
3086
+ for (const name of _names.mount) {
3087
+ const field = get(_fields, name);
3088
+ if (field && field._f) {
3089
+ const fieldReference = Array.isArray(field._f.refs)
3090
+ ? field._f.refs[0]
3091
+ : field._f.ref;
3092
+ if (isHTMLElement(fieldReference)) {
3093
+ const form = fieldReference.closest('form');
3094
+ if (form) {
3095
+ form.reset();
3096
+ break;
3097
+ }
3098
+ }
3099
+ }
3100
+ }
3101
+ }
3102
+ if (keepStateOptions.keepFieldsRef) {
3103
+ for (const fieldName of _names.mount) {
3104
+ setValue(fieldName, get(values, fieldName));
3105
+ }
3106
+ }
3107
+ else {
3108
+ _fields = {};
2849
3109
  }
2850
3110
  }
2851
- }
2852
- control._subjects.state.next({
2853
- name,
2854
- values: cloneObject(control._formValues),
2855
- });
2856
- control._names.focus &&
2857
- iterateFieldsByAction(control._fields, (ref, key) => {
2858
- if (control._names.focus &&
2859
- key.startsWith(control._names.focus) &&
2860
- ref.focus) {
2861
- ref.focus();
2862
- return 1;
3111
+ if (_options.shouldUnregister) {
3112
+ _formValues = keepStateOptions.keepDefaultValues
3113
+ ? cloneObject(_defaultValues)
3114
+ : {};
3115
+ if (keepStateOptions.keepFieldsRef) {
3116
+ for (const fieldName of _names.mount) {
3117
+ set(_formValues, fieldName, get(values, fieldName));
3118
+ }
2863
3119
  }
2864
- return;
3120
+ }
3121
+ else {
3122
+ _formValues = cloneObject(values);
3123
+ }
3124
+ _subjects.array.next({
3125
+ values: { ...values },
2865
3126
  });
2866
- control._names.focus = '';
2867
- control._setValid();
2868
- _actioned.current = false;
2869
- }, [fields, name, control]);
2870
- React.useEffect(() => {
2871
- !get(control._formValues, name) && control._setFieldArray(name);
2872
- return () => {
2873
- const updateMounted = (name, value) => {
2874
- const field = get(control._fields, name);
2875
- if (field && field._f) {
2876
- field._f.mount = value;
2877
- }
2878
- };
2879
- control._options.shouldUnregister || shouldUnregister
2880
- ? control.unregister(name)
2881
- : updateMounted(name, false);
3127
+ _subjects.state.next({
3128
+ name: undefined,
3129
+ type: undefined,
3130
+ values: { ...values },
3131
+ });
3132
+ }
3133
+ _names = {
3134
+ mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(),
3135
+ unMount: new Set(),
3136
+ array: new Set(),
3137
+ registerName: new Set(),
3138
+ disabled: new Set(),
3139
+ watch: new Set(),
3140
+ watchAll: false,
3141
+ focus: '',
3142
+ };
3143
+ _state.mount =
3144
+ !_proxyFormState.isValid ||
3145
+ !!keepStateOptions.keepIsValid ||
3146
+ !!keepStateOptions.keepDirtyValues ||
3147
+ (!_options.shouldUnregister && !isEmptyObject(values));
3148
+ _state.watch = !!_options.shouldUnregister;
3149
+ _state.keepIsValid = !!keepStateOptions.keepIsValid;
3150
+ _state.action = false;
3151
+ if (!keepStateOptions.keepErrors) {
3152
+ _formState.errors = {};
3153
+ }
3154
+ _subjects.state.next({
3155
+ submitCount: keepStateOptions.keepSubmitCount
3156
+ ? _formState.submitCount
3157
+ : 0,
3158
+ isDirty: isEmptyResetValues
3159
+ ? false
3160
+ : keepStateOptions.keepDirty
3161
+ ? _formState.isDirty
3162
+ : keepStateOptions.keepValues
3163
+ ? _getDirty()
3164
+ : !!(keepStateOptions.keepDefaultValues &&
3165
+ !deepEqual(formValues, _defaultValues)),
3166
+ isSubmitted: keepStateOptions.keepIsSubmitted
3167
+ ? _formState.isSubmitted
3168
+ : false,
3169
+ dirtyFields: isEmptyResetValues
3170
+ ? {}
3171
+ : keepStateOptions.keepDirtyValues
3172
+ ? keepStateOptions.keepDefaultValues && _formValues
3173
+ ? getDirtyFields(_defaultValues, _formValues, undefined, fieldRefs)
3174
+ : _formState.dirtyFields
3175
+ : keepStateOptions.keepDefaultValues && formValues
3176
+ ? getDirtyFields(_defaultValues, formValues, undefined, fieldRefs)
3177
+ : keepStateOptions.keepDirty
3178
+ ? _formState.dirtyFields
3179
+ : {},
3180
+ touchedFields: keepStateOptions.keepTouched
3181
+ ? _formState.touchedFields
3182
+ : {},
3183
+ errors: keepStateOptions.keepErrors ? _formState.errors : {},
3184
+ isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful
3185
+ ? _formState.isSubmitSuccessful
3186
+ : false,
3187
+ isSubmitting: false,
3188
+ defaultValues: _defaultValues,
3189
+ });
3190
+ };
3191
+ const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues)
3192
+ ? formValues(_formValues)
3193
+ : formValues, { ..._options.resetOptions, ...keepStateOptions });
3194
+ const setFocus = (name, options = {}) => {
3195
+ const field = get(_fields, name);
3196
+ const fieldReference = field && field._f;
3197
+ if (fieldReference) {
3198
+ const fieldRef = fieldReference.refs
3199
+ ? fieldReference.refs[0]
3200
+ : fieldReference.ref;
3201
+ if (fieldRef.focus) {
3202
+ setTimeout(() => {
3203
+ fieldRef.focus();
3204
+ options.shouldSelect &&
3205
+ isFunction(fieldRef.select) &&
3206
+ fieldRef.select();
3207
+ });
3208
+ }
3209
+ }
3210
+ };
3211
+ const _setFormState = (updatedFormState) => {
3212
+ // `name`, `type`, and `values` describe the event that produced this
3213
+ // update, not the form's persisted state (they aren't part of
3214
+ // `FormState`). Merging them in would leak a stale `name`/`type` from
3215
+ // one event into a later, unrelated notification that doesn't specify
3216
+ // its own.
3217
+ const { name, type, values, ...formState } = updatedFormState;
3218
+ _formState = {
3219
+ ..._formState,
3220
+ ...formState,
2882
3221
  };
2883
- }, [name, control, keyName, shouldUnregister]);
3222
+ };
3223
+ const _resetDefaultValues = () => isFunction(_options.defaultValues) &&
3224
+ _options.defaultValues().then((values) => {
3225
+ reset(values, _options.resetOptions);
3226
+ _subjects.state.next({
3227
+ isLoading: false,
3228
+ });
3229
+ });
3230
+ const resetDefaultValues = (values, options = {}) => {
3231
+ _defaultValues = cloneObject(values);
3232
+ if (!options.keepDirty) {
3233
+ const newDirtyFields = getDirtyFields(_defaultValues, _formValues, undefined, _fields);
3234
+ _formState.dirtyFields = newDirtyFields;
3235
+ _formState.isDirty = !isEmptyObject(newDirtyFields);
3236
+ }
3237
+ if (!options.keepIsValid) {
3238
+ _setValid();
3239
+ }
3240
+ _subjects.state.next({
3241
+ ..._formState,
3242
+ defaultValues: _defaultValues,
3243
+ });
3244
+ };
3245
+ const methods = {
3246
+ control: {
3247
+ register,
3248
+ unregister,
3249
+ getFieldState,
3250
+ handleSubmit,
3251
+ setError,
3252
+ _subscribe,
3253
+ _runSchema,
3254
+ _updateIsValidating,
3255
+ _focusError,
3256
+ _getWatch,
3257
+ _getDirty,
3258
+ _setValid,
3259
+ _setFieldArray,
3260
+ _setDisabledField,
3261
+ _setErrors,
3262
+ _getFieldArray,
3263
+ _reset,
3264
+ _resetDefaultValues,
3265
+ _removeUnmounted,
3266
+ _disableForm,
3267
+ _subjects,
3268
+ _proxyFormState,
3269
+ get _fields() {
3270
+ return _fields;
3271
+ },
3272
+ get _formValues() {
3273
+ return _formValues;
3274
+ },
3275
+ get _state() {
3276
+ return _state;
3277
+ },
3278
+ set _state(value) {
3279
+ _state = value;
3280
+ },
3281
+ get _defaultValues() {
3282
+ return _defaultValues;
3283
+ },
3284
+ get _names() {
3285
+ return _names;
3286
+ },
3287
+ set _names(value) {
3288
+ _names = value;
3289
+ },
3290
+ get _formState() {
3291
+ return _formState;
3292
+ },
3293
+ get _options() {
3294
+ return _options;
3295
+ },
3296
+ set _options(value) {
3297
+ _options = {
3298
+ ..._options,
3299
+ ...value,
3300
+ };
3301
+ _validationModeBeforeSubmit = getValidationModes(_options.mode);
3302
+ _validationModeAfterSubmit = getValidationModes(_options.reValidateMode);
3303
+ },
3304
+ },
3305
+ subscribe,
3306
+ trigger,
3307
+ register,
3308
+ handleSubmit,
3309
+ watch,
3310
+ setValue,
3311
+ setValues,
3312
+ getValues,
3313
+ reset,
3314
+ resetField,
3315
+ resetDefaultValues,
3316
+ clearErrors,
3317
+ unregister,
3318
+ setError,
3319
+ setFocus,
3320
+ getFieldState,
3321
+ };
2884
3322
  return {
2885
- swap: React.useCallback(swap, [updateValues, name, control]),
2886
- move: React.useCallback(move, [updateValues, name, control]),
2887
- prepend: React.useCallback(prepend, [updateValues, name, control]),
2888
- append: React.useCallback(append, [updateValues, name, control]),
2889
- remove: React.useCallback(remove, [updateValues, name, control]),
2890
- insert: React.useCallback(insert$1, [updateValues, name, control]),
2891
- update: React.useCallback(update, [updateValues, name, control]),
2892
- replace: React.useCallback(replace, [updateValues, name, control]),
2893
- fields: React.useMemo(() => fields.map((field, index) => ({
2894
- ...field,
2895
- [keyName]: ids.current[index] || generateId(),
2896
- })), [fields, keyName]),
3323
+ ...methods,
3324
+ formControl: methods,
2897
3325
  };
2898
3326
  }
2899
3327
 
@@ -2929,26 +3357,19 @@ function useFieldArray(props) {
2929
3357
  function useForm(props = {}) {
2930
3358
  const _formControl = React.useRef(undefined);
2931
3359
  const _values = React.useRef(undefined);
2932
- const [formState, updateFormState] = React.useState({
2933
- isDirty: false,
2934
- isValidating: false,
3360
+ const _formControlProp = React.useRef(props.formControl);
3361
+ const [formState, updateFormState] = React.useState(() => ({
3362
+ ...cloneObject(DEFAULT_FORM_STATE),
2935
3363
  isLoading: isFunction(props.defaultValues),
2936
- isSubmitted: false,
2937
- isSubmitting: false,
2938
- isSubmitSuccessful: false,
2939
- isValid: false,
2940
- submitCount: 0,
2941
- dirtyFields: {},
2942
- touchedFields: {},
2943
- validatingFields: {},
2944
3364
  errors: props.errors || {},
2945
3365
  disabled: props.disabled || false,
2946
- isReady: false,
2947
3366
  defaultValues: isFunction(props.defaultValues)
2948
3367
  ? undefined
2949
3368
  : props.defaultValues,
2950
- });
2951
- if (!_formControl.current) {
3369
+ }));
3370
+ if (!_formControl.current ||
3371
+ (props.formControl && _formControlProp.current !== props.formControl)) {
3372
+ _formControlProp.current = props.formControl;
2952
3373
  if (props.formControl) {
2953
3374
  _formControl.current = {
2954
3375
  ...props.formControl,
@@ -2971,7 +3392,10 @@ function useForm(props = {}) {
2971
3392
  useIsomorphicLayoutEffect(() => {
2972
3393
  const sub = control._subscribe({
2973
3394
  formState: control._proxyFormState,
2974
- callback: () => updateFormState({ ...control._formState }),
3395
+ callback: () => updateFormState({
3396
+ ...control._formState,
3397
+ defaultValues: control._defaultValues,
3398
+ }),
2975
3399
  reRenderRoot: true,
2976
3400
  });
2977
3401
  updateFormState((data) => ({
@@ -3072,5 +3496,5 @@ function useForm(props = {}) {
3072
3496
  */
3073
3497
  const Watch = (props) => props.render(useWatch({ name: props.names, ...props }));
3074
3498
 
3075
- export { Controller, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
3499
+ export { Controller, FieldArray, Form, FormProvider, FormStateSubscribe, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useForm, useFormContext, useFormState, useWatch };
3076
3500
  //# sourceMappingURL=index.esm.mjs.map