@miragon/mcp-toolkit-ui 2.7.0 → 2.8.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 (387) hide show
  1. package/README.md +7 -4
  2. package/dist/app/adapt-data-widget.d.ts +1 -22
  3. package/dist/app/adapt-data-widget.d.ts.map +1 -1
  4. package/dist/app/adapt-data-widget.js +1 -35
  5. package/dist/app/adapt-data-widget.js.map +1 -1
  6. package/dist/app/builder/BuilderBanners.js +1 -1
  7. package/dist/app/builder/BuilderBanners.js.map +1 -1
  8. package/dist/app/builder/CanvasRow.d.ts +4 -2
  9. package/dist/app/builder/CanvasRow.d.ts.map +1 -1
  10. package/dist/app/builder/CanvasRow.js +21 -7
  11. package/dist/app/builder/CanvasRow.js.map +1 -1
  12. package/dist/app/builder/CatalogueSheet.d.ts.map +1 -1
  13. package/dist/app/builder/CatalogueSheet.js +11 -4
  14. package/dist/app/builder/CatalogueSheet.js.map +1 -1
  15. package/dist/app/builder/CellPropsSheet.d.ts +7 -3
  16. package/dist/app/builder/CellPropsSheet.d.ts.map +1 -1
  17. package/dist/app/builder/CellPropsSheet.js +10 -3
  18. package/dist/app/builder/CellPropsSheet.js.map +1 -1
  19. package/dist/app/builder/DiscardDialog.d.ts +18 -0
  20. package/dist/app/builder/DiscardDialog.d.ts.map +1 -0
  21. package/dist/app/builder/DiscardDialog.js +18 -0
  22. package/dist/app/builder/DiscardDialog.js.map +1 -0
  23. package/dist/app/builder/LayoutSurface.d.ts +33 -9
  24. package/dist/app/builder/LayoutSurface.d.ts.map +1 -1
  25. package/dist/app/builder/LayoutSurface.js +74 -23
  26. package/dist/app/builder/LayoutSurface.js.map +1 -1
  27. package/dist/app/builder/PipelineStrip.d.ts +2 -1
  28. package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
  29. package/dist/app/builder/PipelineStrip.js +26 -13
  30. package/dist/app/builder/PipelineStrip.js.map +1 -1
  31. package/dist/app/builder/SaveDialog.d.ts +9 -1
  32. package/dist/app/builder/SaveDialog.d.ts.map +1 -1
  33. package/dist/app/builder/SaveDialog.js +8 -2
  34. package/dist/app/builder/SaveDialog.js.map +1 -1
  35. package/dist/app/builder/Toolbar.d.ts +12 -4
  36. package/dist/app/builder/Toolbar.d.ts.map +1 -1
  37. package/dist/app/builder/Toolbar.js +18 -7
  38. package/dist/app/builder/Toolbar.js.map +1 -1
  39. package/dist/app/builder/Workspace.d.ts +23 -3
  40. package/dist/app/builder/Workspace.d.ts.map +1 -1
  41. package/dist/app/builder/Workspace.js +58 -8
  42. package/dist/app/builder/Workspace.js.map +1 -1
  43. package/dist/app/builder/builder-model.d.ts +143 -1
  44. package/dist/app/builder/builder-model.d.ts.map +1 -1
  45. package/dist/app/builder/builder-model.js +191 -1
  46. package/dist/app/builder/builder-model.js.map +1 -1
  47. package/dist/app/builder/reveal.d.ts +10 -0
  48. package/dist/app/builder/reveal.d.ts.map +1 -0
  49. package/dist/app/builder/reveal.js +10 -0
  50. package/dist/app/builder/reveal.js.map +1 -0
  51. package/dist/app/builder/use-builder-catalogue.d.ts +4 -1
  52. package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
  53. package/dist/app/builder/use-builder-catalogue.js +44 -17
  54. package/dist/app/builder/use-builder-catalogue.js.map +1 -1
  55. package/dist/app/builder/use-builder-session.d.ts +30 -0
  56. package/dist/app/builder/use-builder-session.d.ts.map +1 -0
  57. package/dist/app/builder/use-builder-session.js +58 -0
  58. package/dist/app/builder/use-builder-session.js.map +1 -0
  59. package/dist/app/builder/use-display-resolver.d.ts +17 -0
  60. package/dist/app/builder/use-display-resolver.d.ts.map +1 -0
  61. package/dist/app/builder/use-display-resolver.js +16 -0
  62. package/dist/app/builder/use-display-resolver.js.map +1 -0
  63. package/dist/app/index.d.ts +8 -3
  64. package/dist/app/index.d.ts.map +1 -1
  65. package/dist/app/index.js +8 -2
  66. package/dist/app/index.js.map +1 -1
  67. package/dist/app/layout-builder.d.ts +13 -25
  68. package/dist/app/layout-builder.d.ts.map +1 -1
  69. package/dist/app/layout-builder.js +75 -81
  70. package/dist/app/layout-builder.js.map +1 -1
  71. package/dist/app/mcp-app-view-chrome.d.ts +12 -3
  72. package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
  73. package/dist/app/mcp-app-view-chrome.js +21 -5
  74. package/dist/app/mcp-app-view-chrome.js.map +1 -1
  75. package/dist/app/mcp-app-view-states.d.ts +11 -3
  76. package/dist/app/mcp-app-view-states.d.ts.map +1 -1
  77. package/dist/app/mcp-app-view-states.js +29 -8
  78. package/dist/app/mcp-app-view-states.js.map +1 -1
  79. package/dist/app/mcp-app-view.d.ts +33 -1
  80. package/dist/app/mcp-app-view.d.ts.map +1 -1
  81. package/dist/app/mcp-app-view.js +181 -127
  82. package/dist/app/mcp-app-view.js.map +1 -1
  83. package/dist/app/mcp-toolkit-app.d.ts +6 -1
  84. package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
  85. package/dist/app/mcp-toolkit-app.js +8 -1
  86. package/dist/app/mcp-toolkit-app.js.map +1 -1
  87. package/dist/app/mcp-use-host-bridge.d.ts +15 -6
  88. package/dist/app/mcp-use-host-bridge.d.ts.map +1 -1
  89. package/dist/app/mcp-use-host-bridge.js +51 -22
  90. package/dist/app/mcp-use-host-bridge.js.map +1 -1
  91. package/dist/app/model-context.d.ts +71 -0
  92. package/dist/app/model-context.d.ts.map +1 -0
  93. package/dist/app/model-context.js +101 -0
  94. package/dist/app/model-context.js.map +1 -0
  95. package/dist/app/use-build-mode-focus.d.ts +33 -0
  96. package/dist/app/use-build-mode-focus.d.ts.map +1 -0
  97. package/dist/app/use-build-mode-focus.js +59 -0
  98. package/dist/app/use-build-mode-focus.js.map +1 -0
  99. package/dist/app/use-view-actions.d.ts +31 -0
  100. package/dist/app/use-view-actions.d.ts.map +1 -0
  101. package/dist/app/use-view-actions.js +81 -0
  102. package/dist/app/use-view-actions.js.map +1 -0
  103. package/dist/app/use-view-lifecycle.d.ts +4 -0
  104. package/dist/app/use-view-lifecycle.d.ts.map +1 -1
  105. package/dist/app/use-view-lifecycle.js +2 -0
  106. package/dist/app/use-view-lifecycle.js.map +1 -1
  107. package/dist/app/view-lifecycle.d.ts +80 -4
  108. package/dist/app/view-lifecycle.d.ts.map +1 -1
  109. package/dist/app/view-lifecycle.js +90 -3
  110. package/dist/app/view-lifecycle.js.map +1 -1
  111. package/dist/app/widget-fixture.d.ts +10 -3
  112. package/dist/app/widget-fixture.d.ts.map +1 -1
  113. package/dist/app/widget-fixture.js +21 -8
  114. package/dist/app/widget-fixture.js.map +1 -1
  115. package/dist/app/widget-props-sheet.d.ts +3 -1
  116. package/dist/app/widget-props-sheet.d.ts.map +1 -1
  117. package/dist/app/widget-props-sheet.js +22 -10
  118. package/dist/app/widget-props-sheet.js.map +1 -1
  119. package/dist/app/widget-renderer.js +1 -1
  120. package/dist/app/widget-renderer.js.map +1 -1
  121. package/dist/components/DrillButton.d.ts +9 -6
  122. package/dist/components/DrillButton.d.ts.map +1 -1
  123. package/dist/components/DrillButton.js +8 -6
  124. package/dist/components/DrillButton.js.map +1 -1
  125. package/dist/components/EmptyState.d.ts.map +1 -1
  126. package/dist/components/EmptyState.js +4 -2
  127. package/dist/components/EmptyState.js.map +1 -1
  128. package/dist/components/ErrorState.d.ts +5 -2
  129. package/dist/components/ErrorState.d.ts.map +1 -1
  130. package/dist/components/ErrorState.js +25 -8
  131. package/dist/components/ErrorState.js.map +1 -1
  132. package/dist/components/FilterBar.d.ts +15 -4
  133. package/dist/components/FilterBar.d.ts.map +1 -1
  134. package/dist/components/FilterBar.js +11 -6
  135. package/dist/components/FilterBar.js.map +1 -1
  136. package/dist/components/KpiGrid.d.ts +66 -21
  137. package/dist/components/KpiGrid.d.ts.map +1 -1
  138. package/dist/components/KpiGrid.js +101 -34
  139. package/dist/components/KpiGrid.js.map +1 -1
  140. package/dist/components/ListFooter.d.ts +31 -4
  141. package/dist/components/ListFooter.d.ts.map +1 -1
  142. package/dist/components/ListFooter.js +30 -11
  143. package/dist/components/ListFooter.js.map +1 -1
  144. package/dist/components/PagedListFooter.d.ts +57 -0
  145. package/dist/components/PagedListFooter.d.ts.map +1 -0
  146. package/dist/components/PagedListFooter.js +27 -0
  147. package/dist/components/PagedListFooter.js.map +1 -0
  148. package/dist/components/Pills.d.ts +27 -7
  149. package/dist/components/Pills.d.ts.map +1 -1
  150. package/dist/components/Pills.js +21 -6
  151. package/dist/components/Pills.js.map +1 -1
  152. package/dist/components/SectionHeading.d.ts +3 -1
  153. package/dist/components/SectionHeading.d.ts.map +1 -1
  154. package/dist/components/SectionHeading.js +6 -2
  155. package/dist/components/SectionHeading.js.map +1 -1
  156. package/dist/components/Toast.d.ts +9 -3
  157. package/dist/components/Toast.d.ts.map +1 -1
  158. package/dist/components/Toast.js +31 -16
  159. package/dist/components/Toast.js.map +1 -1
  160. package/dist/components/WidgetHeader.d.ts +34 -10
  161. package/dist/components/WidgetHeader.d.ts.map +1 -1
  162. package/dist/components/WidgetHeader.js +11 -6
  163. package/dist/components/WidgetHeader.js.map +1 -1
  164. package/dist/hooks/index.d.ts +4 -4
  165. package/dist/hooks/index.d.ts.map +1 -1
  166. package/dist/hooks/index.js +1 -1
  167. package/dist/hooks/index.js.map +1 -1
  168. package/dist/hooks/tool-result-recovery-model.d.ts +155 -0
  169. package/dist/hooks/tool-result-recovery-model.d.ts.map +1 -0
  170. package/dist/hooks/tool-result-recovery-model.js +273 -0
  171. package/dist/hooks/tool-result-recovery-model.js.map +1 -0
  172. package/dist/hooks/use-tool-query.d.ts +56 -14
  173. package/dist/hooks/use-tool-query.d.ts.map +1 -1
  174. package/dist/hooks/use-tool-query.js +102 -25
  175. package/dist/hooks/use-tool-query.js.map +1 -1
  176. package/dist/hooks/use-tool-result-recovery.d.ts +47 -52
  177. package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
  178. package/dist/hooks/use-tool-result-recovery.js +58 -120
  179. package/dist/hooks/use-tool-result-recovery.js.map +1 -1
  180. package/dist/hooks/use-view-data.d.ts +52 -10
  181. package/dist/hooks/use-view-data.d.ts.map +1 -1
  182. package/dist/hooks/use-view-data.js +81 -16
  183. package/dist/hooks/use-view-data.js.map +1 -1
  184. package/dist/hooks/use-view-tool-query.d.ts +12 -7
  185. package/dist/hooks/use-view-tool-query.d.ts.map +1 -1
  186. package/dist/hooks/use-view-tool-query.js +15 -14
  187. package/dist/hooks/use-view-tool-query.js.map +1 -1
  188. package/dist/index.d.ts +17 -10
  189. package/dist/index.d.ts.map +1 -1
  190. package/dist/index.js +18 -6
  191. package/dist/index.js.map +1 -1
  192. package/dist/lib/focus-return.d.ts +61 -0
  193. package/dist/lib/focus-return.d.ts.map +1 -0
  194. package/dist/lib/focus-return.js +46 -0
  195. package/dist/lib/focus-return.js.map +1 -0
  196. package/dist/lib/parse-tool-result.d.ts +23 -1
  197. package/dist/lib/parse-tool-result.d.ts.map +1 -1
  198. package/dist/lib/parse-tool-result.js +38 -2
  199. package/dist/lib/parse-tool-result.js.map +1 -1
  200. package/dist/lib/toast-model.d.ts +41 -1
  201. package/dist/lib/toast-model.d.ts.map +1 -1
  202. package/dist/lib/toast-model.js +67 -1
  203. package/dist/lib/toast-model.js.map +1 -1
  204. package/dist/lib/tone-utils.d.ts +58 -6
  205. package/dist/lib/tone-utils.d.ts.map +1 -1
  206. package/dist/lib/tone-utils.js +66 -4
  207. package/dist/lib/tone-utils.js.map +1 -1
  208. package/dist/lib/tool-query.d.ts +107 -0
  209. package/dist/lib/tool-query.d.ts.map +1 -0
  210. package/dist/lib/tool-query.js +182 -0
  211. package/dist/lib/tool-query.js.map +1 -0
  212. package/dist/lib/tool-result-observer.d.ts +108 -0
  213. package/dist/lib/tool-result-observer.d.ts.map +1 -0
  214. package/dist/lib/tool-result-observer.js +158 -0
  215. package/dist/lib/tool-result-observer.js.map +1 -0
  216. package/dist/lib/typography.d.ts +37 -0
  217. package/dist/lib/typography.d.ts.map +1 -0
  218. package/dist/lib/typography.js +41 -0
  219. package/dist/lib/typography.js.map +1 -0
  220. package/dist/lib/utils.d.ts.map +1 -1
  221. package/dist/lib/utils.js +11 -1
  222. package/dist/lib/utils.js.map +1 -1
  223. package/dist/locale/index.d.ts +1 -1
  224. package/dist/locale/index.d.ts.map +1 -1
  225. package/dist/locale/message-types.d.ts +117 -4
  226. package/dist/locale/message-types.d.ts.map +1 -1
  227. package/dist/locale/messages-de.d.ts.map +1 -1
  228. package/dist/locale/messages-de.js +44 -10
  229. package/dist/locale/messages-de.js.map +1 -1
  230. package/dist/locale/messages-en.d.ts.map +1 -1
  231. package/dist/locale/messages-en.js +44 -10
  232. package/dist/locale/messages-en.js.map +1 -1
  233. package/dist/locale/toolkit-messages.d.ts +19 -1
  234. package/dist/locale/toolkit-messages.d.ts.map +1 -1
  235. package/dist/locale/toolkit-messages.js +54 -1
  236. package/dist/locale/toolkit-messages.js.map +1 -1
  237. package/dist/primitives/alert.d.ts +1 -1
  238. package/dist/primitives/alert.d.ts.map +1 -1
  239. package/dist/primitives/alert.js +2 -0
  240. package/dist/primitives/alert.js.map +1 -1
  241. package/dist/primitives/badge.d.ts +1 -1
  242. package/dist/primitives/badge.d.ts.map +1 -1
  243. package/dist/primitives/badge.js +9 -4
  244. package/dist/primitives/badge.js.map +1 -1
  245. package/dist/primitives/button.d.ts +1 -1
  246. package/dist/primitives/button.js +1 -1
  247. package/dist/primitives/button.js.map +1 -1
  248. package/dist/primitives/dialog.d.ts +1 -1
  249. package/dist/primitives/dialog.d.ts.map +1 -1
  250. package/dist/primitives/dialog.js +10 -3
  251. package/dist/primitives/dialog.js.map +1 -1
  252. package/dist/primitives/select.js +1 -1
  253. package/dist/primitives/select.js.map +1 -1
  254. package/dist/primitives/sheet.d.ts +1 -1
  255. package/dist/primitives/sheet.d.ts.map +1 -1
  256. package/dist/primitives/sheet.js +6 -2
  257. package/dist/primitives/sheet.js.map +1 -1
  258. package/dist/providers/query-provider.d.ts +32 -1
  259. package/dist/providers/query-provider.d.ts.map +1 -1
  260. package/dist/providers/query-provider.js +53 -4
  261. package/dist/providers/query-provider.js.map +1 -1
  262. package/dist/render-cases-primitives.js +1 -1
  263. package/dist/render-cases-primitives.js.map +1 -1
  264. package/dist/render-cases.d.ts.map +1 -1
  265. package/dist/render-cases.js +30 -6
  266. package/dist/render-cases.js.map +1 -1
  267. package/dist/render-effects.d.ts +42 -0
  268. package/dist/render-effects.d.ts.map +1 -0
  269. package/dist/render-effects.js +81 -0
  270. package/dist/render-effects.js.map +1 -0
  271. package/dist/theme/create-theme.d.ts +19 -1
  272. package/dist/theme/create-theme.d.ts.map +1 -1
  273. package/dist/theme/create-theme.js +15 -0
  274. package/dist/theme/create-theme.js.map +1 -1
  275. package/package.json +5 -4
  276. package/src/app/adapt-data-widget.tsx +2 -42
  277. package/src/app/builder/BuilderBanners.tsx +1 -1
  278. package/src/app/builder/CanvasRow.tsx +63 -17
  279. package/src/app/builder/CatalogueSheet.tsx +50 -29
  280. package/src/app/builder/CellPropsSheet.tsx +17 -2
  281. package/src/app/builder/DiscardDialog.tsx +59 -0
  282. package/src/app/builder/LayoutSurface.tsx +206 -66
  283. package/src/app/builder/PipelineStrip.tsx +253 -153
  284. package/src/app/builder/SaveDialog.tsx +14 -2
  285. package/src/app/builder/Toolbar.tsx +144 -59
  286. package/src/app/builder/Workspace.tsx +226 -58
  287. package/src/app/builder/builder-model.ts +341 -2
  288. package/src/app/builder/builder-model.ux.test.ts +456 -0
  289. package/src/app/builder/builder-ux.test.tsx +844 -0
  290. package/src/app/builder/reveal.ts +10 -0
  291. package/src/app/builder/use-builder-catalogue.ts +56 -19
  292. package/src/app/builder/use-builder-session.ts +68 -0
  293. package/src/app/builder/use-display-resolver.ts +24 -0
  294. package/src/app/index.ts +12 -2
  295. package/src/app/layout-builder.tsx +178 -191
  296. package/src/app/mcp-app-view-chrome.test.tsx +141 -1
  297. package/src/app/mcp-app-view-chrome.tsx +56 -6
  298. package/src/app/mcp-app-view-states.tsx +51 -11
  299. package/src/app/mcp-app-view.effects.test.tsx +292 -0
  300. package/src/app/mcp-app-view.test.tsx +222 -2
  301. package/src/app/mcp-app-view.tsx +267 -117
  302. package/src/app/mcp-toolkit-app.test.tsx +40 -0
  303. package/src/app/mcp-toolkit-app.tsx +8 -1
  304. package/src/app/mcp-use-host-bridge.test.tsx +180 -0
  305. package/src/app/mcp-use-host-bridge.tsx +67 -24
  306. package/src/app/model-context.test.tsx +116 -0
  307. package/src/app/model-context.tsx +125 -0
  308. package/src/app/use-build-mode-focus.ts +62 -0
  309. package/src/app/use-view-actions.ts +89 -0
  310. package/src/app/use-view-lifecycle.ts +6 -0
  311. package/src/app/view-lifecycle.test.ts +216 -0
  312. package/src/app/view-lifecycle.ts +165 -5
  313. package/src/app/widget-fixture.effects.test.tsx +51 -0
  314. package/src/app/widget-fixture.render.test.tsx +81 -0
  315. package/src/app/widget-fixture.tsx +34 -11
  316. package/src/app/widget-props-sheet.tsx +57 -16
  317. package/src/app/widget-renderer.tsx +1 -1
  318. package/src/components/DrillButton.tsx +23 -10
  319. package/src/components/EmptyState.tsx +6 -4
  320. package/src/components/ErrorState.tsx +31 -9
  321. package/src/components/FilterBar.test.tsx +82 -0
  322. package/src/components/FilterBar.tsx +52 -26
  323. package/src/components/KpiGrid.test.tsx +279 -0
  324. package/src/components/KpiGrid.tsx +297 -90
  325. package/src/components/ListFooter.test.tsx +116 -0
  326. package/src/components/ListFooter.tsx +102 -15
  327. package/src/components/PagedListFooter.test.tsx +140 -0
  328. package/src/components/PagedListFooter.tsx +107 -0
  329. package/src/components/Pills.test.tsx +77 -0
  330. package/src/components/Pills.tsx +63 -10
  331. package/src/components/SectionHeading.tsx +9 -3
  332. package/src/components/Toast.tsx +37 -19
  333. package/src/components/WidgetHeader.test.tsx +78 -0
  334. package/src/components/WidgetHeader.tsx +63 -16
  335. package/src/components/feedback-states.test.tsx +98 -9
  336. package/src/components/tone-figures.test.tsx +8 -4
  337. package/src/hooks/index.ts +6 -3
  338. package/src/hooks/tool-result-recovery-model.test.ts +744 -0
  339. package/src/hooks/tool-result-recovery-model.ts +418 -0
  340. package/src/hooks/use-tool-query.effects.test.tsx +205 -0
  341. package/src/hooks/use-tool-query.ts +156 -33
  342. package/src/hooks/use-tool-result-recovery.effects.test.tsx +141 -0
  343. package/src/hooks/use-tool-result-recovery.test.ts +3 -4
  344. package/src/hooks/use-tool-result-recovery.ts +84 -142
  345. package/src/hooks/use-view-data.test.tsx +118 -9
  346. package/src/hooks/use-view-data.ts +128 -18
  347. package/src/hooks/use-view-tool-query.ts +25 -19
  348. package/src/i18n-coverage.test.tsx +104 -2
  349. package/src/index.ts +48 -11
  350. package/src/lib/focus-return.test.ts +288 -0
  351. package/src/lib/focus-return.ts +96 -0
  352. package/src/lib/parse-tool-result.test.ts +46 -1
  353. package/src/lib/parse-tool-result.ts +40 -2
  354. package/src/lib/toast-model.test.ts +166 -1
  355. package/src/lib/toast-model.ts +104 -2
  356. package/src/lib/tone-utils.test.ts +86 -10
  357. package/src/lib/tone-utils.ts +89 -8
  358. package/src/lib/tool-query.test.ts +569 -0
  359. package/src/lib/tool-query.ts +253 -0
  360. package/src/lib/tool-result-observer.test.ts +296 -0
  361. package/src/lib/tool-result-observer.ts +211 -0
  362. package/src/lib/typography.test.ts +45 -0
  363. package/src/lib/typography.ts +47 -0
  364. package/src/lib/utils.ts +12 -1
  365. package/src/locale/index.ts +1 -0
  366. package/src/locale/message-types.ts +118 -2
  367. package/src/locale/messages-de.ts +49 -10
  368. package/src/locale/messages-en.ts +49 -10
  369. package/src/locale/toolkit-messages.test.ts +133 -0
  370. package/src/locale/toolkit-messages.ts +63 -2
  371. package/src/primitives/alert.tsx +3 -0
  372. package/src/primitives/badge.tsx +9 -4
  373. package/src/primitives/button.tsx +1 -1
  374. package/src/primitives/dialog.tsx +10 -1
  375. package/src/primitives/select.tsx +1 -1
  376. package/src/primitives/sheet.tsx +7 -0
  377. package/src/providers/query-provider.test.tsx +154 -0
  378. package/src/providers/query-provider.tsx +66 -5
  379. package/src/render-cases-primitives.tsx +1 -1
  380. package/src/render-cases.tsx +38 -6
  381. package/src/render-effects.tsx +96 -0
  382. package/src/theme/cd-tokens.test.ts +3 -1
  383. package/src/theme/create-theme.test.ts +10 -0
  384. package/src/theme/create-theme.ts +28 -0
  385. package/src/theme/theme-css.test.ts +51 -0
  386. package/src/theme.css +31 -1
  387. package/ui-catalog.json +448 -41
