@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
@@ -0,0 +1,6 @@
1
+ import type { DashboardRefresh } from "@cosmicdrift/kumiko-framework/ui-types";
2
+ /** Polling interval of a dashboard in ms; undefined means no polling. A record
3
+ * field that is missing, not a positive number or not loaded yet disables it
4
+ * until a valid value arrives. The result never drops below
5
+ * DASHBOARD_MIN_REFRESH_SECONDS, whatever the record says. */
6
+ export declare function resolveRefreshIntervalMs(refresh: DashboardRefresh | undefined, record: Readonly<Record<string, unknown>> | null): number | undefined;
@@ -0,0 +1,15 @@
1
+ import { DASHBOARD_MIN_REFRESH_SECONDS } from "@cosmicdrift/kumiko-types/screen";
2
+ // setInterval treats anything above a signed 32-bit int as 0 ms and would fire in a tight loop.
3
+ const MAX_TIMER_MS = 2_147_483_647;
4
+ /** Polling interval of a dashboard in ms; undefined means no polling. A record
5
+ * field that is missing, not a positive number or not loaded yet disables it
6
+ * until a valid value arrives. The result never drops below
7
+ * DASHBOARD_MIN_REFRESH_SECONDS, whatever the record says. */
8
+ export function resolveRefreshIntervalMs(refresh, record) {
9
+ if (refresh === undefined)
10
+ return undefined;
11
+ const seconds = "seconds" in refresh ? refresh.seconds : record?.[refresh.field];
12
+ if (typeof seconds !== "number" || !Number.isFinite(seconds) || seconds <= 0)
13
+ return undefined;
14
+ return Math.min(Math.max(seconds, DASHBOARD_MIN_REFRESH_SECONDS) * 1000, MAX_TIMER_MS);
15
+ }
@@ -0,0 +1,4 @@
1
+ import type { LocaleResolver } from "../../headless/index.ts";
2
+ export declare function DocumentLangSync({ resolver }: {
3
+ readonly resolver: LocaleResolver;
4
+ }): null;
@@ -0,0 +1,27 @@
1
+ // Keeps document.documentElement.lang (+ dataset.kumikoLocale) in sync with
2
+ // the active locale. Screen readers and the browser's built-in translate
3
+ // offer read lang; dispatcher-live reads dataset.kumikoLocale for X-Locale
4
+ // (see dispatcher-live/src/locale.ts) so a static <html lang> cannot spoof
5
+ // the active UI language.
6
+ //
7
+ // Lives here, not in @cosmicdrift/kumiko-renderer: that package is DOM-free
8
+ // by design (Renderer-Boundaries Guard enforces it — web/native both
9
+ // consume it). createApp/createPublicSurface are the two places every web
10
+ // app already goes through, so mounting this here covers every app with
11
+ // zero app-side wiring, same as createBrowserLocaleResolver.
12
+ import { useEffect } from "react";
13
+ function syncDocumentLocale(locale) {
14
+ document.documentElement.lang = locale;
15
+ // Dedicated marker for dispatcher-live — static <html lang> must not
16
+ // look like an active UI locale (kumiko-framework#2334).
17
+ document.documentElement.dataset["kumikoLocale"] = locale;
18
+ }
19
+ export function DocumentLangSync({ resolver }) {
20
+ useEffect(() => {
21
+ syncDocumentLocale(resolver.locale());
22
+ return resolver.subscribe(() => {
23
+ syncDocumentLocale(resolver.locale());
24
+ });
25
+ }, [resolver]);
26
+ return null;
27
+ }
@@ -0,0 +1,11 @@
1
+ import type { DraftStorage } from "../../index.ts";
2
+ export type CreateBrowserDraftStorageOptions = {
3
+ /** sessionStorage-key prefix, one entry per screenId gets appended.
4
+ * Default: `"kumiko:draft-id:"`. */
5
+ readonly storagePrefix?: string;
6
+ };
7
+ /** Default DraftStorage when createKumikoApp boots without one. Guards every
8
+ * sessionStorage call — Safari private mode and storage-disabled browsers
9
+ * throw on access, and a lost draftId just falls back to the `list` resume
10
+ * path (same UX as a genuinely cleared storage), not a broken form. */
11
+ export declare function createBrowserDraftStorage(options?: CreateBrowserDraftStorageOptions): DraftStorage;
@@ -0,0 +1,53 @@
1
+ // Browser-backed DraftStorage default for createKumikoApp (issue #1913).
2
+ //
3
+ // Persists a create-mode draftId per screen in `sessionStorage` — same-tab
4
+ // scope only (deliberately, unlike browser-locale.ts's localStorage): the
5
+ // draft row itself already survives a new tab / cleared storage via
6
+ // RenderEdit's `form-draft:query:list` mount-time fallback, so this is only
7
+ // about not losing the draftId on an accidental same-tab reload.
8
+ function keyFor(prefix, screenId) {
9
+ return `${prefix}${screenId}`;
10
+ }
11
+ /** Default DraftStorage when createKumikoApp boots without one. Guards every
12
+ * sessionStorage call — Safari private mode and storage-disabled browsers
13
+ * throw on access, and a lost draftId just falls back to the `list` resume
14
+ * path (same UX as a genuinely cleared storage), not a broken form. */
15
+ export function createBrowserDraftStorage(options = {}) {
16
+ const prefix = options.storagePrefix ?? "kumiko:draft-id:";
17
+ return {
18
+ getDraftId: (screenId) => {
19
+ if (typeof sessionStorage === "undefined")
20
+ return null;
21
+ try {
22
+ return sessionStorage.getItem(keyFor(prefix, screenId));
23
+ }
24
+ catch {
25
+ return null;
26
+ }
27
+ },
28
+ setDraftId: (screenId, draftId) => {
29
+ // skip: no sessionStorage in this environment (SSR, disabled) — the
30
+ // draftId just stays in-memory-only for this render.
31
+ if (typeof sessionStorage === "undefined")
32
+ return;
33
+ try {
34
+ sessionStorage.setItem(keyFor(prefix, screenId), draftId);
35
+ }
36
+ catch {
37
+ // Persistence failure isn't fatal — the draft stays usable in the
38
+ // current tab, only a reload would lose the draftId.
39
+ }
40
+ },
41
+ clearDraftId: (screenId) => {
42
+ // skip: no sessionStorage in this environment — nothing to clear.
43
+ if (typeof sessionStorage === "undefined")
44
+ return;
45
+ try {
46
+ sessionStorage.removeItem(keyFor(prefix, screenId));
47
+ }
48
+ catch {
49
+ // skip: nothing to clean up if storage is unreachable.
50
+ }
51
+ },
52
+ };
53
+ }
@@ -0,0 +1,13 @@
1
+ import type { TreeChildrenSubscribe } from "@cosmicdrift/kumiko-framework/engine";
2
+ import { type ReactNode } from "react";
3
+ export type NavProvidersProviderProps = {
4
+ readonly value: ReadonlyMap<string, TreeChildrenSubscribe>;
5
+ readonly entities?: ReadonlyMap<string, readonly string[]>;
6
+ readonly children: ReactNode;
7
+ };
8
+ export declare function NavProvidersProvider({ value, entities, children, }: NavProvidersProviderProps): ReactNode;
9
+ /** Provider-Map keyed auf Nav-QN. Empty-Map-Default → kein Crash ohne
10
+ * registrierte Provider. */
11
+ export declare function useNavProviders(): ReadonlyMap<string, TreeChildrenSubscribe>;
12
+ /** SSE-Entity-Liste pro Provider-QN für Live-Refresh. Empty-Map-Default. */
13
+ export declare function useNavEntities(): ReadonlyMap<string, readonly string[]>;
@@ -0,0 +1,18 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ const EMPTY_PROVIDERS = new Map();
4
+ const EMPTY_ENTITIES = new Map();
5
+ const NavProvidersContext = createContext(EMPTY_PROVIDERS);
6
+ const NavEntitiesContext = createContext(EMPTY_ENTITIES);
7
+ export function NavProvidersProvider({ value, entities, children, }) {
8
+ return (_jsx(NavProvidersContext.Provider, { value: value, children: _jsx(NavEntitiesContext.Provider, { value: entities ?? EMPTY_ENTITIES, children: children }) }));
9
+ }
10
+ /** Provider-Map keyed auf Nav-QN. Empty-Map-Default → kein Crash ohne
11
+ * registrierte Provider. */
12
+ export function useNavProviders() {
13
+ return useContext(NavProvidersContext);
14
+ }
15
+ /** SSE-Entity-Liste pro Provider-QN für Live-Refresh. Empty-Map-Default. */
16
+ export function useNavEntities() {
17
+ return useContext(NavEntitiesContext);
18
+ }
@@ -0,0 +1,40 @@
1
+ import { type AnchorHTMLAttributes, type ReactNode } from "react";
2
+ import { type FeatureSchema, type NavApi, type NavTarget } from "../../index.ts";
3
+ /** React-Hook der eine NavApi aus der Browser-History baut. Sollte
4
+ * einmal im App-Root aufgerufen und als value an den shared
5
+ * `<NavProvider>` durchgereicht werden — createKumikoApp tut das.
6
+ *
7
+ * hasWorkspaces aus dem Schema (schema.workspaces non-empty) entscheidet,
8
+ * ob das erste URL-Segment als Workspace-id parsed wird. Pure Pass-
9
+ * through an parsePath; formatPath checkt selbst auf target.workspaceId.
10
+ *
11
+ * basePath mounted die App unter einem URL-Prefix (z.B. "/admin"). Read-
12
+ * Pfad strippt vor parsePath, Write-Pfad prepend'd vor pushState/href.
13
+ * URLs außerhalb des basePath liefern route=undefined, ohne Auto-Redirect.
14
+ *
15
+ * Achtung — Ambiguität bei route=undefined mit basePath:
16
+ * Sowohl die App-Root (URL === basePath, z.B. "/admin") als auch URLs
17
+ * außerhalb des basePath (z.B. "/marketing") liefern route=undefined. Eine
18
+ * App die zwischen "render Default-Screen" und "render Not-Found"
19
+ * unterscheiden muss, muss zusätzlich `window.location.pathname` prüfen:
20
+ *
21
+ * if (window.location.pathname.startsWith("/admin")) {
22
+ * // in-app, aber an der Root → Default-Screen
23
+ * } else {
24
+ * // out-of-app → Not-Found / Marketing-Layer
25
+ * }
26
+ *
27
+ * Im non-basePath-Modus ergibt sich diese Ambiguität nicht — out-of-app
28
+ * ist dort kein Konzept. */
29
+ export declare function useBrowserNavApi(options?: {
30
+ readonly hasWorkspaces?: boolean;
31
+ readonly basePath?: string;
32
+ /** Feature list ObjectTarget resolution needs (resolveTarget). Omit when
33
+ * the caller never passes an ObjectTarget — a ScreenTarget resolves
34
+ * without looking at the feature list at all. */
35
+ readonly features?: readonly FeatureSchema[];
36
+ }): NavApi;
37
+ export type KumikoLinkProps = Omit<AnchorHTMLAttributes<HTMLAnchorElement>, "href"> & {
38
+ readonly to: NavTarget;
39
+ };
40
+ export declare function KumikoLink({ to, onClick, children, ...rest }: KumikoLinkProps): ReactNode;
@@ -0,0 +1,231 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // Browser-Impl der Navigation: HTML5-History + popstate subscribe.
3
+ // Types + Context + useNav leben im shared `@cosmicdrift/kumiko-renderer`; dieser
4
+ // File liefert nur die Web-spezifische NavApi-Instanz und die
5
+ // `<KumikoLink>` Anchor-Komponente.
6
+ //
7
+ // Bewusst KEIN createStore: Source-of-truth ist `window.location.pathname`
8
+ // (extern, kann via replaceState außerhalb unserer Kontrolle wechseln).
9
+ // Ein Store wäre entweder eine zweite Wahrheit (Drift-Risiko) oder ein
10
+ // reiner Tick-Counter (Anti-Pattern — createStore ist State-Holder, kein
11
+ // Event-Bus). Hand-rolled Listener-Set ist hier idiomatisch: zwei
12
+ // Notify-Trigger (eigenes pushPath, popstate-Event), nicht generalisierbar.
13
+ import { useCallback, useMemo, useSyncExternalStore, } from "react";
14
+ import { formatPath, parsePath, resolveTarget, useNav, } from "../../index.js";
15
+ // basePath erlaubt es, die App unter einem URL-Prefix zu mounten
16
+ // (z.B. `/admin`). Read-Pfad strippt den Prefix vor dem parsePath,
17
+ // Write-Pfad prepend'd ihn vor dem pushState/replaceState/href.
18
+ //
19
+ // Wenn die URL nicht im basePath liegt (z.B. /marketing/foo bei
20
+ // basePath="/admin"), liefert stripBasePath `undefined` — useBrowserNavApi
21
+ // gibt dann route=undefined zurück, die App rendert ihren "outside"-State
22
+ // (Not-Found, Marketing-Layer, Server-Routing-Pickup, …). Es gibt KEIN
23
+ // Auto-Redirect zur App-Root — die Host-App entscheidet selbst.
24
+ function normalizeBasePath(raw) {
25
+ if (raw === undefined || raw === "" || raw === "/")
26
+ return "";
27
+ const withLeading = raw.startsWith("/") ? raw : `/${raw}`;
28
+ return withLeading.endsWith("/") ? withLeading.slice(0, -1) : withLeading;
29
+ }
30
+ // Returns the in-app path (basePath-relativ) wenn `path` im basePath liegt,
31
+ // sonst `undefined`. Strict-segment-Boundary: "/administrator" matcht
32
+ // nicht "/admin" — sonst würde der Prefix-Check auf String-Ebene falsche
33
+ // Treffer liefern.
34
+ function stripBasePath(path, basePath) {
35
+ if (basePath === "")
36
+ return path;
37
+ if (path === basePath)
38
+ return "/";
39
+ if (path.startsWith(`${basePath}/`))
40
+ return path.slice(basePath.length);
41
+ return undefined;
42
+ }
43
+ function prependBasePath(path, basePath) {
44
+ if (basePath === "")
45
+ return path;
46
+ // formatPath liefert immer absoluten in-app-Pfad: "/" oder "/screen-id"
47
+ // oder "/screen-id/entity-id". "/" → einfach basePath, sonst concat.
48
+ if (path === "/" || path === "")
49
+ return basePath;
50
+ return `${basePath}${path}`;
51
+ }
52
+ // pushState feuert keinen popstate — wir halten einen eigenen
53
+ // Listener-Set, den navigate() notifiziert. popstate (Back/Forward)
54
+ // läuft über einen window-Listener, den wir einmalig verdrahten.
55
+ const listeners = new Set();
56
+ let popstateWired = false;
57
+ // Stable identity for the omitted-features case — `?? []` would create a
58
+ // fresh array every render, busting the useMemo below on every render for
59
+ // every existing useBrowserNavApi() call site (none of which pass features).
60
+ const NO_FEATURES = [];
61
+ function ensurePopstateWired() {
62
+ if (popstateWired)
63
+ return;
64
+ if (typeof window === "undefined")
65
+ return;
66
+ window.addEventListener("popstate", () => {
67
+ for (const l of listeners)
68
+ l();
69
+ });
70
+ popstateWired = true;
71
+ }
72
+ function subscribe(listener) {
73
+ ensurePopstateWired();
74
+ listeners.add(listener);
75
+ return () => {
76
+ listeners.delete(listener);
77
+ };
78
+ }
79
+ function readPath() {
80
+ return typeof window !== "undefined" ? window.location.pathname : "/";
81
+ }
82
+ // Read der aktuellen ?key=value-Pairs als Plain-Record. URLSearchParams-
83
+ // Iterator gibt String/String — wir kollabieren auf "letzter Wert
84
+ // gewinnt" wenn ein Key mehrfach im Query auftaucht (`?a=1&a=2` → "2").
85
+ // Multi-Value-Lists sind kein Use-Case in Kumiko-Filter-State; explizit
86
+ // dokumentieren statt unspezifizierten Behavior zu liefern.
87
+ function readSearch() {
88
+ return typeof window !== "undefined" ? window.location.search : "";
89
+ }
90
+ function parseSearchParams(search) {
91
+ const out = {};
92
+ if (search === "")
93
+ return out;
94
+ const params = new URLSearchParams(search);
95
+ for (const [k, v] of params.entries())
96
+ out[k] = v;
97
+ return out;
98
+ }
99
+ // Mergt updates in den aktuellen ?-String. `null` löscht, sonst
100
+ // überschreibt. Verwendet replaceState (KEIN push) — Sort/Filter-Toggles
101
+ // flutten sonst die Back-Navigation und User clicked sich durch
102
+ // dutzende Zwischen-States um zur vorherigen Seite zu kommen.
103
+ function applySearchParamUpdates(updates) {
104
+ if (typeof window === "undefined")
105
+ return;
106
+ const params = new URLSearchParams(window.location.search);
107
+ for (const [key, value] of Object.entries(updates)) {
108
+ if (value === null) {
109
+ params.delete(key);
110
+ }
111
+ else {
112
+ params.set(key, value);
113
+ }
114
+ }
115
+ const next = params.toString();
116
+ const nextSearch = next === "" ? "" : `?${next}`;
117
+ if (nextSearch === window.location.search)
118
+ return;
119
+ const url = `${window.location.pathname}${nextSearch}${window.location.hash}`;
120
+ window.history.replaceState(null, "", url);
121
+ for (const l of listeners)
122
+ l();
123
+ }
124
+ // undefined = the caller passed no search params; "" = an explicitly empty query.
125
+ function formatSearch(options) {
126
+ if (options?.searchParams === undefined)
127
+ return undefined;
128
+ const query = new URLSearchParams(options.searchParams).toString();
129
+ return query === "" ? "" : `?${query}`;
130
+ }
131
+ function pushPath(path, search) {
132
+ if (typeof window === "undefined")
133
+ return;
134
+ // Repeated navigate() calls to the same URL must not flood the history.
135
+ // Without explicit search params the current query counts as unchanged.
136
+ const unchanged = window.location.pathname === path &&
137
+ (search === undefined || window.location.search === search);
138
+ if (unchanged)
139
+ return;
140
+ window.history.pushState(null, "", `${path}${search ?? ""}`);
141
+ for (const l of listeners)
142
+ l();
143
+ }
144
+ function replacePath(path, search) {
145
+ if (typeof window === "undefined")
146
+ return;
147
+ // No path-change short-circuit here: callers explicitly chose replace
148
+ // to avoid creating a history entry, even when the URL is identical.
149
+ // (pushPath skips no-op pushes; replacePath honors the call so the
150
+ // entry-stack semantics stay predictable.)
151
+ window.history.replaceState(null, "", `${path}${search ?? ""}`);
152
+ for (const l of listeners)
153
+ l();
154
+ }
155
+ /** React-Hook der eine NavApi aus der Browser-History baut. Sollte
156
+ * einmal im App-Root aufgerufen und als value an den shared
157
+ * `<NavProvider>` durchgereicht werden — createKumikoApp tut das.
158
+ *
159
+ * hasWorkspaces aus dem Schema (schema.workspaces non-empty) entscheidet,
160
+ * ob das erste URL-Segment als Workspace-id parsed wird. Pure Pass-
161
+ * through an parsePath; formatPath checkt selbst auf target.workspaceId.
162
+ *
163
+ * basePath mounted die App unter einem URL-Prefix (z.B. "/admin"). Read-
164
+ * Pfad strippt vor parsePath, Write-Pfad prepend'd vor pushState/href.
165
+ * URLs außerhalb des basePath liefern route=undefined, ohne Auto-Redirect.
166
+ *
167
+ * Achtung — Ambiguität bei route=undefined mit basePath:
168
+ * Sowohl die App-Root (URL === basePath, z.B. "/admin") als auch URLs
169
+ * außerhalb des basePath (z.B. "/marketing") liefern route=undefined. Eine
170
+ * App die zwischen "render Default-Screen" und "render Not-Found"
171
+ * unterscheiden muss, muss zusätzlich `window.location.pathname` prüfen:
172
+ *
173
+ * if (window.location.pathname.startsWith("/admin")) {
174
+ * // in-app, aber an der Root → Default-Screen
175
+ * } else {
176
+ * // out-of-app → Not-Found / Marketing-Layer
177
+ * }
178
+ *
179
+ * Im non-basePath-Modus ergibt sich diese Ambiguität nicht — out-of-app
180
+ * ist dort kein Konzept. */
181
+ export function useBrowserNavApi(options) {
182
+ const path = useSyncExternalStore(subscribe, readPath, () => "/");
183
+ // Search wird über denselben Listener-Set notifiziert (popstate +
184
+ // unsere replaceState-Calls), also reichen wir denselben subscribe
185
+ // durch. Beide Snapshots werden zusammen recomputed — kein Drift
186
+ // zwischen Pfad und Query.
187
+ const search = useSyncExternalStore(subscribe, readSearch, () => "");
188
+ const hasWorkspaces = options?.hasWorkspaces === true;
189
+ const basePath = useMemo(() => normalizeBasePath(options?.basePath), [options?.basePath]);
190
+ const searchParams = useMemo(() => parseSearchParams(search), [search]);
191
+ const inAppPath = useMemo(() => stripBasePath(path, basePath), [path, basePath]);
192
+ const features = options?.features ?? NO_FEATURES;
193
+ return useMemo(() => {
194
+ const route = inAppPath === undefined ? undefined : parsePath(inAppPath, hasWorkspaces);
195
+ // NavTarget-Contract: workspaceId weglassen = aktueller Workspace
196
+ // bleibt. formatPath kennt die aktuelle Route nicht — ohne Injection
197
+ // landet `/screen-id` in parsePath(hasWorkspaces) als workspaceId,
198
+ // WorkspaceShell sieht einen unbekannten Workspace und revertet
199
+ // sofort auf den Default-Screen ("Klick tut nichts"-Prod-Bug).
200
+ const inCurrentWorkspace = (target) => hasWorkspaces && target.workspaceId === undefined && route?.workspaceId !== undefined
201
+ ? { ...target, workspaceId: route.workspaceId }
202
+ : target;
203
+ // resolveTarget runs first so an ObjectTarget never reaches formatPath —
204
+ // everything downstream (workspace-injection, path-building) only ever
205
+ // sees the ScreenTarget shape it already knew about.
206
+ const toPath = (target) => prependBasePath(formatPath(inCurrentWorkspace(resolveTarget(features, target))), basePath);
207
+ return {
208
+ route,
209
+ navigate: (target, navigateOptions) => pushPath(toPath(target), formatSearch(navigateOptions)),
210
+ replace: (target, navigateOptions) => replacePath(toPath(target), formatSearch(navigateOptions)),
211
+ hrefFor: (target, navigateOptions) => `${toPath(target)}${formatSearch(navigateOptions) ?? ""}`,
212
+ searchParams,
213
+ setSearchParams: applySearchParamUpdates,
214
+ };
215
+ }, [inAppPath, hasWorkspaces, basePath, searchParams, features]);
216
+ }
217
+ export function KumikoLink({ to, onClick, children, ...rest }) {
218
+ const nav = useNav();
219
+ const handleClick = useCallback((e) => {
220
+ onClick?.(e);
221
+ if (e.defaultPrevented)
222
+ return;
223
+ // Standard-Browser-Verhalten für Cmd/Ctrl/Shift/Alt + Middle-Click
224
+ // erhalten — nur der plain-left-click landet bei navigate().
225
+ if (e.button !== 0 || e.metaKey || e.ctrlKey || e.shiftKey || e.altKey)
226
+ return;
227
+ e.preventDefault();
228
+ nav.navigate(to);
229
+ }, [nav, to, onClick]);
230
+ return (_jsx("a", { href: nav.hrefFor(to), onClick: handleClick, ...rest, children: children }));
231
+ }
@@ -0,0 +1,3 @@
1
+ import type { ReactNode } from "react";
2
+ import { type ContentEditorProps } from "../../index.ts";
3
+ export declare function PlainContentEditor({ id, value, onChange, variables, readOnly, }: ContentEditorProps): ReactNode;
@@ -0,0 +1,30 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from "react";
3
+ import { TextareaContentEditor, VariableChips } from "../../index.js";
4
+ export function PlainContentEditor({ id, value, onChange, variables, readOnly, }) {
5
+ const [caret, setCaret] = useState(null);
6
+ // biome-ignore lint/correctness/useExhaustiveDependencies: keyed on value only — must fire once per committed insert, not on every caret write
7
+ useEffect(() => {
8
+ if (caret === null)
9
+ return;
10
+ const el = document.getElementById(id);
11
+ if (el instanceof HTMLTextAreaElement) {
12
+ el.focus();
13
+ el.setSelectionRange(caret, caret);
14
+ }
15
+ setCaret(null);
16
+ }, [value]);
17
+ const insertAtCaret = (name) => {
18
+ const el = document.getElementById(id);
19
+ const placeholder = `{{${name}}}`;
20
+ if (!(el instanceof HTMLTextAreaElement)) {
21
+ onChange(value + placeholder);
22
+ return;
23
+ }
24
+ const start = el.selectionStart ?? value.length;
25
+ const end = el.selectionEnd ?? value.length;
26
+ setCaret(start + placeholder.length);
27
+ onChange(value.slice(0, start) + placeholder + value.slice(end));
28
+ };
29
+ return (_jsxs("div", { className: "rounded-md border border-input bg-transparent", children: [_jsx(TextareaContentEditor, { id: id, value: value, onChange: onChange, variables: variables, readOnly: readOnly }), variables.length > 0 && (_jsx("div", { className: "flex flex-wrap gap-1 border-t border-input p-1", children: _jsx(VariableChips, { variables: variables, onInsert: insertAtCaret, disabled: readOnly }) }))] }));
30
+ }
@@ -0,0 +1,10 @@
1
+ /** "5 minutes ago" / "in 30 seconds" in the given locale. The unit grows with the
2
+ * distance (seconds below a minute, minutes below an hour, hours below a day,
3
+ * days beyond); each step is chosen on the already rounded value so 59.6 minutes
4
+ * reads "1 hour" instead of "60 minutes". `numeric: "auto"` yields "now" and "yesterday". */
5
+ export declare function formatRelativeTime(atMs: number, nowMs: number, locale: string): string;
6
+ /** Interval at which a relative text at `distanceMs` from now needs a redraw. */
7
+ export declare function relativeTickIntervalMs(distanceMs: number): number;
8
+ /** Returns a formatter for relative times that redraws its component on a timer, but
9
+ * only while a render actually called it: no relative output on screen, no timer. */
10
+ export declare function useRelativeTimeFormatter(locale: string): (atMs: number) => string;
@@ -0,0 +1,56 @@
1
+ import { useEffect, useRef, useState } from "react";
2
+ import { resolveSafeLocale } from "../primitives/locale-number.js";
3
+ const SECONDS_PER_MINUTE = 60;
4
+ const MINUTES_PER_HOUR = 60;
5
+ const HOURS_PER_DAY = 24;
6
+ /** "5 minutes ago" / "in 30 seconds" in the given locale. The unit grows with the
7
+ * distance (seconds below a minute, minutes below an hour, hours below a day,
8
+ * days beyond); each step is chosen on the already rounded value so 59.6 minutes
9
+ * reads "1 hour" instead of "60 minutes". `numeric: "auto"` yields "now" and "yesterday". */
10
+ export function formatRelativeTime(atMs, nowMs, locale) {
11
+ const formatter = new Intl.RelativeTimeFormat(resolveSafeLocale(locale), { numeric: "auto" });
12
+ const seconds = Math.round((atMs - nowMs) / 1000);
13
+ if (Math.abs(seconds) < SECONDS_PER_MINUTE)
14
+ return formatter.format(seconds, "second");
15
+ const minutes = Math.round(seconds / SECONDS_PER_MINUTE);
16
+ if (Math.abs(minutes) < MINUTES_PER_HOUR)
17
+ return formatter.format(minutes, "minute");
18
+ const hours = Math.round(minutes / MINUTES_PER_HOUR);
19
+ if (Math.abs(hours) < HOURS_PER_DAY)
20
+ return formatter.format(hours, "hour");
21
+ return formatter.format(Math.round(hours / HOURS_PER_DAY), "day");
22
+ }
23
+ const SECOND_TICK_MS = 1000;
24
+ // Above a minute the text changes at most once per minute; half a minute keeps it
25
+ // at most 30 s late without waking the page every second for a "5 minutes ago".
26
+ const COARSE_TICK_MS = 30_000;
27
+ const SECOND_RESOLUTION_BELOW_MS = SECONDS_PER_MINUTE * 1000;
28
+ /** Interval at which a relative text at `distanceMs` from now needs a redraw. */
29
+ export function relativeTickIntervalMs(distanceMs) {
30
+ return distanceMs < SECOND_RESOLUTION_BELOW_MS ? SECOND_TICK_MS : COARSE_TICK_MS;
31
+ }
32
+ /** Returns a formatter for relative times that redraws its component on a timer, but
33
+ * only while a render actually called it: no relative output on screen, no timer. */
34
+ export function useRelativeTimeFormatter(locale) {
35
+ const [, setTick] = useState(0);
36
+ const [intervalMs, setIntervalMs] = useState(null);
37
+ const nearestDistanceMs = useRef(Number.POSITIVE_INFINITY);
38
+ nearestDistanceMs.current = Number.POSITIVE_INFINITY;
39
+ // After every render: the formatter calls of this render decide whether and how fast to tick.
40
+ useEffect(() => {
41
+ const distance = nearestDistanceMs.current;
42
+ setIntervalMs(distance === Number.POSITIVE_INFINITY ? null : relativeTickIntervalMs(distance));
43
+ });
44
+ useEffect(() => {
45
+ // skip: no relative output rendered, nothing to keep current
46
+ if (intervalMs === null)
47
+ return;
48
+ const timer = setInterval(() => setTick((tick) => tick + 1), intervalMs);
49
+ return () => clearInterval(timer);
50
+ }, [intervalMs]);
51
+ return (atMs) => {
52
+ const nowMs = Date.now();
53
+ nearestDistanceMs.current = Math.min(nearestDistanceMs.current, Math.abs(atMs - nowMs));
54
+ return formatRelativeTime(atMs, nowMs, locale);
55
+ };
56
+ }
@@ -0,0 +1,12 @@
1
+ import type { TargetRef } from "@cosmicdrift/kumiko-framework/engine";
2
+ import type { ComponentType, ReactNode } from "react";
3
+ export type ResolverComponent = ComponentType<{
4
+ readonly target: TargetRef;
5
+ readonly onClose: () => void;
6
+ }>;
7
+ export type ResolversProviderProps = {
8
+ readonly resolvers: ReadonlyMap<string, ResolverComponent>;
9
+ readonly children: ReactNode;
10
+ };
11
+ export declare function ResolversProvider({ resolvers, children }: ResolversProviderProps): ReactNode;
12
+ export declare function useResolvers(): ReadonlyMap<string, ResolverComponent>;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext } from "react";
3
+ const ResolversContext = createContext(null);
4
+ export function ResolversProvider({ resolvers, children }) {
5
+ return _jsx(ResolversContext.Provider, { value: resolvers, children: children });
6
+ }
7
+ export function useResolvers() {
8
+ const ctx = useContext(ResolversContext);
9
+ return ctx ?? new Map();
10
+ }
@@ -0,0 +1,3 @@
1
+ import { type ReactNode } from "react";
2
+ import { type ContentEditorProps } from "../../index.ts";
3
+ export declare function RichContentEditor(props: ContentEditorProps): ReactNode;
@@ -0,0 +1,15 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ // @runtime client
3
+ //
4
+ // "rich" contentFormat editor: WYSIWYG on tiptap. Public contract is the
5
+ // same four props every ContentEditorComponent gets — no tiptap type
6
+ // crosses this boundary. tiptap itself is dynamic-imported (TiptapEditor
7
+ // lives in ./tiptap-editor) so an app that never mounts a "rich" collection
8
+ // never pays for it; the fallback while the chunk loads is the same plain
9
+ // textarea #1794 uses for a missing editor, never a blank panel.
10
+ import { lazy, Suspense } from "react";
11
+ import { TextareaContentEditor } from "../../index.js";
12
+ const TiptapEditor = lazy(() => import("./tiptap-editor.js"));
13
+ export function RichContentEditor(props) {
14
+ return (_jsx(Suspense, { fallback: _jsx(TextareaContentEditor, { ...props }), children: _jsx(TiptapEditor, { ...props }) }));
15
+ }
@@ -0,0 +1,2 @@
1
+ import type { ReactNode } from "react";
2
+ export declare function RootErrorFallback(): ReactNode;
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ROOT_ERROR_FALLBACK_TEST_ID } from "@cosmicdrift/kumiko-types/error-boundary";
3
+ // Renders outside every provider, so no i18n/theme/primitives: plain DOM + inline text.
4
+ const ROOT_ERROR_TEXTS = {
5
+ de: { title: "Etwas ist schiefgelaufen.", reload: "Seite neu laden" },
6
+ en: { title: "Something went wrong.", reload: "Reload page" },
7
+ es: { title: "Algo salió mal.", reload: "Recargar la página" },
8
+ };
9
+ function rootErrorTexts() {
10
+ const language = typeof navigator === "undefined" ? "en" : navigator.language;
11
+ const lower = language.toLowerCase();
12
+ if (lower.startsWith("de"))
13
+ return ROOT_ERROR_TEXTS.de;
14
+ if (lower.startsWith("es"))
15
+ return ROOT_ERROR_TEXTS.es;
16
+ return ROOT_ERROR_TEXTS.en;
17
+ }
18
+ export function RootErrorFallback() {
19
+ const texts = rootErrorTexts();
20
+ return (_jsxs("div", { role: "alert", "data-testid": ROOT_ERROR_FALLBACK_TEST_ID, children: [_jsx("p", { children: texts.title }), _jsx("button", { type: "button", onClick: () => window.location.reload(), children: texts.reload })] }));
21
+ }
@@ -0,0 +1,6 @@
1
+ import type { ReactNode } from "react";
2
+ export declare function ScreenErrorFallback({ screen, error, onReset, }: {
3
+ readonly screen: string;
4
+ readonly error: Error;
5
+ readonly onReset: () => void;
6
+ }): ReactNode;
@@ -0,0 +1,17 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { SCREEN_ERROR_FALLBACK_TEST_ID } from "@cosmicdrift/kumiko-types/error-boundary";
3
+ import { usePrimitives, useTranslation } from "../../index.js";
4
+ // Opt-in: a bundle that leaves NODE_ENV unset must not leak error messages to end users.
5
+ function showsErrorDetails() {
6
+ if (typeof process === "undefined")
7
+ return false;
8
+ const nodeEnv = process.env.NODE_ENV;
9
+ return nodeEnv !== undefined && nodeEnv !== "" && nodeEnv !== "production";
10
+ }
11
+ export function ScreenErrorFallback({ screen, error, onReset, }) {
12
+ const { Banner, Button } = usePrimitives();
13
+ const t = useTranslation();
14
+ return (_jsx(Banner, { variant: "error", padded: true, testId: SCREEN_ERROR_FALLBACK_TEST_ID, title: t("kumiko.screen-error.title"), actions: _jsx(Button, { variant: "secondary", onClick: onReset, testId: `${SCREEN_ERROR_FALLBACK_TEST_ID}-reset`, children: t("kumiko.actions.reload") }), children: showsErrorDetails()
15
+ ? t("kumiko.screen-error.detail", { screen, message: error.message })
16
+ : t("kumiko.screen-error.screen", { screen }) }));
17
+ }
@@ -0,0 +1,3 @@
1
+ import { type ReactNode } from "react";
2
+ import { type ContentEditorProps } from "../../index.ts";
3
+ export default function TiptapEditor({ id, value, onChange, variables, readOnly, }: ContentEditorProps): ReactNode;