@miragon/mcp-toolkit-ui 2.6.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 (511) hide show
  1. package/README.md +14 -5
  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.d.ts +7 -2
  7. package/dist/app/builder/BuilderBanners.d.ts.map +1 -1
  8. package/dist/app/builder/BuilderBanners.js +8 -3
  9. package/dist/app/builder/BuilderBanners.js.map +1 -1
  10. package/dist/app/builder/CanvasRow.d.ts +4 -2
  11. package/dist/app/builder/CanvasRow.d.ts.map +1 -1
  12. package/dist/app/builder/CanvasRow.js +29 -17
  13. package/dist/app/builder/CanvasRow.js.map +1 -1
  14. package/dist/app/builder/CatalogueSheet.d.ts.map +1 -1
  15. package/dist/app/builder/CatalogueSheet.js +14 -6
  16. package/dist/app/builder/CatalogueSheet.js.map +1 -1
  17. package/dist/app/builder/CellPropsSheet.d.ts +7 -3
  18. package/dist/app/builder/CellPropsSheet.d.ts.map +1 -1
  19. package/dist/app/builder/CellPropsSheet.js +10 -3
  20. package/dist/app/builder/CellPropsSheet.js.map +1 -1
  21. package/dist/app/builder/DiscardDialog.d.ts +18 -0
  22. package/dist/app/builder/DiscardDialog.d.ts.map +1 -0
  23. package/dist/app/builder/DiscardDialog.js +18 -0
  24. package/dist/app/builder/DiscardDialog.js.map +1 -0
  25. package/dist/app/builder/EmptyHint.d.ts +4 -0
  26. package/dist/app/builder/EmptyHint.d.ts.map +1 -1
  27. package/dist/app/builder/EmptyHint.js +6 -1
  28. package/dist/app/builder/EmptyHint.js.map +1 -1
  29. package/dist/app/builder/LayoutSurface.d.ts +33 -9
  30. package/dist/app/builder/LayoutSurface.d.ts.map +1 -1
  31. package/dist/app/builder/LayoutSurface.js +74 -23
  32. package/dist/app/builder/LayoutSurface.js.map +1 -1
  33. package/dist/app/builder/PipelineStrip.d.ts +5 -2
  34. package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
  35. package/dist/app/builder/PipelineStrip.js +33 -15
  36. package/dist/app/builder/PipelineStrip.js.map +1 -1
  37. package/dist/app/builder/SaveDialog.d.ts +9 -1
  38. package/dist/app/builder/SaveDialog.d.ts.map +1 -1
  39. package/dist/app/builder/SaveDialog.js +9 -3
  40. package/dist/app/builder/SaveDialog.js.map +1 -1
  41. package/dist/app/builder/Toolbar.d.ts +14 -4
  42. package/dist/app/builder/Toolbar.d.ts.map +1 -1
  43. package/dist/app/builder/Toolbar.js +24 -7
  44. package/dist/app/builder/Toolbar.js.map +1 -1
  45. package/dist/app/builder/Workspace.d.ts +23 -3
  46. package/dist/app/builder/Workspace.d.ts.map +1 -1
  47. package/dist/app/builder/Workspace.js +58 -8
  48. package/dist/app/builder/Workspace.js.map +1 -1
  49. package/dist/app/builder/builder-model.d.ts +146 -3
  50. package/dist/app/builder/builder-model.d.ts.map +1 -1
  51. package/dist/app/builder/builder-model.js +196 -5
  52. package/dist/app/builder/builder-model.js.map +1 -1
  53. package/dist/app/builder/labels.d.ts +13 -62
  54. package/dist/app/builder/labels.d.ts.map +1 -1
  55. package/dist/app/builder/labels.js +9 -58
  56. package/dist/app/builder/labels.js.map +1 -1
  57. package/dist/app/builder/reveal.d.ts +10 -0
  58. package/dist/app/builder/reveal.d.ts.map +1 -0
  59. package/dist/app/builder/reveal.js +10 -0
  60. package/dist/app/builder/reveal.js.map +1 -0
  61. package/dist/app/builder/status-chip.d.ts.map +1 -1
  62. package/dist/app/builder/status-chip.js +3 -2
  63. package/dist/app/builder/status-chip.js.map +1 -1
  64. package/dist/app/builder/use-builder-catalogue.d.ts +5 -1
  65. package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
  66. package/dist/app/builder/use-builder-catalogue.js +50 -17
  67. package/dist/app/builder/use-builder-catalogue.js.map +1 -1
  68. package/dist/app/builder/use-builder-session.d.ts +30 -0
  69. package/dist/app/builder/use-builder-session.d.ts.map +1 -0
  70. package/dist/app/builder/use-builder-session.js +58 -0
  71. package/dist/app/builder/use-builder-session.js.map +1 -0
  72. package/dist/app/builder/use-display-resolver.d.ts +17 -0
  73. package/dist/app/builder/use-display-resolver.d.ts.map +1 -0
  74. package/dist/app/builder/use-display-resolver.js +16 -0
  75. package/dist/app/builder/use-display-resolver.js.map +1 -0
  76. package/dist/app/builder/use-save-dashboard.d.ts +3 -1
  77. package/dist/app/builder/use-save-dashboard.d.ts.map +1 -1
  78. package/dist/app/builder/use-save-dashboard.js +3 -1
  79. package/dist/app/builder/use-save-dashboard.js.map +1 -1
  80. package/dist/app/index.d.ts +8 -3
  81. package/dist/app/index.d.ts.map +1 -1
  82. package/dist/app/index.js +8 -2
  83. package/dist/app/index.js.map +1 -1
  84. package/dist/app/layout-builder.d.ts +18 -25
  85. package/dist/app/layout-builder.d.ts.map +1 -1
  86. package/dist/app/layout-builder.js +84 -78
  87. package/dist/app/layout-builder.js.map +1 -1
  88. package/dist/app/mcp-app-view-chrome.d.ts +103 -20
  89. package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
  90. package/dist/app/mcp-app-view-chrome.js +125 -40
  91. package/dist/app/mcp-app-view-chrome.js.map +1 -1
  92. package/dist/app/mcp-app-view-states.d.ts +23 -0
  93. package/dist/app/mcp-app-view-states.d.ts.map +1 -0
  94. package/dist/app/mcp-app-view-states.js +55 -0
  95. package/dist/app/mcp-app-view-states.js.map +1 -0
  96. package/dist/app/mcp-app-view.d.ts +72 -5
  97. package/dist/app/mcp-app-view.d.ts.map +1 -1
  98. package/dist/app/mcp-app-view.js +241 -141
  99. package/dist/app/mcp-app-view.js.map +1 -1
  100. package/dist/app/mcp-toolkit-app.d.ts +8 -2
  101. package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
  102. package/dist/app/mcp-toolkit-app.js +33 -4
  103. package/dist/app/mcp-toolkit-app.js.map +1 -1
  104. package/dist/app/mcp-use-host-bridge.d.ts +15 -6
  105. package/dist/app/mcp-use-host-bridge.d.ts.map +1 -1
  106. package/dist/app/mcp-use-host-bridge.js +51 -22
  107. package/dist/app/mcp-use-host-bridge.js.map +1 -1
  108. package/dist/app/model-context.d.ts +71 -0
  109. package/dist/app/model-context.d.ts.map +1 -0
  110. package/dist/app/model-context.js +101 -0
  111. package/dist/app/model-context.js.map +1 -0
  112. package/dist/app/use-build-mode-focus.d.ts +33 -0
  113. package/dist/app/use-build-mode-focus.d.ts.map +1 -0
  114. package/dist/app/use-build-mode-focus.js +59 -0
  115. package/dist/app/use-build-mode-focus.js.map +1 -0
  116. package/dist/app/use-view-actions.d.ts +31 -0
  117. package/dist/app/use-view-actions.d.ts.map +1 -0
  118. package/dist/app/use-view-actions.js +81 -0
  119. package/dist/app/use-view-actions.js.map +1 -0
  120. package/dist/app/use-view-lifecycle.d.ts +42 -0
  121. package/dist/app/use-view-lifecycle.d.ts.map +1 -0
  122. package/dist/app/use-view-lifecycle.js +81 -0
  123. package/dist/app/use-view-lifecycle.js.map +1 -0
  124. package/dist/app/view-lifecycle.d.ts +185 -0
  125. package/dist/app/view-lifecycle.d.ts.map +1 -0
  126. package/dist/app/view-lifecycle.js +207 -0
  127. package/dist/app/view-lifecycle.js.map +1 -0
  128. package/dist/app/widget-fixture.d.ts +10 -3
  129. package/dist/app/widget-fixture.d.ts.map +1 -1
  130. package/dist/app/widget-fixture.js +21 -8
  131. package/dist/app/widget-fixture.js.map +1 -1
  132. package/dist/app/widget-props-sheet.d.ts +6 -10
  133. package/dist/app/widget-props-sheet.d.ts.map +1 -1
  134. package/dist/app/widget-props-sheet.js +25 -20
  135. package/dist/app/widget-props-sheet.js.map +1 -1
  136. package/dist/app/widget-renderer.d.ts +41 -1
  137. package/dist/app/widget-renderer.d.ts.map +1 -1
  138. package/dist/app/widget-renderer.js +82 -31
  139. package/dist/app/widget-renderer.js.map +1 -1
  140. package/dist/components/DrillButton.d.ts +9 -6
  141. package/dist/components/DrillButton.d.ts.map +1 -1
  142. package/dist/components/DrillButton.js +9 -6
  143. package/dist/components/DrillButton.js.map +1 -1
  144. package/dist/components/EmptyState.d.ts +33 -0
  145. package/dist/components/EmptyState.d.ts.map +1 -0
  146. package/dist/components/EmptyState.js +19 -0
  147. package/dist/components/EmptyState.js.map +1 -0
  148. package/dist/components/ErrorState.d.ts +53 -0
  149. package/dist/components/ErrorState.d.ts.map +1 -0
  150. package/dist/components/ErrorState.js +77 -0
  151. package/dist/components/ErrorState.js.map +1 -0
  152. package/dist/components/FilterBar.d.ts +16 -5
  153. package/dist/components/FilterBar.d.ts.map +1 -1
  154. package/dist/components/FilterBar.js +13 -5
  155. package/dist/components/FilterBar.js.map +1 -1
  156. package/dist/components/GroupCard.d.ts.map +1 -1
  157. package/dist/components/GroupCard.js +2 -1
  158. package/dist/components/GroupCard.js.map +1 -1
  159. package/dist/components/KpiGrid.d.ts +70 -18
  160. package/dist/components/KpiGrid.d.ts.map +1 -1
  161. package/dist/components/KpiGrid.js +112 -23
  162. package/dist/components/KpiGrid.js.map +1 -1
  163. package/dist/components/ListFooter.d.ts +32 -4
  164. package/dist/components/ListFooter.d.ts.map +1 -1
  165. package/dist/components/ListFooter.js +35 -6
  166. package/dist/components/ListFooter.js.map +1 -1
  167. package/dist/components/PagedListFooter.d.ts +57 -0
  168. package/dist/components/PagedListFooter.d.ts.map +1 -0
  169. package/dist/components/PagedListFooter.js +27 -0
  170. package/dist/components/PagedListFooter.js.map +1 -0
  171. package/dist/components/Pills.d.ts +36 -12
  172. package/dist/components/Pills.d.ts.map +1 -1
  173. package/dist/components/Pills.js +29 -8
  174. package/dist/components/Pills.js.map +1 -1
  175. package/dist/components/SectionHeading.d.ts +3 -1
  176. package/dist/components/SectionHeading.d.ts.map +1 -1
  177. package/dist/components/SectionHeading.js +6 -2
  178. package/dist/components/SectionHeading.js.map +1 -1
  179. package/dist/components/Toast.d.ts +43 -0
  180. package/dist/components/Toast.d.ts.map +1 -0
  181. package/dist/components/Toast.js +106 -0
  182. package/dist/components/Toast.js.map +1 -0
  183. package/dist/components/WidgetHeader.d.ts +34 -10
  184. package/dist/components/WidgetHeader.d.ts.map +1 -1
  185. package/dist/components/WidgetHeader.js +11 -6
  186. package/dist/components/WidgetHeader.js.map +1 -1
  187. package/dist/hooks/index.d.ts +4 -4
  188. package/dist/hooks/index.d.ts.map +1 -1
  189. package/dist/hooks/index.js +1 -1
  190. package/dist/hooks/index.js.map +1 -1
  191. package/dist/hooks/tool-result-recovery-model.d.ts +155 -0
  192. package/dist/hooks/tool-result-recovery-model.d.ts.map +1 -0
  193. package/dist/hooks/tool-result-recovery-model.js +273 -0
  194. package/dist/hooks/tool-result-recovery-model.js.map +1 -0
  195. package/dist/hooks/use-tool-query.d.ts +56 -14
  196. package/dist/hooks/use-tool-query.d.ts.map +1 -1
  197. package/dist/hooks/use-tool-query.js +102 -25
  198. package/dist/hooks/use-tool-query.js.map +1 -1
  199. package/dist/hooks/use-tool-result-recovery.d.ts +61 -44
  200. package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
  201. package/dist/hooks/use-tool-result-recovery.js +62 -110
  202. package/dist/hooks/use-tool-result-recovery.js.map +1 -1
  203. package/dist/hooks/use-view-data.d.ts +55 -7
  204. package/dist/hooks/use-view-data.d.ts.map +1 -1
  205. package/dist/hooks/use-view-data.js +81 -11
  206. package/dist/hooks/use-view-data.js.map +1 -1
  207. package/dist/hooks/use-view-tool-query.d.ts +12 -7
  208. package/dist/hooks/use-view-tool-query.d.ts.map +1 -1
  209. package/dist/hooks/use-view-tool-query.js +15 -14
  210. package/dist/hooks/use-view-tool-query.js.map +1 -1
  211. package/dist/index.d.ts +27 -13
  212. package/dist/index.d.ts.map +1 -1
  213. package/dist/index.js +29 -7
  214. package/dist/index.js.map +1 -1
  215. package/dist/lib/focus-return.d.ts +61 -0
  216. package/dist/lib/focus-return.d.ts.map +1 -0
  217. package/dist/lib/focus-return.js +46 -0
  218. package/dist/lib/focus-return.js.map +1 -0
  219. package/dist/lib/focus-ring.d.ts +18 -0
  220. package/dist/lib/focus-ring.d.ts.map +1 -0
  221. package/dist/lib/focus-ring.js +18 -0
  222. package/dist/lib/focus-ring.js.map +1 -0
  223. package/dist/lib/icon-stroke.d.ts +12 -0
  224. package/dist/lib/icon-stroke.d.ts.map +1 -0
  225. package/dist/lib/icon-stroke.js +12 -0
  226. package/dist/lib/icon-stroke.js.map +1 -0
  227. package/dist/lib/parse-tool-result.d.ts +23 -1
  228. package/dist/lib/parse-tool-result.d.ts.map +1 -1
  229. package/dist/lib/parse-tool-result.js +38 -2
  230. package/dist/lib/parse-tool-result.js.map +1 -1
  231. package/dist/lib/toast-model.d.ts +86 -0
  232. package/dist/lib/toast-model.d.ts.map +1 -0
  233. package/dist/lib/toast-model.js +102 -0
  234. package/dist/lib/toast-model.js.map +1 -0
  235. package/dist/lib/tone-utils.d.ts +95 -9
  236. package/dist/lib/tone-utils.d.ts.map +1 -1
  237. package/dist/lib/tone-utils.js +100 -9
  238. package/dist/lib/tone-utils.js.map +1 -1
  239. package/dist/lib/tool-query.d.ts +107 -0
  240. package/dist/lib/tool-query.d.ts.map +1 -0
  241. package/dist/lib/tool-query.js +182 -0
  242. package/dist/lib/tool-query.js.map +1 -0
  243. package/dist/lib/tool-result-observer.d.ts +108 -0
  244. package/dist/lib/tool-result-observer.d.ts.map +1 -0
  245. package/dist/lib/tool-result-observer.js +158 -0
  246. package/dist/lib/tool-result-observer.js.map +1 -0
  247. package/dist/lib/typography.d.ts +37 -0
  248. package/dist/lib/typography.d.ts.map +1 -0
  249. package/dist/lib/typography.js +41 -0
  250. package/dist/lib/typography.js.map +1 -0
  251. package/dist/lib/utils.d.ts.map +1 -1
  252. package/dist/lib/utils.js +11 -1
  253. package/dist/lib/utils.js.map +1 -1
  254. package/dist/locale/index.d.ts +3 -1
  255. package/dist/locale/index.d.ts.map +1 -1
  256. package/dist/locale/index.js +2 -1
  257. package/dist/locale/index.js.map +1 -1
  258. package/dist/locale/locale-provider.d.ts +42 -1
  259. package/dist/locale/locale-provider.d.ts.map +1 -1
  260. package/dist/locale/locale-provider.js +44 -3
  261. package/dist/locale/locale-provider.js.map +1 -1
  262. package/dist/locale/message-types.d.ts +336 -0
  263. package/dist/locale/message-types.d.ts.map +1 -0
  264. package/dist/locale/message-types.js +7 -0
  265. package/dist/locale/message-types.js.map +1 -0
  266. package/dist/locale/messages-de.d.ts +9 -0
  267. package/dist/locale/messages-de.d.ts.map +1 -0
  268. package/dist/locale/messages-de.js +185 -0
  269. package/dist/locale/messages-de.js.map +1 -0
  270. package/dist/locale/messages-en.d.ts +8 -0
  271. package/dist/locale/messages-en.d.ts.map +1 -0
  272. package/dist/locale/messages-en.js +184 -0
  273. package/dist/locale/messages-en.js.map +1 -0
  274. package/dist/locale/toolkit-messages.d.ts +57 -0
  275. package/dist/locale/toolkit-messages.d.ts.map +1 -0
  276. package/dist/locale/toolkit-messages.js +103 -0
  277. package/dist/locale/toolkit-messages.js.map +1 -0
  278. package/dist/primitives/alert.d.ts +1 -1
  279. package/dist/primitives/alert.d.ts.map +1 -1
  280. package/dist/primitives/alert.js +6 -2
  281. package/dist/primitives/alert.js.map +1 -1
  282. package/dist/primitives/badge.d.ts +1 -1
  283. package/dist/primitives/badge.d.ts.map +1 -1
  284. package/dist/primitives/badge.js +19 -6
  285. package/dist/primitives/badge.js.map +1 -1
  286. package/dist/primitives/button.d.ts +1 -1
  287. package/dist/primitives/button.d.ts.map +1 -1
  288. package/dist/primitives/button.js +12 -8
  289. package/dist/primitives/button.js.map +1 -1
  290. package/dist/primitives/card.js +4 -4
  291. package/dist/primitives/card.js.map +1 -1
  292. package/dist/primitives/dialog.d.ts +7 -3
  293. package/dist/primitives/dialog.d.ts.map +1 -1
  294. package/dist/primitives/dialog.js +22 -8
  295. package/dist/primitives/dialog.js.map +1 -1
  296. package/dist/primitives/input.d.ts.map +1 -1
  297. package/dist/primitives/input.js +4 -1
  298. package/dist/primitives/input.js.map +1 -1
  299. package/dist/primitives/scroll-area.js +1 -1
  300. package/dist/primitives/scroll-area.js.map +1 -1
  301. package/dist/primitives/select.d.ts.map +1 -1
  302. package/dist/primitives/select.js +6 -3
  303. package/dist/primitives/select.js.map +1 -1
  304. package/dist/primitives/sheet.d.ts +3 -1
  305. package/dist/primitives/sheet.d.ts.map +1 -1
  306. package/dist/primitives/sheet.js +17 -7
  307. package/dist/primitives/sheet.js.map +1 -1
  308. package/dist/primitives/skeleton.js +1 -1
  309. package/dist/primitives/skeleton.js.map +1 -1
  310. package/dist/primitives/switch.d.ts.map +1 -1
  311. package/dist/primitives/switch.js +2 -1
  312. package/dist/primitives/switch.js.map +1 -1
  313. package/dist/primitives/tabs.d.ts.map +1 -1
  314. package/dist/primitives/tabs.js +5 -3
  315. package/dist/primitives/tabs.js.map +1 -1
  316. package/dist/providers/query-provider.d.ts +32 -1
  317. package/dist/providers/query-provider.d.ts.map +1 -1
  318. package/dist/providers/query-provider.js +53 -4
  319. package/dist/providers/query-provider.js.map +1 -1
  320. package/dist/render-cases-primitives.js +1 -1
  321. package/dist/render-cases-primitives.js.map +1 -1
  322. package/dist/render-cases.d.ts.map +1 -1
  323. package/dist/render-cases.js +48 -6
  324. package/dist/render-cases.js.map +1 -1
  325. package/dist/render-effects.d.ts +42 -0
  326. package/dist/render-effects.d.ts.map +1 -0
  327. package/dist/render-effects.js +81 -0
  328. package/dist/render-effects.js.map +1 -0
  329. package/dist/render-scan.d.ts +25 -0
  330. package/dist/render-scan.d.ts.map +1 -0
  331. package/dist/render-scan.js +66 -0
  332. package/dist/render-scan.js.map +1 -0
  333. package/dist/theme/cd-tokens.d.ts +66 -0
  334. package/dist/theme/cd-tokens.d.ts.map +1 -0
  335. package/dist/theme/cd-tokens.js +64 -0
  336. package/dist/theme/cd-tokens.js.map +1 -0
  337. package/dist/theme/create-theme.d.ts +214 -39
  338. package/dist/theme/create-theme.d.ts.map +1 -1
  339. package/dist/theme/create-theme.js +204 -13
  340. package/dist/theme/create-theme.js.map +1 -1
  341. package/dist/theme/fonts.d.ts +38 -0
  342. package/dist/theme/fonts.d.ts.map +1 -0
  343. package/dist/theme/fonts.js +56 -0
  344. package/dist/theme/fonts.js.map +1 -0
  345. package/dist/theme/host-fonts.d.ts +39 -0
  346. package/dist/theme/host-fonts.d.ts.map +1 -0
  347. package/dist/theme/host-fonts.js +44 -0
  348. package/dist/theme/host-fonts.js.map +1 -0
  349. package/dist/theme/index.d.ts +8 -1
  350. package/dist/theme/index.d.ts.map +1 -1
  351. package/dist/theme/index.js +5 -1
  352. package/dist/theme/index.js.map +1 -1
  353. package/dist/theme/portal-container.d.ts +16 -0
  354. package/dist/theme/portal-container.d.ts.map +1 -0
  355. package/dist/theme/portal-container.js +19 -0
  356. package/dist/theme/portal-container.js.map +1 -0
  357. package/dist/theme/presets.d.ts +24 -9
  358. package/dist/theme/presets.d.ts.map +1 -1
  359. package/dist/theme/presets.js +44 -11
  360. package/dist/theme/presets.js.map +1 -1
  361. package/dist/theme/theme-provider.d.ts +27 -9
  362. package/dist/theme/theme-provider.d.ts.map +1 -1
  363. package/dist/theme/theme-provider.js +42 -20
  364. package/dist/theme/theme-provider.js.map +1 -1
  365. package/package.json +11 -5
  366. package/src/app/adapt-data-widget.tsx +2 -42
  367. package/src/app/builder/BuilderBanners.tsx +26 -13
  368. package/src/app/builder/CanvasRow.tsx +79 -32
  369. package/src/app/builder/CatalogueSheet.tsx +58 -35
  370. package/src/app/builder/CellPropsSheet.tsx +17 -2
  371. package/src/app/builder/DiscardDialog.tsx +59 -0
  372. package/src/app/builder/EmptyHint.tsx +16 -11
  373. package/src/app/builder/LayoutSurface.tsx +207 -67
  374. package/src/app/builder/PipelineStrip.tsx +265 -156
  375. package/src/app/builder/SaveDialog.tsx +25 -14
  376. package/src/app/builder/Toolbar.tsx +154 -57
  377. package/src/app/builder/Workspace.tsx +226 -56
  378. package/src/app/builder/builder-feedback.test.tsx +75 -0
  379. package/src/app/builder/builder-model.test.ts +5 -0
  380. package/src/app/builder/builder-model.ts +346 -6
  381. package/src/app/builder/builder-model.ux.test.ts +456 -0
  382. package/src/app/builder/builder-ux.test.tsx +844 -0
  383. package/src/app/builder/labels.ts +15 -121
  384. package/src/app/builder/reveal.ts +10 -0
  385. package/src/app/builder/status-chip.tsx +8 -4
  386. package/src/app/builder/use-builder-catalogue.ts +62 -19
  387. package/src/app/builder/use-builder-session.ts +68 -0
  388. package/src/app/builder/use-display-resolver.ts +24 -0
  389. package/src/app/builder/use-save-dashboard.ts +5 -0
  390. package/src/app/index.ts +20 -3
  391. package/src/app/layout-builder.tsx +193 -186
  392. package/src/app/mcp-app-view-chrome.test.tsx +487 -14
  393. package/src/app/mcp-app-view-chrome.tsx +328 -100
  394. package/src/app/mcp-app-view-states.tsx +140 -0
  395. package/src/app/mcp-app-view.effects.test.tsx +292 -0
  396. package/src/app/mcp-app-view.test.tsx +478 -0
  397. package/src/app/mcp-app-view.tsx +447 -190
  398. package/src/app/mcp-toolkit-app.test.tsx +40 -0
  399. package/src/app/mcp-toolkit-app.tsx +39 -8
  400. package/src/app/mcp-use-host-bridge.test.tsx +180 -0
  401. package/src/app/mcp-use-host-bridge.tsx +67 -24
  402. package/src/app/model-context.test.tsx +116 -0
  403. package/src/app/model-context.tsx +125 -0
  404. package/src/app/use-build-mode-focus.ts +62 -0
  405. package/src/app/use-view-actions.ts +89 -0
  406. package/src/app/use-view-lifecycle.ts +122 -0
  407. package/src/app/view-lifecycle.test.ts +443 -0
  408. package/src/app/view-lifecycle.ts +334 -0
  409. package/src/app/widget-fixture.effects.test.tsx +51 -0
  410. package/src/app/widget-fixture.render.test.tsx +81 -0
  411. package/src/app/widget-fixture.tsx +34 -11
  412. package/src/app/widget-props-sheet.tsx +67 -39
  413. package/src/app/widget-renderer.render.test.tsx +131 -0
  414. package/src/app/widget-renderer.tsx +136 -38
  415. package/src/components/DrillButton.tsx +24 -10
  416. package/src/components/EmptyState.tsx +83 -0
  417. package/src/components/ErrorState.tsx +204 -0
  418. package/src/components/FilterBar.test.tsx +82 -0
  419. package/src/components/FilterBar.tsx +56 -27
  420. package/src/components/GroupCard.tsx +3 -2
  421. package/src/components/KpiGrid.test.tsx +279 -0
  422. package/src/components/KpiGrid.tsx +329 -91
  423. package/src/components/ListFooter.test.tsx +116 -0
  424. package/src/components/ListFooter.tsx +110 -12
  425. package/src/components/PagedListFooter.test.tsx +140 -0
  426. package/src/components/PagedListFooter.tsx +107 -0
  427. package/src/components/Pills.test.tsx +77 -0
  428. package/src/components/Pills.tsx +78 -16
  429. package/src/components/SectionHeading.tsx +9 -3
  430. package/src/components/Toast.tsx +206 -0
  431. package/src/components/WidgetHeader.test.tsx +78 -0
  432. package/src/components/WidgetHeader.tsx +63 -16
  433. package/src/components/feedback-states.test.tsx +314 -0
  434. package/src/components/tone-figures.test.tsx +58 -0
  435. package/src/fonts.css +19 -0
  436. package/src/globals.css +9 -165
  437. package/src/hooks/index.ts +6 -3
  438. package/src/hooks/tool-result-recovery-model.test.ts +744 -0
  439. package/src/hooks/tool-result-recovery-model.ts +418 -0
  440. package/src/hooks/use-tool-query.effects.test.tsx +205 -0
  441. package/src/hooks/use-tool-query.ts +156 -33
  442. package/src/hooks/use-tool-result-recovery.effects.test.tsx +141 -0
  443. package/src/hooks/use-tool-result-recovery.test.ts +28 -5
  444. package/src/hooks/use-tool-result-recovery.ts +101 -131
  445. package/src/hooks/use-view-data.test.tsx +169 -0
  446. package/src/hooks/use-view-data.ts +131 -10
  447. package/src/hooks/use-view-tool-query.ts +25 -19
  448. package/src/i18n-coverage.test.tsx +425 -0
  449. package/src/index.ts +102 -13
  450. package/src/lib/focus-return.test.ts +288 -0
  451. package/src/lib/focus-return.ts +96 -0
  452. package/src/lib/focus-ring.ts +20 -0
  453. package/src/lib/icon-stroke.test.ts +59 -0
  454. package/src/lib/icon-stroke.ts +13 -0
  455. package/src/lib/parse-tool-result.test.ts +46 -1
  456. package/src/lib/parse-tool-result.ts +40 -2
  457. package/src/lib/toast-model.test.ts +233 -0
  458. package/src/lib/toast-model.ts +165 -0
  459. package/src/lib/tone-utils.test.ts +125 -16
  460. package/src/lib/tone-utils.ts +144 -15
  461. package/src/lib/tool-query.test.ts +569 -0
  462. package/src/lib/tool-query.ts +253 -0
  463. package/src/lib/tool-result-observer.test.ts +296 -0
  464. package/src/lib/tool-result-observer.ts +211 -0
  465. package/src/lib/typography.test.ts +45 -0
  466. package/src/lib/typography.ts +47 -0
  467. package/src/lib/utils.ts +12 -1
  468. package/src/locale/index.ts +14 -1
  469. package/src/locale/locale-provider.test.tsx +87 -0
  470. package/src/locale/locale-provider.tsx +90 -3
  471. package/src/locale/message-types.ts +337 -0
  472. package/src/locale/messages-de.ts +198 -0
  473. package/src/locale/messages-en.ts +196 -0
  474. package/src/locale/toolkit-messages.test.ts +349 -0
  475. package/src/locale/toolkit-messages.ts +143 -0
  476. package/src/no-hardcoded-copy.test.ts +432 -0
  477. package/src/primitives/alert.tsx +7 -2
  478. package/src/primitives/badge.tsx +19 -7
  479. package/src/primitives/button.tsx +13 -8
  480. package/src/primitives/card.tsx +4 -4
  481. package/src/primitives/dialog.tsx +42 -8
  482. package/src/primitives/input.tsx +5 -3
  483. package/src/primitives/scroll-area.tsx +1 -1
  484. package/src/primitives/select.tsx +7 -4
  485. package/src/primitives/sheet.tsx +33 -6
  486. package/src/primitives/skeleton.tsx +1 -1
  487. package/src/primitives/switch.tsx +4 -2
  488. package/src/primitives/tabs.tsx +9 -6
  489. package/src/providers/query-provider.test.tsx +154 -0
  490. package/src/providers/query-provider.tsx +66 -5
  491. package/src/render-cases-primitives.tsx +1 -1
  492. package/src/render-cases.tsx +82 -6
  493. package/src/render-effects.tsx +96 -0
  494. package/src/render-scan.ts +75 -0
  495. package/src/theme/cd-tokens.generated.css +48 -0
  496. package/src/theme/cd-tokens.test.ts +109 -0
  497. package/src/theme/cd-tokens.ts +67 -0
  498. package/src/theme/create-theme.test.ts +253 -5
  499. package/src/theme/create-theme.ts +341 -41
  500. package/src/theme/fonts.test.ts +85 -0
  501. package/src/theme/fonts.ts +72 -0
  502. package/src/theme/host-fonts.test.ts +135 -0
  503. package/src/theme/host-fonts.ts +52 -0
  504. package/src/theme/index.ts +15 -1
  505. package/src/theme/portal-container.ts +20 -0
  506. package/src/theme/presets.ts +44 -11
  507. package/src/theme/theme-css.test.ts +619 -0
  508. package/src/theme/theme-provider.test.tsx +82 -0
  509. package/src/theme/theme-provider.tsx +60 -24
  510. package/src/theme.css +344 -0
  511. package/ui-catalog.json +783 -49
