@miragon/mcp-toolkit-ui 2.7.0 → 2.8.1

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 (388) 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 +14 -6
  122. package/dist/components/DrillButton.d.ts.map +1 -1
  123. package/dist/components/DrillButton.js +14 -7
  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.test.tsx +48 -0
  319. package/src/components/DrillButton.tsx +26 -11
  320. package/src/components/EmptyState.tsx +6 -4
  321. package/src/components/ErrorState.tsx +31 -9
  322. package/src/components/FilterBar.test.tsx +82 -0
  323. package/src/components/FilterBar.tsx +52 -26
  324. package/src/components/KpiGrid.test.tsx +279 -0
  325. package/src/components/KpiGrid.tsx +297 -90
  326. package/src/components/ListFooter.test.tsx +116 -0
  327. package/src/components/ListFooter.tsx +102 -15
  328. package/src/components/PagedListFooter.test.tsx +140 -0
  329. package/src/components/PagedListFooter.tsx +107 -0
  330. package/src/components/Pills.test.tsx +77 -0
  331. package/src/components/Pills.tsx +63 -10
  332. package/src/components/SectionHeading.tsx +9 -3
  333. package/src/components/Toast.tsx +37 -19
  334. package/src/components/WidgetHeader.test.tsx +78 -0
  335. package/src/components/WidgetHeader.tsx +63 -16
  336. package/src/components/feedback-states.test.tsx +98 -9
  337. package/src/components/tone-figures.test.tsx +8 -4
  338. package/src/hooks/index.ts +6 -3
  339. package/src/hooks/tool-result-recovery-model.test.ts +744 -0
  340. package/src/hooks/tool-result-recovery-model.ts +418 -0
  341. package/src/hooks/use-tool-query.effects.test.tsx +205 -0
  342. package/src/hooks/use-tool-query.ts +156 -33
  343. package/src/hooks/use-tool-result-recovery.effects.test.tsx +141 -0
  344. package/src/hooks/use-tool-result-recovery.test.ts +3 -4
  345. package/src/hooks/use-tool-result-recovery.ts +84 -142
  346. package/src/hooks/use-view-data.test.tsx +118 -9
  347. package/src/hooks/use-view-data.ts +128 -18
  348. package/src/hooks/use-view-tool-query.ts +25 -19
  349. package/src/i18n-coverage.test.tsx +104 -2
  350. package/src/index.ts +48 -11
  351. package/src/lib/focus-return.test.ts +288 -0
  352. package/src/lib/focus-return.ts +96 -0
  353. package/src/lib/parse-tool-result.test.ts +46 -1
  354. package/src/lib/parse-tool-result.ts +40 -2
  355. package/src/lib/toast-model.test.ts +166 -1
  356. package/src/lib/toast-model.ts +104 -2
  357. package/src/lib/tone-utils.test.ts +86 -10
  358. package/src/lib/tone-utils.ts +89 -8
  359. package/src/lib/tool-query.test.ts +569 -0
  360. package/src/lib/tool-query.ts +253 -0
  361. package/src/lib/tool-result-observer.test.ts +296 -0
  362. package/src/lib/tool-result-observer.ts +211 -0
  363. package/src/lib/typography.test.ts +45 -0
  364. package/src/lib/typography.ts +47 -0
  365. package/src/lib/utils.ts +12 -1
  366. package/src/locale/index.ts +1 -0
  367. package/src/locale/message-types.ts +118 -2
  368. package/src/locale/messages-de.ts +49 -10
  369. package/src/locale/messages-en.ts +49 -10
  370. package/src/locale/toolkit-messages.test.ts +133 -0
  371. package/src/locale/toolkit-messages.ts +63 -2
  372. package/src/primitives/alert.tsx +3 -0
  373. package/src/primitives/badge.tsx +9 -4
  374. package/src/primitives/button.tsx +1 -1
  375. package/src/primitives/dialog.tsx +10 -1
  376. package/src/primitives/select.tsx +1 -1
  377. package/src/primitives/sheet.tsx +7 -0
  378. package/src/providers/query-provider.test.tsx +154 -0
  379. package/src/providers/query-provider.tsx +66 -5
  380. package/src/render-cases-primitives.tsx +1 -1
  381. package/src/render-cases.tsx +38 -6
  382. package/src/render-effects.tsx +96 -0
  383. package/src/theme/cd-tokens.test.ts +3 -1
  384. package/src/theme/create-theme.test.ts +10 -0
  385. package/src/theme/create-theme.ts +28 -0
  386. package/src/theme/theme-css.test.ts +51 -0
  387. package/src/theme.css +31 -1
  388. package/ui-catalog.json +448 -41
