@cosmicdrift/kumiko-renderer 0.374.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 (455) 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 +7 -6
  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/grid-cell-for-field.d.ts +1 -1
  30. package/dist/components/multi-select-checkboxes.d.ts +1 -1
  31. package/dist/components/multi-select-checkboxes.js +1 -1
  32. package/dist/components/query-options-select.d.ts +1 -1
  33. package/dist/components/related-list-section.d.ts +1 -1
  34. package/dist/components/render-edit-logic.d.ts +1 -1
  35. package/dist/components/render-edit-types.d.ts +2 -2
  36. package/dist/components/render-edit.d.ts +1 -1
  37. package/dist/components/render-edit.js +4 -2
  38. package/dist/components/render-field.d.ts +1 -1
  39. package/dist/components/render-field.js +4 -1
  40. package/dist/components/render-list.d.ts +1 -1
  41. package/dist/components/render-list.js +20 -4
  42. package/dist/components/write-form-section.d.ts +1 -1
  43. package/dist/components/write-form-section.js +1 -1
  44. package/dist/context/dispatcher-context.d.ts +1 -1
  45. package/dist/format-when.js +1 -1
  46. package/dist/headless/apex/css.d.ts +3 -0
  47. package/dist/headless/apex/css.js +298 -0
  48. package/dist/headless/apex/index.d.ts +236 -0
  49. package/dist/headless/apex/index.js +377 -0
  50. package/dist/headless/apex/lightbox.d.ts +4 -0
  51. package/dist/headless/apex/lightbox.js +81 -0
  52. package/dist/headless/contracts/asset.d.ts +15 -0
  53. package/dist/headless/contracts/asset.js +17 -0
  54. package/dist/headless/contracts/index.d.ts +3 -0
  55. package/dist/headless/contracts/index.js +1 -0
  56. package/dist/headless/contracts/locale.d.ts +7 -0
  57. package/dist/headless/contracts/locale.js +11 -0
  58. package/dist/headless/contracts/primitives.d.ts +93 -0
  59. package/dist/headless/contracts/primitives.js +21 -0
  60. package/dist/headless/dispatcher/index.d.ts +2 -0
  61. package/dist/headless/dispatcher/index.js +1 -0
  62. package/dist/headless/dispatcher/types.d.ts +86 -0
  63. package/dist/headless/dispatcher/types.js +34 -0
  64. package/dist/headless/form/form-controller.d.ts +2 -0
  65. package/dist/headless/form/form-controller.js +409 -0
  66. package/dist/headless/form/index.d.ts +3 -0
  67. package/dist/headless/form/index.js +2 -0
  68. package/dist/headless/form/types.d.ts +76 -0
  69. package/dist/headless/form/types.js +1 -0
  70. package/dist/headless/form/zod-bridge.d.ts +10 -0
  71. package/dist/headless/form/zod-bridge.js +103 -0
  72. package/dist/headless/format/document-values.d.ts +12 -0
  73. package/dist/headless/format/document-values.js +70 -0
  74. package/dist/headless/format/escape.d.ts +5 -0
  75. package/dist/headless/format/escape.js +75 -0
  76. package/dist/headless/format/html-template.d.ts +9 -0
  77. package/dist/headless/format/html-template.js +39 -0
  78. package/dist/headless/format/index.d.ts +12 -0
  79. package/dist/headless/format/index.js +237 -0
  80. package/dist/headless/format/money.d.ts +3 -0
  81. package/dist/headless/format/money.js +39 -0
  82. package/dist/headless/index.d.ts +14 -0
  83. package/dist/headless/index.js +9 -0
  84. package/dist/headless/locale-routing/index.d.ts +41 -0
  85. package/dist/headless/locale-routing/index.js +145 -0
  86. package/dist/headless/nav/index.d.ts +2 -0
  87. package/dist/headless/nav/index.js +1 -0
  88. package/dist/headless/nav/resolve.d.ts +2 -0
  89. package/dist/headless/nav/resolve.js +71 -0
  90. package/dist/headless/nav/types.d.ts +26 -0
  91. package/dist/headless/nav/types.js +1 -0
  92. package/dist/headless/store/create-store.d.ts +2 -0
  93. package/dist/headless/store/create-store.js +43 -0
  94. package/dist/headless/store/equality.d.ts +1 -0
  95. package/dist/headless/store/equality.js +34 -0
  96. package/dist/headless/store/index.d.ts +3 -0
  97. package/dist/headless/store/index.js +2 -0
  98. package/dist/headless/store/types.d.ts +7 -0
  99. package/dist/headless/store/types.js +10 -0
  100. package/dist/headless/view-model/edit.d.ts +18 -0
  101. package/dist/headless/view-model/edit.js +501 -0
  102. package/dist/headless/view-model/embedded-list.d.ts +27 -0
  103. package/dist/headless/view-model/embedded-list.js +63 -0
  104. package/dist/headless/view-model/index.d.ts +7 -0
  105. package/dist/headless/view-model/index.js +3 -0
  106. package/dist/headless/view-model/list-file-display.d.ts +3 -0
  107. package/dist/headless/view-model/list-file-display.js +27 -0
  108. package/dist/headless/view-model/list.d.ts +16 -0
  109. package/dist/headless/view-model/list.js +229 -0
  110. package/dist/headless/view-model/types.d.ts +382 -0
  111. package/dist/headless/view-model/types.js +1 -0
  112. package/dist/hooks/use-ai-text.d.ts +1 -1
  113. package/dist/hooks/use-form.d.ts +1 -1
  114. package/dist/hooks/use-form.js +1 -1
  115. package/dist/hooks/use-mutation.d.ts +1 -1
  116. package/dist/hooks/use-query.d.ts +1 -1
  117. package/dist/hooks/use-store.d.ts +1 -1
  118. package/dist/hooks/use-store.js +7 -7
  119. package/dist/hooks/use-stream-handler.d.ts +1 -1
  120. package/dist/i18n.d.ts +1 -1
  121. package/dist/i18n.js +1 -1
  122. package/dist/index.js +4 -4
  123. package/dist/live/csrf.d.ts +2 -0
  124. package/dist/live/csrf.js +60 -0
  125. package/dist/live/dispatcher-live.d.ts +7 -0
  126. package/dist/live/dispatcher-live.js +286 -0
  127. package/dist/live/envelopes.d.ts +101 -0
  128. package/dist/live/envelopes.js +35 -0
  129. package/dist/live/error-mapping.d.ts +16 -0
  130. package/dist/live/error-mapping.js +82 -0
  131. package/dist/live/index.d.ts +7 -0
  132. package/dist/live/index.js +5 -0
  133. package/dist/live/locale.d.ts +2 -0
  134. package/dist/live/locale.js +25 -0
  135. package/dist/live/sse-stream.d.ts +14 -0
  136. package/dist/live/sse-stream.js +128 -0
  137. package/dist/primitives.d.ts +35 -36
  138. package/dist/primitives.js +1 -1
  139. package/dist/session/session-ended.d.ts +1 -1
  140. package/dist/tokens.d.ts +3 -4
  141. package/dist/tokens.js +4 -5
  142. package/dist/web/app/app-schema-boot.d.ts +19 -0
  143. package/dist/web/app/app-schema-boot.js +124 -0
  144. package/dist/web/app/browser-locale.d.ts +22 -0
  145. package/dist/web/app/browser-locale.js +78 -0
  146. package/dist/web/app/client-plugin.d.ts +106 -0
  147. package/dist/web/app/client-plugin.js +12 -0
  148. package/dist/web/app/create-app.d.ts +104 -0
  149. package/dist/web/app/create-app.js +498 -0
  150. package/dist/web/app/create-public-surface.d.ts +36 -0
  151. package/dist/web/app/create-public-surface.js +40 -0
  152. package/dist/web/app/dashboard-body.d.ts +3 -0
  153. package/dist/web/app/dashboard-body.js +865 -0
  154. package/dist/web/app/dashboard-refresh.d.ts +6 -0
  155. package/dist/web/app/dashboard-refresh.js +15 -0
  156. package/dist/web/app/document-lang-sync.d.ts +4 -0
  157. package/dist/web/app/document-lang-sync.js +27 -0
  158. package/dist/web/app/draft-storage.d.ts +11 -0
  159. package/dist/web/app/draft-storage.js +53 -0
  160. package/dist/web/app/nav-providers-context.d.ts +13 -0
  161. package/dist/web/app/nav-providers-context.js +18 -0
  162. package/dist/web/app/nav.d.ts +40 -0
  163. package/dist/web/app/nav.js +231 -0
  164. package/dist/web/app/plain-content-editor.d.ts +3 -0
  165. package/dist/web/app/plain-content-editor.js +30 -0
  166. package/dist/web/app/relative-time.d.ts +10 -0
  167. package/dist/web/app/relative-time.js +56 -0
  168. package/dist/web/app/resolvers-context.d.ts +12 -0
  169. package/dist/web/app/resolvers-context.js +10 -0
  170. package/dist/web/app/rich-content-editor.d.ts +3 -0
  171. package/dist/web/app/rich-content-editor.js +15 -0
  172. package/dist/web/app/root-error-fallback.d.ts +2 -0
  173. package/dist/web/app/root-error-fallback.js +21 -0
  174. package/dist/web/app/screen-error-fallback.d.ts +6 -0
  175. package/dist/web/app/screen-error-fallback.js +17 -0
  176. package/dist/web/app/tiptap-editor.d.ts +3 -0
  177. package/dist/web/app/tiptap-editor.js +120 -0
  178. package/dist/web/app/toast-action-notifier.d.ts +5 -0
  179. package/dist/web/app/toast-action-notifier.js +17 -0
  180. package/dist/web/components/config-cascade.d.ts +13 -0
  181. package/dist/web/components/config-cascade.js +155 -0
  182. package/dist/web/components/config-source-badge.d.ts +6 -0
  183. package/dist/web/components/config-source-badge.js +55 -0
  184. package/dist/web/default-color-scheme.d.ts +2 -0
  185. package/dist/web/default-color-scheme.js +3 -0
  186. package/dist/web/icons.d.ts +94 -0
  187. package/dist/web/icons.js +100 -0
  188. package/dist/web/index.d.ts +78 -0
  189. package/dist/web/index.js +53 -0
  190. package/dist/web/layout/app-layout.d.ts +21 -0
  191. package/dist/web/layout/app-layout.js +8 -0
  192. package/dist/web/layout/avatar.d.ts +12 -0
  193. package/dist/web/layout/avatar.js +63 -0
  194. package/dist/web/layout/default-app-shell.d.ts +41 -0
  195. package/dist/web/layout/default-app-shell.js +16 -0
  196. package/dist/web/layout/editor-panel.d.ts +10 -0
  197. package/dist/web/layout/editor-panel.js +29 -0
  198. package/dist/web/layout/fill-classes.d.ts +9 -0
  199. package/dist/web/layout/fill-classes.js +15 -0
  200. package/dist/web/layout/filter-app-schema-navs.d.ts +7 -0
  201. package/dist/web/layout/filter-app-schema-navs.js +68 -0
  202. package/dist/web/layout/header-action-group.d.ts +6 -0
  203. package/dist/web/layout/header-action-group.js +8 -0
  204. package/dist/web/layout/header-overflow-menu.d.ts +4 -0
  205. package/dist/web/layout/header-overflow-menu.js +8 -0
  206. package/dist/web/layout/language-menu-items.d.ts +8 -0
  207. package/dist/web/layout/language-menu-items.js +16 -0
  208. package/dist/web/layout/language-switcher.d.ts +25 -0
  209. package/dist/web/layout/language-switcher.js +46 -0
  210. package/dist/web/layout/nav-tree.d.ts +19 -0
  211. package/dist/web/layout/nav-tree.js +536 -0
  212. package/dist/web/layout/page-header-slot.d.ts +25 -0
  213. package/dist/web/layout/page-header-slot.js +50 -0
  214. package/dist/web/layout/profile-menu.d.ts +13 -0
  215. package/dist/web/layout/profile-menu.js +6 -0
  216. package/dist/web/layout/shell-breadcrumb.d.ts +11 -0
  217. package/dist/web/layout/shell-breadcrumb.js +34 -0
  218. package/dist/web/layout/shell-header.d.ts +12 -0
  219. package/dist/web/layout/shell-header.js +159 -0
  220. package/dist/web/layout/sidebar-brand.d.ts +15 -0
  221. package/dist/web/layout/sidebar-brand.js +9 -0
  222. package/dist/web/layout/sidebar-panel.d.ts +41 -0
  223. package/dist/web/layout/sidebar-panel.js +107 -0
  224. package/dist/web/layout/sidebar-user.d.ts +8 -0
  225. package/dist/web/layout/sidebar-user.js +17 -0
  226. package/dist/web/layout/sidebar.d.ts +17 -0
  227. package/dist/web/layout/sidebar.js +11 -0
  228. package/dist/web/layout/target-resolver-stub.d.ts +13 -0
  229. package/dist/web/layout/target-resolver-stub.js +61 -0
  230. package/dist/web/layout/target-url.d.ts +12 -0
  231. package/dist/web/layout/target-url.js +77 -0
  232. package/dist/web/layout/theme-label.d.ts +15 -0
  233. package/dist/web/layout/theme-label.js +35 -0
  234. package/dist/web/layout/theme-menu-item.d.ts +12 -0
  235. package/dist/web/layout/theme-menu-item.js +16 -0
  236. package/dist/web/layout/theme-toggle.d.ts +17 -0
  237. package/dist/web/layout/theme-toggle.js +22 -0
  238. package/dist/web/layout/topbar.d.ts +8 -0
  239. package/dist/web/layout/topbar.js +4 -0
  240. package/dist/web/layout/workspace-shell.d.ts +63 -0
  241. package/dist/web/layout/workspace-shell.js +220 -0
  242. package/dist/web/layout/workspace-switcher.d.ts +15 -0
  243. package/dist/web/layout/workspace-switcher.js +36 -0
  244. package/dist/web/lib/accept-attr.d.ts +1 -0
  245. package/dist/web/lib/accept-attr.js +6 -0
  246. package/dist/web/lib/clamp.d.ts +1 -0
  247. package/dist/web/lib/clamp.js +3 -0
  248. package/dist/web/lib/cn.d.ts +6 -0
  249. package/dist/web/lib/cn.js +9 -0
  250. package/dist/web/lib/download.d.ts +2 -0
  251. package/dist/web/lib/download.js +24 -0
  252. package/dist/web/lib/file-ref-download.d.ts +15 -0
  253. package/dist/web/lib/file-ref-download.js +62 -0
  254. package/dist/web/lib/file-upload-form-data.d.ts +7 -0
  255. package/dist/web/lib/file-upload-form-data.js +11 -0
  256. package/dist/web/lib/resize-image.d.ts +1 -0
  257. package/dist/web/lib/resize-image.js +66 -0
  258. package/dist/web/lib/upload-file-ref.d.ts +9 -0
  259. package/dist/web/lib/upload-file-ref.js +29 -0
  260. package/dist/web/primitives/action-menu.d.ts +34 -0
  261. package/dist/web/primitives/action-menu.js +30 -0
  262. package/dist/web/primitives/calendar-popover.d.ts +13 -0
  263. package/dist/web/primitives/calendar-popover.js +76 -0
  264. package/dist/web/primitives/combobox.d.ts +56 -0
  265. package/dist/web/primitives/combobox.js +127 -0
  266. package/dist/web/primitives/date-field.d.ts +18 -0
  267. package/dist/web/primitives/date-field.js +74 -0
  268. package/dist/web/primitives/date-input.d.ts +1 -0
  269. package/dist/web/primitives/date-input.js +5 -0
  270. package/dist/web/primitives/date-parse.d.ts +11 -0
  271. package/dist/web/primitives/date-parse.js +159 -0
  272. package/dist/web/primitives/dialog.d.ts +3 -0
  273. package/dist/web/primitives/dialog.js +42 -0
  274. package/dist/web/primitives/drawer.d.ts +3 -0
  275. package/dist/web/primitives/drawer.js +17 -0
  276. package/dist/web/primitives/dropdown-menu.d.ts +15 -0
  277. package/dist/web/primitives/dropdown-menu.js +56 -0
  278. package/dist/web/primitives/embedded-list-input.d.ts +9 -0
  279. package/dist/web/primitives/embedded-list-input.js +382 -0
  280. package/dist/web/primitives/file-thumbnail.d.ts +25 -0
  281. package/dist/web/primitives/file-thumbnail.js +90 -0
  282. package/dist/web/primitives/file-upload.d.ts +21 -0
  283. package/dist/web/primitives/file-upload.js +56 -0
  284. package/dist/web/primitives/index.d.ts +34 -0
  285. package/dist/web/primitives/index.js +2021 -0
  286. package/dist/web/primitives/json-view.d.ts +7 -0
  287. package/dist/web/primitives/json-view.js +84 -0
  288. package/dist/web/primitives/layout.d.ts +27 -0
  289. package/dist/web/primitives/layout.js +30 -0
  290. package/dist/web/primitives/lightbox.d.ts +3 -0
  291. package/dist/web/primitives/lightbox.js +36 -0
  292. package/dist/web/primitives/locale-number.d.ts +2 -0
  293. package/dist/web/primitives/locale-number.js +54 -0
  294. package/dist/web/primitives/located-timestamp-input.d.ts +22 -0
  295. package/dist/web/primitives/located-timestamp-input.js +22 -0
  296. package/dist/web/primitives/metric.d.ts +5 -0
  297. package/dist/web/primitives/metric.js +18 -0
  298. package/dist/web/primitives/modal-shell.d.ts +17 -0
  299. package/dist/web/primitives/modal-shell.js +9 -0
  300. package/dist/web/primitives/modal.d.ts +3 -0
  301. package/dist/web/primitives/modal.js +13 -0
  302. package/dist/web/primitives/money-input.d.ts +18 -0
  303. package/dist/web/primitives/money-input.js +122 -0
  304. package/dist/web/primitives/narrow-pinned-footer.d.ts +12 -0
  305. package/dist/web/primitives/narrow-pinned-footer.js +153 -0
  306. package/dist/web/primitives/number-input.d.ts +18 -0
  307. package/dist/web/primitives/number-input.js +53 -0
  308. package/dist/web/primitives/option-groups.d.ts +11 -0
  309. package/dist/web/primitives/option-groups.js +27 -0
  310. package/dist/web/primitives/page-header.d.ts +3 -0
  311. package/dist/web/primitives/page-header.js +52 -0
  312. package/dist/web/primitives/promo-panel.d.ts +3 -0
  313. package/dist/web/primitives/promo-panel.js +11 -0
  314. package/dist/web/primitives/segmented-select.d.ts +21 -0
  315. package/dist/web/primitives/segmented-select.js +62 -0
  316. package/dist/web/primitives/share-actions.d.ts +4 -0
  317. package/dist/web/primitives/share-actions.js +56 -0
  318. package/dist/web/primitives/status-badge.d.ts +3 -0
  319. package/dist/web/primitives/status-badge.js +5 -0
  320. package/dist/web/primitives/sticky-action-bar.d.ts +5 -0
  321. package/dist/web/primitives/sticky-action-bar.js +15 -0
  322. package/dist/web/primitives/tabs.d.ts +3 -0
  323. package/dist/web/primitives/tabs.js +107 -0
  324. package/dist/web/primitives/timestamp-input.d.ts +27 -0
  325. package/dist/web/primitives/timestamp-input.js +87 -0
  326. package/dist/web/primitives/toast.d.ts +19 -0
  327. package/dist/web/primitives/toast.js +63 -0
  328. package/dist/web/primitives/tz-input.d.ts +11 -0
  329. package/dist/web/primitives/tz-input.js +8 -0
  330. package/dist/web/primitives/tz-options.d.ts +4 -0
  331. package/dist/web/primitives/tz-options.js +17 -0
  332. package/dist/web/primitives/use-keyboard-inset.d.ts +1 -0
  333. package/dist/web/primitives/use-keyboard-inset.js +28 -0
  334. package/dist/web/primitives/use-narrow-viewport.d.ts +4 -0
  335. package/dist/web/primitives/use-narrow-viewport.js +46 -0
  336. package/dist/web/react-css-custom-properties.d.ts +6 -0
  337. package/dist/web/react-css-custom-properties.js +1 -0
  338. package/dist/web/sse/live-events.d.ts +15 -0
  339. package/dist/web/sse/live-events.js +148 -0
  340. package/dist/web/theme-plugin.d.ts +41 -0
  341. package/dist/web/theme-plugin.js +123 -0
  342. package/dist/web/tokens.d.ts +24 -0
  343. package/dist/web/tokens.js +203 -0
  344. package/dist/web/ui/avatar.d.ts +11 -0
  345. package/dist/web/ui/avatar.js +25 -0
  346. package/dist/web/ui/badge.d.ts +9 -0
  347. package/dist/web/ui/badge.js +26 -0
  348. package/dist/web/ui/breadcrumb.d.ts +11 -0
  349. package/dist/web/ui/breadcrumb.js +29 -0
  350. package/dist/web/ui/button.d.ts +10 -0
  351. package/dist/web/ui/button.js +37 -0
  352. package/dist/web/ui/checkbox.d.ts +4 -0
  353. package/dist/web/ui/checkbox.js +11 -0
  354. package/dist/web/ui/input.d.ts +3 -0
  355. package/dist/web/ui/input.js +8 -0
  356. package/dist/web/ui/label.d.ts +4 -0
  357. package/dist/web/ui/label.js +10 -0
  358. package/dist/web/ui/resizable.d.ts +7 -0
  359. package/dist/web/ui/resizable.js +16 -0
  360. package/dist/web/ui/separator.d.ts +4 -0
  361. package/dist/web/ui/separator.js +10 -0
  362. package/dist/web/ui/sheet.d.ts +14 -0
  363. package/dist/web/ui/sheet.js +42 -0
  364. package/dist/web/ui/sidebar.d.ts +73 -0
  365. package/dist/web/ui/sidebar.js +211 -0
  366. package/dist/web/ui/skeleton.d.ts +2 -0
  367. package/dist/web/ui/skeleton.js +7 -0
  368. package/dist/web/ui/switch.d.ts +6 -0
  369. package/dist/web/ui/switch.js +10 -0
  370. package/dist/web/ui/table.d.ts +10 -0
  371. package/dist/web/ui/table.js +30 -0
  372. package/dist/web/ui/tabs.d.ts +11 -0
  373. package/dist/web/ui/tabs.js +31 -0
  374. package/dist/web/ui/textarea.d.ts +3 -0
  375. package/dist/web/ui/textarea.js +8 -0
  376. package/dist/web/ui/tooltip.d.ts +7 -0
  377. package/dist/web/ui/tooltip.js +19 -0
  378. package/dist/web/ui/use-mobile.d.ts +1 -0
  379. package/dist/web/ui/use-mobile.js +16 -0
  380. package/dist/web/version/update-checker.d.ts +9 -0
  381. package/dist/web/version/update-checker.js +88 -0
  382. package/dist/web/widgets/ai-text-field.d.ts +36 -0
  383. package/dist/web/widgets/ai-text-field.js +137 -0
  384. package/dist/web/widgets/chart-window.d.ts +58 -0
  385. package/dist/web/widgets/chart-window.js +190 -0
  386. package/dist/web/widgets/charts.d.ts +208 -0
  387. package/dist/web/widgets/charts.js +685 -0
  388. package/dist/web/widgets/collapsible-section.d.ts +10 -0
  389. package/dist/web/widgets/collapsible-section.js +17 -0
  390. package/dist/web/widgets/dashboard-list.d.ts +21 -0
  391. package/dist/web/widgets/dashboard-list.js +45 -0
  392. package/dist/web/widgets/detail-list.d.ts +15 -0
  393. package/dist/web/widgets/detail-list.js +8 -0
  394. package/dist/web/widgets/drawer.d.ts +65 -0
  395. package/dist/web/widgets/drawer.js +142 -0
  396. package/dist/web/widgets/feed-list.d.ts +13 -0
  397. package/dist/web/widgets/feed-list.js +9 -0
  398. package/dist/web/widgets/floating-panel.d.ts +30 -0
  399. package/dist/web/widgets/floating-panel.js +242 -0
  400. package/dist/web/widgets/form-fields.d.ts +93 -0
  401. package/dist/web/widgets/form-fields.js +50 -0
  402. package/dist/web/widgets/index.d.ts +27 -0
  403. package/dist/web/widgets/index.js +30 -0
  404. package/dist/web/widgets/infinity-list.d.ts +46 -0
  405. package/dist/web/widgets/infinity-list.js +211 -0
  406. package/dist/web/widgets/mode-switch.d.ts +21 -0
  407. package/dist/web/widgets/mode-switch.js +25 -0
  408. package/dist/web/widgets/photo-slots.d.ts +29 -0
  409. package/dist/web/widgets/photo-slots.js +52 -0
  410. package/dist/web/widgets/plan-card.d.ts +36 -0
  411. package/dist/web/widgets/plan-card.js +13 -0
  412. package/dist/web/widgets/progress-bar.d.ts +19 -0
  413. package/dist/web/widgets/progress-bar.js +24 -0
  414. package/dist/web/widgets/progress-list.d.ts +19 -0
  415. package/dist/web/widgets/progress-list.js +11 -0
  416. package/dist/web/widgets/public-shell.d.ts +22 -0
  417. package/dist/web/widgets/public-shell.js +15 -0
  418. package/dist/web/widgets/query-table.d.ts +29 -0
  419. package/dist/web/widgets/query-table.js +30 -0
  420. package/dist/web/widgets/result-panel.d.ts +69 -0
  421. package/dist/web/widgets/result-panel.js +30 -0
  422. package/dist/web/widgets/section-card.d.ts +12 -0
  423. package/dist/web/widgets/section-card.js +9 -0
  424. package/dist/web/widgets/sheet-parts.d.ts +9 -0
  425. package/dist/web/widgets/sheet-parts.js +11 -0
  426. package/dist/web/widgets/side-by-side-table.d.ts +31 -0
  427. package/dist/web/widgets/side-by-side-table.js +11 -0
  428. package/dist/web/widgets/stat.d.ts +54 -0
  429. package/dist/web/widgets/stat.js +65 -0
  430. package/dist/web/widgets/states.d.ts +23 -0
  431. package/dist/web/widgets/states.js +20 -0
  432. package/dist/web/widgets/status-badge.d.ts +15 -0
  433. package/dist/web/widgets/status-badge.js +24 -0
  434. package/dist/web/widgets/step-bar.d.ts +35 -0
  435. package/dist/web/widgets/step-bar.js +60 -0
  436. package/dist/web/widgets/upload-zone.d.ts +24 -0
  437. package/dist/web/widgets/upload-zone.js +108 -0
  438. package/dist/web/widgets/use-draft.d.ts +20 -0
  439. package/dist/web/widgets/use-draft.js +21 -0
  440. package/dist/web/widgets/use-pointer-drag.d.ts +21 -0
  441. package/dist/web/widgets/use-pointer-drag.js +53 -0
  442. package/package.json +105 -7
  443. package/src/changes.json +53 -0
  444. package/src/web/fonts/OFL.txt +93 -0
  445. package/src/web/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
  446. package/src/web/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
  447. package/src/web/fonts/ibm-plex-mono-latin-ext-400.woff2 +0 -0
  448. package/src/web/fonts/ibm-plex-mono-latin-ext-500.woff2 +0 -0
  449. package/src/web/fonts/ibm-plex-sans-latin-400.woff2 +0 -0
  450. package/src/web/fonts/ibm-plex-sans-latin-500.woff2 +0 -0
  451. package/src/web/fonts/ibm-plex-sans-latin-600.woff2 +0 -0
  452. package/src/web/fonts/ibm-plex-sans-latin-ext-400.woff2 +0 -0
  453. package/src/web/fonts/ibm-plex-sans-latin-ext-500.woff2 +0 -0
  454. package/src/web/fonts/ibm-plex-sans-latin-ext-600.woff2 +0 -0
  455. package/src/web/styles.css +401 -0
