@cosmicdrift/kumiko-renderer 0.373.0 → 0.377.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 (466) hide show
  1. package/README.md +2 -2
  2. package/dist/app/action-form-support.d.ts +58 -0
  3. package/dist/app/action-form-support.js +96 -0
  4. package/dist/app/client-actions.d.ts +46 -0
  5. package/dist/app/client-actions.js +60 -0
  6. package/dist/app/column-renderers.js +1 -1
  7. package/dist/app/config-edit-shim.js +1 -1
  8. package/dist/app/content-preview.js +1 -6
  9. package/dist/app/custom-screens.js +1 -1
  10. package/dist/app/dashboard-body.d.ts +1 -1
  11. package/dist/app/entity-list-expanded-row.d.ts +1 -1
  12. package/dist/app/entity-list-expanded-row.js +4 -0
  13. package/dist/app/form-schema.d.ts +1 -1
  14. package/dist/app/form-schema.js +2 -2
  15. package/dist/app/header-actions-bar.d.ts +19 -0
  16. package/dist/app/header-actions-bar.js +30 -0
  17. package/dist/app/kumiko-screen.d.ts +1 -1
  18. package/dist/app/kumiko-screen.js +134 -66
  19. package/dist/app/list-empty-content.d.ts +2 -2
  20. package/dist/app/list-empty-content.js +3 -2
  21. package/dist/app/list-facets.d.ts +1 -1
  22. package/dist/app/nav.js +2 -2
  23. package/dist/app/query-state-banners.d.ts +1 -1
  24. package/dist/app/reference-link.d.ts +1 -1
  25. package/dist/app/row-actions.d.ts +10 -2
  26. package/dist/app/row-actions.js +85 -6
  27. package/dist/app/secret-mint-body.d.ts +1 -1
  28. package/dist/app/secrets-edit-body.d.ts +1 -1
  29. package/dist/app/use-record-actions.d.ts +12 -0
  30. package/dist/app/use-record-actions.js +30 -0
  31. package/dist/app/write-failed-error.d.ts +1 -1
  32. package/dist/components/availability-options-select.d.ts +1 -1
  33. package/dist/components/embedded-list-field.d.ts +1 -1
  34. package/dist/components/embedded-list-field.js +1 -1
  35. package/dist/components/file-list-field.d.ts +1 -1
  36. package/dist/components/grid-cell-for-field.d.ts +4 -2
  37. package/dist/components/grid-cell-for-field.js +2 -2
  38. package/dist/components/multi-select-checkboxes.d.ts +1 -1
  39. package/dist/components/multi-select-checkboxes.js +1 -1
  40. package/dist/components/query-options-select.d.ts +1 -1
  41. package/dist/components/related-list-section.d.ts +1 -1
  42. package/dist/components/related-list-section.js +16 -3
  43. package/dist/components/render-edit-logic.d.ts +1 -1
  44. package/dist/components/render-edit-types.d.ts +2 -2
  45. package/dist/components/render-edit.d.ts +1 -1
  46. package/dist/components/render-edit.js +5 -3
  47. package/dist/components/render-field.d.ts +5 -2
  48. package/dist/components/render-field.js +103 -9
  49. package/dist/components/render-list.d.ts +1 -1
  50. package/dist/components/render-list.js +20 -4
  51. package/dist/components/write-form-section.d.ts +1 -1
  52. package/dist/components/write-form-section.js +1 -1
  53. package/dist/context/dispatcher-context.d.ts +1 -1
  54. package/dist/format-when.js +1 -1
  55. package/dist/headless/apex/css.d.ts +3 -0
  56. package/dist/headless/apex/css.js +298 -0
  57. package/dist/headless/apex/index.d.ts +236 -0
  58. package/dist/headless/apex/index.js +377 -0
  59. package/dist/headless/apex/lightbox.d.ts +4 -0
  60. package/dist/headless/apex/lightbox.js +81 -0
  61. package/dist/headless/contracts/asset.d.ts +15 -0
  62. package/dist/headless/contracts/asset.js +17 -0
  63. package/dist/headless/contracts/index.d.ts +3 -0
  64. package/dist/headless/contracts/index.js +1 -0
  65. package/dist/headless/contracts/locale.d.ts +7 -0
  66. package/dist/headless/contracts/locale.js +11 -0
  67. package/dist/headless/contracts/primitives.d.ts +93 -0
  68. package/dist/headless/contracts/primitives.js +21 -0
  69. package/dist/headless/dispatcher/index.d.ts +2 -0
  70. package/dist/headless/dispatcher/index.js +1 -0
  71. package/dist/headless/dispatcher/types.d.ts +86 -0
  72. package/dist/headless/dispatcher/types.js +34 -0
  73. package/dist/headless/form/form-controller.d.ts +2 -0
  74. package/dist/headless/form/form-controller.js +409 -0
  75. package/dist/headless/form/index.d.ts +3 -0
  76. package/dist/headless/form/index.js +2 -0
  77. package/dist/headless/form/types.d.ts +76 -0
  78. package/dist/headless/form/types.js +1 -0
  79. package/dist/headless/form/zod-bridge.d.ts +10 -0
  80. package/dist/headless/form/zod-bridge.js +103 -0
  81. package/dist/headless/format/document-values.d.ts +12 -0
  82. package/dist/headless/format/document-values.js +70 -0
  83. package/dist/headless/format/escape.d.ts +5 -0
  84. package/dist/headless/format/escape.js +75 -0
  85. package/dist/headless/format/html-template.d.ts +9 -0
  86. package/dist/headless/format/html-template.js +39 -0
  87. package/dist/headless/format/index.d.ts +12 -0
  88. package/dist/headless/format/index.js +237 -0
  89. package/dist/headless/format/money.d.ts +3 -0
  90. package/dist/headless/format/money.js +39 -0
  91. package/dist/headless/index.d.ts +14 -0
  92. package/dist/headless/index.js +9 -0
  93. package/dist/headless/locale-routing/index.d.ts +41 -0
  94. package/dist/headless/locale-routing/index.js +145 -0
  95. package/dist/headless/nav/index.d.ts +2 -0
  96. package/dist/headless/nav/index.js +1 -0
  97. package/dist/headless/nav/resolve.d.ts +2 -0
  98. package/dist/headless/nav/resolve.js +71 -0
  99. package/dist/headless/nav/types.d.ts +26 -0
  100. package/dist/headless/nav/types.js +1 -0
  101. package/dist/headless/store/create-store.d.ts +2 -0
  102. package/dist/headless/store/create-store.js +43 -0
  103. package/dist/headless/store/equality.d.ts +1 -0
  104. package/dist/headless/store/equality.js +34 -0
  105. package/dist/headless/store/index.d.ts +3 -0
  106. package/dist/headless/store/index.js +2 -0
  107. package/dist/headless/store/types.d.ts +7 -0
  108. package/dist/headless/store/types.js +10 -0
  109. package/dist/headless/view-model/edit.d.ts +18 -0
  110. package/dist/headless/view-model/edit.js +501 -0
  111. package/dist/headless/view-model/embedded-list.d.ts +27 -0
  112. package/dist/headless/view-model/embedded-list.js +63 -0
  113. package/dist/headless/view-model/index.d.ts +7 -0
  114. package/dist/headless/view-model/index.js +3 -0
  115. package/dist/headless/view-model/list-file-display.d.ts +3 -0
  116. package/dist/headless/view-model/list-file-display.js +27 -0
  117. package/dist/headless/view-model/list.d.ts +16 -0
  118. package/dist/headless/view-model/list.js +229 -0
  119. package/dist/headless/view-model/types.d.ts +382 -0
  120. package/dist/headless/view-model/types.js +1 -0
  121. package/dist/hooks/use-ai-text.d.ts +1 -1
  122. package/dist/hooks/use-form.d.ts +1 -1
  123. package/dist/hooks/use-form.js +1 -1
  124. package/dist/hooks/use-mutation.d.ts +1 -1
  125. package/dist/hooks/use-query.d.ts +1 -1
  126. package/dist/hooks/use-store.d.ts +1 -1
  127. package/dist/hooks/use-store.js +7 -7
  128. package/dist/hooks/use-stream-handler.d.ts +1 -1
  129. package/dist/i18n-defaults.js +7 -0
  130. package/dist/i18n.d.ts +1 -1
  131. package/dist/i18n.js +1 -1
  132. package/dist/index.d.ts +5 -1
  133. package/dist/index.js +7 -4
  134. package/dist/live/csrf.d.ts +2 -0
  135. package/dist/live/csrf.js +60 -0
  136. package/dist/live/dispatcher-live.d.ts +7 -0
  137. package/dist/live/dispatcher-live.js +286 -0
  138. package/dist/live/envelopes.d.ts +101 -0
  139. package/dist/live/envelopes.js +35 -0
  140. package/dist/live/error-mapping.d.ts +16 -0
  141. package/dist/live/error-mapping.js +82 -0
  142. package/dist/live/index.d.ts +7 -0
  143. package/dist/live/index.js +5 -0
  144. package/dist/live/locale.d.ts +2 -0
  145. package/dist/live/locale.js +25 -0
  146. package/dist/live/sse-stream.d.ts +14 -0
  147. package/dist/live/sse-stream.js +128 -0
  148. package/dist/primitives.d.ts +53 -36
  149. package/dist/primitives.js +1 -1
  150. package/dist/session/session-ended.d.ts +1 -1
  151. package/dist/tokens.d.ts +3 -4
  152. package/dist/tokens.js +4 -5
  153. package/dist/web/app/app-schema-boot.d.ts +19 -0
  154. package/dist/web/app/app-schema-boot.js +124 -0
  155. package/dist/web/app/browser-locale.d.ts +22 -0
  156. package/dist/web/app/browser-locale.js +78 -0
  157. package/dist/web/app/client-plugin.d.ts +106 -0
  158. package/dist/web/app/client-plugin.js +12 -0
  159. package/dist/web/app/create-app.d.ts +104 -0
  160. package/dist/web/app/create-app.js +498 -0
  161. package/dist/web/app/create-public-surface.d.ts +36 -0
  162. package/dist/web/app/create-public-surface.js +40 -0
  163. package/dist/web/app/dashboard-body.d.ts +3 -0
  164. package/dist/web/app/dashboard-body.js +865 -0
  165. package/dist/web/app/dashboard-refresh.d.ts +6 -0
  166. package/dist/web/app/dashboard-refresh.js +15 -0
  167. package/dist/web/app/document-lang-sync.d.ts +4 -0
  168. package/dist/web/app/document-lang-sync.js +27 -0
  169. package/dist/web/app/draft-storage.d.ts +11 -0
  170. package/dist/web/app/draft-storage.js +53 -0
  171. package/dist/web/app/nav-providers-context.d.ts +13 -0
  172. package/dist/web/app/nav-providers-context.js +18 -0
  173. package/dist/web/app/nav.d.ts +40 -0
  174. package/dist/web/app/nav.js +231 -0
  175. package/dist/web/app/plain-content-editor.d.ts +3 -0
  176. package/dist/web/app/plain-content-editor.js +30 -0
  177. package/dist/web/app/relative-time.d.ts +10 -0
  178. package/dist/web/app/relative-time.js +56 -0
  179. package/dist/web/app/resolvers-context.d.ts +12 -0
  180. package/dist/web/app/resolvers-context.js +10 -0
  181. package/dist/web/app/rich-content-editor.d.ts +3 -0
  182. package/dist/web/app/rich-content-editor.js +15 -0
  183. package/dist/web/app/root-error-fallback.d.ts +2 -0
  184. package/dist/web/app/root-error-fallback.js +21 -0
  185. package/dist/web/app/screen-error-fallback.d.ts +6 -0
  186. package/dist/web/app/screen-error-fallback.js +17 -0
  187. package/dist/web/app/tiptap-editor.d.ts +3 -0
  188. package/dist/web/app/tiptap-editor.js +120 -0
  189. package/dist/web/app/toast-action-notifier.d.ts +5 -0
  190. package/dist/web/app/toast-action-notifier.js +17 -0
  191. package/dist/web/components/config-cascade.d.ts +13 -0
  192. package/dist/web/components/config-cascade.js +155 -0
  193. package/dist/web/components/config-source-badge.d.ts +6 -0
  194. package/dist/web/components/config-source-badge.js +55 -0
  195. package/dist/web/default-color-scheme.d.ts +2 -0
  196. package/dist/web/default-color-scheme.js +3 -0
  197. package/dist/web/icons.d.ts +94 -0
  198. package/dist/web/icons.js +100 -0
  199. package/dist/web/index.d.ts +78 -0
  200. package/dist/web/index.js +53 -0
  201. package/dist/web/layout/app-layout.d.ts +21 -0
  202. package/dist/web/layout/app-layout.js +8 -0
  203. package/dist/web/layout/avatar.d.ts +12 -0
  204. package/dist/web/layout/avatar.js +63 -0
  205. package/dist/web/layout/default-app-shell.d.ts +41 -0
  206. package/dist/web/layout/default-app-shell.js +16 -0
  207. package/dist/web/layout/editor-panel.d.ts +10 -0
  208. package/dist/web/layout/editor-panel.js +29 -0
  209. package/dist/web/layout/fill-classes.d.ts +9 -0
  210. package/dist/web/layout/fill-classes.js +15 -0
  211. package/dist/web/layout/filter-app-schema-navs.d.ts +7 -0
  212. package/dist/web/layout/filter-app-schema-navs.js +68 -0
  213. package/dist/web/layout/header-action-group.d.ts +6 -0
  214. package/dist/web/layout/header-action-group.js +8 -0
  215. package/dist/web/layout/header-overflow-menu.d.ts +4 -0
  216. package/dist/web/layout/header-overflow-menu.js +8 -0
  217. package/dist/web/layout/language-menu-items.d.ts +8 -0
  218. package/dist/web/layout/language-menu-items.js +16 -0
  219. package/dist/web/layout/language-switcher.d.ts +25 -0
  220. package/dist/web/layout/language-switcher.js +46 -0
  221. package/dist/web/layout/nav-tree.d.ts +19 -0
  222. package/dist/web/layout/nav-tree.js +536 -0
  223. package/dist/web/layout/page-header-slot.d.ts +25 -0
  224. package/dist/web/layout/page-header-slot.js +50 -0
  225. package/dist/web/layout/profile-menu.d.ts +13 -0
  226. package/dist/web/layout/profile-menu.js +6 -0
  227. package/dist/web/layout/shell-breadcrumb.d.ts +11 -0
  228. package/dist/web/layout/shell-breadcrumb.js +34 -0
  229. package/dist/web/layout/shell-header.d.ts +12 -0
  230. package/dist/web/layout/shell-header.js +159 -0
  231. package/dist/web/layout/sidebar-brand.d.ts +15 -0
  232. package/dist/web/layout/sidebar-brand.js +9 -0
  233. package/dist/web/layout/sidebar-panel.d.ts +41 -0
  234. package/dist/web/layout/sidebar-panel.js +107 -0
  235. package/dist/web/layout/sidebar-user.d.ts +8 -0
  236. package/dist/web/layout/sidebar-user.js +17 -0
  237. package/dist/web/layout/sidebar.d.ts +17 -0
  238. package/dist/web/layout/sidebar.js +11 -0
  239. package/dist/web/layout/target-resolver-stub.d.ts +13 -0
  240. package/dist/web/layout/target-resolver-stub.js +61 -0
  241. package/dist/web/layout/target-url.d.ts +12 -0
  242. package/dist/web/layout/target-url.js +77 -0
  243. package/dist/web/layout/theme-label.d.ts +15 -0
  244. package/dist/web/layout/theme-label.js +35 -0
  245. package/dist/web/layout/theme-menu-item.d.ts +12 -0
  246. package/dist/web/layout/theme-menu-item.js +16 -0
  247. package/dist/web/layout/theme-toggle.d.ts +17 -0
  248. package/dist/web/layout/theme-toggle.js +22 -0
  249. package/dist/web/layout/topbar.d.ts +8 -0
  250. package/dist/web/layout/topbar.js +4 -0
  251. package/dist/web/layout/workspace-shell.d.ts +63 -0
  252. package/dist/web/layout/workspace-shell.js +220 -0
  253. package/dist/web/layout/workspace-switcher.d.ts +15 -0
  254. package/dist/web/layout/workspace-switcher.js +36 -0
  255. package/dist/web/lib/accept-attr.d.ts +1 -0
  256. package/dist/web/lib/accept-attr.js +6 -0
  257. package/dist/web/lib/clamp.d.ts +1 -0
  258. package/dist/web/lib/clamp.js +3 -0
  259. package/dist/web/lib/cn.d.ts +6 -0
  260. package/dist/web/lib/cn.js +9 -0
  261. package/dist/web/lib/download.d.ts +2 -0
  262. package/dist/web/lib/download.js +24 -0
  263. package/dist/web/lib/file-ref-download.d.ts +15 -0
  264. package/dist/web/lib/file-ref-download.js +62 -0
  265. package/dist/web/lib/file-upload-form-data.d.ts +7 -0
  266. package/dist/web/lib/file-upload-form-data.js +11 -0
  267. package/dist/web/lib/resize-image.d.ts +1 -0
  268. package/dist/web/lib/resize-image.js +66 -0
  269. package/dist/web/lib/upload-file-ref.d.ts +9 -0
  270. package/dist/web/lib/upload-file-ref.js +29 -0
  271. package/dist/web/primitives/action-menu.d.ts +34 -0
  272. package/dist/web/primitives/action-menu.js +30 -0
  273. package/dist/web/primitives/calendar-popover.d.ts +13 -0
  274. package/dist/web/primitives/calendar-popover.js +76 -0
  275. package/dist/web/primitives/combobox.d.ts +56 -0
  276. package/dist/web/primitives/combobox.js +127 -0
  277. package/dist/web/primitives/date-field.d.ts +18 -0
  278. package/dist/web/primitives/date-field.js +74 -0
  279. package/dist/web/primitives/date-input.d.ts +1 -0
  280. package/dist/web/primitives/date-input.js +5 -0
  281. package/dist/web/primitives/date-parse.d.ts +11 -0
  282. package/dist/web/primitives/date-parse.js +159 -0
  283. package/dist/web/primitives/dialog.d.ts +3 -0
  284. package/dist/web/primitives/dialog.js +42 -0
  285. package/dist/web/primitives/drawer.d.ts +3 -0
  286. package/dist/web/primitives/drawer.js +17 -0
  287. package/dist/web/primitives/dropdown-menu.d.ts +15 -0
  288. package/dist/web/primitives/dropdown-menu.js +56 -0
  289. package/dist/web/primitives/embedded-list-input.d.ts +9 -0
  290. package/dist/web/primitives/embedded-list-input.js +382 -0
  291. package/dist/web/primitives/file-thumbnail.d.ts +25 -0
  292. package/dist/web/primitives/file-thumbnail.js +90 -0
  293. package/dist/web/primitives/file-upload.d.ts +21 -0
  294. package/dist/web/primitives/file-upload.js +56 -0
  295. package/dist/web/primitives/index.d.ts +34 -0
  296. package/dist/web/primitives/index.js +2021 -0
  297. package/dist/web/primitives/json-view.d.ts +7 -0
  298. package/dist/web/primitives/json-view.js +84 -0
  299. package/dist/web/primitives/layout.d.ts +27 -0
  300. package/dist/web/primitives/layout.js +30 -0
  301. package/dist/web/primitives/lightbox.d.ts +3 -0
  302. package/dist/web/primitives/lightbox.js +36 -0
  303. package/dist/web/primitives/locale-number.d.ts +2 -0
  304. package/dist/web/primitives/locale-number.js +54 -0
  305. package/dist/web/primitives/located-timestamp-input.d.ts +22 -0
  306. package/dist/web/primitives/located-timestamp-input.js +22 -0
  307. package/dist/web/primitives/metric.d.ts +5 -0
  308. package/dist/web/primitives/metric.js +18 -0
  309. package/dist/web/primitives/modal-shell.d.ts +17 -0
  310. package/dist/web/primitives/modal-shell.js +9 -0
  311. package/dist/web/primitives/modal.d.ts +3 -0
  312. package/dist/web/primitives/modal.js +13 -0
  313. package/dist/web/primitives/money-input.d.ts +18 -0
  314. package/dist/web/primitives/money-input.js +122 -0
  315. package/dist/web/primitives/narrow-pinned-footer.d.ts +12 -0
  316. package/dist/web/primitives/narrow-pinned-footer.js +153 -0
  317. package/dist/web/primitives/number-input.d.ts +18 -0
  318. package/dist/web/primitives/number-input.js +53 -0
  319. package/dist/web/primitives/option-groups.d.ts +11 -0
  320. package/dist/web/primitives/option-groups.js +27 -0
  321. package/dist/web/primitives/page-header.d.ts +3 -0
  322. package/dist/web/primitives/page-header.js +52 -0
  323. package/dist/web/primitives/promo-panel.d.ts +3 -0
  324. package/dist/web/primitives/promo-panel.js +11 -0
  325. package/dist/web/primitives/segmented-select.d.ts +21 -0
  326. package/dist/web/primitives/segmented-select.js +62 -0
  327. package/dist/web/primitives/share-actions.d.ts +4 -0
  328. package/dist/web/primitives/share-actions.js +56 -0
  329. package/dist/web/primitives/status-badge.d.ts +3 -0
  330. package/dist/web/primitives/status-badge.js +5 -0
  331. package/dist/web/primitives/sticky-action-bar.d.ts +5 -0
  332. package/dist/web/primitives/sticky-action-bar.js +15 -0
  333. package/dist/web/primitives/tabs.d.ts +3 -0
  334. package/dist/web/primitives/tabs.js +107 -0
  335. package/dist/web/primitives/timestamp-input.d.ts +27 -0
  336. package/dist/web/primitives/timestamp-input.js +87 -0
  337. package/dist/web/primitives/toast.d.ts +19 -0
  338. package/dist/web/primitives/toast.js +63 -0
  339. package/dist/web/primitives/tz-input.d.ts +11 -0
  340. package/dist/web/primitives/tz-input.js +8 -0
  341. package/dist/web/primitives/tz-options.d.ts +4 -0
  342. package/dist/web/primitives/tz-options.js +17 -0
  343. package/dist/web/primitives/use-keyboard-inset.d.ts +1 -0
  344. package/dist/web/primitives/use-keyboard-inset.js +28 -0
  345. package/dist/web/primitives/use-narrow-viewport.d.ts +4 -0
  346. package/dist/web/primitives/use-narrow-viewport.js +46 -0
  347. package/dist/web/react-css-custom-properties.d.ts +6 -0
  348. package/dist/web/react-css-custom-properties.js +1 -0
  349. package/dist/web/sse/live-events.d.ts +15 -0
  350. package/dist/web/sse/live-events.js +148 -0
  351. package/dist/web/theme-plugin.d.ts +41 -0
  352. package/dist/web/theme-plugin.js +123 -0
  353. package/dist/web/tokens.d.ts +24 -0
  354. package/dist/web/tokens.js +203 -0
  355. package/dist/web/ui/avatar.d.ts +11 -0
  356. package/dist/web/ui/avatar.js +25 -0
  357. package/dist/web/ui/badge.d.ts +9 -0
  358. package/dist/web/ui/badge.js +26 -0
  359. package/dist/web/ui/breadcrumb.d.ts +11 -0
  360. package/dist/web/ui/breadcrumb.js +29 -0
  361. package/dist/web/ui/button.d.ts +10 -0
  362. package/dist/web/ui/button.js +37 -0
  363. package/dist/web/ui/checkbox.d.ts +4 -0
  364. package/dist/web/ui/checkbox.js +11 -0
  365. package/dist/web/ui/input.d.ts +3 -0
  366. package/dist/web/ui/input.js +8 -0
  367. package/dist/web/ui/label.d.ts +4 -0
  368. package/dist/web/ui/label.js +10 -0
  369. package/dist/web/ui/resizable.d.ts +7 -0
  370. package/dist/web/ui/resizable.js +16 -0
  371. package/dist/web/ui/separator.d.ts +4 -0
  372. package/dist/web/ui/separator.js +10 -0
  373. package/dist/web/ui/sheet.d.ts +14 -0
  374. package/dist/web/ui/sheet.js +42 -0
  375. package/dist/web/ui/sidebar.d.ts +73 -0
  376. package/dist/web/ui/sidebar.js +211 -0
  377. package/dist/web/ui/skeleton.d.ts +2 -0
  378. package/dist/web/ui/skeleton.js +7 -0
  379. package/dist/web/ui/switch.d.ts +6 -0
  380. package/dist/web/ui/switch.js +10 -0
  381. package/dist/web/ui/table.d.ts +10 -0
  382. package/dist/web/ui/table.js +30 -0
  383. package/dist/web/ui/tabs.d.ts +11 -0
  384. package/dist/web/ui/tabs.js +31 -0
  385. package/dist/web/ui/textarea.d.ts +3 -0
  386. package/dist/web/ui/textarea.js +8 -0
  387. package/dist/web/ui/tooltip.d.ts +7 -0
  388. package/dist/web/ui/tooltip.js +19 -0
  389. package/dist/web/ui/use-mobile.d.ts +1 -0
  390. package/dist/web/ui/use-mobile.js +16 -0
  391. package/dist/web/version/update-checker.d.ts +9 -0
  392. package/dist/web/version/update-checker.js +88 -0
  393. package/dist/web/widgets/ai-text-field.d.ts +36 -0
  394. package/dist/web/widgets/ai-text-field.js +137 -0
  395. package/dist/web/widgets/chart-window.d.ts +58 -0
  396. package/dist/web/widgets/chart-window.js +190 -0
  397. package/dist/web/widgets/charts.d.ts +208 -0
  398. package/dist/web/widgets/charts.js +685 -0
  399. package/dist/web/widgets/collapsible-section.d.ts +10 -0
  400. package/dist/web/widgets/collapsible-section.js +17 -0
  401. package/dist/web/widgets/dashboard-list.d.ts +21 -0
  402. package/dist/web/widgets/dashboard-list.js +45 -0
  403. package/dist/web/widgets/detail-list.d.ts +15 -0
  404. package/dist/web/widgets/detail-list.js +8 -0
  405. package/dist/web/widgets/drawer.d.ts +65 -0
  406. package/dist/web/widgets/drawer.js +142 -0
  407. package/dist/web/widgets/feed-list.d.ts +13 -0
  408. package/dist/web/widgets/feed-list.js +9 -0
  409. package/dist/web/widgets/floating-panel.d.ts +30 -0
  410. package/dist/web/widgets/floating-panel.js +242 -0
  411. package/dist/web/widgets/form-fields.d.ts +93 -0
  412. package/dist/web/widgets/form-fields.js +50 -0
  413. package/dist/web/widgets/index.d.ts +27 -0
  414. package/dist/web/widgets/index.js +30 -0
  415. package/dist/web/widgets/infinity-list.d.ts +46 -0
  416. package/dist/web/widgets/infinity-list.js +211 -0
  417. package/dist/web/widgets/mode-switch.d.ts +21 -0
  418. package/dist/web/widgets/mode-switch.js +25 -0
  419. package/dist/web/widgets/photo-slots.d.ts +29 -0
  420. package/dist/web/widgets/photo-slots.js +52 -0
  421. package/dist/web/widgets/plan-card.d.ts +36 -0
  422. package/dist/web/widgets/plan-card.js +13 -0
  423. package/dist/web/widgets/progress-bar.d.ts +19 -0
  424. package/dist/web/widgets/progress-bar.js +24 -0
  425. package/dist/web/widgets/progress-list.d.ts +19 -0
  426. package/dist/web/widgets/progress-list.js +11 -0
  427. package/dist/web/widgets/public-shell.d.ts +22 -0
  428. package/dist/web/widgets/public-shell.js +15 -0
  429. package/dist/web/widgets/query-table.d.ts +29 -0
  430. package/dist/web/widgets/query-table.js +30 -0
  431. package/dist/web/widgets/result-panel.d.ts +69 -0
  432. package/dist/web/widgets/result-panel.js +30 -0
  433. package/dist/web/widgets/section-card.d.ts +12 -0
  434. package/dist/web/widgets/section-card.js +9 -0
  435. package/dist/web/widgets/sheet-parts.d.ts +9 -0
  436. package/dist/web/widgets/sheet-parts.js +11 -0
  437. package/dist/web/widgets/side-by-side-table.d.ts +31 -0
  438. package/dist/web/widgets/side-by-side-table.js +11 -0
  439. package/dist/web/widgets/stat.d.ts +54 -0
  440. package/dist/web/widgets/stat.js +65 -0
  441. package/dist/web/widgets/states.d.ts +23 -0
  442. package/dist/web/widgets/states.js +20 -0
  443. package/dist/web/widgets/status-badge.d.ts +15 -0
  444. package/dist/web/widgets/status-badge.js +24 -0
  445. package/dist/web/widgets/step-bar.d.ts +35 -0
  446. package/dist/web/widgets/step-bar.js +60 -0
  447. package/dist/web/widgets/upload-zone.d.ts +24 -0
  448. package/dist/web/widgets/upload-zone.js +108 -0
  449. package/dist/web/widgets/use-draft.d.ts +20 -0
  450. package/dist/web/widgets/use-draft.js +21 -0
  451. package/dist/web/widgets/use-pointer-drag.d.ts +21 -0
  452. package/dist/web/widgets/use-pointer-drag.js +53 -0
  453. package/package.json +105 -7
  454. package/src/changes.json +77 -0
  455. package/src/web/fonts/OFL.txt +93 -0
  456. package/src/web/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
  457. package/src/web/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
  458. package/src/web/fonts/ibm-plex-mono-latin-ext-400.woff2 +0 -0
  459. package/src/web/fonts/ibm-plex-mono-latin-ext-500.woff2 +0 -0
  460. package/src/web/fonts/ibm-plex-sans-latin-400.woff2 +0 -0
  461. package/src/web/fonts/ibm-plex-sans-latin-500.woff2 +0 -0
  462. package/src/web/fonts/ibm-plex-sans-latin-600.woff2 +0 -0
  463. package/src/web/fonts/ibm-plex-sans-latin-ext-400.woff2 +0 -0
  464. package/src/web/fonts/ibm-plex-sans-latin-ext-500.woff2 +0 -0
  465. package/src/web/fonts/ibm-plex-sans-latin-ext-600.woff2 +0 -0
  466. package/src/web/styles.css +401 -0
