@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
@@ -1,7 +1,8 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { evalFieldCondition, isFieldsEditSection, normalizeEditField, PROJECTION_DETAIL_ENTITY, sectionFieldSpecs, } from "@cosmicdrift/kumiko-framework/ui-types";
3
- import { computeEditViewModel, groupIssuesByPath, relevantFieldIssues, zodErrorToFieldIssues, } from "@cosmicdrift/kumiko-headless";
4
3
  import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
4
+ import { computeEditViewModel, groupIssuesByPath, relevantFieldIssues, zodErrorToFieldIssues, } from "../headless/index.js";
5
+ import { changedDerivedValues } from "./form-derivation-patch.js";
5
6
  import { RenderEditActionButton } from "./render-edit-action-button.js";
6
7
  import { AllFieldsRequiredProvider } from "./render-field.js";
7
8
  import { useActionMenuItems } from "./use-action-menu-items.js";
@@ -229,7 +230,7 @@ function resolveTitleTemplate(template, values, translate, fallback) {
229
230
  return translate(template, values);
230
231
  }
231
232
  export function RenderEdit(props) {
232
- const { screen, entity, featureName, initial, writeCommand, translate: translateProp, ctx, schema, onSubmit, payloadMode = "values", buildPayload, serverFieldPathPrefix, onDelete, onCancel, onReload, refreshToken, onDirtyChange, onCopyLink, actions, menuActions, onRelatedListDrawerAction, submitLabel, submitVariant, submitWithoutChanges, footerActions, summary, labelAppendix, fieldAppendix, fieldAppendixPlacement, fieldDescription, fieldAccent, markChangedFields = false, entityId: entityIdProp, extensionInitialValues, onChange, onControlsReady, fields: fieldsFilter, disabled: disabledProp = false, viewMode = false, hideActions, valueDisplay = "form", hideSectionTitles, fillScreenHeight, dirtyFooter, validateOnChange, headerRegion, buildSectionActions, leadContent, submitBlocked = false, } = props;
233
+ const { screen, entity, featureName, initial, writeCommand, translate: translateProp, ctx, schema, onSubmit, payloadMode = "values", buildPayload, serverFieldPathPrefix, onDelete, onCancel, onReload, refreshToken, onDirtyChange, onCopyLink, actions, menuActions, onRelatedListDrawerAction, submitLabel, submitVariant, submitWithoutChanges, footerActions, summary, labelAppendix, fieldAppendix, fieldAppendixPlacement, fieldDescription, fieldAccent, markChangedFields = false, entityId: entityIdProp, extensionInitialValues, onChange, onControlsReady, fields: fieldsFilter, disabled: disabledProp = false, viewMode = false, hideActions, valueDisplay = "form", hideSectionTitles, fillScreenHeight, dirtyFooter, validateOnChange, headerRegion, buildSectionActions, leadContent, submitBlocked = false, formDerivation, } = props;
233
234
  // View mode is a locked form, so everything keyed on `disabled` follows.
234
235
  const disabled = disabledProp || viewMode;
235
236
  const i18nScreenId = props.i18nScreenId ?? screen.id;
@@ -367,6 +368,16 @@ export function RenderEdit(props) {
367
368
  ...(ctx !== undefined && { ctx }),
368
369
  ...(submitConfig !== undefined && { submit: submitConfig }),
369
370
  });
371
+ // Derived fields are written into form state (not only displayed) so required
372
+ // validation and the submit payload carry them; only a real change is set, which
373
+ // keeps this from looping.
374
+ useEffect(() => {
375
+ if (formDerivation === undefined)
376
+ return;
377
+ const patch = changedDerivedValues(snapshot.values, formDerivation);
378
+ if (patch !== undefined)
379
+ controller.setValues(patch); // @cast-boundary form-values
380
+ }, [snapshot.values, formDerivation, controller]);
370
381
  // Wired at the user-input boundary, not in controller.setField: computed
371
382
  // fields, prefill, draft restore and action patches also call setValues
372
383
  // after a failed submit and must not wipe the errors.