@@ -0,0 +1,7 @@
1
+ export { CSRF_HEADER_NAME, readCsrfToken } from "./csrf.ts";
2
+ export type { LiveDispatcherOptions } from "./dispatcher-live.ts";
3
+ export { createLiveDispatcher } from "./dispatcher-live.ts";
4
+ export { buildAbortError, buildNetworkError, mapServerError } from "./error-mapping.ts";
5
+ export { LOCALE_HEADER_NAME, readActiveLocale } from "./locale.ts";
6
+ export type { SseFrame } from "./sse-stream.ts";
7
+ export { iterateSseChunks, parseSseBlock, parseSseFrames } from "./sse-stream.ts";
@@ -0,0 +1,5 @@
1
+ export { CSRF_HEADER_NAME, readCsrfToken } from "./csrf.js";
2
+ export { createLiveDispatcher } from "./dispatcher-live.js";
3
+ export { buildAbortError, buildNetworkError, mapServerError } from "./error-mapping.js";
4
+ export { LOCALE_HEADER_NAME, readActiveLocale } from "./locale.js";
5
+ export { iterateSseChunks, parseSseBlock, parseSseFrames } from "./sse-stream.js";
@@ -0,0 +1,2 @@
1
+ export declare const LOCALE_HEADER_NAME = "X-Locale";
2
+ export declare function readActiveLocale(): string | undefined;
@@ -0,0 +1,25 @@
1
+ // Active-locale header transport for the live dispatcher.
2
+ //
3
+ // @cosmicdrift/kumiko-renderer/web's DocumentLangSync (mounted by
4
+ // createKumikoApp/createPublicSurface) sets dataset.kumikoLocale from the
5
+ // LocaleResolver. This module reads that marker back so every outgoing
6
+ // request carries the language the user is ACTUALLY using — not a static
7
+ // <html lang> — with zero app-side wiring.
8
+ import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
9
+ // Kept in sync with LOCALE_HEADER_NAME in api-constants.ts by hand rather
10
+ // than imported from @cosmicdrift/kumiko-framework — this package must
11
+ // remain server-dep-free (runs in browsers and React Native).
12
+ export const LOCALE_HEADER_NAME = "X-Locale";
13
+ // Loose BCP-47 tag check — reject newlines/junk that would break fetch headers.
14
+ const LOCALE_TAG = /^[A-Za-z]{2,3}(-[A-Za-z0-9]{2,8})*$/;
15
+ // Reads dataset.kumikoLocale. Returns undefined for non-browser environments
16
+ // (SSR, Web Worker, React Native), before DocumentLangSync has run, or when
17
+ // the value is not a safe language tag — callers skip the header and the
18
+ // server falls back to Accept-Language, then its boot default.
19
+ export function readActiveLocale() {
20
+ const dataset = propertyOf(propertyOf(propertyOf(globalThis, "document"), "documentElement"), "dataset");
21
+ const lang = propertyOf(dataset, "kumikoLocale");
22
+ if (typeof lang !== "string" || lang.length === 0)
23
+ return undefined;
24
+ return LOCALE_TAG.test(lang) ? lang : undefined;
25
+ }
@@ -0,0 +1,14 @@
1
+ export type SseFrame = {
2
+ readonly event: string;
3
+ readonly data: string;
4
+ };
5
+ export declare function parseSseBlock(block: string): SseFrame | null;
6
+ /** Split a complete SSE body (tests / non-streaming buffers) into frames. */
7
+ export declare function parseSseFrames(text: string): SseFrame[];
8
+ /**
9
+ * Incremental SSE reader over a fetch body. Yields `chunk` payloads as
10
+ * parsed JSON; swallows `ping`; returns on `done`; throws DispatcherError
11
+ * on `error` frames. Caller is responsible for aborting the underlying
12
+ * fetch via AbortSignal.
13
+ */
14
+ export declare function iterateSseChunks<TChunk>(body: ReadableStream<Uint8Array>): AsyncGenerator<TChunk, void, undefined>;
@@ -0,0 +1,128 @@
1
+ import { StreamFrame } from "../headless/index.js";
2
+ import { serverErrorSchema } from "./envelopes.js";
3
+ import { mapServerError } from "./error-mapping.js";
4
+ export function parseSseBlock(block) {
5
+ const trimmed = block.trim();
6
+ if (trimmed.length === 0)
7
+ return null;
8
+ const event = /^event: (.*)$/m.exec(trimmed)?.[1] ?? "";
9
+ const data = /^data: (.*)$/m.exec(trimmed)?.[1] ?? "";
10
+ return { event, data };
11
+ }
12
+ /** Split a complete SSE body (tests / non-streaming buffers) into frames. */
13
+ export function parseSseFrames(text) {
14
+ return text
15
+ .split("\n\n")
16
+ .map(parseSseBlock)
17
+ .filter((f) => f !== null);
18
+ }
19
+ /**
20
+ * Incremental SSE reader over a fetch body. Yields `chunk` payloads as
21
+ * parsed JSON; swallows `ping`; returns on `done`; throws DispatcherError
22
+ * on `error` frames. Caller is responsible for aborting the underlying
23
+ * fetch via AbortSignal.
24
+ */
25
+ export async function* iterateSseChunks(body) {
26
+ const reader = body.getReader();
27
+ const decoder = new TextDecoder();
28
+ let buffer = "";
29
+ let sawDone = false;
30
+ try {
31
+ while (true) {
32
+ const { done, value } = await reader.read();
33
+ if (done)
34
+ break;
35
+ buffer += decoder.decode(value, { stream: true });
36
+ const parts = buffer.split("\n\n");
37
+ buffer = parts.pop() ?? "";
38
+ for (const part of parts) {
39
+ const frame = parseSseBlock(part);
40
+ if (frame === null)
41
+ continue;
42
+ if (frame.event === StreamFrame.ping)
43
+ continue;
44
+ // skip: terminal SSE done frame — end the generator cleanly
45
+ if (frame.event === StreamFrame.done) {
46
+ sawDone = true;
47
+ return;
48
+ }
49
+ if (frame.event === StreamFrame.error) {
50
+ throw frameDataToDispatcherError(frame.data);
51
+ }
52
+ if (frame.event === StreamFrame.chunk) {
53
+ yield parseChunkData(frame.data);
54
+ }
55
+ }
56
+ }
57
+ // Trailing buffer without final blank line (some runtimes).
58
+ const frame = parseSseBlock(buffer);
59
+ if (frame?.event === StreamFrame.chunk) {
60
+ yield parseChunkData(frame.data);
61
+ }
62
+ else if (frame?.event === StreamFrame.error) {
63
+ throw frameDataToDispatcherError(frame.data);
64
+ }
65
+ else if (frame?.event === StreamFrame.done) {
66
+ sawDone = true;
67
+ }
68
+ if (!sawDone) {
69
+ throw buildTruncatedStreamError();
70
+ }
71
+ }
72
+ finally {
73
+ // cancel() releases the reader's lock too (safe on an already-drained
74
+ // stream) and, unlike releaseLock() alone, tells the underlying HTTP
75
+ // response to close instead of leaving the connection open until the
76
+ // server finishes writing a body no one is reading anymore.
77
+ await reader.cancel().catch(() => { });
78
+ }
79
+ }
80
+ function parseChunkData(data) {
81
+ try {
82
+ return JSON.parse(data);
83
+ }
84
+ catch (e) {
85
+ const cause = e instanceof Error ? e.message : String(e);
86
+ throw {
87
+ code: "stream_error",
88
+ httpStatus: 200,
89
+ i18nKey: "errors.unknown",
90
+ message: `malformed chunk frame: ${cause}`,
91
+ };
92
+ }
93
+ }
94
+ function buildTruncatedStreamError() {
95
+ return {
96
+ code: "stream_error",
97
+ httpStatus: 200,
98
+ i18nKey: "errors.unknown",
99
+ message: "stream ended without a done frame",
100
+ };
101
+ }
102
+ function frameDataToDispatcherError(data) {
103
+ let parsed;
104
+ try {
105
+ parsed = JSON.parse(data);
106
+ }
107
+ catch {
108
+ return unparsableErrorFrame(data);
109
+ }
110
+ // Server serializeError shape — mapServerError expects the same fields
111
+ // as /api/query failures (httpStatus may be absent; reinject 200 for
112
+ // mid-stream gates that flush SSE headers first).
113
+ const envelope = serverErrorSchema.safeParse(parsed);
114
+ if (!envelope.success)
115
+ return unparsableErrorFrame(data);
116
+ return mapServerError({
117
+ ...envelope.data,
118
+ httpStatus: envelope.data.httpStatus ?? 200,
119
+ });
120
+ }
121
+ function unparsableErrorFrame(data) {
122
+ return {
123
+ code: "stream_error",
124
+ httpStatus: 200,
125
+ i18nKey: "errors.unknown",
126
+ message: data.length > 0 ? data : "stream error frame",
127
+ };
128
+ }
@@ -1,11 +1,11 @@
1
1
  import type { ConfigCascade, ConfigScope, ConfigValueSource } from "@cosmicdrift/kumiko-framework/engine";