@@ -1,13 +1,21 @@
1
1
  import type { ReactNode } from "react"
2
2
  import { renderToStaticMarkup } from "react-dom/server"
3
+ import { QueryClient, useQueryClient } from "@tanstack/react-query"
3
4
  import { ToolCancelledError, ToolError } from "mcp-use/react"
4
5
  import { beforeEach, describe, expect, it, vi } from "vitest"
6
+ import { useToolQueryKey } from "../hooks/use-tool-query.js"
7
+ import { AppQueryProvider, queryClient } from "../providers/query-provider.js"
8
+ import type {
9
+ ToolResultRecoveryOptions,
10
+ ToolResultRecoveryState,
11
+ } from "../hooks/use-tool-result-recovery.js"
5
12
  import { LocaleProvider, useLocale } from "../locale/locale-provider.js"
6
13
  import { TOOLKIT_MESSAGES, type ToolkitMessages } from "../locale/toolkit-messages.js"
7
14
  import { attribute, decodeEntities, openingTags, userFacingTexts } from "../render-scan.js"
8
15
  import { createStandaloneHostBridge, HostBridgeProvider } from "./host-bridge.js"
9
16
  import { McpAppView } from "./mcp-app-view.js"
10
17
  import type { ViewData } from "./mcp-app-view-chrome.js"
18
+ import { McpUseViewContext } from "./model-context.js"
11
19
 
12
20
  /**
13
21
  * McpAppView's wiring, rendered through its real hooks (SSR, the house path):
@@ -23,9 +31,29 @@ interface HostState {
23
31
  tool: Record<string, unknown>
24
32
  locale: string
25
33
  hostContext: Record<string, unknown> | undefined
34
+ /** Replaces the recovery's state (it settles in effects, which SSR never runs). */
35
+ recovery: ToolResultRecoveryState<unknown> | null
26
36
  }
27
37
 
28
- const host: HostState = vi.hoisted(() => ({ tool: {}, locale: "en-US", hostContext: undefined }))
38
+ const host: HostState = vi.hoisted(() => ({
39
+ tool: {},
40
+ locale: "en-US",
41
+ hostContext: undefined,
42
+ recovery: null,
43
+ }))
44
+
45
+ // The real hook always runs (hook order stays fixed); a fixture state stands
46
+ // in for what its controller decides once the stripped result arrived.
47
+ vi.mock(import("../hooks/use-tool-result-recovery.js"), async (importOriginal) => {
48
+ const actual = await importOriginal()
49
+ return {
50
+ ...actual,
51
+ useToolResultRecovery: <T,>(options: ToolResultRecoveryOptions) => {
52
+ const state = actual.useToolResultRecovery<T>(options)
53
+ return (host.recovery as ToolResultRecoveryState<T> | null) ?? state
54
+ },
55
+ }
56
+ })
29
57
 
30
58
  // Only the fields McpAppView reads; the casts narrow the fixtures to the hook types.
