@cosmicdrift/kumiko-renderer 0.388.0 → 0.390.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 (379) hide show
  1. package/dist/app/base-path-context.d.ts +9 -0
  2. package/dist/app/base-path-context.js +13 -0
  3. package/dist/app/base-path.d.ts +3 -0
  4. package/dist/app/base-path.js +27 -0
  5. package/dist/app/config-edit-body.d.ts +1 -1
  6. package/dist/app/config-edit-body.js +15 -6
  7. package/dist/app/config-edit-without-secret-fields.d.ts +2 -0
  8. package/dist/app/config-edit-without-secret-fields.js +28 -0
  9. package/dist/app/entity-list-facet-specs.d.ts +3 -0
  10. package/dist/app/entity-list-facet-specs.js +65 -0
  11. package/dist/app/entity-list-screen.js +74 -206
  12. package/dist/app/kumiko-screen.js +6 -14
  13. package/dist/app/list-bulk-actions.d.ts +18 -0
  14. package/dist/app/list-bulk-actions.js +54 -0
  15. package/dist/app/locked-screen-header.d.ts +9 -0
  16. package/dist/app/locked-screen-header.js +33 -0
  17. package/dist/app/projection-detail-body.js +59 -394
  18. package/dist/app/projection-detail-header-model.d.ts +11 -0
  19. package/dist/app/projection-detail-header-model.js +33 -0
  20. package/dist/app/projection-detail-header-region.d.ts +28 -0
  21. package/dist/app/projection-detail-header-region.js +81 -0
  22. package/dist/app/projection-detail-header.d.ts +29 -0
  23. package/dist/app/projection-detail-header.js +84 -0
  24. package/dist/app/projection-detail-navigation.d.ts +13 -0
  25. package/dist/app/projection-detail-navigation.js +91 -0
  26. package/dist/app/projection-detail-states.d.ts +22 -0
  27. package/dist/app/projection-detail-states.js +26 -0
  28. package/dist/app/projection-drawer-host.d.ts +12 -0
  29. package/dist/app/projection-drawer-host.js +10 -0
  30. package/dist/app/projection-list-body.d.ts +1 -1
  31. package/dist/app/projection-list-body.js +82 -197
  32. package/dist/app/projection-list-render-props.d.ts +56 -0
  33. package/dist/app/projection-list-render-props.js +47 -0
  34. package/dist/app/projection-list-render.d.ts +26 -0
  35. package/dist/app/projection-list-render.js +20 -0
  36. package/dist/app/projection-list-row-click.d.ts +12 -0
  37. package/dist/app/projection-list-row-click.js +14 -0
  38. package/dist/app/row-actions.d.ts +3 -0
  39. package/dist/app/row-actions.js +10 -5
  40. package/dist/app/screen-shared.js +9 -2
  41. package/dist/app/use-entity-range-facets.d.ts +24 -0
  42. package/dist/app/use-entity-range-facets.js +64 -0
  43. package/dist/app/use-projection-date-range.d.ts +12 -0
  44. package/dist/app/use-projection-date-range.js +21 -0
  45. package/dist/app/use-projection-detail-actions.d.ts +35 -0
  46. package/dist/app/use-projection-detail-actions.js +156 -0
  47. package/dist/app/use-projection-detail-data.d.ts +19 -0
  48. package/dist/app/use-projection-detail-data.js +47 -0
  49. package/dist/app/use-projection-detail-layout.d.ts +17 -0
  50. package/dist/app/use-projection-detail-layout.js +23 -0
  51. package/dist/app/use-projection-list-actions.d.ts +31 -0
  52. package/dist/app/use-projection-list-actions.js +73 -0
  53. package/dist/app/use-projection-list-data.d.ts +20 -0
  54. package/dist/app/use-projection-list-data.js +26 -0
  55. package/dist/app/use-projection-list-definitions.d.ts +11 -0
  56. package/dist/app/use-projection-list-definitions.js +20 -0
  57. package/dist/app/use-projection-list-query.d.ts +28 -0
  58. package/dist/app/use-projection-list-query.js +83 -0
  59. package/dist/app/use-screen-list-rows.d.ts +37 -0
  60. package/dist/app/use-screen-list-rows.js +104 -0
  61. package/dist/app/use-screen-list-table.d.ts +24 -0
  62. package/dist/app/use-screen-list-table.js +46 -0
  63. package/dist/components/list-group-page-bridges.d.ts +3 -0
  64. package/dist/components/list-group-page-bridges.js +31 -0
  65. package/dist/components/list-state-store.d.ts +16 -0
  66. package/dist/components/list-state-store.js +31 -0
  67. package/dist/components/related-list-section.js +37 -89
  68. package/dist/components/render-edit-banners.d.ts +12 -0
  69. package/dist/components/render-edit-banners.js +90 -0
  70. package/dist/components/render-edit-draft-save-helpers.d.ts +19 -0
  71. package/dist/components/render-edit-draft-save-helpers.js +42 -0
  72. package/dist/components/render-edit-field-grid.d.ts +4 -0
  73. package/dist/components/render-edit-field-grid.js +40 -0
  74. package/dist/components/render-edit-fields-section.d.ts +4 -0
  75. package/dist/components/render-edit-fields-section.js +76 -0
  76. package/dist/components/render-edit-form-actions.d.ts +4 -0
  77. package/dist/components/render-edit-form-actions.js +66 -0
  78. package/dist/components/render-edit-header-actions.d.ts +11 -0
  79. package/dist/components/render-edit-header-actions.js +120 -0
  80. package/dist/components/render-edit-layout-flags.d.ts +29 -0
  81. package/dist/components/render-edit-layout-flags.js +106 -0
  82. package/dist/components/render-edit-layout.d.ts +4 -0
  83. package/dist/components/render-edit-layout.js +79 -0
  84. package/dist/components/render-edit-render-model.d.ts +63 -0
  85. package/dist/components/render-edit-render-model.js +14 -0
  86. package/dist/components/render-edit-section-kinds.d.ts +4 -0
  87. package/dist/components/render-edit-section-kinds.js +115 -0
  88. package/dist/components/render-edit-submit-result.d.ts +8 -0
  89. package/dist/components/render-edit-submit-result.js +77 -0
  90. package/dist/components/render-edit-submit.d.ts +7 -0
  91. package/dist/components/render-edit-submit.js +113 -0
  92. package/dist/components/render-edit-titles.d.ts +17 -0
  93. package/dist/components/render-edit-titles.js +99 -0
  94. package/dist/components/render-edit-wizard-navigation.d.ts +11 -0
  95. package/dist/components/render-edit-wizard-navigation.js +115 -0
  96. package/dist/components/render-edit.d.ts +2 -2
  97. package/dist/components/render-edit.js +63 -1128
  98. package/dist/components/render-field-choice-inputs.d.ts +7 -0
  99. package/dist/components/render-field-choice-inputs.js +52 -0
  100. package/dist/components/render-field-control.d.ts +12 -0
  101. package/dist/components/render-field-control.js +93 -0
  102. package/dist/components/render-field-display-text.d.ts +4 -0
  103. package/dist/components/render-field-display-text.js +48 -0
  104. package/dist/components/render-field-fill-action.d.ts +13 -0
  105. package/dist/components/render-field-fill-action.js +63 -0
  106. package/dist/components/render-field-input-shared.d.ts +39 -0
  107. package/dist/components/render-field-input-shared.js +20 -0
  108. package/dist/components/render-field-input.d.ts +3 -0
  109. package/dist/components/render-field-input.js +34 -0
  110. package/dist/components/render-field-meta.d.ts +6 -0
  111. package/dist/components/render-field-meta.js +51 -0
  112. package/dist/components/render-field-read-only.d.ts +11 -0
  113. package/dist/components/render-field-read-only.js +75 -0
  114. package/dist/components/render-field-reference.d.ts +15 -0
  115. package/dist/components/render-field-reference.js +103 -0
  116. package/dist/components/render-field-scalar-inputs.d.ts +10 -0
  117. package/dist/components/render-field-scalar-inputs.js +35 -0
  118. package/dist/components/render-field-text-inputs.d.ts +3 -0
  119. package/dist/components/render-field-text-inputs.js +34 -0
  120. package/dist/components/render-field-values.d.ts +18 -0
  121. package/dist/components/render-field-values.js +111 -0
  122. package/dist/components/render-field-write-only.d.ts +9 -0
  123. package/dist/components/render-field-write-only.js +29 -0
  124. package/dist/components/render-field.d.ts +2 -2
  125. package/dist/components/render-field.js +39 -669
  126. package/dist/components/render-list-header-slot.d.ts +5 -0
  127. package/dist/components/render-list-header-slot.js +30 -0
  128. package/dist/components/render-list-reference-bridge.d.ts +3 -0
  129. package/dist/components/render-list-reference-bridge.js +25 -0
  130. package/dist/components/render-list-reference-columns.d.ts +25 -0
  131. package/dist/components/render-list-reference-columns.js +137 -0
  132. package/dist/components/render-list-table-props.d.ts +52 -0
  133. package/dist/components/render-list-table-props.js +53 -0
  134. package/dist/components/render-list-toolbar-action.d.ts +27 -0
  135. package/dist/components/render-list-toolbar-action.js +40 -0
  136. package/dist/components/render-list-toolbar-model.d.ts +42 -0
  137. package/dist/components/render-list-toolbar-model.js +82 -0
  138. package/dist/components/render-list-toolbar.d.ts +38 -0
  139. package/dist/components/render-list-toolbar.js +40 -0
  140. package/dist/components/render-list-types.d.ts +113 -0
  141. package/dist/components/render-list-types.js +1 -0
  142. package/dist/components/render-list.d.ts +5 -130
  143. package/dist/components/render-list.js +95 -319
  144. package/dist/components/use-reference-input-state.d.ts +20 -0
  145. package/dist/components/use-reference-input-state.js +85 -0
  146. package/dist/components/use-render-edit-controlled-sync.d.ts +3 -0
  147. package/dist/components/use-render-edit-controlled-sync.js +26 -0
  148. package/dist/components/use-render-edit-draft-save.d.ts +29 -0
  149. package/dist/components/use-render-edit-draft-save.js +141 -0
  150. package/dist/components/use-render-edit-form.d.ts +10 -0
  151. package/dist/components/use-render-edit-form.js +101 -0
  152. package/dist/components/use-render-edit-sections.d.ts +15 -0
  153. package/dist/components/use-render-edit-sections.js +100 -0
  154. package/dist/components/use-render-edit-state.d.ts +65 -0
  155. package/dist/components/use-render-edit-state.js +158 -0
  156. package/dist/components/use-render-edit-steps.d.ts +13 -0
  157. package/dist/components/use-render-edit-steps.js +52 -0
  158. package/dist/components/use-render-list-columns.d.ts +18 -0
  159. package/dist/components/use-render-list-columns.js +41 -0
  160. package/dist/components/use-render-list-search.d.ts +4 -0
  161. package/dist/components/use-render-list-search.js +50 -0
  162. package/dist/current-user.d.ts +2 -0
  163. package/dist/data-table-aggregate-types.d.ts +47 -0
  164. package/dist/data-table-aggregate-types.js +1 -0
  165. package/dist/data-table-bulk-types.d.ts +27 -0
  166. package/dist/data-table-bulk-types.js +1 -0
  167. package/dist/data-table-facet-types.d.ts +36 -0
  168. package/dist/data-table-facet-types.js +1 -0
  169. package/dist/data-table-view-types.d.ts +73 -0
  170. package/dist/data-table-view-types.js +1 -0
  171. package/dist/headless/view-model/edit.js +3 -1
  172. package/dist/headless/view-model/types.d.ts +4 -2
  173. package/dist/hooks/list-column-layout.d.ts +19 -0
  174. package/dist/hooks/list-column-layout.js +36 -0
  175. package/dist/hooks/list-group-pages.d.ts +26 -0
  176. package/dist/hooks/list-group-pages.js +37 -0
  177. package/dist/hooks/list-reset.d.ts +8 -0
  178. package/dist/hooks/list-reset.js +15 -0
  179. package/dist/hooks/list-server-groups.d.ts +39 -0
  180. package/dist/hooks/list-server-groups.js +84 -0
  181. package/dist/hooks/list-state-schema.d.ts +28 -0
  182. package/dist/hooks/list-state-schema.js +76 -0
  183. package/dist/hooks/use-bulk-run.d.ts +41 -0
  184. package/dist/hooks/use-bulk-run.js +65 -0
  185. package/dist/hooks/use-group-load-state.d.ts +11 -0
  186. package/dist/hooks/use-group-load-state.js +31 -0
  187. package/dist/hooks/use-list-aggregates.d.ts +38 -0
  188. package/dist/hooks/use-list-aggregates.js +107 -0
  189. package/dist/hooks/use-list-table.d.ts +38 -0
  190. package/dist/hooks/use-list-table.js +91 -0
  191. package/dist/hooks/use-list-view-state.d.ts +43 -0
  192. package/dist/hooks/use-list-view-state.js +161 -0
  193. package/dist/hooks/use-related-list-rows.d.ts +27 -0
  194. package/dist/hooks/use-related-list-rows.js +81 -0
  195. package/dist/hooks/use-related-list-state.d.ts +15 -0
  196. package/dist/hooks/use-related-list-state.js +31 -0
  197. package/dist/hooks/use-remembered-list-params.d.ts +13 -0
  198. package/dist/hooks/use-remembered-list-params.js +53 -0
  199. package/dist/hooks/use-remembered-local-list-state.d.ts +26 -0
  200. package/dist/hooks/use-remembered-local-list-state.js +63 -0
  201. package/dist/i18n-defaults.js +53 -0
  202. package/dist/index.d.ts +3 -1
  203. package/dist/index.js +2 -0
  204. package/dist/primitives.d.ts +11 -47
  205. package/dist/web/app/create-app.d.ts +5 -0
  206. package/dist/web/app/create-app.js +7 -4
  207. package/dist/web/app/dashboard-body.d.ts +1 -1
  208. package/dist/web/app/dashboard-body.js +42 -246
  209. package/dist/web/app/dashboard-header.d.ts +34 -0
  210. package/dist/web/app/dashboard-header.js +58 -0
  211. package/dist/web/app/dashboard-screen-controls.d.ts +11 -0
  212. package/dist/web/app/dashboard-screen-controls.js +42 -0
  213. package/dist/web/app/dashboard-screen-tiles.d.ts +8 -0
  214. package/dist/web/app/dashboard-screen-tiles.js +42 -0
  215. package/dist/web/app/dashboard-visibility.d.ts +42 -0
  216. package/dist/web/app/dashboard-visibility.js +102 -0
  217. package/dist/web/app/history-leave-guard.d.ts +6 -0
  218. package/dist/web/app/history-leave-guard.js +115 -0
  219. package/dist/web/app/list-state-store-boot.d.ts +6 -0
  220. package/dist/web/app/list-state-store-boot.js +15 -0
  221. package/dist/web/app/nav.js +7 -54
  222. package/dist/web/app/session-list-state-store.d.ts +15 -0
  223. package/dist/web/app/session-list-state-store.js +117 -0
  224. package/dist/web/app/use-dashboard-screen-state.d.ts +35 -0
  225. package/dist/web/app/use-dashboard-screen-state.js +69 -0
  226. package/dist/web/index.d.ts +1 -0
  227. package/dist/web/index.js +1 -0
  228. package/dist/web/lib/export-xlsx-request.d.ts +11 -0
  229. package/dist/web/lib/export-xlsx-request.js +46 -0
  230. package/dist/web/primitives/data-table/actions-column.d.ts +16 -0
  231. package/dist/web/primitives/data-table/actions-column.js +35 -0
  232. package/dist/web/primitives/data-table/bulk-selection-bar.d.ts +20 -0
  233. package/dist/web/primitives/data-table/bulk-selection-bar.js +37 -0
  234. package/dist/web/primitives/data-table/card-body.d.ts +6 -0
  235. package/dist/web/primitives/data-table/card-body.js +32 -0
  236. package/dist/web/primitives/data-table/card-row.d.ts +5 -0
  237. package/dist/web/primitives/data-table/card-row.js +31 -0
  238. package/dist/web/primitives/data-table/card-sort-select.d.ts +14 -0
  239. package/dist/web/primitives/data-table/card-sort-select.js +40 -0
  240. package/dist/web/primitives/data-table/card-view.d.ts +3 -0
  241. package/dist/web/primitives/data-table/card-view.js +13 -0
  242. package/dist/web/primitives/data-table/column-layout-mode.d.ts +5 -0
  243. package/dist/web/primitives/data-table/column-layout-mode.js +10 -0
  244. package/dist/web/primitives/data-table/column-picker-section.d.ts +7 -0
  245. package/dist/web/primitives/data-table/column-picker-section.js +35 -0
  246. package/dist/web/primitives/data-table/column-resize-handle.d.ts +14 -0
  247. package/dist/web/primitives/data-table/column-resize-handle.js +48 -0
  248. package/dist/web/primitives/data-table/data-cell-props.d.ts +7 -0
  249. package/dist/web/primitives/data-table/data-cell-props.js +8 -0
  250. package/dist/web/primitives/data-table/density.d.ts +14 -0
  251. package/dist/web/primitives/data-table/density.js +20 -0
  252. package/dist/web/primitives/data-table/export-button.d.ts +5 -0
  253. package/dist/web/primitives/data-table/export-button.js +37 -0
  254. package/dist/web/primitives/data-table/facet-cluster.d.ts +8 -0
  255. package/dist/web/primitives/data-table/facet-cluster.js +37 -0
  256. package/dist/web/primitives/data-table/group-band.d.ts +28 -0
  257. package/dist/web/primitives/data-table/group-band.js +53 -0
  258. package/dist/web/primitives/data-table/measure-value.d.ts +10 -0
  259. package/dist/web/primitives/data-table/measure-value.js +28 -0
  260. package/dist/web/primitives/data-table/pin-section.d.ts +8 -0
  261. package/dist/web/primitives/data-table/pin-section.js +20 -0
  262. package/dist/web/primitives/data-table/reset-all-button.d.ts +4 -0
  263. package/dist/web/primitives/data-table/reset-all-button.js +8 -0
  264. package/dist/web/primitives/data-table/row-render-parts.d.ts +8 -0
  265. package/dist/web/primitives/data-table/row-render-parts.js +35 -0
  266. package/dist/web/primitives/data-table/server-group-header.d.ts +11 -0
  267. package/dist/web/primitives/data-table/server-group-header.js +51 -0
  268. package/dist/web/primitives/data-table/sortable-header.d.ts +17 -0
  269. package/dist/web/primitives/data-table/sortable-header.js +41 -0
  270. package/dist/web/primitives/data-table/table-body.d.ts +3 -0
  271. package/dist/web/primitives/data-table/table-body.js +32 -0
  272. package/dist/web/primitives/data-table/table-chrome.d.ts +13 -0
  273. package/dist/web/primitives/data-table/table-chrome.js +30 -0
  274. package/dist/web/primitives/data-table/table-content.d.ts +3 -0
  275. package/dist/web/primitives/data-table/table-content.js +41 -0
  276. package/dist/web/primitives/data-table/table-data-cell.d.ts +4 -0
  277. package/dist/web/primitives/data-table/table-data-cell.js +25 -0
  278. package/dist/web/primitives/data-table/table-footer.d.ts +7 -0
  279. package/dist/web/primitives/data-table/table-footer.js +20 -0
  280. package/dist/web/primitives/data-table/table-header-row.d.ts +3 -0
  281. package/dist/web/primitives/data-table/table-header-row.js +21 -0
  282. package/dist/web/primitives/data-table/table-view.d.ts +3 -0
  283. package/dist/web/primitives/data-table/table-view.js +25 -0
  284. package/dist/web/primitives/data-table/toolbar-end-cluster.d.ts +10 -0
  285. package/dist/web/primitives/data-table/toolbar-end-cluster.js +13 -0
  286. package/dist/web/primitives/data-table/toolbar.d.ts +6 -0
  287. package/dist/web/primitives/data-table/toolbar.js +53 -0
  288. package/dist/web/primitives/data-table/totals-footer.d.ts +24 -0
  289. package/dist/web/primitives/data-table/totals-footer.js +48 -0
  290. package/dist/web/primitives/data-table/use-bulk-selection.d.ts +21 -0
  291. package/dist/web/primitives/data-table/use-bulk-selection.js +66 -0
  292. package/dist/web/primitives/data-table/use-column-pins.d.ts +32 -0
  293. package/dist/web/primitives/data-table/use-column-pins.js +117 -0
  294. package/dist/web/primitives/data-table/use-column-sizing.d.ts +22 -0
  295. package/dist/web/primitives/data-table/use-column-sizing.js +44 -0
  296. package/dist/web/primitives/data-table/use-data-table-state.d.ts +44 -0
  297. package/dist/web/primitives/data-table/use-data-table-state.js +123 -0
  298. package/dist/web/primitives/data-table/use-measured-column-widths.d.ts +15 -0
  299. package/dist/web/primitives/data-table/use-measured-column-widths.js +83 -0
  300. package/dist/web/primitives/data-table/use-row-keyboard-navigation.d.ts +22 -0
  301. package/dist/web/primitives/data-table/use-row-keyboard-navigation.js +65 -0
  302. package/dist/web/primitives/data-table/use-row-selection.d.ts +14 -0
  303. package/dist/web/primitives/data-table/use-row-selection.js +48 -0
  304. package/dist/web/primitives/data-table/use-view-columns.d.ts +6 -0
  305. package/dist/web/primitives/data-table/use-view-columns.js +17 -0
  306. package/dist/web/primitives/data-table/view-menu.d.ts +8 -0
  307. package/dist/web/primitives/data-table/view-menu.js +45 -0
  308. package/dist/web/primitives/data-table-cell.d.ts +0 -22
  309. package/dist/web/primitives/data-table-cell.js +1 -58
  310. package/dist/web/primitives/data-table.d.ts +3 -4
  311. package/dist/web/primitives/data-table.js +30 -272
  312. package/dist/web/primitives/file-value-list.d.ts +1 -1
  313. package/dist/web/primitives/file-value-list.js +5 -5
  314. package/dist/web/primitives/form-footer-parts.d.ts +25 -0
  315. package/dist/web/primitives/form-footer-parts.js +55 -0
  316. package/dist/web/primitives/form.js +33 -43
  317. package/dist/web/primitives/input-choice-kinds.d.ts +4 -0
  318. package/dist/web/primitives/input-choice-kinds.js +67 -0
  319. package/dist/web/primitives/input-file-kinds.d.ts +3 -0
  320. package/dist/web/primitives/input-file-kinds.js +6 -0
  321. package/dist/web/primitives/input-number-kinds.d.ts +4 -0
  322. package/dist/web/primitives/input-number-kinds.js +16 -0
  323. package/dist/web/primitives/input-optional-props.d.ts +20 -0
  324. package/dist/web/primitives/input-optional-props.js +24 -0
  325. package/dist/web/primitives/input-select-presentation.d.ts +13 -0
  326. package/dist/web/primitives/input-select-presentation.js +19 -0
  327. package/dist/web/primitives/input-shared.d.ts +22 -0
  328. package/dist/web/primitives/input-shared.js +10 -0
  329. package/dist/web/primitives/input-temporal-kinds.d.ts +5 -0
  330. package/dist/web/primitives/input-temporal-kinds.js +10 -0
  331. package/dist/web/primitives/input-text-kinds.d.ts +7 -0
  332. package/dist/web/primitives/input-text-kinds.js +33 -0
  333. package/dist/web/primitives/input.js +35 -161
  334. package/dist/web/primitives/number-range-facet.d.ts +7 -0
  335. package/dist/web/primitives/number-range-facet.js +33 -0
  336. package/dist/web/widgets/bounded-load-cache.d.ts +5 -1
  337. package/dist/web/widgets/bounded-load-cache.js +48 -26
  338. package/dist/web/widgets/chart-data.d.ts +35 -0
  339. package/dist/web/widgets/chart-data.js +37 -0
  340. package/dist/web/widgets/chart-markers.d.ts +26 -0
  341. package/dist/web/widgets/chart-markers.js +64 -0
  342. package/dist/web/widgets/chart-parts.d.ts +20 -0
  343. package/dist/web/widgets/chart-parts.js +15 -0
  344. package/dist/web/widgets/charts.d.ts +5 -78
  345. package/dist/web/widgets/charts.js +7 -485
  346. package/dist/web/widgets/drawer-panel-class.d.ts +3 -0
  347. package/dist/web/widgets/drawer-panel-class.js +40 -0
  348. package/dist/web/widgets/drawer-resize-controls.d.ts +11 -0
  349. package/dist/web/widgets/drawer-resize-controls.js +12 -0
  350. package/dist/web/widgets/drawer-sizing.d.ts +19 -0
  351. package/dist/web/widgets/drawer-sizing.js +60 -0
  352. package/dist/web/widgets/drawer.js +17 -116
  353. package/dist/web/widgets/pdf-preview.js +9 -4
  354. package/dist/web/widgets/stacked-area-brush.d.ts +13 -0
  355. package/dist/web/widgets/stacked-area-brush.js +91 -0
  356. package/dist/web/widgets/stacked-area-chart.d.ts +6 -0
  357. package/dist/web/widgets/stacked-area-chart.js +45 -0
  358. package/dist/web/widgets/stacked-area-chrome.d.ts +7 -0
  359. package/dist/web/widgets/stacked-area-chrome.js +77 -0
  360. package/dist/web/widgets/stacked-area-geometry.d.ts +54 -0
  361. package/dist/web/widgets/stacked-area-geometry.js +83 -0
  362. package/dist/web/widgets/stacked-area-model.d.ts +11 -0
  363. package/dist/web/widgets/stacked-area-model.js +1 -0
  364. package/dist/web/widgets/stacked-area-plot.d.ts +3 -0
  365. package/dist/web/widgets/stacked-area-plot.js +51 -0
  366. package/dist/web/widgets/stacked-area-props.d.ts +83 -0
  367. package/dist/web/widgets/stacked-area-props.js +16 -0
  368. package/dist/web/widgets/stacked-area-svg.d.ts +3 -0
  369. package/dist/web/widgets/stacked-area-svg.js +38 -0
  370. package/dist/web/widgets/stacked-area-tooltip.d.ts +3 -0
  371. package/dist/web/widgets/stacked-area-tooltip.js +86 -0
  372. package/dist/web/widgets/use-drawer-resize.d.ts +22 -0
  373. package/dist/web/widgets/use-drawer-resize.js +52 -0
  374. package/dist/web/widgets/use-stacked-area-tooltip.d.ts +9 -0
  375. package/dist/web/widgets/use-stacked-area-tooltip.js +34 -0
  376. package/dist/web/widgets/use-stacked-area-window.d.ts +20 -0
  377. package/dist/web/widgets/use-stacked-area-window.js +76 -0
  378. package/package.json +9 -9
  379. package/src/changes.json +163 -0
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Checkbox } from "../ui/checkbox.js";
3
+ import { Switch } from "../ui/switch.js";
4
+ import { ComboboxInput } from "./combobox.js";
5
+ import { RadioListSelect, SegmentedSelect, withInlineDisabledHint, withoutSegmentedSelectPlaceholder, } from "./field.js";
6
+ import { stateProps } from "./input-optional-props.js";
7
+ import { resolveSelectPresentation } from "./input-select-presentation.js";
8
+ // layout="inline" (checkbox lists like MultiSelectCheckboxes, the
9
+ // BooleanField widget) keeps the checkbox optics; the standard form
10
+ // field (render-field.tsx, layout="stacked") gets the switch.
11
+ export const renderBooleanKind = (props, { booleanLayout }) => booleanLayout === "inline" ? (_jsx(Checkbox, { id: props.id, name: props.name, disabled: props.disabled, "aria-required": props.required, "aria-invalid": props.hasError === true ? true : undefined, checked: props.value, onCheckedChange: (checked) => props.onChange(checked === true) })) : (_jsx(Switch, { id: props.id, name: props.name, disabled: props.disabled, "aria-required": props.required, "aria-invalid": props.hasError === true ? true : undefined, checked: props.value, onCheckedChange: (checked) => props.onChange(checked === true), className: "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40" }));
12
+ function normalizeSelectOptions(options) {
13
+ return options.map((o) => (typeof o === "string" ? { value: o, label: o } : o));
14
+ }
15
+ // Visual consolidation: all selects go through ComboboxInput
16
+ // (cmdk + Radix popover). Before, there were two paths: Radix
17
+ // Select for `kind:"select"` and cmdk for `kind:"combobox"`. Three
18
+ // visually different variants (single select, combobox single, combobox
19
+ // multi) became unmanageable. With the merge the combobox is the only
20
+ // implementation: the search input is present even for 4-item status
21
+ // selects, a deliberately accepted UX consequence for style consistency.
22
+ export const renderSelectKind = (props) => {
23
+ const comboOptions = normalizeSelectOptions(props.options);
24
+ // The radio group can't render the unselected placeholder as its own
25
+ // segment, so it counts and renders on the real options only — the
26
+ // dropdown below keeps comboOptions (placeholder included) since it
27
+ // has a genuine "nothing selected" row.
28
+ // An author who asks for `display: "radio"` explicitly declared the ""
29
+ // option as a real choice (e.g. "Any"), so it stays a segment.
30
+ const radioGroupOptions = props.display === "radio" ? comboOptions : withoutSegmentedSelectPlaceholder(comboOptions);
31
+ const presentation = resolveSelectPresentation(props, radioGroupOptions);
32
+ if (presentation === "radioList" && radioGroupOptions.length > 0) {
33
+ return (_jsx(RadioListSelect, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, options: radioGroupOptions, ...(props.radioVariant !== undefined && { variant: props.radioVariant }), ...stateProps(props) }));
34
+ }
35
+ if (presentation === "segmented" && radioGroupOptions.length > 0) {
36
+ return (_jsx(SegmentedSelect, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, options: radioGroupOptions, ...stateProps(props) }));
37
+ }
38
+ // The dropdown shows a disabled option's hint inline, so it stays readable in the trigger and search.
39
+ return (_jsx(ComboboxInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, options: comboOptions.map(withInlineDisabledHint), ...stateProps(props) }));
40
+ };
41
+ function comboboxBaseProps(props) {
42
+ return {
43
+ id: props.id,
44
+ name: props.name,
45
+ options: props.options,
46
+ ...stateProps(props),
47
+ ...(props.placeholder !== undefined && { placeholder: props.placeholder }),
48
+ ...(props.searchPlaceholder !== undefined && {
49
+ searchPlaceholder: props.searchPlaceholder,
50
+ }),
51
+ ...(props.emptyText !== undefined && { emptyText: props.emptyText }),
52
+ ...(props.onSearchChange !== undefined && { onSearchChange: props.onSearchChange }),
53
+ ...(props.loading !== undefined && { loading: props.loading }),
54
+ ...(props.onCreate !== undefined && { onCreate: props.onCreate }),
55
+ ...(props.createLabel !== undefined && { createLabel: props.createLabel }),
56
+ };
57
+ }
58
+ // Discriminated union per `multiple`; we split
59
+ // TS-side into two branches so ComboboxInput's single/multi variants
60
+ // render with the right types.
61
+ export const renderComboboxKind = (props) => {
62
+ const baseProps = comboboxBaseProps(props);
63
+ if (props.multiple === true) {
64
+ return _jsx(ComboboxInput, { ...baseProps, multiple: true, value: props.value, onChange: props.onChange });
65
+ }
66
+ return _jsx(ComboboxInput, { ...baseProps, value: props.value, onChange: props.onChange });
67
+ };
@@ -0,0 +1,3 @@
1
+ import type { KindRenderer } from "./input-shared.ts";
2
+ export declare const renderFileKind: KindRenderer<"file" | "image">;
3
+ export declare const renderFilesDropzoneKind: KindRenderer<"files-dropzone">;
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { FileUploadInput } from "./file-upload.js";
3
+ import { FilesDropzoneInput } from "./files-dropzone.js";
4
+ import { uploadTargetProps } from "./input-optional-props.js";
5
+ export const renderFileKind = (props) => (_jsx(FileUploadInput, { kind: props.kind, id: props.id, value: props.value, onChange: props.onChange, ...(props.accept !== undefined && { accept: props.accept }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...uploadTargetProps(props), ...(props.imageVariant !== undefined && { imageVariant: props.imageVariant }), ...(props.capture !== undefined && { capture: props.capture }), ...(props.directory !== undefined && { directory: props.directory }), ...(props.onFilesPicked !== undefined && { onFilesPicked: props.onFilesPicked }), ...(props.pickLabel !== undefined && { pickLabel: props.pickLabel }), ...(props.testId !== undefined && { testId: props.testId }) }));
6
+ export const renderFilesDropzoneKind = (props) => (_jsx(FilesDropzoneInput, { id: props.id, value: props.value, onChange: props.onChange, ...(props.accept !== undefined && { accept: props.accept }), ...(props.maxSize !== undefined && { maxSize: props.maxSize }), ...(props.maxCount !== undefined && { maxCount: props.maxCount }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...uploadTargetProps(props), ...(props.testId !== undefined && { testId: props.testId }) }));
@@ -0,0 +1,4 @@
1
+ import type { KindRenderer } from "./input-shared.ts";
2
+ export declare const renderNumberKind: KindRenderer<"number">;
3
+ export declare const renderRangeKind: KindRenderer<"range">;
4
+ export declare const renderMoneyKind: KindRenderer<"money">;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cn.js";
3
+ import { FIELD_ICON_CLASS, fieldIconFor, unitSuffixId, withInputAddons } from "./field.js";
4
+ import { stateProps } from "./input-optional-props.js";
5
+ import { MoneyInput } from "./money-input.js";
6
+ import { NumberInput } from "./number-input.js";
7
+ export const renderNumberKind = (props) => {
8
+ const NumberIcon = fieldIconFor(props.icon);
9
+ // Icon, input and unit share this one box, and the grid cell sizes the
10
+ // box rather than the bare input: anchored to a wider wrapper, the unit
11
+ // would sit next to a narrower input instead of inside it.
12
+ const numberField = (_jsxs("div", { "data-slot": "number-field", className: "relative", children: [NumberIcon !== undefined && _jsx(NumberIcon, { "aria-hidden": "true", className: FIELD_ICON_CLASS }), _jsx(NumberInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, disabled: props.disabled, required: props.required, hasError: props.hasError, testId: props.testId, ...(props.unit !== undefined && { ariaDescribedBy: unitSuffixId(props.id) }), ...(props.locale !== undefined && { locale: props.locale }), ...(props.grouping !== undefined && { grouping: props.grouping }), ...(props.integer !== undefined && { integer: props.integer }), ...(props.placeholder !== undefined && { placeholder: props.placeholder }), className: cn(NumberIcon !== undefined ? "pl-8" : undefined, props.unit !== undefined ? "pr-8" : undefined) }), props.unit !== undefined && (_jsx("span", { id: unitSuffixId(props.id), className: "pointer-events-none absolute right-2.5 top-1/2 max-w-[40%] -translate-y-1/2 truncate text-sm text-muted-foreground", children: props.unit }))] }));
13
+ return withInputAddons(props, numberField);
14
+ };
15
+ export const renderRangeKind = (props, { common }) => (_jsx("input", { type: "range", ...common, min: props.min, max: props.max, step: props.step ?? 1, value: props.value, onChange: (e) => props.onChange(Number(e.target.value)), className: "w-full accent-primary" }));
16
+ export const renderMoneyKind = (props) => (_jsx(MoneyInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, currency: props.currency ?? "EUR", ...(props.locale !== undefined && { locale: props.locale }), ...stateProps(props) }));
@@ -0,0 +1,20 @@
1
+ type StateInput = {
2
+ readonly disabled?: boolean;
3
+ readonly required?: boolean;
4
+ readonly hasError?: boolean;
5
+ };
6
+ type LocaleBoundsInput = {
7
+ readonly locale?: string;
8
+ readonly min?: string;
9
+ readonly max?: string;
10
+ };
11
+ type UploadTargetInput = {
12
+ readonly entityType?: string;
13
+ readonly uploadActionForm?: string;
14
+ readonly entityId?: string;
15
+ readonly fieldName?: string;
16
+ };
17
+ export declare function stateProps({ disabled, required, hasError }: StateInput): StateInput;
18
+ export declare function localeBoundsProps({ locale, min, max }: LocaleBoundsInput): LocaleBoundsInput;
19
+ export declare function uploadTargetProps({ entityType, uploadActionForm, entityId, fieldName, }: UploadTargetInput): UploadTargetInput;
20
+ export {};
@@ -0,0 +1,24 @@
1
+ // The inputs below take optional props that must be absent, not `undefined`,
2
+ // so a primitive's own defaults still apply.
3
+ export function stateProps({ disabled, required, hasError }) {
4
+ return {
5
+ ...(disabled !== undefined && { disabled }),
6
+ ...(required !== undefined && { required }),
7
+ ...(hasError !== undefined && { hasError }),
8
+ };
9
+ }
10
+ export function localeBoundsProps({ locale, min, max }) {
11
+ return {
12
+ ...(locale !== undefined && { locale }),
13
+ ...(min !== undefined && { min }),
14
+ ...(max !== undefined && { max }),
15
+ };
16
+ }
17
+ export function uploadTargetProps({ entityType, uploadActionForm, entityId, fieldName, }) {
18
+ return {
19
+ ...(entityType !== undefined && { entityType }),
20
+ ...(uploadActionForm !== undefined && { uploadActionForm }),
21
+ ...(entityId !== undefined && { entityId }),
22
+ ...(fieldName !== undefined && { fieldName }),
23
+ };
24
+ }
@@ -0,0 +1,13 @@
1
+ import { defaultSelectPresentation } from "./field.tsx";
2
+ type SelectPresentation = ReturnType<typeof defaultSelectPresentation>;
3
+ type PresentationOption = {
4
+ readonly label: string;
5
+ readonly description?: string;
6
+ readonly group?: string;
7
+ };
8
+ type PresentationRequest = {
9
+ readonly radioVariant?: "list" | "card";
10
+ readonly display?: "radio" | "dropdown";
11
+ };
12
+ export declare function resolveSelectPresentation(request: PresentationRequest, options: readonly PresentationOption[]): SelectPresentation;
13
+ export {};
@@ -0,0 +1,19 @@
1
+ import { defaultSelectPresentation } from "./field.js";
2
+ import { hasDescriptionOrGroup } from "./option-groups.js";
3
+ // An explicit `display` is an author decision and outranks the heuristic in
4
+ // both directions — a requested radio group renders as one even when the
5
+ // options outnumber the heuristic's threshold.
6
+ function requestedSelectPresentation({ radioVariant, display }, options) {
7
+ if (radioVariant === "card")
8
+ return "radioList";
9
+ if (display === "radio")
10
+ return "segmented";
11
+ if (display === "dropdown")
12
+ return "dropdown";
13
+ return defaultSelectPresentation(options);
14
+ }
15
+ // A segmented control has no room for a description line or group headings.
16
+ export function resolveSelectPresentation(request, options) {
17
+ const requested = requestedSelectPresentation(request, options);
18
+ return requested === "segmented" && hasDescriptionOrGroup(options) ? "radioList" : requested;
19
+ }
@@ -0,0 +1,22 @@
1
+ import type { ContextType, ReactNode } from "react";
2
+ import type { InputProps } from "../../index.ts";
3
+ import type { FieldDescriptionContext, FieldLayoutContext } from "./contexts.tsx";
4
+ import type { useFocusOnMount } from "./use-focus-on-mount.ts";
5
+ export type InputKind = InputProps["kind"];
6
+ export type PropsOfKind<K extends InputKind> = InputProps extends infer P ? P extends {
7
+ readonly kind: infer PK;
8
+ } ? K extends PK ? P : never : never : never;
9
+ export declare function commonInputAttrs(props: InputProps, describedBy: ContextType<typeof FieldDescriptionContext>): {
10
+ readonly id: string;
11
+ readonly name: string;
12
+ readonly disabled: boolean | undefined;
13
+ readonly "aria-describedby": string | undefined;
14
+ readonly "aria-required": boolean | undefined;
15
+ readonly "aria-invalid": true | undefined;
16
+ };
17
+ export type DefaultInputShared = {
18
+ readonly common: ReturnType<typeof commonInputAttrs>;
19
+ readonly textInputRef: ReturnType<typeof useFocusOnMount>;
20
+ readonly booleanLayout: ContextType<typeof FieldLayoutContext>;
21
+ };
22
+ export type KindRenderer<K extends InputKind> = (props: PropsOfKind<K>, shared: DefaultInputShared) => ReactNode;
@@ -0,0 +1,10 @@
1
+ export function commonInputAttrs(props, describedBy) {
2
+ return {
3
+ id: props.id,
4
+ name: props.name,
5
+ disabled: props.disabled,
6
+ "aria-describedby": describedBy,
7
+ "aria-required": props.required,
8
+ "aria-invalid": props.hasError === true ? true : undefined,
9
+ };
10
+ }
@@ -0,0 +1,5 @@
1
+ import type { KindRenderer } from "./input-shared.ts";
2
+ export declare const renderDateKind: KindRenderer<"date">;
3
+ export declare const renderTimestampKind: KindRenderer<"timestamp">;
4
+ export declare const renderLocatedTimestampKind: KindRenderer<"locatedTimestamp">;
5
+ export declare const renderTzKind: KindRenderer<"tz">;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { DateInput } from "./date-input.js";
3
+ import { localeBoundsProps, stateProps } from "./input-optional-props.js";
4
+ import { LocatedTimestampInput } from "./located-timestamp-input.js";
5
+ import { TimestampInput } from "./timestamp-input.js";
6
+ import { TzInput } from "./tz-input.js";
7
+ export const renderDateKind = (props) => (_jsx(DateInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...localeBoundsProps(props), ...stateProps(props) }));
8
+ export const renderTimestampKind = (props) => (_jsx(TimestampInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...(props.wallClock !== undefined && { wallClock: props.wallClock }), ...localeBoundsProps(props), ...stateProps(props) }));
9
+ export const renderLocatedTimestampKind = (props) => (_jsx(LocatedTimestampInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...localeBoundsProps(props), ...stateProps(props) }));
10
+ export const renderTzKind = (props) => (_jsx(TzInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...stateProps(props) }));
@@ -0,0 +1,7 @@
1
+ import type { KindRenderer } from "./input-shared.ts";
2
+ export declare const renderTextKind: KindRenderer<"text">;
3
+ export declare const renderCodeKind: KindRenderer<"code">;
4
+ export declare const renderEmailKind: KindRenderer<"email">;
5
+ export declare const renderMonthKind: KindRenderer<"month">;
6
+ export declare const renderPasswordKind: KindRenderer<"password">;
7
+ export declare const renderTextareaKind: KindRenderer<"textarea">;
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from "../lib/cn.js";
3
+ import { Input as UiInput } from "../ui/input.js";
4
+ import { Textarea } from "../ui/textarea.js";
5
+ import { CodeInput } from "./code-input.js";
6
+ import { fieldIconFor, textareaMinHeight, withFieldIcon, withInputAddons, withTrailingAction, } from "./field.js";
7
+ export const renderTextKind = (props, { common, textInputRef }) => withInputAddons(props, withFieldIcon(props.icon, _jsx(UiInput, { type: "text", ref: textInputRef, ...common, ...props.dataAttributes, "data-testid": props.testId, readOnly: props.readOnly, value: props.value, onChange: (e) => props.onChange(e.target.value), onKeyDown: props.onKeyDown, ...(props.placeholder !== undefined && { placeholder: props.placeholder }), ...(props.autoComplete !== undefined && { autoComplete: props.autoComplete }), className: cn(fieldIconFor(props.icon) !== undefined ? "pl-8" : undefined) })));
8
+ export const renderCodeKind = (props) => _jsx(CodeInput, { ...props });
9
+ export const renderEmailKind = (props, { common }) => (_jsx(UiInput, { type: "email", ...common, "data-testid": props.testId, value: props.value, onChange: (e) => props.onChange(e.target.value), ...(props.placeholder !== undefined && { placeholder: props.placeholder }), autoComplete: props.autoComplete ?? "email" }));
10
+ export const renderMonthKind = (props, { common }) => (_jsx(UiInput, { type: "month", ...common, "data-testid": props.testId, value: props.value, onChange: (e) => props.onChange(e.target.value) }));
11
+ export const renderPasswordKind = (props, { common }) => withTrailingAction(props.trailingAction, _jsx(UiInput, { type: "password", ...common, "data-testid": props.testId, value: props.value, onChange: (e) => props.onChange(e.target.value), ...(props.placeholder !== undefined && { placeholder: props.placeholder }), autoComplete: props.autoComplete ?? "current-password", className: props.trailingAction !== undefined ? "pr-9" : undefined }), true);
12
+ function textareaShortcutProps({ onKeyDown, onSubmitShortcut }) {
13
+ if (onSubmitShortcut === undefined && onKeyDown === undefined)
14
+ return {};
15
+ return {
16
+ ...(onSubmitShortcut !== undefined && {
17
+ "aria-keyshortcuts": "Control+Enter Meta+Enter",
18
+ }),
19
+ onKeyDown: (e) => {
20
+ onKeyDown?.(e);
21
+ // Lets a caller that already handles Ctrl/Cmd+Enter (e.g. an
22
+ // "Enter sends" handler that ignores only Shift) opt out of the
23
+ // shortcut instead of submitting twice.
24
+ if (e.defaultPrevented)
25
+ return;
26
+ if (onSubmitShortcut === undefined || e.key !== "Enter" || !(e.metaKey || e.ctrlKey))
27
+ return;
28
+ e.preventDefault();
29
+ onSubmitShortcut();
30
+ },
31
+ };
32
+ }
33
+ export const renderTextareaKind = (props, { common }) => (_jsx(Textarea, { ...common, ...props.dataAttributes, readOnly: props.readOnly, value: props.value, onChange: (e) => props.onChange(e.target.value), rows: props.rows ?? 4, className: "resize-y", ...(props.placeholder !== undefined && { placeholder: props.placeholder }), ...(props.rows !== undefined && { style: textareaMinHeight(props.rows) }), ...textareaShortcutProps(props) }));
@@ -1,171 +1,45 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
1
  import { useContext } from "react";