2
2
  import type { FieldIconKey, FormWidth, IconKey, NavIconKey, RowActionDisplay, SelectOptionTone } from "@cosmicdrift/kumiko-framework/ui-types";
3
- import type { FieldIssue, ListColumnViewModel, ListRowViewModel, RuntimeRenderer } from "@cosmicdrift/kumiko-headless";
4
3
  import { type ComponentType, type FormEvent, type KeyboardEvent, type ReactNode, type Ref } from "react";
4
+ import type { FieldIssue, ListColumnViewModel, ListRowViewModel, RuntimeRenderer } from "./headless/index.ts";
5
5
  export type { RuntimeRenderer };
6
6
  /** Escape hatch for `data-*` test hooks (e.g. an E2E selector) that don't
7
7
  * warrant a dedicated typed prop. Web merges these onto the rendered
8
- * element; native impls ignore it (precedent: `className`). */
8
+ * element. */
9
9
  export type DataAttributes = Readonly<Record<`data-${string}`, string>>;
10
10
  /** Structural marker a top-level `actions` node can carry so DefaultForm's
11
11
  * sticky-footer split (fw#1918) treats it as the pinned primary action even
@@ -56,7 +56,7 @@ type ButtonBaseProps = {
56
56
  /** Barrierefreies Label — Pflicht bei icon-only-Buttons (children ist nur
57
57
  * ein Icon/Zeichen), sonst hat der Button keinen zugänglichen Namen. */