@@ -0,0 +1,206 @@
1
+ import {
2
+ createContext,
3
+ useCallback,
4
+ useContext,
5
+ useEffect,
6
+ useMemo,
7
+ useReducer,
8
+ useRef,
9
+ type FocusEvent,
10
+ type ReactNode,
11
+ } from "react"
12
+ import { CircleAlert, CircleCheck, Info, TriangleAlert, X, type LucideIcon } from "lucide-react"
13
+ import { useToolkitMessages } from "../locale/locale-provider.js"
14
+ import { FOCUS_RING } from "../lib/focus-ring.js"
15
+ import { TONE_ICON } from "../lib/tone-utils.js"
16
+ import { cn } from "../lib/utils.js"
17
+ import {
18
+ createToast,
19
+ createToastTimer,
20
+ toastReducer,
21
+ type ToastItem,
22
+ type ToastOptions,
23
+ type ToastTimer,
24
+ type ToastTone,
25
+ } from "../lib/toast-model.js"
26
+
27
+ export type { ToastOptions, ToastTone } from "../lib/toast-model.js"
28
+
29
+ /** What {@link useToast} returns. */
30
+ export interface ToastApi {
31
+ /** Show a toast; returns its id (for an early {@link ToastApi.dismiss}). */
32
+ show: (options: ToastOptions) => number
33
+ /** Remove a toast before its timer runs out. */
34
+ dismiss: (id: number) => void
35
+ }
36
+
37
+ const ToastContext = createContext<ToastApi | null>(null)
38
+
39
+ /** Outside a provider `useToast()` degrades to a no-op instead of throwing. */
40
+ const NOOP_TOASTS: ToastApi = { show: () => -1, dismiss: () => {} }
41
+
42
+ /**
43
+ * Raise toasts from anywhere below a {@link ToastProvider}: `show({ tone,
44
+ * title })` after a write succeeded or failed, never a silent `console` line.
45
+ * Outside a provider it returns a no-op API, so a widget rendered in a bare
46
+ * fixture never crashes on feedback.
47
+ */
48
+ export function useToast(): ToastApi {
49
+ return useContext(ToastContext) ?? NOOP_TOASTS
50
+ }
51
+
52
+ /**
53
+ * Status edge per tone — the status colour as border, never as text. Repeated
54
+ * under `dark:` so the card's dark 3:1 rim (`dark:border-input`, a later rule)
55
+ * does not paint over it.
56
+ */
57
+ const TONE_EDGE: Record<ToastTone, string> = {
58
+ success: "border-l-success dark:border-l-success",
59
+ warning: "border-l-warning dark:border-l-warning",
60
+ danger: "border-l-danger dark:border-l-danger",
61
+ info: "border-l-info dark:border-l-info",
62
+ }
63
+
64
+ /**
65
+ * Lucide icon per tone, drawn in the tone colour (`TONE_ICON`, CI §3.3: status
66
+ * as edge and icon). The title next to it carries the message, so success and
67
+ * warning stay CI-exempt from 3:1 on light like every other status icon.
68
+ */
69
+ const TOAST_ICON: Record<ToastTone, LucideIcon> = {
70
+ success: CircleCheck,
71
+ warning: TriangleAlert,
72
+ danger: CircleAlert,
73
+ info: Info,
74
+ }
75
+
76
+ /**
77
+ * The stack of toasts — a presentational view over a list (the provider owns
78
+ * the state). The container is ONE persistent live region
79
+ * (`aria-live="polite"`, mounted before the first toast so that toast is
80
+ * announced, each new toast on its own: `aria-atomic="false"`), without
81
+ * stealing focus. Its attributes never change: a role or name that switched
82
+ * on with the first toast would make the browser rebuild the region in the
83
+ * same commit that inserts the toast, and a region created with its content
84
+ * already in it is not announced. So it carries no role (a generic element
85
+ * takes no name either): an idle stack is no second "status" next to a view's
86
+ * own loading status. Bottom centre, above dialogs (z 60), per CI §5/§8.
87
+ */
88
+ export function ToastViewport({
89
+ toasts,
90
+ onDismiss,
91
+ }: {
92
+ toasts: readonly ToastItem[]
93
+ onDismiss: (id: number) => void
94
+ }) {
95
+ const messages = useToolkitMessages()
96
+ return (
97
+ <div
98
+ data-slot="toast-viewport"
99
+ aria-live="polite"
100
+ aria-atomic="false"
101
+ className="pointer-events-none fixed inset-x-0 bottom-4 z-60 flex flex-col items-center gap-2 px-4"
102
+ >
103
+ {toasts.map((toast) => (
104
+ <ToastCard
105
+ key={toast.id}
106
+ toast={toast}
107
+ dismissLabel={messages.common.dismiss}
108
+ onDismiss={onDismiss}
109
+ />
110
+ ))}
111
+ </div>
112
+ )
113
+ }
114
+
115
+ function ToastCard({
116
+ toast,
117
+ dismissLabel,
118
+ onDismiss,
119
+ }: {
120
+ toast: ToastItem
121
+ dismissLabel: string
122
+ onDismiss: (id: number) => void
123
+ }) {
124
+ // Hover or keyboard focus holds the toast; on leave it resumes with the
125
+ // time that was LEFT (createToastTimer), never a fresh full duration.
126
+ const timer = useRef<ToastTimer | null>(null)
127
+ useEffect(() => {
128
+ const countdown = createToastTimer(toast.duration, () => onDismiss(toast.id))
129
+ timer.current = countdown
130
+ return () => {
131
+ countdown.cancel()
132
+ timer.current = null
133
+ }
134
+ }, [onDismiss, toast.id, toast.duration])
135
+ const releaseFocus = (event: FocusEvent<HTMLDivElement>) => {
136
+ // Focus moving inside the toast (card → close button) keeps the hold.
137
+ if (!event.currentTarget.contains(event.relatedTarget)) {
138
+ timer.current?.release("focus")
139
+ }
140
+ }
141
+ const Icon = TOAST_ICON[toast.tone]
142
+ return (
143
+ <div
144
+ data-slot="toast"
145
+ data-tone={toast.tone}
146
+ onMouseEnter={() => timer.current?.hold("pointer")}
147
+ onMouseLeave={() => timer.current?.release("pointer")}
148
+ onFocus={() => timer.current?.hold("focus")}
149
+ onBlur={releaseFocus}
150
+ className={cn(
151
+ // An overlay like Dialog/Sheet: shadow-2 on light, the 3:1 input rim on
152
+ // dark (shadows vanish on the ground). Its words are running text (16 px).
153
+ "bg-popover text-popover-foreground dark:border-input shadow-2 text-body pointer-events-auto flex w-full max-w-sm items-start gap-3 rounded-md border border-l-4 px-4 py-3",
154
+ "motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-bottom-2 motion-safe:duration-(--motion-base) motion-safe:ease-(--ease)",
155
+ TONE_EDGE[toast.tone],
156
+ )}
157
+ >
158
+ {/* mt-1 centres the 16 px icon on the first 16/1.6 line. */}
159
+ <Icon aria-hidden="true" className={cn("mt-1 size-4 shrink-0", TONE_ICON[toast.tone])} />
160
+ <div className="min-w-0 flex-1">
161
+ <p className="font-medium break-words">{toast.title}</p>
162
+ {toast.description && (
163
+ <p className="text-muted-foreground mt-0.5 break-words">{toast.description}</p>
164
+ )}
165
+ </div>
166
+ <button
167
+ type="button"
168
+ aria-label={dismissLabel}
169
+ onClick={() => onDismiss(toast.id)}
170
+ className={`text-muted-foreground hover:text-foreground -mr-1 inline-flex size-6 shrink-0 items-center justify-center rounded-sm ${FOCUS_RING}`}
171
+ >
172
+ <X aria-hidden="true" className="size-4" />
173
+ </button>
174
+ </div>
175
+ )
176
+ }
177
+
178
+ function ToastRoot({ children }: { children: ReactNode }) {
179
+ const [toasts, dispatch] = useReducer(toastReducer, [])
180
+ const nextId = useRef(0)
181
+ const dismiss = useCallback((id: number) => dispatch({ type: "dismiss", id }), [])
182
+ const show = useCallback((options: ToastOptions) => {
183
+ nextId.current += 1
184
+ const id = nextId.current
185
+ dispatch({ type: "add", toast: createToast(id, options) })
186
+ return id
187
+ }, [])
188
+ const api = useMemo<ToastApi>(() => ({ show, dismiss }), [show, dismiss])
189
+ return (
190
+ <ToastContext.Provider value={api}>
191
+ {children}
192
+ <ToastViewport toasts={toasts} onDismiss={dismiss} />
193
+ </ToastContext.Provider>
194
+ )
195
+ }
196
+
197
+ /**
198
+ * Provide toasts to a subtree and render their stack. Idempotent: nested
199
+ * inside another `ToastProvider` it adds nothing, so the app shell and an
200
+ * embedded builder share one stack and one live region. `McpAppView` mounts
201
+ * one for you.
202
+ */
203
+ export function ToastProvider({ children }: { children: ReactNode }) {
204
+ const parent = useContext(ToastContext)
205
+ return parent ? children : <ToastRoot>{children}</ToastRoot>
206
+ }
@@ -0,0 +1,78 @@
1
+ import { renderToStaticMarkup } from "react-dom/server"
2
+ import { describe, expect, it } from "vitest"
3
+ import { MICRO_LABEL } from "../lib/typography.js"
4
+ import { attribute, openingTags } from "../render-scan.js"
5
+ import { StatusBadge } from "./Pills.js"
6
+ import { SectionHeading } from "./SectionHeading.js"
7
+ import { WidgetHeader, type WidgetHeadingLevel } from "./WidgetHeader.js"
8
+
9
+ const classOf = (tag: string | undefined) => attribute(tag ?? "", "class") ?? ""
10
+
11
+ describe("WidgetHeader: one title at the level of its surface", () => {
12
+ it("is an h1 at the page-title size by default", () => {
13
+ const html = renderToStaticMarkup(<WidgetHeader title="Incidents" />)
14
+ expect(html).toMatch(/<h1 class="[^"]*text-title[^"]*">Incidents<\/h1>/)
15
+ expect(html).not.toMatch(/text-3xl|text-xs/)
16
+ })
17
+
18
+ it.each(["h2", "h3", "h4", "h5", "h6"] satisfies WidgetHeadingLevel[])(
19
+ "takes the heading level %s from `as`, keeping the size",
20
+ (level) => {
21
+ const html = renderToStaticMarkup(<WidgetHeader as={level} title="Incidents" />)
22
+ expect(html).toMatch(
23
+ new RegExp(`<${level} class="[^"]*text-title[^"]*">Incidents</${level}>`),
24
+ )
25
+ expect(html).not.toContain("<h1")
26
+ },
27
+ )
28
+
29
+ it("renders the compact detail size at the section step", () => {
30
+ const html = renderToStaticMarkup(<WidgetHeader as="h2" size="detail" title="Instance" />)
31
+ expect(classOf(openingTags(html, "h2")[0])).toContain("text-section")
32
+ expect(classOf(openingTags(html, "h2")[0])).not.toContain("text-title")
33
+ })
34
+
35
+ it("puts a state badge above the title and a suffix inside the heading", () => {
36
+ const html = renderToStaticMarkup(
37
+ <WidgetHeader
38
+ title="Invoice"
39
+ titleSuffix={<span>v3</span>}
40
+ badge={<StatusBadge tone="warning">Suspended</StatusBadge>}
41
+ sub="Updated 14:32"
42
+ actions={<button type="button">Refresh</button>}
43
+ />,
44
+ )
45
+ expect(html.indexOf("Suspended")).toBeLessThan(html.indexOf("<h1"))
46
+ expect(html).toMatch(/<h1[^>]*>Invoice<span>v3<\/span><\/h1>/)
47
+ expect(html).toContain("Updated 14:32")
48
+ expect(html).toContain("Refresh</button>")
49
+ expect(html).not.toContain("size-11")
50
+ // The meta row is a caption at the 13 px step, not running text in the
51
+ // dense-table size.
52
+ const meta = openingTags(html, "div").find((t) => /flex-wrap items-center gap-2/.test(t))
53
+ expect(classOf(meta)).toMatch(/(^| )text-small( |$)/)
54
+ expect(html).not.toMatch(/\btext-dense\b/)
55
+ })
56
+
57
+ it("still renders the deprecated icon tile, hidden from assistive tech", () => {
58
+ const html = renderToStaticMarkup(<WidgetHeader icon={<svg />} iconTone="info" title="Tasks" />)
59
+ const tile = openingTags(html, "div").find((t) => /size-11/.test(t))
60
+ expect(attribute(tile ?? "", "aria-hidden")).toBe("true")
61
+ expect(classOf(tile)).toContain("bg-info-soft")
62
+ })
63
+
64
+ it("merges a className onto the header", () => {
65
+ const html = renderToStaticMarkup(<WidgetHeader title="x" className="mb-6" />)
66
+ expect(classOf(openingTags(html, "header")[0])).toContain("mb-6")
67
+ })
68
+ })
69
+
70
+ describe("SectionHeading: a block label inside a widget body", () => {
71
+ it("is a 13 px caption (MICRO_LABEL), never in the dense-table size", () => {
72
+ const html = renderToStaticMarkup(<SectionHeading title="Recent" hint="3 new" />)
73
+ const row = classOf(openingTags(html, "div")[0])
74
+ expect(row).toContain(MICRO_LABEL)
75
+ expect(row).toContain("text-muted-foreground")
76
+ expect(html).not.toMatch(/\btext-dense\b/)
77
+ })
78
+ })
@@ -1,46 +1,93 @@
1
1
  import type { ReactNode } from "react"