@@ -1,6 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { evalFieldCondition, isRecordLocked, isWriteFormEditSection, metricField, parseRefTarget, } from "@cosmicdrift/kumiko-framework/ui-types";
3
- import { applyFormatSpec, buildOptionLabels, computeRelatedListSectionViewModel, fieldLabelKey, fieldOptionLabelKey, isSafeHref, } from "@cosmicdrift/kumiko-headless";
4
3
  import { resolveActionIcon } from "@cosmicdrift/kumiko-types/action-icon";
5
4
  import { TENANT_CURRENCY_CONFIG_KEY } from "@cosmicdrift/kumiko-types/fields";
6
5
  import { Temporal } from "@cosmicdrift/kumiko-types/temporal";
@@ -9,13 +8,12 @@ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from "rea
9
8
  import { QueryOptionLabel, resolveOptionsQueryPayload, } from "../components/query-options-select.js";
10
9
  import { extractCreatedId, extractIdField } from "../components/reference-create-dialog.js";
11
10
  import { RenderEdit, resolveRecordTitle, } from "../components/render-edit.js";
12
- import { RenderEditActionButton } from "../components/render-edit-action-button.js";
13
11
  import { RenderList } from "../components/render-list.js";
14
- import { useActionMenuItems } from "../components/use-action-menu-items.js";
15
12
  import { useDispatcher, useOptionalDispatcher } from "../context/dispatcher-context.js";
