@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/lib/add-crud.js CHANGED
@@ -1,18 +1,16 @@
1
1
  import _locreq from "locreq";
2
- import prompts from "prompts";
3
2
  import { escape_url_params } from "./utils/escape-url-params.js";
3
+ import prompts from "prompts";
4
4
  import { toKebabCase, toPascalCase } from "js-convert-case";
5
5
  import { listCollections } from "./utils/list-collections.js";
6
- import {
7
- makeDefaultDisplayFields,
8
- makeDefaultFilterFields
9
- } from "./templates/shared/collection-list.js";
6
+ import { collectionListTemplate } from "./templates/shared/collection-list.js";
10
7
  import { writeFile } from "./utils/write-file.js";
11
- import { extractCollectionClassname } from "./generate-collections.js";
12
- import extract_fields_from_collection from "./utils/extract-fields-from-collection.js";
13
- 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";
14
10
  import { generateRoutes } from "./generate-routes.js";
15
- 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";
16
14
  async function addCRUD(params, app_directory = process.cwd()) {
17
15
  const target_locreq = _locreq(app_directory);
18
16
  prompts.override(params);
@@ -29,7 +27,7 @@ async function addCRUD(params, app_directory = process.cwd()) {
29
27
  {
30
28
  type: "text",
31
29
  name: "url",
32
- message: "Enter a full absolute path for the new route (for example: /admin/users/): ",
30
+ message: "Enter a full absolute path for the new route (for example: /admin/users/:id/edit): ",
33
31
  validate: (s) => s.trim()[0] == "/" ? true : "Should start with a '/'",
34
32
  initial: function(_, { collection }) {
35
33
  return "/" + toKebabCase(collection);
@@ -38,88 +36,81 @@ async function addCRUD(params, app_directory = process.cwd()) {
38
36
  ]);
39
37
  const collection_name = response.collection;
40
38
  const url = response.url;
39
+ const list_action_name = toPascalCase(collection_name) + "CRUDList";
40
+ const create_action_name = toPascalCase(collection_name) + "CRUDCreate";
41
+ const edit_action_name = toPascalCase(collection_name) + "CRUDEdit";
42
+ const delete_action_name = toPascalCase(collection_name) + "CRUDDelete";
41
43
  const list_path = target_locreq.resolve(
42
- `src/back/routes/${escape_url_params(url)}/index.page.ts`
44
+ `src/back/routes/${escape_url_params(url)}/index.list.tsx`
43
45
  );
44
- const [uppercase_collection, collection_fields] = await Promise.all([
45
- extractCollectionClassname(
46
- target_locreq.resolve(
47
- "src/back/collections/" + collection_name + ".ts"
48
- )
49
- ),
50
- extract_fields_from_collection(collection_name)
51
- ]);
52
- const field_handler_results = await Promise.all(
53
- collection_fields.map(async (field) => {
54
- return getFieldHandler(
55
- collection_name,
56
- field,
57
- (p) => p,
58
- "edit_fields"
59
- );
60
- })
46
+ const list_content = await collectionListTemplate(
47
+ collection_name,
48
+ list_action_name,
49
+ list_path,
50
+ {
51
+ post_import_js: `import { ${create_action_name}URL, ${edit_action_name}URL, ${delete_action_name}URL } from "${importPath(
52
+ list_path,
53
+ "src/back/routes/urls.ts"
54
+ )}";`,
55
+ post_header_html: `<a href={${create_action_name}URL}> Create </a>`,
56
+ render_item: (collection_name2) => ` async renderItem(ctx: Context, item: CollectionItem<typeof ${toPascalCase(
57
+ collection_name2
58
+ )}>) {
59
+ return <tr>
60
+ {displayFields.map(({ field, format }) => {
61
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
62
+ const value = item.get(field as any);
63
+ return <td>{format ? format(value, item) : value}</td>;
64
+ })}
65
+ <td><div class="sealious-list__actions">
66
+ <a href={${edit_action_name}URL(item.id)}>Edit</a>
67
+ <a data-turbo-method="POST" data-turbo-confirm="Delete item?" href={${delete_action_name}URL(item.id)}>Delete</a>
68
+ </div>
69
+ </td>
70
+ </tr>;
71
+ }`
72
+ }
61
73
  );
62
- const list_content = `import { CRUD } from "@sealcode/crud-ui";
63
- import type { CollectionItem } from "sealious";
64
- import type { ListFilterRender } from "@sealcode/sealgen";
65
- import { Controls, DefaultListFilters, Fields } from "@sealcode/sealgen";
66
- import { ${toPascalCase(
67
- collection_name
68
- )} } from "src/back/collections/collections.js";
69
- import html from "src/back/html.js";
70
-
71
- export const actionName = "${toPascalCase(collection_name)}CRUD";
72
-
73
- const edit_fields = <const>
74
- {
75
- ${field_handler_results.filter(({ hide_field }) => !hide_field).map(({ field }) => field).filter((e) => e != "").join(",\n")}
76
- };
77
-
78
-
79
- const edit_controls = [
80
- ${field_handler_results.filter(({ hide_control }) => !hide_control).map(({ controls }) => controls).filter((e) => e != "").join(",\n")}
81
- ]
82
-
83
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
84
- const fields_for_display = [
85
- ${makeDefaultDisplayFields(collection_fields)}
86
- ] as {
87
- field: keyof (typeof ${toPascalCase(collection_name)})["fields"];
88
- label: string;
89
- format?: (value: unknown, item: CollectionItem<typeof ${toPascalCase(
90
- collection_name
91
- )}>) => string | Promise<string>;
92
- }[];
93
-
94
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
95
- const fields_for_filters = [
96
- ${makeDefaultFilterFields(collection_fields)}
97
- ] as {
98
- field: keyof (typeof ${uppercase_collection})["fields"];
99
- render?: ListFilterRender;
100
- prepareValue?: (filter_value: unknown)=>unknown; // set this function to change what filter value is passed to Sealious
101
- }[];
102
-
103
- export default new CRUD({
104
- collection: ${toPascalCase(collection_name)},
105
- nice_collection_name: "${toPascalCase(collection_name)}",
106
- fields_for_display,
107
- fields_for_filters,
108
- html,
109
- list_title: "${toPascalCase(collection_name)} list",
110
- edit_title: "Edit",
111
- edit_button_text: "Edit",
112
- delete_button_text: "Delete",
113
- back_to_list_button_text: "\u2190 Back to ${toPascalCase(collection_name)} list",
114
- edit_fields,
115
- edit_controls,
116
- form_value_to_sealious_value: {},
117
- sealious_value_to_form_value: {},
118
- post_edit: async () => {},
119
- post_create: async () => {},
120
- });
121
- `;
122
- await writeFile(list_path, await formatWithPrettier(list_content));
74
+ await writeFile(list_path, list_content);
75
+ const fields_path = target_locreq.resolve(
76
+ `src/back/routes/${escape_url_params(url)}/shared.ts`
77
+ );
78
+ const fields_content = await sharedCrudFormFields(
79
+ collection_name,
80
+ fields_path
81
+ );
82
+ await writeFile(fields_path, fields_content);
83
+ const create_path = target_locreq.resolve(
84
+ `src/back/routes/${escape_url_params(url)}/create.form.ts`
85
+ );
86
+ const create_content = await createItemFormTemplate(
87
+ create_action_name,
88
+ create_path,
89
+ collection_name,
90
+ list_action_name
91
+ );
92
+ await writeFile(create_path, create_content);
93
+ const edit_path = target_locreq.resolve(
94
+ `src/back/routes/${escape_url_params(url)}/[id]/edit.form.ts`
95
+ );
96
+ const edit_content = await editItemFormTemplate(
97
+ edit_action_name,
98
+ edit_path,
99
+ collection_name,
100
+ list_action_name
101
+ );
102
+ await writeFile(edit_path, edit_content);
103
+ const delete_path = target_locreq.resolve(
104
+ `src/back/routes/${escape_url_params(url)}/[id]/delete.page.tsx`
105
+ );
106
+ const base_import_path = curryImportPath(delete_path);
107
+ const delete_content = await itemDeleteTemplate(
108
+ delete_action_name,
109
+ collection_name,
110
+ list_action_name,
111
+ base_import_path
112
+ );
113
+ await writeFile(delete_path, delete_content);
123
114
  await generateRoutes();
124
115
  }
125
116
  export {
@@ -2,7 +2,7 @@ import { getBrowser } from "./utils/browser-creator.js";
2
2
  import { RealAppTest } from "./test_utils/test-on-real-app.js";
3
3
  import { collectionTemplate } from "./templates/collection.js";
4
4
  import assert from "node:assert";
5
- describe("single-reference.test", () => {
5
+ describe("single-reference", () => {
6
6
  let page;
7
7
  before(async () => {
8
8
  const browser = await getBrowser();
package/lib/add-route.js 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";
@@ -67,12 +66,6 @@ async function addRoute(params, app_directory = process.cwd()) {
67
66
  }
68
67
  await fs.mkdir(resolve(file_path, "../"), { recursive: true });
69
68
  await fs.writeFile(file_path, await template(action, file_path));
70
- if (mode !== "lpr" && mode !== "jdd-editor") {
71
- await fs.writeFile(
72
- test_file_path,
73
- await testTemplate(action, file_path)
74
- );
75
- }
76
69
  console.log(`${file_path} created`);
77
70
  console.log(`${test_file_path} created`);
78
71
  await generateRoutes();
package/lib/build.js CHANGED
@@ -86,7 +86,9 @@ async function build(watch) {
86
86
  ];
87
87
  await Promise.all(builders.map((b) => b.build()));
88
88
  if (watch) {
89
- const watcher = chokidar.watch("src", { ignoreInitial: true });
89
+ const watcher = chokidar.watch(["src", ...controller_dirs], {
90
+ ignoreInitial: true
91
+ });
90
92
  const port = await get_notifier_port();
91
93
  const notifier = make_notifier(port, 8080);
92
94
  await write_notifier_config(watch, port);
package/lib/cli.js CHANGED
@@ -1,17 +1,15 @@
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";
15
13
  import {
16
14
  registerExternalControllers,
17
15
  registerExternalStyles
@@ -19,7 +17,6 @@ import {
19
17
  const actions = {
20
18
  "add-collection": addCollection,
21
19
  "add-route": addRoute,
22
- "add-verbose-crud": addVerboseCRUD,
23
20
  "add-crud": addCRUD,
24
21
  "generate-collections": generateCollections,
25
22
  "generate-components": generateComponents,
@@ -34,7 +31,7 @@ const actions = {
34
31
  "make-env": makeEnv,
35
32
  "add-component": addJDDComponent,
36
33
  "get-fonts": getFonts,
37
- "crud-field-snippets": crudFieldSnippets,
34
+ // "crud-field-snippets": crudFieldSnippets,
38
35
  "register-external-controllers": registerExternalControllers,
39
36
  "register-external-styles": registerExternalStyles
40
37
  };
@@ -0,0 +1,35 @@
1
+ import { Controller } from "stimulus";
2
+ class table_add_button_stimulus_default extends Controller {
3
+ constructor() {
4
+ super(...arguments);
5
+ this.defaultRowsNumber = 20;
6
+ }
7
+ static {
8
+ this.targets = ["textarea"];
9
+ }
10
+ addRow() {
11
+ const template = this.element.closest("turbo-frame")?.querySelector("template");
12
+ if (!template) {
13
+ throw new Error("Couldn't find template");
14
+ }
15
+ const tbody = this.element.closest("turbo-frame")?.querySelector("tbody");
16
+ if (!tbody) {
17
+ throw new Error("tbody not found");
18
+ }
19
+ const orig_template = template.innerHTML;
20
+ const placeholder = this.element.getAttribute("data-table-placeholder");
21
+ if (!placeholder) {
22
+ throw new Error("Could find placeholder attribute");
23
+ }
24
+ template.innerHTML = orig_template.replaceAll(
25
+ placeholder,
26
+ String(tbody.querySelectorAll("tr").length)
27
+ );
28
+ tbody.appendChild(template.cloneNode(true).content);
29
+ template.innerHTML = orig_template;
30
+ }
31
+ }
32
+ export {
33
+ table_add_button_stimulus_default as default
34
+ };
35
+ //# sourceMappingURL=table-add-button.stimulus.js.map
@@ -1,7 +1,7 @@
1
1
  import { hasShape, predicates } from "@sealcode/ts-predicates";
2
2
  import qs from "qs";
3
3
  import { tempstream } from "tempstream";
4
- import { SimpleFormField } from "../fields/simple-form-field.js";
4
+ import { TextBasedSimpleField } from "../fields/simple-form-field.js";
5
5
  import { Derived } from "./derived.js";
6
6
  import { FormFieldControl } from "./form-field-control.js";
7
7
  function UnboundControl(controlClass, arbitrary_field_name, params) {
@@ -26,12 +26,12 @@ class StructuredArray extends FormFieldControl {
26
26
  return {};
27
27
  }
28
28
  makeSubfield(_field_name) {
29
- return new SimpleFormField(false);
29
+ return new TextBasedSimpleField(false);
30
30
  }
31
31
  async renderItemControl(ctx, form_id, control, item, index) {
32
32
  const fctx = {
33
33
  ctx,
34
- data: {},
34
+ data: { raw_values: {}, messages: [], field_messages: {} },
35
35
  messages: [],
36
36
  field_name_prefix: "",
37
37
  form_id,
@@ -46,9 +46,7 @@ class StructuredArray extends FormFieldControl {
46
46
  );
47
47
  return "";
48
48
  }
49
- await field.init(
50
- `${this.field.name}[data][${index}][${field_name}]`
51
- );
49
+ field.setName(`${this.field.name}[data][${index}][${field_name}]`);
52
50
  const hidden_shadow = new Derived(
53
51
  [field],
54
52
  async (values, { inner_form_id, field_name: field_name2 }) => (
@@ -67,10 +65,22 @@ class StructuredArray extends FormFieldControl {
67
65
  );
68
66
  return tempstream`${new constructor(field, params).render({
69
67
  ...fctx,
70
- data: { [field.name]: item[field_name] }
68
+ data: {
69
+ raw_values: {
70
+ [field.name]: item[field_name]
71
+ },
72
+ messages: [],
73
+ field_messages: {}
74
+ }
71
75
  })}${hidden_shadow.render({
72
76
  ...fctx,
73
- data: { [field.name]: item[field_name] },
77
+ data: {
78
+ raw_values: {
79
+ [field.name]: item[field_name]
80
+ },
81
+ messages: [],
82
+ field_messages: {}
83
+ },
74
84
  form_id: this.getInnerFormID()
75
85
  })}`;
76
86
  } else {
@@ -93,7 +103,7 @@ class StructuredArray extends FormFieldControl {
93
103
  </div>`;
94
104
  }
95
105
  async getItems(ctx, raw_values) {
96
- return (await this.field.getValue(ctx, raw_values)).parsed;
106
+ return (await this.field.getParsedValue(ctx, raw_values)).parsed;
97
107
  }
98
108
  async _render(ctx, form_id, raw_values) {
99
109
  const items = await this.getItems(ctx, raw_values);
@@ -114,13 +124,12 @@ class StructuredArray extends FormFieldControl {
114
124
  </turbo-frame>`;
115
125
  }
116
126
  render(fctx) {
117
- return this._render(fctx.ctx, fctx.form_id, fctx.data);
127
+ return this._render(fctx.ctx, fctx.form_id, fctx.data.raw_values);
118
128
  }
119
129
  async getTargetItemID(ctx) {
120
130
  return ctx.params.id;
121
131
  }
122
132
  mount(router) {
123
- console.log("mounting!", this.getActionURL());
124
133
  router.post(this.getActionURL(), async (ctx) => {
125
134
  const form_id = ctx.query.form_id;
126
135
  if (typeof form_id != "string") {
@@ -134,7 +143,6 @@ class StructuredArray extends FormFieldControl {
134
143
  throw new Error("Missing action param");
135
144
  }
136
145
  const field_data = ctx.$body[this.field.name] || { data: [] };
137
- console.log({ action: field_data });
138
146
  if (!hasShape(
139
147
  {
140
148
  data: predicates.array(
@@ -149,10 +157,6 @@ class StructuredArray extends FormFieldControl {
149
157
  ...ctx.$body.action,
150
158
  data: field_data.data || []
151
159
  });
152
- console.log("ACTION", {
153
- ...ctx.$body.action,
154
- data: field_data.data || []
155
- });
156
160
  await item.save(ctx.$context);
157
161
  console.log(await item.getDecodedBody(ctx.$context, {}));
158
162
  ctx.body = this._render(
@@ -7,9 +7,9 @@ class BigRadioGroup extends FormFieldControl {
7
7
  this.options = options;
8
8
  }
9
9
  async render(fctx) {
10
- const { raw: current_value } = await this.field.getValue(
10
+ const { raw: current_value } = await this.field.getParsedValue(
11
11
  fctx.ctx,
12
- fctx.data
12
+ fctx.data.raw_values
13
13
  );
14
14
  return tempstream`<div class="bigradios">
15
15
  ${Object.entries(this.options).map(([key, { description }]) => {
@@ -18,24 +18,24 @@ class CheckboxGroup extends FormFieldControl {
18
18
  }).render(fctx);
19
19
  }
20
20
  async render(fctx) {
21
- const { parsed: values } = await this.field.getValue(
21
+ const { parsed: values } = await this.field.getParsedValue(
22
22
  fctx.ctx,
23
- fctx.data
23
+ fctx.data.raw_values
24
24
  );
25
- const checkboxes = this.field.options.map(
25
+ const checkboxes = (await this.field.generateOptions(fctx.ctx)).map(
26
26
  (option) => new CheckboxWithValue(
27
27
  new ProxyFormField(
28
28
  false,
29
29
  this.field.name,
30
30
  false,
31
- (values || []).includes(option)
31
+ Object.keys(values || {}).includes(option.value)
32
32
  ),
33
33
  {
34
- id: this.field.name + "__" + option,
35
- label: (this.options.checkboxNameToLabel || ((s) => s))(option),
34
+ id: this.field.name + "__" + option.value,
35
+ label: (this.options.checkboxNameToLabel || ((s) => s))(option.value),
36
36
  default_value: false
37
37
  },
38
- option
38
+ option.value
39
39
  )
40
40
  );
41
41
  return this.wrapGroup(fctx, checkboxes);
@@ -21,7 +21,11 @@ class CheckboxedListInput extends FormFieldControl {
21
21
  valid,
22
22
  message,
23
23
  parsed: currentValue
24
- } = await this.field.getValue(fctx.ctx, fctx.data, true);
24
+ } = await this.field.getParsedValue(
25
+ fctx.ctx,
26
+ fctx.data.raw_values,
27
+ true
28
+ );
25
29
  const pickedValues = Object.entries(currentValue || {}).filter(([, is_on]) => is_on).map(([key]) => key);
26
30
  const [options, isVisible] = await Promise.all([
27
31
  this.field.generateOptions(fctx.ctx),
@@ -56,7 +60,9 @@ class CheckboxedListInput extends FormFieldControl {
56
60
  ([group_label, options2]) => tempstream` <h3>
57
61
  ${group_label}
58
62
  </h3>
59
- ${options2.map(
63
+
64
+ ${// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
65
+ options2.map(
60
66
  ({ value, label }) => this.renderOption({
61
67
  name,
62
68
  value,
@@ -99,6 +105,7 @@ class CheckboxedListInput extends FormFieldControl {
99
105
  name="${name}.${value}"
100
106
  ${checked ? "checked" : ""}
101
107
  form=${form_id}
108
+ autocomplete="off"
102
109
  />
103
110
  <label for="${name}.${value}">${label || value}</label>
104
111
  `
@@ -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 "./array.js";
31
31
  export * from "./table.js";
32
32
  export {
@@ -58,7 +58,11 @@ class DerivedFrame extends Derived {
58
58
  await this.generateFrameContent(
59
59
  new FormControlContext(
60
60
  ctx,
61
- ctx.query,
61
+ {
62
+ messages: [],
63
+ field_messages: {},
64
+ raw_values: ctx.query
65
+ },
62
66
  [],
63
67
  query.field_name_prefix,
64
68
  query.form_id,
@@ -12,7 +12,7 @@ class Derived extends FormControl {
12
12
  async getBackendValues(fctx) {
13
13
  const fieldnames = this.fields.map((f) => f.name);
14
14
  const result = Object.fromEntries(
15
- Object.entries(fctx.data).filter(
15
+ Object.entries(fctx.data.raw_values).filter(
16
16
  ([key]) => fieldnames.includes(key)
17
17
  )
18
18
  );
@@ -30,7 +30,10 @@ class FreeformDropdown extends SimpleInput {
30
30
  };
31
31
  }
32
32
  async renderInput(ctx, attributes_str, data) {
33
- const { parsed: picked_value } = await this.field.getValue(ctx, data);
33
+ const { parsed: picked_value } = await this.field.getParsedValue(
34
+ ctx,
35
+ data
36
+ );
34
37
  return (
35
38
  /* HTML */
36
39
  tempstream`<select ${attributes_str}>
@@ -11,9 +11,9 @@ class EditableCollectionSubset extends FormFieldControl {
11
11
  this.role = "input";
12
12
  }
13
13
  async render(fctx) {
14
- const { parsed: values } = await this.field.getValue(
14
+ const { parsed: values } = await this.field.getParsedValue(
15
15
  fctx.ctx,
16
- fctx.data
16
+ fctx.data.raw_values
17
17
  );
18
18
  return tempstream`<div>
19
19
  <ul>
@@ -1,6 +1,8 @@
1
+ import { PathFilePointer } from "@sealcode/file-manager";
1
2
  import { tempstream } from "tempstream";
2
3
  import { SimpleInput } from "./simple-input.js";
3
4
  import { htmlEscape } from "escape-goat";
5
+ import { extname } from "node:path";
4
6
  class File extends SimpleInput {
5
7
  getType() {
6
8
  return "file";
@@ -11,12 +13,31 @@ class File extends SimpleInput {
11
13
  if (!file) {
12
14
  return empty_container;
13
15
  }
16
+ if (file instanceof PathFilePointer) {
17
+ const filename = await file.getOriginalFilename();
18
+ return tempstream`<div class="${class_name}">
19
+ <div class="${class_name}__icon">
20
+ <picture>
21
+ <img
22
+ src="/dist/sealgen/file-icon.svg"
23
+ width="80"
24
+ height="80"
25
+ alt=""
26
+ />
27
+ <span class="${class_name}__icon__extension"
28
+ >${extname(filename)}</span
29
+ >
30
+ </picture>
31
+ <a href="${file.getURL()}" download>${filename}</a>
32
+ </div>
33
+ </div>`;
34
+ }
14
35
  return tempstream`<div class="${class_name}">
15
36
  ${file.getOriginalFilename()}
16
37
  </div>`;
17
38
  }
18
39
  async preInput(fctx, data) {
19
- let { parsed } = await this.field.getValue(fctx.ctx, data);
40
+ let { parsed } = await this.field.getParsedValue(fctx.ctx, data);
20
41
  if (parsed === null) {
21
42
  parsed = { old: null, new: null };
22
43
  }
@@ -35,7 +56,10 @@ class File extends SimpleInput {
35
56
  }
36
57
  async getInputAttributes(fctx) {
37
58
  const original = await super.getInputAttributes(fctx);
38
- const { parsed } = await this.field.getValue(fctx.ctx, fctx.data);
59
+ const { parsed } = await this.field.getParsedValue(
60
+ fctx.ctx,
61
+ fctx.data.raw_values
62
+ );
39
63
  return {
40
64
  ...original,
41
65
  name: this.field.name + "[new]",
@@ -20,11 +20,11 @@ describe("file-control", () => {
20
20
  });
21
21
  it("doesn't require image input if it already has old-value", async () => {
22
22
  const port = await getPort();
23
- console.log(`Using port ${port} for photo.test.ts`);
23
+ console.log(`Using port ${port} for image.test.ts`);
24
24
  const app = new Koa();
25
25
  const router = new Router();
26
26
  const fields = {
27
- file: new Fields.File(true, new FileManager("/tmp", "/uploaded_files"))
27
+ file: new Fields.File(true)
28
28
  };
29
29
  let submit_called = false;
30
30
  mount(
@@ -7,7 +7,10 @@ class HiddenInput extends FormFieldControl {
7
7
  this.field = field;
8
8
  }
9
9
  async render(fctx) {
10
- const { raw } = await this.field.getValue(fctx.ctx, fctx.data);
10
+ const { raw } = await this.field.getParsedValue(
11
+ fctx.ctx,
12
+ fctx.data.raw_values
13
+ );
11
14
  return tempstream`<input type="hidden" name="${this.field.name}" value="${attribute((raw || "").toString())}" form="${fctx.form_id}">`;
12
15
  }
13
16
  }