@@ -654,7 +665,9 @@ export function RenderEdit(props) {
654
665
  featureName,
655
666
  mode: writeVerb,
656
667
  ...(!isCreateMode && entityIdProp != null && { entityId: entityIdProp }),
668
+ ...(formDerivation !== undefined && { derivation: formDerivation }),
657
669
  }), [
670
+ formDerivation,
658
671
  screen,
659
672
  entity,
660
673
  snapshot.values,
@@ -1075,6 +1088,7 @@ export function RenderEdit(props) {
1075
1088
  wizardBackRef.current = isWizard ? handleWizardBack : () => { };
1076
1089
  // Screen forms (entityEdit/actionForm filling the shell height) drop the card;
1077
1090
  // the title then lives in the shell header when the shell offers a slot.
1091
+ const rootIssues = snapshot.errors[ROOT_ISSUE_PATH] ?? [];
1078
1092
  const isScreenForm = fillScreenHeight === true && hideSectionTitles !== true && !insideDrawer;
1079
1093
  const titleInShell = PageHeader !== undefined &&
1080
1094
  pageHeaderSlotAvailable &&
@@ -1480,7 +1494,8 @@ export function RenderEdit(props) {
1480
1494
  onReload();
1481
1495
  setFormError(null);
1482
1496
  setExtraDeleteIssues([]);
1483
- }, testId: "render-edit-form-error-reload", children: translate("kumiko.actions.reload") })) : undefined, children: [_jsx(Text, { testId: "render-edit-form-error-key", children: translate(formError.i18nKey, formError.i18nParams) }), extraDeleteIssues.map((issue) => (_jsx(Text, { testId: "render-edit-form-error-extra", children: translate(issue.i18nKey, issue.params) }, `${issue.path}:${issue.i18nKey}`)))] })), (snapshot.errors[ROOT_ISSUE_PATH] ?? []).map((issue) => (_jsx(Banner, { variant: "error", testId: "render-edit-root-issue", children: _jsx(Text, { children: translate(issue.i18nKey, issue.params) }) }, issue.i18nKey))), extensionErrorKey !== null && (_jsx(Banner, { variant: "error", testId: "render-edit-extension-error", children: _jsx(Text, { testId: "render-edit-extension-error-key", children: translate(extensionErrorKey) }) })), actionError !== null && (_jsx(Banner, { variant: "error", testId: "render-edit-action-error", children: actionError })), onDelete !== undefined && (_jsx(Dialog, { open: confirmDeleteOpen, onOpenChange: setConfirmDeleteOpen, title: translate("kumiko.actions.delete-confirm"), confirmLabel: translate("kumiko.actions.delete"), variant: "danger", onConfirm: async () => {
1497
+ }, testId: "render-edit-form-error-reload", children: translate("kumiko.actions.reload") })) : undefined, children: [_jsx(Text, { testId: "render-edit-form-error-key", children: translate(formError.i18nKey, formError.i18nParams) }), rootIssues.map((issue) => (_jsx(Text, { testId: "render-edit-form-error-root", children: translate(issue.i18nKey, issue.params) }, `${issue.path}:${issue.i18nKey}`))), extraDeleteIssues.map((issue) => (_jsx(Text, { testId: "render-edit-form-error-extra", children: translate(issue.i18nKey, issue.params) }, `${issue.path}:${issue.i18nKey}`)))] })), formError === null &&
1498
+ rootIssues.map((issue) => (_jsx(Banner, { variant: "error", testId: "render-edit-root-issue", children: _jsx(Text, { children: translate(issue.i18nKey, issue.params) }) }, issue.i18nKey))), extensionErrorKey !== null && (_jsx(Banner, { variant: "error", testId: "render-edit-extension-error", children: _jsx(Text, { testId: "render-edit-extension-error-key", children: translate(extensionErrorKey) }) })), actionError !== null && (_jsx(Banner, { variant: "error", testId: "render-edit-action-error", children: actionError })), onDelete !== undefined && (_jsx(Dialog, { open: confirmDeleteOpen, onOpenChange: setConfirmDeleteOpen, title: translate("kumiko.actions.delete-confirm"), confirmLabel: translate("kumiko.actions.delete"), variant: "danger", onConfirm: async () => {
1484
1499
  const rejection = await onDelete();
1485
1500
  // A rejected delete (e.g. a preDelete hook) carries its reason in
1486
1501
  // the field issues; the top-level key is only "validation failed".
@@ -1,5 +1,5 @@
1
- import { type EditFieldViewModel, type FieldIssue } from "@cosmicdrift/kumiko-headless";
2
1
  import { type ReactNode } from "react";
2
+ import { type EditFieldViewModel, type FieldIssue } from "../headless/index.ts";
3
3
  import { type FieldProps } from "../primitives.tsx";
4
4
  export type RenderFieldProps = {
5
5
  readonly field: EditFieldViewModel;
@@ -1,6 +1,5 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { isFormatSpec, SYSTEM_REFERENCE_LABELS, } from "@cosmicdrift/kumiko-framework/ui-types";
3
- import { applyFormatSpec, currencyDecimals, EMPTY_VALUE_PLACEHOLDER, } from "@cosmicdrift/kumiko-headless";
4
3
  import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
5
4
  import { createContext, Fragment, useCallback, useContext, useEffect, useMemo, useRef, useState, } from "react";
6
5
  import { useAppFeatures } from "../app/app-features-context.js";
@@ -12,6 +11,8 @@ import { evalRowExtractor } from "../app/row-actions.js";
12
11
  import { screenAccessAllows } from "../app/screen-access.js";
13
12
  import { useOptionalDispatcher } from "../context/dispatcher-context.js";
14
13
  import { useUserRoles } from "../context/user-roles-context.js";
14
+ import { fileIdsOf } from "../file-ids-of.js";
15
+ import { applyFormatSpec, currencyDecimals, EMPTY_VALUE_PLACEHOLDER, } from "../headless/index.js";
15
16
  import { REFERENCE_COMBOBOX_LIMIT } from "../hooks/reference-limits.js";
16
17
  import { useQuery } from "../hooks/use-query.js";
17
18
  import { referenceOptionSource } from "../hooks/use-reference-lookup.js";
@@ -280,7 +281,7 @@ function inputId(field) {
280
281
  // Doesn't resolve the `string` (cross-feature QN) FieldRenderer variant — the
281
282
  // list-column path (DataTableCell) doesn't either, so this stays in parity.
282
283
  function FieldRendererOutput({ field, renderer, row, appLocale, }) {
283
- const { Text, JsonView } = usePrimitives();
284
+ const { Text, JsonView, FileValueList } = usePrimitives();
284
285
  const t = useTranslation();
285
286
  const componentName = !isFormatSpec(renderer) && typeof renderer === "object" && renderer !== null
286
287
  ? extensionSectionName(renderer)
@@ -293,6 +294,12 @@ function FieldRendererOutput({ field, renderer, row, appLocale, }) {
293
294
  if (renderer.format === "json" && JsonView !== undefined) {
294
295
  return (_jsx(JsonView, { value: field.value, indent: renderer.indent, testId: `field-value-${field.field}` }));
295
296
  }
297
+ if (renderer.format === "file" && FileValueList !== undefined) {
298
+ const fileIds = fileIdsOf(field.value);
299
+ if (fileIds.length === 0)
300
+ return _jsx(Text, { testId: `field-value-${field.field}`, children: EMPTY_VALUE_PLACEHOLDER });
301
+ return _jsx(FileValueList, { fileIds: fileIds, testId: `field-value-${field.field}` });
302
+ }
296
303
  // App locale as default when the FormatSpec declares none of its own —
297
304
  // otherwise locale-sensitive formats (timestamp/date/number/decimal/
298
305
  // bigInt/unit) fell back to Intl's runtime default instead of the app
@@ -494,6 +501,9 @@ function renderInput({ field, id, hasError, onChange, Input, appLocale, Banner,
494
501
  if (field.type === "text" && field.format === "password") {
495
502
  return (_jsx(Input, { kind: "password", ...common, value: stringValue(field.value), onChange: (v) => onChange(v) }));
496
503
  }
504
+ if (field.type === "text" && field.format === "month") {
505
+ return (_jsx(Input, { kind: "month", ...common, value: stringValue(field.value), onChange: (v) => onChange(v) }));
506
+ }
497
507
  // text + unknown scalar type → text input. If TextFieldDef.multiline
498
508
  // is set (the view-model carries it), the renderer switches to
499
509
  // textarea. longText always renders a textarea — that's the point of
@@ -1,6 +1,6 @@
1
1
  import type { EntityDefinition, EntityListScreenDefinition, IconKey } from "@cosmicdrift/kumiko-framework/ui-types";
2
- import type { ListRowViewModel, Translate } from "@cosmicdrift/kumiko-headless";
3
2
  import { type ReactNode } from "react";
3
+ import type { ListRowViewModel, Translate } from "../headless/index.ts";
4
4
  import type { ListSort } from "../hooks/use-list-url-state.ts";
5
5
  import { type DataTableDateRangeFacet, type DataTableFacet, type DataTableProps, type DataTableRowAction, type DataTableRowActionMode, type DataTableRowGrouping } from "../primitives.tsx";
6
6
  import { type ListEmptyStateContent } from "./list-empty-state.tsx";
@@ -1,8 +1,8 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { computeListViewModel, EMPTY_VALUE_PLACEHOLDER } from "@cosmicdrift/kumiko-headless";
3
2
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
4
3
  import { extensionSectionName, useExtensionSectionComponent } from "../app/extension-sections.js";
5
4
  import { useReferenceLinkResolver } from "../app/reference-link.js";
5
+ import { computeListViewModel, EMPTY_VALUE_PLACEHOLDER } from "../headless/index.js";
6
6
  import { useReferenceLookup } from "../hooks/use-reference-lookup.js";
7
7
  import { useTranslation } from "../i18n.js";
8
8
  import { usePageHeaderCompact, usePageHeaderSlotAvailable } from "../page-header-slot.js";
@@ -104,7 +104,7 @@ export function RenderList(props) {
104
104
  const labelField = col.refLabelField ?? "id";
105
105
  const refEntity = col.refEntity ?? "";
106
106
  // Only a row the user can see is linkable: resolved by the server
107
- // eagerload or by the lookup query. A multi-reference stays text.
107
+ // eagerload or by the lookup query. A multi-reference links per entry via linkItemsFor.
108
108
  const linkFor = (value, row) => {
109
109
  if (value === null || value === undefined || value === "" || Array.isArray(value)) {
110
110
  return undefined;
@@ -118,6 +118,22 @@ export function RenderList(props) {
118
118
  map?.has(id);
119
119
  return resolved === true ? resolveReferenceLink(refEntity, id) : undefined;
120
120
  };
121
+ const linkItemsFor = (value, row) => {
122
+ if (!Array.isArray(value) || value.length === 0)
123
+ return undefined;
124
+ const eagerloaded = eagerloadedRef(row, col.field);
125
+ const eagerById = new Map(Array.isArray(eagerloaded) ? eagerloaded.map((r) => [String(r["id"]), r]) : []);
126
+ return value.map((v) => {
127
+ const id = String(v);
128
+ const target = eagerById.get(id);
129
+ const label = String(target?.[labelField] ?? map?.get(id) ?? id);
130
+ // Only a row the user can see is linkable: server eagerload or lookup query.
131
+ const link = target !== undefined || map?.has(id) === true
132
+ ? resolveReferenceLink(refEntity, id)
133
+ : undefined;
134
+ return { id, label, ...(link !== undefined && { link }) };
135
+ });
136
+ };
121
137
  const renderer = (value, row) => {
122
138
  // Tier 2.7e Server-Eagerload: wenn der Server _refs mit-
123
139
  // schickt, lesen wir den Display-Wert direkt aus der
@@ -142,7 +158,7 @@ export function RenderList(props) {
142
158
  const idStr = String(value);
143
159
  return map?.get(idStr) ?? idStr;
144
160
  };
145
- return { ...col, renderer, linkFor };
161
+ return { ...col, renderer, linkFor, linkItemsFor };
146
162
  });
147
163
  }, [vm.columns, referenceColumns, referenceLookups, resolveReferenceLink]);
148
164
  const enrichedVm = useMemo(() => ({
@@ -190,7 +206,7 @@ export function RenderList(props) {
190
206
  // Wenn weder onCreate noch ein Override gegeben ist, fällt die
191
207
  // DataTable auf den DataTable-Default zurück (`kumiko.list.no-entries`).
192
208
  const composedEmptyState = emptyState ??
193
- (onCreate !== undefined || emptyContent !== undefined || narrowed ? (_jsx(ListEmptyStateBody, { content: emptyContent, narrowed: narrowed, translate: translate, createButton: onCreate !== undefined && !narrowed ? (_jsx(Button, { variant: "primary", icon: "plus", onClick: onCreate, testId: "render-list-empty-create", children: effectiveCreateLabel })) : undefined })) : undefined);
209
+ (onCreate !== undefined || emptyContent !== undefined || narrowed ? (_jsx(ListEmptyStateBody, { content: emptyContent, narrowed: narrowed, translate: translate, createButton: onCreate !== undefined && !narrowed && !createInPageHeader ? (_jsx(Button, { variant: "primary", icon: "plus", onClick: onCreate, testId: "render-list-empty-create", children: effectiveCreateLabel })) : undefined })) : undefined);
194
210
  // Title-Resolution: ein konventioneller i18n-Key `screen:<id>.title`.
195
211
  // Wenn das Bundle den Key kennt, schöner Titel; sonst kommt der
196
212
  // screenId selber raus (kein "Untitled"-Fallback — der App-Dev sieht
@@ -1,5 +1,5 @@
1
- import type { EditWriteFormSectionViewModel, Translate } from "@cosmicdrift/kumiko-headless";
2
1
  import { type ReactNode } from "react";
2
+ import type { EditWriteFormSectionViewModel, Translate } from "../headless/index.ts";
3
3
  export type WriteFormSectionProps = {
4
4
  readonly section: EditWriteFormSectionViewModel;
5
5
  readonly featureName: string;
@@ -1,9 +1,9 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { I18N_KEY_PARAM } from "@cosmicdrift/kumiko-headless";
3
2
  import { useEffect, useMemo, useRef, useState } from "react";
4
3
  import * as z from "zod";
5
4
  import { isPresent, REQUIRED_FIELD_I18N_KEY } from "../app/form-schema.js";
6
5
  import { dispatcherErrorText } from "../app/write-failed-error.js";
6
+ import { I18N_KEY_PARAM } from "../headless/index.js";
7
7
  import { useForm } from "../hooks/use-form.js";
8
8
  import { useTranslation } from "../i18n.js";
9
9
  import { STICKY_PRIMARY_ACTION_PROP, usePrimitives } from "../primitives.js";
@@ -1,5 +1,5 @@
1
- import type { Dispatcher, DispatcherStatus } from "@cosmicdrift/kumiko-headless";
2
1
  import { type ReactNode } from "react";
2
+ import type { Dispatcher, DispatcherStatus } from "../headless/index.ts";
3
3
  import { type QueryPools } from "./query-pool.ts";
4
4
  export type DispatcherProviderProps = {
5
5
  readonly dispatcher: Dispatcher;
@@ -0,0 +1 @@
1
+ export declare function fileIdsOf(value: unknown): readonly string[];
@@ -0,0 +1,7 @@
1
+ export function fileIdsOf(value) {
2
+ if (typeof value === "string")
3
+ return value === "" ? [] : [value];
4
+ if (!Array.isArray(value))
5
+ return [];
6
+ return value.filter((entry) => typeof entry === "string" && entry !== "");
7
+ }
@@ -0,0 +1,3 @@
1
+ import type { FlowIcon } from "./types.ts";
2
+ /** Inner markup for a 24x24 viewBox, stroked via the `.icon` CSS class. "ai" renders as a text badge instead — see render.ts. */
3
+ export declare const ICONS: Record<Exclude<FlowIcon, "ai">, string>;
@@ -0,0 +1,14 @@
1
+ /** Inner markup for a 24x24 viewBox, stroked via the `.icon` CSS class. "ai" renders as a text badge instead — see render.ts. */
2
+ export const ICONS = {
3
+ ui: '<rect class="icon" x="3" y="4" width="18" height="15" rx="1.5"/><path class="icon" d="M3 8h18"/>',
4
+ api: '<path class="icon" d="M8 6l-5 6 5 6"/><path class="icon" d="M16 6l5 6-5 6"/>',
5
+ handler: '<path class="icon" d="M8 4l-4 8 4 8"/><path class="icon" d="M16 4l4 8-4 8"/><path class="icon" d="M11 20l2-16"/>',
6
+ "event-store": '<path class="icon" d="M4 6c0-1.5 3.6-2.5 8-2.5S20 4.5 20 6s-3.6 2.5-8 2.5S4 7.5 4 6z"/><path class="icon" d="M4 6v12c0 1.5 3.6 2.5 8 2.5s8-1 8-2.5V6"/><path class="icon" d="M4 12c0 1.5 3.6 2.5 8 2.5s8-1 8-2.5"/>',
7
+ database: '<path class="icon" d="M4 6c0-1.5 3.6-2.5 8-2.5S20 4.5 20 6s-3.6 2.5-8 2.5S4 7.5 4 6z"/><path class="icon" d="M4 6v12c0 1.5 3.6 2.5 8 2.5s8-1 8-2.5V6"/>',
8
+ inbox: '<path class="icon" d="M3 6h18v13H3z"/><path class="icon" d="M3 6l9 7 9-7"/>',
9
+ broadcast: '<path class="icon" d="M12 20v-1"/><path class="icon" d="M8.5 15.5a5 5 0 017 0"/><path class="icon" d="M5 12a9 9 0 0114 0"/>',
10
+ person: '<circle class="icon" cx="12" cy="8" r="3.2"/><path class="icon" d="M5 20c0-4 3-6 7-6s7 2 7 6"/>',
11
+ check: '<path class="icon" d="M5 12l5 5L20 6"/>',
12
+ stop: '<rect class="icon" x="7" y="7" width="10" height="10" rx="1.5"/>',
13
+ box: '<rect class="icon" x="4" y="4" width="16" height="16" rx="2"/>',
14
+ };
@@ -0,0 +1,2 @@
1
+ export { renderFlow } from "./render.ts";
2
+ export type { FlowEdge, FlowIcon, FlowNode, FlowNodeKind, FlowSpec } from "./types.ts";
@@ -0,0 +1 @@
1
+ export { renderFlow } from "./render.js";
@@ -0,0 +1,3 @@
1
+ import type { FlowSpec } from "./types.ts";
2
+ /** Renders a FlowSpec (a small acyclic node/edge graph) to a self-contained, animated SVG diagram string for embedding in docs pages. */
3
+ export declare function renderFlow(spec: FlowSpec): string;
@@ -0,0 +1,234 @@
1
+ import { escapeHtml } from "../headless/index.js";
2
+ import { ICONS } from "./icons.js";
3
+ const BADGE = 24;
4
+ const ICON_SIZE = 13;
5
+ const PAD_X = 9.6;
6
+ const GAP_BADGE_TEXT = 8;
7
+ const GAP_RIGHT = 11.2;
8
+ const ROW_GAP = 35;
9
+ const COL_GAP = 22;
10
+ const MIN_CARD_WIDTH = 120;
11
+ const TITLE_SIZE = 11.2;
12
+ const SUB_SIZE = 9.2;
13
+ const STEP_SECONDS = 1.2;
14
+ function textWidth(text, fontSize, bold) {
15
+ return text.length * fontSize * (bold ? 0.62 : 0.56);
16
+ }
17
+ function cardSize(node) {
18
+ const titleWidth = textWidth(node.title, TITLE_SIZE, true);
19
+ const subWidth = node.sub ? textWidth(node.sub, SUB_SIZE, false) : 0;
20
+ const content = Math.max(titleWidth, subWidth);
21
+ const width = Math.max(MIN_CARD_WIDTH, BADGE + GAP_BADGE_TEXT + content + PAD_X + GAP_RIGHT);
22
+ const height = node.sub ? 42 : 32;
23
+ return { width, height };
24
+ }
25
+ function assertEdgesReferenceKnownNodes(spec) {
26
+ const ids = new Set(spec.nodes.map((n) => n.id));
27
+ for (const edge of spec.edges) {
28
+ if (!ids.has(edge.from))
29
+ throw new Error(`FlowSpec: edge references unknown node "${edge.from}"`);
30
+ if (!ids.has(edge.to))
31
+ throw new Error(`FlowSpec: edge references unknown node "${edge.to}"`);
32
+ }
33
+ }
34
+ function buildAdjacency(spec) {
35
+ const children = new Map();
36
+ const inDegree = new Map();
37
+ for (const node of spec.nodes)
38
+ inDegree.set(node.id, 0);
39
+ for (const edge of spec.edges) {
40
+ children.set(edge.from, [...(children.get(edge.from) ?? []), edge]);
41
+ inDegree.set(edge.to, (inDegree.get(edge.to) ?? 0) + 1);
42
+ }
43
+ return { children, inDegree };
44
+ }
45
+ /** Longest-path depth per node via Kahn's algorithm; throws if the graph has no root or contains a cycle. */
46
+ function longestPathDepths(spec, children, inDegree) {
47
+ const depth = new Map();
48
+ const queue = spec.nodes.filter((n) => inDegree.get(n.id) === 0).map((n) => n.id);
49
+ if (queue.length === 0 && spec.nodes.length > 0) {
50
+ throw new Error("FlowSpec: no root node found (every node has an incoming edge — check for a cycle)");
51
+ }
52
+ for (const id of queue)
53
+ depth.set(id, 0);
54
+ const remaining = new Map(inDegree);
55
+ let visited = 0;
56
+ for (const id of queue) {
57
+ visited += 1;
58
+ for (const edge of children.get(id) ?? []) {
59
+ const next = Math.max(depth.get(edge.to) ?? 0, (depth.get(id) ?? 0) + 1);
60
+ depth.set(edge.to, next);
61
+ const left = (remaining.get(edge.to) ?? 0) - 1;
62
+ remaining.set(edge.to, left);
63
+ if (left === 0)
64
+ queue.push(edge.to);
65
+ }
66
+ }
67
+ if (visited < spec.nodes.length) {
68
+ throw new Error("FlowSpec: graph has a cycle — a flow diagram must be acyclic");
69
+ }
70
+ return depth;
71
+ }
72
+ function computeDepths(spec) {
73
+ assertEdgesReferenceKnownNodes(spec);
74
+ const { children, inDegree } = buildAdjacency(spec);
75
+ return longestPathDepths(spec, children, inDegree);
76
+ }
77
+ function layout(spec) {
78
+ const depthById = computeDepths(spec);
79
+ const maxDepth = Math.max(0, ...[...depthById.values()]);
80
+ const rows = Array.from({ length: maxDepth + 1 }, () => []);
81
+ for (const node of spec.nodes)
82
+ rows[depthById.get(node.id) ?? 0]?.push(node);
83
+ // Siblings in the same row share one card size (the row's largest), so a
84
+ // row of 3+ always lands symmetrically under its parent — an odd sibling
85
+ // count with mismatched widths otherwise throws the middle card off-center.
86
+ const sizedRows = rows.map((row) => {
87
+ const sizes = row.map((n) => cardSize(n));
88
+ return {
89
+ row,
90
+ width: Math.max(MIN_CARD_WIDTH, ...sizes.map((s) => s.width)),
91
+ height: Math.max(0, ...sizes.map((s) => s.height)),
92
+ };
93
+ });
94
+ const rowWidths = sizedRows.map(({ row, width }) => row.length * width + COL_GAP * Math.max(0, row.length - 1));
95
+ const canvasWidth = Math.max(...rowWidths, MIN_CARD_WIDTH) + 40;
96
+ const centerX = canvasWidth / 2;
97
+ const placed = new Map();
98
+ let y = 20;
99
+ for (const { row, width, height } of sizedRows) {
100
+ const rowWidth = row.length * width + COL_GAP * Math.max(0, row.length - 1);
101
+ let x = centerX - rowWidth / 2;
102
+ for (const node of row) {
103
+ placed.set(node.id, { node, depth: depthById.get(node.id) ?? 0, x, y, width, height });
104
+ x += width + COL_GAP;
105
+ }
106
+ y += height + ROW_GAP;
107
+ }
108
+ const canvasHeight = y - ROW_GAP + 20;
109
+ return { placed, width: canvasWidth, height: canvasHeight, maxDepth };
110
+ }
111
+ function computeTiming(placed, spec, maxDepth) {
112
+ const totalSeconds = STEP_SECONDS * (maxDepth + 1) + STEP_SECONDS * 0.5;
113
+ const timingByEdge = new Map();
114
+ const arrivalByNode = new Map();
115
+ for (const edge of spec.edges) {
116
+ const from = placed.get(edge.from);
117
+ const to = placed.get(edge.to);
118
+ if (!from || !to)
119
+ continue;
120
+ const span = Math.max(1, to.depth - from.depth);
121
+ const startT = from.depth * STEP_SECONDS;
122
+ const travelT = STEP_SECONDS * 0.75 * span;
123
+ const startFrac = startT / totalSeconds;
124
+ const endFrac = Math.min(0.98, (startT + travelT) / totalSeconds);
125
+ timingByEdge.set(edge, { startFrac, endFrac });
126
+ arrivalByNode.set(edge.to, Math.max(arrivalByNode.get(edge.to) ?? 0, endFrac));
127
+ }
128
+ return { totalSeconds, timingByEdge, arrivalByNode };
129
+ }
130
+ const CORNER_RADIUS = 8; // 10 * 0.8
131
+ function edgePath(from, to) {
132
+ const x1 = from.x + from.width / 2;
133
+ const y1 = from.y + from.height;
134
+ const x2 = to.x + to.width / 2;
135
+ const y2 = to.y;
136
+ if (Math.abs(x1 - x2) < 1) {
137
+ return { d: `M ${x1} ${y1} L ${x2} ${y2}`, midX: x1, midY: (y1 + y2) / 2 };
138
+ }
139
+ const midY = (y1 + y2) / 2;
140
+ const dir = x2 > x1 ? 1 : -1;
141
+ const r = Math.min(CORNER_RADIUS, Math.abs(x2 - x1) / 2, midY - y1, y2 - midY);
142
+ const d = `M ${x1} ${y1} L ${x1} ${midY - r} ` +
143
+ `Q ${x1} ${midY} ${x1 + dir * r} ${midY} ` +
144
+ `L ${x2 - dir * r} ${midY} ` +
145
+ `Q ${x2} ${midY} ${x2} ${midY + r} ` +
146
+ `L ${x2} ${y2}`;
147
+ return { d, midX: (x1 + x2) / 2, midY };
148
+ }
149
+ /** Renders a FlowSpec (a small acyclic node/edge graph) to a self-contained, animated SVG diagram string for embedding in docs pages. */
150
+ export function renderFlow(spec) {
151
+ const { placed, width, height, maxDepth } = layout(spec);
152
+ const { totalSeconds, timingByEdge, arrivalByNode } = computeTiming(placed, spec, maxDepth);
153
+ const wires = [];
154
+ const dots = [];
155
+ const labels = [];
156
+ for (const edge of spec.edges) {
157
+ const from = placed.get(edge.from);
158
+ const to = placed.get(edge.to);
159
+ if (!from || !to)
160
+ continue;
161
+ const { d, midX, midY } = edgePath(from, to);
162
+ // html-ok: d is built in edgePath() from numeric coordinates only, never user input
163
+ wires.push(`<path class="wire" d="${d}"/>`);
164
+ if (edge.label) {
165
+ labels.push(`<text class="edge-label" x="${midX}" y="${midY - 6}" text-anchor="middle">${escapeHtml(edge.label)}</text>`);
166
+ }
167
+ const timing = timingByEdge.get(edge);
168
+ if (!timing)
169
+ continue;
170
+ const { startFrac, endFrac } = timing;
171
+ const fadeIn = Math.min(startFrac + 0.02, endFrac);
172
+ const fadeOut = Math.min(endFrac + 0.02, 1);
173
+ dots.push(`<circle r="3.2" class="dot">` +
174
+ `<animateMotion dur="${totalSeconds}s" repeatCount="indefinite" calcMode="linear" ` +
175
+ `keyPoints="0;0;1;1" keyTimes="0;${startFrac};${endFrac};1" path="${d}"/>` +
176
+ `<animate attributeName="opacity" dur="${totalSeconds}s" repeatCount="indefinite" ` +
177
+ `values="0;0;1;1;0;0" keyTimes="0;${startFrac};${fadeIn};${endFrac};${fadeOut};1"/>` +
178
+ `</circle>`);
179
+ }
180
+ const cards = spec.nodes.map((node) => {
181
+ const p = placed.get(node.id);
182
+ if (!p)
183
+ return "";
184
+ const arrival = arrivalByNode.get(node.id) ?? 0.02;
185
+ const pulseEnd = Math.min(arrival + 0.05, 1);
186
+ const badgeX = p.x + PAD_X;
187
+ const badgeY = p.y + (p.height - BADGE) / 2;
188
+ const textX = badgeX + BADGE + GAP_BADGE_TEXT;
189
+ const isTerminal = node.kind === "terminal";
190
+ const badgeFill = isTerminal
191
+ ? "var(--flow-card)"
192
+ : node.icon === "check"
193
+ ? "var(--flow-green)"
194
+ : "var(--flow-badge)";
195
+ const badgeClass = isTerminal ? "flow-badge flow-badge-terminal" : "flow-badge";
196
+ const iconGroupClass = isTerminal ? "flow-icon-terminal" : "";
197
+ const iconInset = (BADGE - ICON_SIZE) / 2;
198
+ const iconInner = node.icon === "ai"
199
+ ? `<text class="flow-ai-label" x="${BADGE / 2}" y="${BADGE / 2 + 3}" text-anchor="middle">AI</text>`
200
+ : // html-ok: ICONS is a static internal map keyed by the FlowIcon union, not user input
201
+ `<svg class="${iconGroupClass}" x="${iconInset}" y="${iconInset}" width="${ICON_SIZE}" height="${ICON_SIZE}" viewBox="0 0 24 24">${ICONS[node.icon ?? "box"]}</svg>`;
202
+ return `<g>
203
+ <rect class="flow-card" x="${p.x}" y="${p.y}" width="${p.width}" height="${p.height}" rx="9">
204
+ <animate attributeName="stroke" dur="${totalSeconds}s" repeatCount="indefinite"
205
+ values="var(--flow-card-border);var(--flow-card-border);var(--flow-violet);var(--flow-card-border);var(--flow-card-border)"
206
+ keyTimes="0;${Math.max(0, arrival - 0.02)};${arrival};${pulseEnd};1"/>
207
+ </rect>
208
+ <g transform="translate(${badgeX}, ${badgeY})">
209
+ <rect class="${badgeClass}" width="${BADGE}" height="${BADGE}" rx="6" fill="${badgeFill}"/>
210
+ ${iconInner}
211
+ </g>
212
+ <text class="flow-title" x="${textX}" y="${node.sub ? p.y + p.height / 2 - 2 : p.y + p.height / 2 + 3.5}">${escapeHtml(node.title)}</text>
213
+ ${node.sub ? `<text class="flow-sub" x="${textX}" y="${p.y + p.height / 2 + 11}">${escapeHtml(node.sub)}</text>` : ""}
214
+ </g>`;
215
+ });
216
+ // html-ok: wires/dots/labels/cards hold only fragments built from numeric
217
+ // coordinates or already-escaped text (escapeHtml above), never raw user input
218
+ return `<div class="kumiko-flow">
219
+ <svg width="${width}" height="${height}" viewBox="0 0 ${width} ${height}" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="Flow diagram">
220
+ ${
221
+ // html-ok: see comment above return
222
+ wires.join("\n ")}
223
+ ${
224
+ // html-ok: see comment above return
225
+ dots.join("\n ")}
226
+ ${
227
+ // html-ok: see comment above return
228
+ labels.join("\n ")}
229
+ ${
230
+ // html-ok: see comment above return
231
+ cards.join("\n ")}
232
+ </svg>
233
+ </div>`;
234
+ }
@@ -0,0 +1,18 @@
1
+ export type FlowIcon = "ui" | "api" | "handler" | "event-store" | "database" | "broadcast" | "ai" | "inbox" | "person" | "check" | "stop" | "box";
2
+ export type FlowNodeKind = "process" | "decision" | "terminal";
3
+ export interface FlowNode {
4
+ id: string;
5
+ title: string;
6
+ sub?: string;
7
+ icon?: FlowIcon;
8
+ kind?: FlowNodeKind;
9
+ }
10
+ export interface FlowEdge {
11
+ from: string;
12
+ to: string;
13
+ label?: string;
14
+ }
15
+ export interface FlowSpec {
16
+ nodes: FlowNode[];
17
+ edges: FlowEdge[];
18
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -1,4 +1,4 @@
1
- import { toInstant } from "@cosmicdrift/kumiko-headless";
1
+ import { toInstant } from "./headless/index.js";
2
2
  // Shared timestamp formatter for operator screens (audit log, job runs) —
3
3
  // falls back to the raw ISO string on an unparseable value instead of "Invalid Date".
4
4
  export function formatWhen(value) {
@@ -0,0 +1,3 @@
1
+ export declare const APEX_NAV_MENU_CSS = "\n .nav-toggle { display: none; }\n .nav-toggle__trigger { display: none; align-items: center; justify-content: center;\n width: 2.25rem; height: 2.25rem; border-radius: 0.5rem; cursor: pointer;\n color: var(--fg-muted); list-style: none; }\n .nav-toggle__trigger::-webkit-details-marker { display: none; }\n .nav-toggle__trigger:hover { color: var(--fg); background: var(--bg-muted); }\n .nav-toggle__trigger svg { width: 1.35rem; height: 1.35rem; }\n .apex-dark .nav-toggle__trigger { color: var(--on-dark-muted); }\n .apex-dark .nav-toggle__trigger:hover { color: var(--on-dark); background: rgba(255,255,255,0.08); }\n\n .nav-menu { position: relative; display: inline-flex; }\n .nav-menu__trigger { display: inline-flex; align-items: center; gap: 0.3rem;\n font: inherit; font-size: 0.9375rem; color: var(--fg-muted);\n cursor: pointer; list-style: none; }\n .nav-menu__trigger::-webkit-details-marker { display: none; }\n .nav-menu__trigger:hover { color: var(--fg); }\n .nav-menu__chev { display: inline-flex; transition: transform 0.15s; opacity: 0.7; }\n .nav-menu__chev svg { width: 0.95em; height: 0.95em; }\n .nav-menu[open] .nav-menu__chev { transform: rotate(180deg); }\n .nav-menu__panel { position: absolute; top: calc(100% + 0.5rem); left: 0; z-index: 20;\n min-width: 21rem; padding: 0.5rem; background: var(--bg-card); color: var(--fg);\n border: 1px solid var(--border); border-radius: 0.75rem; box-shadow: var(--shadow);\n flex-direction: column; gap: 0.125rem; }\n .nav-menu[open] .nav-menu__panel { display: flex; }\n .nav-menu__item { display: flex; gap: 0.75rem; align-items: flex-start;\n padding: 0.6rem 0.7rem; border-radius: 0.5rem; color: var(--fg); }\n .nav-menu__item:hover { background: var(--bg-muted); color: var(--fg); }\n .nav-menu__icon { flex: none; display: inline-flex; align-items: center; justify-content: center;\n width: 2rem; height: 2rem; border-radius: 0.5rem;\n background: color-mix(in srgb, var(--primary) 12%, transparent); color: var(--primary); }\n .nav-menu__icon svg { width: 1.1rem; height: 1.1rem; }\n .nav-menu__text { display: flex; flex-direction: column; gap: 0.1rem; }\n .nav-menu__title { font-weight: 600; font-size: 0.9rem; line-height: 1.2; }\n .nav-menu__desc { font-size: 0.8rem; color: var(--fg-muted); line-height: 1.35; }\n .nav-menu__sep { height: 1px; background: var(--border); margin: 0.375rem 0.3rem; }\n .nav-menu__more { display: inline-flex; padding: 0.4rem 0.7rem; font-size: 0.85rem; font-weight: 600; color: var(--primary); }\n .nav-menu__more:hover { color: var(--primary-hover); }\n .apex-dark .nav-menu__trigger { color: var(--on-dark-muted); }\n .apex-dark .nav-menu__trigger:hover { color: var(--on-dark); }\n /* The panel is a light popover; its links must NOT inherit the dark-chrome\n nav-link color (.apex-dark .nav-links a, specificity 0,2,1) or a consumer's\n own .nav-links a. Pin both link types with matching specificity (0,2,1) so\n titles + the footer link stay readable in the dark theme. */\n .nav-menu__panel a.nav-menu__item { color: var(--fg); }\n .nav-menu__panel a.nav-menu__item:hover { color: var(--fg); }\n .nav-menu__panel a.nav-menu__more { color: var(--primary); }\n .nav-menu__panel a.nav-menu__more:hover { color: var(--primary-hover); }\n";
2
+ export declare const APEX_NAV_TOGGLE_RESPONSIVE_CSS = "\n @media (max-width: 640px) {\n .nav { position: relative; }\n .nav .nav-toggle { display: inline-flex; }\n .nav .nav-toggle__trigger { display: inline-flex; }\n .nav-toggle[open] > .nav-links { display: flex; flex-direction: column; align-items: stretch;\n gap: 0.25rem; position: absolute; top: calc(100% + 0.5rem); left: 0; right: 0; z-index: 30;\n background: var(--bg-card); border: 1px solid var(--border); border-radius: 0.75rem;\n box-shadow: var(--shadow); padding: 0.75rem; }\n .nav-toggle[open] > .nav-links > a { color: var(--fg); padding: 0.4rem 0.25rem; }\n .nav-toggle[open] > .nav-links > a:hover { color: var(--fg); }\n .nav-toggle .nav-menu { display: block; }\n .nav-toggle .nav-menu__panel { position: static; min-width: 0;\n margin-top: 0.375rem; box-shadow: none; }\n }\n";
3
+ export declare const APEX_STRUCTURAL_CSS: string;