@xyo-network/react-form-group 2.81.2

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 (398) hide show
  1. package/LICENSE +165 -0
  2. package/README.md +13 -0
  3. package/dist/browser/FormGroup.d.cts +44 -0
  4. package/dist/browser/FormGroup.d.cts.map +1 -0
  5. package/dist/browser/FormGroup.d.mts +44 -0
  6. package/dist/browser/FormGroup.d.mts.map +1 -0
  7. package/dist/browser/FormGroup.d.ts +44 -0
  8. package/dist/browser/FormGroup.d.ts.map +1 -0
  9. package/dist/browser/InputError.d.cts +5 -0
  10. package/dist/browser/InputError.d.cts.map +1 -0
  11. package/dist/browser/InputError.d.mts +5 -0
  12. package/dist/browser/InputError.d.mts.map +1 -0
  13. package/dist/browser/InputError.d.ts +5 -0
  14. package/dist/browser/InputError.d.ts.map +1 -0
  15. package/dist/browser/context/Context.d.cts +7 -0
  16. package/dist/browser/context/Context.d.cts.map +1 -0
  17. package/dist/browser/context/Context.d.mts +7 -0
  18. package/dist/browser/context/Context.d.mts.map +1 -0
  19. package/dist/browser/context/Context.d.ts +7 -0
  20. package/dist/browser/context/Context.d.ts.map +1 -0
  21. package/dist/browser/context/Provider.d.cts +8 -0
  22. package/dist/browser/context/Provider.d.cts.map +1 -0
  23. package/dist/browser/context/Provider.d.mts +8 -0
  24. package/dist/browser/context/Provider.d.mts.map +1 -0
  25. package/dist/browser/context/Provider.d.ts +8 -0
  26. package/dist/browser/context/Provider.d.ts.map +1 -0
  27. package/dist/browser/context/State.d.cts +7 -0
  28. package/dist/browser/context/State.d.cts.map +1 -0
  29. package/dist/browser/context/State.d.mts +7 -0
  30. package/dist/browser/context/State.d.mts.map +1 -0
  31. package/dist/browser/context/State.d.ts +7 -0
  32. package/dist/browser/context/State.d.ts.map +1 -0
  33. package/dist/browser/context/index.d.cts +5 -0
  34. package/dist/browser/context/index.d.cts.map +1 -0
  35. package/dist/browser/context/index.d.mts +5 -0
  36. package/dist/browser/context/index.d.mts.map +1 -0
  37. package/dist/browser/context/index.d.ts +5 -0
  38. package/dist/browser/context/index.d.ts.map +1 -0
  39. package/dist/browser/context/use.d.cts +6 -0
  40. package/dist/browser/context/use.d.cts.map +1 -0
  41. package/dist/browser/context/use.d.mts +6 -0
  42. package/dist/browser/context/use.d.mts.map +1 -0
  43. package/dist/browser/context/use.d.ts +6 -0
  44. package/dist/browser/context/use.d.ts.map +1 -0
  45. package/dist/browser/control/AbstractControl.d.cts +21 -0
  46. package/dist/browser/control/AbstractControl.d.cts.map +1 -0
  47. package/dist/browser/control/AbstractControl.d.mts +21 -0
  48. package/dist/browser/control/AbstractControl.d.mts.map +1 -0
  49. package/dist/browser/control/AbstractControl.d.ts +21 -0
  50. package/dist/browser/control/AbstractControl.d.ts.map +1 -0
  51. package/dist/browser/control/FormControl.d.cts +25 -0
  52. package/dist/browser/control/FormControl.d.cts.map +1 -0
  53. package/dist/browser/control/FormControl.d.mts +25 -0
  54. package/dist/browser/control/FormControl.d.mts.map +1 -0
  55. package/dist/browser/control/FormControl.d.ts +25 -0
  56. package/dist/browser/control/FormControl.d.ts.map +1 -0
  57. package/dist/browser/control/FormControlBase.d.cts +26 -0
  58. package/dist/browser/control/FormControlBase.d.cts.map +1 -0
  59. package/dist/browser/control/FormControlBase.d.mts +26 -0
  60. package/dist/browser/control/FormControlBase.d.mts.map +1 -0
  61. package/dist/browser/control/FormControlBase.d.ts +26 -0
  62. package/dist/browser/control/FormControlBase.d.ts.map +1 -0
  63. package/dist/browser/control/accessor/ControlValueAccessor.d.cts +21 -0
  64. package/dist/browser/control/accessor/ControlValueAccessor.d.cts.map +1 -0
  65. package/dist/browser/control/accessor/ControlValueAccessor.d.mts +21 -0
  66. package/dist/browser/control/accessor/ControlValueAccessor.d.mts.map +1 -0
  67. package/dist/browser/control/accessor/ControlValueAccessor.d.ts +21 -0
  68. package/dist/browser/control/accessor/ControlValueAccessor.d.ts.map +1 -0
  69. package/dist/browser/control/accessor/ControlValueAccessorBase.d.cts +45 -0
  70. package/dist/browser/control/accessor/ControlValueAccessorBase.d.cts.map +1 -0
  71. package/dist/browser/control/accessor/ControlValueAccessorBase.d.mts +45 -0
  72. package/dist/browser/control/accessor/ControlValueAccessorBase.d.mts.map +1 -0
  73. package/dist/browser/control/accessor/ControlValueAccessorBase.d.ts +45 -0
  74. package/dist/browser/control/accessor/ControlValueAccessorBase.d.ts.map +1 -0
  75. package/dist/browser/control/accessor/FormControlStatus.d.cts +6 -0
  76. package/dist/browser/control/accessor/FormControlStatus.d.cts.map +1 -0
  77. package/dist/browser/control/accessor/FormControlStatus.d.mts +6 -0
  78. package/dist/browser/control/accessor/FormControlStatus.d.mts.map +1 -0
  79. package/dist/browser/control/accessor/FormControlStatus.d.ts +6 -0
  80. package/dist/browser/control/accessor/FormControlStatus.d.ts.map +1 -0
  81. package/dist/browser/control/accessor/ValidControlValue.d.cts +2 -0
  82. package/dist/browser/control/accessor/ValidControlValue.d.cts.map +1 -0
  83. package/dist/browser/control/accessor/ValidControlValue.d.mts +2 -0
  84. package/dist/browser/control/accessor/ValidControlValue.d.mts.map +1 -0
  85. package/dist/browser/control/accessor/ValidControlValue.d.ts +2 -0
  86. package/dist/browser/control/accessor/ValidControlValue.d.ts.map +1 -0
  87. package/dist/browser/control/accessor/index.d.cts +5 -0
  88. package/dist/browser/control/accessor/index.d.cts.map +1 -0
  89. package/dist/browser/control/accessor/index.d.mts +5 -0
  90. package/dist/browser/control/accessor/index.d.mts.map +1 -0
  91. package/dist/browser/control/accessor/index.d.ts +5 -0
  92. package/dist/browser/control/accessor/index.d.ts.map +1 -0
  93. package/dist/browser/control/index.d.cts +5 -0
  94. package/dist/browser/control/index.d.cts.map +1 -0
  95. package/dist/browser/control/index.d.mts +5 -0
  96. package/dist/browser/control/index.d.mts.map +1 -0
  97. package/dist/browser/control/index.d.ts +5 -0
  98. package/dist/browser/control/index.d.ts.map +1 -0
  99. package/dist/browser/index.cjs +517 -0
  100. package/dist/browser/index.cjs.map +1 -0
  101. package/dist/browser/index.d.cts +6 -0
  102. package/dist/browser/index.d.cts.map +1 -0
  103. package/dist/browser/index.d.mts +6 -0
  104. package/dist/browser/index.d.mts.map +1 -0
  105. package/dist/browser/index.d.ts +6 -0
  106. package/dist/browser/index.d.ts.map +1 -0
  107. package/dist/browser/index.js +494 -0
  108. package/dist/browser/index.js.map +1 -0
  109. package/dist/browser/storage/ArchivistFormGroupStorage.d.cts +13 -0
  110. package/dist/browser/storage/ArchivistFormGroupStorage.d.cts.map +1 -0
  111. package/dist/browser/storage/ArchivistFormGroupStorage.d.mts +13 -0
  112. package/dist/browser/storage/ArchivistFormGroupStorage.d.mts.map +1 -0
  113. package/dist/browser/storage/ArchivistFormGroupStorage.d.ts +13 -0
  114. package/dist/browser/storage/ArchivistFormGroupStorage.d.ts.map +1 -0
  115. package/dist/browser/storage/FormGroupStorage.d.cts +8 -0
  116. package/dist/browser/storage/FormGroupStorage.d.cts.map +1 -0
  117. package/dist/browser/storage/FormGroupStorage.d.mts +8 -0
  118. package/dist/browser/storage/FormGroupStorage.d.mts.map +1 -0
  119. package/dist/browser/storage/FormGroupStorage.d.ts +8 -0
  120. package/dist/browser/storage/FormGroupStorage.d.ts.map +1 -0
  121. package/dist/browser/storage/index.d.cts +3 -0
  122. package/dist/browser/storage/index.d.cts.map +1 -0
  123. package/dist/browser/storage/index.d.mts +3 -0
  124. package/dist/browser/storage/index.d.mts.map +1 -0
  125. package/dist/browser/storage/index.d.ts +3 -0
  126. package/dist/browser/storage/index.d.ts.map +1 -0
  127. package/dist/neutral/FormGroup.d.cts +44 -0
  128. package/dist/neutral/FormGroup.d.cts.map +1 -0
  129. package/dist/neutral/FormGroup.d.mts +44 -0
  130. package/dist/neutral/FormGroup.d.mts.map +1 -0
  131. package/dist/neutral/FormGroup.d.ts +44 -0
  132. package/dist/neutral/FormGroup.d.ts.map +1 -0
  133. package/dist/neutral/InputError.d.cts +5 -0
  134. package/dist/neutral/InputError.d.cts.map +1 -0
  135. package/dist/neutral/InputError.d.mts +5 -0
  136. package/dist/neutral/InputError.d.mts.map +1 -0
  137. package/dist/neutral/InputError.d.ts +5 -0
  138. package/dist/neutral/InputError.d.ts.map +1 -0
  139. package/dist/neutral/context/Context.d.cts +7 -0
  140. package/dist/neutral/context/Context.d.cts.map +1 -0
  141. package/dist/neutral/context/Context.d.mts +7 -0
  142. package/dist/neutral/context/Context.d.mts.map +1 -0
  143. package/dist/neutral/context/Context.d.ts +7 -0
  144. package/dist/neutral/context/Context.d.ts.map +1 -0
  145. package/dist/neutral/context/Provider.d.cts +8 -0
  146. package/dist/neutral/context/Provider.d.cts.map +1 -0
  147. package/dist/neutral/context/Provider.d.mts +8 -0
  148. package/dist/neutral/context/Provider.d.mts.map +1 -0
  149. package/dist/neutral/context/Provider.d.ts +8 -0
  150. package/dist/neutral/context/Provider.d.ts.map +1 -0
  151. package/dist/neutral/context/State.d.cts +7 -0
  152. package/dist/neutral/context/State.d.cts.map +1 -0
  153. package/dist/neutral/context/State.d.mts +7 -0
  154. package/dist/neutral/context/State.d.mts.map +1 -0
  155. package/dist/neutral/context/State.d.ts +7 -0
  156. package/dist/neutral/context/State.d.ts.map +1 -0
  157. package/dist/neutral/context/index.d.cts +5 -0
  158. package/dist/neutral/context/index.d.cts.map +1 -0
  159. package/dist/neutral/context/index.d.mts +5 -0
  160. package/dist/neutral/context/index.d.mts.map +1 -0
  161. package/dist/neutral/context/index.d.ts +5 -0
  162. package/dist/neutral/context/index.d.ts.map +1 -0
  163. package/dist/neutral/context/use.d.cts +6 -0
  164. package/dist/neutral/context/use.d.cts.map +1 -0
  165. package/dist/neutral/context/use.d.mts +6 -0
  166. package/dist/neutral/context/use.d.mts.map +1 -0
  167. package/dist/neutral/context/use.d.ts +6 -0
  168. package/dist/neutral/context/use.d.ts.map +1 -0
  169. package/dist/neutral/control/AbstractControl.d.cts +21 -0
  170. package/dist/neutral/control/AbstractControl.d.cts.map +1 -0
  171. package/dist/neutral/control/AbstractControl.d.mts +21 -0
  172. package/dist/neutral/control/AbstractControl.d.mts.map +1 -0
  173. package/dist/neutral/control/AbstractControl.d.ts +21 -0
  174. package/dist/neutral/control/AbstractControl.d.ts.map +1 -0
  175. package/dist/neutral/control/FormControl.d.cts +25 -0
  176. package/dist/neutral/control/FormControl.d.cts.map +1 -0
  177. package/dist/neutral/control/FormControl.d.mts +25 -0
  178. package/dist/neutral/control/FormControl.d.mts.map +1 -0
  179. package/dist/neutral/control/FormControl.d.ts +25 -0
  180. package/dist/neutral/control/FormControl.d.ts.map +1 -0
  181. package/dist/neutral/control/FormControlBase.d.cts +26 -0
  182. package/dist/neutral/control/FormControlBase.d.cts.map +1 -0
  183. package/dist/neutral/control/FormControlBase.d.mts +26 -0
  184. package/dist/neutral/control/FormControlBase.d.mts.map +1 -0
  185. package/dist/neutral/control/FormControlBase.d.ts +26 -0
  186. package/dist/neutral/control/FormControlBase.d.ts.map +1 -0
  187. package/dist/neutral/control/accessor/ControlValueAccessor.d.cts +21 -0
  188. package/dist/neutral/control/accessor/ControlValueAccessor.d.cts.map +1 -0
  189. package/dist/neutral/control/accessor/ControlValueAccessor.d.mts +21 -0
  190. package/dist/neutral/control/accessor/ControlValueAccessor.d.mts.map +1 -0
  191. package/dist/neutral/control/accessor/ControlValueAccessor.d.ts +21 -0
  192. package/dist/neutral/control/accessor/ControlValueAccessor.d.ts.map +1 -0
  193. package/dist/neutral/control/accessor/ControlValueAccessorBase.d.cts +45 -0
  194. package/dist/neutral/control/accessor/ControlValueAccessorBase.d.cts.map +1 -0
  195. package/dist/neutral/control/accessor/ControlValueAccessorBase.d.mts +45 -0
  196. package/dist/neutral/control/accessor/ControlValueAccessorBase.d.mts.map +1 -0
  197. package/dist/neutral/control/accessor/ControlValueAccessorBase.d.ts +45 -0
  198. package/dist/neutral/control/accessor/ControlValueAccessorBase.d.ts.map +1 -0
  199. package/dist/neutral/control/accessor/FormControlStatus.d.cts +6 -0
  200. package/dist/neutral/control/accessor/FormControlStatus.d.cts.map +1 -0
  201. package/dist/neutral/control/accessor/FormControlStatus.d.mts +6 -0
  202. package/dist/neutral/control/accessor/FormControlStatus.d.mts.map +1 -0
  203. package/dist/neutral/control/accessor/FormControlStatus.d.ts +6 -0
  204. package/dist/neutral/control/accessor/FormControlStatus.d.ts.map +1 -0
  205. package/dist/neutral/control/accessor/ValidControlValue.d.cts +2 -0
  206. package/dist/neutral/control/accessor/ValidControlValue.d.cts.map +1 -0
  207. package/dist/neutral/control/accessor/ValidControlValue.d.mts +2 -0
  208. package/dist/neutral/control/accessor/ValidControlValue.d.mts.map +1 -0
  209. package/dist/neutral/control/accessor/ValidControlValue.d.ts +2 -0
  210. package/dist/neutral/control/accessor/ValidControlValue.d.ts.map +1 -0
  211. package/dist/neutral/control/accessor/index.d.cts +5 -0
  212. package/dist/neutral/control/accessor/index.d.cts.map +1 -0
  213. package/dist/neutral/control/accessor/index.d.mts +5 -0
  214. package/dist/neutral/control/accessor/index.d.mts.map +1 -0
  215. package/dist/neutral/control/accessor/index.d.ts +5 -0
  216. package/dist/neutral/control/accessor/index.d.ts.map +1 -0
  217. package/dist/neutral/control/index.d.cts +5 -0
  218. package/dist/neutral/control/index.d.cts.map +1 -0
  219. package/dist/neutral/control/index.d.mts +5 -0
  220. package/dist/neutral/control/index.d.mts.map +1 -0
  221. package/dist/neutral/control/index.d.ts +5 -0
  222. package/dist/neutral/control/index.d.ts.map +1 -0
  223. package/dist/neutral/index.cjs +517 -0
  224. package/dist/neutral/index.cjs.map +1 -0
  225. package/dist/neutral/index.d.cts +6 -0
  226. package/dist/neutral/index.d.cts.map +1 -0
  227. package/dist/neutral/index.d.mts +6 -0
  228. package/dist/neutral/index.d.mts.map +1 -0
  229. package/dist/neutral/index.d.ts +6 -0
  230. package/dist/neutral/index.d.ts.map +1 -0
  231. package/dist/neutral/index.js +494 -0
  232. package/dist/neutral/index.js.map +1 -0
  233. package/dist/neutral/storage/ArchivistFormGroupStorage.d.cts +13 -0
  234. package/dist/neutral/storage/ArchivistFormGroupStorage.d.cts.map +1 -0
  235. package/dist/neutral/storage/ArchivistFormGroupStorage.d.mts +13 -0
  236. package/dist/neutral/storage/ArchivistFormGroupStorage.d.mts.map +1 -0
  237. package/dist/neutral/storage/ArchivistFormGroupStorage.d.ts +13 -0
  238. package/dist/neutral/storage/ArchivistFormGroupStorage.d.ts.map +1 -0
  239. package/dist/neutral/storage/FormGroupStorage.d.cts +8 -0
  240. package/dist/neutral/storage/FormGroupStorage.d.cts.map +1 -0
  241. package/dist/neutral/storage/FormGroupStorage.d.mts +8 -0
  242. package/dist/neutral/storage/FormGroupStorage.d.mts.map +1 -0
  243. package/dist/neutral/storage/FormGroupStorage.d.ts +8 -0
  244. package/dist/neutral/storage/FormGroupStorage.d.ts.map +1 -0
  245. package/dist/neutral/storage/index.d.cts +3 -0
  246. package/dist/neutral/storage/index.d.cts.map +1 -0
  247. package/dist/neutral/storage/index.d.mts +3 -0
  248. package/dist/neutral/storage/index.d.mts.map +1 -0
  249. package/dist/neutral/storage/index.d.ts +3 -0
  250. package/dist/neutral/storage/index.d.ts.map +1 -0
  251. package/dist/node/FormGroup.d.cts +44 -0
  252. package/dist/node/FormGroup.d.cts.map +1 -0
  253. package/dist/node/FormGroup.d.mts +44 -0
  254. package/dist/node/FormGroup.d.mts.map +1 -0
  255. package/dist/node/FormGroup.d.ts +44 -0
  256. package/dist/node/FormGroup.d.ts.map +1 -0
  257. package/dist/node/InputError.d.cts +5 -0
  258. package/dist/node/InputError.d.cts.map +1 -0
  259. package/dist/node/InputError.d.mts +5 -0
  260. package/dist/node/InputError.d.mts.map +1 -0
  261. package/dist/node/InputError.d.ts +5 -0
  262. package/dist/node/InputError.d.ts.map +1 -0
  263. package/dist/node/context/Context.d.cts +7 -0
  264. package/dist/node/context/Context.d.cts.map +1 -0
  265. package/dist/node/context/Context.d.mts +7 -0
  266. package/dist/node/context/Context.d.mts.map +1 -0
  267. package/dist/node/context/Context.d.ts +7 -0
  268. package/dist/node/context/Context.d.ts.map +1 -0
  269. package/dist/node/context/Provider.d.cts +8 -0
  270. package/dist/node/context/Provider.d.cts.map +1 -0
  271. package/dist/node/context/Provider.d.mts +8 -0
  272. package/dist/node/context/Provider.d.mts.map +1 -0
  273. package/dist/node/context/Provider.d.ts +8 -0
  274. package/dist/node/context/Provider.d.ts.map +1 -0
  275. package/dist/node/context/State.d.cts +7 -0
  276. package/dist/node/context/State.d.cts.map +1 -0
  277. package/dist/node/context/State.d.mts +7 -0
  278. package/dist/node/context/State.d.mts.map +1 -0
  279. package/dist/node/context/State.d.ts +7 -0
  280. package/dist/node/context/State.d.ts.map +1 -0
  281. package/dist/node/context/index.d.cts +5 -0
  282. package/dist/node/context/index.d.cts.map +1 -0
  283. package/dist/node/context/index.d.mts +5 -0
  284. package/dist/node/context/index.d.mts.map +1 -0
  285. package/dist/node/context/index.d.ts +5 -0
  286. package/dist/node/context/index.d.ts.map +1 -0
  287. package/dist/node/context/use.d.cts +6 -0
  288. package/dist/node/context/use.d.cts.map +1 -0
  289. package/dist/node/context/use.d.mts +6 -0
  290. package/dist/node/context/use.d.mts.map +1 -0
  291. package/dist/node/context/use.d.ts +6 -0
  292. package/dist/node/context/use.d.ts.map +1 -0
  293. package/dist/node/control/AbstractControl.d.cts +21 -0
  294. package/dist/node/control/AbstractControl.d.cts.map +1 -0
  295. package/dist/node/control/AbstractControl.d.mts +21 -0
  296. package/dist/node/control/AbstractControl.d.mts.map +1 -0
  297. package/dist/node/control/AbstractControl.d.ts +21 -0
  298. package/dist/node/control/AbstractControl.d.ts.map +1 -0
  299. package/dist/node/control/FormControl.d.cts +25 -0
  300. package/dist/node/control/FormControl.d.cts.map +1 -0
  301. package/dist/node/control/FormControl.d.mts +25 -0
  302. package/dist/node/control/FormControl.d.mts.map +1 -0
  303. package/dist/node/control/FormControl.d.ts +25 -0
  304. package/dist/node/control/FormControl.d.ts.map +1 -0
  305. package/dist/node/control/FormControlBase.d.cts +26 -0
  306. package/dist/node/control/FormControlBase.d.cts.map +1 -0
  307. package/dist/node/control/FormControlBase.d.mts +26 -0
  308. package/dist/node/control/FormControlBase.d.mts.map +1 -0
  309. package/dist/node/control/FormControlBase.d.ts +26 -0
  310. package/dist/node/control/FormControlBase.d.ts.map +1 -0
  311. package/dist/node/control/accessor/ControlValueAccessor.d.cts +21 -0
  312. package/dist/node/control/accessor/ControlValueAccessor.d.cts.map +1 -0
  313. package/dist/node/control/accessor/ControlValueAccessor.d.mts +21 -0
  314. package/dist/node/control/accessor/ControlValueAccessor.d.mts.map +1 -0
  315. package/dist/node/control/accessor/ControlValueAccessor.d.ts +21 -0
  316. package/dist/node/control/accessor/ControlValueAccessor.d.ts.map +1 -0
  317. package/dist/node/control/accessor/ControlValueAccessorBase.d.cts +45 -0
  318. package/dist/node/control/accessor/ControlValueAccessorBase.d.cts.map +1 -0
  319. package/dist/node/control/accessor/ControlValueAccessorBase.d.mts +45 -0
  320. package/dist/node/control/accessor/ControlValueAccessorBase.d.mts.map +1 -0
  321. package/dist/node/control/accessor/ControlValueAccessorBase.d.ts +45 -0
  322. package/dist/node/control/accessor/ControlValueAccessorBase.d.ts.map +1 -0
  323. package/dist/node/control/accessor/FormControlStatus.d.cts +6 -0
  324. package/dist/node/control/accessor/FormControlStatus.d.cts.map +1 -0
  325. package/dist/node/control/accessor/FormControlStatus.d.mts +6 -0
  326. package/dist/node/control/accessor/FormControlStatus.d.mts.map +1 -0
  327. package/dist/node/control/accessor/FormControlStatus.d.ts +6 -0
  328. package/dist/node/control/accessor/FormControlStatus.d.ts.map +1 -0
  329. package/dist/node/control/accessor/ValidControlValue.d.cts +2 -0
  330. package/dist/node/control/accessor/ValidControlValue.d.cts.map +1 -0
  331. package/dist/node/control/accessor/ValidControlValue.d.mts +2 -0
  332. package/dist/node/control/accessor/ValidControlValue.d.mts.map +1 -0
  333. package/dist/node/control/accessor/ValidControlValue.d.ts +2 -0
  334. package/dist/node/control/accessor/ValidControlValue.d.ts.map +1 -0
  335. package/dist/node/control/accessor/index.d.cts +5 -0
  336. package/dist/node/control/accessor/index.d.cts.map +1 -0
  337. package/dist/node/control/accessor/index.d.mts +5 -0
  338. package/dist/node/control/accessor/index.d.mts.map +1 -0
  339. package/dist/node/control/accessor/index.d.ts +5 -0
  340. package/dist/node/control/accessor/index.d.ts.map +1 -0
  341. package/dist/node/control/index.d.cts +5 -0
  342. package/dist/node/control/index.d.cts.map +1 -0
  343. package/dist/node/control/index.d.mts +5 -0
  344. package/dist/node/control/index.d.mts.map +1 -0
  345. package/dist/node/control/index.d.ts +5 -0
  346. package/dist/node/control/index.d.ts.map +1 -0
  347. package/dist/node/index.cjs +542 -0
  348. package/dist/node/index.cjs.map +1 -0
  349. package/dist/node/index.d.cts +6 -0
  350. package/dist/node/index.d.cts.map +1 -0
  351. package/dist/node/index.d.mts +6 -0
  352. package/dist/node/index.d.mts.map +1 -0
  353. package/dist/node/index.d.ts +6 -0
  354. package/dist/node/index.d.ts.map +1 -0
  355. package/dist/node/index.js +503 -0
  356. package/dist/node/index.js.map +1 -0
  357. package/dist/node/storage/ArchivistFormGroupStorage.d.cts +13 -0
  358. package/dist/node/storage/ArchivistFormGroupStorage.d.cts.map +1 -0
  359. package/dist/node/storage/ArchivistFormGroupStorage.d.mts +13 -0
  360. package/dist/node/storage/ArchivistFormGroupStorage.d.mts.map +1 -0
  361. package/dist/node/storage/ArchivistFormGroupStorage.d.ts +13 -0
  362. package/dist/node/storage/ArchivistFormGroupStorage.d.ts.map +1 -0
  363. package/dist/node/storage/FormGroupStorage.d.cts +8 -0
  364. package/dist/node/storage/FormGroupStorage.d.cts.map +1 -0
  365. package/dist/node/storage/FormGroupStorage.d.mts +8 -0
  366. package/dist/node/storage/FormGroupStorage.d.mts.map +1 -0
  367. package/dist/node/storage/FormGroupStorage.d.ts +8 -0
  368. package/dist/node/storage/FormGroupStorage.d.ts.map +1 -0
  369. package/dist/node/storage/index.d.cts +3 -0
  370. package/dist/node/storage/index.d.cts.map +1 -0
  371. package/dist/node/storage/index.d.mts +3 -0
  372. package/dist/node/storage/index.d.mts.map +1 -0
  373. package/dist/node/storage/index.d.ts +3 -0
  374. package/dist/node/storage/index.d.ts.map +1 -0
  375. package/package.json +88 -0
  376. package/src/FormGroup.ts +226 -0
  377. package/src/InputError.ts +4 -0
  378. package/src/context/Context.ts +5 -0
  379. package/src/context/Provider.tsx +25 -0
  380. package/src/context/State.ts +8 -0
  381. package/src/context/index.ts +4 -0
  382. package/src/context/use.tsx +5 -0
  383. package/src/control/AbstractControl.ts +125 -0
  384. package/src/control/FormControl.ts +31 -0
  385. package/src/control/FormControlBase.ts +82 -0
  386. package/src/control/accessor/ControlValueAccessor.ts +23 -0
  387. package/src/control/accessor/ControlValueAccessorBase.ts +187 -0
  388. package/src/control/accessor/FormControlStatus.ts +36 -0
  389. package/src/control/accessor/ValidControlValue.ts +1 -0
  390. package/src/control/accessor/index.ts +4 -0
  391. package/src/control/index.ts +4 -0
  392. package/src/index.ts +5 -0
  393. package/src/storage/ArchivistFormGroupStorage.ts +21 -0
  394. package/src/storage/FormGroupStorage.ts +8 -0
  395. package/src/storage/index.ts +2 -0
  396. package/src/stories/test.stories.tsx +20 -0
  397. package/src/types/images.d.ts +5 -0
  398. package/typedoc.json +5 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uBAAuB,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './ArchivistFormGroupStorage.js';