3
- import { cn } from "../lib/cn.js";
4
- import { Checkbox } from "../ui/checkbox.js";
5
- import { Input as UiInput } from "../ui/input.js";
6
- import { Switch } from "../ui/switch.js";
7
- import { Textarea } from "../ui/textarea.js";
8
- import { CodeInput } from "./code-input.js";
9
- import { ComboboxInput } from "./combobox.js";
10
- import { DateInput } from "./date-input.js";
11
- import { FileUploadInput } from "./file-upload.js";
12
- import { FilesDropzoneInput } from "./files-dropzone.js";
13
- import { LocatedTimestampInput } from "./located-timestamp-input.js";
14
- import { MoneyInput } from "./money-input.js";
15
- import { NumberInput } from "./number-input.js";
16
- import { hasDescriptionOrGroup } from "./option-groups.js";
17
- import { TimestampInput } from "./timestamp-input.js";
18
- import { TzInput } from "./tz-input.js";
19
- import { useFocusOnMount } from "./use-focus-on-mount.js";
20
2
  import "../react-css-custom-properties.js";
21
3
  import { FieldDescriptionContext, FieldLayoutContext } from "./contexts.js";
22
- import { defaultSelectPresentation, FIELD_ICON_CLASS, fieldIconFor, RadioListSelect, SegmentedSelect, textareaMinHeight, unitSuffixId, withFieldIcon, withInlineDisabledHint, withInputAddons, withoutSegmentedSelectPlaceholder, withTrailingAction, } from "./field.js";
4
+ import { renderBooleanKind, renderComboboxKind, renderSelectKind } from "./input-choice-kinds.js";
5
+ import { renderFileKind, renderFilesDropzoneKind } from "./input-file-kinds.js";
6
+ import { renderMoneyKind, renderNumberKind, renderRangeKind } from "./input-number-kinds.js";
7
+ import { commonInputAttrs, } from "./input-shared.js";
8
+ import { renderDateKind, renderLocatedTimestampKind, renderTimestampKind, renderTzKind, } from "./input-temporal-kinds.js";
9
+ import { renderCodeKind, renderEmailKind, renderMonthKind, renderPasswordKind, renderTextareaKind, renderTextKind, } from "./input-text-kinds.js";
10
+ import { useFocusOnMount } from "./use-focus-on-mount.js";
11
+ const KIND_RENDERERS = {
12
+ text: renderTextKind,
13
+ code: renderCodeKind,
14
+ email: renderEmailKind,
15
+ month: renderMonthKind,
16
+ password: renderPasswordKind,
17
+ number: renderNumberKind,
18
+ range: renderRangeKind,
19
+ boolean: renderBooleanKind,
20
+ file: renderFileKind,
21
+ image: renderFileKind,
22
+ "files-dropzone": renderFilesDropzoneKind,
23
+ date: renderDateKind,
24
+ select: renderSelectKind,
25
+ combobox: renderComboboxKind,
26
+ money: renderMoneyKind,
27
+ timestamp: renderTimestampKind,
28
+ locatedTimestamp: renderLocatedTimestampKind,
29
+ tz: renderTzKind,
30
+ textarea: renderTextareaKind,
31
+ };
32
+ function renderKind(kind, props, shared) {
33
+ return KIND_RENDERERS[kind](props, shared);
34
+ }
23
35
  export function DefaultInput(props) {
24
36
  // Vendored ui/input + ui/checkbox style errors via `aria-invalid`
25
37
  // themselves, no manual border-destructive needed anymore.
26
38
  const booleanLayout = useContext(FieldLayoutContext);
27
39
  const describedBy = useContext(FieldDescriptionContext);
28
40
  const textInputRef = useFocusOnMount(props.kind === "text" ? props.autoFocus : undefined);
29
- const common = {
30
- id: props.id,
31
- name: props.name,
32
- disabled: props.disabled,
33
- "aria-describedby": describedBy,
34
- "aria-required": props.required,
35
- "aria-invalid": props.hasError === true ? true : undefined,
36
- };
37
- switch (props.kind) {
38
- case "text":
39
- return withInputAddons(props, withFieldIcon(props.icon, _jsx(UiInput, { type: "text", ref: textInputRef, ...common, ...props.dataAttributes, "data-testid": props.testId, readOnly: props.readOnly, value: props.value, onChange: (e) => props.onChange(e.target.value), onKeyDown: props.onKeyDown, ...(props.placeholder !== undefined && { placeholder: props.placeholder }), ...(props.autoComplete !== undefined && { autoComplete: props.autoComplete }), className: cn(fieldIconFor(props.icon) !== undefined ? "pl-8" : undefined) })));
40
- case "code":
41
- return _jsx(CodeInput, { ...props });
42
- case "email":
43
- return (_jsx(UiInput, { type: "email", ...common, "data-testid": props.testId, value: props.value, onChange: (e) => props.onChange(e.target.value), ...(props.placeholder !== undefined && { placeholder: props.placeholder }), autoComplete: props.autoComplete ?? "email" }));
44
- case "month":
45
- return (_jsx(UiInput, { type: "month", ...common, "data-testid": props.testId, value: props.value, onChange: (e) => props.onChange(e.target.value) }));
46
- case "password":
47
- return withTrailingAction(props.trailingAction, _jsx(UiInput, { type: "password", ...common, "data-testid": props.testId, value: props.value, onChange: (e) => props.onChange(e.target.value), ...(props.placeholder !== undefined && { placeholder: props.placeholder }), autoComplete: props.autoComplete ?? "current-password", className: props.trailingAction !== undefined ? "pr-9" : undefined }), true);
48
- case "number": {
49
- const NumberIcon = fieldIconFor(props.icon);
50
- // Icon, input and unit share this one box, and the grid cell sizes the
51
- // box rather than the bare input: anchored to a wider wrapper, the unit
52
- // would sit next to a narrower input instead of inside it.
53
- const numberField = (_jsxs("div", { "data-slot": "number-field", className: "relative", children: [NumberIcon !== undefined && (_jsx(NumberIcon, { "aria-hidden": "true", className: FIELD_ICON_CLASS })), _jsx(NumberInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, disabled: props.disabled, required: props.required, hasError: props.hasError, testId: props.testId, ...(props.unit !== undefined && { ariaDescribedBy: unitSuffixId(props.id) }), ...(props.locale !== undefined && { locale: props.locale }), ...(props.grouping !== undefined && { grouping: props.grouping }), ...(props.integer !== undefined && { integer: props.integer }), ...(props.placeholder !== undefined && { placeholder: props.placeholder }), className: cn(NumberIcon !== undefined ? "pl-8" : undefined, props.unit !== undefined ? "pr-8" : undefined) }), props.unit !== undefined && (_jsx("span", { id: unitSuffixId(props.id), className: "pointer-events-none absolute right-2.5 top-1/2 max-w-[40%] -translate-y-1/2 truncate text-sm text-muted-foreground", children: props.unit }))] }));
54
- return withInputAddons(props, numberField);
55
- }
56
- case "range":
57
- return (_jsx("input", { type: "range", ...common, min: props.min, max: props.max, step: props.step ?? 1, value: props.value, onChange: (e) => props.onChange(Number(e.target.value)), className: "w-full accent-primary" }));
58
- case "boolean":
59
- // layout="inline" (checkbox lists like MultiSelectCheckboxes, the
60
- // BooleanField widget) keeps the checkbox optics; the standard form
61
- // field (render-field.tsx, layout="stacked") gets the switch.
62
- return booleanLayout === "inline" ? (_jsx(Checkbox, { id: props.id, name: props.name, disabled: props.disabled, "aria-required": props.required, "aria-invalid": props.hasError === true ? true : undefined, checked: props.value, onCheckedChange: (checked) => props.onChange(checked === true) })) : (_jsx(Switch, { id: props.id, name: props.name, disabled: props.disabled, "aria-required": props.required, "aria-invalid": props.hasError === true ? true : undefined, checked: props.value, onCheckedChange: (checked) => props.onChange(checked === true), className: "aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40" }));
63
- case "file":
64
- case "image":
65
- return (_jsx(FileUploadInput, { kind: props.kind, id: props.id, value: props.value, onChange: props.onChange, ...(props.accept !== undefined && { accept: props.accept }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.entityType !== undefined && { entityType: props.entityType }), ...(props.uploadActionForm !== undefined && {
66
- uploadActionForm: props.uploadActionForm,
67
- }), ...(props.entityId !== undefined && { entityId: props.entityId }), ...(props.fieldName !== undefined && { fieldName: props.fieldName }), ...(props.imageVariant !== undefined && { imageVariant: props.imageVariant }), ...(props.capture !== undefined && { capture: props.capture }), ...(props.directory !== undefined && { directory: props.directory }), ...(props.onFilesPicked !== undefined && { onFilesPicked: props.onFilesPicked }), ...(props.pickLabel !== undefined && { pickLabel: props.pickLabel }), ...(props.testId !== undefined && { testId: props.testId }) }));
68
- case "files-dropzone":
69
- return (_jsx(FilesDropzoneInput, { id: props.id, value: props.value, onChange: props.onChange, ...(props.accept !== undefined && { accept: props.accept }), ...(props.maxSize !== undefined && { maxSize: props.maxSize }), ...(props.maxCount !== undefined && { maxCount: props.maxCount }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.entityType !== undefined && { entityType: props.entityType }), ...(props.uploadActionForm !== undefined && {
70
- uploadActionForm: props.uploadActionForm,
71
- }), ...(props.entityId !== undefined && { entityId: props.entityId }), ...(props.fieldName !== undefined && { fieldName: props.fieldName }), ...(props.testId !== undefined && { testId: props.testId }) }));
72
- case "date":
73
- return (_jsx(DateInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...(props.locale !== undefined && { locale: props.locale }), ...(props.min !== undefined && { min: props.min }), ...(props.max !== undefined && { max: props.max }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
74
- case "select": {
75
- // Visual consolidation: all selects go through ComboboxInput
76
- // (cmdk + Radix popover). Before, there were two paths: Radix
77
- // Select for `kind:"select"` and cmdk for `kind:"combobox"`. Three
78
- // visually different variants (single select, combobox single, combobox
79
- // multi) became unmanageable. With the merge the combobox is the only
80
- // implementation: the search input is present even for 4-item status
81
- // selects, a deliberately accepted UX consequence for style consistency.
82
- const comboOptions = props.options.map((o) => typeof o === "string" ? { value: o, label: o } : o);
83
- // The dropdown shows a disabled option's hint inline, so it stays readable in the trigger and search.
84
- const dropdownOptions = comboOptions.map(withInlineDisabledHint);
85
- // The radio group can't render the unselected placeholder as its own
86
- // segment, so it counts and renders on the real options only — the
87
- // dropdown below keeps comboOptions (placeholder included) since it
88
- // has a genuine "nothing selected" row.
89
- // An author who asks for `display: "radio"` explicitly declared the ""
90
- // option as a real choice (e.g. "Any"), so it stays a segment.
91
- const radioGroupOptions = props.display === "radio" ? comboOptions : withoutSegmentedSelectPlaceholder(comboOptions);
92
- // An explicit `display` is an author decision and outranks the
93
- // heuristic in both directions — a requested radio group renders as
94
- // one even when the options outnumber the heuristic's threshold.
95
- const requestedPresentation = props.radioVariant === "card"
96
- ? "radioList"
97
- : props.display === "radio"
98
- ? "segmented"
99
- : props.display === "dropdown"
100
- ? "dropdown"
101
- : defaultSelectPresentation(radioGroupOptions);
102
- // A segmented control has no room for a description line or group headings.
103
- const presentation = requestedPresentation === "segmented" && hasDescriptionOrGroup(radioGroupOptions)
104
- ? "radioList"
105
- : requestedPresentation;
106
- if (presentation === "radioList" && radioGroupOptions.length > 0) {
107
- return (_jsx(RadioListSelect, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, options: radioGroupOptions, ...(props.radioVariant !== undefined && { variant: props.radioVariant }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
108
- }
109
- if (presentation === "segmented" && radioGroupOptions.length > 0) {
110
- return (_jsx(SegmentedSelect, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, options: radioGroupOptions, ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
111
- }
112
- return (_jsx(ComboboxInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, options: dropdownOptions, ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
113
- }
114
- case "combobox": {
115
- // Discriminated union per `multiple`; we split
116
- // TS-side into two branches so ComboboxInput's single/multi variants
117
- // render with the right types.
118
- const baseProps = {
119
- id: props.id,
120
- name: props.name,
121
- options: props.options,
122
- ...(props.disabled !== undefined && { disabled: props.disabled }),
123
- ...(props.required !== undefined && { required: props.required }),
124
- ...(props.hasError !== undefined && { hasError: props.hasError }),
125
- ...(props.placeholder !== undefined && { placeholder: props.placeholder }),
126
- ...(props.searchPlaceholder !== undefined && {
127
- searchPlaceholder: props.searchPlaceholder,
128
- }),
129
- ...(props.emptyText !== undefined && { emptyText: props.emptyText }),
130
- ...(props.onSearchChange !== undefined && { onSearchChange: props.onSearchChange }),
131
- ...(props.loading !== undefined && { loading: props.loading }),
132
- ...(props.onCreate !== undefined && { onCreate: props.onCreate }),
133
- ...(props.createLabel !== undefined && { createLabel: props.createLabel }),
134
- };
135
- if (props.multiple === true) {
136
- return (_jsx(ComboboxInput, { ...baseProps, multiple: true, value: props.value, onChange: props.onChange }));
137
- }
138
- return _jsx(ComboboxInput, { ...baseProps, value: props.value, onChange: props.onChange });
139
- }
140
- case "money":
141
- return (_jsx(MoneyInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, currency: props.currency ?? "EUR", ...(props.locale !== undefined && { locale: props.locale }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
142
- case "timestamp":
143
- return (_jsx(TimestampInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...(props.wallClock !== undefined && { wallClock: props.wallClock }), ...(props.locale !== undefined && { locale: props.locale }), ...(props.min !== undefined && { min: props.min }), ...(props.max !== undefined && { max: props.max }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
144
- case "locatedTimestamp":
145
- return (_jsx(LocatedTimestampInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...(props.locale !== undefined && { locale: props.locale }), ...(props.min !== undefined && { min: props.min }), ...(props.max !== undefined && { max: props.max }), ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
146
- case "textarea": {
147
- const rows = props.rows;
148
- const onSubmitShortcut = props.onSubmitShortcut;
149
- const onKeyDown = props.onKeyDown;
150
- return (_jsx(Textarea, { ...common, ...props.dataAttributes, readOnly: props.readOnly, value: props.value, onChange: (e) => props.onChange(e.target.value), rows: rows ?? 4, className: "resize-y", ...(props.placeholder !== undefined && { placeholder: props.placeholder }), ...(rows !== undefined && { style: textareaMinHeight(rows) }), ...((onSubmitShortcut !== undefined || onKeyDown !== undefined) && {
151
- ...(onSubmitShortcut !== undefined && {
152
- "aria-keyshortcuts": "Control+Enter Meta+Enter",
153
- }),
154
- onKeyDown: (e) => {
155
- onKeyDown?.(e);
156
- // Lets a caller that already handles Ctrl/Cmd+Enter (e.g. an
157
- // "Enter sends" handler that ignores only Shift) opt out of the
158
- // shortcut instead of submitting twice.
159
- if (e.defaultPrevented)
160
- return;
161
- if (onSubmitShortcut === undefined || e.key !== "Enter" || !(e.metaKey || e.ctrlKey))
162
- return;
163
- e.preventDefault();
164
- onSubmitShortcut();
165
- },
166
- }) }));
167
- }
168
- case "tz":
169
- return (_jsx(TzInput, { id: props.id, name: props.name, value: props.value, onChange: props.onChange, ...(props.disabled !== undefined && { disabled: props.disabled }), ...(props.required !== undefined && { required: props.required }), ...(props.hasError !== undefined && { hasError: props.hasError }) }));
170
- }
41
+ const common = commonInputAttrs(props, describedBy);
42
+ if (!Object.hasOwn(KIND_RENDERERS, props.kind))
43
+ return undefined;
44
+ return renderKind(props.kind, props, { common, textInputRef, booleanLayout });
171
45
  }
@@ -0,0 +1,7 @@
1
+ import { type ReactNode } from "react";
2
+ import type { DataTableRangeBound, DataTableRangeFacet } from "../../data-table-aggregate-types.ts";
3
+ /** "From/to" bounds of a number, decimal, money or bigInt field. */
4
+ export declare function NumberRangeFacetFilter({ facet, onChange, }: {
5
+ readonly facet: DataTableRangeFacet;
6
+ readonly onChange: (field: string, bound: DataTableRangeBound, value: string) => void;
7
+ }): ReactNode;
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { useOptionalTranslation } from "../../index.js";
4
+ const INPUT_CLASS = "h-9 w-24 rounded-md border border-input bg-transparent px-2 text-sm tabular-nums shadow-xs outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 max-md:min-h-11";
5
+ // A keystroke must not refetch the list, so a bound commits on blur or Enter;
6
+ // a value changed from outside (reset, back navigation) replaces the draft.
7
+ function RangeBoundInput({ facet, bound, label, onCommit, }) {
8
+ const committed = facet[bound];
9
+ const [draft, setDraft] = useState(committed);
10
+ const [seen, setSeen] = useState(committed);
11
+ if (seen !== committed) {
12
+ setSeen(committed);
13
+ setDraft(committed);
14
+ }
15
+ const commit = () => {
16
+ const trimmed = draft.trim();
17
+ if (trimmed !== "" && !Number.isFinite(Number(trimmed))) {
18
+ setDraft(committed);
19
+ return;
20
+ }
21
+ if (trimmed !== committed)
22
+ onCommit(facet.field, bound, trimmed);
23
+ };
24
+ return (_jsx("input", { type: "number", inputMode: "decimal", step: "any", className: INPUT_CLASS, value: draft, placeholder: label, "aria-label": `${facet.label} ${label}`, "data-testid": `facet-range-${facet.field}-${bound}`, onChange: (event) => setDraft(event.target.value), onBlur: commit, onKeyDown: (event) => {
25
+ if (event.key === "Enter")
26
+ commit();
27
+ } }));
28
+ }
29
+ /** "From/to" bounds of a number, decimal, money or bigInt field. */
30
+ export function NumberRangeFacetFilter({ facet, onChange, }) {
31
+ const translate = useOptionalTranslation();
32
+ return (_jsxs("div", { className: "flex items-center gap-2", "data-testid": `facet-range-${facet.field}`, children: [_jsx("span", { className: "text-sm text-muted-foreground", children: facet.label }), _jsx(RangeBoundInput, { facet: facet, bound: "min", label: translate?.("kumiko.list.range.min") ?? "From", onCommit: onChange }), _jsx("span", { className: "text-sm text-muted-foreground", children: "\u2013" }), _jsx(RangeBoundInput, { facet: facet, bound: "max", label: translate?.("kumiko.list.range.max") ?? "To", onCommit: onChange }), facet.unit !== undefined && (_jsx("span", { className: "text-sm text-muted-foreground", children: facet.unit }))] }));
33
+ }
@@ -1 +1,5 @@
1
- export declare function createBoundedLoadCache<T>(max: number, dispose: (value: T) => void, shouldKeep?: (value: T) => boolean): (key: string, load: () => Promise<T>) => Promise<T>;
1
+ export type BoundedLoadCache<T> = {
2
+ readonly load: (key: string, load: () => Promise<T>) => Promise<T>;
3
+ readonly retain: (key: string) => () => void;
4
+ };
5
+ export declare function createBoundedLoadCache<T>(max: number, dispose: (value: T) => void, shouldKeep?: (value: T) => boolean): BoundedLoadCache<T>;