@sealcode/sealgen 0.18.10 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/.eslintrc.cjs +7 -2
  2. package/.xunit +74 -69
  3. package/@types/add-crud.d.sync-conflict-20250918-184311-TFDLWFG.ts +1 -0
  4. package/@types/builders/colors-builder.d.sync-conflict-20250918-184323-TFDLWFG.ts +10 -0
  5. package/@types/builders/colors-builder.d.ts +1 -1
  6. package/@types/builders/fonts-builder.d.sync-conflict-20250918-184322-TFDLWFG.ts +7 -0
  7. package/@types/builders/fonts-builder.d.ts +1 -1
  8. package/@types/controllers/table-add-button.d.ts +6 -0
  9. package/@types/controllers/table-add-button.stimulus.d.ts +6 -0
  10. package/@types/crud-field-snippets.d.sync-conflict-20250918-184323-TFDLWFG.ts +1 -0
  11. package/@types/crud-field-snippets.d.ts +1 -3
  12. package/@types/forms/controls/array.d.sync-conflict-20250918-184306-TFDLWFG.ts +33 -0
  13. package/@types/forms/controls/array.d.ts +1 -3
  14. package/@types/forms/controls/array.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  15. package/@types/forms/controls/autocomplete.d.sync-conflict-20250918-222042-TFDLWFG.ts +22 -0
  16. package/@types/forms/controls/autocomplete.d.ts +1 -1
  17. package/@types/forms/controls/checkbox-group.d.sync-conflict-20250918-184319-TFDLWFG.ts +21 -0
  18. package/@types/forms/controls/checkbox-group.d.ts +3 -3
  19. package/@types/forms/controls/checkboxed-list-input.d.sync-conflict-20250918-184323-TFDLWFG.ts +21 -0
  20. package/@types/forms/controls/checkboxed-list-input.d.ts +3 -3
  21. package/@types/forms/controls/controls.d.ts +2 -2
  22. package/@types/forms/controls/derived-frame.d.sync-conflict-20250918-184314-TFDLWFG.ts +19 -0
  23. package/@types/forms/controls/derived-frame.d.ts +0 -2
  24. package/@types/forms/controls/dropdown.d.sync-conflict-20250918-222044-TFDLWFG.ts +30 -0
  25. package/@types/forms/controls/dropdown.d.ts +1 -1
  26. package/@types/forms/controls/file.d.sync-conflict-20250918-222045-TFDLWFG.ts +13 -0
  27. package/@types/forms/controls/file.d.ts +1 -2
  28. package/@types/forms/controls/form-control.d.sync-conflict-20250918-184322-TFDLWFG.ts +19 -0
  29. package/@types/forms/controls/form-control.d.sync-conflict-20250918-222046-TFDLWFG.ts +19 -0
  30. package/@types/forms/controls/form-control.d.ts +7 -4
  31. package/@types/forms/controls/image.d.ts +19 -0
  32. package/@types/forms/controls/image.test.d.ts +1 -0
  33. package/@types/forms/controls/multiple-files.d.sync-conflict-20250918-184318-TFDLWFG.ts +42 -0
  34. package/@types/forms/controls/multiple-files.d.ts +3 -1
  35. package/@types/forms/controls/multiple-images.d.ts +19 -0
  36. package/@types/forms/controls/number.d.sync-conflict-20250918-222046-TFDLWFG.ts +13 -0
  37. package/@types/forms/controls/number.d.ts +1 -1
  38. package/@types/forms/controls/photo.d.sync-conflict-20250918-184321-TFDLWFG.ts +19 -0
  39. package/@types/forms/controls/photo.d.ts +3 -5
  40. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-184310-TFDLWFG.ts +33 -0
  41. package/@types/forms/controls/simple-input.d.sync-conflict-20250918-222042-TFDLWFG.ts +33 -0
  42. package/@types/forms/controls/simple-input.d.ts +5 -4
  43. package/@types/forms/controls/simple-input.sync-conflict-20250918-222045-TFDLWFG.d.ts +33 -0
  44. package/@types/forms/controls/single-reference.d.ts +3 -2
  45. package/@types/forms/controls/table.d.sync-conflict-20250918-184302-TFDLWFG.ts +39 -0
  46. package/@types/forms/controls/table.d.ts +8 -3
  47. package/@types/forms/controls/table.sync-conflict-20250918-222042-TFDLWFG.d.ts +39 -0
  48. package/@types/forms/controls/textarea.d.sync-conflict-20250918-222045-TFDLWFG.ts +25 -0
  49. package/@types/forms/controls/textarea.d.ts +3 -3
  50. package/@types/forms/fields/boolean.d.sync-conflict-20250918-184325-TFDLWFG.ts +22 -0
  51. package/@types/forms/fields/boolean.d.ts +6 -1
  52. package/@types/forms/fields/boolean.sync-conflict-20250918-222042-TFDLWFG.d.ts +22 -0
  53. package/@types/forms/fields/checkboxed-list.d.sync-conflict-20250918-184325-TFDLWFG.ts +23 -0
  54. package/@types/forms/fields/checkboxed-list.d.ts +3 -1
  55. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-184319-TFDLWFG.ts +22 -0
  56. package/@types/forms/fields/collection-field.d.sync-conflict-20250918-222047-TFDLWFG.ts +22 -0
  57. package/@types/forms/fields/collection-field.d.ts +8 -1
  58. package/@types/forms/fields/color.d.ts +4 -0
  59. package/@types/forms/fields/coordinates.d.sync-conflict-20250918-222044-TFDLWFG.ts +14 -0
  60. package/@types/forms/fields/coordinates.d.ts +14 -0
  61. package/@types/forms/fields/date.d.ts +13 -0
  62. package/@types/forms/fields/datetime.d.sync-conflict-20250918-222050-TFDLWFG.ts +4 -0
  63. package/@types/forms/fields/datetime.d.ts +14 -0
  64. package/@types/forms/fields/deep-reverse-single-reference-list.d.ts +24 -0
  65. package/@types/forms/fields/deep-reverse-single-reference-table.d.ts +16 -0
  66. package/@types/forms/fields/email.d.sync-conflict-20250918-184303-TFDLWFG.ts +8 -0
  67. package/@types/forms/fields/email.d.ts +3 -0
  68. package/@types/forms/fields/enum-multiple-sealious.d.ts +16 -0
  69. package/@types/forms/fields/enum-multiple-sealious.sync-conflict-20250918-222047-TFDLWFG.d.ts +16 -0
  70. package/@types/forms/fields/field.d.sync-conflict-20250918-184306-TFDLWFG.ts +70 -0
  71. package/@types/forms/fields/field.d.ts +37 -5
  72. package/@types/forms/fields/fields.d.sync-conflict-20250918-184314-TFDLWFG.ts +29 -0
  73. package/@types/forms/fields/fields.d.ts +23 -8
  74. package/@types/forms/fields/file.d.sync-conflict-20250918-184310-TFDLWFG.ts +23 -0
  75. package/@types/forms/fields/file.d.sync-conflict-20250918-222046-TFDLWFG.ts +23 -0
  76. package/@types/forms/fields/file.d.ts +11 -5
  77. package/@types/forms/fields/file.sync-conflict-20250918-222049-TFDLWFG.d.ts +23 -0
  78. package/@types/forms/fields/float.d.ts +4 -0
  79. package/@types/forms/fields/get-field-for-sealious.d.sync-conflict-20250918-222046-TFDLWFG.ts +29 -0
  80. package/@types/forms/fields/get-field-for-sealious.d.ts +31 -0
  81. package/@types/forms/fields/get-field-for-sealious.sync-conflict-20250918-222042-TFDLWFG.d.ts +29 -0
  82. package/@types/forms/fields/html.d.ts +6 -0
  83. package/@types/forms/fields/image.d.sync-conflict-20250918-222042-TFDLWFG.ts +5 -0
  84. package/@types/forms/fields/image.d.ts +5 -0
  85. package/@types/forms/fields/int.d.ts +6 -0
  86. package/@types/forms/fields/json.d.ts +13 -0
  87. package/@types/forms/fields/markdown.d.ts +6 -0
  88. package/@types/forms/fields/multiple-files.d.sync-conflict-20250918-184304-TFDLWFG.ts +16 -0
  89. package/@types/forms/fields/multiple-files.d.ts +3 -1
  90. package/@types/forms/fields/number.d.sync-conflict-20250918-184317-TFDLWFG.ts +25 -0
  91. package/@types/forms/fields/number.d.sync-conflict-20250918-222047-TFDLWFG.ts +25 -0
  92. package/@types/forms/fields/number.d.ts +3 -1
  93. package/@types/forms/fields/password.d.ts +6 -0
  94. package/@types/forms/fields/pick-from-list-sealious.d.ts +11 -0
  95. package/@types/forms/fields/pick-from-list.d.sync-conflict-20250918-184322-TFDLWFG.ts +15 -0
  96. package/@types/forms/fields/pick-from-list.d.ts +4 -3
  97. package/@types/forms/fields/proxy-field.d.sync-conflict-20250918-184307-TFDLWFG.ts +15 -0
  98. package/@types/forms/fields/proxy-field.d.ts +3 -1
  99. package/@types/forms/fields/regexp.d.sync-conflict-20250918-184305-TFDLWFG.ts +21 -0
  100. package/@types/forms/fields/regexp.d.sync-conflict-20250918-222045-TFDLWFG.ts +21 -0
  101. package/@types/forms/fields/regexp.d.ts +6 -1
  102. package/@types/forms/fields/regexp.sync-conflict-20250918-222047-TFDLWFG.d.ts +21 -0
  103. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-184309-TFDLWFG.ts +29 -0
  104. package/@types/forms/fields/simple-form-field.d.sync-conflict-20250918-222044-TFDLWFG.ts +29 -0
  105. package/@types/forms/fields/simple-form-field.d.ts +23 -3
  106. package/@types/forms/fields/simple-form-field.sync-conflict-20250918-222049-TFDLWFG.d.ts +29 -0
  107. package/@types/forms/fields/single-reference.d.ts +19 -0
  108. package/@types/forms/fields/single-reference.sync-conflict-20250918-222043-TFDLWFG.d.ts +10 -0
  109. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-184302-TFDLWFG.ts +27 -0
  110. package/@types/forms/fields/structured-array.d.sync-conflict-20250918-222049-TFDLWFG.ts +27 -0
  111. package/@types/forms/fields/structured-array.d.ts +19 -10
  112. package/@types/forms/fields/structured-array.sync-conflict-20250918-222047-TFDLWFG.d.ts +27 -0
  113. package/@types/forms/fields/table.d.sync-conflict-20250918-184303-TFDLWFG.ts +16 -0
  114. package/@types/forms/fields/table.d.ts +3 -0
  115. package/@types/forms/fields/text.d.ts +6 -0
  116. package/@types/forms/fields/url.d.ts +6 -0
  117. package/@types/forms/form-types.d.sync-conflict-20250918-222045-TFDLWFG.ts +26 -0
  118. package/@types/forms/form-types.d.ts +2 -0
  119. package/@types/forms/form.d.sync-conflict-20250918-184315-TFDLWFG.ts +32 -0
  120. package/@types/forms/form.d.sync-conflict-20250918-222049-TFDLWFG.ts +32 -0
  121. package/@types/forms/form.d.ts +10 -8
  122. package/@types/forms/form.sync-conflict-20250918-222049-TFDLWFG.d.ts +33 -0
  123. package/@types/forms/form.test.d.sync-conflict-20250918-184318-TFDLWFG.ts +6 -0
  124. package/@types/forms/form.test.d.sync-conflict-20250918-222047-TFDLWFG.ts +6 -0
  125. package/@types/forms/form.test.d.ts +2 -2
  126. package/@types/forms/multiform.d.sync-conflict-20250918-184308-TFDLWFG.ts +23 -0
  127. package/@types/forms/multiform.d.ts +1 -2
  128. package/@types/forms/multiform.sync-conflict-20250918-222044-TFDLWFG.d.ts +23 -0
  129. package/@types/index.d.sync-conflict-20250918-184316-TFDLWFG.ts +46 -0
  130. package/@types/index.d.ts +2 -2
  131. package/@types/mount.d.sync-conflict-20250918-184320-TFDLWFG.ts +6 -0
  132. package/@types/mount.d.ts +0 -1
  133. package/@types/page/list.d.sync-conflict-20250918-184318-TFDLWFG.ts +48 -0
  134. package/@types/page/list.d.sync-conflict-20250918-222046-TFDLWFG.ts +48 -0
  135. package/@types/page/list.d.ts +2 -2
  136. package/@types/page/list.sync-conflict-20250918-222048-TFDLWFG.d.ts +48 -0
  137. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-184321-TFDLWFG.ts +42 -0
  138. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-222046-TFDLWFG.ts +42 -0
  139. package/@types/page/mountable-with-fields.d.ts +3 -3
  140. package/@types/page/mountable-with-fields.sync-conflict-20250918-222044-TFDLWFG.d.ts +42 -0
  141. package/@types/page/mountable.d.sync-conflict-20250918-184306-TFDLWFG.ts +10 -0
  142. package/@types/page/mountable.d.ts +0 -1
  143. package/@types/page/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
  144. package/@types/page/page.d.ts +0 -1
  145. package/@types/page/props-parser.d.sync-conflict-20250918-184305-TFDLWFG.ts +15 -0
  146. package/@types/page/props-parser.d.ts +0 -1
  147. package/@types/page/stateful-page.d.sync-conflict-20250918-184326-TFDLWFG.ts +62 -0
  148. package/@types/page/stateful-page.d.ts +0 -1
  149. package/@types/templates/shared/shared-crud-form-fields.d.sync-conflict-20250918-184306-TFDLWFG.ts +1 -0
  150. package/@types/templates/shared/shared-crud-form-fields.d.ts +0 -67
  151. package/@types/test_utils/test-on-real-app.d.sync-conflict-20250918-184320-TFDLWFG.ts +26 -0
  152. package/@types/test_utils/test-on-real-app.d.ts +0 -1
  153. package/@types/utils/extract-fields-from-collection.d.sync-conflict-20250918-184312-TFDLWFG.ts +18 -0
  154. package/@types/utils/extract-fields-from-collection.d.ts +5 -1
  155. package/@types/utils/extract-fields-from-collection.sync-conflict-20250918-222045-TFDLWFG.d.ts +18 -0
  156. package/@types/utils/wrap-attributes.d.ts +3 -0
  157. package/README.md +5 -0
  158. package/assets/file-icon.svg +5 -0
  159. package/lib/add-crud.js +80 -89
  160. package/lib/add-list-route.test.js +1 -1
  161. package/lib/add-route.js +0 -7
  162. package/lib/build.js +3 -1
  163. package/lib/cli.js +2 -5
  164. package/lib/controllers/table-add-button.stimulus.js +35 -0
  165. package/lib/forms/controls/array.js +20 -16
  166. package/lib/forms/controls/big-radio-group.js +2 -2
  167. package/lib/forms/controls/checkbox-group.js +7 -7
  168. package/lib/forms/controls/checkboxed-list-input.js +9 -2
  169. package/lib/forms/controls/controls.js +2 -2
  170. package/lib/forms/controls/derived-frame.js +5 -1
  171. package/lib/forms/controls/derived.js +1 -1
  172. package/lib/forms/controls/dropdown.js +4 -1
  173. package/lib/forms/controls/editable-collection-subset.js +2 -2
  174. package/lib/forms/controls/file.js +26 -2
  175. package/lib/forms/controls/file.test.js +2 -2
  176. package/lib/forms/controls/hidden-input.js +4 -1
  177. package/lib/forms/controls/{photo.js → image.js} +6 -7
  178. package/lib/forms/controls/{photo.test.js → image.test.js} +6 -21
  179. package/lib/forms/controls/multiple-files.js +10 -1
  180. package/lib/forms/controls/{multiple-photos.js → multiple-images.js} +3 -3
  181. package/lib/forms/controls/simple-input.js +13 -12
  182. package/lib/forms/controls/single-reference.js +4 -0
  183. package/lib/forms/controls/table.js +66 -24
  184. package/lib/forms/controls/textarea.js +4 -2
  185. package/lib/forms/controls/tickable.js +13 -5
  186. package/lib/forms/fields/boolean.js +14 -0
  187. package/lib/forms/fields/checkboxed-list.js +4 -0
  188. package/lib/forms/fields/collection-field.js +9 -0
  189. package/lib/forms/fields/color.js +10 -0
  190. package/lib/forms/fields/coordinates.js +49 -0
  191. package/lib/forms/fields/date.js +34 -0
  192. package/lib/forms/fields/datetime.js +46 -0
  193. package/lib/forms/fields/deep-reverse-single-reference-list.js +81 -0
  194. package/lib/forms/fields/deep-reverse-single-reference-table.js +122 -0
  195. package/lib/forms/fields/email.js +7 -0
  196. package/lib/forms/fields/enum-multiple-sealious.js +32 -0
  197. package/lib/forms/fields/field.js +32 -4
  198. package/lib/forms/fields/field.test.js +5 -5
  199. package/lib/forms/fields/fields.js +23 -8
  200. package/lib/forms/fields/file.js +33 -9
  201. package/lib/forms/fields/file.test.js +4 -16
  202. package/lib/forms/fields/float.js +10 -0
  203. package/lib/forms/fields/get-field-for-sealious.js +213 -0
  204. package/lib/forms/fields/html.js +14 -0
  205. package/lib/forms/fields/image.js +13 -0
  206. package/lib/forms/fields/int.js +23 -0
  207. package/lib/forms/fields/json.js +31 -0
  208. package/lib/forms/fields/markdown.js +14 -0
  209. package/lib/forms/fields/multiple-files.js +4 -0
  210. package/lib/forms/fields/number.js +6 -0
  211. package/lib/forms/fields/password.js +13 -0
  212. package/lib/forms/fields/pick-from-list-sealious.js +17 -0
  213. package/lib/forms/fields/pick-from-list.js +6 -2
  214. package/lib/forms/fields/proxy-field.js +3 -0
  215. package/lib/forms/fields/regexp.js +14 -0
  216. package/lib/forms/fields/simple-form-field.js +60 -2
  217. package/lib/forms/fields/single-reference.js +44 -0
  218. package/lib/forms/fields/structured-array.js +63 -12
  219. package/lib/forms/fields/table.js +28 -1
  220. package/lib/forms/fields/text.js +17 -0
  221. package/lib/forms/fields/url.js +17 -0
  222. package/lib/forms/form.js +30 -13
  223. package/lib/forms/form.test.js +3 -4
  224. package/lib/forms/multiform.js +4 -2
  225. package/lib/forms/multiform.test.js +3 -3
  226. package/lib/generate-stimulus.js +1 -0
  227. package/lib/index.js +1 -0
  228. package/lib/make-hidden-inputs.js +1 -1
  229. package/lib/mount.js +11 -0
  230. package/lib/notifier.js +0 -1
  231. package/lib/page/list.js +15 -8
  232. package/lib/page/mountable-with-fields.js +14 -6
  233. package/lib/page/mountable-with-fields.test.js +1 -1
  234. package/lib/templates/form.js +8 -9
  235. package/lib/templates/multiform.js +4 -4
  236. package/lib/templates/page.js +0 -2
  237. package/lib/templates/shared/collection-create-form.js +28 -40
  238. package/lib/templates/shared/collection-edit-form.js +40 -77
  239. package/lib/templates/shared/collection-list.js +12 -20
  240. package/lib/templates/shared/shared-crud-form-fields.js +27 -95
  241. package/lib/test_utils/test-on-real-app.js +3 -3
  242. package/lib/utils/extract-fields-from-collection.js +60 -20
  243. package/lib/utils/make-slug.js +1 -1
  244. package/lib/utils/wrap-attributes.js +20 -0
  245. package/package.json +4 -3
  246. package/src/add-crud.ts +86 -97
  247. package/src/add-list-route.test.ts +1 -1
  248. package/src/add-route.ts +0 -7
  249. package/src/build.ts +3 -1
  250. package/src/cli.ts +3 -5
  251. package/src/controllers/table-add-button.stimulus.ts +35 -0
  252. package/src/forms/controls/array.ts +23 -20
  253. package/src/forms/controls/autocomplete.ts +1 -1
  254. package/src/forms/controls/big-radio-group.ts +2 -2
  255. package/src/forms/controls/checkbox-group.ts +9 -9
  256. package/src/forms/controls/checkboxed-list-input.ts +27 -15
  257. package/src/forms/controls/controls.ts +2 -2
  258. package/src/forms/controls/derived-frame.ts +5 -1
  259. package/src/forms/controls/derived.ts +1 -1
  260. package/src/forms/controls/dropdown.ts +5 -2
  261. package/src/forms/controls/editable-collection-subset.ts +2 -2
  262. package/src/forms/controls/file.test.ts +4 -2
  263. package/src/forms/controls/file.ts +31 -5
  264. package/src/forms/controls/form-control.ts +7 -2
  265. package/src/forms/controls/hidden-input.ts +4 -1
  266. package/src/forms/controls/{photo.test.ts → image.test.ts} +5 -22
  267. package/src/forms/controls/{photo.ts → image.ts} +3 -5
  268. package/src/forms/controls/multiple-files.ts +18 -1
  269. package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +1 -1
  270. package/src/forms/controls/number.ts +1 -1
  271. package/src/forms/controls/simple-input.ts +18 -34
  272. package/src/forms/controls/single-reference.ts +10 -2
  273. package/src/forms/controls/table.ts +90 -31
  274. package/src/forms/controls/textarea.ts +6 -4
  275. package/src/forms/controls/tickable.ts +13 -5
  276. package/src/forms/fields/boolean.ts +23 -1
  277. package/src/forms/fields/checkboxed-list.ts +11 -2
  278. package/src/forms/fields/collection-field.ts +16 -1
  279. package/src/forms/fields/color.ts +9 -0
  280. package/src/forms/fields/coordinates.ts +66 -0
  281. package/src/forms/fields/date.ts +50 -0
  282. package/src/forms/fields/datetime.ts +66 -0
  283. package/src/forms/fields/deep-reverse-single-reference-list.ts +136 -0
  284. package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
  285. package/src/forms/fields/email.ts +9 -0
  286. package/src/forms/fields/enum-multiple-sealious.ts +48 -0
  287. package/src/forms/fields/field.test.ts +5 -5
  288. package/src/forms/fields/field.ts +94 -8
  289. package/src/forms/fields/fields.ts +23 -8
  290. package/src/forms/fields/file.test.ts +4 -16
  291. package/src/forms/fields/file.ts +43 -15
  292. package/src/forms/fields/float.ts +9 -0
  293. package/src/forms/fields/get-field-for-sealious.ts +304 -0
  294. package/src/forms/fields/html.ts +15 -0
  295. package/src/forms/fields/image.ts +12 -0
  296. package/src/forms/fields/int.ts +25 -0
  297. package/src/forms/fields/json.ts +48 -0
  298. package/src/forms/fields/markdown.ts +15 -0
  299. package/src/forms/fields/multiple-files.ts +10 -1
  300. package/src/forms/fields/number.ts +8 -1
  301. package/src/forms/fields/password.ts +17 -0
  302. package/src/forms/fields/pick-from-list-sealious.ts +22 -0
  303. package/src/forms/fields/pick-from-list.ts +7 -3
  304. package/src/forms/fields/proxy-field.ts +6 -1
  305. package/src/forms/fields/regexp.ts +27 -1
  306. package/src/forms/fields/simple-form-field.ts +95 -7
  307. package/src/forms/fields/single-reference.ts +62 -0
  308. package/src/forms/fields/structured-array.ts +115 -18
  309. package/src/forms/fields/table.ts +32 -1
  310. package/src/forms/fields/text.ts +18 -0
  311. package/src/forms/fields/url.ts +20 -0
  312. package/src/forms/form-types.ts +2 -0
  313. package/src/forms/form.test.ts +3 -4
  314. package/src/forms/form.ts +37 -16
  315. package/src/forms/forms.css +0 -85
  316. package/src/forms/multiform.test.ts +3 -3
  317. package/src/forms/multiform.ts +2 -0
  318. package/src/generate-stimulus.ts +1 -0
  319. package/src/index.ts +2 -1
  320. package/src/make-hidden-inputs.ts +1 -1
  321. package/src/mount.ts +14 -0
  322. package/src/notifier.ts +0 -1
  323. package/src/page/list.ts +15 -8
  324. package/src/page/mountable-with-fields.test.ts +1 -1
  325. package/src/page/mountable-with-fields.ts +18 -9
  326. package/src/register-external.ts +1 -1
  327. package/src/templates/form.ts +8 -9
  328. package/src/templates/multiform.ts +4 -4
  329. package/src/templates/page.ts +0 -2
  330. package/src/templates/shared/collection-create-form.ts +30 -66
  331. package/src/templates/shared/collection-edit-form.ts +41 -102
  332. package/src/templates/shared/collection-list.ts +12 -20
  333. package/src/templates/shared/item-delete.ts +0 -1
  334. package/src/templates/shared/shared-crud-form-fields.ts +37 -171
  335. package/src/test_utils/test-on-real-app.ts +4 -3
  336. package/src/utils/extract-fields-from-collection.ts +76 -25
  337. package/src/utils/make-slug.ts +1 -1
  338. package/src/utils/wrap-attributes.ts +17 -0
  339. package/lib/add-verbose-crud.js +0 -119
  340. package/lib/crud-field-snippets.js +0 -52
  341. package/lib/find-css-includes.js +0 -3
  342. package/lib/forms/controls/reverse-single-reference.js +0 -1
  343. package/lib/forms/fields/enum-multiple.js +0 -47
  344. package/lib/forms/fields/enum-multiple.test.js +0 -27
  345. package/lib/forms/fields/enum.js +0 -41
  346. package/lib/forms/fields/enum.test.js +0 -21
  347. package/lib/forms/fields/reverse-single-reference.js +0 -17
  348. package/lib/templates/shared/handlers/boolean.js +0 -14
  349. package/lib/templates/shared/handlers/date.js +0 -8
  350. package/lib/templates/shared/handlers/deep-reverse-single-reference.js +0 -209
  351. package/lib/templates/shared/handlers/default.js +0 -49
  352. package/lib/templates/shared/handlers/enum.js +0 -19
  353. package/lib/templates/shared/handlers/file.js +0 -23
  354. package/lib/templates/shared/handlers/image.js +0 -32
  355. package/lib/templates/shared/handlers/int.js +0 -11
  356. package/lib/templates/shared/handlers/jdd.js +0 -10
  357. package/lib/templates/shared/handlers/single-reference.js +0 -12
  358. package/lib/templates/shared/handlers/structured-array.js +0 -33
  359. package/src/add-verbose-crud.ts +0 -138
  360. package/src/crud-field-snippets.ts +0 -57
  361. package/src/find-css-includes.ts +0 -3
  362. package/src/forms/controls/reverse-single-reference.ts +0 -50
  363. package/src/forms/fields/enum-multiple.test.ts +0 -31
  364. package/src/forms/fields/enum-multiple.ts +0 -62
  365. package/src/forms/fields/enum.test.ts +0 -25
  366. package/src/forms/fields/enum.ts +0 -56
  367. package/src/forms/fields/reverse-single-reference.ts +0 -20
  368. package/src/templates/shared/handlers/boolean.ts +0 -18
  369. package/src/templates/shared/handlers/date.ts +0 -12
  370. package/src/templates/shared/handlers/deep-reverse-single-reference.ts +0 -244
  371. package/src/templates/shared/handlers/default.ts +0 -64
  372. package/src/templates/shared/handlers/enum.ts +0 -23
  373. package/src/templates/shared/handlers/file.ts +0 -27
  374. package/src/templates/shared/handlers/image.ts +0 -45
  375. package/src/templates/shared/handlers/int.ts +0 -15
  376. package/src/templates/shared/handlers/jdd.ts +0 -14
  377. package/src/templates/shared/handlers/single-reference.ts +0 -16
  378. package/src/templates/shared/handlers/structured-array.ts +0 -42
