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