@cosmicdrift/kumiko-renderer 0.373.0 → 0.377.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (466) hide show
  1. package/README.md +2 -2
  2. package/dist/app/action-form-support.d.ts +58 -0
  3. package/dist/app/action-form-support.js +96 -0
  4. package/dist/app/client-actions.d.ts +46 -0
  5. package/dist/app/client-actions.js +60 -0
  6. package/dist/app/column-renderers.js +1 -1
  7. package/dist/app/config-edit-shim.js +1 -1
  8. package/dist/app/content-preview.js +1 -6
  9. package/dist/app/custom-screens.js +1 -1
  10. package/dist/app/dashboard-body.d.ts +1 -1
  11. package/dist/app/entity-list-expanded-row.d.ts +1 -1
  12. package/dist/app/entity-list-expanded-row.js +4 -0
  13. package/dist/app/form-schema.d.ts +1 -1
  14. package/dist/app/form-schema.js +2 -2
  15. package/dist/app/header-actions-bar.d.ts +19 -0
  16. package/dist/app/header-actions-bar.js +30 -0
  17. package/dist/app/kumiko-screen.d.ts +1 -1
  18. package/dist/app/kumiko-screen.js +134 -66
  19. package/dist/app/list-empty-content.d.ts +2 -2
  20. package/dist/app/list-empty-content.js +3 -2
  21. package/dist/app/list-facets.d.ts +1 -1
  22. package/dist/app/nav.js +2 -2
  23. package/dist/app/query-state-banners.d.ts +1 -1
  24. package/dist/app/reference-link.d.ts +1 -1
  25. package/dist/app/row-actions.d.ts +10 -2
  26. package/dist/app/row-actions.js +85 -6
  27. package/dist/app/secret-mint-body.d.ts +1 -1
  28. package/dist/app/secrets-edit-body.d.ts +1 -1
  29. package/dist/app/use-record-actions.d.ts +12 -0
  30. package/dist/app/use-record-actions.js +30 -0
  31. package/dist/app/write-failed-error.d.ts +1 -1
  32. package/dist/components/availability-options-select.d.ts +1 -1
  33. package/dist/components/embedded-list-field.d.ts +1 -1
  34. package/dist/components/embedded-list-field.js +1 -1
  35. package/dist/components/file-list-field.d.ts +1 -1
  36. package/dist/components/grid-cell-for-field.d.ts +4 -2
  37. package/dist/components/grid-cell-for-field.js +2 -2
  38. package/dist/components/multi-select-checkboxes.d.ts +1 -1
  39. package/dist/components/multi-select-checkboxes.js +1 -1
  40. package/dist/components/query-options-select.d.ts +1 -1
  41. package/dist/components/related-list-section.d.ts +1 -1
  42. package/dist/components/related-list-section.js +16 -3
  43. package/dist/components/render-edit-logic.d.ts +1 -1
  44. package/dist/components/render-edit-types.d.ts +2 -2
  45. package/dist/components/render-edit.d.ts +1 -1
  46. package/dist/components/render-edit.js +5 -3
  47. package/dist/components/render-field.d.ts +5 -2
  48. package/dist/components/render-field.js +103 -9
  49. package/dist/components/render-list.d.ts +1 -1
  50. package/dist/components/render-list.js +20 -4
  51. package/dist/components/write-form-section.d.ts +1 -1
  52. package/dist/components/write-form-section.js +1 -1
  53. package/dist/context/dispatcher-context.d.ts +1 -1
  54. package/dist/format-when.js +1 -1
  55. package/dist/headless/apex/css.d.ts +3 -0
  56. package/dist/headless/apex/css.js +298 -0
  57. package/dist/headless/apex/index.d.ts +236 -0
  58. package/dist/headless/apex/index.js +377 -0
  59. package/dist/headless/apex/lightbox.d.ts +4 -0
  60. package/dist/headless/apex/lightbox.js +81 -0
  61. package/dist/headless/contracts/asset.d.ts +15 -0
  62. package/dist/headless/contracts/asset.js +17 -0
  63. package/dist/headless/contracts/index.d.ts +3 -0
  64. package/dist/headless/contracts/index.js +1 -0
  65. package/dist/headless/contracts/locale.d.ts +7 -0
  66. package/dist/headless/contracts/locale.js +11 -0
  67. package/dist/headless/contracts/primitives.d.ts +93 -0
  68. package/dist/headless/contracts/primitives.js +21 -0
  69. package/dist/headless/dispatcher/index.d.ts +2 -0
  70. package/dist/headless/dispatcher/index.js +1 -0
  71. package/dist/headless/dispatcher/types.d.ts +86 -0
  72. package/dist/headless/dispatcher/types.js +34 -0
  73. package/dist/headless/form/form-controller.d.ts +2 -0
  74. package/dist/headless/form/form-controller.js +409 -0
  75. package/dist/headless/form/index.d.ts +3 -0
  76. package/dist/headless/form/index.js +2 -0
  77. package/dist/headless/form/types.d.ts +76 -0
  78. package/dist/headless/form/types.js +1 -0
  79. package/dist/headless/form/zod-bridge.d.ts +10 -0
  80. package/dist/headless/form/zod-bridge.js +103 -0
  81. package/dist/headless/format/document-values.d.ts +12 -0
  82. package/dist/headless/format/document-values.js +70 -0
  83. package/dist/headless/format/escape.d.ts +5 -0
  84. package/dist/headless/format/escape.js +75 -0
  85. package/dist/headless/format/html-template.d.ts +9 -0
  86. package/dist/headless/format/html-template.js +39 -0
  87. package/dist/headless/format/index.d.ts +12 -0
  88. package/dist/headless/format/index.js +237 -0
  89. package/dist/headless/format/money.d.ts +3 -0
  90. package/dist/headless/format/money.js +39 -0
  91. package/dist/headless/index.d.ts +14 -0
  92. package/dist/headless/index.js +9 -0
  93. package/dist/headless/locale-routing/index.d.ts +41 -0
  94. package/dist/headless/locale-routing/index.js +145 -0
  95. package/dist/headless/nav/index.d.ts +2 -0
  96. package/dist/headless/nav/index.js +1 -0
  97. package/dist/headless/nav/resolve.d.ts +2 -0
  98. package/dist/headless/nav/resolve.js +71 -0
  99. package/dist/headless/nav/types.d.ts +26 -0
  100. package/dist/headless/nav/types.js +1 -0
  101. package/dist/headless/store/create-store.d.ts +2 -0
  102. package/dist/headless/store/create-store.js +43 -0
  103. package/dist/headless/store/equality.d.ts +1 -0
  104. package/dist/headless/store/equality.js +34 -0
  105. package/dist/headless/store/index.d.ts +3 -0
  106. package/dist/headless/store/index.js +2 -0
  107. package/dist/headless/store/types.d.ts +7 -0
  108. package/dist/headless/store/types.js +10 -0
  109. package/dist/headless/view-model/edit.d.ts +18 -0
  110. package/dist/headless/view-model/edit.js +501 -0
  111. package/dist/headless/view-model/embedded-list.d.ts +27 -0
  112. package/dist/headless/view-model/embedded-list.js +63 -0
  113. package/dist/headless/view-model/index.d.ts +7 -0
  114. package/dist/headless/view-model/index.js +3 -0
  115. package/dist/headless/view-model/list-file-display.d.ts +3 -0
  116. package/dist/headless/view-model/list-file-display.js +27 -0
  117. package/dist/headless/view-model/list.d.ts +16 -0
  118. package/dist/headless/view-model/list.js +229 -0
  119. package/dist/headless/view-model/types.d.ts +382 -0
  120. package/dist/headless/view-model/types.js +1 -0
  121. package/dist/hooks/use-ai-text.d.ts +1 -1
  122. package/dist/hooks/use-form.d.ts +1 -1
  123. package/dist/hooks/use-form.js +1 -1
  124. package/dist/hooks/use-mutation.d.ts +1 -1
  125. package/dist/hooks/use-query.d.ts +1 -1
  126. package/dist/hooks/use-store.d.ts +1 -1
  127. package/dist/hooks/use-store.js +7 -7
  128. package/dist/hooks/use-stream-handler.d.ts +1 -1
  129. package/dist/i18n-defaults.js +7 -0
  130. package/dist/i18n.d.ts +1 -1
  131. package/dist/i18n.js +1 -1
  132. package/dist/index.d.ts +5 -1
  133. package/dist/index.js +7 -4
  134. package/dist/live/csrf.d.ts +2 -0
  135. package/dist/live/csrf.js +60 -0
  136. package/dist/live/dispatcher-live.d.ts +7 -0
  137. package/dist/live/dispatcher-live.js +286 -0
  138. package/dist/live/envelopes.d.ts +101 -0
  139. package/dist/live/envelopes.js +35 -0
  140. package/dist/live/error-mapping.d.ts +16 -0
  141. package/dist/live/error-mapping.js +82 -0
  142. package/dist/live/index.d.ts +7 -0
  143. package/dist/live/index.js +5 -0
  144. package/dist/live/locale.d.ts +2 -0
  145. package/dist/live/locale.js +25 -0
  146. package/dist/live/sse-stream.d.ts +14 -0
  147. package/dist/live/sse-stream.js +128 -0
  148. package/dist/primitives.d.ts +53 -36
  149. package/dist/primitives.js +1 -1
  150. package/dist/session/session-ended.d.ts +1 -1
  151. package/dist/tokens.d.ts +3 -4
  152. package/dist/tokens.js +4 -5
  153. package/dist/web/app/app-schema-boot.d.ts +19 -0
  154. package/dist/web/app/app-schema-boot.js +124 -0
  155. package/dist/web/app/browser-locale.d.ts +22 -0
  156. package/dist/web/app/browser-locale.js +78 -0
  157. package/dist/web/app/client-plugin.d.ts +106 -0
  158. package/dist/web/app/client-plugin.js +12 -0
  159. package/dist/web/app/create-app.d.ts +104 -0
  160. package/dist/web/app/create-app.js +498 -0
  161. package/dist/web/app/create-public-surface.d.ts +36 -0
  162. package/dist/web/app/create-public-surface.js +40 -0
  163. package/dist/web/app/dashboard-body.d.ts +3 -0
  164. package/dist/web/app/dashboard-body.js +865 -0
  165. package/dist/web/app/dashboard-refresh.d.ts +6 -0
  166. package/dist/web/app/dashboard-refresh.js +15 -0
  167. package/dist/web/app/document-lang-sync.d.ts +4 -0
  168. package/dist/web/app/document-lang-sync.js +27 -0
  169. package/dist/web/app/draft-storage.d.ts +11 -0
  170. package/dist/web/app/draft-storage.js +53 -0
  171. package/dist/web/app/nav-providers-context.d.ts +13 -0
  172. package/dist/web/app/nav-providers-context.js +18 -0
  173. package/dist/web/app/nav.d.ts +40 -0
  174. package/dist/web/app/nav.js +231 -0
  175. package/dist/web/app/plain-content-editor.d.ts +3 -0
  176. package/dist/web/app/plain-content-editor.js +30 -0
  177. package/dist/web/app/relative-time.d.ts +10 -0
  178. package/dist/web/app/relative-time.js +56 -0
  179. package/dist/web/app/resolvers-context.d.ts +12 -0
  180. package/dist/web/app/resolvers-context.js +10 -0
  181. package/dist/web/app/rich-content-editor.d.ts +3 -0
  182. package/dist/web/app/rich-content-editor.js +15 -0
  183. package/dist/web/app/root-error-fallback.d.ts +2 -0
  184. package/dist/web/app/root-error-fallback.js +21 -0
  185. package/dist/web/app/screen-error-fallback.d.ts +6 -0
  186. package/dist/web/app/screen-error-fallback.js +17 -0
  187. package/dist/web/app/tiptap-editor.d.ts +3 -0
  188. package/dist/web/app/tiptap-editor.js +120 -0
  189. package/dist/web/app/toast-action-notifier.d.ts +5 -0
  190. package/dist/web/app/toast-action-notifier.js +17 -0
  191. package/dist/web/components/config-cascade.d.ts +13 -0
  192. package/dist/web/components/config-cascade.js +155 -0
  193. package/dist/web/components/config-source-badge.d.ts +6 -0
  194. package/dist/web/components/config-source-badge.js +55 -0
  195. package/dist/web/default-color-scheme.d.ts +2 -0
  196. package/dist/web/default-color-scheme.js +3 -0
  197. package/dist/web/icons.d.ts +94 -0
  198. package/dist/web/icons.js +100 -0
  199. package/dist/web/index.d.ts +78 -0
  200. package/dist/web/index.js +53 -0
  201. package/dist/web/layout/app-layout.d.ts +21 -0
  202. package/dist/web/layout/app-layout.js +8 -0
  203. package/dist/web/layout/avatar.d.ts +12 -0
  204. package/dist/web/layout/avatar.js +63 -0
  205. package/dist/web/layout/default-app-shell.d.ts +41 -0
  206. package/dist/web/layout/default-app-shell.js +16 -0
  207. package/dist/web/layout/editor-panel.d.ts +10 -0
  208. package/dist/web/layout/editor-panel.js +29 -0
  209. package/dist/web/layout/fill-classes.d.ts +9 -0
  210. package/dist/web/layout/fill-classes.js +15 -0
  211. package/dist/web/layout/filter-app-schema-navs.d.ts +7 -0
  212. package/dist/web/layout/filter-app-schema-navs.js +68 -0
  213. package/dist/web/layout/header-action-group.d.ts +6 -0
  214. package/dist/web/layout/header-action-group.js +8 -0
  215. package/dist/web/layout/header-overflow-menu.d.ts +4 -0
  216. package/dist/web/layout/header-overflow-menu.js +8 -0
  217. package/dist/web/layout/language-menu-items.d.ts +8 -0
  218. package/dist/web/layout/language-menu-items.js +16 -0
  219. package/dist/web/layout/language-switcher.d.ts +25 -0
  220. package/dist/web/layout/language-switcher.js +46 -0
  221. package/dist/web/layout/nav-tree.d.ts +19 -0
  222. package/dist/web/layout/nav-tree.js +536 -0
  223. package/dist/web/layout/page-header-slot.d.ts +25 -0
  224. package/dist/web/layout/page-header-slot.js +50 -0
  225. package/dist/web/layout/profile-menu.d.ts +13 -0
  226. package/dist/web/layout/profile-menu.js +6 -0
  227. package/dist/web/layout/shell-breadcrumb.d.ts +11 -0
  228. package/dist/web/layout/shell-breadcrumb.js +34 -0
  229. package/dist/web/layout/shell-header.d.ts +12 -0
  230. package/dist/web/layout/shell-header.js +159 -0
  231. package/dist/web/layout/sidebar-brand.d.ts +15 -0
  232. package/dist/web/layout/sidebar-brand.js +9 -0
  233. package/dist/web/layout/sidebar-panel.d.ts +41 -0
  234. package/dist/web/layout/sidebar-panel.js +107 -0
  235. package/dist/web/layout/sidebar-user.d.ts +8 -0
  236. package/dist/web/layout/sidebar-user.js +17 -0
  237. package/dist/web/layout/sidebar.d.ts +17 -0
  238. package/dist/web/layout/sidebar.js +11 -0
  239. package/dist/web/layout/target-resolver-stub.d.ts +13 -0
  240. package/dist/web/layout/target-resolver-stub.js +61 -0
  241. package/dist/web/layout/target-url.d.ts +12 -0
  242. package/dist/web/layout/target-url.js +77 -0
  243. package/dist/web/layout/theme-label.d.ts +15 -0
  244. package/dist/web/layout/theme-label.js +35 -0
  245. package/dist/web/layout/theme-menu-item.d.ts +12 -0
  246. package/dist/web/layout/theme-menu-item.js +16 -0
  247. package/dist/web/layout/theme-toggle.d.ts +17 -0
  248. package/dist/web/layout/theme-toggle.js +22 -0
  249. package/dist/web/layout/topbar.d.ts +8 -0
  250. package/dist/web/layout/topbar.js +4 -0
  251. package/dist/web/layout/workspace-shell.d.ts +63 -0
  252. package/dist/web/layout/workspace-shell.js +220 -0
  253. package/dist/web/layout/workspace-switcher.d.ts +15 -0
  254. package/dist/web/layout/workspace-switcher.js +36 -0
  255. package/dist/web/lib/accept-attr.d.ts +1 -0
  256. package/dist/web/lib/accept-attr.js +6 -0
  257. package/dist/web/lib/clamp.d.ts +1 -0
  258. package/dist/web/lib/clamp.js +3 -0
  259. package/dist/web/lib/cn.d.ts +6 -0
  260. package/dist/web/lib/cn.js +9 -0
  261. package/dist/web/lib/download.d.ts +2 -0
  262. package/dist/web/lib/download.js +24 -0
  263. package/dist/web/lib/file-ref-download.d.ts +15 -0
  264. package/dist/web/lib/file-ref-download.js +62 -0
  265. package/dist/web/lib/file-upload-form-data.d.ts +7 -0
  266. package/dist/web/lib/file-upload-form-data.js +11 -0
  267. package/dist/web/lib/resize-image.d.ts +1 -0
  268. package/dist/web/lib/resize-image.js +66 -0
  269. package/dist/web/lib/upload-file-ref.d.ts +9 -0
  270. package/dist/web/lib/upload-file-ref.js +29 -0
  271. package/dist/web/primitives/action-menu.d.ts +34 -0
  272. package/dist/web/primitives/action-menu.js +30 -0
  273. package/dist/web/primitives/calendar-popover.d.ts +13 -0
  274. package/dist/web/primitives/calendar-popover.js +76 -0
  275. package/dist/web/primitives/combobox.d.ts +56 -0
  276. package/dist/web/primitives/combobox.js +127 -0
  277. package/dist/web/primitives/date-field.d.ts +18 -0
  278. package/dist/web/primitives/date-field.js +74 -0
  279. package/dist/web/primitives/date-input.d.ts +1 -0
  280. package/dist/web/primitives/date-input.js +5 -0
  281. package/dist/web/primitives/date-parse.d.ts +11 -0
  282. package/dist/web/primitives/date-parse.js +159 -0
  283. package/dist/web/primitives/dialog.d.ts +3 -0
  284. package/dist/web/primitives/dialog.js +42 -0
  285. package/dist/web/primitives/drawer.d.ts +3 -0
  286. package/dist/web/primitives/drawer.js +17 -0
  287. package/dist/web/primitives/dropdown-menu.d.ts +15 -0
  288. package/dist/web/primitives/dropdown-menu.js +56 -0
  289. package/dist/web/primitives/embedded-list-input.d.ts +9 -0
  290. package/dist/web/primitives/embedded-list-input.js +382 -0
  291. package/dist/web/primitives/file-thumbnail.d.ts +25 -0
  292. package/dist/web/primitives/file-thumbnail.js +90 -0
  293. package/dist/web/primitives/file-upload.d.ts +21 -0
  294. package/dist/web/primitives/file-upload.js +56 -0
  295. package/dist/web/primitives/index.d.ts +34 -0
  296. package/dist/web/primitives/index.js +2021 -0
  297. package/dist/web/primitives/json-view.d.ts +7 -0
  298. package/dist/web/primitives/json-view.js +84 -0
  299. package/dist/web/primitives/layout.d.ts +27 -0
  300. package/dist/web/primitives/layout.js +30 -0
  301. package/dist/web/primitives/lightbox.d.ts +3 -0
  302. package/dist/web/primitives/lightbox.js +36 -0
  303. package/dist/web/primitives/locale-number.d.ts +2 -0
  304. package/dist/web/primitives/locale-number.js +54 -0
  305. package/dist/web/primitives/located-timestamp-input.d.ts +22 -0
  306. package/dist/web/primitives/located-timestamp-input.js +22 -0
  307. package/dist/web/primitives/metric.d.ts +5 -0
  308. package/dist/web/primitives/metric.js +18 -0
  309. package/dist/web/primitives/modal-shell.d.ts +17 -0
  310. package/dist/web/primitives/modal-shell.js +9 -0
  311. package/dist/web/primitives/modal.d.ts +3 -0
  312. package/dist/web/primitives/modal.js +13 -0
  313. package/dist/web/primitives/money-input.d.ts +18 -0
  314. package/dist/web/primitives/money-input.js +122 -0
  315. package/dist/web/primitives/narrow-pinned-footer.d.ts +12 -0
  316. package/dist/web/primitives/narrow-pinned-footer.js +153 -0
  317. package/dist/web/primitives/number-input.d.ts +18 -0
  318. package/dist/web/primitives/number-input.js +53 -0
  319. package/dist/web/primitives/option-groups.d.ts +11 -0
  320. package/dist/web/primitives/option-groups.js +27 -0
  321. package/dist/web/primitives/page-header.d.ts +3 -0
  322. package/dist/web/primitives/page-header.js +52 -0
  323. package/dist/web/primitives/promo-panel.d.ts +3 -0
  324. package/dist/web/primitives/promo-panel.js +11 -0
  325. package/dist/web/primitives/segmented-select.d.ts +21 -0
  326. package/dist/web/primitives/segmented-select.js +62 -0
  327. package/dist/web/primitives/share-actions.d.ts +4 -0
  328. package/dist/web/primitives/share-actions.js +56 -0
  329. package/dist/web/primitives/status-badge.d.ts +3 -0
  330. package/dist/web/primitives/status-badge.js +5 -0
  331. package/dist/web/primitives/sticky-action-bar.d.ts +5 -0
  332. package/dist/web/primitives/sticky-action-bar.js +15 -0
  333. package/dist/web/primitives/tabs.d.ts +3 -0
  334. package/dist/web/primitives/tabs.js +107 -0
  335. package/dist/web/primitives/timestamp-input.d.ts +27 -0
  336. package/dist/web/primitives/timestamp-input.js +87 -0
  337. package/dist/web/primitives/toast.d.ts +19 -0
  338. package/dist/web/primitives/toast.js +63 -0
  339. package/dist/web/primitives/tz-input.d.ts +11 -0
  340. package/dist/web/primitives/tz-input.js +8 -0
  341. package/dist/web/primitives/tz-options.d.ts +4 -0
  342. package/dist/web/primitives/tz-options.js +17 -0
  343. package/dist/web/primitives/use-keyboard-inset.d.ts +1 -0
  344. package/dist/web/primitives/use-keyboard-inset.js +28 -0
  345. package/dist/web/primitives/use-narrow-viewport.d.ts +4 -0
  346. package/dist/web/primitives/use-narrow-viewport.js +46 -0
  347. package/dist/web/react-css-custom-properties.d.ts +6 -0
  348. package/dist/web/react-css-custom-properties.js +1 -0
  349. package/dist/web/sse/live-events.d.ts +15 -0
  350. package/dist/web/sse/live-events.js +148 -0
  351. package/dist/web/theme-plugin.d.ts +41 -0
  352. package/dist/web/theme-plugin.js +123 -0
  353. package/dist/web/tokens.d.ts +24 -0
  354. package/dist/web/tokens.js +203 -0
  355. package/dist/web/ui/avatar.d.ts +11 -0
  356. package/dist/web/ui/avatar.js +25 -0
  357. package/dist/web/ui/badge.d.ts +9 -0
  358. package/dist/web/ui/badge.js +26 -0
  359. package/dist/web/ui/breadcrumb.d.ts +11 -0
  360. package/dist/web/ui/breadcrumb.js +29 -0
  361. package/dist/web/ui/button.d.ts +10 -0
  362. package/dist/web/ui/button.js +37 -0
  363. package/dist/web/ui/checkbox.d.ts +4 -0
  364. package/dist/web/ui/checkbox.js +11 -0
  365. package/dist/web/ui/input.d.ts +3 -0
  366. package/dist/web/ui/input.js +8 -0
  367. package/dist/web/ui/label.d.ts +4 -0
  368. package/dist/web/ui/label.js +10 -0
  369. package/dist/web/ui/resizable.d.ts +7 -0
  370. package/dist/web/ui/resizable.js +16 -0
  371. package/dist/web/ui/separator.d.ts +4 -0
  372. package/dist/web/ui/separator.js +10 -0
  373. package/dist/web/ui/sheet.d.ts +14 -0
  374. package/dist/web/ui/sheet.js +42 -0
  375. package/dist/web/ui/sidebar.d.ts +73 -0
  376. package/dist/web/ui/sidebar.js +211 -0
  377. package/dist/web/ui/skeleton.d.ts +2 -0
  378. package/dist/web/ui/skeleton.js +7 -0
  379. package/dist/web/ui/switch.d.ts +6 -0
  380. package/dist/web/ui/switch.js +10 -0
  381. package/dist/web/ui/table.d.ts +10 -0
  382. package/dist/web/ui/table.js +30 -0
  383. package/dist/web/ui/tabs.d.ts +11 -0
  384. package/dist/web/ui/tabs.js +31 -0
  385. package/dist/web/ui/textarea.d.ts +3 -0
  386. package/dist/web/ui/textarea.js +8 -0
  387. package/dist/web/ui/tooltip.d.ts +7 -0
  388. package/dist/web/ui/tooltip.js +19 -0
  389. package/dist/web/ui/use-mobile.d.ts +1 -0
  390. package/dist/web/ui/use-mobile.js +16 -0
  391. package/dist/web/version/update-checker.d.ts +9 -0
  392. package/dist/web/version/update-checker.js +88 -0
  393. package/dist/web/widgets/ai-text-field.d.ts +36 -0
  394. package/dist/web/widgets/ai-text-field.js +137 -0
  395. package/dist/web/widgets/chart-window.d.ts +58 -0
  396. package/dist/web/widgets/chart-window.js +190 -0
  397. package/dist/web/widgets/charts.d.ts +208 -0
  398. package/dist/web/widgets/charts.js +685 -0
  399. package/dist/web/widgets/collapsible-section.d.ts +10 -0
  400. package/dist/web/widgets/collapsible-section.js +17 -0
  401. package/dist/web/widgets/dashboard-list.d.ts +21 -0
  402. package/dist/web/widgets/dashboard-list.js +45 -0
  403. package/dist/web/widgets/detail-list.d.ts +15 -0
  404. package/dist/web/widgets/detail-list.js +8 -0
  405. package/dist/web/widgets/drawer.d.ts +65 -0
  406. package/dist/web/widgets/drawer.js +142 -0
  407. package/dist/web/widgets/feed-list.d.ts +13 -0
  408. package/dist/web/widgets/feed-list.js +9 -0
  409. package/dist/web/widgets/floating-panel.d.ts +30 -0
  410. package/dist/web/widgets/floating-panel.js +242 -0
  411. package/dist/web/widgets/form-fields.d.ts +93 -0
  412. package/dist/web/widgets/form-fields.js +50 -0
  413. package/dist/web/widgets/index.d.ts +27 -0
  414. package/dist/web/widgets/index.js +30 -0
  415. package/dist/web/widgets/infinity-list.d.ts +46 -0
  416. package/dist/web/widgets/infinity-list.js +211 -0
  417. package/dist/web/widgets/mode-switch.d.ts +21 -0
  418. package/dist/web/widgets/mode-switch.js +25 -0
  419. package/dist/web/widgets/photo-slots.d.ts +29 -0
  420. package/dist/web/widgets/photo-slots.js +52 -0
  421. package/dist/web/widgets/plan-card.d.ts +36 -0
  422. package/dist/web/widgets/plan-card.js +13 -0
  423. package/dist/web/widgets/progress-bar.d.ts +19 -0
  424. package/dist/web/widgets/progress-bar.js +24 -0
  425. package/dist/web/widgets/progress-list.d.ts +19 -0
  426. package/dist/web/widgets/progress-list.js +11 -0
  427. package/dist/web/widgets/public-shell.d.ts +22 -0
  428. package/dist/web/widgets/public-shell.js +15 -0
  429. package/dist/web/widgets/query-table.d.ts +29 -0
  430. package/dist/web/widgets/query-table.js +30 -0
  431. package/dist/web/widgets/result-panel.d.ts +69 -0
  432. package/dist/web/widgets/result-panel.js +30 -0
  433. package/dist/web/widgets/section-card.d.ts +12 -0
  434. package/dist/web/widgets/section-card.js +9 -0
  435. package/dist/web/widgets/sheet-parts.d.ts +9 -0
  436. package/dist/web/widgets/sheet-parts.js +11 -0
  437. package/dist/web/widgets/side-by-side-table.d.ts +31 -0
  438. package/dist/web/widgets/side-by-side-table.js +11 -0
  439. package/dist/web/widgets/stat.d.ts +54 -0
  440. package/dist/web/widgets/stat.js +65 -0
  441. package/dist/web/widgets/states.d.ts +23 -0
  442. package/dist/web/widgets/states.js +20 -0
  443. package/dist/web/widgets/status-badge.d.ts +15 -0
  444. package/dist/web/widgets/status-badge.js +24 -0
  445. package/dist/web/widgets/step-bar.d.ts +35 -0
  446. package/dist/web/widgets/step-bar.js +60 -0
  447. package/dist/web/widgets/upload-zone.d.ts +24 -0
  448. package/dist/web/widgets/upload-zone.js +108 -0
  449. package/dist/web/widgets/use-draft.d.ts +20 -0
  450. package/dist/web/widgets/use-draft.js +21 -0
  451. package/dist/web/widgets/use-pointer-drag.d.ts +21 -0
  452. package/dist/web/widgets/use-pointer-drag.js +53 -0
  453. package/package.json +105 -7
  454. package/src/changes.json +77 -0
  455. package/src/web/fonts/OFL.txt +93 -0
  456. package/src/web/fonts/ibm-plex-mono-latin-400.woff2 +0 -0
  457. package/src/web/fonts/ibm-plex-mono-latin-500.woff2 +0 -0
  458. package/src/web/fonts/ibm-plex-mono-latin-ext-400.woff2 +0 -0
  459. package/src/web/fonts/ibm-plex-mono-latin-ext-500.woff2 +0 -0
  460. package/src/web/fonts/ibm-plex-sans-latin-400.woff2 +0 -0
  461. package/src/web/fonts/ibm-plex-sans-latin-500.woff2 +0 -0
  462. package/src/web/fonts/ibm-plex-sans-latin-600.woff2 +0 -0
  463. package/src/web/fonts/ibm-plex-sans-latin-ext-400.woff2 +0 -0
  464. package/src/web/fonts/ibm-plex-sans-latin-ext-500.woff2 +0 -0
  465. package/src/web/fonts/ibm-plex-sans-latin-ext-600.woff2 +0 -0
  466. package/src/web/styles.css +401 -0
