@sealcode/sealgen 0.18.10 → 0.19.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 (444) hide show
  1. package/.xunit +74 -69
  2. package/@types/add-crud.d.sync-conflict-20250918-184311-TFDLWFG.ts +1 -0
  3. package/@types/builders/colors-builder.d.sync-conflict-20250918-184323-TFDLWFG.ts +10 -0
  4. package/@types/builders/colors-builder.d.ts +1 -1
  5. package/@types/builders/fonts-builder.d.sync-conflict-20250918-184322-TFDLWFG.ts +7 -0
  6. package/@types/builders/fonts-builder.d.ts +1 -1
  7. package/@types/controllers/table-add-button.d.ts +6 -0
  8. package/@types/controllers/table-add-button.stimulus.d.ts +6 -0
  9. package/@types/crud-field-snippets.d.sync-conflict-20250918-184323-TFDLWFG.ts +1 -0
  10. package/@types/crud-field-snippets.d.ts +1 -3
  11. package/@types/forms/controls/array.d.sync-conflict-20250918-184306-TFDLWFG.ts +33 -0
  12. package/@types/forms/controls/array.d.ts +1 -3
  13. package/@types/forms/controls/array.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  14. package/@types/forms/controls/autocomplete.d.sync-conflict-20250918-222042-TFDLWFG.ts +22 -0
  15. package/@types/forms/controls/autocomplete.d.ts +1 -1
  16. package/@types/forms/controls/checkbox-group.d.sync-conflict-20250918-184319-TFDLWFG.ts +21 -0
  17. package/@types/forms/controls/checkbox-group.d.ts +3 -3
  18. package/@types/forms/controls/checkboxed-list-input.d.sync-conflict-20250918-184323-TFDLWFG.ts +21 -0
  19. package/@types/forms/controls/checkboxed-list-input.d.ts +3 -3
  20. package/@types/forms/controls/controls.d.ts +2 -2
  21. package/@types/forms/controls/derived-frame.d.sync-conflict-20250918-184314-TFDLWFG.ts +19 -0
  22. package/@types/forms/controls/derived-frame.d.ts +0 -2
  23. package/@types/forms/controls/dropdown.d.sync-conflict-20250918-222044-TFDLWFG.ts +30 -0
  24. package/@types/forms/controls/dropdown.d.ts +1 -1
  25. package/@types/forms/controls/file.d.sync-conflict-20250918-222045-TFDLWFG.ts +13 -0
  26. package/@types/forms/controls/file.d.ts +1 -2
  27. package/@types/forms/controls/form-control.d.sync-conflict-20250918-184322-TFDLWFG.ts +19 -0
  28. package/@types/forms/controls/form-control.d.sync-conflict-20250918-222046-TFDLWFG.ts +19 -0
  29. package/@types/forms/controls/form-control.d.ts +7 -4
  30. package/@types/forms/controls/image.d.ts +19 -0
  31. package/@types/forms/controls/image.test.d.ts +1 -0
  32. package/@types/forms/controls/multiple-files.d.sync-conflict-20250918-184318-TFDLWFG.ts +42 -0
  33. package/@types/forms/controls/multiple-files.d.ts +3 -1
  34. package/@types/forms/controls/multiple-images.d.ts +19 -0
  35. package/@types/forms/controls/number.d.sync-conflict-20250918-222046-TFDLWFG.ts +13 -0
  36. package/@types/forms/controls/number.d.ts +1 -1
  37. package/@types/forms/controls/photo.d.sync-conflict-20250918-184321-TFDLWFG.ts +19 -0
  38. package/@types/forms/controls/photo.d.ts +3 -5
  39. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-184310-TFDLWFG.ts +33 -0
  40. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-222042-TFDLWFG.ts +33 -0
  41. package/@types/forms/controls/simple-input.d.ts +5 -4
  42. package/@types/forms/controls/simple-input.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  43. package/@types/forms/controls/single-reference.d.ts +3 -2
  44. package/@types/forms/controls/table.d.sync-conflict-20250918-184302-TFDLWFG.ts +39 -0
  45. package/@types/forms/controls/table.d.ts +8 -3
  46. package/@types/forms/controls/table.sync-conflict-20250918-222042-TFDLWFG.d.ts +39 -0
  47. package/@types/forms/controls/textarea.d.sync-conflict-20250918-222045-TFDLWFG.ts +25 -0
  48. package/@types/forms/controls/textarea.d.ts +3 -3
  49. package/@types/forms/fields/boolean.d.sync-conflict-20250918-184325-TFDLWFG.ts +22 -0
  50. package/@types/forms/fields/boolean.d.ts +6 -1
  51. package/@types/forms/fields/boolean.sync-conflict-20250918-222042-TFDLWFG.d.ts +22 -0
  52. package/@types/forms/fields/checkboxed-list.d.sync-conflict-20250918-184325-TFDLWFG.ts +23 -0
  53. package/@types/forms/fields/checkboxed-list.d.ts +3 -1
  54. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-184319-TFDLWFG.ts +22 -0
  55. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-222047-TFDLWFG.ts +22 -0
  56. package/@types/forms/fields/collection-field.d.ts +8 -1
  57. package/@types/forms/fields/color.d.ts +4 -0
  58. package/@types/forms/fields/coordinates.d.sync-conflict-20250918-222044-TFDLWFG.ts +14 -0
  59. package/@types/forms/fields/coordinates.d.ts +14 -0
  60. package/@types/forms/fields/date.d.ts +13 -0
  61. package/@types/forms/fields/datetime.d.sync-conflict-20250918-222050-TFDLWFG.ts +4 -0
  62. package/@types/forms/fields/datetime.d.ts +14 -0
  63. package/@types/forms/fields/deep-reverse-single-reference-list.d.ts +20 -0
  64. package/@types/forms/fields/deep-reverse-single-reference-table.d.ts +16 -0
  65. package/@types/forms/fields/email.d.sync-conflict-20250918-184303-TFDLWFG.ts +8 -0
  66. package/@types/forms/fields/email.d.ts +3 -0
  67. package/@types/forms/fields/enum-multiple-sealious.d.ts +16 -0
  68. package/@types/forms/fields/enum-multiple-sealious.sync-conflict-20250918-222047-TFDLWFG.d.ts +16 -0
  69. package/@types/forms/fields/field.d.sync-conflict-20250918-184306-TFDLWFG.ts +70 -0
  70. package/@types/forms/fields/field.d.ts +37 -5
  71. package/@types/forms/fields/fields.d.sync-conflict-20250918-184314-TFDLWFG.ts +29 -0
  72. package/@types/forms/fields/fields.d.ts +23 -8
  73. package/@types/forms/fields/file.d.sync-conflict-20250918-184310-TFDLWFG.ts +23 -0
  74. package/@types/forms/fields/file.d.sync-conflict-20250918-222046-TFDLWFG.ts +23 -0
  75. package/@types/forms/fields/file.d.ts +11 -5
  76. package/@types/forms/fields/file.sync-conflict-20250918-222049-TFDLWFG.d.ts +23 -0
  77. package/@types/forms/fields/float.d.ts +4 -0
  78. package/@types/forms/fields/get-field-for-sealious.d.sync-conflict-20250918-222046-TFDLWFG.ts +29 -0
  79. package/@types/forms/fields/get-field-for-sealious.d.ts +31 -0
  80. package/@types/forms/fields/get-field-for-sealious.sync-conflict-20250918-222042-TFDLWFG.d.ts +29 -0
  81. package/@types/forms/fields/html.d.ts +6 -0
  82. package/@types/forms/fields/image.d.sync-conflict-20250918-222042-TFDLWFG.ts +5 -0
  83. package/@types/forms/fields/image.d.ts +5 -0
  84. package/@types/forms/fields/int.d.ts +6 -0
  85. package/@types/forms/fields/json.d.ts +13 -0
  86. package/@types/forms/fields/markdown.d.ts +6 -0
  87. package/@types/forms/fields/multiple-files.d.sync-conflict-20250918-184304-TFDLWFG.ts +16 -0
  88. package/@types/forms/fields/multiple-files.d.ts +3 -1
  89. package/@types/forms/fields/number.d.sync-conflict-20250918-184317-TFDLWFG.ts +25 -0
  90. package/@types/forms/fields/number.d.sync-conflict-20250918-222047-TFDLWFG.ts +25 -0
  91. package/@types/forms/fields/number.d.ts +3 -1
  92. package/@types/forms/fields/password.d.ts +5 -0
  93. package/@types/forms/fields/pick-from-list-sealious.d.ts +11 -0
  94. package/@types/forms/fields/pick-from-list.d.sync-conflict-20250918-184322-TFDLWFG.ts +15 -0
  95. package/@types/forms/fields/pick-from-list.d.ts +4 -3
  96. package/@types/forms/fields/proxy-field.d.sync-conflict-20250918-184307-TFDLWFG.ts +15 -0
  97. package/@types/forms/fields/proxy-field.d.ts +3 -1
  98. package/@types/forms/fields/regexp.d.sync-conflict-20250918-184305-TFDLWFG.ts +21 -0
  99. package/@types/forms/fields/regexp.d.sync-conflict-20250918-222045-TFDLWFG.ts +21 -0
  100. package/@types/forms/fields/regexp.d.ts +6 -1
  101. package/@types/forms/fields/regexp.sync-conflict-20250918-222047-TFDLWFG.d.ts +21 -0
  102. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-184309-TFDLWFG.ts +29 -0
  103. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-222044-TFDLWFG.ts +29 -0
  104. package/@types/forms/fields/simple-form-field.d.ts +23 -3
  105. package/@types/forms/fields/simple-form-field.sync-conflict-20250918-222049-TFDLWFG.d.ts +29 -0
  106. package/@types/forms/fields/single-reference.d.ts +19 -0
  107. package/@types/forms/fields/single-reference.sync-conflict-20250918-222043-TFDLWFG.d.ts +10 -0
  108. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-184302-TFDLWFG.ts +27 -0
  109. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-222049-TFDLWFG.ts +27 -0
  110. package/@types/forms/fields/structured-array.d.ts +19 -10
  111. package/@types/forms/fields/structured-array.sync-conflict-20250918-222047-TFDLWFG.d.ts +27 -0
  112. package/@types/forms/fields/table.d.sync-conflict-20250918-184303-TFDLWFG.ts +16 -0
  113. package/@types/forms/fields/table.d.ts +3 -0
  114. package/@types/forms/fields/text.d.ts +6 -0
  115. package/@types/forms/fields/url.d.ts +6 -0
  116. package/@types/forms/form-types.d.sync-conflict-20250918-222045-TFDLWFG.ts +26 -0
  117. package/@types/forms/form-types.d.ts +2 -0
  118. package/@types/forms/form.d.sync-conflict-20250918-184315-TFDLWFG.ts +32 -0
  119. package/@types/forms/form.d.sync-conflict-20250918-222049-TFDLWFG.ts +32 -0
  120. package/@types/forms/form.d.ts +10 -8
  121. package/@types/forms/form.sync-conflict-20250918-222049-TFDLWFG.d.ts +33 -0
  122. package/@types/forms/form.test.d.sync-conflict-20250918-184318-TFDLWFG.ts +6 -0
  123. package/@types/forms/form.test.d.sync-conflict-20250918-222047-TFDLWFG.ts +6 -0
  124. package/@types/forms/form.test.d.ts +2 -2
  125. package/@types/forms/multiform.d.sync-conflict-20250918-184308-TFDLWFG.ts +23 -0
  126. package/@types/forms/multiform.d.ts +1 -2
  127. package/@types/forms/multiform.sync-conflict-20250918-222044-TFDLWFG.d.ts +23 -0
  128. package/@types/index.d.sync-conflict-20250918-184316-TFDLWFG.ts +46 -0
  129. package/@types/index.d.ts +2 -2
  130. package/@types/mount.d.sync-conflict-20250918-184320-TFDLWFG.ts +6 -0
  131. package/@types/mount.d.ts +0 -1
  132. package/@types/page/list.d.sync-conflict-20250918-184318-TFDLWFG.ts +48 -0
  133. package/@types/page/list.d.sync-conflict-20250918-222046-TFDLWFG.ts +48 -0
  134. package/@types/page/list.d.ts +2 -2
  135. package/@types/page/list.sync-conflict-20250918-222048-TFDLWFG.d.ts +48 -0
  136. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-184321-TFDLWFG.ts +42 -0
  137. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-222046-TFDLWFG.ts +42 -0
  138. package/@types/page/mountable-with-fields.d.ts +3 -3
  139. package/@types/page/mountable-with-fields.sync-conflict-20250918-222044-TFDLWFG.d.ts +42 -0
  140. package/@types/page/mountable.d.sync-conflict-20250918-184306-TFDLWFG.ts +10 -0
  141. package/@types/page/mountable.d.ts +0 -1
  142. package/@types/page/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
  143. package/@types/page/page.d.ts +0 -1
  144. package/@types/page/props-parser.d.sync-conflict-20250918-184305-TFDLWFG.ts +15 -0
  145. package/@types/page/props-parser.d.ts +0 -1
  146. package/@types/page/stateful-page.d.sync-conflict-20250918-184326-TFDLWFG.ts +62 -0
  147. package/@types/page/stateful-page.d.ts +0 -1
  148. package/@types/register-external.d.ts +2 -2
  149. package/@types/templates/form.d.ts +1 -3
  150. package/@types/templates/jdd-component.d.ts +1 -1
  151. package/@types/templates/page.d.ts +1 -1
  152. package/@types/templates/shared/shared-crud-form-fields.d.sync-conflict-20250918-184306-TFDLWFG.ts +1 -0
  153. package/@types/templates/shared/shared-crud-form-fields.d.ts +1 -68
  154. package/@types/templates/templates.d.ts +1 -21
  155. package/@types/test_utils/test-on-real-app.d.sync-conflict-20250918-184320-TFDLWFG.ts +26 -0
  156. package/@types/test_utils/test-on-real-app.d.ts +0 -1
  157. package/@types/utils/extract-fields-from-collection.d.sync-conflict-20250918-184312-TFDLWFG.ts +18 -0
  158. package/@types/utils/extract-fields-from-collection.d.ts +5 -1
  159. package/@types/utils/extract-fields-from-collection.sync-conflict-20250918-222045-TFDLWFG.d.ts +18 -0
  160. package/@types/utils/wrap-attributes.d.ts +3 -0
  161. package/README.md +5 -0
  162. package/assets/file-icon.svg +5 -0
  163. package/eslint.config.mjs +56 -0
  164. package/lib/add-crud.js +77 -89
  165. package/lib/add-jdd-component.js +3 -3
  166. package/lib/add-list-route.test.js +1 -1
  167. package/lib/add-route.js +2 -9
  168. package/lib/build.js +6 -4
  169. package/lib/builders/backend-ts-builder.js +0 -1
  170. package/lib/builders/colors-builder.js +11 -8
  171. package/lib/builders/fonts-builder.js +0 -1
  172. package/lib/builders/frontend-ts-builder.js +0 -1
  173. package/lib/cli.js +4 -7
  174. package/lib/components/tabs.js +36 -36
  175. package/lib/controllers/table-add-button.stimulus.js +35 -0
  176. package/lib/esbuild-plugins/rewrite-asset-imports.js +7 -10
  177. package/lib/forms/controls/array.js +25 -22
  178. package/lib/forms/controls/big-radio-group.js +2 -2
  179. package/lib/forms/controls/checkbox-group.js +7 -7
  180. package/lib/forms/controls/checkboxed-list-input.js +7 -1
  181. package/lib/forms/controls/checkboxed-list-input.test.js +6 -6
  182. package/lib/forms/controls/controls.js +2 -2
  183. package/lib/forms/controls/derived-frame.js +8 -4
  184. package/lib/forms/controls/derived.js +1 -1
  185. package/lib/forms/controls/dropdown.js +5 -3
  186. package/lib/forms/controls/editable-collection-subset.js +2 -2
  187. package/lib/forms/controls/file.js +26 -2
  188. package/lib/forms/controls/file.test.js +2 -2
  189. package/lib/forms/controls/form-control.js +1 -1
  190. package/lib/forms/controls/hidden-input.js +4 -1
  191. package/lib/forms/controls/{photo.js → image.js} +6 -7
  192. package/lib/forms/controls/{photo.test.js → image.test.js} +8 -23
  193. package/lib/forms/controls/multiple-files.js +10 -1
  194. package/lib/forms/controls/{multiple-photos.js → multiple-images.js} +3 -3
  195. package/lib/forms/controls/simple-input.js +13 -12
  196. package/lib/forms/controls/single-reference.js +4 -0
  197. package/lib/forms/controls/single-reference.test.js +1 -1
  198. package/lib/forms/controls/table.js +62 -25
  199. package/lib/forms/controls/textarea.js +5 -3
  200. package/lib/forms/controls/tickable.js +13 -5
  201. package/lib/forms/fields/boolean.js +14 -0
  202. package/lib/forms/fields/checkboxed-list.js +4 -0
  203. package/lib/forms/fields/collection-field.js +9 -0
  204. package/lib/forms/fields/color.js +10 -0
  205. package/lib/forms/fields/coordinates.js +49 -0
  206. package/lib/forms/fields/date.js +34 -0
  207. package/lib/forms/fields/datetime.js +46 -0
  208. package/lib/forms/fields/deep-reverse-single-reference-list.js +81 -0
  209. package/lib/forms/fields/deep-reverse-single-reference-table.js +122 -0
  210. package/lib/forms/fields/email.js +7 -0
  211. package/lib/forms/fields/enum-multiple-sealious.js +32 -0
  212. package/lib/forms/fields/field.js +32 -4
  213. package/lib/forms/fields/field.test.js +8 -8
  214. package/lib/forms/fields/fields.js +23 -8
  215. package/lib/forms/fields/file.js +33 -9
  216. package/lib/forms/fields/file.test.js +5 -17
  217. package/lib/forms/fields/float.js +10 -0
  218. package/lib/forms/fields/get-field-for-sealious.js +213 -0
  219. package/lib/forms/fields/html.js +14 -0
  220. package/lib/forms/fields/image.js +13 -0
  221. package/lib/forms/fields/int.js +23 -0
  222. package/lib/forms/fields/json.js +31 -0
  223. package/lib/forms/fields/markdown.js +14 -0
  224. package/lib/forms/fields/multiple-files.js +4 -0
  225. package/lib/forms/fields/number.js +6 -0
  226. package/lib/forms/fields/password.js +13 -0
  227. package/lib/forms/fields/pick-from-list-sealious.js +17 -0
  228. package/lib/forms/fields/pick-from-list.js +6 -2
  229. package/lib/forms/fields/proxy-field.js +3 -0
  230. package/lib/forms/fields/regexp.js +14 -0
  231. package/lib/forms/fields/simple-form-field.js +61 -2
  232. package/lib/forms/fields/single-reference.js +44 -0
  233. package/lib/forms/fields/structured-array.js +61 -12
  234. package/lib/forms/fields/table.js +29 -2
  235. package/lib/forms/fields/text.js +17 -0
  236. package/lib/forms/fields/url.js +17 -0
  237. package/lib/forms/form.js +30 -14
  238. package/lib/forms/form.test.js +5 -7
  239. package/lib/forms/multiform.js +10 -9
  240. package/lib/forms/multiform.test.js +5 -5
  241. package/lib/generate-collections.js +2 -3
  242. package/lib/generate-components.js +2 -3
  243. package/lib/generate-routes.js +3 -5
  244. package/lib/generate-routes.test.js +7 -16
  245. package/lib/generate-stimulus.js +4 -4
  246. package/lib/get-fonts.js +29 -27
  247. package/lib/index.js +1 -0
  248. package/lib/make-env.js +1 -1
  249. package/lib/make-hidden-inputs.js +4 -4
  250. package/lib/mount.js +11 -1
  251. package/lib/notifier.js +3 -4
  252. package/lib/page/list.js +20 -15
  253. package/lib/page/mountable-with-fields.js +14 -6
  254. package/lib/page/mountable-with-fields.test.js +1 -1
  255. package/lib/page/mountable.js +0 -1
  256. package/lib/page/page.js +0 -1
  257. package/lib/register-external.js +4 -4
  258. package/lib/templates/form.js +9 -10
  259. package/lib/templates/jdd-component.js +1 -1
  260. package/lib/templates/jdd-editor.js +1 -1
  261. package/lib/templates/multiform.js +4 -4
  262. package/lib/templates/page.js +1 -3
  263. package/lib/templates/shared/collection-create-form.js +31 -44
  264. package/lib/templates/shared/collection-edit-form.js +43 -81
  265. package/lib/templates/shared/collection-list.js +13 -21
  266. package/lib/templates/shared/shared-crud-form-fields.js +28 -98
  267. package/lib/test_utils/exec_async.js +3 -3
  268. package/lib/test_utils/test-on-real-app.js +12 -14
  269. package/lib/utils/extract-fields-from-collection.js +60 -20
  270. package/lib/utils/make-slug.js +1 -1
  271. package/lib/utils/wrap-attributes.js +20 -0
  272. package/lib/utils/write-file.js +1 -1
  273. package/package.json +11 -9
  274. package/src/add-collection.ts +1 -3
  275. package/src/add-crud.ts +84 -100
  276. package/src/add-jdd-component.ts +4 -5
  277. package/src/add-list-route.test.ts +1 -1
  278. package/src/add-route.ts +3 -13
  279. package/src/build.ts +6 -4
  280. package/src/builders/backend-ts-builder.ts +0 -1
  281. package/src/builders/builder.ts +4 -1
  282. package/src/builders/colors-builder.ts +11 -9
  283. package/src/builders/css-builder.ts +4 -1
  284. package/src/builders/fonts-builder.ts +0 -1
  285. package/src/builders/frontend-ts-builder.ts +0 -1
  286. package/src/cli.ts +5 -7
  287. package/src/components/tabs.ts +38 -37
  288. package/src/components/toggle-modal.ts +1 -1
  289. package/src/controllers/table-add-button.stimulus.ts +35 -0
  290. package/src/esbuild-plugins/rewrite-asset-imports.ts +7 -10
  291. package/src/forms/controls/array.ts +35 -36
  292. package/src/forms/controls/autocomplete.ts +2 -2
  293. package/src/forms/controls/big-radio-group.ts +4 -4
  294. package/src/forms/controls/checkbox-group.ts +10 -10
  295. package/src/forms/controls/checkboxed-list-input.test.ts +6 -6
  296. package/src/forms/controls/checkboxed-list-input.ts +16 -8
  297. package/src/forms/controls/controls.ts +2 -2
  298. package/src/forms/controls/derived-frame.ts +16 -11
  299. package/src/forms/controls/derived.ts +7 -6
  300. package/src/forms/controls/dropdown.ts +13 -13
  301. package/src/forms/controls/editable-collection-subset.ts +4 -3
  302. package/src/forms/controls/field-group.ts +1 -1
  303. package/src/forms/controls/file.test.ts +4 -2
  304. package/src/forms/controls/file.ts +30 -7
  305. package/src/forms/controls/form-control.ts +8 -3
  306. package/src/forms/controls/hidden-input.ts +5 -1
  307. package/src/forms/controls/html.ts +1 -0
  308. package/src/forms/controls/{photo.test.ts → image.test.ts} +7 -24
  309. package/src/forms/controls/{photo.ts → image.ts} +4 -6
  310. package/src/forms/controls/multiple-files.ts +23 -8
  311. package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +2 -2
  312. package/src/forms/controls/number.ts +1 -1
  313. package/src/forms/controls/simple-input.ts +21 -33
  314. package/src/forms/controls/single-reference.test.ts +1 -1
  315. package/src/forms/controls/single-reference.ts +11 -3
  316. package/src/forms/controls/table.ts +87 -33
  317. package/src/forms/controls/textarea.ts +7 -5
  318. package/src/forms/controls/tickable.ts +13 -7
  319. package/src/forms/fields/boolean.ts +27 -2
  320. package/src/forms/fields/checkboxed-list.ts +11 -2
  321. package/src/forms/fields/collection-field.ts +21 -3
  322. package/src/forms/fields/color.ts +9 -0
  323. package/src/forms/fields/coordinates.ts +66 -0
  324. package/src/forms/fields/date.ts +50 -0
  325. package/src/forms/fields/datetime.ts +66 -0
  326. package/src/forms/fields/deep-reverse-single-reference-list.ts +130 -0
  327. package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
  328. package/src/forms/fields/email.ts +10 -1
  329. package/src/forms/fields/enum-multiple-sealious.ts +48 -0
  330. package/src/forms/fields/existing-sealious-value.ts +1 -1
  331. package/src/forms/fields/field.test.ts +8 -8
  332. package/src/forms/fields/field.ts +98 -11
  333. package/src/forms/fields/fields.ts +23 -8
  334. package/src/forms/fields/file.test.ts +5 -17
  335. package/src/forms/fields/file.ts +44 -16
  336. package/src/forms/fields/float.ts +9 -0
  337. package/src/forms/fields/get-field-for-sealious.ts +337 -0
  338. package/src/forms/fields/html.ts +15 -0
  339. package/src/forms/fields/image.ts +12 -0
  340. package/src/forms/fields/int.ts +25 -0
  341. package/src/forms/fields/json.ts +48 -0
  342. package/src/forms/fields/markdown.ts +15 -0
  343. package/src/forms/fields/multiple-files.ts +10 -1
  344. package/src/forms/fields/number.ts +10 -3
  345. package/src/forms/fields/password.ts +13 -0
  346. package/src/forms/fields/pick-from-list-sealious.ts +22 -0
  347. package/src/forms/fields/pick-from-list.ts +8 -4
  348. package/src/forms/fields/proxy-field.ts +7 -1
  349. package/src/forms/fields/regexp.ts +27 -1
  350. package/src/forms/fields/simple-form-field.ts +103 -7
  351. package/src/forms/fields/single-reference.ts +62 -0
  352. package/src/forms/fields/structured-array.ts +111 -18
  353. package/src/forms/fields/table.ts +39 -16
  354. package/src/forms/fields/text.ts +18 -0
  355. package/src/forms/fields/url.ts +20 -0
  356. package/src/forms/form-types.ts +5 -4
  357. package/src/forms/form.test.ts +5 -7
  358. package/src/forms/form.ts +42 -23
  359. package/src/forms/forms.css +0 -85
  360. package/src/forms/multiform.test.ts +9 -9
  361. package/src/forms/multiform.ts +12 -10
  362. package/src/generate-collections.ts +2 -3
  363. package/src/generate-components.ts +2 -3
  364. package/src/generate-routes.test.ts +7 -16
  365. package/src/generate-routes.ts +6 -10
  366. package/src/generate-stimulus.ts +4 -5
  367. package/src/get-fonts.ts +32 -30
  368. package/src/index.ts +2 -1
  369. package/src/make-env.ts +1 -1
  370. package/src/make-hidden-inputs.ts +8 -7
  371. package/src/mount.ts +16 -7
  372. package/src/notifier.ts +4 -7
  373. package/src/page/default-list-filters.ts +1 -0
  374. package/src/page/list.ts +33 -28
  375. package/src/page/mountable-with-fields.test.ts +1 -1
  376. package/src/page/mountable-with-fields.ts +21 -12
  377. package/src/page/mountable.ts +0 -1
  378. package/src/page/page.ts +2 -3
  379. package/src/page/props-parser.ts +1 -1
  380. package/src/page/sealious-list.ts +1 -1
  381. package/src/page/stateful-page.ts +6 -10
  382. package/src/register-external.ts +5 -5
  383. package/src/templates/form.ts +9 -11
  384. package/src/templates/jdd-component.ts +1 -1
  385. package/src/templates/jdd-editor.ts +2 -4
  386. package/src/templates/list.ts +0 -1
  387. package/src/templates/multiform.ts +4 -4
  388. package/src/templates/page.ts +1 -6
  389. package/src/templates/shared/collection-create-form.ts +34 -71
  390. package/src/templates/shared/collection-edit-form.ts +46 -108
  391. package/src/templates/shared/collection-list.ts +13 -21
  392. package/src/templates/shared/item-delete.ts +0 -1
  393. package/src/templates/shared/shared-crud-form-fields.ts +38 -177
  394. package/src/templates/templates.ts +5 -1
  395. package/src/test_utils/exec_async.ts +3 -4
  396. package/src/test_utils/test-on-real-app.ts +13 -14
  397. package/src/utils/browser-creator.js +0 -1
  398. package/src/utils/exec.ts +0 -1
  399. package/src/utils/extract-fields-from-collection.ts +76 -25
  400. package/src/utils/input-wrapper.ts +1 -1
  401. package/src/utils/make-slug.ts +1 -1
  402. package/src/utils/wrap-attributes.ts +17 -0
  403. package/src/utils/write-file.ts +1 -1
  404. package/.eslintrc.cjs +0 -39
  405. package/lib/add-verbose-crud.js +0 -119
  406. package/lib/crud-field-snippets.js +0 -52
  407. package/lib/find-css-includes.js +0 -3
  408. package/lib/forms/controls/reverse-single-reference.js +0 -1
  409. package/lib/forms/fields/enum-multiple.js +0 -47
  410. package/lib/forms/fields/enum-multiple.test.js +0 -27
  411. package/lib/forms/fields/enum.js +0 -41
  412. package/lib/forms/fields/enum.test.js +0 -21
  413. package/lib/forms/fields/reverse-single-reference.js +0 -17
  414. package/lib/templates/shared/handlers/boolean.js +0 -14
  415. package/lib/templates/shared/handlers/date.js +0 -8
  416. package/lib/templates/shared/handlers/deep-reverse-single-reference.js +0 -209
  417. package/lib/templates/shared/handlers/default.js +0 -49
  418. package/lib/templates/shared/handlers/enum.js +0 -19
  419. package/lib/templates/shared/handlers/file.js +0 -23
  420. package/lib/templates/shared/handlers/image.js +0 -32
  421. package/lib/templates/shared/handlers/int.js +0 -11
  422. package/lib/templates/shared/handlers/jdd.js +0 -10
  423. package/lib/templates/shared/handlers/single-reference.js +0 -12
  424. package/lib/templates/shared/handlers/structured-array.js +0 -33
  425. package/src/add-verbose-crud.ts +0 -138
  426. package/src/crud-field-snippets.ts +0 -57
  427. package/src/find-css-includes.ts +0 -3
  428. package/src/forms/controls/reverse-single-reference.ts +0 -50
  429. package/src/forms/fields/enum-multiple.test.ts +0 -31
  430. package/src/forms/fields/enum-multiple.ts +0 -62
  431. package/src/forms/fields/enum.test.ts +0 -25
  432. package/src/forms/fields/enum.ts +0 -56
  433. package/src/forms/fields/reverse-single-reference.ts +0 -20
  434. package/src/templates/shared/handlers/boolean.ts +0 -18
  435. package/src/templates/shared/handlers/date.ts +0 -12
  436. package/src/templates/shared/handlers/deep-reverse-single-reference.ts +0 -244
  437. package/src/templates/shared/handlers/default.ts +0 -64
  438. package/src/templates/shared/handlers/enum.ts +0 -23
  439. package/src/templates/shared/handlers/file.ts +0 -27
  440. package/src/templates/shared/handlers/image.ts +0 -45
  441. package/src/templates/shared/handlers/int.ts +0 -15
  442. package/src/templates/shared/handlers/jdd.ts +0 -14
  443. package/src/templates/shared/handlers/single-reference.ts +0 -16
  444. package/src/templates/shared/handlers/structured-array.ts +0 -42