@@ -1,31 +1,32 @@
1
+ import { QueryClient } from "@tanstack/react-query"
1
2
  import { renderToStaticMarkup } from "react-dom/server"
2
3
  import { describe, expect, it, vi } from "vitest"
4
+ import { toolQueryKey } from "../lib/tool-query.js"
3
5
  import { AppQueryProvider } from "../providers/query-provider.js"
4
- import { useViewData, type ViewDataResult } from "./use-view-data.js"
6
+ import { useViewData, type UseViewDataOptions, type ViewDataResult } from "./use-view-data.js"
5
7
 
6
8
  type Demo = { n: number }
7
9
  type CallTool = (name: string, args: object) => Promise<unknown>
8
10
 
11
+ const KEY = ["use-view-data.test"] as const
12
+ const ARGS = { id: 1 }
13
+
9
14
  /** Renders a probe once (SSR, the house path) and hands back the hook's result. */
10
15
  function probe(
11
16
  initialData: Demo | null,
12
17
  ready: boolean,
13
18
  callTool: CallTool,
14
19
  key: string,
20
+ options?: UseViewDataOptions<Demo> & { client?: QueryClient; toolNameInQueryKey?: boolean },
15
21
  ): ViewDataResult<Demo> {
16
22
  let result: ViewDataResult<Demo> | undefined
23
+ const { client, toolNameInQueryKey, ...hookOptions } = options ?? {}
17
24
  function Probe() {
18
- result = useViewData<Demo>(
19
- initialData,
20
- ["use-view-data.test", key],
21
- "demo_data",
22
- { id: 1 },
23
- ready,
24
- )
25
+ result = useViewData<Demo>(initialData, [...KEY, key], "demo_data", ARGS, ready, hookOptions)
25
26
  return null
26
27
  }
27
28
  renderToStaticMarkup(
28
- <AppQueryProvider callTool={callTool}>
29
+ <AppQueryProvider callTool={callTool} client={client} toolNameInQueryKey={toolNameInQueryKey}>
29
30
  <Probe />
30
31
  </AppQueryProvider>,
31
32
  )
@@ -48,6 +49,16 @@ describe("useViewData", () => {
48
49
  expect(result).toMatchObject({ data: null, loading: false, error: null })
49
50
  })
50
51
 
52
+ it("exposes the query's progress: failureCount, failureReason, isFetching, isPlaceholderData", () => {
53
+ const result = probe(null, false, vi.fn<CallTool>(), "progress")
54
+ expect(result).toMatchObject({
55
+ failureCount: 0,
56
+ failureReason: null,
57
+ isFetching: false,
58
+ isPlaceholderData: false,
59
+ })
60
+ })
61
+
51
62
  it("refetch calls the tool again: the retry an error state offers", async () => {
52
63
  const callTool = vi.fn<CallTool>(() => Promise.resolve({ structuredContent: { n: 2 } }))
53
64
  const result = probe(null, false, callTool, "refetch")
@@ -57,4 +68,102 @@ describe("useViewData", () => {
57
68
  expect(callTool).toHaveBeenCalledWith("demo_data", { id: 1 })
58
69
  })
59
70
  })
71
+
72
+ it("enabled: false gates the feed next to ready; a ready feed without data is loading", () => {
73
+ const client = new QueryClient()
74
+ expect(probe(null, true, vi.fn<CallTool>(), "gated", { client, enabled: false }).loading).toBe(
75
+ false,
76
+ )
77
+ expect(probe(null, true, vi.fn<CallTool>(), "open", { client }).loading).toBe(true)
78
+ })
79
+
80
+ it("a function gate that says no idles like enabled: false, never an endless skeleton", () => {
81
+ const client = new QueryClient()
82
+ const closed = probe(null, true, vi.fn<CallTool>(), "fn-closed", {
83
+ client,
84
+ enabled: () => false,
85
+ })
86
+ expect(closed).toMatchObject({ data: null, loading: false, error: null })
87
+ const open = probe(null, true, vi.fn<CallTool>(), "fn-open", { client, enabled: () => true })
88
+ expect(open.loading).toBe(true)
89
+ // Not ready keeps it off whatever the gate says.
90
+ expect(
91
+ probe(null, false, vi.fn<CallTool>(), "fn-not-ready", { client, enabled: () => true })
92
+ .loading,
93
+ ).toBe(false)
94
+ })
95
+
96
+ it("passes TanStack's options through: initialData-free placeholderData shows meanwhile", () => {
97
+ const client = new QueryClient()
98
+ const result = probe(null, true, vi.fn<CallTool>(), "placeholder", {
99
+ client,
100
+ placeholderData: { n: 0 },
101
+ })
102
+ expect(result).toMatchObject({ data: { n: 0 }, isPlaceholderData: true, loading: false })
103
+ })
104
+ })
105
+
106
+ describe('useViewData initialDataMode: "seed" (the live standalone view)', () => {
107
+ const cacheKey = (key: string) => toolQueryKey([...KEY, key], "demo_data", ARGS)
108
+
109
+ it("seeds the feed's cache entry with the host's payload and returns it", () => {
110
+ const client = new QueryClient()
111
+ const result = probe({ n: 1 }, true, vi.fn<CallTool>(), "seeded", {
112
+ client,
113
+ initialDataMode: "seed",
114
+ initialDataUpdatedAt: 1234,
115
+ })
116
+ expect(result).toMatchObject({ data: { n: 1 }, loading: false })
117
+ expect(client.getQueryData(cacheKey("seeded"))).toEqual({ n: 1 })
118
+ expect(client.getQueryState(cacheKey("seeded"))?.dataUpdatedAt).toBe(1234)
119
+ })
120
+
121
+ it("with toolNameInQueryKey the seed lands under the key carrying the tool name", () => {
122
+ const client = new QueryClient()
123
+ const result = probe({ n: 1 }, true, vi.fn<CallTool>(), "tool-key", {
124
+ client,
125
+ initialDataMode: "seed",
126
+ toolNameInQueryKey: true,
127
+ })
128
+ expect(result.data).toEqual({ n: 1 })
129
+ expect(client.getQueryData([...KEY, "tool-key", "demo_data", ARGS])).toEqual({ n: 1 })
130
+ expect(client.getQueryData(cacheKey("tool-key")), "never the 2.x key").toBeUndefined()
131
+ })
132
+
133
+ it("static mode never writes the cache", () => {
134
+ const client = new QueryClient()
135
+ probe({ n: 1 }, true, vi.fn<CallTool>(), "static", { client })
136
+ expect(client.getQueryData(cacheKey("static"))).toBeUndefined()
137
+ })
138
+
139
+ it("the cached answer wins over the seed it came from once the feed answered anew", () => {
140
+ const client = new QueryClient()
141
+ probe({ n: 1 }, true, vi.fn<CallTool>(), "refetched", { client, initialDataMode: "seed" })
142
+ client.setQueryData(cacheKey("refetched"), { n: 2 })
143
+ const remounted = probe({ n: 1 }, true, vi.fn<CallTool>(), "refetched", {
144
+ client,
145
+ initialDataMode: "seed",
146
+ initialDataUpdatedAt: () => 99,
147
+ })
148
+ expect(remounted.data, "an old payload never rolls the answer back").toEqual({ n: 2 })
149
+ const delivered = probe({ n: 3 }, true, vi.fn<CallTool>(), "refetched", {
150
+ client,
151
+ initialDataMode: "seed",
152
+ })
153
+ expect(delivered.data, "a new delivery wins").toEqual({ n: 3 })
154
+ })
155
+
156
+ it("refetch over a seeded entry reads the feed again", async () => {
157
+ const client = new QueryClient()
158
+ const callTool = vi.fn<CallTool>(() => Promise.resolve({ structuredContent: { n: 2 } }))
159
+ const result = probe({ n: 1 }, true, callTool, "seed-refetch", {
160
+ client,
161
+ initialDataMode: "seed",
162
+ })
163
+ result.refetch()
164
+ await vi.waitFor(() => {
165
+ expect(client.getQueryData(cacheKey("seed-refetch"))).toEqual({ n: 2 })
166
+ })
167
+ expect(callTool).toHaveBeenCalledWith("demo_data", ARGS)
168
+ })
60
169
  })