@@ -1,12 +1,12 @@
1
1
  import { useRef, useSyncExternalStore } from "react";
2
- // React-Bindings für Kumikos Store-Primitive (`createStore` aus
3
- // @cosmicdrift/kumiko-headless). Beide Hooks sind dünne Wrapper um React's
4
- // useSyncExternalStore — die ganze Subscribe/Notify-Mechanik lebt im
5
- // Store selbst, hier wird nur React verdrahtet.
2
+ // React bindings for Kumiko's store primitive (`createStore` from
3
+ // @cosmicdrift/kumiko-renderer/headless). Both hooks are thin wrappers around React's
4
+ // useSyncExternalStore — the whole subscribe/notify mechanism lives in the
5
+ // store itself, only React wiring happens here.
6
6
  //
7
- // useStore: gibt den ganzen Snapshot zurück. Re-rendert wenn der
8
- // Store seine Identität wechselt. Object.is-Gate im Store selbst
9
- // verhindert no-op-Updates.
7
+ // useStore: returns the whole snapshot. Re-renders when the store changes
8
+ // its identity. The Object.is gate in the store itself prevents no-op
9
+ // updates.
10
10
  //
11
11
  // useStoreSelector: gibt eine abgeleitete Sicht zurück. Selectors die
12
12
  // Object-/Array-Literale zurückgeben (z.B. `s => ({ a, b })`) erzeugen
