@cosmicdrift/kumiko-renderer 0.374.0 → 0.378.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 (477) hide show
  1. package/README.md +2 -2
  2. package/dist/app/action-form-support.d.ts +9 -2
  3. package/dist/app/action-form-support.js +24 -2
  4. package/dist/app/client-actions.d.ts +2 -2
  5. package/dist/app/column-renderers.js +1 -1
  6. package/dist/app/config-edit-shim.js +1 -1
  7. package/dist/app/content-preview.js +1 -6
  8. package/dist/app/custom-screens.js +1 -1
  9. package/dist/app/dashboard-body.d.ts +1 -1
  10. package/dist/app/entity-list-expanded-row.d.ts +1 -1
  11. package/dist/app/form-schema.d.ts +1 -1
  12. package/dist/app/form-schema.js +2 -2
  13. package/dist/app/kumiko-screen.d.ts +1 -1
  14. package/dist/app/kumiko-screen.js +10 -7
  15. package/dist/app/list-empty-content.d.ts +1 -1
  16. package/dist/app/list-facets.d.ts +1 -1
  17. package/dist/app/nav.js +2 -2
  18. package/dist/app/query-state-banners.d.ts +1 -1
  19. package/dist/app/reference-link.d.ts +1 -1
  20. package/dist/app/row-actions.d.ts +1 -1
  21. package/dist/app/secret-mint-body.d.ts +1 -1
  22. package/dist/app/secrets-edit-body.d.ts +1 -1
  23. package/dist/app/use-record-actions.d.ts +1 -1
  24. package/dist/app/write-failed-error.d.ts +1 -1
  25. package/dist/components/availability-options-select.d.ts +1 -1
  26. package/dist/components/embedded-list-field.d.ts +1 -1
  27. package/dist/components/embedded-list-field.js +1 -1
  28. package/dist/components/file-list-field.d.ts +1 -1
  29. package/dist/components/form-derivation-patch.d.ts +8 -0
  30. package/dist/components/form-derivation-patch.js +24 -0
  31. package/dist/components/form-screen-layout.d.ts +13 -0
  32. package/dist/components/form-screen-layout.js +13 -0
  33. package/dist/components/grid-cell-for-field.d.ts +1 -1
  34. package/dist/components/multi-select-checkboxes.d.ts +1 -1
  35. package/dist/components/multi-select-checkboxes.js +1 -1
  36. package/dist/components/query-options-select.d.ts +1 -1
  37. package/dist/components/related-list-section.d.ts +1 -1
  38. package/dist/components/render-edit-logic.d.ts +1 -1
  39. package/dist/components/render-edit-types.d.ts +6 -3
  40. package/dist/components/render-edit.d.ts +1 -1
  41. package/dist/components/render-edit.js +18 -3
  42. package/dist/components/render-field.d.ts +1 -1
  43. package/dist/components/render-field.js +12 -2
  44. package/dist/components/render-list.d.ts +1 -1
  45. package/dist/components/render-list.js +20 -4
  46. package/dist/components/write-form-section.d.ts +1 -1
  47. package/dist/components/write-form-section.js +1 -1
  48. package/dist/context/dispatcher-context.d.ts +1 -1
  49. package/dist/file-ids-of.d.ts +1 -0
  50. package/dist/file-ids-of.js +7 -0
  51. package/dist/flow-diagram/icons.d.ts +3 -0
  52. package/dist/flow-diagram/icons.js +14 -0
  53. package/dist/flow-diagram/index.d.ts +2 -0
  54. package/dist/flow-diagram/index.js +1 -0
  55. package/dist/flow-diagram/render.d.ts +3 -0
  56. package/dist/flow-diagram/render.js +234 -0
  57. package/dist/flow-diagram/types.d.ts +18 -0
  58. package/dist/flow-diagram/types.js +1 -0
  59. package/dist/format-when.js +1 -1
  60. package/dist/headless/apex/css.d.ts +3 -0
  61. package/dist/headless/apex/css.js +298 -0
  62. package/dist/headless/apex/index.d.ts +236 -0
  63. package/dist/headless/apex/index.js +377 -0
  64. package/dist/headless/apex/lightbox.d.ts +4 -0
  65. package/dist/headless/apex/lightbox.js +81 -0
  66. package/dist/headless/contracts/asset.d.ts +15 -0
  67. package/dist/headless/contracts/asset.js +17 -0
  68. package/dist/headless/contracts/index.d.ts +3 -0
  69. package/dist/headless/contracts/index.js +1 -0
  70. package/dist/headless/contracts/locale.d.ts +7 -0
  71. package/dist/headless/contracts/locale.js +11 -0
  72. package/dist/headless/contracts/primitives.d.ts +93 -0
  73. package/dist/headless/contracts/primitives.js +21 -0
  74. package/dist/headless/dispatcher/index.d.ts +2 -0
  75. package/dist/headless/dispatcher/index.js +1 -0
  76. package/dist/headless/dispatcher/types.d.ts +86 -0
  77. package/dist/headless/dispatcher/types.js +34 -0
  78. package/dist/headless/form/form-controller.d.ts +2 -0
  79. package/dist/headless/form/form-controller.js +409 -0
  80. package/dist/headless/form/index.d.ts +3 -0
  81. package/dist/headless/form/index.js +2 -0
  82. package/dist/headless/form/types.d.ts +76 -0
  83. package/dist/headless/form/types.js +1 -0
  84. package/dist/headless/form/zod-bridge.d.ts +10 -0
  85. package/dist/headless/form/zod-bridge.js +103 -0
  86. package/dist/headless/format/document-values.d.ts +12 -0
  87. package/dist/headless/format/document-values.js +70 -0
  88. package/dist/headless/format/escape.d.ts +5 -0
  89. package/dist/headless/format/escape.js +75 -0
  90. package/dist/headless/format/html-template.d.ts +9 -0
  91. package/dist/headless/format/html-template.js +39 -0
  92. package/dist/headless/format/index.d.ts +12 -0
  93. package/dist/headless/format/index.js +237 -0
  94. package/dist/headless/format/money.d.ts +3 -0
  95. package/dist/headless/format/money.js +39 -0
  96. package/dist/headless/index.d.ts +14 -0
  97. package/dist/headless/index.js +9 -0
  98. package/dist/headless/locale-routing/index.d.ts +41 -0
  99. package/dist/headless/locale-routing/index.js +145 -0
  100. package/dist/headless/nav/index.d.ts +2 -0
  101. package/dist/headless/nav/index.js +1 -0
  102. package/dist/headless/nav/resolve.d.ts +2 -0
  103. package/dist/headless/nav/resolve.js +71 -0
  104. package/dist/headless/nav/types.d.ts +26 -0
  105. package/dist/headless/nav/types.js +1 -0
  106. package/dist/headless/store/create-store.d.ts +2 -0
  107. package/dist/headless/store/create-store.js +43 -0
  108. package/dist/headless/store/equality.d.ts +1 -0
  109. package/dist/headless/store/equality.js +34 -0
  110. package/dist/headless/store/index.d.ts +3 -0
  111. package/dist/headless/store/index.js +2 -0
  112. package/dist/headless/store/types.d.ts +7 -0
  113. package/dist/headless/store/types.js +10 -0
  114. package/dist/headless/view-model/edit.d.ts +21 -0
  115. package/dist/headless/view-model/edit.js +512 -0
  116. package/dist/headless/view-model/embedded-list.d.ts +27 -0
  117. package/dist/headless/view-model/embedded-list.js +63 -0
  118. package/dist/headless/view-model/index.d.ts +7 -0
  119. package/dist/headless/view-model/index.js +3 -0
  120. package/dist/headless/view-model/list-file-display.d.ts +3 -0
  121. package/dist/headless/view-model/list-file-display.js +27 -0
  122. package/dist/headless/view-model/list.d.ts +16 -0
  123. package/dist/headless/view-model/list.js +229 -0
  124. package/dist/headless/view-model/types.d.ts +382 -0
  125. package/dist/headless/view-model/types.js +1 -0
  126. package/dist/hooks/use-ai-text.d.ts +1 -1
  127. package/dist/hooks/use-form.d.ts +1 -1
  128. package/dist/hooks/use-form.js +1 -1
  129. package/dist/hooks/use-mutation.d.ts +1 -1
  130. package/dist/hooks/use-query.d.ts +1 -1
  131. package/dist/hooks/use-store.d.ts +1 -1
  132. package/dist/hooks/use-store.js +7 -7
  133. package/dist/hooks/use-stream-handler.d.ts +1 -1
  134. package/dist/i18n-defaults.js +6 -0
  135. package/dist/i18n.d.ts +1 -1
  136. package/dist/i18n.js +1 -1
  137. package/dist/index.d.ts +3 -1
  138. package/dist/index.js +5 -4
  139. package/dist/live/csrf.d.ts +2 -0
  140. package/dist/live/csrf.js +60 -0
  141. package/dist/live/dispatcher-live.d.ts +7 -0
  142. package/dist/live/dispatcher-live.js +286 -0
  143. package/dist/live/envelopes.d.ts +101 -0
  144. package/dist/live/envelopes.js +35 -0
  145. package/dist/live/error-mapping.d.ts +16 -0
  146. package/dist/live/error-mapping.js +82 -0
  147. package/dist/live/index.d.ts +7 -0
  148. package/dist/live/index.js +5 -0
  149. package/dist/live/locale.d.ts +2 -0
  150. package/dist/live/locale.js +25 -0
  151. package/dist/live/sse-stream.d.ts +14 -0
  152. package/dist/live/sse-stream.js +128 -0
  153. package/dist/primitives.d.ts +45 -36
  154. package/dist/primitives.js +1 -1
  155. package/dist/session/session-ended.d.ts +1 -1
  156. package/dist/tokens.d.ts +3 -4
  157. package/dist/tokens.js +4 -5
  158. package/dist/web/app/app-schema-boot.d.ts +19 -0
  159. package/dist/web/app/app-schema-boot.js +124 -0
  160. package/dist/web/app/browser-locale.d.ts +22 -0
  161. package/dist/web/app/browser-locale.js +78 -0
  162. package/dist/web/app/client-plugin.d.ts +106 -0
  163. package/dist/web/app/client-plugin.js +12 -0
  164. package/dist/web/app/create-app.d.ts +104 -0
  165. package/dist/web/app/create-app.js +498 -0
  166. package/dist/web/app/create-public-surface.d.ts +36 -0
  167. package/dist/web/app/create-public-surface.js +40 -0
  168. package/dist/web/app/dashboard-body.d.ts +3 -0
  169. package/dist/web/app/dashboard-body.js +865 -0
  170. package/dist/web/app/dashboard-refresh.d.ts +6 -0
  171. package/dist/web/app/dashboard-refresh.js +15 -0
  172. package/dist/web/app/document-lang-sync.d.ts +4 -0
  173. package/dist/web/app/document-lang-sync.js +27 -0
  174. package/dist/web/app/draft-storage.d.ts +11 -0
  175. package/dist/web/app/draft-storage.js +53 -0
  176. package/dist/web/app/nav-providers-context.d.ts +13 -0
  177. package/dist/web/app/nav-providers-context.js +18 -0
  178. package/dist/web/app/nav.d.ts +40 -0
  179. package/dist/web/app/nav.js +231 -0
  180. package/dist/web/app/plain-content-editor.d.ts +3 -0
  181. package/dist/web/app/plain-content-editor.js +30 -0
  182. package/dist/web/app/relative-time.d.ts +10 -0
  183. package/dist/web/app/relative-time.js +56 -0
  184. package/dist/web/app/resolvers-context.d.ts +12 -0
  185. package/dist/web/app/resolvers-context.js +10 -0
  186. package/dist/web/app/rich-content-editor.d.ts +3 -0
  187. package/dist/web/app/rich-content-editor.js +15 -0
  188. package/dist/web/app/root-error-fallback.d.ts +2 -0
  189. package/dist/web/app/root-error-fallback.js +21 -0
  190. package/dist/web/app/screen-error-fallback.d.ts +6 -0
  191. package/dist/web/app/screen-error-fallback.js +17 -0
  192. package/dist/web/app/tiptap-editor.d.ts +3 -0
  193. package/dist/web/app/tiptap-editor.js +120 -0
  194. package/dist/web/app/toast-action-notifier.d.ts +5 -0
  195. package/dist/web/app/toast-action-notifier.js +17 -0
  196. package/dist/web/components/config-cascade.d.ts +13 -0
  197. package/dist/web/components/config-cascade.js +155 -0
  198. package/dist/web/components/config-source-badge.d.ts +6 -0
  199. package/dist/web/components/config-source-badge.js +55 -0
  200. package/dist/web/default-color-scheme.d.ts +2 -0
  201. package/dist/web/default-color-scheme.js +3 -0
  202. package/dist/web/icons.d.ts +94 -0
  203. package/dist/web/icons.js +100 -0
  204. package/dist/web/index.d.ts +78 -0
  205. package/dist/web/index.js +53 -0
  206. package/dist/web/layout/app-layout.d.ts +21 -0
  207. package/dist/web/layout/app-layout.js +8 -0
  208. package/dist/web/layout/avatar.d.ts +12 -0
  209. package/dist/web/layout/avatar.js +63 -0
  210. package/dist/web/layout/default-app-shell.d.ts +41 -0
  211. package/dist/web/layout/default-app-shell.js +16 -0
  212. package/dist/web/layout/editor-panel.d.ts +10 -0
  213. package/dist/web/layout/editor-panel.js +29 -0
  214. package/dist/web/layout/fill-classes.d.ts +9 -0
  215. package/dist/web/layout/fill-classes.js +15 -0
  216. package/dist/web/layout/filter-app-schema-navs.d.ts +7 -0
  217. package/dist/web/layout/filter-app-schema-navs.js +68 -0
  218. package/dist/web/layout/header-action-group.d.ts +6 -0
  219. package/dist/web/layout/header-action-group.js +8 -0
  220. package/dist/web/layout/header-overflow-menu.d.ts +4 -0
  221. package/dist/web/layout/header-overflow-menu.js +8 -0
  222. package/dist/web/layout/language-menu-items.d.ts +8 -0
  223. package/dist/web/layout/language-menu-items.js +16 -0
  224. package/dist/web/layout/language-switcher.d.ts +25 -0
  225. package/dist/web/layout/language-switcher.js +46 -0
  226. package/dist/web/layout/nav-tree.d.ts +19 -0
  227. package/dist/web/layout/nav-tree.js +536 -0
  228. package/dist/web/layout/page-header-slot.d.ts +25 -0
  229. package/dist/web/layout/page-header-slot.js +50 -0
  230. package/dist/web/layout/profile-menu.d.ts +13 -0
  231. package/dist/web/layout/profile-menu.js +6 -0
  232. package/dist/web/layout/shell-breadcrumb.d.ts +11 -0
  233. package/dist/web/layout/shell-breadcrumb.js +34 -0
  234. package/dist/web/layout/shell-header.d.ts +12 -0
  235. package/dist/web/layout/shell-header.js +159 -0
  236. package/dist/web/layout/sidebar-brand.d.ts +15 -0
  237. package/dist/web/layout/sidebar-brand.js +9 -0
  238. package/dist/web/layout/sidebar-panel.d.ts +41 -0
  239. package/dist/web/layout/sidebar-panel.js +107 -0
  240. package/dist/web/layout/sidebar-user.d.ts +8 -0
  241. package/dist/web/layout/sidebar-user.js +17 -0
  242. package/dist/web/layout/sidebar.d.ts +17 -0
  243. package/dist/web/layout/sidebar.js +11 -0
  244. package/dist/web/layout/target-resolver-stub.d.ts +13 -0
  245. package/dist/web/layout/target-resolver-stub.js +61 -0
  246. package/dist/web/layout/target-url.d.ts +12 -0
  247. package/dist/web/layout/target-url.js +77 -0
  248. package/dist/web/layout/theme-label.d.ts +15 -0
  249. package/dist/web/layout/theme-label.js +35 -0
  250. package/dist/web/layout/theme-menu-item.d.ts +12 -0
  251. package/dist/web/layout/theme-menu-item.js +16 -0
  252. package/dist/web/layout/theme-toggle.d.ts +17 -0
  253. package/dist/web/layout/theme-toggle.js +22 -0
  254. package/dist/web/layout/topbar.d.ts +8 -0
  255. package/dist/web/layout/topbar.js +4 -0
  256. package/dist/web/layout/workspace-shell.d.ts +63 -0
  257. package/dist/web/layout/workspace-shell.js +220 -0
  258. package/dist/web/layout/workspace-switcher.d.ts +15 -0
  259. package/dist/web/layout/workspace-switcher.js +36 -0
  260. package/dist/web/lib/accept-attr.d.ts +1 -0
  261. package/dist/web/lib/accept-attr.js +6 -0
  262. package/dist/web/lib/clamp.d.ts +1 -0
  263. package/dist/web/lib/clamp.js +3 -0
  264. package/dist/web/lib/cn.d.ts +6 -0
  265. package/dist/web/lib/cn.js +9 -0
  266. package/dist/web/lib/download.d.ts +2 -0
  267. package/dist/web/lib/download.js +24 -0
  268. package/dist/web/lib/file-ref-download.d.ts +15 -0
  269. package/dist/web/lib/file-ref-download.js +62 -0
  270. package/dist/web/lib/file-upload-form-data.d.ts +7 -0
  271. package/dist/web/lib/file-upload-form-data.js +11 -0
  272. package/dist/web/lib/resize-image.d.ts +1 -0
  273. package/dist/web/lib/resize-image.js +66 -0
  274. package/dist/web/lib/upload-file-ref.d.ts +9 -0
  275. package/dist/web/lib/upload-file-ref.js +29 -0
  276. package/dist/web/primitives/action-menu.d.ts +34 -0
  277. package/dist/web/primitives/action-menu.js +30 -0
  278. package/dist/web/primitives/calendar-popover.d.ts +13 -0
  279. package/dist/web/primitives/calendar-popover.js +76 -0
  280. package/dist/web/primitives/combobox.d.ts +56 -0
  281. package/dist/web/primitives/combobox.js +127 -0
  282. package/dist/web/primitives/date-field.d.ts +18 -0
  283. package/dist/web/primitives/date-field.js +74 -0
  284. package/dist/web/primitives/date-input.d.ts +1 -0
  285. package/dist/web/primitives/date-input.js +5 -0
  286. package/dist/web/primitives/date-parse.d.ts +11 -0
  287. package/dist/web/primitives/date-parse.js +159 -0
  288. package/dist/web/primitives/dialog.d.ts +3 -0
  289. package/dist/web/primitives/dialog.js +42 -0
  290. package/dist/web/primitives/drawer.d.ts +3 -0
  291. package/dist/web/primitives/drawer.js +17 -0
  292. package/dist/web/primitives/dropdown-menu.d.ts +15 -0
  293. package/dist/web/primitives/dropdown-menu.js +56 -0
  294. package/dist/web/primitives/embedded-list-input.d.ts +9 -0
  295. package/dist/web/primitives/embedded-list-input.js +382 -0
  296. package/dist/web/primitives/file-thumbnail.d.ts +31 -0
  297. package/dist/web/primitives/file-thumbnail.js +90 -0
  298. package/dist/web/primitives/file-upload.d.ts +21 -0
  299. package/dist/web/primitives/file-upload.js +56 -0
  300. package/dist/web/primitives/file-value-list.d.ts +3 -0
  301. package/dist/web/primitives/file-value-list.js +22 -0
  302. package/dist/web/primitives/index.d.ts +34 -0
  303. package/dist/web/primitives/index.js +2023 -0
  304. package/dist/web/primitives/json-view.d.ts +7 -0
  305. package/dist/web/primitives/json-view.js +84 -0
  306. package/dist/web/primitives/layout.d.ts +27 -0
  307. package/dist/web/primitives/layout.js +30 -0
  308. package/dist/web/primitives/lightbox.d.ts +3 -0
  309. package/dist/web/primitives/lightbox.js +36 -0
  310. package/dist/web/primitives/locale-number.d.ts +2 -0
  311. package/dist/web/primitives/locale-number.js +54 -0
  312. package/dist/web/primitives/located-timestamp-input.d.ts +22 -0
  313. package/dist/web/primitives/located-timestamp-input.js +22 -0
  314. package/dist/web/primitives/metric.d.ts +5 -0
  315. package/dist/web/primitives/metric.js +18 -0
  316. package/dist/web/primitives/modal-shell.d.ts +17 -0
  317. package/dist/web/primitives/modal-shell.js +9 -0
  318. package/dist/web/primitives/modal.d.ts +3 -0
  319. package/dist/web/primitives/modal.js +13 -0
  320. package/dist/web/primitives/money-input.d.ts +18 -0
  321. package/dist/web/primitives/money-input.js +122 -0
  322. package/dist/web/primitives/narrow-pinned-footer.d.ts +12 -0
  323. package/dist/web/primitives/narrow-pinned-footer.js +153 -0
  324. package/dist/web/primitives/number-input.d.ts +18 -0
  325. package/dist/web/primitives/number-input.js +53 -0
  326. package/dist/web/primitives/option-groups.d.ts +11 -0
  327. package/dist/web/primitives/option-groups.js +27 -0
  328. package/dist/web/primitives/page-header.d.ts +3 -0
  329. package/dist/web/primitives/page-header.js +52 -0
  330. package/dist/web/primitives/promo-panel.d.ts +3 -0
  331. package/dist/web/primitives/promo-panel.js +11 -0
  332. package/dist/web/primitives/segmented-select.d.ts +21 -0
  333. package/dist/web/primitives/segmented-select.js +62 -0
  334. package/dist/web/primitives/share-actions.d.ts +4 -0
  335. package/dist/web/primitives/share-actions.js +56 -0
  336. package/dist/web/primitives/status-badge.d.ts +3 -0
  337. package/dist/web/primitives/status-badge.js +5 -0
  338. package/dist/web/primitives/sticky-action-bar.d.ts +5 -0
  339. package/dist/web/primitives/sticky-action-bar.js +15 -0
  340. package/dist/web/primitives/tabs.d.ts +3 -0
  341. package/dist/web/primitives/tabs.js +107 -0
  342. package/dist/web/primitives/timestamp-input.d.ts +27 -0
  343. package/dist/web/primitives/timestamp-input.js +87 -0
  344. package/dist/web/primitives/toast.d.ts +19 -0
  345. package/dist/web/primitives/toast.js +63 -0
  346. package/dist/web/primitives/tz-input.d.ts +11 -0
  347. package/dist/web/primitives/tz-input.js +8 -0
  348. package/dist/web/primitives/tz-options.d.ts +4 -0
  349. package/dist/web/primitives/tz-options.js +17 -0
  350. package/dist/web/primitives/use-keyboard-inset.d.ts +1 -0
  351. package/dist/web/primitives/use-keyboard-inset.js +28 -0
  352. package/dist/web/primitives/use-narrow-viewport.d.ts +4 -0
  353. package/dist/web/primitives/use-narrow-viewport.js +46 -0
  354. package/dist/web/react-css-custom-properties.d.ts +6 -0
  355. package/dist/web/react-css-custom-properties.js +1 -0
  356. package/dist/web/sse/live-events.d.ts +15 -0
  357. package/dist/web/sse/live-events.js +148 -0
  358. package/dist/web/theme-plugin.d.ts +41 -0
  359. package/dist/web/theme-plugin.js +123 -0
  360. package/dist/web/tokens.d.ts +24 -0
  361. package/dist/web/tokens.js +203 -0
  362. package/dist/web/ui/avatar.d.ts +11 -0
  363. package/dist/web/ui/avatar.js +25 -0
  364. package/dist/web/ui/badge.d.ts +9 -0
  365. package/dist/web/ui/badge.js +26 -0
  366. package/dist/web/ui/breadcrumb.d.ts +11 -0
  367. package/dist/web/ui/breadcrumb.js +29 -0
  368. package/dist/web/ui/button.d.ts +10 -0
  369. package/dist/web/ui/button.js +37 -0
  370. package/dist/web/ui/checkbox.d.ts +4 -0
  371. package/dist/web/ui/checkbox.js +11 -0
  372. package/dist/web/ui/input.d.ts +3 -0
  373. package/dist/web/ui/input.js +8 -0
  374. package/dist/web/ui/label.d.ts +4 -0
  375. package/dist/web/ui/label.js +10 -0
  376. package/dist/web/ui/resizable.d.ts +7 -0
  377. package/dist/web/ui/resizable.js +16 -0
  378. package/dist/web/ui/separator.d.ts +4 -0
  379. package/dist/web/ui/separator.js +10 -0
  380. package/dist/web/ui/sheet.d.ts +14 -0
  381. package/dist/web/ui/sheet.js +42 -0
  382. package/dist/web/ui/sidebar.d.ts +73 -0
  383. package/dist/web/ui/sidebar.js +211 -0
  384. package/dist/web/ui/skeleton.d.ts +2 -0
  385. package/dist/web/ui/skeleton.js +7 -0
  386. package/dist/web/ui/switch.d.ts +6 -0
  387. package/dist/web/ui/switch.js +10 -0
  388. package/dist/web/ui/table.d.ts +10 -0
  389. package/dist/web/ui/table.js +30 -0
  390. package/dist/web/ui/tabs.d.ts +11 -0
  391. package/dist/web/ui/tabs.js +31 -0
  392. package/dist/web/ui/textarea.d.ts +3 -0
  393. package/dist/web/ui/textarea.js +8 -0
  394. package/dist/web/ui/tooltip.d.ts +7 -0
  395. package/dist/web/ui/tooltip.js +19 -0
  396. package/dist/web/ui/use-mobile.d.ts +1 -0
  397. package/dist/web/ui/use-mobile.js +16 -0
  398. package/dist/web/version/update-checker.d.ts +9 -0
  399. package/dist/web/version/update-checker.js +88 -0
  400. package/dist/web/widgets/ai-text-field.d.ts +36 -0
  401. package/dist/web/widgets/ai-text-field.js +137 -0
  402. package/dist/web/widgets/bounded-load-cache.d.ts +1 -0
  403. package/dist/web/widgets/bounded-load-cache.js +25 -0
  404. package/dist/web/widgets/chart-window.d.ts +58 -0
  405. package/dist/web/widgets/chart-window.js +190 -0
  406. package/dist/web/widgets/charts.d.ts +208 -0
  407. package/dist/web/widgets/charts.js +685 -0
  408. package/dist/web/widgets/collapsible-section.d.ts +10 -0
  409. package/dist/web/widgets/collapsible-section.js +17 -0
  410. package/dist/web/widgets/dashboard-list.d.ts +21 -0
  411. package/dist/web/widgets/dashboard-list.js +45 -0
  412. package/dist/web/widgets/detail-list.d.ts +15 -0
  413. package/dist/web/widgets/detail-list.js +8 -0
  414. package/dist/web/widgets/drawer.d.ts +65 -0
  415. package/dist/web/widgets/drawer.js +177 -0
  416. package/dist/web/widgets/feed-list.d.ts +13 -0
  417. package/dist/web/widgets/feed-list.js +9 -0
  418. package/dist/web/widgets/floating-panel.d.ts +30 -0
  419. package/dist/web/widgets/floating-panel.js +242 -0
  420. package/dist/web/widgets/form-fields.d.ts +93 -0
  421. package/dist/web/widgets/form-fields.js +50 -0
  422. package/dist/web/widgets/index.d.ts +28 -0
  423. package/dist/web/widgets/index.js +31 -0
  424. package/dist/web/widgets/infinity-list.d.ts +46 -0
  425. package/dist/web/widgets/infinity-list.js +211 -0
  426. package/dist/web/widgets/mode-switch.d.ts +21 -0
  427. package/dist/web/widgets/mode-switch.js +25 -0
  428. package/dist/web/widgets/pdf-preview.d.ts +10 -0
  429. package/dist/web/widgets/pdf-preview.js +140 -0
  430. package/dist/web/widgets/photo-slots.d.ts +29 -0
  431. package/dist/web/widgets/photo-slots.js +52 -0
  432. package/dist/web/widgets/plan-card.d.ts +36 -0
  433. package/dist/web/widgets/plan-card.js +13 -0
  434. package/dist/web/widgets/progress-bar.d.ts +19 -0
  435. package/dist/web/widgets/progress-bar.js +24 -0
  436. package/dist/web/widgets/progress-list.d.ts +19 -0
  437. package/dist/web/widgets/progress-list.js +11 -0
  438. package/dist/web/widgets/public-shell.d.ts +22 -0
  439. package/dist/web/widgets/public-shell.js +15 -0
  440. package/dist/web/widgets/query-table.d.ts +29 -0
  441. package/dist/web/widgets/query-table.js +30 -0
  442. package/dist/web/widgets/result-panel.d.ts +69 -0
  443. package/dist/web/widgets/result-panel.js +30 -0
  444. package/dist/web/widgets/section-card.d.ts +12 -0
  445. package/dist/web/widgets/section-card.js +9 -0
  446. package/dist/web/widgets/sheet-parts.d.ts +9 -0
  447. package/dist/web/widgets/sheet-parts.js +11 -0
  448. package/dist/web/widgets/side-by-side-table.d.ts +31 -0
  449. package/dist/web/widgets/side-by-side-table.js +11 -0
  450. package/dist/web/widgets/stat.d.ts +54 -0
  451. package/dist/web/widgets/stat.js +65 -0
  452. package/dist/web/widgets/states.d.ts +23 -0
  453. package/dist/web/widgets/states.js +20 -0
  454. package/dist/web/widgets/status-badge.d.ts +15 -0
  455. package/dist/web/widgets/status-badge.js +24 -0
  456. package/dist/web/widgets/step-bar.d.ts +35 -0
  457. package/dist/web/widgets/step-bar.js +60 -0
  458. package/dist/web/widgets/upload-zone.d.ts +24 -0
  459. package/dist/web/widgets/upload-zone.js +108 -0
  460. package/dist/web/widgets/use-draft.d.ts +20 -0
  461. package/dist/web/widgets/use-draft.js +21 -0
  462. package/dist/web/widgets/use-pointer-drag.d.ts +21 -0
  463. package/dist/web/widgets/use-pointer-drag.js +53 -0
  464. package/package.json +114 -7
  465. package/src/changes.json +92 -0
  466. package/src/web/fonts/OFL.txt +93 -0
  467. package/src/web/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
  468. package/src/web/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
  469. package/src/web/fonts/ibm-plex-mono-latin-ext-400.woff2 +0 -0
  470. package/src/web/fonts/ibm-plex-mono-latin-ext-500.woff2 +0 -0
  471. package/src/web/fonts/ibm-plex-sans-latin-400.woff2 +0 -0
  472. package/src/web/fonts/ibm-plex-sans-latin-500.woff2 +0 -0
  473. package/src/web/fonts/ibm-plex-sans-latin-600.woff2 +0 -0
  474. package/src/web/fonts/ibm-plex-sans-latin-ext-400.woff2 +0 -0
  475. package/src/web/fonts/ibm-plex-sans-latin-ext-500.woff2 +0 -0
  476. package/src/web/fonts/ibm-plex-sans-latin-ext-600.woff2 +0 -0
  477. package/src/web/styles.css +405 -0