package/src/add-crud.ts CHANGED
@@ -1,19 +1,16 @@
1
1
  import _locreq from "locreq";
2
- import prompts from "prompts";
3
-
4
2
  import { escape_url_params } from "./utils/escape-url-params.js";
3
+ import prompts from "prompts";
5
4
  import { toKebabCase, toPascalCase } from "js-convert-case";
6
5
  import { listCollections } from "./utils/list-collections.js";
7
- import {
8
- makeDefaultDisplayFields,
9
- makeDefaultFilterFields,
10
- } from "./templates/shared/collection-list.js";
6
+ import { collectionListTemplate } from "./templates/shared/collection-list.js";
11
7
  import { writeFile } from "./utils/write-file.js";
12
- import { extractCollectionClassname } from "./generate-collections.js";
13
- import extract_fields_from_collection from "./utils/extract-fields-from-collection.js";
14
- import { getFieldHandler } from "./templates/shared/shared-crud-form-fields.js";
8
+ import { curryImportPath, importPath } from "./utils/import-path.js";
9
+ import { sharedCrudFormFields } from "./templates/shared/shared-crud-form-fields.js";
15
10
  import { generateRoutes } from "./generate-routes.js";
16
- import { formatWithPrettier } from "./utils/prettier.js";
11
+ import { createItemFormTemplate } from "./templates/shared/collection-create-form.js";
12
+ import { editItemFormTemplate } from "./templates/shared/collection-edit-form.js";
13
+ import { itemDeleteTemplate } from "./templates/shared/item-delete.js";
17
14
 