31
59
  vi.mock(import("mcp-use/react"), async (importOriginal) => {
@@ -33,11 +61,18 @@ vi.mock(import("mcp-use/react"), async (importOriginal) => {
33
61
  const useToolContext = () => host.tool
34
62
  const useHostContext = () => ({
35
63
  locale: host.locale,
64
+ timeZone: "UTC",
36
65
  safeArea: { top: 0, right: 0, bottom: 0, left: 0 },
37
66
  hostContext: host.hostContext,
38
67
  })
68
+ // The view's model-context node, made visible: a <meta> whose `content`
69
+ // the scans below never read as user-facing text.
70
+ const { createElement } = await import("react")
71
+ const ModelContext = ({ content }: { content: string }) =>
72
+ createElement("meta", { "data-model-context": content })
39
73
  return {
40
74
  ...actual,
75
+ ModelContext: ModelContext as unknown as typeof actual.ModelContext,
41
76
  useToolContext: useToolContext as unknown as typeof actual.useToolContext,
42
77
  useHostContext: useHostContext as unknown as typeof actual.useHostContext,
43
78
  useDisplayMode: () => ({
@@ -113,6 +148,21 @@ beforeEach(() => {
113
148
  host.tool = { status: "pending", toolInput: undefined, toolOutput: undefined }
114
149
  host.locale = "en-US"
115
150
  host.hostContext = KNOWN_TOOL
151
+ host.recovery = null
152
+ })
153
+
154
+ /** A tool the host names, with its annotations (SEP-1865 `toolInfo.tool`). */
155
+ const toolInfo = (name: string, annotations: Record<string, unknown>) => ({
156
+ toolInfo: { tool: { name, annotations } },
157
+ })
158
+
159
+ /** The recovery's state when a needed recovery did not run. */
160
+ const blockedBy = (reason: "policy" | "no-tool"): ToolResultRecoveryState<unknown> => ({
161
+ data: null,
162
+ failed: false,
163
+ blocked: reason,
164
+ recoveredAt: null,
165
+ args: null,
116
166
  })
117
167
 
118
168
  describe("McpAppView lifecycle wiring (toolkit#176)", () => {
@@ -148,6 +198,77 @@ describe("McpAppView lifecycle wiring (toolkit#176)", () => {
148
198
  expect(view).toContain(en.errorHintNoRetry)
149
199
  })
150
200
 
201
+ it("a stripped result of a writing tool the policy kept: the notice, never a button that writes again", () => {
202
+ // claude.ai strips the result of a "start and show" tool; "auto" never
203
+ // re-runs a tool reported as writing (readOnlyHint: false).
204
+ host.hostContext = toolInfo("start_and_show", { readOnlyHint: false })
205
+ host.recovery = blockedBy("policy")
206
+ const view = decodeEntities(render().view)
207
+ expect(view).not.toContain('data-slot="skeleton"')
208
+ expect(view).toContain('data-tone="info"')
209
+ expect(view).toContain(en.blockedTitle)
210
+ expect(view).toContain(en.blockedHintNoRetry)
211
+ expect(view).not.toContain(en.errorTitle)
212
+ expect(view).not.toContain("<button")
213
+ // The same for destructiveHint: true.
214
+ host.hostContext = toolInfo("start_and_show", { readOnlyHint: true, destructiveHint: true })
215
+ expect(render().view).not.toContain("<button")
216
+ })
217
+
218
+ it("a tool not reported as writing that a stricter policy kept: the notice offers to load the view", () => {
219
+ host.hostContext = toolInfo("show_list", {})
220
+ host.recovery = blockedBy("policy")
221
+ const view = decodeEntities(render().view)
222
+ expect(view).toContain(en.blockedTitle)
223
+ expect(view).toContain(en.blockedHint)
224
+ expect(view).toContain(`${en.blockedRetry}</button>`)
225
+ })
226
+
227
+ it("a recovery blocked for want of a tool name stays the plain error without retry", () => {
228
+ host.hostContext = undefined
229
+ host.recovery = blockedBy("no-tool")
230
+ const view = decodeEntities(render().view)
231
+ expect(view).toContain(en.errorTitle)
232
+ expect(view).toContain(en.errorHintNoRetry)
233
+ expect(view).not.toContain(en.blockedTitle)
234
+ expect(view).not.toContain("<button")
235
+ })
236
+
237
+ it("a failed recovery stays the plain error with its retry", () => {
238
+ host.recovery = { ...blockedBy("policy"), blocked: null, failed: true }
239
+ const view = decodeEntities(render().view)
240
+ expect(view).toContain(en.errorTitle)
241
+ expect(view).toContain(`${en.retry}</button>`)
242
+ })
243
+
244
+ it("a payload the view re-loaded itself carries the stamp under its title, in the host's words (N23)", () => {
245
+ const recoveredAt = Date.UTC(2026, 9, 11, 14, 32)
246
+ host.recovery = { data: VIEW, failed: false, blocked: null, recoveredAt, args: {} }
247
+ const view = decodeEntities(render().view)
248
+ expect(view).toContain(
249
+ `<p data-slot="view-data-as-of" class="text-muted-foreground truncate text-sm">Reloaded at 2:32 PM</p>`,
250
+ )
251
+ host.locale = "de-DE"
252
+ expect(decodeEntities(render().view)).toContain(">Neu geladen um 14:32 Uhr</p>")
253
+ // A host-delivered payload carries none.
254
+ host.recovery = null
255
+ host.tool = { status: "ready", toolOutput: VIEW, toolInput: {} }
256
+ expect(render().view).not.toContain('data-slot="view-data-as-of"')
257
+ })
258
+
259
+ it("the stamp's time speaks the language of its words, not the host's other one", () => {
260
+ const recoveredAt = Date.UTC(2026, 9, 11, 14, 32)
261
+ host.recovery = { data: VIEW, failed: false, blocked: null, recoveredAt, args: {} }
262
+ // A German profile (LocaleProvider) on an en-US host: never "4:32 PM Uhr".
263
+ host.locale = "en-US"
264
+ const german = render((node) => <LocaleProvider locale="de">{node}</LocaleProvider>)
265
+ expect(decodeEntities(german.view)).toContain(">Neu geladen um 14:32 Uhr</p>")
266
+ // The host's region of the same language stays: en-GB keeps its 24-hour clock.
267
+ host.locale = "en-GB"
268
+ const british = render((node) => <LocaleProvider locale="en">{node}</LocaleProvider>)
269
+ expect(decodeEntities(british.view)).toContain(">Reloaded at 14:32</p>")
270
+ })
271
+
151
272
  it("a host cancellation shows the cancelled notice, no skeleton and no retry", () => {
152
273
  host.tool = { status: "error", error: new ToolCancelledError("user"), toolInput: {} }
153
274
  const { view } = render()
@@ -179,6 +300,104 @@ describe("McpAppView lifecycle wiring (toolkit#176)", () => {
179
300
  })
180
301
  })
181
302
 
303
+ describe("McpAppView toolNameInQueryKey (toolkit#176 K18)", () => {
304
+ /** A widget that prints the cache key its data hooks would use. */
305
+ function KeyProbe() {
306
+ return <output>{JSON.stringify(useToolQueryKey(["feed"], "feed_data", { id: 1 }))}</output>
307
+ }
308
+ const keyIn = (props: { toolNameInQueryKey?: boolean }) =>
309
+ decodeEntities(
310
+ renderToStaticMarkup(
311
+ <HostBridgeProvider bridge={bridge}>
312
+ <McpAppView widgets={{ "demo:probe": KeyProbe }} {...props} />
313
+ </HostBridgeProvider>,
314
+ ),
315
+ ).match(/<output>(.*?)<\/output>/)?.[1]
316
+
317
+ it("hands the setting to the widgets' data hooks; omitted, the 2.x key stays", () => {
318
+ host.tool = { status: "ready", toolOutput: VIEW, toolInput: {} }
319
+ expect(keyIn({ toolNameInQueryKey: true })).toBe('["feed","feed_data",{"id":1}]')
320
+ expect(keyIn({})).toBe('["feed",{"id":1}]')
321
+ })
322
+ })
323
+
324
+ describe("McpAppView query client", () => {
325
+ /** A widget that tells which client its data hooks use. */
326
+ function clientIn(wrap: (node: ReactNode) => ReactNode) {
327
+ const clients: QueryClient[] = []
328
+ function ClientProbe() {
329
+ clients.push(useQueryClient())
330
+ return null
331
+ }
332
+ renderToStaticMarkup(
333
+ <HostBridgeProvider bridge={bridge}>
334
+ {wrap(<McpAppView widgets={{ "demo:probe": ClientProbe }} />)}
335
+ </HostBridgeProvider>,
336
+ )
337
+ expect(clients.length, "the widget rendered").toBeGreaterThan(0)
338
+ return clients[0]
339
+ }
340
+
341
+ it("its widgets fetch through an enclosing AppQueryProvider's client", () => {
342
+ host.tool = { status: "ready", toolOutput: VIEW, toolInput: {} }
343
+ const perMount = new QueryClient()
344
+ expect(clientIn((node) => <AppQueryProvider client={perMount}>{node}</AppQueryProvider>)).toBe(
345
+ perMount,
346
+ )
347
+ expect(
348
+ clientIn((node) => node),
349
+ "else the toolkit's shared client",
350
+ ).toBe(queryClient)
351
+ })
352
+ })
353
+
354
+ describe("McpAppView model context (toolkit#176 K20)", () => {
355
+ /** Inside an mcp-use view, where the view's line joins the native tree. */
356
+ const inView = (node: ReactNode) => (
357
+ <McpUseViewContext.Provider value={true}>{node}</McpUseViewContext.Provider>
358
+ )
359
+ const contexts = (html: string) =>
360
+ openingTags(html, "meta").map((tag) =>
361
+ decodeEntities(attribute(tag, "data-model-context") ?? ""),
362
+ )
363
+
364
+ it("an error the user sees instead of the view reaches the model: what failed, and that it is an error", () => {
365
+ host.tool = { status: "error", error: toolError(REASON), toolInput: {} }
366
+ const { view } = render(inView)
367
+ expect(contexts(view)).toEqual([
368
+ `The view of render-view could not be shown (reason: ${REASON}). ` +
369
+ "The user sees an error message with a retry button instead of the view.",
370
+ ])
371
+ })
372
+
373
+ it("a blocked recovery tells the model the tool ran and must not be re-run to show the view", () => {
374
+ host.hostContext = toolInfo("start_and_show", { readOnlyHint: false })
375
+ host.recovery = blockedBy("policy")
376
+ expect(contexts(render(inView).view)).toEqual([
377
+ "The view of start_and_show is not shown: start_and_show ran, but the host did not pass its " +
378
+ "result to the view, and the view did not re-run it. The user sees a note to ask in the chat " +
379
+ "for the current state instead of the view. Do not re-run start_and_show just to show the view.",
380
+ ])
381
+ })
382
+
383
+ it("a cancelled call says so", () => {
384
+ host.tool = { status: "error", error: new ToolCancelledError("user"), toolInput: {} }
385
+ expect(contexts(render(inView).view)).toEqual([
386
+ "The view of render-view was cancelled before it rendered. The user sees a note that the call was cancelled.",
387
+ ])
388
+ })
389
+
390
+ it("failed data steps of a shown view are reported; a waiting view reports nothing", () => {
391
+ host.tool = { status: "ready", toolOutput: VIEW, toolInput: {} }
392
+ expect(contexts(render(inView).view)).toEqual([
393
+ "The view of render-view is shown, but some of its data could not be loaded (kpi: timeout). " +
394
+ "The user sees an alert with a retry button.",
395
+ ])
396
+ host.tool = { status: "pending", toolInput: undefined, toolOutput: undefined }
397
+ expect(contexts(render(inView).view)).toEqual([])
398
+ })
399
+ })
400
+
182
401
  describe("McpAppView locale", () => {
183
402
  it("speaks the host's language in its own chrome", () => {
184
403
  host.locale = "de-DE"
@@ -186,7 +405,8 @@ describe("McpAppView locale", () => {
186
405
  const { view, toasts } = render()
187
406
  expect(decodeEntities(view)).toContain(de.errorTitle)
188
407
  expect(view).toContain(`${de.retry}</button>`)
189
- expect(toasts).toContain(`aria-label="${TOOLKIT_MESSAGES.de.common.notifications}"`)
408
+ // The toast stack below the view speaks it too (its close buttons).
409
+ expect(toasts).toContain(`aria-label="${TOOLKIT_MESSAGES.de.common.dismiss}"`)
190
410
  })
191
411
 
192
412
  it("leaves useLocale() of consumer widgets alone (no LocaleProvider of its own)", () => {