2
- import { TONE_SOFT, type ToneVariant } from "../lib/tone-utils.js"
2
+ import { resolveTone, TONE_SOFT, type ToneName } from "../lib/tone-utils.js"
3
+ import { cn } from "../lib/utils.js"
4
+
5
+ /** Heading element of a {@link WidgetHeader} title. */
6
+ export type WidgetHeadingLevel = "h1" | "h2" | "h3" | "h4" | "h5" | "h6"
3
7
 
4
8
  export interface WidgetHeaderProps {
5
- /** Optional icon/glyph rendered in a tinted tile above the title. */
6
- icon?: ReactNode
7
- /** Tone for the icon tile. Default `"neutral"`. */
8
- iconTone?: ToneVariant
9
9
  /** The widget title. */
10
10
  title: ReactNode
11
- /** Subtitle/meta row under the title (e.g. a live pill + counts). */
11
+ /**
12
+ * Heading element of the title. Default `"h1"`: the widget is the page.
13
+ * Pick the level that keeps ONE outline per view — below a toolbar title
14
+ * (`McpAppView` `titleMode="show"`, an h2 by default) use `"h3"`, inside a
15
+ * composed view under its own heading one level below it. The size follows
16
+ * `size`, not the level.
17
+ */
18
+ as?: WidgetHeadingLevel
19
+ /**
20
+ * `"default"`: the page title (28 px / 700, the CI h2 style). `"detail"`:
21
+ * the compact detail-page title (21 px / 600, the CI h3 style).
22
+ */
23
+ size?: "default" | "detail"
24
+ /** Inline after the title inside the heading (e.g. a version chip). */
25
+ titleSuffix?: ReactNode
26
+ /** Above the title — a `StatusBadge` that says the state in words. */
27
+ badge?: ReactNode
28
+ /** Subtitle/meta row under the title (e.g. a live pill + counts), a 13 px caption row. */
12
29
  sub?: ReactNode
13
30
  /** Right-aligned actions slot (buttons, drill controls). */
14
31
  actions?: ReactNode
32
+ /**
33
+ * @deprecated A glyph in a tinted tile above every title is the icon-tile
34
+ * pattern the CI rules out (anti-slop U2). Say a state in words with a
35
+ * `StatusBadge` in {@link WidgetHeaderProps.badge}. Still rendered when set.
36
+ */
37
+ icon?: ReactNode
38
+ /** @deprecated Tone of the deprecated {@link WidgetHeaderProps.icon} tile. */
39
+ iconTone?: ToneName
40
+ className?: string
41
+ }
42
+
43
+ const TITLE_SIZE: Record<NonNullable<WidgetHeaderProps["size"]>, string> = {
44
+ default: "text-title",
45
+ detail: "text-section",
15
46
  }