18
15
  export async function addCRUD(
19
16
  params: Partial<{ [key in "collection" | "url"]: string }>,
@@ -38,7 +35,7 @@ export async function addCRUD(
38
35
  type: "text",
39
36
  name: "url",
40
37
  message:
41
- "Enter a full absolute path for the new route (for example: /admin/users/): ",
38
+ "Enter a full absolute path for the new route (for example: /admin/users/:id/edit): ",
42
39
  validate: (s: string) =>
43
40
  s.trim()[0] == "/" ? true : "Should start with a '/'",
44
41
  initial: function (_, { collection }: { collection: string }) {
@@ -46,103 +43,95 @@ export async function addCRUD(
46
43
  },
47
44
  },
48
45
  ]);
49
-
50
46
  const collection_name = response.collection as string;
51
47
  const url = response.url as string;
48
+ const list_action_name = toPascalCase(collection_name) + "CRUDList";
49
+ const create_action_name = toPascalCase(collection_name) + "CRUDCreate";
50
+ const edit_action_name = toPascalCase(collection_name) + "CRUDEdit";
51
+ const delete_action_name = toPascalCase(collection_name) + "CRUDDelete";
52
52
 
53
53
  /* create the list endpoint */
54
54
  const list_path = target_locreq.resolve(
55
- `src/back/routes/${escape_url_params(url)}/index.page.ts`
55
+ `src/back/routes/${escape_url_params(url)}/index.list.tsx`
56
56
  );