@@ -1,5 +1,7 @@
1
- import { useCallback } from "react"
2
- import { useToolQuery } from "./use-tool-query.js"
1
+ import { useCallback, useState } from "react"
2
+ import { hashKey, useQueryClient } from "@tanstack/react-query"
3
+ import { seedToolQuery, type UseToolQueryOptions } from "../lib/tool-query.js"
4
+ import { useToolQuery, useToolQueryKey } from "./use-tool-query.js"
3
5
 
4
6
  export interface ViewDataResult<T> {
5
7
  data: T | null
@@ -7,23 +9,66 @@ export interface ViewDataResult<T> {
7
9
  loading: boolean
8
10
  error: Error | null
9
11
  /**
10
- * Fetch `tool` again: the retry of an error state
11
- * (`<ErrorState onRetry={refetch} … />`). Host-pushed data, when present,
12
- * stays what `data` returns.
12
+ * Fetch `tool` again now: the retry of an error state
13
+ * (`<ErrorState onRetry={refetch} … />`) or a manual refresh — a new read
14
+ * even while a failed fetch still waits on its retry backoff. In `"static"`
15
+ * mode host-pushed data, when present, stays what `data` returns.
13
16
  */
14
17
  refetch: () => void
18
+ /** Failed attempts of the current fetch (0 once it succeeds). */
19
+ failureCount: number
20
+ /**
21
+ * The current fetch's last failed attempt — set from the first failure on,
22
+ * while the query still retries (`error` waits for the last retry).
23
+ */
24
+ failureReason: Error | null
25
+ /** A fetch is in flight (the first one or a refetch). */
26
+ isFetching: boolean
27
+ /**
28
+ * `data` is a placeholder (`placeholderData`, e.g. `keepPreviousData`):
29
+ * the previous args' answer while the current args' fetch runs or failed.
30
+ */
31
+ isPlaceholderData: boolean
32
+ }
33
+
34
+ /**
35
+ * How {@link useViewData} treats host-pushed `initialData`.
36
+ *
37
+ * - `"static"` (default): returned verbatim; the feed query stays off while
38
+ * it is present.
39
+ * - `"seed"`: it becomes the feed query's cached answer, and the query stays
40
+ * live (once `ready`): an invalidation after a write, a `refetch` or a
41
+ * retry re-reads the feed. A fresh seed is not refetched on mount (it is
42
+ * younger than `staleTime`); a payload delivered anew (content not seeded
43
+ * for the key before) replaces the cached answer, while a re-rendered or
44
+ * remounted old one never rolls a refetched answer back.
45
+ */
46
+ export type ViewDataMode = "static" | "seed"
47
+
48
+ /**
49
+ * Options of {@link useViewData}: TanStack's query options for the feed
50
+ * (`retry`, `retryDelay`, `staleTime`, `placeholderData` /
51
+ * `keepPreviousData`, `enabled` as an extra gate next to `ready`, …),
52
+ * plus how host data seeds it.
53
+ */
54
+ export type UseViewDataOptions<T> = Omit<UseToolQueryOptions<T>, "initialData" | "select"> & {
55
+ initialDataMode?: ViewDataMode
15
56
  }
16
57
 
17
58
  /**
18
59
  * The seam that lets one widget component serve both modes without a duplicate UI.
19
60
  *
20
61
  * Standalone (a `*_show_*` widget) the agent's tool result is handed in via
21
- * `initialData` (from the view's stepData, e.g. through `adaptDataWidget`) and
22
- * returned verbatim. Embedded in a self-fetching cockpit only scope params are
23
- * passed, so the component fetches `tool` with `args` under `key` — disabled
24
- * unless data is absent AND `ready` (i.e. the required id/key is present).
25
- * Sibling widgets sharing `key` dedupe to a single call, so a composed view of
26
- * N widgets over one data feed fetches once.
62
+ * `initialData` (from the view's stepData, e.g. through `adaptDataWidget`).
63
+ * Embedded in a self-fetching cockpit only scope params are passed, so the
64
+ * component fetches `tool` with `args` under `key`, gated on `ready` (i.e.
65
+ * the required id/key is present). Sibling widgets sharing `key` and `args`
66
+ * dedupe to a single call, so a composed view of N widgets over one data
67
+ * feed fetches once.
68
+ *
69
+ * By default host data is returned verbatim and switches the query off;
70
+ * `initialDataMode: "seed"` keeps the query live over it instead (see
71
+ * {@link ViewDataMode}). `options` passes TanStack's query options through.
27
72
  */
28
73
  export function useViewData<T>(
29
74
  initialData: T | null | undefined,
@@ -31,12 +76,77 @@ export function useViewData<T>(
31
76
  tool: string,
32
77
  args: Record<string, unknown>,
33
78
  ready: boolean,
79
+ options?: UseViewDataOptions<T>,
34
80
  ): ViewDataResult<T> {
35
- const query = useToolQuery<T>([...key], tool, args, { enabled: !initialData && ready })
36
- const data = initialData ?? query.data ?? null
37
- const { refetch: refetchQuery } = query
38
- const refetch = useCallback(() => {
39
- void refetchQuery()
40
- }, [refetchQuery])
41
- return { data, loading: !data && ready && !query.isError, error: query.error ?? null, refetch }
81
+ const { initialDataMode = "static", enabled, ...queryOptions } = options ?? {}
82
+ const seeding = initialDataMode === "seed"
83
+ const cacheKey = useStableKey(useToolQueryKey(key, tool, args))
84
+ useSeed(seeding ? initialData : null, cacheKey, queryOptions.initialDataUpdatedAt)
85
+
86
+ const active = ready && enabled !== false
87
+ const fetches = active && (seeding || !initialData)
88
+ const query = useToolQuery<T>([...key], tool, args, {
89
+ ...queryOptions,
90
+ enabled: typeof enabled === "function" ? (q) => fetches && enabled(q) : fetches,
91
+ })
92
+ const data = seeding ? (query.data ?? initialData) : (initialData ?? query.data)
93
+ const refetch = useFreshRefetch(cacheKey, query.refetch)
94
+ return {
95
+ data: data ?? null,
96
+ // The query's own verdict: a function `enabled` that returns false idles
97
+ // like `enabled: false`, never an endless skeleton.
98
+ loading: !data && query.isEnabled && !query.isError,
99
+ error: query.error,
100
+ refetch,
101
+ failureCount: query.failureCount,
102
+ failureReason: query.failureReason,
103
+ isFetching: query.isFetching,
104
+ isPlaceholderData: query.isPlaceholderData,
105
+ }
106
+ }
107
+
108
+ /** `key`, kept by content: callers build `key`/`args` anew every render. */
109
+ function useStableKey(key: unknown[]): unknown[] {
110
+ const id = hashKey(key)
111
+ const [stable, setStable] = useState({ id, key })
112
+ if (stable.id !== id) setStable({ id, key })
113
+ return stable.id === id ? stable.key : key
114
+ }
115
+
116
+ /**
117
+ * `"seed"` mode: write the host's payload into the feed's cache entry in the
118
+ * render phase, before the query's observer reads the cache — what TanStack's
119
+ * own `initialData` does (see {@link seedToolQuery} for when it wins over a
120
+ * cached answer). The last processed seed skips the content check while the
121
+ * same object comes in render after render.
122
+ */
123
+ function useSeed(
124
+ seed: unknown,
125
+ cacheKey: unknown[],
126
+ updatedAt: number | (() => number | undefined) | undefined,
127
+ ): void {
128
+ const client = useQueryClient()
129
+ const keyId = hashKey(cacheKey)
130
+ const [seen, setSeen] = useState<{ seed: unknown; keyId: string } | null>(null)
131
+ if (seed == null || (seen?.seed === seed && seen.keyId === keyId)) return
132
+ const at = typeof updatedAt === "function" ? updatedAt() : updatedAt
133
+ const written = seedToolQuery(client, cacheKey, seed, at)
134
+ // Only a real change re-renders: an equal new object per render must not loop.
135
+ if (written || seen?.keyId !== keyId) setSeen({ seed, keyId })
136
+ }
137
+
138
+ /**
139
+ * A refetch that reads anew at once. TanStack restarts an in-flight fetch only
140
+ * over data (`cancelRefetch`); a key without data joins the running retry
141
+ * chain and waits out its backoff. So cancel that chain first, then read.
142
+ */
143
+ function useFreshRefetch(cacheKey: unknown[], refetchQuery: () => Promise<unknown>): () => void {
144
+ const client = useQueryClient()
145
+ return useCallback(() => {
146
+ if (client.getQueryData(cacheKey) !== undefined) {
147
+ void refetchQuery()
148
+ return
149
+ }
150
+ void client.cancelQueries({ queryKey: cacheKey, exact: true }).then(() => refetchQuery())
151
+ }, [client, cacheKey, refetchQuery])
42
152
  }
@@ -1,10 +1,15 @@
1
1
  import { useQuery, type UseQueryResult } from "@tanstack/react-query"
2
- import { useCallTool } from "../providers/query-provider.js"
2
+ import { useCallTool, useToolNameInQueryKey } from "../providers/query-provider.js"
3
3
  import { parseViewToolResult } from "../lib/parse-tool-result.js"
4
+ import { toolQueryOptions, type UseToolQueryOptions } from "../lib/tool-query.js"
5
+ import { useRefetchOnTransport, useToolKeyGuard } from "./use-tool-query.js"
4
6
 
5
- export interface UseViewToolQueryOptions {
6
- enabled?: boolean
7
- }
7
+ /**
8
+ * Options of {@link useViewToolQuery}: TanStack's query options, passed
9
+ * through like `useToolQuery`'s (`enabled`, `retry`, `staleTime`,
10
+ * `placeholderData`, `initialData`, …).
11
+ */
12
+ export type UseViewToolQueryOptions<T = unknown> = UseToolQueryOptions<T>
8
13
 
9
14
  /**
10
15
  * Self-fetch hook for `*_show_*` widget tools — the envelope-unwrapping sibling
@@ -14,25 +19,26 @@ export interface UseViewToolQueryOptions {
14
19
  * envelope; this hook decodes via {@link parseViewToolResult} (single-step →
15
20
  * flat data, multi-step → keyed by step id) instead.
16
21
  *
17
- * `args` is appended to the effective query key — same queryKey-vs-args
18
- * contract as {@link useToolQuery}, so sibling widgets sharing a query key
19
- * collapse to a single deduped tool call.
22
+ * Same key and options contract as {@link useToolQuery}: the effective key is
23
+ * `[...queryKey, args]` (`[...queryKey, toolName, args]` under an
24
+ * `AppQueryProvider` with `toolNameInQueryKey`), so sibling widgets sharing a
25
+ * query key and args collapse to a single deduped tool call.
20
26
  */
21
27
  export function useViewToolQuery<T = unknown>(
22
- queryKey: unknown[],
28
+ queryKey: readonly unknown[],
23
29
  toolName: string,
24
30
  args: object,
25
- opts?: UseViewToolQueryOptions,
31
+ opts?: UseViewToolQueryOptions<T>,
26
32
  ): UseQueryResult<T, Error> {
27
33
  const callTool = useCallTool()
28
-
29
- return useQuery<T, Error>({
30
- queryKey: [...queryKey, args],
31
- queryFn: async () => {
32
- if (!callTool) throw new Error("callTool not available")
33
- const result = await callTool(toolName, args)
34
- return parseViewToolResult<T>(result)
35
- },
36
- enabled: !!callTool && (opts?.enabled ?? true),
37
- })
34
+ const toolNameInKey = useToolNameInQueryKey()
35
+ useToolKeyGuard(queryKey, toolName, args)
36
+ const query = useQuery<T, Error>(
37
+ toolQueryOptions<T>(queryKey, toolName, args, callTool, opts, {
38
+ decode: parseViewToolResult,
39
+ toolNameInKey,
40
+ }),
41
+ )
42
+ useRefetchOnTransport(callTool, query)
43
+ return query
38
44
  }
@@ -17,6 +17,7 @@ import { BuilderBanners } from "./app/builder/BuilderBanners.js"
17
17
  import { PipelineStrip } from "./app/builder/PipelineStrip.js"
18
18
  import { StatusChip } from "./app/builder/status-chip.js"
19
19
  import { Toolbar } from "./app/builder/Toolbar.js"
20
+ import { Workspace } from "./app/builder/Workspace.js"
20
21
  import { WidgetCrashFallback, WidgetRenderer } from "./app/widget-renderer.js"
21
22
 
22
23
  /**
@@ -135,6 +136,26 @@ const CHROME_CASES: { name: string; render: () => ReactElement }[] = [
135
136
  />
136
137
  ),
137
138
  },
139
+ {
140
+ name: "ViewPlaceholder blocked (a writing tool, no retry)",
141
+ render: () => (
142
+ <ViewPlaceholder
143
+ lifecycle={{ phase: "error", reason: undefined, canRetry: false, kind: "blocked" }}
144
+ labels={PSEUDO.view}
145
+ onRetry={noop}
146
+ />
147
+ ),
148
+ },
149
+ {
150
+ name: "ViewPlaceholder blocked (load the view)",
151
+ render: () => (
152
+ <ViewPlaceholder
153
+ lifecycle={{ phase: "error", reason: undefined, canRetry: true, kind: "blocked" }}
154
+ labels={PSEUDO.view}
155
+ onRetry={noop}
156
+ />
157
+ ),
158
+ },
138
159
  {
139
160
  name: "StepErrors without a refresh",
140
161
  render: () => (
@@ -167,6 +188,7 @@ const CHROME_CASES: { name: string; render: () => ReactElement }[] = [
167
188
  onRefresh={asyncNoop}
168
189
  onEnterBuildMode={noop}
169
190
  onToggleFullscreen={asyncNoop}
191
+ dataAsOf="14:32"
170
192
  />
171
193
  ),
172
194
  },
@@ -236,7 +258,7 @@ const CHROME_CASES: { name: string; render: () => ReactElement }[] = [
236
258
  ),
237
259
  },
238
260
  {
239
- name: "Builder toolbar",
261
+ name: "Builder toolbar (advanced, unsaved)",
240
262
  render: () => (
241
263
  <Toolbar
242
264
  L={PSEUDO.builder}
@@ -246,13 +268,93 @@ const CHROME_CASES: { name: string; render: () => ReactElement }[] = [
246
268
  liveKeys={2}
247
269
  reachableCount={5}
248
270
  unreachableCount={1}
271
+ advanced
272
+ onToggleAdvanced={noop}
273
+ unsaved
249
274
  onOpenCatalogue={noop}
250
275
  onOpenSave={noop}
251
- onDone={noop}
276
+ onDiscard={noop}
277
+ onApply={noop}
252
278
  hasAnyCell
253
279
  />
254
280
  ),
255
281
  },
282
+ {
283
+ name: "Builder workspace (titled and untitled palette entries, canvas cells)",
284
+ render: () => (
285
+ <Workspace
286
+ L={PSEUDO.builder}
287
+ paletteByApp={[
288
+ [
289
+ "demo",
290
+ [
291
+ {
292
+ id: "demo:orders",
293
+ app: "demo",
294
+ requires: ["demo:key"],
295
+ size: "full",
296
+ title: { en: "Orders", de: "Bestellungen" },
297
+ summary: { de: "Alle offenen Bestellungen." },
298
+ },
299
+ { id: "demo:raw", app: "demo", requires: [], size: "half" },
300
+ ],
301
+ ],
302
+ ]}
303
+ appDisplayByName={new Map()}
304
+ paletteCount={2}
305
+ paletteLoading={false}
306
+ onOpenDataSources={noop}
307
+ activeRows={[{ row: [{ widget: "demo:orders" }] }, { row: [] }]}
308
+ focusedRowIndex={0}
309
+ setFocusedRowIndex={noop}
310
+ dragOverRow={null}
311
+ setDragOverRow={noop}
312
+ onAddRow={noop}
313
+ onRemoveRow={noop}
314
+ onMoveRow={noop}
315
+ onSetCellSpan={noop}
316
+ onRemoveCell={noop}
317
+ onAddWidget={noop}
318
+ onConfigureCell={noop}
319
+ propsSchemaByWidgetId={new Map([["demo:orders", { type: "object" }]])}
320
+ displayByWidgetId={new Map([["demo:orders", { title: { de: "Bestellungen" } }]])}
321
+ advanced
322
+ widgets={{}}
323
+ widgetProps={{ keys: {}, context: { keys: {}, steps: {}, errors: [] } }}
324
+ onAddTab={noop}
325
+ />
326
+ ),
327
+ },
328
+ ...[true, false].map((paletteLoading) => ({
329
+ name: `Builder workspace (palette ${paletteLoading ? "loading" : "empty"})`,
330
+ render: () => (
331
+ <Workspace
332
+ L={PSEUDO.builder}
333
+ paletteByApp={[]}
334
+ appDisplayByName={new Map()}
335
+ paletteCount={0}
336
+ paletteLoading={paletteLoading}
337
+ onOpenDataSources={noop}
338
+ activeRows={[{ row: [] }]}
339
+ focusedRowIndex={0}
340
+ setFocusedRowIndex={noop}
341
+ dragOverRow={null}
342
+ setDragOverRow={noop}
343
+ onAddRow={noop}
344
+ onRemoveRow={noop}
345
+ onMoveRow={noop}
346
+ onSetCellSpan={noop}
347
+ onRemoveCell={noop}
348
+ onAddWidget={noop}
349
+ onConfigureCell={noop}
350
+ propsSchemaByWidgetId={new Map()}
351
+ displayByWidgetId={new Map()}
352
+ advanced={false}
353
+ widgets={{}}
354
+ widgetProps={{ keys: {}, context: { keys: {}, steps: {}, errors: [] } }}
355
+ />
356
+ ),
357
+ })),
256
358
  {
257
359
  name: "Builder data sources",
258
360
  render: () => (
package/src/index.ts CHANGED
@@ -66,16 +66,40 @@ export {
66
66
  // NOTE: the view-tool hooks (`useViewToolQuery`, `useViewData`) are exported
67
67
  // from the `./hooks` subpath only — see `packages/ui/src/hooks/index.ts`.
68
68
  export { useIsMobile } from "./hooks/use-mobile.js"
69
- export { useToolQuery, useToolMutation } from "./hooks/use-tool-query.js"
70
- export type { UseToolQueryOptions } from "./hooks/use-tool-query.js"
69
+ export { useToolQuery, useToolQueryKey, useToolMutation } from "./hooks/use-tool-query.js"
70
+ export type { UseToolQueryOptions, UseToolMutationOptions } from "./hooks/use-tool-query.js"
71
+ // The query layer's contract: the effective cache key, the opt-in retry
72
+ // policy (no retry of a tool's own isError answer), and TanStack's
73
+ // keepPreviousData for `placeholderData`, so a consumer needs no direct
74
+ // @tanstack/react-query import for the common options.
75
+ export { toolQueryKey, shouldRetryToolCall } from "./lib/tool-query.js"
76
+ export { ToolResultError, isToolError } from "./lib/parse-tool-result.js"
77
+ export { keepPreviousData } from "@tanstack/react-query"
71
78
  export { useDebouncedValue } from "./hooks/use-debounced-value.js"
72
79
 
73
80
  // Tone token system — the semantic status tones (ToneVariant + TONE_* maps)
74
- // behind the tone-aware components below. Pure data + class strings. Three
81
+ // behind the tone-aware components below. Pure data + class strings. ONE
82
+ // vocabulary (TONE_VARIANTS; retired names map through resolveTone). Three
75
83
  // roles per tone: colour (TONE_DOT/TONE_BORDER/TONE_ICON), tint (TONE_SOFT,
76
- // foreground text on it), text on a plain surface (TONE_TEXT, the -ink role).
77
- export { TONE_SOFT, TONE_DOT, TONE_TEXT, TONE_BORDER, TONE_ICON } from "./lib/tone-utils.js"
78
- export type { ToneVariant } from "./lib/tone-utils.js"
84
+ // foreground text on it; TONE_TINT alone), text on a plain surface (TONE_INK,
85
+ // the -ink role; TONE_TEXT is its deprecated name).
86
+ export {
87
+ TONE_VARIANTS,
88
+ TONE_ALIASES,
89
+ resolveTone,
90
+ isToneVariant,
91
+ TONE_SOFT,
92
+ TONE_TINT,
93
+ TONE_DOT,
94
+ TONE_INK,
95
+ TONE_TEXT,
96
+ TONE_BORDER,
97
+ TONE_ICON,
98
+ } from "./lib/tone-utils.js"
99
+ export type { ToneVariant, ToneAlias, ToneName } from "./lib/tone-utils.js"
100
+ // The type scale (CI §4): text-title/section/body/dense/small utilities, 13 px floor.
101
+ export { TYPE_SCALE, TYPE_STEPS, TYPE_FLOOR_PX, MICRO_LABEL } from "./lib/typography.js"
102
+ export type { TypeStep } from "./lib/typography.js"
79
103
  // The kit's opaque focus ring as class strings, for custom controls.
80
104
  export { FOCUS_RING, FOCUS_RING_INSET } from "./lib/focus-ring.js"
81
105
 
@@ -83,14 +107,24 @@ export { FOCUS_RING, FOCUS_RING_INSET } from "./lib/focus-ring.js"
83
107
  // primitives. Pure (React + primitives + cn), so they live in the root barrel.
84
108
  export { GridLayout, GridItem } from "./components/GridLayout.js"
85
109
  export type { GridLayoutProps, GridItemProps } from "./components/GridLayout.js"
86
- export { KpiGrid } from "./components/KpiGrid.js"
87
- export type { KpiGridProps, KpiGridHeader, KpiCell } from "./components/KpiGrid.js"
88
- export { LivePill, CountPill } from "./components/Pills.js"
89
- export type { LivePillProps, CountPillProps } from "./components/Pills.js"
110
+ export { KpiGrid, KpiGridSkeleton } from "./components/KpiGrid.js"
111
+ export type {
112
+ KpiGridProps,
113
+ KpiGridHeader,
114
+ KpiCell,
115
+ KpiGridSkeletonProps,
116
+ } from "./components/KpiGrid.js"
117
+ export { LivePill, CountPill, StatusBadge } from "./components/Pills.js"
118
+ export type {
119
+ LivePillProps,
120
+ CountPillProps,
121
+ StatusBadgeProps,
122
+ StatusBadgeText,
123
+ } from "./components/Pills.js"
90
124
  export { SectionHeading } from "./components/SectionHeading.js"
91
125
  export type { SectionHeadingProps } from "./components/SectionHeading.js"
92
126
  export { WidgetHeader } from "./components/WidgetHeader.js"
93
- export type { WidgetHeaderProps } from "./components/WidgetHeader.js"
127
+ export type { WidgetHeaderProps, WidgetHeadingLevel } from "./components/WidgetHeader.js"
94
128
  export { GroupCard } from "./components/GroupCard.js"
95
129
  export type { GroupCardProps } from "./components/GroupCard.js"
96
130
  export { FilterBar } from "./components/FilterBar.js"
@@ -99,6 +133,8 @@ export { DrillButton } from "./components/DrillButton.js"
99
133
  export type { DrillButtonProps } from "./components/DrillButton.js"
100
134
  export { ListFooter } from "./components/ListFooter.js"
101
135
  export type { ListFooterProps } from "./components/ListFooter.js"
136
+ export { PagedListFooter } from "./components/PagedListFooter.js"
137
+ export type { PagedListFooterProps, PagedListState } from "./components/PagedListFooter.js"
102
138
 
103
139
  // Feedback and states — one pattern each for toasts, empty and error states.
104
140
  export { ToastProvider, useToast } from "./components/Toast.js"
@@ -166,6 +202,7 @@ export type {
166
202
  BoundTranslate,
167
203
  BuilderMessages,
168
204
  CommonMessages,
205
+ FilterBarMessages,
169
206
  ListFooterMessages,
170
207
  PropsSheetMessages,
171
208
  RendererMessages,