@@ -0,0 +1,16 @@
1
+ import type { EntityDefinition, EntityListScreenDefinition } from "@cosmicdrift/kumiko-framework/ui-types";
2
+ import type { ListViewModel, Translate } from "./types.ts";
3
+ export type ComputeListViewModelInput = {
4
+ readonly screen: EntityListScreenDefinition;
5
+ readonly entity: EntityDefinition;
6
+ readonly rows: readonly Readonly<Record<string, unknown>>[];
7
+ readonly translate: Translate;
8
+ readonly featureName: string;
9
+ };
10
+ export declare function computeListViewModel(input: ComputeListViewModelInput): ListViewModel;
11
+ export declare function fieldLabelKey(featureName: string, entityName: string, fieldName: string): string;
12
+ export declare function fieldOptionLabelKeyPrefix(featureName: string, entityName: string, fieldName: string): string;
13
+ export declare function fieldOptionLabelKey(featureName: string, entityName: string, fieldName: string, value: string): string;
14
+ export declare function embeddedCellLabelKey(featureName: string, entityName: string, fieldName: string, subFieldName: string): string;
15
+ export declare function embeddedCellOptionLabelKey(featureName: string, entityName: string, fieldName: string, subFieldName: string, value: string): string;
16
+ export declare function buildOptionLabels(translate: (key: string, params?: Readonly<Record<string, unknown>>) => string, keyFor: (value: string) => string, options: readonly string[]): Readonly<Record<string, string>>;
@@ -0,0 +1,229 @@
1
+ import { LIST_ROW_META_COLUMNS, LIST_ROW_META_REFERENCES, normalizeListColumn, parseRefTarget, } from "@cosmicdrift/kumiko-framework/ui-types";
2
+ import { deriveListFileDisplay } from "./list-file-display.js";
3
+ const WRITE_ONLY_SET_LABEL_KEY = "kumiko.field.writeOnly.set";
4
+ // Pure transform: takes the declared screen + entity + incoming rows, spits
5
+ // out the flat shape the renderer draws. No conditions, no access-checks —
6
+ // those are list-level decisions that the caller makes BEFORE calling
7
+ // here (e.g. filtering rows by ownership on the server / before query).
8
+ // Field-level read-access (Level 3 of UI-architecture.md §Permission) is a
9
+ // follow-up; this v1 assumes the caller passed a row-filter that drops any
10
+ // field the user may not see.
11
+ export function computeListViewModel(input) {
12
+ const { screen, entity, rows, translate, featureName } = input;
13
+ const columns = [];
14
+ for (const spec of screen.columns) {
15
+ const normalized = normalizeListColumn(spec);
16
+ const storedFieldType = entity.fields[normalized.field]?.type;
17
+ // A real non-text entity field keeps its own type (documented on
18
+ // ListColumnSpec.refEntity); only the all-"text" pseudo-entities of the
19
+ // projection shims and fields without a stored def take the declared path.
20
+ if (normalized.refEntity !== undefined &&
21
+ (storedFieldType === undefined || storedFieldType === "text")) {
22
+ // Declared reference metadata (ListColumnSpec.refEntity) — for
23
+ // projectionList/relatedList columns, which have no EntityDefinition
24
+ // field to carry a real "reference" type. Checked before the
25
+ // entity.fields lookup below so it also fires against the pseudo-
26
+ // entities that hardcode every field as "text" (projection-list-shim,
27
+ // related-list-section) — those never reach the reference branch
28
+ // further down since fieldDef.type is always "text" there.
29
+ const refTarget = parseRefTarget(normalized.refEntity, featureName);
30
+ columns.push({
31
+ field: normalized.field,
32
+ label: translate(normalized.label ?? fieldLabelKey(featureName, screen.entity, normalized.field)),
33
+ type: "reference",
34
+ // The declared value is the referenced id, not the resolved label —
35
+ // there is no column to server-sort by, same as row-meta references.
36
+ sortable: false,
37
+ refEntity: refTarget.entityName,
38
+ refFeature: refTarget.featureName,
39
+ refLabelField: normalized.refLabelField ?? "id",
40
+ ...(normalized.renderer !== undefined && { renderer: normalized.renderer }),
41
+ ...(normalized.hideOnNarrow === true && { hideOnNarrow: true }),
42
+ });
43
+ continue;
44
+ }
45
+ const fieldDef = entity.fields[normalized.field];
46
+ if (!fieldDef) {
47
+ // Not a stored field — may be a read-time derived field (value appended
48
+ // by the list-query handler). Render it as its display valueType; derived
49
+ // columns carry no reference/select metadata and never server-sort.
50
+ const derivedDef = entity.derivedFields?.[normalized.field];
51
+ if (!derivedDef) {
52
+ // Row-meta column (id/tenantId/version/insertedAt/modifiedAt/...) —
53
+ // a real base-table column that's never a declared entity field, e.g.
54
+ // a SystemAdmin cross-tenant list exposing tenantId. Unlike the
55
+ // derivedFields branch above, these are actual DB columns, so
56
+ // server-side ORDER BY works — sortable stays true, except for the
57
+ // ID columns in LIST_ROW_META_REFERENCES (see their reference branch).
58
+ const rowMetaType = LIST_ROW_META_COLUMNS[normalized.field];
59
+ if (rowMetaType !== undefined) {
60
+ const rowMetaRef = LIST_ROW_META_REFERENCES[normalized.field];
61
+ columns.push({
62
+ field: normalized.field,
63
+ label: translate(normalized.label ?? fieldLabelKey(featureName, screen.entity, normalized.field)),
64
+ type: rowMetaRef !== undefined ? "reference" : rowMetaType,
65
+ // The DB column holds the GUID, not the resolved label — server-side
66
+ // ORDER BY would sort by GUID while the cell shows the name.
67
+ sortable: rowMetaRef === undefined,
68
+ ...(normalized.renderer !== undefined && { renderer: normalized.renderer }),
69
+ ...(normalized.hideOnNarrow === true && { hideOnNarrow: true }),
70
+ ...(rowMetaRef !== undefined && {
71
+ refEntity: rowMetaRef.refEntity,
72
+ refFeature: rowMetaRef.refFeature,
73
+ refLabelField: rowMetaRef.refLabelField,
74
+ }),
75
+ });
76
+ continue;
77
+ }
78
+ // A virtual presentational column — drawn entirely by a columnRenderer
79
+ // component from the row (e.g. tag chips); value is undefined and it
80
+ // never server-sorts. `field` is just the column key. It needs BOTH a
81
+ // label AND a renderer — renderer is what actually draws it; a label
82
+ // alone with no renderer would push an empty, unrendered column into
83
+ // the view model. Missing either is an author typo (or a stale
84
+ // field-rename) → fail loud instead of silently drawing nothing.
85
+ if (normalized.label !== undefined && normalized.renderer !== undefined) {
86
+ columns.push({
87
+ field: normalized.field,
88
+ label: translate(normalized.label),
89
+ type: "text",
90
+ sortable: false,
91
+ renderer: normalized.renderer,
92
+ ...(normalized.hideOnNarrow === true && { hideOnNarrow: true }),
93
+ });
94
+ continue;
95
+ }
96
+ throw new Error(`computeListViewModel: screen "${screen.id}" references unknown field "${normalized.field}" on entity "${screen.entity}"`);
97
+ }
98
+ columns.push({
99
+ field: normalized.field,
100
+ label: translate(normalized.label ?? fieldLabelKey(featureName, screen.entity, normalized.field)),
101
+ type: derivedDef.valueType,
102
+ // Display-only: a header sort would round-trip to the server, which has
103
+ // no column to sort by (see DerivedFieldDef). Never offer the affordance.
104
+ sortable: false,
105
+ ...(normalized.renderer !== undefined && { renderer: normalized.renderer }),
106
+ ...(normalized.hideOnNarrow === true && { hideOnNarrow: true }),
107
+ });
108
+ continue;
109
+ }
110
+ const label = translate(normalized.label ?? fieldLabelKey(featureName, screen.entity, normalized.field));
111
+ // Tier 2.7e-3 + Cross-Feature: Reference-Field — entity-String
112
+ // kann same-feature ("user") oder cross-feature ("users:user")
113
+ // sein. parseRefTarget gibt (featureName, entityName), der
114
+ // Renderer baut die Lookup-QN als
115
+ // `<refFeature>:query:<refEntity>:list`.
116
+ const refRaw = fieldDef.type === "reference"
117
+ ? fieldDef.entity
118
+ : undefined;
119
+ const refTarget = refRaw !== undefined ? parseRefTarget(refRaw, featureName) : undefined;
120
+ const refEntity = refTarget?.entityName;
121
+ const refFeature = refTarget?.featureName;
122
+ const refLabelField = fieldDef.type === "reference"
123
+ ? (fieldDef.labelField ?? "id")
124
+ : undefined;
125
+ // For select and multiSelect fields: bake in translated option labels.
126
+ // Convention matches the form path → one translation source for list +
127
+ // form. A missing key returns the key itself per convention; the
128
+ // renderer then falls back to humanizeSlug.
129
+ const optionLabels = fieldDef.type === "select" || fieldDef.type === "multiSelect"
130
+ ? buildOptionLabels(translate, (value) => fieldOptionLabelKey(featureName, screen.entity, normalized.field, value), fieldDef.options)
131
+ : undefined;
132
+ const optionTones = fieldDef.type === "select" ? fieldDef.optionTones : undefined;
133
+ const grouping = fieldDef.type === "number" ? fieldDef.grouping : undefined;
134
+ const fileDisplay = deriveListFileDisplay(fieldDef, normalized.renderer);
135
+ const column = {
136
+ field: normalized.field,
137
+ label,
138
+ type: fieldDef.type,
139
+ sortable: fieldIsSortable(fieldDef),
140
+ ...(normalized.renderer !== undefined && { renderer: normalized.renderer }),
141
+ ...(optionLabels !== undefined && { optionLabels }),
142
+ ...(optionTones !== undefined && { optionTones }),
143
+ ...(refEntity !== undefined && { refEntity }),
144
+ ...(refFeature !== undefined && { refFeature }),
145
+ ...(refLabelField !== undefined && { refLabelField }),
146
+ ...(grouping !== undefined && { grouping }),
147
+ ...(fileDisplay !== undefined && { fileDisplay }),
148
+ ...(normalized.hideOnNarrow === true && { hideOnNarrow: true }),
149
+ };
150
+ columns.push(column);
151
+ }
152
+ const writeOnlyFieldNames = screen.columns
153
+ .map((spec) => normalizeListColumn(spec).field)
154
+ .filter((name) => {
155
+ const fieldDef = entity.fields[name];
156
+ return fieldDef?.type === "text" && fieldDef.writeOnly === true;
157
+ });
158
+ // The wire carries `true` (set) / `null` (empty) for writeOnly fields; the cell shows a word, not "true".
159
+ const showWriteOnlyAsWord = (row) => {
160
+ const shown = { ...row };
161
+ for (const name of writeOnlyFieldNames) {
162
+ if (row[name] === true)
163
+ shown[name] = translate(WRITE_ONLY_SET_LABEL_KEY);
164
+ }
165
+ return shown;
166
+ };
167
+ const listRows = rows.map((row) => ({
168
+ id: String(row["id"] ?? ""),
169
+ values: showWriteOnlyAsWord(row),
170
+ }));
171
+ return {
172
+ screenId: screen.id,
173
+ entityName: screen.entity,
174
+ columns,
175
+ rows: listRows,
176
+ ...(screen.slots && { slots: screen.slots }),
177
+ isEmpty: listRows.length === 0,
178
+ };
179
+ }
180
+ // Field-i18n-key convention matches what features register translations
181
+ // under (see packages/framework/src/i18n/ for the pattern). Duplicated
182
+ // here as a plain function — the ui-core boundary forbids depending on
183
+ // the i18n module directly.
184
+ export function fieldLabelKey(featureName, entityName, fieldName) {
185
+ return `${featureName}:entity:${entityName}:field:${fieldName}`;
186
+ }
187
+ export function fieldOptionLabelKeyPrefix(featureName, entityName, fieldName) {
188
+ return `${fieldLabelKey(featureName, entityName, fieldName)}:option:`;
189
+ }
190
+ export function fieldOptionLabelKey(featureName, entityName, fieldName, value) {
191
+ return `${fieldOptionLabelKeyPrefix(featureName, entityName, fieldName)}${value}`;
192
+ }
193
+ // Embedded-list cell label key — one level deeper than fieldLabelKey,
194
+ // keyed by the sub-field name inside an embedded-LIST field's `schema`
195
+ // (invoice-positions-style tables built via createEmbeddedListField()).
196
+ export function embeddedCellLabelKey(featureName, entityName, fieldName, subFieldName) {
197
+ return `${featureName}:entity:${entityName}:field:${fieldName}:cell:${subFieldName}`;
198
+ }
199
+ export function embeddedCellOptionLabelKey(featureName, entityName, fieldName, subFieldName, value) {
200
+ return `${featureName}:entity:${entityName}:field:${fieldName}:cell:${subFieldName}:option:${value}`;
201
+ }
202
+ // Build a value→label map for a select-field's options. Convention:
203
+ // translate() returns the input key when the lookup misses (i18next
204
+ // default + LocaleResolver convention) — we surface the *raw value* in
205
+ // that case so the renderer's humanizeSlug fallback can take over.
206
+ // Without that fallback, an unlabeled option would render as the full
207
+ // `feature:entity:field:option:value`-key.
208
+ //
209
+ // `keyFor` carries whichever key convention the caller needs (top-level
210
+ // field via fieldOptionLabelKey, embedded-list cell via
211
+ // embeddedCellOptionLabelKey) — shared between list-VM, edit-VM, and
212
+ // embedded-list cells so all three produce identical option-translations.
213
+ export function buildOptionLabels(translate, keyFor, options) {
214
+ const out = {};
215
+ for (const value of options) {
216
+ const key = keyFor(value);
217
+ const translated = translate(key);
218
+ out[value] = translated === key ? value : translated;
219
+ }
220
+ return out;
221
+ }
222
+ // A field can declare `sortable: true` on the FieldDefinition. This is
223
+ // framework-level metadata used both by the server's list-query builder
224
+ // (ORDER BY safety) and by the UI (column header click indicator). All
225
+ // field types can bear the flag; it's off by default.
226
+ function fieldIsSortable(field) {
227
+ const flag = field.sortable;
228
+ return flag === true;
229
+ }
@@ -0,0 +1,382 @@
1
+ import type { EditFieldSpec, EditSectionSpec, FieldAffix, FieldFillAction, FieldIconKey, FieldRenderer, IconKey, ListColumnSpec, ListFacetSpec, ListSortSpec, OptionsQueryPayload, PlatformComponent, RelatedListGroupBy, RelatedListRowTone, RelatedListToolbarAction, RowAction, RowActionMode, ScreenSlots, SelectOptionTone } from "@cosmicdrift/kumiko-framework/ui-types";
2
+ export type RuntimeRenderer = (value: unknown, row?: Readonly<Record<string, unknown>>) => string;
3
+ /** Where a cell's text links to. `href` comes from NavApi.hrefFor (new-tab and
4
+ * copy-link work); `onPress` is the in-app navigation for a plain click. */
5
+ export type CellLink = {
6
+ readonly href: string;
7
+ readonly onPress: () => void;
8
+ };
9
+ /** Runtime-only like RuntimeRenderer; undefined means the cell stays plain text. */
10
+ export type RuntimeCellLink = (value: unknown, row?: Readonly<Record<string, unknown>>) => CellLink | undefined;
11
+ /** One entry of a multi-reference cell: its label, linked when the target is readable. */
12
+ export type CellLinkItem = {
13
+ readonly id: string;
14
+ readonly label: string;
15
+ readonly link?: CellLink;
16
+ };
17
+ /** Runtime-only like RuntimeCellLink; undefined means the cell uses its single renderer. */
18
+ export type RuntimeCellLinkItems = (value: unknown, row?: Readonly<Record<string, unknown>>) => readonly CellLinkItem[] | undefined;
19
+ /** How a list cell shows a FileRef value (id or id array). */
20
+ export type ListColumnFileDisplay = {
21
+ readonly kind: "image";
22
+ readonly variant?: string;
23
+ } | {
24
+ readonly kind: "file";
25
+ };
26
+ export type ListColumnViewModel = {
27
+ readonly field: string;
28
+ readonly label: string;
29
+ readonly type: string;
30
+ readonly renderer?: FieldRenderer | RuntimeRenderer;
31
+ readonly linkFor?: RuntimeCellLink;
32
+ readonly linkItemsFor?: RuntimeCellLinkItems;
33
+ readonly sortable: boolean;
34
+ /** Only for `type: "select"` or `type: "multiSelect"` — translated option
35
+ * labels keyed by raw value. The renderer renders `optionLabels[value]`
36
+ * instead of humanizeSlug when present. Convention key:
37
+ * `<feature>:entity:<entity>:field:<field>:option:<value>`. */
38
+ readonly optionLabels?: Readonly<Record<string, string>>;
39
+ /** Only for `type: "select"` — declared tone per raw option value. */
40
+ readonly optionTones?: Readonly<Partial<Record<string, SelectOptionTone>>>;
41
+ /** Only for `type: "reference"` — referenced entity name for the bulk
42
+ * lookup in the renderer (`<refFeature>:query:<refEntity>:list`). */
43
+ readonly refEntity?: string;
44
+ /** Only for `type: "reference"` — name of the feature the referenced
45
+ * entity lives in. Default = current feature. Cross-feature via the
46
+ * qualified form ("feature:entity") on ReferenceFieldDef. */
47
+ readonly refFeature?: string;
48
+ /** Only for `type: "reference"` — which field of the referenced entity
49
+ * appears as the display value in the cell (default "id"). */
50
+ readonly refLabelField?: string;
51
+ /** Set by the caller at runtime (not schema-derived) to emphasize one
52
+ * column — e.g. the currently selected base-year column in a
53
+ * multi-year statement grid. DataTable renders it with a distinct
54
+ * header/cell background. */
55
+ readonly highlighted?: boolean;
56
+ /** Mirrors `ListColumnSpec.hideOnNarrow`: card layout skips the column. */
57
+ readonly hideOnNarrow?: boolean;
58
+ /** Only for `type: "number"` — mirrors `NumberFieldDef.grouping` (default
59
+ * `true`). `false` renders without thousands-separators (e.g. a model
60
+ * year). */
61
+ readonly grouping?: boolean;
62
+ /** Set for file/image columns: from the entity field type, or from a
63
+ * `{ format: "image" | "file" }` renderer. The cell shows a thumbnail or the
64
+ * file name instead of the FileRef UUID. */
65
+ readonly fileDisplay?: ListColumnFileDisplay;
66
+ };
67
+ export type ListRowViewModel = {
68
+ readonly id: string;
69
+ readonly values: Readonly<Record<string, unknown>>;
70
+ };
71
+ export type ListViewModel = {
72
+ readonly screenId: string;
73
+ readonly entityName: string;
74
+ readonly columns: readonly ListColumnViewModel[];
75
+ readonly rows: readonly ListRowViewModel[];
76
+ readonly slots?: ScreenSlots;
77
+ readonly isEmpty: boolean;
78
+ };
79
+ export type EmbeddedListCellViewModel = {
80
+ readonly field: string;
81
+ readonly label: string;
82
+ readonly type: "text" | "number" | "boolean" | "date" | "money" | "decimal" | "select" | "reference" | "timestamp";
83
+ readonly required: boolean;
84
+ /** Only for `type: "select"`. */
85
+ readonly options?: readonly string[];
86
+ readonly optionLabels?: Readonly<Record<string, string>>;
87
+ /** Only for `type: "select"`; `"radio"` renders segmented buttons instead of a dropdown. */
88
+ readonly display?: "radio" | "dropdown";
89
+ /** Cell is shown but not editable (`EditFieldSpec.embeddedList.readOnlyCells`). */
90
+ readonly readOnly?: boolean;
91
+ /** Only for `type: "reference"`. */
92
+ readonly refEntity?: string;
93
+ readonly refFeature?: string;
94
+ readonly refLabelField?: string;
95
+ readonly refOptionsQuery?: string;
96
+ /** Only for `type: "decimal"`. */
97
+ readonly scale?: number;
98
+ };
99
+ export type EditFieldViewModel = {
100
+ readonly field: string;
101
+ readonly label: string;
102
+ readonly type: string;
103
+ readonly value: unknown;
104
+ readonly visible: boolean;
105
+ readonly readOnly: boolean;
106
+ readonly required: boolean;
107
+ readonly span?: number;
108
+ readonly renderer?: FieldRenderer;
109
+ /** Set for `type: "select"` and `type: "multiSelect"` — the allowed
110
+ * values. The renderer uses these as dropdown/combobox options.
111
+ * Source is SelectFieldDef.options / MultiSelectFieldDef.options on
112
+ * the EntityDefinition. */
113
+ readonly options?: readonly string[];
114
+ /** Set for `type: "select"` and `type: "multiSelect"` — translated
115
+ * labels per option, keyed by raw value. The renderer shows
116
+ * `optionLabels[value]` as the dropdown/combobox label instead of the
117
+ * raw value. Convention key:
118
+ * `<feature>:entity:<entity>:field:<field>:option:<value>`. */
119
+ readonly optionLabels?: Readonly<Record<string, string>>;
120
+ /** Set for `type: "select"` when SelectFieldDef.optionsQuery is set: the
121
+ * renderer loads the options from this query (`{ rows: { value, label,
122
+ * description?, group? }[] }`, labels verbatim) instead of `options`. `payload`
123
+ * is optionsQueryPayload (`{ field }` refs are resolved by the renderer against
124
+ * the live form values), `{}` when absent. */
125
+ readonly selectOptionsQuery?: {
126
+ readonly query: string;
127
+ readonly payload: OptionsQueryPayload;
128
+ };
129
+ /** Set for `type: "select"` / `"multiSelect"` when optionsAvailabilityQuery is set:
130
+ * the renderer loads `{ rows: { value, disabled?, hint? }[] }` from this query and
131
+ * merges it onto `options`. `payload` is optionsQueryPayload, `{}` when absent
132
+ * (always `{}` for multiSelect). */
133
+ readonly selectOptionsAvailabilityQuery?: {
134
+ readonly query: string;
135
+ readonly payload: OptionsQueryPayload;
136
+ };
137
+ /** Set for `type: "multiSelect"` when MultiSelectFieldDef.display is
138
+ * "checkboxes" — the renderer shows a checkbox grid with a select-all
139
+ * toggle instead of the default combobox dropdown. Set for
140
+ * `type: "select"` when SelectFieldDef.display is "radio" or "dropdown" —
141
+ * the renderer then skips its own radio-vs-dropdown heuristic. */
142
+ readonly display?: "checkboxes" | "dropdown" | "radio";
143
+ /** Set for `type: "multiSelect"` when MultiSelectFieldDef.columns is
144
+ * defined — column count for the checkbox grid at the widest breakpoint.
145
+ * Ignored unless `display` is "checkboxes". */
146
+ readonly columns?: 1 | 2 | 3 | 4;
147
+ /** Set for `type: "multiSelect"` when MultiSelectFieldDef.maxRows is
148
+ * defined — grid rows visible before the checkbox grid becomes
149
+ * scrollable. Ignored unless `display` is "checkboxes". */
150
+ readonly maxRows?: number;
151
+ /** For `type: "text"`, set when TextFieldDef.multiline is true — the
152
+ * renderer then renders a textarea instead of a single-line input.
153
+ * `type: "longText"` always renders a textarea regardless of this
154
+ * value; here it only carries an optional `{ rows }` override.
155
+ * `true` = default rows, `{ rows }` = explicit height. */
156
+ readonly multiline?: boolean | {
157
+ readonly rows?: number;
158
+ };
159
+ /** From TextFieldDef.format — `password` makes the renderer mask the input. */
160
+ readonly format?: "email" | "url" | "phone" | "password" | "month";
161
+ /** From TextFieldDef.autoComplete — HTML autocomplete token for the text input. */
162
+ readonly autoComplete?: string;
163
+ /** From TextFieldDef.writeOnly — value is `true` (set) / `null` (empty), never plaintext. */
164
+ readonly writeOnly?: true;
165
+ /** From the field's `sensitive: true` — the value must not leave the form (drafts, URL prefill). */
166
+ readonly sensitive?: true;
167
+ /** Only set for `type: "timestamp"` when TimestampFieldDef.locatedBy
168
+ * exists — wall-clock time without offset. The renderer then emits
169
+ * local time without `Z` instead of a UTC instant. */
170
+ readonly wallClock?: boolean;
171
+ /** Only for `type: "date" | "timestamp"` — date bounds (ISO) and
172
+ * format/locale override from the FieldDefinition. The renderer limits
173
+ * the picker with them; write validation runs separately via Zod. */
174
+ readonly min?: string;
175
+ readonly max?: string;
176
+ readonly dateLocale?: string;
177
+ /** Only for `type: "number"` — mirrors `NumberFieldDef.grouping` (default
178
+ * `true`). `false` renders without thousands-separators (e.g. a model
179
+ * year). */
180
+ readonly grouping?: boolean;
181
+ /** Only set for `type: "reference"`.
182
+ * The referenced entity (short, without feature prefix). The renderer
183
+ * builds the query QN as `<refFeature>:query:<refEntity>:list`. */
184
+ readonly refEntity?: string;
185
+ /** Only set for `type: "reference"` — name of the feature the
186
+ * referenced entity lives in. Same-feature default = current
187
+ * feature. Cross-feature is detected via "feature:entity" on
188
+ * ReferenceFieldDef.entity. */
189
+ readonly refFeature?: string;
190
+ /** Only set for `type: "reference"` — which field of the referenced
191
+ * entity appears as the display label in the dropdown. Default: "id". */
192
+ readonly refLabelField?: string;
193
+ /** Only for `type: "reference"` — query handler QN the picker sources its
194
+ * options from (fw#2780), replacing the referenced entity's list handler.
195
+ * Rows carry `{ id, label }`; `refLabelField` is then unused for the
196
+ * picker but still drives list cells. */
197
+ readonly refOptionsQuery?: string;
198
+ /** Only for `type: "reference"` — multi mode:
199
+ * the value is a UUID array, the renderer mounts a multi-combobox with tags. */
200
+ readonly refMultiple?: boolean;
201
+ /** Only for `type: "file" | "image"` — allowed extensions/MIME (e.g.
202
+ * ["jpg","png"]) + max size ("5mb"). The renderer sets the `accept`
203
+ * attribute and shows the limit; validation runs server-side in the
204
+ * upload endpoint against the field def. */
205
+ readonly accept?: readonly string[];
206
+ readonly maxSize?: string;
207
+ /** Only for `type: "files" | "images"` — upper bound on list length. */
208
+ readonly maxCount?: number;
209
+ /** Only for `type: "file" | "image"` — entity name + field name for the
210
+ * upload POST (`/api/files`), so the endpoint can check maxSize/accept
211
+ * against the right field def. */
212
+ readonly entityType?: string;
213
+ readonly fieldName?: string;
214
+ /** Record being edited (update mode only). Sent with the upload so the
215
+ * FileRef is attached to the record. */
216
+ readonly entityId?: string;
217
+ /** Only for `type: "image"` and `"images"` — the variant name the preview requests
218
+ * (`/api/files/:id/variant/:name`) instead of the original. The FIRST
219
+ * variant declared on the field def wins; a spec may legitimately carry
220
+ * neither `size` nor `maxEdge` (format-/blur-only), so "the smallest one"
221
+ * is not a rule that always has an answer. Absent when the field declares
222
+ * no variants — the preview then loads the original. */
223
+ readonly imageVariant?: string;
224
+ /** Only for `type: "image"` — forwarded to the file input's `capture`
225
+ * attribute so a phone opens the camera instead of the file picker. */
226
+ readonly capture?: "environment" | "user";
227
+ /** Closed FieldIconKey from EditFieldSpec.icon (FIELD_ICONS registry). */
228
+ readonly icon?: FieldIconKey;
229
+ /** From EditFieldSpec.placeholder, already translated — hint shown while the input is empty. */
230
+ readonly placeholder?: string;
231
+ /** From EditFieldSpec.prefix / suffix. A string affix is already translated;
232
+ * a `{ field }` affix stays a reference, the renderer reads it from the live form values. */
233
+ readonly prefix?: FieldAffix;
234
+ readonly suffix?: FieldAffix;
235
+ /** From EditFieldSpec.fillAction, `label` already translated. */
236
+ readonly fillAction?: FieldFillAction;
237
+ /** Only set for an embedded-LIST field (`multiple: true`) — the per-cell
238
+ * metadata the renderer needs to draw each column/cell. Absent for a
239
+ * plain (non-list) embedded field. */
240
+ readonly embeddedListCells?: readonly EmbeddedListCellViewModel[];
241
+ /** Minimum row count for the embedded list. From EmbeddedFieldDef.minItems. */
242
+ readonly embeddedListMinItems?: number;
243
+ /** Maximum row count for the embedded list. From EmbeddedFieldDef.maxItems. */
244
+ readonly embeddedListMaxItems?: number;
245
+ /** Sub-field name → how to compute its cell from other sub-fields of the
246
+ * same row. From EmbeddedFieldDef.derived. */
247
+ readonly embeddedListDerived?: Readonly<Record<string, {
248
+ readonly op: "multiply" | "sum" | "subtract" | "percent";
249
+ readonly from: readonly string[];
250
+ }>>;
251
+ /** Numeric sub-field names to sum in a totals row. From EmbeddedFieldDef.totals. */
252
+ readonly embeddedListTotals?: readonly string[];
253
+ /** No add, remove, duplicate or move; cells stay editable. From
254
+ * EditFieldSpec.embeddedList.fixedRows. */
255
+ readonly embeddedListFixedRows?: boolean;
256
+ /** Currency for the whole embedded list's money cells and totals row —
257
+ * currency lives on the head aggregate (EntityDefinition.defaultCurrency),
258
+ * not per row. Falls back to "EUR" when the entity has no defaultCurrency. */
259
+ readonly embeddedListCurrency?: string;
260
+ /** Only set for a plain (non-list, non-embedded) `type: "money"` field —
261
+ * same source as embeddedListCurrency (EntityDefinition.defaultCurrency,
262
+ * falls back to "EUR"). The renderer needs this to build the payload's
263
+ * `{amount, currency}` shape (kumiko-framework#1923). */
264
+ readonly currency?: string;
265
+ /** Only set for `type: "number"` when NumberFieldDef.unit is set — a static
266
+ * suffix string, or a sibling-field reference the renderer resolves against
267
+ * the live row values. Display-only, never converts the stored number. */
268
+ readonly unit?: string | {
269
+ readonly field: string;
270
+ };
271
+ };
272
+ export type EditSectionViewModel = EditFieldsSectionViewModel | EditExtensionSectionViewModel | EditRelatedListSectionViewModel | EditWriteFormSectionViewModel;
273
+ export type EditFieldsSectionViewModel = {
274
+ readonly kind: "fields";
275
+ /** From `EditFieldsSection.id`. The boot-validator makes it mandatory under
276
+ * `layout.mode: "tabs"` so the tab strip has a stable key per tab; other
277
+ * layouts leave it unset. */
278
+ readonly id?: string;
279
+ /** False when the section has fields but none of them is visible.
280
+ * The renderer then draws nothing, but the section stays in the array
281
+ * (key stability). */
282
+ readonly visible: boolean;
283
+ /** Set when every declared field was hidden by the create handler's
284
+ * `excludeFields`. Unlike a declared-empty section (review step), the
285
+ * renderer must not give it a tab or wizard step. */
286
+ readonly emptiedByWriteExclusion?: boolean;
287
+ /** Optional — eine titellose Section rendert nur ihre Felder (flache Form). */
288
+ readonly title?: string;
289
+ /** Translated help text under the block heading, from
290
+ * `EditFieldsSection.description`. Renders even without `title`. */
291
+ readonly description?: string;
292
+ /** Translated `EditFieldsSection.subtitle` (wizard step rail / up-next box). */
293
+ readonly subtitle?: string;
294
+ readonly columns: number;
295
+ readonly fields: readonly EditFieldViewModel[];
296
+ /** From `EditFieldsSection.groups` — each entry's `fields` are the same
297
+ * view-model objects as `fields` above, re-grouped (not recomputed). */
298
+ readonly groups?: readonly {
299
+ readonly title: string;
300
+ readonly columns: number;
301
+ readonly fields: readonly EditFieldViewModel[];
302
+ }[];
303
+ /** From `EditFieldsSection.icon` — closed IconKey vocabulary, renders
304
+ * left of the title. No effect without `title`. */
305
+ readonly icon?: IconKey;
306
+ /** From `EditFieldsSection.actions` — rendered in the Section's
307
+ * title row, same slot as the projectionDetail head card's actions. */
308
+ readonly actions?: readonly RowAction[];
309
+ };
310
+ export type EditExtensionSectionViewModel = {
311
+ readonly kind: "extension";
312
+ /** From `EditExtensionSection.id` — same tab-strip role as on a "fields"
313
+ * section, see EditFieldsSectionViewModel.id. */
314
+ readonly id?: string;
315
+ readonly title: string;
316
+ readonly component: PlatformComponent;
317
+ readonly contributesToFormSubmit: boolean;
318
+ /** Section-declared override — see `EditExtensionSection.entityName`. */
319
+ readonly entityName?: string;
320
+ /** From `EditExtensionSection.actions`. */
321
+ readonly actions?: readonly RowAction[];
322
+ };
323
+ export type EditRelatedListSectionViewModel = {
324
+ readonly kind: "relatedList";
325
+ readonly title: string;
326
+ readonly query: string;
327
+ readonly parentParam?: string;
328
+ readonly parentFilter?: {
329
+ readonly field: string;
330
+ };
331
+ readonly columns: readonly ListColumnSpec[];
332
+ readonly entity?: string;
333
+ readonly description?: string;
334
+ /** Untranslated plural-forms key, resolved with the row count by the list footer. */
335
+ readonly itemNoun?: string;
336
+ readonly pageSize?: number;
337
+ readonly defaultSort?: ListSortSpec;
338
+ readonly searchable?: boolean;
339
+ readonly facets?: readonly ListFacetSpec[];
340
+ readonly rowClick?: {
341
+ readonly entity: string;
342
+ readonly idColumn?: string;
343
+ };
344
+ readonly rowActions?: readonly RowAction[];
345
+ readonly rowActionMode?: RowActionMode;
346
+ readonly groupBy?: RelatedListGroupBy;
347
+ readonly rowTone?: RelatedListRowTone;
348
+ readonly toolbarActions?: readonly RelatedListToolbarAction[];
349
+ /** From `EditRelatedListSection.actions` — rendered in the
350
+ * Section's title row, distinct from `toolbarActions` (which render
351
+ * above the table itself). */
352
+ readonly actions?: readonly RowAction[];
353
+ /** From `EditRelatedListSection.emptyState` — forwarded to the
354
+ * DataTable's `emptyState` prop when the section has zero rows. */
355
+ readonly emptyState?: {
356
+ readonly title: string;
357
+ readonly description?: string;
358
+ readonly action?: RowAction;
359
+ };
360
+ };
361
+ export type EditWriteFormSectionViewModel = {
362
+ readonly kind: "writeForm";
363
+ readonly title?: string;
364
+ readonly description?: string;
365
+ readonly columns: number;
366
+ readonly fields: readonly EditFieldViewModel[];
367
+ readonly icon?: IconKey;
368
+ readonly handler: string;
369
+ readonly submitLabel?: string;
370
+ /** From `EditWriteFormSection.actions`. */
371
+ readonly actions?: readonly RowAction[];
372
+ };
373
+ export type EditViewModel = {
374
+ readonly screenId: string;
375
+ readonly entityName: string;
376
+ readonly id: string | null;
377
+ readonly sections: readonly EditSectionViewModel[];
378
+ readonly slots?: ScreenSlots;
379
+ };
380
+ export type Translate = (key: string, params?: Readonly<Record<string, unknown>>) => string;
381
+ export type FieldConditionCtx = unknown;
382
+ export type { EditFieldSpec, EditSectionSpec, FieldRenderer, ListColumnSpec, ScreenSlots };
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import type { DispatcherError } from "@cosmicdrift/kumiko-headless";
1
+ import type { DispatcherError } from "../headless/index.ts";
2
2
  export declare const AI_TEXT_RUN_QN = "ai-text:query:run";