16
47
 
17
48
  /**
18
- * Page-level header for the top of a dashboard widget: an optional tinted icon
19
- * tile, a large title, a subtitle/meta row, and a right-aligned actions slot.
20
- * Use once per widget surface to anchor it.
49
+ * Page-level header at the top of a widget: an optional state badge, the
50
+ * title (heading level per `as`, size per `size`), a subtitle/meta row and a
51
+ * right-aligned actions slot. Use once per widget surface to anchor it.
21
52
  */
22
53
  export function WidgetHeader({
23
- icon,
24
- iconTone = "neutral",
25
54
  title,
55
+ as: Heading = "h1",
56
+ size = "default",
57
+ titleSuffix,
58
+ badge,
26
59
  sub,
27
60
  actions,
61
+ icon,
62
+ iconTone = "neutral",
63
+ className,
28
64
  }: WidgetHeaderProps) {
29
65
  return (
30
- <header className="flex flex-wrap items-start justify-between gap-4">
66
+ <header
67
+ data-slot="widget-header"
68
+ className={cn("flex flex-wrap items-start justify-between gap-4", className)}
69
+ >
31
70
  <div className="min-w-0">
32
71
  {icon && (
33
72
  <div
34
- className={`mb-3.5 grid size-11 place-items-center rounded-xl text-xl ${TONE_SOFT[iconTone]}`}
73
+ aria-hidden="true"
74
+ className={cn(
75
+ "text-section mb-3.5 grid size-11 place-items-center rounded-md",
76
+ TONE_SOFT[resolveTone(iconTone)],
77
+ )}
35
78
  >
36
79
  {icon}
37
80
  </div>
38
81
  )}
39
- <h1 className="text-foreground mb-1.5 text-3xl leading-tight font-bold tracking-tight">
82
+ {badge && <div className="mb-3">{badge}</div>}
83
+ <Heading
84
+ className={cn("text-foreground mb-1.5 tracking-tight break-words", TITLE_SIZE[size])}
85
+ >
40
86
  {title}
41
- </h1>
87
+ {titleSuffix}
88
+ </Heading>
42
89
  {sub && (
43
- <div className="text-muted-foreground flex flex-wrap items-center gap-2 text-sm">
90
+ <div className="text-muted-foreground text-small flex flex-wrap items-center gap-2">
44
91
  {sub}
45
92
  </div>
46
93
  )}