@@ -0,0 +1,13 @@
1
+ import { TextBasedSimpleField } from "./simple-form-field.js";
2
+
3
+ export class Password<
4
+ Required extends boolean,
5
+ > extends TextBasedSimpleField<Required> {
6
+ constructor(required: Required) {
7
+ super(required, "password");
8
+ }
9
+
10
+ async sealiousValueToForm(): Promise<undefined> {
11
+ return undefined;
12
+ }
13
+ }
@@ -0,0 +1,22 @@
1
+ import { FieldTypes as SealiousFieldTypes } from "sealious";
2
+ import { PickFromListField } from "./pick-from-list.js";
3
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
4
+
5
+ export class PickFromListSealious<
6
+ Required extends boolean,
7
+ > extends PickFromListField<Required> {
8
+ constructor(public sealious_field: SealiousFieldTypes.Enum<string>) {
9
+ super(sealious_field.required as Required, async (ctx) =>
10
+ sealious_field
11
+ .getAllowedValues(ctx.$app)
12
+ .map((value) => ({ value, label: value }))
13
+ );
14
+ }
15
+
16
+ generateFieldDeclaration(
17
+ field_info: ExtractedFieldInfo,
18
+ vars: { form_field_types: string; sealious_field: string }
19
+ ): string {
20
+ return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
21
+ }
22
+ }
@@ -1,12 +1,12 @@
1
1
  import { is, predicates } from "@sealcode/ts-predicates";
