@sealcode/sealgen 0.18.8 → 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 (374) hide show
  1. package/.eslintrc.cjs +7 -2
  2. package/.xunit +75 -0
  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 -2
  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 -1
  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 -3
  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 -0
  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 -2
  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 -7
  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 -1
  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/page/list.d.sync-conflict-20250918-184318-TFDLWFG.ts +48 -0
  133. package/@types/page/list.d.sync-conflict-20250918-222046-TFDLWFG.ts +48 -0
  134. package/@types/page/list.d.ts +2 -2
  135. package/@types/page/list.sync-conflict-20250918-222048-TFDLWFG.d.ts +48 -0
  136. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-184321-TFDLWFG.ts +42 -0
  137. package/@types/page/mountable-with-fields.d.sync-conflict-20250918-222046-TFDLWFG.ts +42 -0
  138. package/@types/page/mountable-with-fields.d.ts +3 -3
  139. package/@types/page/mountable-with-fields.sync-conflict-20250918-222044-TFDLWFG.d.ts +42 -0
  140. package/@types/page/mountable.d.sync-conflict-20250918-184306-TFDLWFG.ts +10 -0
  141. package/@types/page/page.d.sync-conflict-20250918-184320-TFDLWFG.ts +18 -0
  142. package/@types/page/props-parser.d.sync-conflict-20250918-184305-TFDLWFG.ts +15 -0
  143. package/@types/page/props-parser.d.ts +0 -1
  144. package/@types/page/stateful-page.d.sync-conflict-20250918-184326-TFDLWFG.ts +62 -0
  145. package/@types/templates/shared/shared-crud-form-fields.d.sync-conflict-20250918-184306-TFDLWFG.ts +1 -0
  146. package/@types/templates/shared/shared-crud-form-fields.d.ts +0 -67
  147. package/@types/test_utils/test-on-real-app.d.sync-conflict-20250918-184320-TFDLWFG.ts +26 -0
  148. package/@types/test_utils/test-on-real-app.d.ts +0 -1
  149. package/@types/utils/extract-fields-from-collection.d.sync-conflict-20250918-184312-TFDLWFG.ts +18 -0
  150. package/@types/utils/extract-fields-from-collection.d.ts +5 -1
  151. package/@types/utils/extract-fields-from-collection.sync-conflict-20250918-222045-TFDLWFG.d.ts +18 -0
  152. package/@types/utils/wrap-attributes.d.ts +3 -0
  153. package/README.md +5 -0
  154. package/assets/file-icon.svg +5 -0
  155. package/lib/add-crud.js +80 -89
  156. package/lib/add-list-route.test.js +1 -1
  157. package/lib/add-route.js +0 -7
  158. package/lib/build.js +3 -1
  159. package/lib/cli.js +2 -5
  160. package/lib/controllers/table-add-button.stimulus.js +35 -0
  161. package/lib/forms/controls/array.js +20 -16
  162. package/lib/forms/controls/big-radio-group.js +2 -2
  163. package/lib/forms/controls/checkbox-group.js +7 -7
  164. package/lib/forms/controls/checkboxed-list-input.js +9 -2
  165. package/lib/forms/controls/controls.js +2 -2
  166. package/lib/forms/controls/derived-frame.js +5 -1
  167. package/lib/forms/controls/derived.js +1 -1
  168. package/lib/forms/controls/dropdown.js +4 -1
  169. package/lib/forms/controls/editable-collection-subset.js +2 -2
  170. package/lib/forms/controls/file.js +26 -2
  171. package/lib/forms/controls/file.test.js +2 -2
  172. package/lib/forms/controls/hidden-input.js +4 -1
  173. package/lib/forms/controls/{photo.js → image.js} +6 -7
  174. package/lib/forms/controls/{photo.test.js → image.test.js} +6 -21
  175. package/lib/forms/controls/multiple-files.js +10 -1
  176. package/lib/forms/controls/{multiple-photos.js → multiple-images.js} +3 -3
  177. package/lib/forms/controls/simple-input.js +13 -12
  178. package/lib/forms/controls/single-reference.js +4 -0
  179. package/lib/forms/controls/table.js +66 -24
  180. package/lib/forms/controls/textarea.js +4 -2
  181. package/lib/forms/controls/tickable.js +13 -5
  182. package/lib/forms/fields/boolean.js +14 -0
  183. package/lib/forms/fields/checkboxed-list.js +4 -0
  184. package/lib/forms/fields/collection-field.js +9 -0
  185. package/lib/forms/fields/color.js +10 -0
  186. package/lib/forms/fields/coordinates.js +49 -0
  187. package/lib/forms/fields/date.js +34 -0
  188. package/lib/forms/fields/datetime.js +46 -0
  189. package/lib/forms/fields/deep-reverse-single-reference-list.js +81 -0
  190. package/lib/forms/fields/deep-reverse-single-reference-table.js +122 -0
  191. package/lib/forms/fields/email.js +7 -0
  192. package/lib/forms/fields/enum-multiple-sealious.js +32 -0
  193. package/lib/forms/fields/field.js +32 -4
  194. package/lib/forms/fields/field.test.js +5 -5
  195. package/lib/forms/fields/fields.js +23 -8
  196. package/lib/forms/fields/file.js +33 -9
  197. package/lib/forms/fields/file.test.js +4 -16
  198. package/lib/forms/fields/float.js +10 -0
  199. package/lib/forms/fields/get-field-for-sealious.js +213 -0
  200. package/lib/forms/fields/html.js +14 -0
  201. package/lib/forms/fields/image.js +13 -0
  202. package/lib/forms/fields/int.js +23 -0
  203. package/lib/forms/fields/json.js +31 -0
  204. package/lib/forms/fields/markdown.js +14 -0
  205. package/lib/forms/fields/multiple-files.js +4 -0
  206. package/lib/forms/fields/number.js +6 -0
  207. package/lib/forms/fields/password.js +13 -0
  208. package/lib/forms/fields/pick-from-list-sealious.js +17 -0
  209. package/lib/forms/fields/pick-from-list.js +6 -2
  210. package/lib/forms/fields/proxy-field.js +3 -0
  211. package/lib/forms/fields/regexp.js +14 -0
  212. package/lib/forms/fields/simple-form-field.js +60 -2
  213. package/lib/forms/fields/single-reference.js +44 -0
  214. package/lib/forms/fields/structured-array.js +63 -12
  215. package/lib/forms/fields/table.js +28 -1
  216. package/lib/forms/fields/text.js +17 -0
  217. package/lib/forms/fields/url.js +17 -0
  218. package/lib/forms/form.js +30 -13
  219. package/lib/forms/form.test.js +3 -4
  220. package/lib/forms/multiform.js +4 -2
  221. package/lib/forms/multiform.test.js +3 -3
  222. package/lib/generate-stimulus.js +1 -0
  223. package/lib/index.js +1 -0
  224. package/lib/make-hidden-inputs.js +1 -1
  225. package/lib/mount.js +11 -0
  226. package/lib/notifier.js +0 -1
  227. package/lib/page/list.js +15 -8
  228. package/lib/page/mountable-with-fields.js +14 -6
  229. package/lib/page/mountable-with-fields.test.js +1 -1
  230. package/lib/templates/form.js +8 -9
  231. package/lib/templates/multiform.js +4 -4
  232. package/lib/templates/page.js +0 -2
  233. package/lib/templates/shared/collection-create-form.js +28 -40
  234. package/lib/templates/shared/collection-edit-form.js +40 -77
  235. package/lib/templates/shared/collection-list.js +12 -20
  236. package/lib/templates/shared/shared-crud-form-fields.js +27 -95
  237. package/lib/test_utils/test-on-real-app.js +3 -3
  238. package/lib/utils/extract-fields-from-collection.js +60 -20
  239. package/lib/utils/make-slug.js +1 -1
  240. package/lib/utils/wrap-attributes.js +20 -0
  241. package/package.json +5 -4
  242. package/src/add-crud.ts +86 -97
  243. package/src/add-list-route.test.ts +1 -1
  244. package/src/add-route.ts +0 -7
  245. package/src/build.ts +3 -1
  246. package/src/cli.ts +3 -5
  247. package/src/controllers/table-add-button.stimulus.ts +35 -0
  248. package/src/forms/controls/array.ts +23 -20
  249. package/src/forms/controls/autocomplete.ts +1 -1
  250. package/src/forms/controls/big-radio-group.ts +2 -2
  251. package/src/forms/controls/checkbox-group.ts +9 -9
  252. package/src/forms/controls/checkboxed-list-input.ts +27 -15
  253. package/src/forms/controls/controls.ts +2 -2
  254. package/src/forms/controls/derived-frame.ts +5 -1
  255. package/src/forms/controls/derived.ts +1 -1
  256. package/src/forms/controls/dropdown.ts +5 -2
  257. package/src/forms/controls/editable-collection-subset.ts +2 -2
  258. package/src/forms/controls/file.test.ts +4 -2
  259. package/src/forms/controls/file.ts +31 -5
  260. package/src/forms/controls/form-control.ts +7 -2
  261. package/src/forms/controls/hidden-input.ts +4 -1
  262. package/src/forms/controls/{photo.test.ts → image.test.ts} +5 -22
  263. package/src/forms/controls/{photo.ts → image.ts} +3 -5
  264. package/src/forms/controls/multiple-files.ts +18 -1
  265. package/src/forms/controls/{multiple-photos.ts → multiple-images.ts} +1 -1
  266. package/src/forms/controls/number.ts +1 -1
  267. package/src/forms/controls/simple-input.ts +18 -34
  268. package/src/forms/controls/single-reference.ts +10 -2
  269. package/src/forms/controls/table.ts +90 -31
  270. package/src/forms/controls/textarea.ts +6 -4
  271. package/src/forms/controls/tickable.ts +13 -5
  272. package/src/forms/fields/boolean.ts +23 -1
  273. package/src/forms/fields/checkboxed-list.ts +11 -2
  274. package/src/forms/fields/collection-field.ts +16 -1
  275. package/src/forms/fields/color.ts +9 -0
  276. package/src/forms/fields/coordinates.ts +66 -0
  277. package/src/forms/fields/date.ts +50 -0
  278. package/src/forms/fields/datetime.ts +66 -0
  279. package/src/forms/fields/deep-reverse-single-reference-list.ts +136 -0
  280. package/src/forms/fields/deep-reverse-single-reference-table.ts +213 -0
  281. package/src/forms/fields/email.ts +9 -0
  282. package/src/forms/fields/enum-multiple-sealious.ts +48 -0
  283. package/src/forms/fields/field.test.ts +5 -5
  284. package/src/forms/fields/field.ts +94 -8
  285. package/src/forms/fields/fields.ts +23 -8
  286. package/src/forms/fields/file.test.ts +4 -16
  287. package/src/forms/fields/file.ts +43 -15
  288. package/src/forms/fields/float.ts +9 -0
  289. package/src/forms/fields/get-field-for-sealious.ts +304 -0
  290. package/src/forms/fields/html.ts +15 -0
  291. package/src/forms/fields/image.ts +12 -0
  292. package/src/forms/fields/int.ts +25 -0
  293. package/src/forms/fields/json.ts +48 -0
  294. package/src/forms/fields/markdown.ts +15 -0
  295. package/src/forms/fields/multiple-files.ts +10 -1
  296. package/src/forms/fields/number.ts +8 -1
  297. package/src/forms/fields/password.ts +17 -0
  298. package/src/forms/fields/pick-from-list-sealious.ts +22 -0
  299. package/src/forms/fields/pick-from-list.ts +7 -3
  300. package/src/forms/fields/proxy-field.ts +6 -1
  301. package/src/forms/fields/regexp.ts +27 -1
  302. package/src/forms/fields/simple-form-field.ts +95 -7
  303. package/src/forms/fields/single-reference.ts +62 -0
  304. package/src/forms/fields/structured-array.ts +115 -18
  305. package/src/forms/fields/table.ts +32 -1
  306. package/src/forms/fields/text.ts +18 -0
  307. package/src/forms/fields/url.ts +20 -0
  308. package/src/forms/form-types.ts +2 -0
  309. package/src/forms/form.test.ts +3 -4
  310. package/src/forms/form.ts +37 -16
  311. package/src/forms/forms.css +0 -85
  312. package/src/forms/multiform.test.ts +3 -3
  313. package/src/forms/multiform.ts +2 -0
  314. package/src/generate-stimulus.ts +1 -0
  315. package/src/index.ts +2 -1
  316. package/src/make-hidden-inputs.ts +1 -1
  317. package/src/mount.ts +14 -0
  318. package/src/notifier.ts +0 -1
  319. package/src/page/list.ts +15 -8
  320. package/src/page/mountable-with-fields.test.ts +1 -1
  321. package/src/page/mountable-with-fields.ts +18 -9
  322. package/src/register-external.ts +1 -1
  323. package/src/templates/form.ts +8 -9
  324. package/src/templates/multiform.ts +4 -4
  325. package/src/templates/page.ts +0 -2
  326. package/src/templates/shared/collection-create-form.ts +30 -66
  327. package/src/templates/shared/collection-edit-form.ts +41 -102
  328. package/src/templates/shared/collection-list.ts +12 -20
  329. package/src/templates/shared/item-delete.ts +0 -1
  330. package/src/templates/shared/shared-crud-form-fields.ts +37 -171
  331. package/src/test_utils/test-on-real-app.ts +4 -3
  332. package/src/utils/extract-fields-from-collection.ts +76 -25
  333. package/src/utils/make-slug.ts +1 -1
  334. package/src/utils/wrap-attributes.ts +17 -0
  335. package/lib/add-verbose-crud.js +0 -119
  336. package/lib/crud-field-snippets.js +0 -52
  337. package/lib/find-css-includes.js +0 -3
  338. package/lib/forms/controls/reverse-single-reference.js +0 -1
  339. package/lib/forms/fields/enum-multiple.js +0 -47
  340. package/lib/forms/fields/enum-multiple.test.js +0 -27
  341. package/lib/forms/fields/enum.js +0 -41
  342. package/lib/forms/fields/enum.test.js +0 -21
  343. package/lib/forms/fields/reverse-single-reference.js +0 -17
  344. package/lib/templates/shared/handlers/boolean.js +0 -14
  345. package/lib/templates/shared/handlers/date.js +0 -8
  346. package/lib/templates/shared/handlers/deep-reverse-single-reference.js +0 -209
  347. package/lib/templates/shared/handlers/default.js +0 -49
  348. package/lib/templates/shared/handlers/enum.js +0 -19
  349. package/lib/templates/shared/handlers/file.js +0 -23
  350. package/lib/templates/shared/handlers/image.js +0 -32
  351. package/lib/templates/shared/handlers/int.js +0 -11
  352. package/lib/templates/shared/handlers/jdd.js +0 -10
  353. package/lib/templates/shared/handlers/single-reference.js +0 -12
  354. package/lib/templates/shared/handlers/structured-array.js +0 -33
  355. package/src/add-verbose-crud.ts +0 -138
  356. package/src/crud-field-snippets.ts +0 -57
  357. package/src/find-css-includes.ts +0 -3
  358. package/src/forms/controls/reverse-single-reference.ts +0 -50
  359. package/src/forms/fields/enum-multiple.test.ts +0 -31
  360. package/src/forms/fields/enum-multiple.ts +0 -62
  361. package/src/forms/fields/enum.test.ts +0 -25
  362. package/src/forms/fields/enum.ts +0 -56
  363. package/src/forms/fields/reverse-single-reference.ts +0 -20
  364. package/src/templates/shared/handlers/boolean.ts +0 -18
  365. package/src/templates/shared/handlers/date.ts +0 -12
  366. package/src/templates/shared/handlers/deep-reverse-single-reference.ts +0 -244
  367. package/src/templates/shared/handlers/default.ts +0 -64
  368. package/src/templates/shared/handlers/enum.ts +0 -23
  369. package/src/templates/shared/handlers/file.ts +0 -27
  370. package/src/templates/shared/handlers/image.ts +0 -45
  371. package/src/templates/shared/handlers/int.ts +0 -15
  372. package/src/templates/shared/handlers/jdd.ts +0 -14
  373. package/src/templates/shared/handlers/single-reference.ts +0 -16
  374. package/src/templates/shared/handlers/structured-array.ts +0 -42