57
- const [uppercase_collection, collection_fields] = await Promise.all([
58
- extractCollectionClassname(
59
- target_locreq.resolve(
60
- "src/back/collections/" + collection_name + ".ts"
61
- )
62
- ),
63
- extract_fields_from_collection(collection_name),
64
- ]);
65
-
66
- const field_handler_results = await Promise.all(
67
- collection_fields.map(async (field) => {
68
- return getFieldHandler(
69
- collection_name,
70
- field,
71
- (p) => p,
72
- "edit_fields"
73
- );
74
- })
57
+ const list_content = await collectionListTemplate(
58
+ collection_name,
59
+ list_action_name,
60
+ list_path,
61
+ {
62
+ post_import_js: `import { ${create_action_name}URL, ${edit_action_name}URL, ${delete_action_name}URL } from "${importPath(
63
+ list_path,
64
+ "src/back/routes/urls.ts"
65
+ )}";`,
66
+ post_header_html: `<a href={${create_action_name}URL}> Create </a>`,
67
+ render_item: (
68
+ collection_name: string
69
+ ) => ` async renderItem(ctx: Context, item: CollectionItem<typeof ${toPascalCase(
70
+ collection_name
71
+ )}>) {
72
+ return <tr>
73
+ {displayFields.map(({ field, format }) => {
74
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
75
+ const value = item.get(field as any);
76
+ return <td>{format ? format(value, item) : value}</td>;
77
+ })}
78
+ <td><div class="sealious-list__actions">
79
+ <a href={${edit_action_name}URL(item.id)}>Edit</a>
80
+ <a data-turbo-method="POST" data-turbo-confirm="Delete item?" href={${delete_action_name}URL(item.id)}>Delete</a>
81
+ </div>
82
+ </td>
83
+ </tr>;
84
+ }`,
85
+ }
75
86
  );
87
+ await writeFile(list_path, list_content);
76
88
 
77
- const list_content = `import { CRUD } from "@sealcode/crud-ui";
78
- import type { CollectionItem } from "sealious";
79
- import type { ListFilterRender } from "@sealcode/sealgen";
80
- import { Controls, DefaultListFilters, Fields } from "@sealcode/sealgen";
81
- import { ${toPascalCase(
82
- collection_name
83
- )} } from "src/back/collections/collections.js";
84
- import html from "src/back/html.js";
85
-
86
- export const actionName = "${toPascalCase(collection_name)}CRUD";
87
-
88
- const edit_fields = <const>
89
- {
90
- ${field_handler_results
91
- .filter(({ hide_field }) => !hide_field)
92
- .map(({ field }) => field)
93
- .filter((e) => e != "")
94
- .join(",\n")}
95
- };
96
-
97
-
98
- const edit_controls = [
99
- ${field_handler_results
100
- .filter(({ hide_control }) => !hide_control)
101
- .map(({ controls }) => controls)
102
- .filter((e) => e != "")
103
- .join(",\n")}
104
- ]
89
+ /* create the shared fields file */
90
+ const fields_path = target_locreq.resolve(
91
+ `src/back/routes/${escape_url_params(url)}/shared.ts`
92
+ );
93
+ const fields_content = await sharedCrudFormFields(
94
+ collection_name,
95
+ fields_path
96
+ );
97
+ await writeFile(fields_path, fields_content);
105
98
 
106
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
107
- const fields_for_display = [
108
- ${makeDefaultDisplayFields(collection_fields)}
109
- ] as {
110
- field: keyof (typeof ${toPascalCase(collection_name)})["fields"];
111
- label: string;
112
- format?: (value: unknown, item: CollectionItem<typeof ${toPascalCase(
113
- collection_name
114
- )}>) => string | Promise<string>;
115
- }[];
99
+ /* create the create endpoint */
100
+ const create_path = target_locreq.resolve(
101
+ `src/back/routes/${escape_url_params(url)}/create.form.ts`
102
+ );
103
+ const create_content = await createItemFormTemplate(
104
+ create_action_name,
105
+ create_path,
106
+ collection_name,
107
+ list_action_name
108
+ );
109
+ await writeFile(create_path, create_content);
116
110
 
117
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
118
- const fields_for_filters = [
119
- ${makeDefaultFilterFields(collection_fields)}
120
- ] as {
121
- field: keyof (typeof ${uppercase_collection})["fields"];
122
- render?: ListFilterRender;
123
- prepareValue?: (filter_value: unknown)=>unknown; // set this function to change what filter value is passed to Sealious
124
- }[];
111
+ /* create the edit endpoint */
112
+ const edit_path = target_locreq.resolve(
113
+ `src/back/routes/${escape_url_params(url)}/[id]/edit.form.ts`
114
+ );
115
+ const edit_content = await editItemFormTemplate(
116
+ edit_action_name,
117
+ edit_path,
118
+ collection_name,
119
+ list_action_name
120
+ );
121
+ await writeFile(edit_path, edit_content);
125
122
 
126
- export default new CRUD({
127
- collection: ${toPascalCase(collection_name)},
128
- nice_collection_name: "${toPascalCase(collection_name)}",
129
- fields_for_display,
130
- fields_for_filters,
131
- html,
132
- list_title: "${toPascalCase(collection_name)} list",
133
- edit_title: "Edit",
134
- edit_button_text: "Edit",
135
- delete_button_text: "Delete",
136
- back_to_list_button_text: "← Back to ${toPascalCase(collection_name)} list",
137
- edit_fields,
138
- edit_controls,
139
- form_value_to_sealious_value: {},
140
- sealious_value_to_form_value: {},
141
- post_edit: async () => {},
142
- post_create: async () => {},
143
- });
144
- `;
145
- await writeFile(list_path, await formatWithPrettier(list_content));
123
+ /* create the actual delete endpoint */
124
+ const delete_path = target_locreq.resolve(
125
+ `src/back/routes/${escape_url_params(url)}/[id]/delete.page.tsx`
126
+ );
127
+ const base_import_path = curryImportPath(delete_path);
128
+ const delete_content = await itemDeleteTemplate(
129
+ delete_action_name,
130
+ collection_name,
131
+ list_action_name,
132
+ base_import_path
133
+ );
134
+ await writeFile(delete_path, delete_content);
146
135
 
147
136
  await generateRoutes();
148
137
  }