2
2
  import { Context } from "koa";
3
- import type { DropdownOption } from "../controls/dropdown.js";
3
+ import { Dropdown, DropdownOption } from "../controls/dropdown.js";
4
4
  import { FormFieldValidationResponse } from "./field.js";
5
- import { SimpleFormField } from "./simple-form-field.js";
5
+ import { TextBasedSimpleField } from "./simple-form-field.js";
6
6
 
7
7
  export class PickFromListField<
8
- Required extends boolean
9
- > extends SimpleFormField<Required> {
8
+ Required extends boolean,
9
+ > extends TextBasedSimpleField<Required, Dropdown> {
10
10
  constructor(
11
11
  public required: Required,
12
12
  public generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
@@ -49,4 +49,8 @@ export class PickFromListField<
49
49
  public getEmptyValue(): string {
50
50
  return "";
51
51
  }
52
+
53
+ getControl(): Dropdown {
54
+ return new Dropdown(this);
55
+ }
52
56
  }
@@ -1,6 +1,8 @@
1
+ import { FormControl } from "../controls/form-control.js";
1
2
  import { FormField } from "./field.js";
2
3
 
3
- export class ProxyFormField<T> extends FormField<boolean, T> {
4
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
5
+ export class ProxyFormField<T> extends FormField<boolean, T, any> {
4
6
  constructor(
5
7
  required: boolean,
6
8
  public name: string,
@@ -21,4 +23,8 @@ export class ProxyFormField<T> extends FormField<boolean, T> {
21
23
  parsed_value: this.parsed_value,
22
24
  };
23
25
  }
26
+
27
+ getControl(): FormControl {
28
+ throw new Error("This field does not have a default control assigned");
29
+ }
24
30
  }
@@ -1,9 +1,16 @@
1
1
  import { is, predicates } from "@sealcode/ts-predicates";
2
2
  import { Context } from "koa";
3
+ import { SimpleInput } from "../controls/simple-input.js";
3
4
  import { FormDataValue } from "../form-types.js";
4
5
  import { FieldParseResult, FormField } from "./field.js";
6
+ import { FormControlContext } from "../controls/form-control.js";
5
7
 
6
- export class RegExpField<Required extends boolean> extends FormField<Required> {
8
+ export class RegExpField<Required extends boolean> extends FormField<
9
+ Required,
10
+ string,
11
+ SimpleInput,
12
+ string
13
+ > {
7
14
  constructor(
8
15
  required: Required,
9
16
  public regexp: RegExp,
@@ -50,4 +57,23 @@ export class RegExpField<Required extends boolean> extends FormField<Required> {
50
57
  public getEmptyValue(): string {
51
58
  return this.default_value || "";
52
59
  }
60
+
61
+ public getControl(): SimpleInput {
62
+ return new SimpleInput(this, { label: this.name });
63
+ }
64
+
65
+ async getSealiousCreateValue(fctx: FormControlContext): Promise<string> {
66
+ const { parsed } = await this.getParsedValue(
67
+ fctx.ctx,
68
+ fctx.data.raw_values
69
+ );
70
+ return parsed || "";
71
+ }
72
+
73
+ async sealiousValueToForm(
74
+ ctx: Context,
75
+ sealious_value: string | null
76
+ ): Promise<FormDataValue> {
77
+ return sealious_value || "";
78
+ }
53
79
  }
@@ -1,30 +1,126 @@
1
+ /* eslint @typescript-eslint/no-unused-vars: off */
1
2
  import { FormDataValue } from "../form-types.js";
2
3
  import { Context } from "koa";
3
4
  import { predicates } from "@sealcode/ts-predicates";
4
5
  import { FieldParseResult, FormField } from "./field.js";
6
+ import { SimpleInput } from "../controls/simple-input.js";
7
+ import { FormControl } from "../controls/controls.js";
8
+ import { CollectionItem } from "sealious";
9
+ import { FormControlContext } from "../controls/form-control.js";
5
10
 
6
- export class SimpleFormField<Required extends boolean> extends FormField<
7
- Required,
8
- string | null
9
- > {
11
+ export abstract class SimpleFormField<
12
+ Required extends boolean,
13
+ DefaultControl extends FormControl = SimpleInput,
14
+ Parsed = string,
15
+ > extends FormField<Required, Parsed, DefaultControl> {
16
+ predicate = predicates.string;
17
+
18
+ constructor(
19
+ required: Required,
20
+ public type: string = "text"
21
+ ) {
22
+ super(required);
23
+ }
24
+
25
+ async sealiousValueToForm(
26
+ _ctx: Context,
27
+ value: unknown
28
+ ): Promise<FormDataValue> {
29
+ if (value === null) {
30
+ return "";
31
+ }
32
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
33
+ return String(value) as FormDataValue;
34
+ }
35
+ }
36
+
37
+ export class TextBasedSimpleField<
38
+ Required extends boolean,
39
+ DefaultControl extends FormControl = SimpleInput,
40
+ > extends SimpleFormField<Required, DefaultControl, string | null> {
10
41
  async parse(
11
42
  _: Context,
12
43
  raw_value: FormDataValue
13
44
  ): Promise<FieldParseResult<string>> {
14
45
  return {
46
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
15
47
  parsed_value: (raw_value || "").toString(),
16
48
  parsable: true,
17
49
  error: null,
18
50
  };
19
51
  }
20
52
 
21
- predicate = predicates.string;
53
+ async getSealiousCreateValue(
54
+ fctx: FormControlContext
55
+ ): Promise<string | null> {
56
+ const { parsed } = await this.getParsedValue(
57
+ fctx.ctx,
58
+ fctx.data.raw_values
59
+ );
60
+ return parsed || "";
61
+ }
62
+
63
+ async postSealiousCreate(
64
+ ctx: Context,
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
66
+ created_item: CollectionItem<any>
67
+ ): Promise<void> {}
68
+
69
+ async postSealiousEdit(
70
+ ctx: Context,
71
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
72
+ edited_item: CollectionItem<any>
73
+ ): Promise<void> {}
74
+
75
+ getControl(): DefaultControl {
76
+ return new SimpleInput(this, {
77
+ label: this.name,
78
+ type: this.type,
79
+ }) as unknown as DefaultControl;
80
+ }
22
81
 
23
82
  public getEmptyValue(): string {
24
83
  return "";
25
84
  }
85
+ }
26
86
 
27
- constructor(required: Required) {
28
- super(required);
87
+ export class NumberBasedSimpleField<
88
+ Required extends boolean,
89
+ DefaultControl extends FormControl = SimpleInput,
90
+ > extends SimpleFormField<Required, DefaultControl, number> {
91
+ async parse(
92
+ _: Context,
93
+ raw_value: FormDataValue
94
+ ): Promise<FieldParseResult<number>> {
95
+ return {
96
+ parsed_value: parseFloat(raw_value as string) || 0,
97
+ parsable: true,
98
+ error: null,
99
+ };
100
+ }
101
+
102
+ async getSealiousCreateValue(
103
+ fctx: FormControlContext
104
+ ): Promise<number | undefined> {
105
+ const { parsed } = await this.getParsedValue(
106
+ fctx.ctx,
107
+ fctx.data.raw_values
108
+ );
109
+ return parsed || 0;
110
+ }
111
+
112
+ async postSealiousCreate(): Promise<void> {}
113
+
114
+ async postSealiousEdit(): Promise<void> {}
115
+
116
+ getControl(): DefaultControl {
117
+ return new SimpleInput(this, {
118
+ label: this.name,
119
+ type: this.type,
120
+ }) as unknown as DefaultControl;
121
+ }
122
+
123
+ public getEmptyValue(): number {
124
+ return 0;
29
125
  }
30
126
  }
@@ -0,0 +1,62 @@
1
+ import { Collection, FieldTypes as SealiousFieldTypes } from "sealious";
2
+ import { CollectionField } from "./collection-field.js";
3
+ import { SingleReferenceDropdown } from "../controls/single-reference.js";
4
+ import { FormControlContext } from "../controls/form-control.js";
5
+ import { Context } from "koa";
6
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
7
+ import { toPascalCase } from "js-convert-case";
8
+
9
+ export class SingleReference<
10
+ TargetCollection extends Collection,
11
+ Required extends boolean,
12
+ F extends SealiousFieldTypes.SingleReference,
13
+ > extends CollectionField<F, Required> {
14
+ getControl(): SingleReferenceDropdown<TargetCollection, F, Required> {
15
+ return new SingleReferenceDropdown(this, {
16
+ label: this.name,
17
+ getLabel: (item) => item.id,
18
+ });
19
+ }
20
+
21
+ async getSealiousCreateValue(
22
+ fctx: FormControlContext
23
+ ): Promise<string | undefined> {
24
+ const { parsed } = await this.getParsedValue(
25
+ fctx.ctx,
26
+ fctx.data.raw_values
27
+ );
28
+ return parsed || undefined;
29
+ }
30
+
31
+ async sealiousValueToForm(_ctx: Context, value: string | null) {
32
+ return value || undefined;
33
+ }
34
+
35
+ generateImportsForFieldList(field_info: ExtractedFieldInfo) {
36
+ if (!field_info.target) {
37
+ throw new Error("Expected 'target' attribute in field info");
38
+ }
39
+ return [
40
+ {
41
+ what: toPascalCase(field_info.target),
42
+ from: "src/back/collections/collections.js",
43
+ },
44
+ ];
45
+ }
46
+
47
+ generateFieldDeclaration(
48
+ field_info: ExtractedFieldInfo,
49
+ vars: { form_field_types: string; sealious_field: string }
50
+ ): string {
51
+ if (!field_info.target) {
52
+ throw new Error("Expected 'target' attribute in field info");
53
+ }
54
+ return `new ${vars.form_field_types}.${
55
+ this.constructor.name
56
+ }<typeof ${toPascalCase(field_info.target)}, ${String(
57
+ field_info.is_required
58
+ )}, typeof ${vars.sealious_field}>(${String(field_info.is_required)}, ${
59
+ vars.sealious_field
60
+ })`;
61
+ }
62
+ }
@@ -1,27 +1,120 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-return */
4
+ /* eslint-disable @typescript-eslint/no-unsafe-call */
5
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
1
6
  import { Context } from "koa";
2
- import { Field, FieldsetOutput, FieldTypes } from "sealious";
7
+ import {
8
+ Field as SealiousField,
9
+ FieldTypes as SealiousFieldTypes,
10
+ FieldsetInput,
11
+ } from "sealious";
3
12
  import { FormDataValue } from "../form-types.js";
4
- import { FormField } from "./field.js";
13
+ import { Table as TableControl } from "../controls/table.js";
14
+ import {
15
+ sealiousToFormField,
16
+ SealiousToFormField,
17
+ } from "./get-field-for-sealious.js";
18
+ import { FormControl, FormControlContext } from "../controls/form-control.js";
19
+ import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
20
+ import { Table } from "./table.js";
5
21
 
6
- export class StructuredArrayField<
7
- Fields extends Record<string, Field<unknown>>
8
- > extends FormField<
9
- true,
10
- FieldTypes.ArrayStorageInput<FieldsetOutput<Fields>>
11
- > {
12
- constructor(public sealious_field: FieldTypes.StructuredArray<Fields>) {
13
- super(true);
14
- }
22
+ export class StructuredArray<
23
+ SealiousFields extends Record<string, SealiousField<unknown>>,
24
+ > extends Table<{
25
+ [name in keyof SealiousFields]: SealiousToFormField<SealiousFields[name]>;
26
+ }> {
27
+ public sealious_field: SealiousFieldTypes.StructuredArray<SealiousFields>;
15
28
 
16
- async parse(_context: Context, value: FormDataValue) {
17
- return {
18
- parsable: <const>true,
19
- error: null,
20
- parsed_value: (value as FieldsetOutput<Fields>) || [],
29
+ constructor(
30
+ sealious_field: SealiousFieldTypes.StructuredArray<SealiousFields>
31
+ ) {
32
+ const columns = Object.fromEntries(
33
+ Object.entries(sealious_field.subfields).map(
34
+ ([key, sealious_field]) => [
35
+ key,
36
+ sealiousToFormField(sealious_field),
37
+ ]
38
+ )
39
+ ) as {
40
+ [name in keyof SealiousFields]: SealiousToFormField<
41
+ SealiousFields[name]
42
+ >;
21
43
  };
44
+ super(columns);
45
+ this.sealious_field = sealious_field;
46
+ }
47
+
48
+ getControl(): TableControl<{
49
+ [name in keyof SealiousFields]: SealiousToFormField<
50
+ SealiousFields[name]
51
+ >;
52
+ }> {
53
+ return new TableControl<{
54
+ [name in keyof SealiousFields]: SealiousToFormField<
55
+ SealiousFields[name]
56
+ >;
57
+ }>(this as any, {
58
+ label: this.name,
59
+ subfield_controls: Object.fromEntries(
60
+ Object.entries(this.columns).map(([column_name, subfield]) => [
61
+ column_name as keyof SealiousFields,
62
+ subfield.getControl(),
63
+ ])
64
+ ) as unknown as Record<keyof SealiousFields, FormControl>,
65
+ allow_adding: true,
66
+ make_new_row: () => ({}) as any,
67
+ });
68
+ }
69
+
70
+ generateFieldDeclaration(
71
+ _field_info: ExtractedFieldInfo,
72
+ vars: { form_field_types: string; sealious_field: string }
73
+ ): string {
74
+ return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
75
+ }
76
+
77
+ async getSealiousCreateValue(
78
+ fctx: FormControlContext
79
+ ): Promise<
80
+ SealiousFieldTypes.ArrayStorageInput<FieldsetInput<SealiousFields>>
81
+ > {
82
+ const { parsed } = await this.getParsedValue(
83
+ fctx.ctx,
84
+ fctx.data.raw_values
85
+ );
86
+ return (
87
+ (parsed as SealiousFieldTypes.ArrayStorageInput<
88
+ FieldsetInput<SealiousFields>
89
+ >) || this.getEmptyValue()
90
+ );
22
91
  }
23
92
 
24
- getEmptyValue() {
25
- return [] as FieldTypes.ArrayStorageInput<FieldsetOutput<Fields>>;
93
+ async sealiousValueToForm(
94
+ ctx: Context,
95
+ sealiousValue: Record<string, FormDataValue | null>[] | null
96
+ ): Promise<FormDataValue> {
97
+ return Promise.all(
98
+ (sealiousValue || []).map(async (element) =>
99
+ Object.fromEntries(
100
+ await Promise.all(
101
+ Object.entries(element).map(async ([key, value]) => {
102
+ const form_subfield = this.columns[key];
103
+ if (!form_subfield) {
104
+ return [key, ""];
105
+ }
106
+ return [
107
+ key,
108
+ await form_subfield.sealiousValueToForm(
109
+ ctx,
110
+ value,
111
+ {} as any
112
+ ),
113
+ ];
114
+ })
115
+ )
116
+ )
117
+ )
118
+ );
26
119
  }
27
120
  }
@@ -2,21 +2,18 @@ import { is, predicates } from "@sealcode/ts-predicates";
2
2
  import { Context } from "koa";
3
3
  import { FormDataValue } from "../form-types.js";
4
4
  import { FieldParseResult, FormField } from "./field.js";
5
+ import {
6
+ Table as TableControl,
7
+ TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER,
8
+ } from "../controls/table.js";
9
+ import { FormControl } from "../controls/form-control.js";
5
10
 
6
11
  export type ExtractFormFieldParsed<Field extends FormField> =
7
- Field extends FormField<
8
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
- true,
10
- infer T
11
- >
12
+ Field extends FormField<true, infer T>
12
13
  ? NonNullable<T>
13
- : Field extends FormField<
14
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
15
- true,
16
- infer T
17
- >
18
- ? T
19
- : never;
14
+ : Field extends FormField<true, infer T>
15
+ ? T
16
+ : never;
20
17
 
21
18
  export type TableFieldParsed<F extends Record<string, FormField>> = {
22
19
  [field_name in keyof F]: ExtractFormFieldParsed<F[field_name]>;
@@ -34,6 +31,16 @@ export class Table<F extends Record<string, FormField>> extends FormField<
34
31
  return [];
35
32
  }
36
33
 
34
+ setName(name: string) {
35
+ super.setName(name);
36
+ for (const [column_name, field] of Object.entries(this.columns)) {
37
+ field.setName(
38
+ `${this.name}[${TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER}][${column_name}]`
39
+ );
40
+ }
41
+ return this;
42
+ }
43
+
37
44
  async parse(
38
45
  ctx: Context,
39
46
  raw_value: FormDataValue
@@ -51,10 +58,10 @@ export class Table<F extends Record<string, FormField>> extends FormField<
51
58
  const row_data = raw_value[row_number];
52
59
  const parsed_row: Record<string, unknown> = {};
53
60
  if (!is(row_data, predicates.object)) {
54
- console.log("table.ts<fields>:55", this.name);
61
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
55
62
  throw new Error(`Expected object, got ${String(row_data)}`);
56
63
  }
57
- for (const key in row_data) {
64
+ for (const key of Object.keys(row_data)) {
58
65
  const field = this.columns[key];
59
66
  if (field == undefined) {
60
67
  return {
@@ -80,13 +87,29 @@ export class Table<F extends Record<string, FormField>> extends FormField<
80
87
  parsed_value: null,
81
88
  };
82
89
  }
83
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
90
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
84
91
  parsed_row[key] = parse_result.parsed_value as any;
85
92
  }
86
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
87
93
  result.push(parsed_row as { [field_name in keyof F]: unknown });
88
94
  }
89
95
  const ret = { parsed_value: result, parsable: true, error: null };
90
96
  return ret as FieldParseResult<TableFieldParsed<F>>;
91
97
  }
98
+
99
+ getControl(): TableControl<F> {
100
+ return new TableControl<F>(this, {
101
+ label: this.name,
102
+ subfield_controls: Object.fromEntries(
103
+ Object.entries(this.columns).map(([column_name, field]) => [
104
+ column_name as keyof F,
105
+ field.getControl(),
106
+ ])
107
+ ) as Record<keyof F, FormControl>,
108
+ allow_adding: true,
109
+ make_new_row: async () =>
110
+ Object.fromEntries(
111
+ Object.keys(this.columns).map((key) => [key, ""])
112
+ ) as Record<keyof F, string>,
113
+ });
114
+ }
92
115
  }
@@ -0,0 +1,18 @@
1
+ import { FormControlContext } from "../controls/form-control.js";
2
+ import { TextBasedSimpleField } from "./simple-form-field.js";
3
+
4
+ export class Text<
5
+ Required extends boolean,
6
+ > extends TextBasedSimpleField<Required> {
7
+ constructor(required: Required) {
8
+ super(required, "text");
9
+ }
10
+
11
+ async getSealiousCreateValue(fctx: FormControlContext): Promise<string> {
12
+ const { parsed } = await this.getParsedValue(
13
+ fctx.ctx,
14
+ fctx.data.raw_values
15
+ );
16
+ return parsed || this.getEmptyValue();
17
+ }
18
+ }
@@ -0,0 +1,20 @@
1
+ import { FormControlContext } from "../controls/form-control.js";
2
+ import { TextBasedSimpleField } from "./simple-form-field.js";
3
+
4
+ export class URLField<
5
+ Required extends boolean,
6
+ > extends TextBasedSimpleField<Required> {
7
+ constructor(required: Required) {
8
+ super(required, "text");
9
+ }
10
+
11
+ async getSealiousCreateValue(
12
+ fctx: FormControlContext
13
+ ): Promise<string | null> {
14
+ const { parsed } = await this.getParsedValue(
15
+ fctx.ctx,
16
+ fctx.data.raw_values
17
+ );
18
+ return parsed || null;
19
+ }
20
+ }
@@ -1,6 +1,7 @@
1
1
  import { FilePointer } from "@sealcode/file-manager";
2
2
  import type { FlatTemplatable } from "tempstream";
3
3
  import type { FormField } from "./fields/field.js";
4
+ import { FieldMessages } from "./controls/form-control.js";
4
5
 
5
6
  export type FormDataPrimitive =
6
7
  | string
@@ -13,12 +14,11 @@ export type FormDataValue =
13
14
  | FormDataPrimitive
14
15
  | Record<string, FormDataPrimitive>;
15
16
 
16
- export type FieldValueType<F extends FormField> = F extends FormField<infer R>
17
- ? R
18
- : never;
17
+ export type FieldValueType<F extends FormField> =
18
+ F extends FormField<infer R> ? R : never;
19
19
 
20
20
  export type FormFieldsToValues<
21
- F extends Record<string, FormField<boolean, keyof F>>
21
+ F extends Record<string, FormField<boolean, keyof F>>,
22
22
  > = {
23
23
  [Property in keyof F]: FieldValueType<F[Property]>;
24
24
  };
@@ -28,6 +28,7 @@ export type FormMessage = { type: "info" | "success" | "error"; text: string };
28
28
  export type FormData<Fieldnames extends string = string> = {
29
29
  raw_values: Record<Fieldnames, FormDataValue>;
30
30
  messages: FormMessage[];
31
+ field_messages: FieldMessages<Fieldnames>;
31
32
  };
32
33
 
33
34
  export type FormReaction =
@@ -9,11 +9,11 @@ import { getBrowser } from "../utils/browser-creator.js";
9
9
  import { assertThrowsAsync } from "../utils/utils.js";
10
10
  import { FormDataValue } from "./form-types.js";
11
11
  import getPort from "get-port";
12
- import { SimpleFormField } from "./fields/simple-form-field.js";
12
+ import { TextBasedSimpleField } from "./fields/simple-form-field.js";
13
13
  import { expect as PlaywritghtExpect } from "@playwright/test";
14
14
 
15
15
  const fields = {
16
- text: new Fields.SimpleFormField(true),
16
+ text: new Fields.TextBasedSimpleField(true),
17
17
  };
18
18
 
19
19
  export function form_factory(canAccessFun?: Mountable["canAccess"]): Form<typeof fields, void> {
@@ -36,7 +36,7 @@ export function form_factory(canAccessFun?: Mountable["canAccess"]): Form<typeof
36
36
  }
37
37
 
38
38
  const port = await getPort();
39
- console.log("Using port " + port + " for form.test.ts");
39
+ console.info("Using port " + port + " for form.test.ts");
40
40
 
41
41
  describe("form test", () => {
42
42
  let page: Page;
@@ -91,7 +91,6 @@ describe("form test", () => {
91
91
  },
92
92
  }
93
93
  );
94
- console.log(res_axios.data);
95
94
  if (!res_axios.data.includes("Some fields are invalid")) {
96
95
  throw new Error("when sending a empty request with axios, the error didnt appear");
97
96
  }
@@ -139,7 +138,6 @@ describe("form test", () => {
139
138
  async (
140
139
  ctx: Koa.Context
141
140
  ): Promise<{ canAccess: boolean; message: string }> => {
142
- console.log("CAN ACCESS? FALSE");
143
141
  return { canAccess: false, message: "" };
144
142
  }
145
143
  ),
@@ -349,7 +347,7 @@ describe("form test", () => {
349
347
  await page.getByPlaceholder("text").click();
350
348
  await page.getByPlaceholder("text").fill("yes@an.email");
351
349
  await page.getByRole("button", { name: "Submit" }).click();
352
- assertThrowsAsync(async () => {
350
+ await assertThrowsAsync(async () => {
353
351
  return page
354
352
  .getByText("Please enter a proper email address")
355
353
  .click({ timeout: 500 });
@@ -370,7 +368,7 @@ describe("form test", () => {
370
368
  const router = new Router();
371
369
 
372
370
  const fields = {
373
- title: new SimpleFormField(true),
371
+ title: new TextBasedSimpleField(true),
374
372
  };
375
373
 
376
374
  mount(