58
58
  readonly ariaLabel?: string;
59
- /** Tooltip — web renders the native `title` attribute, native impls may ignore it. */
59
+ /** Tooltip — rendered as the `title` attribute. */
60
60
  readonly title?: string;
61
61
  /** Toggle state for toggle buttons — web sets `aria-pressed`; leave unset for plain buttons. */
62
62
  readonly pressed?: boolean;
@@ -67,12 +67,10 @@ type ButtonBaseProps = {
67
67
  * des Containers, kein Button-Prop (Kit hält arbiträres Sizing draußen). */
68
68
  readonly width?: "full" | "auto";
69
69
  readonly testId?: string;
70
- /** Layout extras — Web merges via cn(), native impls ignore it
71
- * (precedent: LinkProps.className). */
70
+ /** Layout extras, merged via cn(). */
72
71
  readonly className?: string;
73
72
  /** DOM ref on the button — escape hatch for cases that need more than
74
- * a click (e.g. binding a drop-target handler). Web forwards it, native
75
- * impls ignore it (no native equivalent). */
73
+ * a click (e.g. binding a drop-target handler). Forwarded to the element. */
76
74
  readonly ref?: Ref<HTMLButtonElement>;
77
75
  /** Icon before the label. */
78
76
  readonly icon?: NavIconKey;
@@ -94,8 +92,7 @@ export type LinkProps = {
94
92
  /** Plain left-click handler (SPA navigation); `href` stays set for
95
93
  * modifier/middle clicks, which the browser handles itself. */
96
94
  readonly onPress?: () => void;
97
- /** Layout-Zusätze (self-center, text-xs) — Web merged via cn(),
98
- * Native-Impls ignorieren es (Präzedenz: CardProps.className). */
95
+ /** Layout extras (self-center, text-xs), merged via cn(). */
99
96
  readonly className?: string;
100
97
  readonly children: ReactNode;
101
98
  readonly testId?: string;
@@ -220,7 +217,7 @@ export type InputProps = {
220
217
  /** Read-only Input (z.B. gewürfelter Free-Tier-Slug). Nicht `disabled`
221
218
  * — bleibt fokussier-/kopierbar. */
222
219
  readonly readOnly?: boolean;
223
- /** Closed FieldIconKey vocabulary (FIELD_ICONS registry, renderer-web). */
220
+ /** Closed FieldIconKey vocabulary (FIELD_ICONS registry, renderer/web). */
224
221
  readonly icon?: FieldIconKey;
225
222
  /** Resolved inline text before/after the input (EditFieldSpec.prefix/suffix). */
226
223
  readonly prefix?: string;
@@ -228,8 +225,7 @@ export type InputProps = {
228
225
  readonly fill?: InputFillAction;
229
226
  readonly dataAttributes?: DataAttributes;
230
227
  /** Raw keydown access (e.g. Enter-to-submit at the field instead of
231
- * the surrounding Form). Web forwards it, native impls ignore it
232
- * (precedent: `ButtonProps.ref`). */
228
+ * the surrounding Form). Forwarded to the element. */
233
229
  readonly onKeyDown?: (event: KeyboardEvent<HTMLInputElement>) => void;
234
230
  } | {
235
231
  readonly kind: "email";
@@ -245,6 +241,17 @@ export type InputProps = {
245
241
  * Username-or-Email) reichen das durch. */
246
242
  readonly autoComplete?: string;
247
243
  readonly testId?: string;
244
+ } | {
245
+ /** Month picker; the value is `YYYY-MM` (empty string when unset). */
246
+ readonly kind: "month";
247
+ readonly id: string;
248
+ readonly name: string;
249
+ readonly value: string;
250
+ readonly onChange: (v: string) => void;
251
+ readonly disabled?: boolean;
252
+ readonly required?: boolean;
253
+ readonly hasError?: boolean;
254
+ readonly testId?: string;
248
255
  } | {
249
256
  readonly kind: "password";
250
257
  readonly id: string;
@@ -276,7 +283,7 @@ export type InputProps = {
276
283
  /** Hint text shown when the field is empty (analog to kind:"text"). */
277
284
  readonly placeholder?: string;
278
285
  readonly testId?: string;
279
- /** Closed FieldIconKey vocabulary (FIELD_ICONS registry, renderer-web). */
286
+ /** Closed FieldIconKey vocabulary (FIELD_ICONS registry, renderer/web). */
280
287
  readonly icon?: FieldIconKey;
281
288
  /** `<input step>`. "any" disables the native stepMismatch constraint
282
289
  * (needed for decimal fields — integer fields leave this unset).
@@ -345,7 +352,7 @@ export type InputProps = {
345
352
  * attribute so a phone opens the camera instead of the file picker. */
346
353
  readonly capture?: "environment" | "user";
347
354
  /** Web-only folder picker: the picked files (with `webkitRelativePath`)
348
- * go to `onFilesPicked` and nothing is uploaded. Native impls ignore it. */
355
+ * go to `onFilesPicked` and nothing is uploaded. */
349
356
  readonly directory?: boolean;
350
357
  readonly onFilesPicked?: (files: readonly PickedFile[]) => void;
351
358
  /** Translated label of the pick button; absent → the upload/change default. */
@@ -541,8 +548,8 @@ export type InputProps = {
541
548
  readonly dataAttributes?: DataAttributes;
542
549
  /** Raw keydown access (e.g. plain-Enter-submits/Shift+Enter-newline at
543
550
  * the field instead of the surrounding Form). Composes with
544
- * `onSubmitShortcut` — both fire on the same keystroke when set. Web
545
- * forwards it, native impls ignore it (precedent: `ButtonProps.ref`). */
551
+ * `onSubmitShortcut` — both fire on the same keystroke when set. Forwarded
552
+ * to the element. */
546
553
  readonly onKeyDown?: (event: KeyboardEvent<HTMLTextAreaElement>) => void;
547
554
  };
548
555
  export type DataTableSortDir = "asc" | "desc";
@@ -783,7 +790,7 @@ export type DataTableProps = {
783
790
  readonly renderExpandedRow?: (row: ListRowViewModel) => ReactNode;
784
791
  };
785
792
  /** Cell type for one column of an embedded-list field. Mirrors
786
- * EmbeddedListCellViewModel["type"] from `@cosmicdrift/kumiko-headless`. */
793
+ * EmbeddedListCellViewModel["type"] from `@cosmicdrift/kumiko-renderer/headless`. */
787
794
  export type EmbeddedListCellType = "text" | "number" | "boolean" | "date" | "money" | "decimal" | "select" | "reference" | "timestamp";
788
795
  /** One column of an embedded-list table (one entry per key of the source
789
796
  * EmbeddedFieldDef's `schema`). */
@@ -880,8 +887,7 @@ export type FormSectionNavItem = {
880
887
  *
881
888
  * `title`: slot in the card header. `actions`: optional slot for the
882
889
  * primary form actions (Save, Cancel) — renders as a footer row at the
883
- * end of the card (normal document flow). Native impls may render the
884
- * same slot as a bottom bar instead. */
890
+ * end of the card (normal document flow). */
885
891
  export type FormProps = {
886
892
  readonly onSubmit: (e?: FormEvent) => void;
887
893
  readonly children: ReactNode;
@@ -895,24 +901,20 @@ export type FormProps = {
895
901
  readonly secondaryActions?: ReactNode;
896
902
  readonly testId?: string;
897
903
  /** Max width of the form container. Default "full" — see FormWidth
898
- * (`packages/types/src/screen.ts`, EditLayout.width). Native impls may
899
- * ignore this prop (no width constraint there). */
904
+ * (`packages/types/src/screen.ts`, EditLayout.width). */
900
905
  readonly width?: FormWidth;
901
906
  /** Pins `actions` to the viewport bottom on narrow screens (`<640px`)
902
907
  * instead of normal document flow, so it stays reachable when a virtual
903
908
  * keyboard shrinks the visible viewport (fw#1918). Desktop/tablet
904
- * unaffected. Native impls may ignore this prop (already bottom-bar by
905
- * convention there). */
909
+ * unaffected. */
906
910
  readonly stickyActions?: boolean;
907
911
  /** Extra content rendered above the card, inside the same page padding
908
912
  * the card itself sits in — for a host that needs its own header region
909
913
  * (title/metrics/tabs) to share the form's left padding and width
910
- * instead of rendering as unpadded siblings before it. Native impls may
911
- * ignore this prop. */
914
+ * instead of rendering as unpadded siblings before it. */
912
915
  readonly headerRegion?: ReactNode;
913
916
  /** Compact content on the right of the form title, same row — status
914
- * chips or allowance badges that belong to the screen, not to a field.
915
- * Native impls may ignore this prop. */
917
+ * chips or allowance badges that belong to the screen, not to a field. */
916
918
  readonly titleAction?: ReactNode;
917
919
  /** Sizes the form to fill its container's height (instead of the page's
918
920
  * natural content height) so a single scrolling child — a lone
@@ -921,8 +923,7 @@ export type FormProps = {
921
923
  * section and for screens that fill the shell height (together with
922
924
  * `stickyActions`: sections scroll, footer stays pinned without
923
925
  * `position: fixed`); every other caller leaves it unset and keeps normal
924
- * document-flow height. Native impls may ignore this prop (already a
925
- * bounded viewport there). */
926
+ * document-flow height. */
926
927
  readonly fillHeight?: boolean;
927
928
  /** Drops the surrounding card (bg/border/rounded, title/subtitle block,
928
929
  * footer border) so sections+footer render as siblings of `headerRegion`
@@ -930,14 +931,12 @@ export type FormProps = {
930
931
  * projectionDetail's tab content is a sibling of the head card, not its
931
932
  * child (bedienkonzept A1), so it must look like a standalone screen
932
933
  * instead of a form embedded in another card. Default false: unchanged
933
- * card chrome. Native impls may ignore this prop (no card chrome there
934
- * to begin with). */
934
+ * card chrome. */
935
935
  readonly chromeless?: boolean;
936
936
  /** Set by RenderEdit for entityEdit/actionForm screens that fill the shell
937
937
  * height: the form renders without a surrounding card, in a padded scroll
938
938
  * surface with a fixed-width form column. Requires `fillHeight`; projection
939
- * detail screens (which also fill the height) do not set it. Native impls
940
- * may ignore this prop. */
939
+ * detail screens (which also fill the height) do not set it. */
941
940
  readonly screenForm?: boolean;
942
941
  /** Number of unsaved changes, shown in the pinned footer; 0 shows the quiet
943
942
  * "No unsaved changes" status. Omitted (create mode) — no status at all. */
@@ -951,7 +950,7 @@ export type FormProps = {
951
950
  * `screenForm`. The web impl shows it only with three or more entries. */
952
951
  readonly sectionNav?: readonly FormSectionNavItem[];
953
952
  /** Leading column next to the scroll surface of a `screenForm` (wizard step
954
- * navigation). Native impls may ignore this prop. */
953
+ * navigation). */
955
954
  readonly sideRail?: ReactNode;
956
955
  };
957
956
  /** Titled Gruppe von Feldern. Web: `<fieldset>` + `<legend>`, Native:
@@ -1432,7 +1431,7 @@ export type CopyButtonProps = {
1432
1431
  readonly label: string;
1433
1432
  readonly copiedLabel: string;
1434
1433
  readonly variant?: "primary" | "secondary";
1435
- /** Layout extras — web merges via cn(), native impls ignore it. */
1434
+ /** Layout extras, merged via cn(). */
1436
1435
  readonly className?: string;
1437
1436
  readonly testId?: string;
1438
1437
  };
@@ -1444,7 +1443,7 @@ export type ShareButtonProps = {
1444
1443
  readonly text: string;
1445
1444
  readonly label: string;
1446
1445
  readonly variant?: "primary" | "secondary";
1447
- /** Layout extras — web merges via cn(), native impls ignore it. */
1446
+ /** Layout extras, merged via cn(). */
1448
1447
  readonly className?: string;
1449
1448
  readonly testId?: string;
1450
1449
  } & ({
@@ -79,7 +79,7 @@ export function useOptionalPrimitives() {
79
79
  export function usePrimitives() {
80
80
  const registry = useContext(PrimitivesContext);
81
81
  if (registry === undefined) {
82
- throw new Error("usePrimitives: no <PrimitivesProvider> mounted. Wrap your app in one (createKumikoApp does this for you with defaultPrimitives from @cosmicdrift/kumiko-renderer-web).");
82
+ throw new Error("usePrimitives: no <PrimitivesProvider> mounted. Wrap your app in one (createKumikoApp does this for you with defaultPrimitives from @cosmicdrift/kumiko-renderer/web).");
83
83
  }
84
84
  return registry;
85
85
  }
@@ -1,5 +1,5 @@
1
- import type { Dispatcher, DispatcherError } from "@cosmicdrift/kumiko-headless";
2
1
  import { type ReactNode } from "react";
2
+ import type { Dispatcher, DispatcherError } from "../headless/index.ts";
3
3
  export declare const SESSION_ENDED_ERROR_CODES: readonly ["session_invalid", "invalid_token", "missing_token", "unauthenticated"];
4
4
  export declare function isSessionEndedError(error: Pick<DispatcherError, "code" | "httpStatus">): boolean;
5
5
  export type SessionEndedSignal = {
package/dist/tokens.d.ts CHANGED
@@ -85,8 +85,7 @@ export declare function TokensProvider({ children, value }: TokensProviderProps)
85
85
  export declare function useTokens(): Tokens;
86
86
  /** Volle API inkl. Theme-Toggle. Für den Dark/Light-Switch-Button. */
87
87
  export declare function useTokenController(): TokensApi;
88
- /** Tokens mit var-string-Werten. Konstant — die "Werte" sind
89
- * Referenzen, die echten Farben ändern sich per CSS ohne dass das
90
- * Objekt mutiert werden muss. Plattform-Packages (renderer-web,
91
- * -native) importieren das in ihre TokensApi-Impl. */
88
+ /** Tokens with var-string values. Constant: the "values" are references,
89
+ * the real colors change via CSS without mutating the object. Platform
90
+ * bindings (renderer/web) import it into their TokensApi impl. */
92
91
  export declare const cssVarTokens: Tokens;
package/dist/tokens.js CHANGED
@@ -30,14 +30,13 @@ export function useTokens() {
30
30
  export function useTokenController() {
31
31
  const api = useContext(TokensContext);
32
32
  if (api === undefined) {
33
- throw new Error("useTokens/useTokenController: no <TokensProvider> mounted. createKumikoApp verdrahtet den Provider automatisch mit @cosmicdrift/kumiko-renderer-web defaults.");
33
+ throw new Error("useTokens/useTokenController: no <TokensProvider> mounted. createKumikoApp verdrahtet den Provider automatisch mit @cosmicdrift/kumiko-renderer/web defaults.");
34
34
  }
35
35
  return api;
36
36
  }
37
- /** Tokens mit var-string-Werten. Konstant — die "Werte" sind
38
- * Referenzen, die echten Farben ändern sich per CSS ohne dass das
39
- * Objekt mutiert werden muss. Plattform-Packages (renderer-web,
40
- * -native) importieren das in ihre TokensApi-Impl. */
37
+ /** Tokens with var-string values. Constant: the "values" are references,
38
+ * the real colors change via CSS without mutating the object. Platform
39
+ * bindings (renderer/web) import it into their TokensApi impl. */
41
40
  export const cssVarTokens = {
42
41
  color: {
43
42
  background: "var(--color-background)",
@@ -0,0 +1,19 @@
1
+ import { type ReactNode } from "react";
2
+ import type { AppSchema } from "../../index.ts";
3
+ export declare const APP_SCHEMA_API_PATH = "/api/schema";
4
+ export declare function isAppSchemaPayload(value: unknown): value is AppSchema;
5
+ export type AppSchemaFetchResult = {
6
+ readonly kind: "loaded";
7
+ readonly app: AppSchema;
8
+ } | {
9
+ readonly kind: "session-ended";
10
+ } | {
11
+ readonly kind: "unauthorized";
12
+ } | {
13
+ readonly kind: "failed";
14
+ };
15
+ export declare function fetchAppSchema(signal: AbortSignal, schemaUrl?: string): Promise<AppSchemaFetchResult>;
16
+ export declare function AppSchemaFetchBoot({ onLoaded, schemaUrl, }: {
17
+ readonly onLoaded: (app: AppSchema) => void;
18
+ readonly schemaUrl?: string;
19
+ }): ReactNode;
@@ -0,0 +1,124 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef, useState } from "react";
3
+ import { toAppSchema, usePrimitives, useSessionEndedSignal, useTranslation } from "../../index.js";
4
+ // Mirrors framework's api-constants Routes.schema, same pattern as
5
+ // dispatcher-live's PATH_* constants — the one place that spells out the
6
+ // wire path both sides agree on.
7
+ export const APP_SCHEMA_API_PATH = "/api/schema";
8
+ function isFeatureSchemaPayload(value) {
9
+ if (typeof value !== "object" || value === null)
10
+ return false;
11
+ if (!("featureName" in value) || typeof value.featureName !== "string")
12
+ return false;
13
+ return "screens" in value && Array.isArray(value.screens);
14
+ }
15
+ export function isAppSchemaPayload(value) {
16
+ if (typeof value !== "object" || value === null)
17
+ return false;
18
+ if (!("features" in value) || !Array.isArray(value.features))
19
+ return false;
20
+ return value.features.every((feature) => isFeatureSchemaPayload(feature));
21
+ }
22
+ function isAbortError(err) {
23
+ return err instanceof DOMException && err.name === "AbortError";
24
+ }
25
+ // Mirrors createLiveDispatcher: a cross-origin API (absolute baseUrl) needs
26
+ // credentials "include" for the session cookie to travel; same-origin stays
27
+ // "same-origin" so a relative path never widens.
28
+ function schemaFetchCredentials(schemaUrl) {
29
+ try {
30
+ return new URL(schemaUrl, window.location.href).origin === window.location.origin
31
+ ? "same-origin"
32
+ : "include";
33
+ }
34
+ catch {
35
+ return "same-origin";
36
+ }
37
+ }
38
+ // Rejects only on abort (caller-cancelled) — every other failure mode
39
+ // (network error, non-2xx, unparseable/invalid body) resolves to
40
+ // `{ kind: "failed" }` so callers get one uniform result shape to branch
41
+ // on instead of a mix of thrown errors and resolved results.
42
+ export async function fetchAppSchema(signal, schemaUrl = APP_SCHEMA_API_PATH) {
43
+ let res;
44
+ try {
45
+ res = await fetch(schemaUrl, {
46
+ credentials: schemaFetchCredentials(schemaUrl),
47
+ headers: { Accept: "application/json" },
48
+ signal,
49
+ });
50
+ }
51
+ catch (err) {
52
+ if (isAbortError(err))
53
+ throw err;
54
+ return { kind: "failed" };
55
+ }
56
+ if (res.status === 401)
57
+ return { kind: "session-ended" };
58
+ if (res.status === 403)
59
+ return { kind: "unauthorized" };
60
+ if (!res.ok)
61
+ return { kind: "failed" };
62
+ let payload;
63
+ try {
64
+ payload = await res.json();
65
+ }
66
+ catch {
67
+ return { kind: "failed" };
68
+ }
69
+ if (!isAppSchemaPayload(payload))
70
+ return { kind: "failed" };
71
+ return { kind: "loaded", app: toAppSchema(payload) };
72
+ }
73
+ // Boots the app once the caller (AppSchemaBoundary, itself inside the
74
+ // clientFeature gates) decides to mount it — a login gate renders its own
75
+ // placeholder instead of children, so this component (and its fetch) never
76
+ // mounts until the user is authenticated.
77
+ export function AppSchemaFetchBoot({ onLoaded, schemaUrl, }) {
78
+ const t = useTranslation();
79
+ const { Banner, Button } = usePrimitives();
80
+ const [status, setStatus] = useState("loading");
81
+ const sessionEndedSignal = useSessionEndedSignal();
82
+ const [attempt, setAttempt] = useState(0);
83
+ // Ref instead of an effect dependency: onLoaded is a fresh closure on
84
+ // every KumikoAppRoot render (it captures setApp) — depending on it
85
+ // directly would refetch on every unrelated re-render.
86
+ const onLoadedRef = useRef(onLoaded);
87
+ onLoadedRef.current = onLoaded;
88
+ // biome-ignore lint/correctness/useExhaustiveDependencies: attempt is the retry trigger, never read in the body — bumping it is how the Retry button re-fires this effect.
89
+ useEffect(() => {
90
+ const controller = new AbortController();
91
+ setStatus("loading");
92
+ fetchAppSchema(controller.signal, schemaUrl)
93
+ .then((result) => {
94
+ if (controller.signal.aborted)
95
+ return;
96
+ if (result.kind === "loaded") {
97
+ onLoadedRef.current(result.app);
98
+ return;
99
+ }
100
+ setStatus(result.kind);
101
+ })
102
+ .catch((err) => {
103
+ if (!isAbortError(err))
104
+ setStatus("failed");
105
+ });
106
+ return () => controller.abort();
107
+ }, [attempt, schemaUrl]);
108
+ useEffect(() => {
109
+ if (status === "session-ended")
110
+ sessionEndedSignal?.notify();
111
+ }, [status, sessionEndedSignal]);
112
+ if (status === "loading") {
113
+ return (_jsx("div", { role: "status", "aria-busy": "true", children: t("kumiko.app-boot.loading") }));
114
+ }
115
+ if (status === "unauthorized" || status === "session-ended") {
116
+ // No auto-retry/reload here on purpose — a signed-out user retrying
117
+ // the same request just gets the same 401 again; the login gate that
118
+ // wraps this component is the actual way out. For session-ended the
119
+ // notify above normally swaps this banner for the login screen; the
120
+ // banner stays as fallback when no session provider is mounted.
121
+ return (_jsx(Banner, { variant: "error", padded: true, children: t("kumiko.app-boot.unauthorized") }));
122
+ }
123
+ return (_jsx(Banner, { variant: "error", padded: true, actions: _jsx(Button, { variant: "secondary", onClick: () => setAttempt((n) => n + 1), children: t("kumiko.actions.reload") }), children: t("kumiko.app-boot.failed") }));
124
+ }
@@ -0,0 +1,22 @@
1
+ import { type LocaleResolver } from "../../headless/index.ts";
2
+ export type CreateBrowserLocaleResolverOptions = {
3
+ /** localStorage-Key unter dem die aktive Locale persistiert wird.
4
+ * Default: `"kumiko:locale"`. Apps die mehrere Kumiko-Instanzen auf
5
+ * derselben Origin mounten (selten), setzen verschiedene Keys. */
6
+ readonly storageKey?: string;
7
+ /** Fallback wenn weder localStorage noch navigator.language liefern.
8
+ * Default: `"en"`. */
9
+ readonly defaultLocale?: string;
10
+ /** Maps a stored or browser-reported tag onto one of the app's locales;
11
+ * `undefined` rejects it (a stored tag then falls through to
12
+ * navigator.language, the browser tag to `defaultLocale`). Only applied to
13
+ * the initial detection, not to `setLocale`. */
14
+ readonly normalizeLocale?: (tag: string) => string | undefined;
15
+ };
16
+ export declare const BROWSER_LOCALE_STORAGE_KEY = "kumiko:locale";
17
+ /** Default-Resolver wenn createKumikoApp ohne `locale`-Option gebootet
18
+ * wird. Stateful: setLocale() persistiert in localStorage und ruft
19
+ * subscribed listeners. Apps die eine vollwertige i18n-Schicht haben
20
+ * (i18next, FormatJS, eigener Store), reichen stattdessen ihre eigene
21
+ * Resolver-Impl via `createKumikoApp({ locale })`. */
22
+ export declare function createBrowserLocaleResolver(options?: CreateBrowserLocaleResolverOptions): LocaleResolver;