@@ -1,4 +1,4 @@
1
- import type { DispatcherError } from "@cosmicdrift/kumiko-headless";
1
+ import type { DispatcherError } from "../headless/index.ts";
2
2
  export type StreamStatus = "idle" | "streaming" | "done" | "error";
3
3
  export type UseStreamHandlerResult<TChunk> = {
4
4
  readonly chunks: readonly TChunk[];
@@ -14,6 +14,7 @@ export const kumikoDefaultTranslations = {
14
14
  "kumiko.actions.delete": "Delete",
15
15
  "kumiko.actions.delete-confirm": "Confirm delete?",
16
16
  "kumiko.actions.reload": "Reload",
17
+ "kumiko.actionForm.success": "Done.",
17
18
  "kumiko.actions.retry": "Try again",
18
19
  "kumiko.actions.create": "New",
19
20
  "kumiko.actions.edit": "Edit",
@@ -39,6 +40,7 @@ export const kumikoDefaultTranslations = {
39
40
  "kumiko.field.locatedTzHint": "Time local to the given location",
40
41
  "kumiko.field.reference-created-no-id": "Record was created but could not be selected automatically. Please select it manually.",
41
42
  "kumiko.field.unsupported": "This field type can't be edited here yet.",
43
+ "kumiko.field.fillAction.failed": "Could not fetch a suggestion.",
42
44
  "kumiko.field.writeOnly.remove": "Remove stored value",
43
45
  "kumiko.field.writeOnly.set": "Set",
44
46
  "kumiko.pii.erased": "Deleted",
@@ -128,6 +130,8 @@ export const kumikoDefaultTranslations = {
128
130
  "kumiko.dashboard.panel.error.isolated": "The other panels are not affected.",
129
131
  "kumiko.dashboard.panel.error.retry": "Try again",
130
132
  "kumiko.dashboard.panel.error.title": "{label} could not be loaded",
133
+ "kumiko.dashboard.progress.unlimited": "unlimited",
134
+ "kumiko.dashboard.record.missing": "Open this page from a record to see its dashboard.",
131
135
  "kumiko.dashboard.time-range": "Time range",
132
136
  "kumiko.screen.unavailable": "This page is not available right now.",
133
137
  "kumiko.dashboard.brush-end": "Window end",
@@ -192,6 +196,9 @@ export const kumikoDefaultTranslations = {
192
196
  "kumiko.aiText.style.expand": "Expand",
193
197
  "kumiko.aiText.capExceeded": "Monthly AI limit reached.",
194
198
  "kumiko.rowAction.failed": "Action failed",
199
+ "kumiko.clientAction.success": "Done.",
200
+ "kumiko.clientAction.unregistered": "This action is not available in this app.",
201
+ "kumiko.clientAction.failed": "The action could not be completed.",
195
202
  "kumiko.contentEditor.insertVariable": "Insert {name}",
196
203
  "kumiko.contentEditor.preview": "Preview",
197
204
  "kumiko.contentEditor.editMode": "Edit",
package/dist/i18n.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { type Formality, type TranslationValue } from "@cosmicdrift/kumiko-framework/ui-types";
2
- import type { LocaleResolver } from "@cosmicdrift/kumiko-headless";
3
2
  import { type ReactNode } from "react";
3
+ import type { LocaleResolver } from "./headless/index.ts";
4
4
  /** Map of i18n key → TranslationValue. Strings may contain `{name}`
5
5
  * placeholders (same semantics as i18next t); plural entries resolve via
6
6
  * `resolveTranslationValue`. */
package/dist/i18n.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  // Locale handling for React consumers of the Kumiko renderer. A thin layer
3
3
  // around the platform-agnostic `LocaleResolver` contract from
4
- // @cosmicdrift/kumiko-headless: provider, hooks, a default no-op resolver,
4
+ // @cosmicdrift/kumiko-renderer/headless: provider, hooks, a default no-op resolver,
5
5
  // and a fallback-bundle merge for feature-supplied translations.
6
6
  //
7
7
  // Architecture:
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@ export { type Formality, formalLocaleTag } from "@cosmicdrift/kumiko-framework/u
2
2
  export { synthesizeActionFormEntity, synthesizeActionFormScreen } from "./app/action-form-shim.ts";
3
3
  export type { AppFeaturesProviderProps } from "./app/app-features-context.tsx";
4
4
  export { AppFeaturesProvider, useAppFeatures } from "./app/app-features-context.tsx";
5
+ export type { ActionNotice, ActionNotifier, ClientActionHandler, ClientActionOutcome, ClientActionRuntime, ClientActionsMap, } from "./app/client-actions.tsx";
6
+ export { ActionNoticeProvider, ClientActionsProvider, runClientAction, useClientActionHandler, useClientActionRuntime, } from "./app/client-actions.tsx";
5
7
  export type { ColumnRendererComponent, ColumnRendererProps, ColumnRenderersMap, ColumnRenderersProviderProps, } from "./app/column-renderers.tsx";
6
8
  export { ColumnRenderersProvider, useColumnRenderer } from "./app/column-renderers.tsx";
7
9
  export type { ContentEditorComponent, ContentEditorProps, ContentEditorsMap, ContentEditorsProviderProps, } from "./app/content-editors.tsx";
@@ -18,6 +20,7 @@ export type { ExtensionSectionComponent, ExtensionSectionProps, ExtensionSection
18
20
  export { ExtensionSectionsProvider, extensionSectionName, useExtensionSectionComponent, } from "./app/extension-sections.tsx";
19
21
  export type { AppSchema, FeatureSchema, QualifiedContentCollection, WorkspaceSchema, } from "./app/feature-schema.ts";
20
22
  export { isAppSchema, toAppSchema } from "./app/feature-schema.ts";
23
+ export { HeaderActionsBar } from "./app/header-actions-bar.tsx";
21
24
  export type { KumikoScreenProps } from "./app/kumiko-screen.tsx";
22
25
  export { KumikoScreen, qualifyNavId, qualifyScreenId, ScreenMissingState, } from "./app/kumiko-screen.tsx";
23
26
  export type { DateRangeBound, DateRangeValue, ResolvedDateRangeFacet } from "./app/list-facets.ts";
@@ -29,6 +32,7 @@ export type { ReturnHost, ReturnTo } from "./app/return-to.tsx";
29
32
  export { navigateToReturn, navigateToReturnOr, navigateWithReturnTo, RETURN_TO_PARAM, ReturnHostProvider, resolveReturnTarget, splitReturnTo, useReturnHost, useReturnTarget, } from "./app/return-to.tsx";
30
33
  export type { EmbeddedScreenTarget } from "./app/use-embedded-screen.ts";
31
34
  export { useEmbeddedScreen } from "./app/use-embedded-screen.ts";
35
+ export { useRecordActions } from "./app/use-record-actions.ts";
32
36
  export type { VariableChipsProps } from "./app/variable-chips.tsx";
33
37
  export { VariableChips } from "./app/variable-chips.tsx";
34
38
  export { evalVisibleWhen, type VisibleWhenVerdict } from "./app/visible-when.ts";
@@ -75,7 +79,7 @@ export { createStaticLocaleResolver, FormalityProvider, LocaleProvider, mergeTra
75
79
  export { kumikoDefaultTranslations } from "./i18n-defaults.ts";
76
80
  export { InsideDrawerProvider, useInsideDrawer } from "./inside-drawer.ts";
77
81
  export { PageHeaderCompactProvider, PageHeaderSlotAvailableProvider, usePageHeaderCompact, usePageHeaderSlotAvailable, } from "./page-header-slot.ts";
78
- export type { ActionMenuItemSpec, ActionOverflowMenuProps, AppPrimitives, BannerProps, ButtonProps, CardOptions, CardProps, CardSlots, CopyButtonProps, CorePrimitives, DataTableDateRangeFacet, DataTableFacet, DataTableFacetChip, DataTableProps, DataTableRowAction, DataTableRowActionMode, DataTableRowGrouping, DataTableSort, DataTableSortDir, DialogProps, DrawerProps, EmbeddedListCellType, EmbeddedListColumn, EmbeddedListInputProps, EmbeddedListTotal, FieldCellWidth, FieldProps, FillContainerProps, FooterActionMarker, FooterActionRole, FormProps, FormSectionNavItem, FormWidth, GridCellProps, GridProps, HeadingProps, InputProps, JsonViewProps, LightboxImage, LightboxProps, LinkProps, MetricBandProps, MetricProps, ModalProps, PageHeaderProps, PickedFile, PrimitivesProviderProps, PrimitivesRegistry, ProgressProps, ProgressTone, PromoPanelAction, PromoPanelProps, RuntimeRenderer, SecretRevealProps, SecretRevealValue, SectionProps, ShareButtonProps, StatusBadgeProps, StatusTone, StepBarProps, StickyActionBarProps, StickyPrimaryActionMarker, TabsProps, TextProps, TrailingInputAction, WizardStepGroupProps, } from "./primitives.tsx";
82
+ export type { ActionMenuItemSpec, ActionOverflowMenuProps, AppPrimitives, BannerProps, ButtonProps, CardOptions, CardProps, CardSlots, CopyButtonProps, CorePrimitives, DataTableDateRangeFacet, DataTableFacet, DataTableFacetChip, DataTableProps, DataTableRowAction, DataTableRowActionMode, DataTableRowGrouping, DataTableSort, DataTableSortDir, DialogProps, DrawerProps, EmbeddedListCellType, EmbeddedListColumn, EmbeddedListInputProps, EmbeddedListTotal, FieldCellWidth, FieldProps, FillContainerProps, FooterActionMarker, FooterActionRole, FormProps, FormSectionNavItem, FormWidth, GridCellProps, GridProps, HeadingProps, InputFillAction, InputProps, JsonViewProps, LightboxImage, LightboxProps, LinkProps, MetricBandProps, MetricProps, ModalProps, PageHeaderProps, PickedFile, PrimitivesProviderProps, PrimitivesRegistry, ProgressProps, ProgressTone, PromoPanelAction, PromoPanelProps, RuntimeRenderer, SecretRevealProps, SecretRevealValue, SectionProps, ShareButtonProps, StatusBadgeProps, StatusTone, StepBarProps, StickyActionBarProps, StickyPrimaryActionMarker, TabsProps, TextProps, TrailingInputAction, WizardStepGroupProps, } from "./primitives.tsx";
79
83
  export { FOOTER_ACTION_ROLE_PROP, NARROW_LABEL_PROP, PrimitivesProvider, STICKY_PRIMARY_ACTION_PROP, shouldRenderActionsIconOnly, statusToneForOptionTone, statusToneForValue, useOptionalPrimitives, usePrimitives, } from "./primitives.tsx";
80
84
  export type { SessionEndedSignal, SessionEndedSignalProviderProps, } from "./session/session-ended.tsx";
81
85
  export { createSessionEndedSignal, isSessionEndedError, SESSION_ENDED_ERROR_CODES, SessionEndedSignalProvider, useSessionEndedSignal, withSessionEndedDetection, } from "./session/session-ended.tsx";
package/dist/index.js CHANGED
@@ -4,13 +4,14 @@
4
4
  // und reichen ihre konkreten Primitives/Nav/SSE-Impls via Provider
5
5
  // in diesen Baum.
6
6
  //
7
- // Wer diesen Layer direkt konsumiert: andere Renderer-Packages
8
- // (@cosmicdrift/kumiko-renderer-web, später -native) oder eine App die ihren
9
- // eigenen Bootstrap schreiben will. Normale Samples gehen über
10
- // @cosmicdrift/kumiko-renderer-web/createKumikoApp, das alle Provider verdrahtet.
7
+ // Direct consumers of this layer: platform bindings
8
+ // (@cosmicdrift/kumiko-renderer/web) or an app writing its own bootstrap.
9
+ // Normal samples go through createKumikoApp from
10
+ // @cosmicdrift/kumiko-renderer/web, which wires all providers.
11
11
  export { formalLocaleTag } from "@cosmicdrift/kumiko-framework/ui-types";
12
12
  export { synthesizeActionFormEntity, synthesizeActionFormScreen } from "./app/action-form-shim.js";
13
13
  export { AppFeaturesProvider, useAppFeatures } from "./app/app-features-context.js";
14
+ export { ActionNoticeProvider, ClientActionsProvider, runClientAction, useClientActionHandler, useClientActionRuntime, } from "./app/client-actions.js";
14
15
  export { ColumnRenderersProvider, useColumnRenderer } from "./app/column-renderers.js";
15
16
  export { CONTENT_EDITOR_ELEMENT_ID, ContentEditorsProvider, TextareaContentEditor, useContentEditor, } from "./app/content-editors.js";
16
17
  export { ContentPreview, substituteVariables } from "./app/content-preview.js";
@@ -19,12 +20,14 @@ export { DashboardBodyProvider, useDashboardBody } from "./app/dashboard-body.js
19
20
  export { ExtensionFormRegistryProvider, useExtensionFormSubmit, } from "./app/extension-form-submit.js";
20
21
  export { ExtensionSectionsProvider, extensionSectionName, useExtensionSectionComponent, } from "./app/extension-sections.js";
21
22
  export { isAppSchema, toAppSchema } from "./app/feature-schema.js";
23
+ export { HeaderActionsBar } from "./app/header-actions-bar.js";
22
24
  export { KumikoScreen, qualifyNavId, qualifyScreenId, ScreenMissingState, } from "./app/kumiko-screen.js";
23
25
  export { buildDateRangePayload, clampDateRange, readDateRange, resolveDateRangeFacets, } from "./app/list-facets.js";
24
26
  export { formatPath, hasDetailScreen, NavProvider, parsePath, resolveTarget, useNav, useNavigateWithInitialValues, useOptionalNav, } from "./app/nav.js";
25
27
  export { lastSegment } from "./app/qn.js";
26
28
  export { navigateToReturn, navigateToReturnOr, navigateWithReturnTo, RETURN_TO_PARAM, ReturnHostProvider, resolveReturnTarget, splitReturnTo, useReturnHost, useReturnTarget, } from "./app/return-to.js";
27
29
  export { useEmbeddedScreen } from "./app/use-embedded-screen.js";
30
+ export { useRecordActions } from "./app/use-record-actions.js";
28
31
  export { VariableChips } from "./app/variable-chips.js";
29
32
  export { evalVisibleWhen } from "./app/visible-when.js";
30
33
  export { dispatcherErrorText, WriteFailedError } from "./app/write-failed-error.js";
@@ -0,0 +1,2 @@
1
+ export declare const CSRF_HEADER_NAME = "X-CSRF-Token";
2
+ export declare function readCsrfToken(cookieSource?: string): string | undefined;
@@ -0,0 +1,60 @@
1
+ // CSRF-token extraction from document.cookie.
2
+ //
3
+ // Kumiko's auth-middleware sets two cookies on login (see Vorarbeit A):
4
+ // - `kumiko_auth` — HttpOnly, carries the JWT. Invisible to JS.
5
+ // - `kumiko_csrf` — JS-readable, carries a random token.
6
+ // Both carry the `__Host-` prefix when the server writes them Secure and
7
+ // without a Domain (see @cosmicdrift/kumiko-types/session-cookies).
8
+ //
9
+ // The double-submit CSRF pattern: every state-changing request echoes the
10
+ // `kumiko_csrf` value into an `X-CSRF-Token` header. Server compares header
11
+ // vs cookie in csrfMiddleware and rejects on mismatch. An attacker on a
12
+ // third-party origin can trigger a cross-site fetch (cookies fly with
13
+ // SameSite=Lax on top-level GETs, or Strict blocks them entirely) but
14
+ // cannot READ `document.cookie` of our origin — so they can't populate the
15
+ // header with the matching value.
16
+ import { CSRF_COOKIE_BASE, sessionCookieNameCandidates, } from "@cosmicdrift/kumiko-types/session-cookies";
17
+ import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
18
+ // Kept here as a literal rather than imported from @cosmicdrift/kumiko-framework because this
19
+ // package must remain server-dep-free (runs in browsers and React Native).
20
+ // The framework's csrf-constants-sync test guards against drift.
21
+ export const CSRF_HEADER_NAME = "X-CSRF-Token";
22
+ const CSRF_COOKIE_NAMES = sessionCookieNameCandidates(CSRF_COOKIE_BASE);
23
+ // Reads the csrf token from document.cookie. Returns undefined when:
24
+ // - `document` isn't available (SSR, Web Worker, React Native)
25
+ // - the cookie was never set (before login, after logout)
26
+ //
27
+ // Callers ALWAYS handle undefined — the request still goes out, the server
28
+ // rejects with csrf_token_missing and the UI surfaces an auth-expired
29
+ // toast. That's the right failure mode: silently skipping the header
30
+ // would hide a broken auth state.
31
+ export function readCsrfToken(cookieSource) {
32
+ const raw = cookieSource ?? readDocumentCookie();
33
+ if (!raw)
34
+ return undefined;
35
+ // cookie format: "a=1; b=2; kumiko_csrf=<uuid>; c=3"
36
+ // Parse by splitting on "; " — cookie values never contain that
37
+ // delimiter literally (they're percent-encoded if needed).
38
+ const valuesByName = new Map();
39
+ for (const pair of raw.split(/;\s*/)) {
40
+ const eq = pair.indexOf("=");
41
+ if (eq < 0)
42
+ continue;
43
+ const name = pair.slice(0, eq);
44
+ if (!valuesByName.has(name))
45
+ valuesByName.set(name, pair.slice(eq + 1));
46
+ }
47
+ for (const name of CSRF_COOKIE_NAMES) {
48
+ const value = valuesByName.get(name);
49
+ if (value !== undefined)
50
+ return value.length > 0 ? decodeURIComponent(value) : undefined;
51
+ }
52
+ return undefined;
53
+ }
54
+ function readDocumentCookie() {
55
+ // Guard for non-browser environments. Avoid `typeof document` on the
56
+ // left so a bundler that const-folds to "document is defined" still
57
+ // compiles — the actual runtime check is what matters.
58
+ const cookie = propertyOf(propertyOf(globalThis, "document"), "cookie");
59
+ return typeof cookie === "string" ? cookie : undefined;
60
+ }
@@ -0,0 +1,7 @@
1
+ import { type Dispatcher } from "../headless/index.ts";
2
+ export type LiveDispatcherOptions = {
3
+ readonly baseUrl?: string;
4
+ readonly fetch?: typeof fetch;
5
+ readonly readCsrf?: () => string | undefined;
6
+ };
7
+ export declare function createLiveDispatcher(options?: LiveDispatcherOptions): Dispatcher;
@@ -0,0 +1,286 @@
1
+ import { propertyOf } from "@cosmicdrift/kumiko-types/type-guards";
2
+ import { createStore, } from "../headless/index.js";
3
+ import { CSRF_HEADER_NAME, readCsrfToken } from "./csrf.js";
4
+ import { batchEnvelopeSchema, errorOnlyEnvelopeSchema, queryEnvelopeSchema, writeEnvelopeSchema, } from "./envelopes.js";
5
+ import { buildAbortError, buildNetworkError, mapServerError } from "./error-mapping.js";
6
+ import { LOCALE_HEADER_NAME, readActiveLocale } from "./locale.js";
7
+ import { iterateSseChunks } from "./sse-stream.js";
8
+ // Paths — matched against the server routes (packages/framework/src/api/routes.ts).
9
+ // Kept as constants so refactors elsewhere (api-constants.ts bumped on the
10
+ // server) flag a mismatch here in a code review instead of at runtime.
11
+ const PATH_WRITE = "/api/write";
12
+ const PATH_QUERY = "/api/query";
13
+ const PATH_BATCH = "/api/batch";
14
+ const PATH_STREAM = "/api/stream";
15
+ export function createLiveDispatcher(options = {}) {
16
+ const baseUrl = options.baseUrl ?? "";
17
+ const readCsrf = options.readCsrf ?? (() => readCsrfToken());
18
+ // Status state — transitions between "online" and "offline" driven
19
+ // purely by call outcomes. "syncing" never fires here (live has
20
+ // nothing to catch up on). Initial "online": optimism — we haven't
21
+ // proven the server is unreachable, and a down-state on boot would
22
+ // show an offline-toast before the user has even clicked anything.
23
+ const statusStore = createStore("online");
24
+ // A status-flip drives network-error → "offline" and any subsequent
25
+ // success → "online". Typed server failures (400, 403, ...) don't flip
26
+ // status — the network reached the server, the server answered, we're
27
+ // online in every operational sense.
28
+ function observeNetworkOutcome(ok) {
29
+ statusStore.setState(ok ? "online" : "offline");
30
+ }
31
+ async function callJson(path, body, signal) {
32
+ const f = options.fetch ?? globalThis.fetch;
33
+ if (!f) {
34
+ return {
35
+ ok: false,
36
+ networkFailure: buildNetworkError("fetch is not available in this runtime — inject via LiveDispatcherOptions.fetch"),
37
+ };
38
+ }
39
+ const headers = {
40
+ "Content-Type": "application/json",
41
+ Accept: "application/json",
42
+ };
43
+ const csrf = readCsrf();
44
+ if (csrf !== undefined)
45
+ headers[CSRF_HEADER_NAME] = csrf;
46
+ const locale = readActiveLocale();
47
+ if (locale !== undefined)
48
+ headers[LOCALE_HEADER_NAME] = locale;
49
+ // If no CSRF token, still send the request — public / pre-login
50
+ // routes like /auth/login don't require CSRF, and POST /write/query/
51
+ // batch against a logged-out client returns 401 via auth-middleware
52
+ // which is a cleaner error than a csrf-mismatch.
53
+ let response;
54
+ try {
55
+ response = await f(`${baseUrl}${path}`, {
56
+ method: "POST",
57
+ credentials: "include",
58
+ headers,
59
+ body: JSON.stringify(body),
60
+ signal,
61
+ });
62
+ }
63
+ catch (e) {
64
+ // Abort surfaces as a DOMException with name="AbortError" in the
65
+ // standard fetch contract. Handle it distinctly so the caller
66
+ // doesn't see the user-cancellation as a network drop.
67
+ if (isAbortError(e)) {
68
+ return { ok: false, networkFailure: buildAbortError() };
69
+ }
70
+ observeNetworkOutcome(false);
71
+ return { ok: false, networkFailure: buildNetworkError(e) };
72
+ }
73
+ observeNetworkOutcome(true);
74
+ // JSON body parse. A server that returned a non-JSON body for any
75
+ // reason (HTML error page from a reverse-proxy, empty body on a
76
+ // weird 502) maps to network-error — structurally the same as a
77
+ // fetch-throw from the UI's perspective.
78
+ let parsed;
79
+ try {
80
+ parsed = await response.json();
81
+ }
82
+ catch (e) {
83
+ return {
84
+ ok: false,
85
+ networkFailure: buildNetworkError(`invalid JSON response (${response.status}): ${e instanceof Error ? e.message : String(e)}`),
86
+ };
87
+ }
88
+ return { ok: true, body: parsed, status: response.status };
89
+ }
90
+ return {
91
+ async write(type, payload, opts) {
92
+ const body = { type, payload };
93
+ // Idempotency by default (#761): without a requestId the server-side
94
+ // dedup never engages and a transport-level double-send duplicates
95
+ // events. Callers with a logical-submit id (savable queue, form
96
+ // controllers) pass their own and keep it across their retries.
97
+ body["requestId"] = opts?.requestId ?? generateRequestId();
98
+ const call = await callJson(PATH_WRITE, body, opts?.signal);
99
+ return normalizeWriteResult(call);
100
+ },
101
+ async query(type, payload, opts) {
102
+ const body = { type, payload };
103
+ const call = await callJson(PATH_QUERY, body, opts?.signal);
104
+ return normalizeQueryResponse(call);
105
+ },
106
+ async batch(commands, opts) {
107
+ const body = { commands };
108
+ // One id for the whole batch — the server caches the BatchResult
109
+ // under it, so a retried batch returns the cached outcome instead of
110
+ // re-executing the commands (#761).
111
+ body["requestId"] = opts?.requestId ?? generateRequestId();
112
+ const call = await callJson(PATH_BATCH, body, opts?.signal);
113
+ return normalizeBatchResponse(call);
114
+ },
115
+ async *stream(type, payload, opts) {
116
+ const f = options.fetch ?? globalThis.fetch;
117
+ if (!f) {
118
+ throw buildNetworkError("fetch is not available in this runtime — inject via LiveDispatcherOptions.fetch");
119
+ }
120
+ const headers = {
121
+ "Content-Type": "application/json",
122
+ Accept: "text/event-stream",
123
+ };
124
+ const csrf = readCsrf();
125
+ if (csrf !== undefined)
126
+ headers[CSRF_HEADER_NAME] = csrf;
127
+ const locale = readActiveLocale();
128
+ if (locale !== undefined)
129
+ headers[LOCALE_HEADER_NAME] = locale;
130
+ let response;
131
+ try {
132
+ response = await f(`${baseUrl}${PATH_STREAM}`, {
133
+ method: "POST",
134
+ credentials: "include",
135
+ headers,
136
+ body: JSON.stringify({ type, payload }),
137
+ signal: opts?.signal,
138
+ });
139
+ }
140
+ catch (e) {
141
+ if (isAbortError(e))
142
+ throw buildAbortError();
143
+ observeNetworkOutcome(false);
144
+ throw buildNetworkError(e);
145
+ }
146
+ observeNetworkOutcome(true);
147
+ const contentType = response.headers.get("content-type") ?? "";
148
+ // Pre-SSE gate failures (PAT deny, etc.) return a normal JSON error
149
+ // envelope — map them like /api/query before trying to read SSE.
150
+ if (!contentType.includes("text/event-stream")) {
151
+ let parsed;
152
+ try {
153
+ parsed = await response.json();
154
+ }
155
+ catch (e) {
156
+ throw buildNetworkError(`invalid stream response (${response.status}): ${e instanceof Error ? e.message : String(e)}`);
157
+ }
158
+ const gateFailure = errorOnlyEnvelopeSchema.safeParse(parsed);
159
+ if (gateFailure.success) {
160
+ throw mapServerErrorWithStatus(gateFailure.data.error, response.status);
161
+ }
162
+ throw buildNetworkError(`unexpected non-SSE stream response (${response.status})`);
163
+ }
164
+ if (!response.body) {
165
+ throw buildNetworkError("stream response has no body");
166
+ }
167
+ try {
168
+ yield* iterateSseChunks(response.body);
169
+ }
170
+ catch (e) {
171
+ // Abort can surface on the initial fetch OR while reading the SSE
172
+ // body — both must map to the same `aborted` envelope so hooks
173
+ // (useStreamHandler) can ignore user-cancel without an error toast.
174
+ if (isAbortError(e) || opts?.signal?.aborted)
175
+ throw buildAbortError();
176
+ observeNetworkOutcome(false);
177
+ throw e;
178
+ }
179
+ },
180
+ statusStore,
181
+ // Live dispatcher has no queue. Returning a constant empty array
182
+ // keeps the contract uniform with savable; UI code that renders
183
+ // pending-badges draws nothing instead of branching on dispatcher
184
+ // type.
185
+ pendingWrites: () => EMPTY_PENDING_WRITES,
186
+ pendingFiles: () => EMPTY_PENDING_FILES,
187
+ };
188
+ }
189
+ const EMPTY_PENDING_WRITES = Object.freeze([]);
190
+ const EMPTY_PENDING_FILES = Object.freeze([]);
191
+ // crypto.randomUUID where available (browser, Bun, Node); Math.random
192
+ // fallback for React-Native runtimes without the WebCrypto polyfill.
193
+ // Uniqueness only needs to hold per user within the server's dedup window —
194
+ // this is an idempotency key, not a security token.
195
+ function generateRequestId() {
196
+ const webCrypto = propertyOf(globalThis, "crypto");
197
+ const randomUUID = propertyOf(webCrypto, "randomUUID");
198
+ if (typeof randomUUID === "function") {
199
+ const id = Reflect.apply(randomUUID, webCrypto, []);
200
+ if (typeof id === "string")
201
+ return id;
202
+ }
203
+ return `req-${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
204
+ }
205
+ function buildUnexpectedShapeError(status) {
206
+ // The server did answer: keep its status so 401/5xx handling still applies.
207
+ return { ...buildNetworkError(`unexpected response shape (${status})`), httpStatus: status };
208
+ }
209
+ // Middleware gates (csrf, origin, auth, rate limits) answer write and batch
210
+ // calls with a bare `{ error }`, without the isSuccess envelope.
211
+ function gateOrShapeError(body, status) {
212
+ const gateFailure = errorOnlyEnvelopeSchema.safeParse(body);
213
+ return gateFailure.success
214
+ ? mapServerErrorWithStatus(gateFailure.data.error, status)
215
+ : buildUnexpectedShapeError(status);
216
+ }
217
+ // Write / Batch share the same envelope: `{ isSuccess: true, data }` on
218
+ // success, `{ isSuccess: false, error: ServerErrorInfo, ... }` on failure.
219
+ // Query uses a different envelope (see normalizeQueryResponse).
220
+ function normalizeWriteResult(call) {
221
+ if (!call.ok)
222
+ return { isSuccess: false, error: call.networkFailure };
223
+ const envelope = writeEnvelopeSchema.safeParse(call.body);
224
+ if (!envelope.success) {
225
+ return { isSuccess: false, error: gateOrShapeError(call.body, call.status) };
226
+ }
227
+ const body = envelope.data;
228
+ if (body.isSuccess)
229
+ return { isSuccess: true, data: body.data };
230
+ return { isSuccess: false, error: mapServerErrorWithStatus(body.error, call.status) };
231
+ }
232
+ function normalizeBatchResponse(call) {
233
+ if (!call.ok) {
234
+ return { isSuccess: false, error: call.networkFailure, failedIndex: -1, results: [] };
235
+ }
236
+ const envelope = batchEnvelopeSchema.safeParse(call.body);
237
+ if (!envelope.success) {
238
+ return {
239
+ isSuccess: false,
240
+ error: gateOrShapeError(call.body, call.status),
241
+ failedIndex: -1,
242
+ results: [],
243
+ };
244
+ }
245
+ const body = envelope.data;
246
+ const results = body.results.map((item) => {
247
+ if (item.isSuccess)
248
+ return { isSuccess: true, data: item.data };
249
+ return { isSuccess: false, error: mapServerErrorWithStatus(item.error, call.status) };
250
+ });
251
+ if (body.isSuccess)
252
+ return { isSuccess: true, results };
253
+ return {
254
+ isSuccess: false,
255
+ error: mapServerErrorWithStatus(body.error, call.status),
256
+ failedIndex: body.failedIndex,
257
+ results,
258
+ };
259
+ }
260
+ // Query envelope: Kumiko's /api/query returns `{ data: ... }` on success
261
+ // (no isSuccess flag) and `{ error: { code, i18nKey, message, ... } }`
262
+ // on failure. Source of truth: packages/framework/src/api/routes.ts:85
263
+ // (the query route handler that emits `c.json({ data: result })`).
264
+ function normalizeQueryResponse(call) {
265
+ if (!call.ok)
266
+ return { isSuccess: false, error: call.networkFailure };
267
+ const envelope = queryEnvelopeSchema.safeParse(call.body);
268
+ if (!envelope.success) {
269
+ return { isSuccess: false, error: buildUnexpectedShapeError(call.status) };
270
+ }
271
+ const body = envelope.data;
272
+ if (body.error) {
273
+ return { isSuccess: false, error: mapServerErrorWithStatus(body.error, call.status) };
274
+ }
275
+ return { isSuccess: true, data: body.data };
276
+ }
277
+ // The HTTP status carries the failure-status; the error body itself
278
+ // doesn't repeat it (serializeError drops httpStatus to keep the wire
279
+ // payload lean). Every envelope has to reinject it from Response.status,
280
+ // otherwise status-based checks like isSessionEndedError never match.
281
+ function mapServerErrorWithStatus(error, responseStatus) {
282
+ return mapServerError({ ...error, httpStatus: error.httpStatus ?? responseStatus });
283
+ }
284
+ function isAbortError(e) {
285
+ return !!e && typeof e === "object" && "name" in e && e.name === "AbortError";
286
+ }
@@ -0,0 +1,101 @@
1
+ import * as z from "zod";
2
+ export declare const serverErrorSchema: z.ZodObject<{
3
+ code: z.ZodString;
4
+ httpStatus: z.ZodOptional<z.ZodNumber>;
5
+ i18nKey: z.ZodDefault<z.ZodString>;
6
+ message: z.ZodString;
7
+ details: z.ZodOptional<z.ZodUnknown>;
8
+ i18nParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
9
+ docsUrl: z.ZodOptional<z.ZodString>;
10
+ requestId: z.ZodOptional<z.ZodString>;
11
+ }, z.core.$strip>;
12
+ export type ServerErrorLike = z.infer<typeof serverErrorSchema>;
13
+ export declare const writeEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
14
+ isSuccess: z.ZodLiteral<true>;
15
+ data: z.ZodOptional<z.ZodUnknown>;
16
+ }, z.core.$strip>, z.ZodObject<{
17
+ isSuccess: z.ZodLiteral<false>;
18
+ error: z.ZodObject<{
19
+ code: z.ZodString;
20
+ httpStatus: z.ZodOptional<z.ZodNumber>;
21
+ i18nKey: z.ZodDefault<z.ZodString>;
22
+ message: z.ZodString;
23
+ details: z.ZodOptional<z.ZodUnknown>;
24
+ i18nParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
25
+ docsUrl: z.ZodOptional<z.ZodString>;
26
+ requestId: z.ZodOptional<z.ZodString>;
27
+ }, z.core.$strip>;
28
+ }, z.core.$strip>], "isSuccess">;
29
+ export declare const batchEnvelopeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
30
+ isSuccess: z.ZodLiteral<true>;
31
+ results: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
32
+ isSuccess: z.ZodLiteral<true>;
33
+ data: z.ZodOptional<z.ZodUnknown>;
34
+ }, z.core.$strip>, z.ZodObject<{
35
+ isSuccess: z.ZodLiteral<false>;
36
+ error: z.ZodObject<{
37
+ code: z.ZodString;
38
+ httpStatus: z.ZodOptional<z.ZodNumber>;
39
+ i18nKey: z.ZodDefault<z.ZodString>;
40
+ message: z.ZodString;
41
+ details: z.ZodOptional<z.ZodUnknown>;
42
+ i18nParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
43
+ docsUrl: z.ZodOptional<z.ZodString>;
44
+ requestId: z.ZodOptional<z.ZodString>;
45
+ }, z.core.$strip>;
46
+ }, z.core.$strip>], "isSuccess">>;
47
+ }, z.core.$strip>, z.ZodObject<{
48
+ isSuccess: z.ZodLiteral<false>;
49
+ error: z.ZodObject<{
50
+ code: z.ZodString;
51
+ httpStatus: z.ZodOptional<z.ZodNumber>;
52
+ i18nKey: z.ZodDefault<z.ZodString>;
53
+ message: z.ZodString;
54
+ details: z.ZodOptional<z.ZodUnknown>;
55
+ i18nParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
56
+ docsUrl: z.ZodOptional<z.ZodString>;
57
+ requestId: z.ZodOptional<z.ZodString>;
58
+ }, z.core.$strip>;
59
+ failedIndex: z.ZodNumber;
60
+ results: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
61
+ isSuccess: z.ZodLiteral<true>;
62
+ data: z.ZodOptional<z.ZodUnknown>;
63
+ }, z.core.$strip>, z.ZodObject<{
64
+ isSuccess: z.ZodLiteral<false>;
65
+ error: z.ZodObject<{
66
+ code: z.ZodString;
67
+ httpStatus: z.ZodOptional<z.ZodNumber>;
68
+ i18nKey: z.ZodDefault<z.ZodString>;
69
+ message: z.ZodString;
70
+ details: z.ZodOptional<z.ZodUnknown>;
71
+ i18nParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
72
+ docsUrl: z.ZodOptional<z.ZodString>;
73
+ requestId: z.ZodOptional<z.ZodString>;
74
+ }, z.core.$strip>;
75
+ }, z.core.$strip>], "isSuccess">>;
76
+ }, z.core.$strip>], "isSuccess">;
77
+ export declare const queryEnvelopeSchema: z.ZodObject<{
78
+ data: z.ZodOptional<z.ZodUnknown>;
79
+ error: z.ZodOptional<z.ZodNullable<z.ZodObject<{
80
+ code: z.ZodString;
81
+ httpStatus: z.ZodOptional<z.ZodNumber>;
82
+ i18nKey: z.ZodDefault<z.ZodString>;
83
+ message: z.ZodString;
84
+ details: z.ZodOptional<z.ZodUnknown>;
85
+ i18nParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
86
+ docsUrl: z.ZodOptional<z.ZodString>;
87
+ requestId: z.ZodOptional<z.ZodString>;
88
+ }, z.core.$strip>>>;
89
+ }, z.core.$strip>;
90
+ export declare const errorOnlyEnvelopeSchema: z.ZodObject<{
91
+ error: z.ZodObject<{
92
+ code: z.ZodString;
93
+ httpStatus: z.ZodOptional<z.ZodNumber>;
94
+ i18nKey: z.ZodDefault<z.ZodString>;
95
+ message: z.ZodString;
96
+ details: z.ZodOptional<z.ZodUnknown>;
97
+ i18nParams: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
98
+ docsUrl: z.ZodOptional<z.ZodString>;
99
+ requestId: z.ZodOptional<z.ZodString>;
100
+ }, z.core.$strip>;
101
+ }, z.core.$strip>;