@@ -4,7 +4,7 @@ import { RealAppTest } from "./test_utils/test-on-real-app.js";
4
4
  import { collectionTemplate } from "./templates/collection.js";
5
5
  import assert from "node:assert";
6
6
 
7
- describe("single-reference.test", () => {
7
+ describe("single-reference", () => {
8
8
  let page: Page;
9
9
  before(async () => {
10
10
  const browser = await getBrowser();
package/src/add-route.ts CHANGED
@@ -2,7 +2,6 @@ import { existsSync, promises as fs } from "fs";
2
2
  import _locreq from "locreq";
3
3
  import { resolve } from "path";
4
4
  import { generateRoutes } from "./generate-routes.js";
5
- import { testTemplate } from "./templates/route-test.js";
6
5
  import { escape_url_params } from "./utils/escape-url-params.js";
7
6
  import prompts from "prompts";
8
7
  import { Templates } from "./templates/templates.js";
@@ -81,12 +80,6 @@ export async function addRoute(
81
80
  }
82
81
  await fs.mkdir(resolve(file_path, "../"), { recursive: true });
83
82
  await fs.writeFile(file_path, await template(action, file_path));
84
- if (mode !== "lpr" && mode !== "jdd-editor") {
85
- await fs.writeFile(
86
- test_file_path,
87
- await testTemplate(action, file_path)
88
- );
89
- }
90
83
  // eslint-disable-next-line no-console
91
84
  console.log(`${file_path} created`);
92
85
  // eslint-disable-next-line no-console
package/src/build.ts CHANGED
@@ -94,7 +94,9 @@ async function build(watch: boolean): Promise<void> {
94
94
  ];
95
95
  await Promise.all(builders.map((b) => b.build()));
96
96
  if (watch) {
97
- const watcher = chokidar.watch("src", { ignoreInitial: true });
97
+ const watcher = chokidar.watch(["src", ...controller_dirs], {
98
+ ignoreInitial: true,
99
+ });
98
100
  const port = await get_notifier_port();
99
101
  const notifier = make_notifier(port, 8080); // TODO: parse the app config to get the actual port
100
102
  await write_notifier_config(watch, port);
package/src/cli.ts CHANGED
@@ -1,17 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  import yargs from "yargs/yargs";
3
3
  import { addCollection } from "./add-collection.js";
4
- import { addCRUD } from "./add-crud.js";
5
4
  import { addJDDComponent } from "./add-jdd-component.js";
6
5
  import { addRoute } from "./add-route.js";
7
- import { addVerboseCRUD } from "./add-verbose-crud.js";
6
+ import { addCRUD } from "./add-crud.js";
8
7
  import { buildProject } from "./build.js";
9
8
  import { generateCollections } from "./generate-collections.js";
10
9
  import { generateComponents } from "./generate-components.js";
11
10
  import { generateRoutes } from "./generate-routes.js";
12
11
  import { getFonts } from "./get-fonts.js";
13
12
  import { makeEnv } from "./make-env.js";
14
- import { crudFieldSnippets } from "./crud-field-snippets.js";
13
+
15
14
  import {
16
15
  registerExternalControllers,
17
16
  registerExternalStyles,
@@ -23,7 +22,6 @@ const actions: Record<
23
22
  > = {
24
23
  "add-collection": addCollection,
25
24
  "add-route": addRoute,
26
- "add-verbose-crud": addVerboseCRUD,
27
25
  "add-crud": addCRUD,
28
26
  "generate-collections": generateCollections,
29
27
  "generate-components": generateComponents,
@@ -40,7 +38,7 @@ const actions: Record<
40
38
  "make-env": makeEnv,
41
39
  "add-component": addJDDComponent,
42
40
  "get-fonts": getFonts,
43
- "crud-field-snippets": crudFieldSnippets,
41
+ // "crud-field-snippets": crudFieldSnippets,
44
42
  "register-external-controllers": registerExternalControllers,
45
43
  "register-external-styles": registerExternalStyles,
46
44
  };
@@ -0,0 +1,35 @@
1
+ /// <reference lib="dom" />
2
+ import { Controller } from "stimulus";
3
+
4
+ export default class extends Controller {
5
+ static targets = ["textarea"];
6
+ defaultRowsNumber = 20;
7
+
8
+ addRow() {
9
+ const template = this.element
10
+ .closest("turbo-frame")
11
+ ?.querySelector("template");
12
+ if (!template) {
13
+ throw new Error("Couldn't find template");
14
+ }
15
+ const tbody = this.element
16
+ .closest("turbo-frame")
17
+ ?.querySelector("tbody");
18
+ if (!tbody) {
19
+ throw new Error("tbody not found");
20
+ }
21
+
22
+ const orig_template = template.innerHTML;
23
+ const placeholder = this.element.getAttribute("data-table-placeholder");
24
+ if (!placeholder) {
25
+ throw new Error("Could find placeholder attribute");
26
+ }
27
+ template.innerHTML = orig_template.replaceAll(
28
+ placeholder,
29
+ String(tbody.querySelectorAll("tr").length)
30
+ );
31
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
32
+ tbody.appendChild((template.cloneNode(true) as any).content);
33
+ template.innerHTML = orig_template;
34
+ }
35
+ }
@@ -6,8 +6,8 @@ import qs from "qs";
6
6
  import { Field, FieldsetOutput } from "sealious";
7
7
  import { tempstream } from "tempstream";
8
8
  import { FormField } from "../fields/field.js";
9
- import { SimpleFormField } from "../fields/simple-form-field.js";
10
- import { StructuredArrayField } from "../fields/structured-array.js";
9
+ import { TextBasedSimpleField } from "../fields/simple-form-field.js";
10
+ import { StructuredArray as StructuredArrayField } from "../fields/structured-array.js";
11
11
  import { FormDataValue } from "../form-types.js";
12
12
  import { Derived } from "./derived.js";
13
13
  import { FormControl, FormControlContext } from "./form-control.js";
@@ -58,7 +58,7 @@ export class StructuredArray<
58
58
  }
59
59
 
60
60
  makeSubfield(_field_name: string): FormField {
61
- return new SimpleFormField(false);
61
+ return new TextBasedSimpleField(false);
62
62
  }
63
63
 
64
64
  async renderItemControl(
@@ -70,12 +70,12 @@ export class StructuredArray<
70
70
  ) {
71
71
  const fctx = {
72
72
  ctx,
73
- data: {},
73
+ data: { raw_values: {}, messages: [], field_messages: {} },
74
74
  messages: [],
75
75
  field_name_prefix: "",
76
76
  form_id,
77
77
  validate: false,
78
- };
78
+ } as FormControlContext;
79
79
  if (Array.isArray(control)) {
80
80
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
81
81
  const [constructor, field_name, params] = control;
@@ -86,9 +86,7 @@ export class StructuredArray<
86
86
  );
87
87
  return "";
88
88
  }
89
- await field.init(
90
- `${this.field.name}[data][${index}][${field_name}]`
91
- );
89
+ field.setName(`${this.field.name}[data][${index}][${field_name}]`);
92
90
  const hidden_shadow = new Derived(
93
91
  [field],
94
92
  async (
@@ -107,10 +105,22 @@ export class StructuredArray<
107
105
  );
108
106
  return tempstream`${new constructor(field, params).render({
109
107
  ...fctx,
110
- data: { [field.name]: item[field_name] as FormDataValue },
108
+ data: {
109
+ raw_values: {
110
+ [field.name]: item[field_name] as FormDataValue,
111
+ },
112
+ messages: [],
113
+ field_messages: {},
114
+ },
111
115
  })}${hidden_shadow.render({
112
116
  ...fctx,
113
- data: { [field.name]: item[field_name] as FormDataValue },
117
+ data: {
118
+ raw_values: {
119
+ [field.name]: item[field_name] as FormDataValue,
120
+ },
121
+ messages: [],
122
+ field_messages: {},
123
+ },
114
124
  form_id: this.getInnerFormID(),
115
125
  })}`;
116
126
  } else {
@@ -140,9 +150,8 @@ export class StructuredArray<
140
150
  }
141
151
 
142
152
  async getItems(ctx: Context, raw_values: Record<string, FormDataValue>) {
143
- return (await this.field.getValue(ctx, raw_values)).parsed as Promise<
144
- FieldsetOutput<Subfields>[]
145
- >;
153
+ return (await this.field.getParsedValue(ctx, raw_values))
154
+ .parsed as FieldsetOutput<Subfields>[];
146
155
  }
147
156
 
148
157
  async _render(
@@ -170,7 +179,7 @@ export class StructuredArray<
170
179
  }
171
180
 
172
181
  render(fctx: FormControlContext) {
173
- return this._render(fctx.ctx, fctx.form_id, fctx.data);
182
+ return this._render(fctx.ctx, fctx.form_id, fctx.data.raw_values);
174
183
  }
175
184
 
176
185
  async getTargetItemID(ctx: Context): Promise<string> {
@@ -179,7 +188,6 @@ export class StructuredArray<
179
188
  }
180
189
 
181
190
  mount(router: Router) {
182
- console.log("mounting!", this.getActionURL());
183
191
  router.post(this.getActionURL(), async (ctx) => {
184
192
  const form_id = ctx.query.form_id;
185
193
  if (typeof form_id != "string") {
@@ -198,7 +206,6 @@ export class StructuredArray<
198
206
  const field_data = (ctx.$body as Record<string, unknown>)[
199
207
  this.field.name
200
208
  ] || { data: [] };
201
- console.log({ action: field_data });
202
209
  if (
203
210
  !hasShape(
204
211
  {
@@ -215,10 +222,6 @@ export class StructuredArray<
215
222
  ...ctx.$body.action,
216
223
  data: field_data.data || [],
217
224
  });
218
- console.log("ACTION", {
219
- ...ctx.$body.action,
220
- data: field_data.data || [],
221
- });
222
225
  await item.save(ctx.$context);
223
226
  console.log(await item.getDecodedBody(ctx.$context, {}));
224
227
  ctx.body = this._render(
@@ -4,7 +4,7 @@ import { PickFromListField } from "../fields/pick-from-list.js";
4
4
  import { FormControlContext } from "./form-control.js";
5
5
  import { SimpleInput } from "./simple-input.js";
6
6
 
7
- export class Autocomplete extends SimpleInput<string | null> {
7
+ export class Autocomplete extends SimpleInput {
8
8
  constructor(
9
9
  public field: PickFromListField<boolean>,
10
10
  public options: { id?: string; label?: string; placeholder?: string }
@@ -19,9 +19,9 @@ export class BigRadioGroup extends FormFieldControl {
19
19
  }
20
20
 
21
21
  async render(fctx: FormControlContext): Promise<FlatTemplatable> {
22
- const { raw: current_value } = await this.field.getValue(
22
+ const { raw: current_value } = await this.field.getParsedValue(
23
23
  fctx.ctx,
24
- fctx.data
24
+ fctx.data.raw_values
25
25
  );
26
26
  return tempstream/* HTML */ `<div class="bigradios">
27
27
  ${Object.entries(this.options).map(([key, { description }]) => {
@@ -1,10 +1,10 @@
1
1
  import { FlatTemplatable } from "tempstream";
2
- import { EnumMultipleField } from "../fields/enum-multiple.js";
3
2
  import { ProxyFormField } from "../fields/proxy-field.js";
4
3
  import { CheckboxWithValue } from "./checkbox.js";
5
4
  import { FieldGroup } from "./field-group.js";
6
5
  import { FormControlContext } from "./form-control.js";
7
6
  import { FormFieldControl } from "./form-field-control.js";
7
+ import { CheckboxedListField } from "../fields/checkboxed-list.js";
8
8
 
9
9
  export type DefaultCheckboxOptions = {
10
10
  id?: string;
@@ -20,7 +20,7 @@ export class CheckboxGroup<
20
20
  Options extends DefaultCheckboxOptions = DefaultCheckboxOptions
21
21
  > extends FormFieldControl {
22
22
  constructor(
23
- public field: EnumMultipleField<readonly string[], boolean>,
23
+ public field: CheckboxedListField<boolean, string>,
24
24
  public options: Options = {} as Options
25
25
  ) {
26
26
  super([field]);
@@ -40,28 +40,28 @@ export class CheckboxGroup<
40
40
  }
41
41
 
42
42
  async render(fctx: FormControlContext): Promise<FlatTemplatable> {
43
- const { parsed: values } = await this.field.getValue(
43
+ const { parsed: values } = await this.field.getParsedValue(
44
44
  fctx.ctx,
45
- fctx.data
45
+ fctx.data.raw_values
46
46
  );
47
- const checkboxes = this.field.options.map(
47
+ const checkboxes = (await this.field.generateOptions(fctx.ctx)).map(
48
48
  (option) =>
49
49
  new CheckboxWithValue(
50
50
  new ProxyFormField(
51
51
  false,
52
52
  this.field.name,
53
53
  false,
54
- (values || []).includes(option)
54
+ Object.keys(values || {}).includes(option.value)
55
55
  ),
56
56
  {
57
- id: this.field.name + "__" + option,
57
+ id: this.field.name + "__" + option.value,
58
58
  label: (
59
59
  this.options.checkboxNameToLabel ||
60
60
  ((s: string) => s)
61
- )(option),
61
+ )(option.value),
62
62
  default_value: false,
63
63
  },
64
- option
64
+ option.value
65
65
  )
66
66
  );
67
67
  return this.wrapGroup(fctx, checkboxes);
@@ -7,9 +7,11 @@ import {
7
7
  import { FormControlContext } from "./form-control.js";
8
8
  import { FormFieldControl } from "./form-field-control.js";
9
9
 
10
- export class CheckboxedListInput extends FormFieldControl {
10
+ export class CheckboxedListInput<
11
+ Values extends string
12
+ > extends FormFieldControl {
11
13
  constructor(
12
- public field: CheckboxedListField<boolean>,
14
+ public field: CheckboxedListField<boolean, Values>,
13
15
  public options: { label: string } = { label: field.name }
14
16
  ) {
15
17
  super([field]);
@@ -30,7 +32,11 @@ export class CheckboxedListInput extends FormFieldControl {
30
32
  valid,
31
33
  message,
32
34
  parsed: currentValue,
33
- } = await this.field.getValue(fctx.ctx, fctx.data, true);
35
+ } = await this.field.getParsedValue(
36
+ fctx.ctx,
37
+ fctx.data.raw_values,
38
+ true
39
+ );
34
40
  const pickedValues = Object.entries(currentValue || {})
35
41
  .filter(([, is_on]) => is_on)
36
42
  .map(([key]) => key);
@@ -48,6 +54,7 @@ export class CheckboxedListInput extends FormFieldControl {
48
54
  if (!groups[option.group]) {
49
55
  groups[option.group] = [];
50
56
  }
57
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
51
58
  groups[option.group]!.push(option);
52
59
  }
53
60
  }
@@ -73,18 +80,22 @@ export class CheckboxedListInput extends FormFieldControl {
73
80
  tempstream/* HTML */ ` <h3>
74
81
  ${group_label}
75
82
  </h3>
76
- ${options!.map(({ value, label }) =>
77
- this.renderOption({
78
- name,
79
- value,
80
- label,
81
- form_id: fctx.form_id,
82
- checked:
83
- pickedValues.includes(
84
- value
85
- ),
86
- })
87
- )}`
83
+
84
+ ${
85
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
86
+ options!.map(({ value, label }) =>
87
+ this.renderOption({
88
+ name,
89
+ value,
90
+ label,
91
+ form_id: fctx.form_id,
92
+ checked:
93
+ pickedValues.includes(
94
+ value
95
+ ),
96
+ })
97
+ )
98
+ }`
88
99
  )
89
100
  : ""}
90
101
  ${isVisible
@@ -126,6 +137,7 @@ export class CheckboxedListInput extends FormFieldControl {
126
137
  name="${name}.${value}"
127
138
  ${checked ? "checked" : ""}
128
139
  form=${form_id}
140
+ autocomplete="off"
129
141
  />
130
142
  <label for="${name}.${value}">${label || value}</label>
131
143
  `
@@ -23,10 +23,10 @@ export * from "./collapsible-field-group.js";
23
23
  export * from "./collapsible-checkbox-group.js";
24
24
  export * from "./autocomplete.js";
25
25
  export * from "./file.js";
26
- export * from "./photo.js";
26
+ export * from "./image.js";
27
27
  export * from "./multiple-files.js";
28
28
  export * from "./number.js";
29
- export * from "./multiple-photos.js";
29
+ export * from "./multiple-images.js";
30
30
  // export * from "./reverse-single-reference";
31
31
  export * from "./array.js";
32
32
  export * from "./table.js";
@@ -76,7 +76,11 @@ export class DerivedFrame extends Derived<{
76
76
  await this.generateFrameContent(
77
77
  new FormControlContext(
78
78
  ctx,
79
- ctx.query,
79
+ {
80
+ messages: [],
81
+ field_messages: {},
82
+ raw_values: ctx.query,
83
+ },
80
84
  [],
81
85
  query.field_name_prefix,
82
86
  query.form_id,
@@ -27,7 +27,7 @@ export class Derived<
27
27
  ): Promise<Record<string, FormDataValue>> {
28
28
  const fieldnames = this.fields.map((f) => f.name);
29
29
  const result = Object.fromEntries(
30
- Object.entries(fctx.data).filter(([key]) =>
30
+ Object.entries(fctx.data.raw_values).filter(([key]) =>
31
31
  fieldnames.includes(key)
32
32
  )
33
33
  );
@@ -15,7 +15,7 @@ export type DropdownOptions = {
15
15
 
16
16
  export type DropdownOption = { value: string; label: string };
17
17
 
18
- export class FreeformDropdown extends SimpleInput<string | null> {
18
+ export class FreeformDropdown extends SimpleInput {
19
19
  constructor(
20
20
  public field: FormField<boolean, string | null>,
21
21
  public _generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
@@ -57,7 +57,10 @@ export class FreeformDropdown extends SimpleInput<string | null> {
57
57
  attributes_str: string,
58
58
  data: Record<string, FormDataValue>
59
59
  ): Promise<FlatTemplatable> {
60
- const { parsed: picked_value } = await this.field.getValue(ctx, data);
60
+ const { parsed: picked_value } = await this.field.getParsedValue(
61
+ ctx,
62
+ data
63
+ );
61
64
  return /* HTML */ tempstream`<select ${attributes_str}>
62
65
  ${
63
66
  // eslint-disable-next-line @typescript-eslint/restrict-template-expressions