2
+ export * from './FormGroupStorage.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uBAAuB,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './ArchivistFormGroupStorage.js';
2
+ export * from './FormGroupStorage.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/storage/index.ts"],"names":[],"mappings":"AAAA,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uBAAuB,CAAA"}
package/package.json ADDED
@@ -0,0 +1,88 @@
1
+ {
2
+ "name": "@xyo-network/react-form-group",
3
+ "author": {
4
+ "email": "support@xyo.network",
5
+ "name": "XYO Development Team",
6
+ "url": "https://xyo.network"
7
+ },
8
+ "bugs": {
9
+ "email": "support@xyo.network",
10
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-react-js/issues"
11
+ },
12
+ "dependencies": {
13
+ "@mui/icons-material": "^5.16.1",
14
+ "@xylabs/forget": "^3.5.9",
15
+ "@xylabs/object": "^3.5.9",
16
+ "@xylabs/promise": "^3.5.9",
17
+ "@xyo-network/archivist-model": "^2.110.5",
18
+ "@xyo-network/module-abstract": "^2.110.5",
19
+ "@xyo-network/module-events": "^2.110.5",
20
+ "@xyo-network/payload-model": "^2.110.5",
21
+ "@xyo-network/react-shared": "^2.81.2"
22
+ },
23
+ "peerDependencies": {
24
+ "@mui/material": "^5",
25
+ "@mui/styles": "^5",
26
+ "react": "^18",
27
+ "react-dom": "^18"
28
+ },
29
+ "devDependencies": {
30
+ "@storybook/react": "^7.6.20",
31
+ "@xylabs/ts-scripts-yarn3": "^3.12.1",
32
+ "@xylabs/tsconfig-react": "^3.12.1",
33
+ "typescript": "^5.5.3"
34
+ },
35
+ "description": "Common React library for all XYO projects that use React",
36
+ "docs": "dist/docs.json",
37
+ "exports": {
38
+ ".": {
39
+ "node": {
40
+ "import": {
41
+ "types": "./dist/node/index.d.mts",
42
+ "default": "./dist/node/index.js"
43
+ },
44
+ "require": {
45
+ "types": "./dist/node/index.d.cts",
46
+ "default": "./dist/node/index.cjs"
47
+ }
48
+ },
49
+ "browser": {
50
+ "import": {
51
+ "types": "./dist/browser/index.d.mts",
52
+ "default": "./dist/browser/index.js"
53
+ },
54
+ "require": {
55
+ "types": "./dist/browser/index.d.cts",
56
+ "default": "./dist/browser/index.cjs"
57
+ }
58
+ },
59
+ "default": "./dist/browser/index.js"
60
+ },
61
+ "./package.json": "./package.json"
62
+ },
63
+ "main": "dist/browser/index.cjs",
64
+ "module": "dist/browser/index.js",
65
+ "homepage": "https://xyo.network",
66
+ "keywords": [
67
+ "xyo",
68
+ "utility",
69
+ "typescript",
70
+ "react"
71
+ ],
72
+ "license": "LGPL-3.0-only",
73
+ "publishConfig": {
74
+ "access": "public"
75
+ },
76
+ "repository": {
77
+ "type": "git",
78
+ "url": "https://github.com/XYOracleNetwork/sdk-xyo-react-js.git"
79
+ },
80
+ "scripts": {
81
+ "lint-pkg": "npmPkgJsonLint .",
82
+ "license": "yarn license-checker --exclude \"MIT, ISC, Apache-2.0, BSD, BSD-2-Clause, CC-BY-4.0, Unlicense, CC-BY-3.0, CC0-1.0\""
83
+ },
84
+ "sideEffects": false,
85
+ "types": "dist/browser/index.d.ts",
86
+ "version": "2.81.2",
87
+ "type": "module"
88
+ }
@@ -0,0 +1,226 @@
1
+ import { forget } from '@xylabs/forget'
2
+ import { EventListener } from '@xyo-network/module-events'
3
+ import { Payload } from '@xyo-network/payload-model'
4
+
5
+ import { AbstractControl, ControlValueAccessorBaseEvents } from './control/index.js'
6
+ import { ErrorSummary } from './InputError.js'
7
+ import { FormGroupStorage } from './storage/index.js'
8
+
9
+ export type PayloadWithTimestamp = Payload<{ timestamp?: number }>
10
+
11
+ export type KeyOfString<T> = keyof T extends string ? keyof T : never
12
+
13
+ type FormGroupErrors<TValue> = Record<KeyOfString<TValue>, string>
14
+
15
+ export type FormGroupParams<TStorageValue extends Payload = Payload> = {
16
+ serialize?: boolean
17
+ storage?: {
18
+ sensitive?: FormGroupStorage<TStorageValue>
19
+ storage?: FormGroupStorage<TStorageValue>
20
+ }
21
+ ttlStorage?: number
22
+ }
23
+
24
+ type ValueChangeEventListener = EventListener<ControlValueAccessorBaseEvents['valueChanged']>
25
+
26
+ /**
27
+ * Organize form controls in a group.
28
+ *
29
+ * NOTE: This is a work in progress and only supports top level controls. Nested controls are not supported.
30
+ */
31
+ export class FormGroup<
32
+ TValue extends PayloadWithTimestamp = PayloadWithTimestamp,
33
+ TStorageValue extends PayloadWithTimestamp = PayloadWithTimestamp,
34
+ > extends AbstractControl {
35
+ private _controls = {} as Record<KeyOfString<TValue>, AbstractControl>
36
+
37
+ private serializeListeners: Record<string, ValueChangeEventListener> = {}
38
+
39
+ private serializedSensitiveState = {} as Record<KeyOfString<TStorageValue>, string>
40
+ private serializedState = {} as Record<KeyOfString<TStorageValue>, string>
41
+
42
+ constructor(private fgParams?: FormGroupParams<TStorageValue>) {
43
+ super()
44
+ }
45
+
46
+ get errorSummary() {
47
+ const errorSummary: ErrorSummary = {
48
+ errorMessage: '',
49
+ invalidFields: [],
50
+ }
51
+ for (const [key, value] of Object.entries(this.errors)) {
52
+ if (value) {
53
+ errorSummary.errorMessage = `${errorSummary.errorMessage}, ${value}`
54
+ errorSummary.invalidFields.push(key)
55
+ }
56
+ }
57
+
58
+ return errorSummary
59
+ }
60
+
61
+ get errors(): FormGroupErrors<TValue> {
62
+ const value = {} as FormGroupErrors<TValue>
63
+ for (const key in this._controls) {
64
+ const castKey = key as KeyOfString<TValue>
65
+ value[castKey] = this._controls[castKey].error
66
+ }
67
+ return value
68
+ }
69
+
70
+ get nonSensitiveStorage() {
71
+ return this.fgParams?.storage?.storage
72
+ }
73
+
74
+ get sensitiveStorage() {
75
+ return this.fgParams?.storage?.sensitive
76
+ }
77
+
78
+ override get touched() {
79
+ return Object.values<AbstractControl>(this._controls).some((control) => control.touched)
80
+ }
81
+
82
+ override get valid() {
83
+ return Object.values<AbstractControl>(this._controls).every((control) => control.valid)
84
+ }
85
+
86
+ get values(): TValue {
87
+ const value = {} as TValue
88
+ for (const key in this._controls) {
89
+ const castKey = key as KeyOfString<TValue>
90
+ value[castKey] = this._controls[castKey].rawValue as TValue[KeyOfString<TValue>]
91
+ }
92
+ return value
93
+ }
94
+
95
+ getControl(name: string) {
96
+ return this._controls[name as KeyOfString<TValue>]
97
+ }
98
+
99
+ async getSerializedValue(name: string, sensitive = false): Promise<string | undefined> {
100
+ const storage = sensitive ? this.sensitiveStorage : this.nonSensitiveStorage
101
+ if (storage) {
102
+ if (!storage) {
103
+ console.warn(`Cannot return value for ${name}. No storage set`)
104
+ return
105
+ }
106
+
107
+ const savedState = await storage.get()
108
+ if (savedState && name in savedState) {
109
+ const savedValue = savedState[name as keyof typeof savedState] as string
110
+
111
+ // casting to PayloadWithTimestamp to check for timestamp
112
+ const savedStateWithTimestamp = savedState as unknown as PayloadWithTimestamp
113
+ if (savedStateWithTimestamp.timestamp && this.fgParams?.ttlStorage) {
114
+ const expirationDate = savedStateWithTimestamp.timestamp + (this.fgParams?.ttlStorage ?? 0)
115
+ const now = Date.now()
116
+ return now > expirationDate ? undefined : savedValue
117
+ }
118
+ return savedValue
119
+ }
120
+ }
121
+ }
122
+
123
+ registerControl(name: string, control: AbstractControl) {
124
+ if (this._controls[name as KeyOfString<TValue>]) console.error(`Replacing Control with name ${name} since it already exists!`)
125
+ this._controls[name as KeyOfString<TValue>] = control
126
+ this.serializeControlValue(name, control)
127
+ }
128
+
129
+ resetControls() {
130
+ for (const key in this._controls) {
131
+ this.unregisterControl(key)
132
+ }
133
+ }
134
+
135
+ resetValues() {
136
+ for (const control of Object.values<AbstractControl>(this._controls)) {
137
+ control.setValue('')
138
+ }
139
+ }
140
+
141
+ unregisterControl(name: string) {
142
+ const control = this._controls[name as KeyOfString<TValue>]
143
+
144
+ if (control) {
145
+ const listener = this.serializeListeners[name]
146
+ control.off('valueChanged', listener)
147
+ delete this.serializeListeners[name]
148
+ delete this._controls[name as KeyOfString<TValue>]
149
+ }
150
+ }
151
+
152
+ validateFields(requiredFields?: string[] | undefined) {
153
+ const castRequiredFields = requiredFields as KeyOfString<TValue>[]
154
+ for (const key in this._controls) {
155
+ const castKey = key as KeyOfString<TValue>
156
+ if (castRequiredFields === undefined || castRequiredFields.includes(castKey)) {
157
+ const control = this._controls[castKey]
158
+ control.validate()
159
+ }
160
+ }
161
+ }
162
+
163
+ private serializeControlValue(name: string, control: AbstractControl) {
164
+ const shouldSerialize = this.fgParams?.serialize
165
+ const sensitiveStorage = this.sensitiveStorage
166
+ const storage = this.nonSensitiveStorage
167
+
168
+ if (!shouldSerialize && (storage || sensitiveStorage)) console.warn('storage medium set but serialize is not enabled')
169
+
170
+ if (shouldSerialize && control.serializeSettings.serializable) {
171
+ this.setStateValueFromStorage(name, control)
172
+
173
+ const listener: ValueChangeEventListener = ({ value }) => {
174
+ // detect if control wants to be serialized
175
+ if (control.serializeSettings.serializable) {
176
+ // detect control's preferred storage
177
+ const targetStorage = control.serializeSettings.sensitive ? sensitiveStorage : storage
178
+
179
+ // detect control's preferred state
180
+ const targetState = control.serializeSettings.sensitive ? this.serializedSensitiveState : this.serializedState
181
+
182
+ // set the value
183
+ targetState[name as KeyOfString<TStorageValue>] = value ?? ''
184
+
185
+ // add a timestamp
186
+ const payloadWithTimestamp = targetState as PayloadWithTimestamp
187
+ payloadWithTimestamp.timestamp = Date.now()
188
+
189
+ // serialize the value
190
+ this.serializeValues(targetStorage, targetState as TStorageValue)
191
+ }
192
+ }
193
+
194
+ // listen for value changes
195
+ control.on('valueChanged', listener)
196
+
197
+ // store the listener for later removal
198
+ this.serializeListeners[name] = listener
199
+ }
200
+ }
201
+
202
+ private serializeValues(storage?: FormGroupStorage<TStorageValue>, values?: TStorageValue) {
203
+ if (storage && values) {
204
+ const write = async () => await storage.insert(values)
205
+ const clear = async () => await storage.clear()
206
+
207
+ forget(clear())
208
+ forget(write())
209
+ }
210
+ }
211
+
212
+ private setStateValueFromStorage(name: string, control: AbstractControl) {
213
+ const read = async () => {
214
+ const savedValue = await this.getSerializedValue(name, control.serializeSettings.sensitive)
215
+
216
+ if (savedValue) {
217
+ const targetState = control.serializeSettings.sensitive ? this.serializedSensitiveState : this.serializedState
218
+ targetState[name as KeyOfString<TStorageValue>] = savedValue
219
+
220
+ control.setValue(savedValue, { disableEmit: true })
221
+ }
222
+ }
223
+
224
+ forget(read())
225
+ }
226
+ }
@@ -0,0 +1,4 @@
1
+ export type ErrorSummary = {
2
+ errorMessage: string
3
+ invalidFields: string[]
4
+ }
@@ -0,0 +1,5 @@
1
+ import { createContextEx } from '@xyo-network/react-shared'
2
+
3
+ import { FormGroupContextWithPayloadState } from './State.js'
4
+
5
+ export const FormGroupBaseContext = createContextEx<FormGroupContextWithPayloadState>()
@@ -0,0 +1,25 @@
1
+ import { Payload } from '@xyo-network/payload-model'
2
+ import { PropsWithChildren, useMemo } from 'react'
3
+
4
+ import { FormGroup, FormGroupParams } from '../FormGroup.js'
5
+ import { FormGroupBaseContext } from './Context.js'
6
+
7
+ export interface FormGroupPayloadProviderProps<TStorage extends Payload = Payload> extends PropsWithChildren {
8
+ params?: FormGroupParams<TStorage>
9
+ }
10
+
11
+ /**
12
+ * Provides a FormGroup to child components.
13
+ */
14
+ export const FormGroupPayloadProvider = ({ children, params, ...props }: FormGroupPayloadProviderProps) => {
15
+ const formGroup = useMemo(() => {
16
+ const formGroup = new FormGroup<Payload, Payload>(params)
17
+ return formGroup
18
+ }, [params])
19
+
20
+ return (
21
+ <FormGroupBaseContext.Provider value={{ formGroup, provided: true }} {...props}>
22
+ {children}
23
+ </FormGroupBaseContext.Provider>
24
+ )
25
+ }
@@ -0,0 +1,8 @@
1
+ import { Payload } from '@xyo-network/payload-model'
2
+ import { ContextExState } from '@xyo-network/react-shared'
3
+
4
+ import { FormGroup } from '../FormGroup.js'
5
+
6
+ export interface FormGroupContextWithPayloadState<TValue extends Payload = Payload, TStorageValue extends Payload = Payload> extends ContextExState {
7
+ formGroup?: FormGroup<TValue, TStorageValue>
8
+ }
@@ -0,0 +1,4 @@
1
+ export * from './Context.js'
2
+ export * from './Provider.js'
3
+ export * from './State.js'
4
+ export * from './use.js'
@@ -0,0 +1,5 @@
1
+ import { useContextEx } from '@xyo-network/react-shared'
2
+
3
+ import { FormGroupBaseContext } from './Context.js'
4
+
5
+ export const useFormGroup = (required = false) => useContextEx(FormGroupBaseContext, 'FormGroup', required)
@@ -0,0 +1,125 @@
1
+ import { forget } from '@xylabs/forget'
2
+
3
+ import {
4
+ ControlValueAccessorBase,
5
+ ControlValueAccessorBaseEvents,
6
+ DISABLED,
7
+ FormControlStatus,
8
+ INVALID,
9
+ PENDING,
10
+ VALID,
11
+ ValidControlValue,
12
+ } from './accessor/index.js'
13
+
14
+ export type AbstractControlEvents<TValue> = ControlValueAccessorBaseEvents<TValue> & {
15
+ statusChanged: { status: FormControlStatus }
16
+ }
17
+
18
+ /**
19
+ * This is the base class for `Control` classes (i.e. FormControl),
20
+ *
21
+ * It provides some of the shared behavior that all controls and groups of controls have, like
22
+ * running validators, calculating status, and resetting state. It also defines the properties
23
+ * that are shared between all sub-classes, like `value`, `valid`, and `dirty`. It shouldn't be
24
+ * instantiated directly.
25
+ *
26
+ * NOTE: Heavily borrowed from Angular's AbstractControl:
27
+ * https://github.com/angular/angular/blob/5dcdbfcba934a930468aec140a7183b034466bdf/packages/forms/src/model/abstract_model.ts
28
+ */
29
+ export class AbstractControl<TValue extends ValidControlValue = ValidControlValue> extends ControlValueAccessorBase<
30
+ TValue,
31
+ AbstractControlEvents<TValue>
32
+ > {
33
+ private _status: FormControlStatus | undefined = undefined
34
+
35
+ constructor() {
36
+ super({})
37
+ }
38
+
39
+ /**
40
+ * A control is `disabled` when its `status` is `DISABLED`.
41
+ *
42
+ * Disabled controls are exempt from validation checks and
43
+ * are not included in the aggregate value of their ancestor
44
+ * controls.
45
+ *
46
+ * @returns True if the control is disabled, false otherwise.
47
+ */
48
+ /** @deprecated - disabled functionality not implemented */
49
+ get disabled(): boolean {
50
+ return this.status === DISABLED
51
+ }
52
+
53
+ /**
54
+ * A control is `enabled` as long as its `status` is not `DISABLED`.
55
+ *
56
+ * @returns True if the control has any status other than 'DISABLED',
57
+ * false if the status is 'DISABLED'.
58
+ */
59
+ get enabled(): boolean {
60
+ return this.status !== DISABLED
61
+ }
62
+
63
+ /**
64
+ * A control is `invalid` when its `status` is `INVALID`.
65
+
66
+ *
67
+ * @returns True if this control has failed one or more of its validation checks,
68
+ * false otherwise.
69
+ */
70
+ get invalid(): boolean {
71
+ return this.status === INVALID
72
+ }
73
+
74
+ /**
75
+ * A control is `pending` when its `status` is `PENDING`.
76
+ *
77
+ * @returns True if this control is in the process of conducting a validation check,
78
+ * false otherwise.
79
+ */
80
+ get pending(): boolean {
81
+ return this.status == PENDING
82
+ }
83
+
84
+ /**
85
+ * The raw value of the control.
86
+ */
87
+ get rawValue(): TValue {
88
+ return this.value
89
+ }
90
+
91
+ /**
92
+ * The current status of the control.
93
+ */
94
+ get status() {
95
+ return this._status
96
+ }
97
+
98
+ /**
99
+ * A control is `valid` when its `status` is `VALID`.
100
+ *
101
+ * @returns True if the control has passed all of its validation tests,
102
+ * false otherwise.
103
+ */
104
+ get valid(): boolean {
105
+ return this.status === VALID
106
+ }
107
+
108
+ setErrorAndValidity(error: string, status: FormControlStatus) {
109
+ this.setError(error)
110
+ this.setStatus(status)
111
+ }
112
+
113
+ setStatus(status: FormControlStatus) {
114
+ if (this._status === status) return
115
+
116
+ this._status = status
117
+
118
+ const emit = async () => await this.emit('statusChanged', { status })
119
+ forget(emit())
120
+ }
121
+
122
+ validate(): boolean {
123
+ return true
124
+ }
125
+ }
@@ -0,0 +1,31 @@
1
+ import { EmptyObject } from '@xylabs/object'
2
+
3
+ import { AbstractControl } from './AbstractControl.js'
4
+
5
+ export type CursorPosition = {
6
+ current: number | undefined
7
+ previous: number | undefined
8
+ }
9
+
10
+ export interface FormControlValidator {
11
+ blurError?: (value: string) => void
12
+ changeError?: (value: string) => void
13
+ // filter that supports an empty value
14
+ pattern?: RegExp
15
+ // filter that does not support an empty value
16
+ patternStrict?: RegExp
17
+ required?: boolean
18
+ }
19
+
20
+ export interface FormControlMask {
21
+ cursorPosition: CursorPosition
22
+ getCursorPosition?: () => number | undefined
23
+ mask?: (value: string) => string
24
+ onCursorChange?: (cursor: number | undefined) => void
25
+ unmask?: (value: string) => string
26
+ }
27
+
28
+ export interface FormControl<TProps extends EmptyObject = EmptyObject> extends FormControlValidator, FormControlMask, AbstractControl {
29
+ readonly name?: string
30
+ props: TProps
31
+ }
@@ -0,0 +1,82 @@
1
+ import { EmptyObject } from '@xylabs/object'
2
+
3
+ import { AbstractControl } from './AbstractControl.js'
4
+ import { SetOptions } from './accessor/index.js'
5
+ import { CursorPosition, FormControl } from './FormControl.js'
6
+
7
+ const AllowAllRegex = /^.*$/s
8
+
9
+ /**
10
+ * A base class for form controls and their validation.
11
+ */
12
+ export abstract class FormControlBase<TProps extends EmptyObject = EmptyObject> extends AbstractControl implements FormControl {
13
+ /**
14
+ * The current and previous cursor position of the input element.
15
+ */
16
+ cursorPosition: CursorPosition = { current: undefined, previous: undefined }
17
+ invalidMessage = 'Invalid input'
18
+ pattern = AllowAllRegex
19
+ patternStrict = AllowAllRegex
20
+ props = {} as TProps
21
+ required = false
22
+
23
+ private _name: string | undefined = undefined
24
+
25
+ constructor() {
26
+ super()
27
+ }
28
+
29
+ get name() {
30
+ return this._name
31
+ }
32
+
33
+ override get rawValue() {
34
+ return this.unmask && this.value ? this.unmask(this.value) : this.value
35
+ }
36
+
37
+ blurError?(value: string): void | undefined
38
+ changeError?(value: string): void
39
+ getCursorPosition?(): number | undefined
40
+ mask?(value: string): string
41
+ onCursorChange: (cursor: number | undefined) => void = () => {}
42
+
43
+ override setValue(value: string = '', setOptions: SetOptions) {
44
+ // check for pattern validation
45
+ if (this.unmask && this.pattern) {
46
+ const unmasked = this.unmask(value)
47
+ const match = unmasked.match(this.pattern)
48
+ // set the new value before checking for errors
49
+ super.setValue(this.mask ? this.mask(unmasked) : unmasked, setOptions)
50
+ if (match) {
51
+ // if the value matches the pattern, update the cursor position
52
+ if (this.getCursorPosition) {
53
+ const newCursor = this.getCursorPosition()
54
+ this.onCursorChange(newCursor)
55
+ }
56
+ } else {
57
+ // if no match, set the error and return to the previous value
58
+ this.setValue(this.previousValue, setOptions)
59
+ this.onCursorChange?.(this.cursorPosition.previous)
60
+ }
61
+ } else {
62
+ // if no mask or pattern, just set the value
63
+ super.setValue(value, setOptions)
64
+ }
65
+ // check for changeError validation after pattern validation
66
+ this.changeError?.(value)
67
+ }
68
+
69
+ unmask?(value: string): string
70
+
71
+ // For FormControls, validate is the same as running one of the error checking functions
72
+ override validate(): boolean {
73
+ const normalizedValue = this.value ?? ''
74
+ // prefer the blurError function since validation assumes the user is done typing
75
+ this.blurError ? this.blurError(normalizedValue) : this.changeError?.(normalizedValue)
76
+ return !this.error
77
+ }
78
+
79
+ protected setName(name: string | undefined) {
80
+ this._name = name
81
+ }
82
+ }
@@ -0,0 +1,23 @@
1
+ import { ValidControlValue } from './ValidControlValue.js'
2
+
3
+ export interface SetOptions {
4
+ disableEmit?: boolean
5
+ }
6
+
7
+ export interface ControlSerializeSettings {
8
+ sensitive?: boolean
9
+ serializable?: boolean
10
+ }
11
+
12
+ export interface ControlValueAccessor<T = ValidControlValue> {
13
+ readonly error: string
14
+ readonly previousValue: T
15
+ readonly serializeSettings: ControlSerializeSettings
16
+ readonly touched: boolean
17
+ readonly value: T
18
+ registerOnChange(fn: (value: T) => void): void
19
+ registerOnErrorChange(fn: (error: string) => void): void
20
+ registerOnTouched(fn: (isTouched: boolean) => void): void
21
+ setTouched(isTouched: boolean): void
22
+ setValue(fieldValue: T, options?: SetOptions): void
23
+ }