16
13
  import { useIsEmbeddedScreen } from "../context/embedded-screen-context.js";
17
14
  import { useUserRoles } from "../context/user-roles-context.js";
18
15
  import { useOptionalCurrentUser } from "../current-user.js";
16
+ import { applyFormatSpec, buildOptionLabels, computeRelatedListSectionViewModel, fieldLabelKey, fieldOptionLabelKey, isSafeHref, } from "../headless/index.js";
19
17
  import { REFERENCE_LIST_LOOKUP_LIMIT } from "../hooks/reference-limits.js";
20
18
  import { PAGE_SIZE_OPTIONS, useListUrlState } from "../hooks/use-list-url-state.js";
21
19
  import { useQuery } from "../hooks/use-query.js";
@@ -26,7 +24,9 @@ import { PageHeaderSlotAvailableProvider, usePageHeaderCompact, usePageHeaderSlo
26
24
  import { statusToneForOptionTone, statusToneForValue, usePrimitives, } from "../primitives.js";
27
25
  import { screenFillsHeight } from "../screen-fills-height.js";
28
26
  import { actionFormSubmittableFields, synthesizeActionFormEntity, synthesizeActionFormScreen, } from "./action-form-shim.js";
27
+ import { ActionFormLoadStatus, ActionFormSuccessBanner, isSecretFormField, resolveActionFormRecordId, resolveSuccessFacts, useActionFormLoad, } from "./action-form-support.js";
29
28
  import { useAppFeatures } from "./app-features-context.js";
29
+ import { useClientActionRuntime } from "./client-actions.js";
30
30
  import { buildConfigEditSchema, synthesizeConfigEditEntity, synthesizeConfigEditScreen, } from "./config-edit-shim.js";
31
31
  import { useCustomScreenComponent } from "./custom-screens.js";
32
32
  import { useDashboardBody } from "./dashboard-body.js";
@@ -34,7 +34,7 @@ import { applyEditPrefill } from "./edit-prefill.js";
34
34
  import { EntityListExpandedRow } from "./entity-list-expanded-row.js";
35
35
  import { FacetCountBridges } from "./facet-count-bridge.js";
36
36
  import { buildFormSchema } from "./form-schema.js";
37
- import { compactHeaderPrimary, orderPlainHeaderActions, primaryHeaderAction, } from "./header-actions.js";
37
+ import { HeaderActionsBar } from "./header-actions-bar.js";
38
38
  import { hiddenRequiredFieldsFilled, layoutEditFields, layoutFieldNames } from "./layout-fields.js";
39
39
  import { isListNarrowed, useListEmptyContent } from "./list-empty-content.js";
40
40
  import { buildDateRangePayload, buildEntityFilterFacets, buildFacetCountRequests, buildFilterFacets, buildFilterPayload, clampDateRange, mergeReferenceFacetOptions, normalizeDefaultFilters, readDateRange, resolveDateRangeFacets, resolveProjectionFacetSpecs, } from "./list-facets.js";
@@ -46,7 +46,7 @@ import { featureNameFromQualifiedScreenId, qualifyScreenId } from "./qualify-scr
46
46
  import { QueryErrorBanner, QueryLoadingBanner } from "./query-state-banners.js";
47
47
  import { ReferenceFacetBridges } from "./reference-facet-bridge.js";
48
48
  import { navigateToReturn, navigateToReturnOr, navigateWithReturnTo, ReturnHostProvider, useReturnHost, useReturnTarget, } from "./return-to.js";
49
- import { buildDefaultEditRowAction, buildDrawerRowAction, buildProjectionRowActions, buildProjectionToolbarActions, buildRecordActions, evalRowExtractor, isWriteHandlerRowAction, navigateActionSearchParams, refetchAfterWrite, runProjectionRowNavigate, } from "./row-actions.js";
49
+ import { buildClientActionRowAction, buildDefaultEditRowAction, buildDrawerRowAction, buildProjectionRowActions, buildProjectionToolbarActions, buildRecordActions, evalRowExtractor, findRowClickAction, navigateActionSearchParams, refetchAfterWrite, runDrawerRowAction, runProjectionRowNavigate, } from "./row-actions.js";
50
50
  import { findEditScreenFor, navigateTargetAllows, screenAccessAllows } from "./screen-access.js";
51
51
  import { SecretMintBody } from "./secret-mint-body.js";
52
52
  import { SecretsEditBody } from "./secrets-edit-body.js";
@@ -174,7 +174,7 @@ function renderScreenBody({ schema, screen, translate, entityId, onRowClick, onC
174
174
  case "dashboard":
175
175
  return (_jsx(DashboardScreenBody, { featureName: schema.featureName, screen: screen, translate: translate }));
176
176
  case "actionForm":
177
- return _jsx(ActionFormBody, { schema: schema, screen: screen, translate: translate });
177
+ return (_jsx(ActionFormBody, { schema: schema, screen: screen, translate: translate, ...(entityId !== undefined && { entityId }) }));
178
178
  case "secretMint":
179
179
  return _jsx(SecretMintBody, { schema: schema, screen: screen, translate: translate });
180
180
  case "configEdit":
@@ -190,12 +190,12 @@ function renderScreenBody({ schema, screen, translate, entityId, onRowClick, onC
190
190
  }
191
191
  // Injection-Body für dashboard-Screens: die Panel-Implementierung (StatCard,
192
192
  // Charts) ist plattform-spezifisch und kommt aus dem DashboardBody-Context
193
- // (renderer-web registriert die Web-Variante in createKumikoApp).
193
+ // (renderer/web registriert die Web-Variante in createKumikoApp).
194
194
  function DashboardScreenBody({ featureName, screen, translate, }) {
195
195
  const { Banner, Text } = usePrimitives();
196
196
  const Body = useDashboardBody();
197
197
  if (Body === undefined) {
198
- return (_jsxs(Banner, { padded: true, variant: "info", testId: "kumiko-screen-dashboard-placeholder", children: ["Dashboard screen ", _jsx(Text, { variant: "code", children: screen.id }), " \u2014 kein Dashboard-Body registriert (createKumikoApp aus ", _jsx(Text, { variant: "code", children: "kumiko-renderer-web" }), " wired ihn automatisch)."] }));
198
+ return (_jsxs(Banner, { padded: true, variant: "info", testId: "kumiko-screen-dashboard-placeholder", children: ["Dashboard screen ", _jsx(Text, { variant: "code", children: screen.id }), " \u2014 no dashboard body registered (createKumikoApp from ", _jsx(Text, { variant: "code", children: "kumiko-renderer/web" }), " wires it automatically)."] }));
199
199
  }
200
200
  return (_jsx(Body, { featureName: featureName, screen: screen, ...(translate !== undefined && { translate }) }));
201
201
  }
@@ -891,6 +891,7 @@ function EntityEditUpdateForm({ schema, screen, entity, entityId, record, onRelo
891
891
  const nav = useNav();
892
892
  const appFeatures = useAppFeatures();
893
893
  const dispatcher = useDispatcher();
894
+ const clientActions = useClientActionRuntime();
894
895
  const t = useTranslation();
895
896
  const effectiveTranslate = translate ?? t;
896
897
  const navigateToList = useNavigateToListAfter(schema, screen.entity);
@@ -954,6 +955,7 @@ function EntityEditUpdateForm({ schema, screen, entity, entityId, record, onRelo
954
955
  onWriteSuccess: onReload,
955
956
  onRecordLeft: handleRecordLeft,
956
957
  sameEntityScreenId,
958
+ clientActions,
957
959
  defaultWritePayloadId: entityId,
958
960
  ...(formDirty && {
959
961
  discardChanges: {
@@ -972,6 +974,7 @@ function EntityEditUpdateForm({ schema, screen, entity, entityId, record, onRelo
972
974
  onReload,
973
975
  handleRecordLeft,
974
976
  sameEntityScreenId,
977
+ clientActions,
975
978
  entityId,
976
979
  ]);
977
980
  const headerActions = useMemo(() => buildSectionActions((screen.actions ?? []).filter((a) => a.placement !== "menu")), [buildSectionActions, screen.actions]);
@@ -1428,6 +1431,7 @@ function EntityListBody({ schema, screen, entity, translate, onRowClick, }) {
1428
1431
  // (sonst rendert die Action-Spalte still nichts und der "warum sind
1429
1432
  // meine Buttons weg?"-Debug ist teuer).
1430
1433
  const dispatcher = useOptionalDispatcher();
1434
+ const clientActions = useClientActionRuntime();
1431
1435
  const hasRowActions = screen.rowActions !== undefined && screen.rowActions.length > 0;
1432
1436
  useEffect(() => {
1433
1437
  if (hasRowActions && dispatcher === undefined) {
@@ -1444,7 +1448,7 @@ function EntityListBody({ schema, screen, entity, translate, onRowClick, }) {
1444
1448
  const runNavigate = useCallback((action, row) => {
1445
1449
  if (action.entity !== undefined) {
1446
1450
  // Entity-Targets (fw#2228) lösen sich erst in der NavApi-Impl gegen
1447
- // ALLE Features auf (resolveTarget in renderer-web/nav.tsx) — dieses
1451
+ // ALLE Features auf (resolveTarget in renderer/web/nav.tsx) — dieses
1448
1452
  // Package kennt nur `schema` (das eine aufrufende Feature) und kann
1449
1453
  // detailFor cross-feature nicht selbst nachschlagen.
1450
1454
  const explicit = action.entityId !== undefined ? String(row.values[action.entityId] ?? "") : undefined;
@@ -1511,10 +1515,11 @@ function EntityListBody({ schema, screen, entity, translate, onRowClick, }) {
1511
1515
  if (action.kind === "drawer") {
1512
1516
  return buildDrawerRowAction(action, effectiveTranslate, openDrawer);
1513
1517
  }
1518
+ if (action.kind === "clientAction") {
1519
+ return buildClientActionRowAction(action, effectiveTranslate, clientActions, refreshRowsAfterWrite);
1520
+ }
1514
1521
  if (dispatcher === undefined)
1515
1522
  return null;
1516
- if (!isWriteHandlerRowAction(action))
1517
- return null;
1518
1523
  const writeAction = action;
1519
1524
  const writeActionVisible = writeAction.visible;
1520
1525
  return {
@@ -1551,6 +1556,7 @@ function EntityListBody({ schema, screen, entity, translate, onRowClick, }) {
1551
1556
  defaultEditScreen,
1552
1557
  effectiveTranslate,
1553
1558
  dispatcher,
1559
+ clientActions,
1554
1560
  runNavigate,
1555
1561
  refreshRowsAfterWrite,
1556
1562
  openDrawer,
@@ -1625,9 +1631,11 @@ function EntityListBody({ schema, screen, entity, translate, onRowClick, }) {
1625
1631
  // gewinnt (deklarierte Author-Absicht "Klick auf die Zeile tut X"). Ohne Flag
1626
1632
  // bleibt der Pfad unverändert — create-app's entityEdit-Default bzw. ein vom
1627
1633
  // App-Author gesetztes onRowClick.
1628
- const rowClickAction = screen.rowActions?.find((a) => a.kind === "navigate" && a.rowClick === true);
1634
+ const rowClickAction = findRowClickAction(screen.rowActions);
1629
1635
  const wrappedOnRowClick = rowClickAction
1630
- ? (row) => runNavigate(rowClickAction, row)
1636
+ ? (row) => rowClickAction.kind === "drawer"
1637
+ ? runDrawerRowAction(rowClickAction, openDrawer, row)
1638
+ : runNavigate(rowClickAction, row)
1631
1639
  : onRowClick !== undefined
1632
1640
  ? (row) => onRowClick(row, screen.entity)
1633
1641
  : undefined;
@@ -1696,6 +1704,7 @@ function ProjectionListBody({ schema, screen, translate, onRowClick, }) {
1696
1704
  const nav = useNav();
1697
1705
  const host = useReturnHost();
1698
1706
  const dispatcher = useOptionalDispatcher();
1707
+ const clientActions = useClientActionRuntime();
1699
1708
  const effectiveTranslate = translate ?? t;
1700
1709
  const userRoles = useUserRoles();
1701
1710
  const appFeatures = useAppFeatures();
@@ -1808,10 +1817,12 @@ function ProjectionListBody({ schema, screen, translate, onRowClick, }) {
1808
1817
  openDrawer,
1809
1818
  defaultEditRowAction,
1810
1819
  host,
1820
+ clientActions,
1811
1821
  }), [
1812
1822
  screen.rowActions,
1813
1823
  effectiveTranslate,
1814
1824
  dispatcher,
1825
+ clientActions,
1815
1826
  nav,
1816
1827
  rowsQuery.refetch,
1817
1828
  openDrawer,
@@ -1856,9 +1867,11 @@ function ProjectionListBody({ schema, screen, translate, onRowClick, }) {
1856
1867
  if (rawRowsData !== null && !Array.isArray(rawRowsData.rows)) {
1857
1868
  return (_jsxs(Banner, { padded: true, variant: "error", testId: "kumiko-screen-projection-list-bad-shape", children: ["Screen ", _jsx(Text, { variant: "code", children: screen.id }), " query", " ", _jsx(Text, { variant: "code", children: screen.query }), " did not return a PagedRows envelope; a projectionList query must return ", _jsx(Text, { variant: "code", children: "{ rows, nextCursor }" }), "."] }));
1858
1869
  }
1859
- const rowClickAction = screen.rowActions?.find((a) => a.kind === "navigate" && a.rowClick === true);
1870
+ const rowClickAction = findRowClickAction(screen.rowActions);
1860
1871
  const wrappedOnRowClick = rowClickAction
1861
- ? (row) => runNavigate(rowClickAction, row)
1872
+ ? (row) => rowClickAction.kind === "drawer"
1873
+ ? runDrawerRowAction(rowClickAction, openDrawer, row)
1874
+ : runNavigate(rowClickAction, row)
1862
1875
  : onRowClick !== undefined
1863
1876
  ? (row) => onRowClick(row, listScreen.entity)
1864
1877
  : undefined;
@@ -2010,31 +2023,6 @@ function resolveSubtitleHref(header, record) {
2010
2023
  // natives Form-Submit (Enter-Keypress) würde ohne customSubmit gegen
2011
2024
  // controller.submit() ohne submit-config throwen — der No-Op macht diesen
2012
2025
  // Pfad harmlos statt ihn dem Zufall zu überlassen.
2013
- // Header actions bar (A7): <=2 actions render as plain buttons; >2 with an
2014
- // `ActionOverflowMenu` primitive collapse to the primary button plus a menu
2015
- // for the rest — same rule as RowActionsCell for table rows. Owns confirm
2016
- // state for menu items: RenderEditActionButton already owns a per-button
2017
- // confirm dialog for the always-visible primary action, but a menu item has
2018
- // no button of its own to carry one.
2019
- function HeaderActionsBar({ actions, Button, Dialog, ActionOverflowMenu, onError, collapseAfterPrimary = false, compact = false, preferredPrimaryId, PageHeader, }) {
2020
- const t = useTranslation();
2021
- const { toMenuItem, confirmDialog: pendingActionDialog } = useActionMenuItems({
2022
- Dialog,
2023
- onError,
2024
- });
2025
- if (compact && PageHeader !== undefined) {
2026
- const compactPrimary = compactHeaderPrimary(actions, preferredPrimaryId);
2027
- const overflowActions = actions.filter((a) => a !== compactPrimary?.action);
2028
- return (_jsxs(_Fragment, { children: [compactPrimary !== undefined && (_jsx(RenderEditActionButton, { action: compactPrimary.action, Button: Button, Dialog: Dialog, iconOnly: compactPrimary.iconOnly, compactLabel: true, onError: onError }, compactPrimary.action.id)), overflowActions.length > 0 && (_jsx(PageHeader, { overflowItems: overflowActions.map(toMenuItem) })), pendingActionDialog] }));
2029
- }
2030
- const maxPlainButtons = collapseAfterPrimary ? 1 : 2;
2031
- if (actions.length <= maxPlainButtons || ActionOverflowMenu === undefined) {
2032
- return (_jsx(_Fragment, { children: orderPlainHeaderActions(actions, preferredPrimaryId).map((action) => (_jsx(RenderEditActionButton, { action: action, Button: Button, Dialog: Dialog, hideIcon: true, onError: onError }, action.id))) }));
2033
- }
2034
- const primary = primaryHeaderAction(actions, preferredPrimaryId);
2035
- const rest = actions.filter((a) => a.id !== primary?.id);
2036
- return (_jsxs(_Fragment, { children: [primary !== undefined && (_jsx(RenderEditActionButton, { action: primary, Button: Button, Dialog: Dialog, hideIcon: true, onError: onError }, primary.id)), _jsx(ActionOverflowMenu, { label: t("kumiko.list.row-actions.more"), testId: "kumiko-screen-projection-detail-actions-overflow", items: rest.map(toMenuItem) }), pendingActionDialog] }));
2037
- }
2038
2026
  function ProjectionDetailBody({ schema, screen, translate, entityId, }) {
2039
2027
  const { Banner, Button, Dialog, Text, Grid, GridCell, Card, Tabs, StatusBadge, Metric, MetricBand, PageHeader, Link, ActionOverflowMenu, } = usePrimitives();
2040
2028
  const t = useTranslation();
@@ -2101,6 +2089,7 @@ function ProjectionDetailBody({ schema, screen, translate, entityId, }) {
2101
2089
  const appFeatures = useAppFeatures();
2102
2090
  const userRoles = useUserRoles();
2103
2091
  const dispatcher = useOptionalDispatcher();
2092
+ const clientActions = useClientActionRuntime();
2104
2093
  const host = useReturnHost();
2105
2094
  const returnTargetParam = useReturnTarget(screen.id);
2106
2095
  // A singleton has no record route to come back to — same as entityEdit.
@@ -2194,6 +2183,7 @@ function ProjectionDetailBody({ schema, screen, translate, entityId, }) {
2194
2183
  onWriteSuccess: detailQuery.refetch,
2195
2184
  onRecordLeft: handleRecordLeft,
2196
2185
  sameEntityScreenId,
2186
+ clientActions,
2197
2187
  }), [
2198
2188
  detailQuery.data,
2199
2189
  detailQuery.refetch,
@@ -2201,6 +2191,7 @@ function ProjectionDetailBody({ schema, screen, translate, entityId, }) {
2201
2191
  nav,
2202
2192
  host,
2203
2193
  dispatcher,
2194
+ clientActions,
2204
2195
  openDrawer,
2205
2196
  handleRecordLeft,
2206
2197
  sameEntityScreenId,
@@ -2218,6 +2209,7 @@ function ProjectionDetailBody({ schema, screen, translate, entityId, }) {
2218
2209
  onWriteSuccess: detailQuery.refetch,
2219
2210
  onRecordLeft: handleRecordLeft,
2220
2211
  sameEntityScreenId,
2212
+ clientActions,
2221
2213
  });
2222
2214
  if (defaultEditAction === undefined || declaredHasEdit)
2223
2215
  return resolved;
@@ -2229,6 +2221,7 @@ function ProjectionDetailBody({ schema, screen, translate, entityId, }) {
2229
2221
  nav,
2230
2222
  host,
2231
2223
  dispatcher,
2224
+ clientActions,
2232
2225
  detailQuery.data,
2233
2226
  detailQuery.refetch,
2234
2227
  openDrawer,
@@ -2354,7 +2347,6 @@ function ProjectionDetailBody({ schema, screen, translate, entityId, }) {
2354
2347
  void reloadDetail();
2355
2348
  } })] }));
2356
2349
  }
2357
- // ---- actionForm (Tier 2.7d) ----
2358
2350
  function redirectScreenTarget(redirect) {
2359
2351
  return typeof redirect === "string" ? redirect : redirect.screen;
2360
2352
  }
@@ -2414,7 +2406,7 @@ function returnToWinsOverRedirect(returnTarget, redirect, schema, appFeatures) {
2414
2406
  // write executor's success payload doesn't flatly expose.
2415
2407
  function resolveRedirectTarget(redirect, submittedData, schema, appFeatures, fallbackRecord) {
2416
2408
  const redirectScreen = redirectScreenTarget(redirect);
2417
- const idField = typeof redirect === "string" ? "id" : redirect.idFrom;
2409
+ const idField = typeof redirect === "string" ? "id" : (redirect.idFrom ?? "id");
2418
2410
  const targetId = lastSegment(redirectScreen);
2419
2411
  const target = findRedirectTargetScreen(redirect, schema, appFeatures);
2420
2412
  const carriesId = target !== undefined && (target.type === "entityEdit" || target.type === "projectionDetail");
@@ -2438,6 +2430,30 @@ function navigateToRedirectTarget(nav, target) {
2438
2430
  else
2439
2431
  nav.navigate(navTarget, { searchParams: { tab: target.tab } });
2440
2432
  }
2433
+ // Links of the success box. Targets resolve like `redirect`; a link whose target
2434
+ // needs a record id (entityEdit, projectionDetail) but whose payload field holds
2435
+ // no string id is dropped instead of navigating to an id-less record screen.
2436
+ // A link without idFrom to a non-record screen always navigates id-less.
2437
+ function resolveSuccessLinks(links, data, schema, appFeatures, nav, translate) {
2438
+ const resolved = [];
2439
+ (links ?? []).forEach((link, index) => {
2440
+ const target = resolveRedirectTarget(link, data, schema, appFeatures);
2441
+ if (target.entityId === undefined && redirectTargetsRecord(link, schema, appFeatures))
2442
+ return;
2443
+ const navTarget = {
2444
+ screenId: target.screenId,
2445
+ ...(target.entityId !== undefined && { entityId: target.entityId }),
2446
+ };
2447
+ const options = target.tab === undefined ? undefined : { searchParams: { tab: target.tab } };
2448
+ resolved.push({
2449
+ key: String(index),
2450
+ label: translate(link.label),
2451
+ href: nav.hrefFor(navTarget, options),
2452
+ onPress: () => nav.navigate(navTarget, options),
2453
+ });
2454
+ });
2455
+ return resolved;
2456
+ }
2441
2457
  // Success navigation for a configured redirect — shared by entityEdit's
2442
2458
  // save and writeHandler record actions. The string form navigates without an
2443
2459
  // entityId; the object form resolves like actionForm's, with `record` as the
@@ -2471,7 +2487,7 @@ function overlayUpdatedProjection(record, resultData) {
2471
2487
  // Button) ist identisch zu entityEdit, nur der Submit-Pfad wechselt
2472
2488
  // vom CRUD-verb auf den Author-deklarierten handler-QN +
2473
2489
  // payloadMode="values" (alle Form-Werte schicken statt nur Changes).
2474
- function ActionFormBody({ schema, screen, translate, initialOverrides, onSuccess, onCancelOverride, onDirtyChange, submitLabelFallback, }) {
2490
+ function ActionFormBody({ schema, screen, translate, entityId, initialOverrides, onSuccess, onCancelOverride, onDirtyChange, submitLabelFallback, }) {
2475
2491
  const nav = useNav();
2476
2492
  const appFeatures = useAppFeatures();
2477
2493
  const insideDrawer = useInsideDrawer();
@@ -2492,27 +2508,55 @@ function ActionFormBody({ schema, screen, translate, initialOverrides, onSuccess
2492
2508
  // submitting a guessed currency would mis-book the amount — block instead.
2493
2509
  const tenantCurrencyFieldNames = useMemo(() => tenantCurrencyMoneyFieldNames(screen.fields), [screen.fields]);
2494
2510
  const { overrides: moneyCurrencyOverrides, loading: currencyLoading, unresolved: currencyUnresolved, } = useMoneyCurrencyOverrides(screen.fields, tenantCurrencyFieldNames, undefined);
2495
- const initial = useMemo(() => mergeSearchParamsIntoInitial(submittableFields, {
2496
- searchParams: nav.searchParams,
2497
- urlPrefillFields: screen.urlPrefillFields,
2498
- renderableFields: layoutFieldNames(synthScreen),
2499
- ...(moneyCurrencyOverrides !== undefined && { moneyCurrencyOverrides }),
2500
- ...(initialOverrides !== undefined && { drawerOverrides: initialOverrides }),
2501
- ...(handoffValues !== undefined && { handoffValues }),
2502
- }), [
2511
+ const loadableFieldNames = useMemo(() => Object.entries(submittableFields)
2512
+ .filter(([, field]) => !isSecretFormField(field))
2513
+ .map(([name]) => name), [submittableFields]);
2514
+ const loadState = useActionFormLoad(screen.load, screen.load !== undefined
2515
+ ? resolveActionFormRecordId({
2516
+ routeEntityId: entityId,
2517
+ drawerOverrides: initialOverrides,
2518
+ searchParams: nav.searchParams,
2519
+ })
2520
+ : undefined, loadableFieldNames);
2521
+ const loadedValues = loadState?.status === "ready" ? loadState.values : undefined;
2522
+ const initial = useMemo(() => {
2523
+ // With `load` the loaded record is the only source of values: a crafted link
2524
+ // or a row's params must not seed fields the record would otherwise own.
2525
+ const prefillSources = screen.load !== undefined
2526
+ ? { searchParams: {}, urlPrefillFields: undefined }
2527
+ : {
2528
+ searchParams: nav.searchParams,
2529
+ urlPrefillFields: screen.urlPrefillFields,
2530
+ ...(initialOverrides !== undefined && { drawerOverrides: initialOverrides }),
2531
+ ...(handoffValues !== undefined && { handoffValues }),
2532
+ };
2533
+ return {
2534
+ ...mergeSearchParamsIntoInitial(submittableFields, {
2535
+ ...prefillSources,
2536
+ renderableFields: layoutFieldNames(synthScreen),
2537
+ ...(moneyCurrencyOverrides !== undefined && { moneyCurrencyOverrides }),
2538
+ }),
2539
+ ...loadedValues,
2540
+ };
2541
+ }, [
2503
2542
  submittableFields,
2543
+ screen.load,
2504
2544
  screen.urlPrefillFields,
2505
2545
  nav.searchParams,
2506
2546
  synthScreen,
2507
2547
  moneyCurrencyOverrides,
2508
2548
  initialOverrides,
2509
2549
  handoffValues,
2550
+ loadedValues,
2510
2551
  ]);
2511
2552
  const t = useTranslation();
2512
2553
  const effectiveTranslate = translate ?? t;
2513
2554
  const summary = useMemo(() => resolveActionFormSummary(screen.summary, initialOverrides, effectiveTranslate, locale), [screen.summary, initialOverrides, effectiveTranslate, locale]);
2514
2555
  const dispatcher = useDispatcher();
2515
- const [successText, setSuccessText] = useState(undefined);
2556
+ const [success, setSuccess] = useState(undefined);
2557
+ // Bumped after a successful submit with resetOnSuccess: remounts RenderEdit, which
2558
+ // re-seeds the form from `initial` (prefill kept, typed values cleared).
2559
+ const [formEpoch, setFormEpoch] = useState(0);
2516
2560
  // A slow label lookup of an earlier submit must not overwrite the banner of a later one.
2517
2561
  const successSequence = useRef(0);
2518
2562
  useEffect(() => () => {
@@ -2521,23 +2565,36 @@ function ActionFormBody({ schema, screen, translate, initialOverrides, onSuccess
2521
2565
  const handleSubmitted = useCallback((result, values) => {
2522
2566
  successSequence.current += 1;
2523
2567
  const sequence = successSequence.current;
2524
- setSuccessText(undefined);
2568
+ setSuccess(undefined);
2525
2569
  if (!result.isSuccess)
2526
2570
  return;
2527
2571
  if (onSuccess !== undefined) {
2528
2572
  onSuccess();
2529
2573
  return;
2530
2574
  }
2531
- if (screen.successMessage !== undefined && screen.redirect === undefined) {
2532
- const messageKey = screen.successMessage;
2533
- const show = (params) => {
2534
- if (successSequence.current === sequence) {
2535
- setSuccessText(effectiveTranslate(messageKey, params));
2536
- }
2575
+ if (screen.redirect === undefined) {
2576
+ const hasSuccessLinks = (screen.successLinks?.length ?? 0) > 0 || (screen.successFacts?.length ?? 0) > 0;
2577
+ const publish = (text) => {
2578
+ if (successSequence.current !== sequence)
2579
+ return;
2580
+ setSuccess({
2581
+ text,
2582
+ links: resolveSuccessLinks(screen.successLinks, result.data, schema, appFeatures, nav, effectiveTranslate),
2583
+ facts: resolveSuccessFacts(screen.successFacts, result.data, effectiveTranslate, locale),
2584
+ });
2537
2585
  };
2538
- void resolveSuccessMessageParams(screen, schema.featureName, values, dispatcher, locale)
2539
- .then(show)
2540
- .catch(() => show(formatSummaryParams(values, locale)));
2586
+ const messageKey = screen.successMessage;
2587
+ if (messageKey !== undefined) {
2588
+ const show = (params) => publish(effectiveTranslate(messageKey, params));
2589
+ void resolveSuccessMessageParams(screen, schema.featureName, values, dispatcher, locale)
2590
+ .then(show)
2591
+ .catch(() => show(formatSummaryParams(values, locale)));
2592
+ }
2593
+ else if (hasSuccessLinks || screen.resetOnSuccess === true) {
2594
+ publish(effectiveTranslate("kumiko.actionForm.success"));
2595
+ }
2596
+ if (screen.resetOnSuccess === true)
2597
+ setFormEpoch((epoch) => epoch + 1);
2541
2598
  }
2542
2599
  // Without a redirect the form stays put; returnTo only replaces an existing
2543
2600
  // navigation, and never one to a record screen (see redirectTargetsRecord).
@@ -2560,6 +2617,14 @@ function ActionFormBody({ schema, screen, translate, initialOverrides, onSuccess
2560
2617
  locale,
2561
2618
  effectiveTranslate,
2562
2619
  ]);
2620
+ // The success box disappears with the next edit; a submit clears it itself.
2621
+ const handleDirtyChange = useCallback((dirty) => {
2622
+ if (dirty) {
2623
+ successSequence.current += 1;
2624
+ setSuccess(undefined);
2625
+ }
2626
+ onDirtyChange?.(dirty);
2627
+ }, [onDirtyChange]);
2563
2628
  // Cancel ist nur sinnvoll wenn ein Navigations-Ziel existiert —
2564
2629
  // sonst hätte der Button nirgendwo hin zu navigieren. cancelTarget
2565
2630
  // gewinnt über redirect; `false` schaltet den Button explizit ab
@@ -2582,6 +2647,9 @@ function ActionFormBody({ schema, screen, translate, initialOverrides, onSuccess
2582
2647
  if (currencyUnresolved) {
2583
2648
  return (_jsx(Banner, { padded: true, variant: "error", testId: "kumiko-screen-currency-unresolved", children: "The tenant currency could not be loaded, so this form cannot be submitted." }));
2584
2649
  }
2650
+ if (loadState !== undefined && loadState.status !== "ready") {
2651
+ return (_jsx(ActionFormLoadStatus, { state: loadState, screenId: screen.id, translate: effectiveTranslate }));
2652
+ }
2585
2653
  return (_jsx(RenderEdit, { screen: synthScreen, entity: synthEntity, featureName: schema.featureName, initial: initial,
2586
2654
  // Extension-Sections im actionForm sehen die initialen Form-Values
2587
2655
  // (inkl. searchParams-Prefill, z.B. ?incidentId=…) als initialValues
@@ -2589,11 +2657,11 @@ function ActionFormBody({ schema, screen, translate, initialOverrides, onSuccess
2589
2657
  // sie Kontext ziehen könnten.
2590
2658
  extensionInitialValues: initial, ...(screen.submitPrefilled === true && {
2591
2659
  submitWithoutChanges: hiddenRequiredFieldsFilled(synthScreen, screen.fields, initial),
2592
- }), ...(successText !== undefined && {
2593
- leadContent: (_jsx(Banner, { variant: "info", testId: "action-form-success", children: successText })),
2594
- }), writeCommand: screen.handler, payloadMode: "values", onSubmit: handleSubmitted, ...(handleCancel !== undefined && { onCancel: handleCancel }), ...(onDirtyChange !== undefined && { onDirtyChange }), ...((insideDrawer || screenFillsHeight(screen)) && { fillScreenHeight: true }), ...((screen.submitLabel ?? submitLabelFallback) !== undefined && {
2660
+ }), ...(success !== undefined && {
2661
+ leadContent: _jsx(ActionFormSuccessBanner, { success: success }),
2662
+ }), writeCommand: screen.handler, payloadMode: "values", onSubmit: handleSubmitted, ...(handleCancel !== undefined && { onCancel: handleCancel }), onDirtyChange: handleDirtyChange, ...((insideDrawer || screenFillsHeight(screen)) && { fillScreenHeight: true }), ...((screen.submitLabel ?? submitLabelFallback) !== undefined && {
2595
2663
  submitLabel: screen.submitLabel ?? submitLabelFallback,
2596
- }), ...(screen.submitStyle !== undefined && { submitVariant: screen.submitStyle }), ...(screen.footerActions !== undefined && { footerActions: screen.footerActions }), ...(summary !== undefined && { summary }), ...(translate !== undefined && { translate }) }));
2664
+ }), ...(screen.submitStyle !== undefined && { submitVariant: screen.submitStyle }), ...(screen.footerActions !== undefined && { footerActions: screen.footerActions }), ...(summary !== undefined && { summary }), ...(translate !== undefined && { translate }) }, formEpoch));
2597
2665
  }
2598
2666
  // A money-typed config-edit field renders through RenderField's entityEdit
2599
2667
  // `{amount, currency}` payload shape (render-field.tsx, #1923), but
@@ -1,8 +1,8 @@
1
1
  import type { ListEmptyStateSpec } from "@cosmicdrift/kumiko-framework/ui-types";
2
- import type { Translate } from "@cosmicdrift/kumiko-headless";
3
2
  import type { ListEmptyStateContent } from "../components/list-empty-state.tsx";
3
+ import type { Translate } from "../headless/index.ts";
4
4
  import { buildRecordActions } from "./row-actions.ts";
5
- type ActionBindings = Pick<Parameters<typeof buildRecordActions>[0], "nav" | "host" | "dispatcher" | "openDrawer" | "onWriteSuccess">;
5
+ type ActionBindings = Pick<Parameters<typeof buildRecordActions>[0], "nav" | "host" | "dispatcher" | "openDrawer" | "onWriteSuccess" | "clientActions">;
6
6
  export declare function useListEmptyContent(spec: ListEmptyStateSpec | undefined, translate: Translate, bindings: ActionBindings): ListEmptyStateContent | undefined;
7
7
  export declare function isListNarrowed(search: string, filters: Readonly<Record<string, readonly string[]>>, defaultFilters?: Readonly<Record<string, readonly string[]>>): boolean;
8
8
  export {};
@@ -3,7 +3,7 @@ import { buildRecordActions } from "./row-actions.js";
3
3
  const NO_RECORD = {};
4
4
  // An empty list has no row, so the action is resolved against an empty record.
5
5
  export function useListEmptyContent(spec, translate, bindings) {
6
- const { nav, host, dispatcher, openDrawer, onWriteSuccess } = bindings;
6
+ const { nav, host, dispatcher, openDrawer, onWriteSuccess, clientActions } = bindings;
7
7
  return useMemo(() => {
8
8
  if (spec === undefined)
9
9
  return undefined;
@@ -18,13 +18,14 @@ export function useListEmptyContent(spec, translate, bindings) {
18
18
  dispatcher,
19
19
  openDrawer,
20
20
  onWriteSuccess,
21
+ clientActions,
21
22
  })?.[0];
22
23
  return {
23
24
  title: translate(spec.title),
24
25
  ...(spec.description !== undefined && { description: translate(spec.description) }),
25
26
  ...(action !== undefined && { action }),
26
27
  };
27
- }, [spec, translate, nav, host, dispatcher, openDrawer, onWriteSuccess]);
28
+ }, [spec, translate, nav, host, dispatcher, openDrawer, onWriteSuccess, clientActions]);
28
29
  }
29
30
  // Facets with a default are only "narrowed" once the user moved off that default.
30
31
  export function isListNarrowed(search, filters, defaultFilters = {}) {
@@ -1,5 +1,5 @@
1
1
  import type { EntityListFacetConfig, ListFacetSpec } from "@cosmicdrift/kumiko-framework/ui-types";
2
- import type { Translate } from "@cosmicdrift/kumiko-headless";
2
+ import type { Translate } from "../headless/index.ts";
3
3
  import type { DataTableFacet, DataTableFacetChip } from "../primitives.tsx";
4
4
  export type ResolvedFacetSpec = {
5
5
  readonly field: string;
package/dist/app/nav.js CHANGED
@@ -76,7 +76,7 @@ export function hasDetailScreen(features, entity) {
76
76
  }
77
77
  // Resolves a NavTarget to the ScreenTarget form navigate/replace/hrefFor
78
78
  // operate on. Pure — no context, no I/O — so callers can use it outside
79
- // React too (see resolve-at-NavApi-build alternative in renderer-web).
79
+ // React too (see resolve-at-NavApi-build alternative in renderer/web).
80
80
  export function resolveTarget(features, target) {
81
81
  if ("screenId" in target)
82
82
  return target;
@@ -151,7 +151,7 @@ export function useOptionalNav() {
151
151
  export function useNav() {
152
152
  const api = useContext(NavContext);
153
153
  if (api === undefined) {
154
- throw new Error("useNav: no <NavProvider> mounted above this component. Plattform-Packages (z.B. @cosmicdrift/kumiko-renderer-web) liefern eine Default-Impl über createKumikoApp.");
154
+ throw new Error("useNav: no <NavProvider> mounted above this component. Plattform-Packages (z.B. @cosmicdrift/kumiko-renderer/web) liefern eine Default-Impl über createKumikoApp.");
155
155
  }
156
156
  return api;
157
157
  }
@@ -1,5 +1,5 @@
1
- import type { DispatcherError, Translate } from "@cosmicdrift/kumiko-headless";
2
1
  import type { ReactNode } from "react";
2
+ import type { DispatcherError, Translate } from "../headless/index.ts";
3
3
  export declare function QueryLoadingBanner(): ReactNode;
4
4
  export declare function QueryErrorBanner({ error, translate, onRetry, }: {
5
5
  readonly error: DispatcherError;
@@ -1,4 +1,4 @@
1
- import type { CellLink } from "@cosmicdrift/kumiko-headless";
1
+ import type { CellLink } from "../headless/index.ts";
2
2
  /** Link to a referenced record's detail screen, or undefined when there is no
3
3
  * navigation, the user may not open that screen, or no detail screen exists. */
4
4
  export type ReferenceLinkResolver = (refEntity: string, id: string) => CellLink | undefined;
@@ -1,8 +1,9 @@
1
- import type { EntityEditScreenDefinition, RelatedListToolbarAction, RowAction, RowActionDrawer, RowActionNavigate, RowActionWriteHandler, RowFieldExtractor, ToolbarAction } from "@cosmicdrift/kumiko-framework/ui-types";
2
- import type { Dispatcher, ListRowViewModel, Translate } from "@cosmicdrift/kumiko-headless";
1
+ import type { EntityEditScreenDefinition, RelatedListToolbarAction, RowAction, RowActionClientAction, RowActionDrawer, RowActionNavigate, RowActionWriteHandler, RowFieldExtractor, ToolbarAction } from "@cosmicdrift/kumiko-framework/ui-types";
3
2
  import type { RenderEditAction } from "../components/render-edit-types.ts";
4
3
  import type { ToolbarActionButton } from "../components/render-list.tsx";
4
+ import type { Dispatcher, ListRowViewModel, Translate } from "../headless/index.ts";
5
5
  import type { DataTableRowAction } from "../primitives.tsx";
6
+ import { type ClientActionRuntime } from "./client-actions.tsx";
6
7
  import type { NavApi } from "./nav.tsx";
7
8
  import { type ReturnHost } from "./return-to.tsx";
8
9
  export declare function buildDefaultEditRowAction(editScreen: EntityEditScreenDefinition | undefined, idColumn?: string): RowActionNavigate | undefined;
@@ -15,7 +16,12 @@ export declare function runProjectionRowNavigate(nav: NavApi, action: RowActionN
15
16
  type OpenDrawer = (action: RowActionDrawer, initialValues: Readonly<Record<string, unknown>> | undefined) => void;
16
17
  /** @internal test-only */
17
18
  export declare function resetDrawerActionWarningsForTests(): void;
19
+ export declare function runDrawerRowAction(action: RowActionDrawer, openDrawer: OpenDrawer, row: ListRowViewModel): void;
20
+ /** The action that claims the row-body click (`rowClick: true`); the boot
21
+ * validator allows at most one per list. */
22
+ export declare function findRowClickAction(rowActions: readonly RowAction[] | undefined): RowActionNavigate | RowActionDrawer | undefined;
18
23
  export declare function buildDrawerRowAction(action: RowActionDrawer, translate: Translate, openDrawer: OpenDrawer): DataTableRowAction;
24
+ export declare function buildClientActionRowAction(action: RowActionClientAction, translate: Translate, runtime: ClientActionRuntime | undefined, refetch: () => Promise<unknown>): DataTableRowAction;
19
25
  export declare function buildProjectionRowActions(options: {
20
26
  readonly rowActions: readonly RowAction[] | undefined;
21
27
  readonly translate: Translate;
@@ -30,6 +36,7 @@ export declare function buildProjectionRowActions(options: {
30
36
  /** Prepended unless a declared action already has id "edit" — declared wins. */
31
37
  readonly defaultEditRowAction?: RowActionNavigate;
32
38
  readonly host: ReturnHost | undefined;
39
+ readonly clientActions?: ClientActionRuntime;
33
40
  }): readonly DataTableRowAction[] | undefined;
34
41
  type OpenToolbarDrawer = (action: ToolbarAction & {
35
42
  readonly kind: "drawer";
@@ -93,5 +100,6 @@ export declare function buildRecordActions(options: {
93
100
  * action (they reload or remount the surrounding form). Set while that
94
101
  * form holds unsaved input so it is not lost silently. */
95
102
  readonly discardChanges?: DiscardChanges;
103
+ readonly clientActions?: ClientActionRuntime;
96
104
  }): readonly RenderEditAction[] | undefined;
97
105
  export {};