3
3
  export type AiTextMode = "complete" | "correct" | "translate" | "rewrite";
4
4
  export type AiTextRewriteStyle = "formal" | "casual" | "concise" | "expand";
@@ -1,4 +1,4 @@
1
- import type { FormController, FormControllerOptions, FormSnapshot, FormValues } from "@cosmicdrift/kumiko-headless";
1
+ import type { FormController, FormControllerOptions, FormSnapshot, FormValues } from "../headless/index.ts";
2
2
  export type UseFormOptions<TValues extends FormValues, TCtx = unknown> = FormControllerOptions<TValues, TCtx>;
3
3
  export type UseFormResult<TValues extends FormValues> = {
4
4
  readonly controller: FormController<TValues>;
@@ -1,6 +1,6 @@
1
- import { createFormController } from "@cosmicdrift/kumiko-headless";
2
1
  import { useMemo, useSyncExternalStore } from "react";
3
2
  import { useOptionalDispatcher } from "../context/dispatcher-context.js";
3
+ import { createFormController } from "../headless/index.js";
4
4
  export function useForm(options) {
5
5
  // Optional: a form with no `submit` config (or one with an explicit
6
6
  // dispatcher) never needs the ambient one, and mounting without a
@@ -1,4 +1,4 @@
1
- import type { DispatcherError, WriteResult } from "@cosmicdrift/kumiko-headless";
1
+ import type { DispatcherError, WriteResult } from "../headless/index.ts";
2
2
  export type UseMutationResult<TData> = {
3
3
  readonly mutate: (payload: unknown) => Promise<WriteResult<TData>>;
4
4
  readonly pending: boolean;