@@ -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
@@ -22,9 +22,9 @@ export class EditableCollectionSubset extends FormFieldControl {
22
22
  }
23
23
 
24
24
  async render(fctx: FormControlContext): Promise<FlatTemplatable> {
25
- const { parsed: values } = await this.field.getValue(
25
+ const { parsed: values } = await this.field.getParsedValue(
26
26
  fctx.ctx,
27
- fctx.data
27
+ fctx.data.raw_values
28
28
  );
29
29
 
30
30
  return tempstream/* HTML */ `<div>
@@ -12,6 +12,7 @@ import _locreq from "locreq";
12
12
  import { module_dirname } from "../../utils/module-dirname.js";
13
13
  import { FileManager, PathFilePointer } from "@sealcode/file-manager";
14
14
  import assert from "node:assert";
15
+
15
16
  const locreq = _locreq(module_dirname(import.meta.url));
16
17
 
17
18
  describe("file-control", () => {
@@ -26,12 +27,12 @@ describe("file-control", () => {
26
27
 
27
28
  it("doesn't require image input if it already has old-value", async () => {
28
29
  const port = await getPort();
29
- console.log(`Using port ${port} for photo.test.ts`);
30
+ console.log(`Using port ${port} for image.test.ts`);
30
31
  const app = new Koa();
31
32
  const router = new Router();
32
33
 
33
34
  const fields = {
34
- file: new Fields.File(true, new FileManager("/tmp", "/uploaded_files")),
35
+ file: new Fields.File(true),
35
36
  };
36
37
 
37
38
  let submit_called = false;
@@ -63,6 +64,7 @@ describe("file-control", () => {
63
64
  })(),
64
65
  true
65
66
  );
67
+
66
68
  app.use(router.routes()).use(router.allowedMethods());
67
69
  server = app.listen(port);
68
70
 
@@ -1,13 +1,17 @@
1
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+ /* eslint-disable @typescript-eslint/no-unsafe-argument */
3
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
4
+ /* eslint-disable @typescript-eslint/no-unsafe-call */
1
5
  import { Context } from "koa";
2
- import { FilePointer } from "@sealcode/file-manager";
6
+ import { FilePointer, PathFilePointer } from "@sealcode/file-manager";
3
7
  import { FlatTemplatable, tempstream } from "tempstream";
4
- import { FileContainer } from "../fields/file.js";
5
8
  import { FormDataValue } from "../form-types.js";
6
9
  import { FormControlContext } from "./form-control.js";
7
10
  import { SimpleInput } from "./simple-input.js";
8
11
  import { htmlEscape } from "escape-goat";
12
+ import { extname } from "node:path";
9
13
 
10
- export class File extends SimpleInput<FileContainer> {
14
+ export class File extends SimpleInput {
11
15
  getType() {
12
16
  return "file";
13
17
  }
@@ -21,6 +25,25 @@ export class File extends SimpleInput<FileContainer> {
21
25
  if (!file) {
22
26
  return empty_container;
23
27
  }
28
+ if (file instanceof PathFilePointer) {
29
+ const filename = await file.getOriginalFilename();
30
+ return tempstream/* HTML */ `<div class="${class_name}">
31
+ <div class="${class_name}__icon">
32
+ <picture>
33
+ <img
34
+ src="/dist/sealgen/file-icon.svg"
35
+ width="80"
36
+ height="80"
37
+ alt=""
38
+ />
39
+ <span class="${class_name}__icon__extension"
40
+ >${extname(filename)}</span
41
+ >
42
+ </picture>
43
+ <a href="${file.getURL()}" download>${filename}</a>
44
+ </div>
45
+ </div>`;
46
+ }
24
47
  return tempstream/* HTML */ `<div class="${class_name}">
25
48
  ${file.getOriginalFilename()}
26
49
  </div>`;
@@ -30,7 +53,7 @@ export class File extends SimpleInput<FileContainer> {
30
53
  fctx: FormControlContext,
31
54
  data: Record<string, FormDataValue>
32
55
  ) {
33
- let { parsed } = await this.field.getValue(fctx.ctx, data);
56
+ let { parsed } = await this.field.getParsedValue(fctx.ctx, data);
34
57
  if (parsed === null) {
35
58
  parsed = { old: null, new: null };
36
59
  }
@@ -52,7 +75,10 @@ export class File extends SimpleInput<FileContainer> {
52
75
  fctx: FormControlContext
53
76
  ): Promise<Record<string, string | boolean>> {
54
77
  const original = await super.getInputAttributes(fctx);
55
- const { parsed } = await this.field.getValue(fctx.ctx, fctx.data);
78
+ const { parsed } = await this.field.getParsedValue(
79
+ fctx.ctx,
80
+ fctx.data.raw_values
81
+ );
56
82
  return {
57
83
  ...original,
58
84
  name: this.field.name + "[new]",
@@ -1,13 +1,18 @@
1
1
  import Router from "@koa/router";
2
2
  import { Context } from "koa";
3
3
  import { FlatTemplatable } from "tempstream";
4
- import { FormDataValue, FormMessage } from "../form-types.js";
4
+ import { FormMessage, FormData } from "../form-types.js";
5
5
  import type { Form } from "../form.js";
6
6
 
7
+ export type FieldMessages<Fieldnames extends string = string> = Record<
8
+ Fieldnames,
9
+ { type: "error" | "info"; message: string }
10
+ >;
11
+
7
12
  export class FormControlContext {
8
13
  constructor(
9
14
  public ctx: Context,
10
- public data: Record<string, FormDataValue>,
15
+ public data: FormData,
11
16
  public messages: FormMessage[],
12
17
  public field_name_prefix: string,
13
18
  public form_id: string,
@@ -10,7 +10,10 @@ export class HiddenInput extends FormFieldControl {
10
10
  }
11
11
 
12
12
  async render(fctx: FormControlContext): Promise<FlatTemplatable> {
13
- const { raw } = await this.field.getValue(fctx.ctx, fctx.data);
13
+ const { raw } = await this.field.getParsedValue(
14
+ fctx.ctx,
15
+ fctx.data.raw_values
16
+ );
14
17
  return tempstream`<input type="hidden" name="${
15
18
  this.field.name
16
19
  }" value="${attribute((raw || "").toString())}" form="${
@@ -7,8 +7,7 @@ import { mount } from "../../mount.js";
7
7
  import { Form } from "../form.js";
8
8
  import { getBrowser } from "../../utils/browser-creator.js";
9
9
  import { Fields } from "../../index.js";
10
- import { Photo } from "./photo.js";
11
- import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
10
+ import { Image } from "./image.js";
12
11
 
13
12
  import _locreq from "locreq";
14
13
  import { module_dirname } from "../../utils/module-dirname.js";
@@ -33,25 +32,17 @@ describe("photo-control", () => {
33
32
  const router = new Router();
34
33
 
35
34
  const fields = {
36
- photo: new Fields.File(false, new FileManager("/tmp", "/uploaded_files")),
35
+ photo: new Fields.File(false),
37
36
  };
38
37
 
39
38
  let received_photo: unknown;
40
39
 
41
- const imageRouter = new KoaResponsiveImageRouter({
42
- staticPath: "/images",
43
- thumbnailSize: 20,
44
- cacheManagerResolutionThreshold: 50,
45
- imageStoragePath: `/tmp/image-cache-${port}`,
46
- smartCropStoragePath: `/tmp/smartcrop-storage-${port}`,
47
- });
48
-
49
40
  mount(
50
41
  router,
51
42
  "/",
52
43
  new (class extends Form<typeof fields, unknown> {
53
44
  fields = fields;
54
- controls = [new Photo(fields.photo, imageRouter)];
45
+ controls = [new Image(fields.photo)];
55
46
 
56
47
  async onSubmit(ctx: Context) {
57
48
  const data = await this.getParsedValues(ctx);
@@ -92,19 +83,11 @@ describe("photo-control", () => {
92
83
  const router = new Router();
93
84
 
94
85
  const fields = {
95
- photo: new Fields.File(true, new FileManager("/tmp", "/uploaded_files")),
86
+ photo: new Fields.File(true),
96
87
  };
97
88
 
98
89
  let received_photo: unknown;
99
90
 
100
- const imageRouter = new KoaResponsiveImageRouter({
101
- staticPath: "/images",
102
- thumbnailSize: 20,
103
- cacheManagerResolutionThreshold: 50,
104
- imageStoragePath: `/tmp/image-cache-${port}`,
105
- smartCropStoragePath: `/tmp/smartcrop-storage-${port}`,
106
- });
107
-
108
91
  let submit_called = false;
109
92
 
110
93
  mount(
@@ -112,7 +95,7 @@ describe("photo-control", () => {
112
95
  "/",
113
96
  new (class extends Form<typeof fields, unknown> {
114
97
  fields = fields;
115
- controls = [new Photo(fields.photo, imageRouter)];
98
+ controls = [new Image(fields.photo)];
116
99
 
117
100
  async onSubmit(ctx: Context) {
118
101
  submit_called = true;
@@ -5,13 +5,11 @@ import { FormField } from "../fields/field.js";
5
5
  import { SimpleInputOptions } from "./simple-input.js";
6
6
  import { FormControlContext } from "./form-control.js";
7
7
  import { FileContainer } from "../fields/file.js";
8
- import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
9
8
  import { FilePointer } from "@sealcode/file-manager";
10
9
 
11
- export class Photo extends File {
10
+ export class Image extends File {
12
11
  constructor(
13
12
  public field: FormField<boolean, FileContainer>,
14
- public imageRouter: KoaResponsiveImageRouter,
15
13
  options?: SimpleInputOptions
16
14
  ) {
17
15
  super(field, options);
@@ -22,7 +20,7 @@ export class Photo extends File {
22
20
  }
23
21
 
24
22
  async renderFilePreview(
25
- _ctx: Context,
23
+ ctx: Context,
26
24
  file: FilePointer | null
27
25
  ): Promise<FlatTemplatable> {
28
26
  const class_name = "file_preview";
@@ -31,7 +29,7 @@ export class Photo extends File {
31
29
  return empty_container;
32
30
  }
33
31
  return tempstream/* HTML */ `<div class="${class_name}">
34
- ${this.imageRouter.image(await file.getPath(), {
32
+ ${ctx.$app.imageRouter.image(await file.getPath(), {
35
33
  resolutions: [100, 200],
36
34
  sizesAttr: "100px",
37
35
  crop: { width: 100, height: 100 },
@@ -151,7 +151,7 @@ export class MultipleFiles extends FormFieldControl {
151
151
  if (!token) {
152
152
  return null;
153
153
  }
154
- return await item.collection.app.FileManager.fromToken(token);
154
+ return await item.collection.app.fileManager.fromToken(token);
155
155
  }
156
156
 
157
157
  async renderFileItemPreview(
@@ -255,4 +255,21 @@ export class MultipleFiles extends FormFieldControl {
255
255
  `
256
256
  );
257
257
  }
258
+
259
+ setLabel(label: string) {
260
+ this.options.label = label;
261
+ }
262
+
263
+ setUploadLabel(label: string) {
264
+ this.options.uploadLabel = label;
265
+ }
266
+
267
+ setAdditionalFieldsGetter(
268
+ fn: (
269
+ ctx: Context,
270
+ file: FilePointer
271
+ ) => Promise<Record<string, unknown>>
272
+ ) {
273
+ this.options.getAdditionalFields = fn;
274
+ }
258
275
  }
@@ -5,7 +5,7 @@ import { MultipleFiles, MultipleFilesOptions } from "./multiple-files.js";
5
5
  import { MultipleFiles as MultipleFilesField } from "../fields/multiple-files.js";
6
6
  import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
7
7
 
8
- export class MultiplePhotos extends MultipleFiles {
8
+ export class MultipleImages extends MultipleFiles {
9
9
  constructor(
10
10
  public field: MultipleFilesField,
11
11
  public imageRouter: KoaResponsiveImageRouter,
@@ -4,7 +4,7 @@ import { SimpleInput, SimpleInputOptions } from "./simple-input.js";
4
4
 
5
5
  export type NumberOptions = SimpleInputOptions & Partial<{ step: number }>;
6
6
 
7
- export class Number extends SimpleInput<number | null> {
7
+ export class Number extends SimpleInput {
8
8
  field: NumberField;
9
9
  options: NumberOptions;
10
10
  constructor(field: NumberField, options: NumberOptions) {
@@ -12,36 +12,20 @@ export type SimpleInputOptions = {
12
12
  label?: string;
13
13
  autocomplete?: boolean;
14
14
  hide_errors?: boolean;
15
- type?:
16
- | "color"
17
- | "date"
18
- | "email"
19
- | "file"
20
- | "month"
21
- | "number"
22
- | "password"
23
- | "search"
24
- | "tel"
25
- | "text"
26
- | "time"
27
- | "url"
28
- | "week";
15
+ type?: string;
29
16
  value?: string;
30
17
  placeholder?: string;
31
18
  readonly?: boolean;
32
19
  step?: number;
33
20
  suffix?: string;
21
+ pattern?: string;
34
22
  };
35
23
 
36
24
  export class SimpleInput<
37
- ParsedValue,
38
25
  Options extends SimpleInputOptions = SimpleInputOptions
39
26
  > extends FormFieldControl {
40
27
  options: SimpleInputOptions;
41
- constructor(
42
- public field: FormField<boolean, ParsedValue>,
43
- options?: Options
44
- ) {
28
+ constructor(public field: FormField<boolean, any>, options?: Options) {
45
29
  super([field]);
46
30
  this.options = options || {};
47
31
  }
@@ -78,29 +62,23 @@ export class SimpleInput<
78
62
  ): Promise<Record<string, string | boolean>> {
79
63
  const readonly = this.options.readonly || false;
80
64
  const required = this.field.required;
81
- const { parsed, raw, valid } = await this.field.getValue(
65
+ const { raw, valid } = await this.field.getParsedValue(
82
66
  fctx.ctx,
83
- fctx.data,
67
+ fctx.data.raw_values,
84
68
  true
85
69
  );
86
70
  return Object.fromEntries([
87
71
  <const>["id", this.getID()],
88
72
  <const>["type", this.getType()],
89
73
  <const>["name", `${fctx.field_name_prefix}${this.field.name}`],
90
- <const>[
91
- "value",
92
- !valid && raw
93
- ? raw.toString()
94
- : parsed !== undefined && parsed !== null
95
- ? (parsed as string)?.toString() || ""
96
- : "",
97
- ],
74
+ <const>["value", raw],
98
75
  ...(fctx.form_id ? [["form", fctx.form_id]] : []),
99
76
  <const>["placeholder", this.getPlaceholder()],
100
77
  ...(readonly ? [["readonly", true]] : []),
101
78
  ...(required ? [["required", true]] : []),
102
79
  ...(!this.options.autocomplete ? [["autocomplete", "off"]] : []),
103
80
  ...(this.options.step ? [["step", this.options.step]] : []),
81
+ ["aria-invalid", String(!valid)],
104
82
  ]) as Record<string, string>;
105
83
  }
106
84
 
@@ -131,9 +109,9 @@ export class SimpleInput<
131
109
  const id = this.getID();
132
110
  const label = this.getLabel();
133
111
 
134
- const { valid, message } = await this.field.getValue(
112
+ const { valid, message } = await this.field.getParsedValue(
135
113
  fctx.ctx,
136
- fctx.data,
114
+ fctx.data.raw_values,
137
115
  true
138
116
  );
139
117
  return inputWrapper(
@@ -141,15 +119,21 @@ export class SimpleInput<
141
119
  this.getWrapperModifiers(),
142
120
  tempstream/* HTML */ `
143
121
  ${label ? `<label for="${id}">${label}</label>` : ""}
144
- ${await this.preInput(fctx, fctx.data)}
122
+ ${await this.preInput(fctx, fctx.data.raw_values)}
145
123
  ${this.renderInput(
146
124
  fctx.ctx,
147
125
  renderAttributes(await this.getInputAttributes(fctx)),
148
- fctx.data
126
+ fctx.data.raw_values
149
127
  )}
150
128
  ${this.postInput(fctx.ctx)}
151
129
  ${~valid && !this.options.hide_errors && fctx.validate
152
- ? `<div class="input__error">${message}</div>`
130
+ ? `<div class="input__error">${[
131
+ message,
132
+ fctx.data.field_messages?.[this.field.name]
133
+ ?.message,
134
+ ]
135
+ .filter((e) => !!e)
136
+ .join(" · ")}</div>`
153
137
  : ""}
154
138
  `
155
139
  );
@@ -1,10 +1,11 @@
1
- import SealiousSingleReference from "sealious/@types/app/base-chips/field-types/single-reference.js";
1
+ import { FieldTypes as SealiousFieldTypes } from "sealious";
2
2
  import { CollectionField } from "../fields/collection-field.js";
3
3
  import { DropdownOptions, FreeformDropdown } from "./dropdown.js";
4
4
  import { Collection, CollectionItem } from "sealious";
5
5
 
6
6
  export class SingleReferenceDropdown<
7
- F extends SealiousSingleReference,
7
+ TargetCollection extends Collection,
8
+ F extends SealiousFieldTypes.SingleReference,
8
9
  Required extends boolean
9
10
  > extends FreeformDropdown {
10
11
  constructor(
@@ -38,4 +39,11 @@ export class SingleReferenceDropdown<
38
39
  options
39
40
  );
40
41
  }
42
+
43
+ setOptionLabelGetter(
44
+ getter: (item: CollectionItem<TargetCollection>) => string
45
+ ): this {
46
+ this.options.getLabel = getter;
47
+ return this;
48
+ }
41
49
  }