@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
@@ -12,14 +12,231 @@ import {
12
12
  SelectTrigger,
13
13
  SelectValue,
14
14
  } from "../../primitives/select.js"
15
- import { formatLiveKeyValue, valueTypeLabel, type KeyEntry } from "./builder-model.js"
15
+ import {
16
+ displayLabel,
17
+ formatLiveKeyValue,
18
+ valueTypeLabel,
19
+ type DisplayKeyResolver,
20
+ type KeyEntry,
21
+ } from "./builder-model.js"
16
22
  import type { LayoutBuilderLabels, RefreshStatus } from "./labels.js"
17
23
  import { StatusChip } from "./status-chip.js"
24
+ import { useDisplayResolver } from "./use-display-resolver.js"
18
25
 
19
26
  // -------------------------------------------------------------------------- //
20
- // Pipeline strip — compact horizontal Keys + Steps
27
+ // Pipeline strip — the data sources (advanced mode): keys + steps
21
28
  // -------------------------------------------------------------------------- //
22
29
 
30
+ type Labels = Required<LayoutBuilderLabels>
31
+
32
+ /** "needs a, b · provides c" in words (no arrow glyphs): a step's contract. */
33
+ function StepContract({ L, step }: { L: Labels; step: AvailableStep }) {
34
+ return (
35
+ <span className="text-muted-foreground text-small flex flex-wrap gap-x-2">
36
+ <span>
37
+ {L.catalogueNeedsKeys}{" "}
38
+ <span className="font-mono">
39
+ {step.requires.length ? step.requires.join(", ") : L.noInputs}
40
+ </span>
41
+ </span>
42
+ <span>
43
+ {L.stepProvides}{" "}
44
+ <span className="font-mono">
45
+ {step.produces.length ? step.produces.join(", ") : L.noOutputs}
46
+ </span>
47
+ </span>
48
+ </span>
49
+ )
50
+ }
51
+
52
+ function KeyRows({
53
+ L,
54
+ keyEntries,
55
+ keyCatalog,
56
+ liveKeys,
57
+ onUpdateKey,
58
+ onRemoveKey,
59
+ }: {
60
+ L: Labels
61
+ keyEntries: KeyEntry[]
62
+ keyCatalog: KeyCatalogEntry[]
63
+ liveKeys: Record<string, unknown>
64
+ onUpdateKey: (idx: number, patch: Partial<KeyEntry>) => void
65
+ onRemoveKey: (idx: number) => void
66
+ }) {
67
+ return (
68
+ <ul className="flex flex-col gap-1">
69
+ {keyEntries.map((entry, idx) => {
70
+ const livePreview = formatLiveKeyValue(liveKeys[entry.name], L.catalogueLive)
71
+ const usedNames = new Set(
72
+ keyEntries.map((e, i) => (i === idx ? "" : e.name)).filter(Boolean),
73
+ )
74
+ const pickable = keyCatalog.filter((c) => c.key === entry.name || !usedNames.has(c.key))
75
+ return (
76
+ <li key={idx} className="grid grid-cols-2 items-center gap-1">
77
+ <Select
78
+ value={entry.name || undefined}
79
+ onValueChange={(value) => onUpdateKey(idx, { name: value })}
80
+ >
81
+ <SelectTrigger aria-label={L.keyName} className="text-small h-7 min-w-0 font-mono">
82
+ {/* The trigger names the chosen key only; who uses it shows in the list. */}
83
+ <SelectValue placeholder={L.keyName}>{entry.name || null}</SelectValue>
84
+ </SelectTrigger>
85
+ <SelectContent>
86
+ {pickable.length === 0 ? (
87
+ <div className="text-muted-foreground text-small px-2 py-1.5 italic">
88
+ {L.noMoreKeys}
89
+ </div>
90
+ ) : (
91
+ pickable.map((c) => (
92
+ <SelectItem key={c.key} value={c.key} className="py-1.5">
93
+ <div className="flex flex-col gap-0.5">
94
+ <span className="text-small font-mono">{c.key}</span>
95
+ {c.consumedByWidgets.length + c.consumedBySteps.length > 0 && (
96
+ <span className="text-muted-foreground text-small">
97
+ {L.catalogueConsumedBy}{" "}
98
+ <span className="font-mono">
99
+ {[...c.consumedByWidgets, ...c.consumedBySteps].join(", ")}
100
+ </span>
101
+ </span>
102
+ )}
103
+ </div>
104
+ </SelectItem>
105
+ ))
106
+ )}
107
+ </SelectContent>
108
+ </Select>
109
+ <div className="flex min-w-0 items-center gap-1">
110
+ <div className="relative min-w-0 flex-1">
111
+ <Input
112
+ aria-label={L.keyValueFor(entry.name)}
113
+ value={entry.rawValue}
114
+ onChange={(e) => onUpdateKey(idx, { rawValue: e.target.value })}
115
+ placeholder={livePreview ?? L.keyValue}
116
+ className="text-small h-7 pr-14 font-mono"
117
+ />
118
+ <span
119
+ className="text-muted-foreground text-small pointer-events-none absolute top-1/2 right-2 -translate-y-1/2 tabular-nums"
120
+ title={L.parsedType}
121
+ >
122
+ {L.valueType(valueTypeLabel(entry.rawValue))}
123
+ </span>
124
+ </div>
125
+ <Button
126
+ variant="ghost"
127
+ size="icon-xs"
128
+ onClick={() => onRemoveKey(idx)}
129
+ aria-label={L.removeKey}
130
+ >
131
+ <X aria-hidden="true" />
132
+ </Button>
133
+ </div>
134
+ </li>
135
+ )
136
+ })}
137
+ </ul>
138
+ )
139
+ }
140
+
141
+ function StepRows({
142
+ L,
143
+ stepEntries,
144
+ stepLookup,
145
+ stepsByApp,
146
+ locale,
147
+ resolveKey,
148
+ onUpdateStep,
149
+ onRemoveStep,
150
+ }: {
151
+ L: Labels
152
+ stepEntries: PipelineStepRef[]
153
+ stepLookup: Map<string, AvailableStep>
154
+ stepsByApp: [string, AvailableStep[]][]
155
+ locale: string
156
+ resolveKey: DisplayKeyResolver
157
+ onUpdateStep: (idx: number, patch: Partial<PipelineStepRef>) => void
158
+ onRemoveStep: (idx: number) => void
159
+ }) {
160
+ return (
161
+ <ul className="flex flex-col gap-1">
162
+ {stepEntries.map((step, idx) => {
163
+ const meta = stepLookup.get(step.step)
164
+ const selected = meta ? displayLabel(meta, meta.id, locale, resolveKey).label : step.step
165
+ return (
166
+ <li key={idx} className="flex flex-col gap-0.5">
167
+ <div className="flex items-center gap-1">
168
+ <Input
169
+ aria-label={L.stepContextId}
170
+ value={step.id}
171
+ onChange={(e) => onUpdateStep(idx, { id: e.target.value })}
172
+ placeholder={L.stepContextId}
173
+ className="text-small h-7 w-24 font-mono"
174
+ />
175
+ <Select
176
+ value={step.step || undefined}
177
+ onValueChange={(value) => onUpdateStep(idx, { step: value })}
178
+ >
179
+ <SelectTrigger
180
+ aria-label={L.stepPickerLabel}
181
+ className="text-small h-7 min-w-0 flex-1"
182
+ >
183
+ {/* The trigger names the chosen step only; its contract follows below. */}
184
+ <SelectValue placeholder={L.stepPickerLabel}>
185
+ {step.step ? selected : null}
186
+ </SelectValue>
187
+ </SelectTrigger>
188
+ <SelectContent>
189
+ {stepsByApp.map(([app, items]) => (
190
+ <div key={app}>
191
+ <div className="text-muted-foreground text-small px-2 py-1 font-semibold">
192
+ {app}
193
+ </div>
194
+ {items.map((s) => {
195
+ const name = displayLabel(s, s.id, locale, resolveKey)
196
+ return (
197
+ <SelectItem key={s.id} value={s.id} className="py-2">
198
+ <div className="flex flex-col gap-0.5">
199
+ <span className="text-small font-medium">{name.label}</span>
200
+ {name.summary && (
201
+ <span className="text-muted-foreground text-small">
202
+ {name.summary}
203
+ </span>
204
+ )}
205
+ {name.hint && (
206
+ <span className="text-muted-foreground text-small font-mono">
207
+ {name.hint}
208
+ </span>
209
+ )}
210
+ <StepContract L={L} step={s} />
211
+ </div>
212
+ </SelectItem>
213
+ )
214
+ })}
215
+ </div>
216
+ ))}
217
+ </SelectContent>
218
+ </Select>
219
+ <Button
220
+ variant="ghost"
221
+ size="icon-xs"
222
+ onClick={() => onRemoveStep(idx)}
223
+ aria-label={L.removeStep}
224
+ >
225
+ <X aria-hidden="true" />
226
+ </Button>
227
+ </div>
228
+ {meta && (
229
+ <div className="ml-1 pl-24">
230
+ <StepContract L={L} step={meta} />
231
+ </div>
232
+ )}
233
+ </li>
234
+ )
235
+ })}
236
+ </ul>
237
+ )
238
+ }
239
+
23
240
  function PipelineStripImpl({
24
241
  L,
25
242
  keyEntries,
@@ -36,7 +253,7 @@ function PipelineStripImpl({
36
253
  onRemoveStep,
37
254
  status,
38
255
  }: {
39
- L: Required<LayoutBuilderLabels>
256
+ L: Labels
40
257
  keyEntries: KeyEntry[]
41
258
  stepEntries: PipelineStepRef[]
42
259
  keyCatalog: KeyCatalogEntry[]
@@ -51,6 +268,7 @@ function PipelineStripImpl({
51
268
  onRemoveStep: (idx: number) => void
52
269
  status: RefreshStatus
53
270
  }) {
271
+ const { locale, resolveKey } = useDisplayResolver()
54
272
  const stepLookup = useMemo(() => {
55
273
  const map = new Map<string, AvailableStep>()
56
274
  for (const s of availableSteps) map.set(s.id, s)
@@ -59,97 +277,36 @@ function PipelineStripImpl({
59
277
 
60
278
  return (
61
279
  <section className="bg-muted/30 -mx-1 rounded-lg border px-3 py-3">
62
- <div className="mb-2 flex items-center gap-2">
63
- <span className="text-muted-foreground text-[10px] font-semibold tracking-[0.12em] uppercase">
64
- {L.pipelineHeader}
65
- </span>
66
- <span className="text-muted-foreground text-[10px]">· {L.autoApplies}</span>
67
- <div className="ml-auto text-[11px]">
280
+ <div className="mb-2 flex flex-wrap items-center gap-2">
281
+ <h3 className="text-muted-foreground text-small font-semibold">{L.pipelineHeader}</h3>
282
+ <span className="text-muted-foreground text-small">{L.autoApplies}</span>
283
+ <div className="text-small ml-auto">
68
284
  <StatusChip status={status} L={L} />
69
285
  </div>
70
286
  </div>
71
287
 
72
288
  <div className="grid grid-cols-1 gap-x-6 gap-y-3 lg:grid-cols-2">
73
289
  <div className="flex flex-col gap-1.5">
74
- <div className="text-muted-foreground flex items-center gap-1.5 text-[11px] font-semibold">
75
- <ArrowRightToLine className="size-3" />
290
+ <div className="text-muted-foreground text-small flex items-center gap-1.5 font-semibold">
291
+ <ArrowRightToLine aria-hidden="true" className="size-3.5" />
76
292
  {L.keysHeader}
77
- <Badge variant="outline" className="px-1.5 text-[10px]">
293
+ <Badge variant="outline" className="px-1.5">
78
294
  {keyEntries.length}
79
295
  </Badge>
80
296
  </div>
81
297
  {keyEntries.length === 0 ? (
82
- <div className="text-muted-foreground rounded-md border border-dashed px-2 py-1.5 text-xs italic">
298
+ <div className="text-muted-foreground text-small rounded-md border border-dashed px-2 py-1.5 italic">
83
299
  {L.emptyKeys}
84
300
  </div>
85
301
  ) : (
86
- <ul className="flex flex-col gap-1">
87
- {keyEntries.map((entry, idx) => {
88
- const livePreview = formatLiveKeyValue(liveKeys[entry.name], L.catalogueLive)
89
- const usedNames = new Set(
90
- keyEntries.map((e, i) => (i === idx ? "" : e.name)).filter(Boolean),
91
- )
92
- const pickable = keyCatalog.filter(
93
- (c) => c.key === entry.name || !usedNames.has(c.key),
94
- )
95
- return (
96
- <li key={idx} className="grid grid-cols-2 items-center gap-1">
97
- <Select
98
- value={entry.name || undefined}
99
- onValueChange={(value) => onUpdateKey(idx, { name: value })}
100
- >
101
- <SelectTrigger className="h-7 min-w-0 font-mono text-xs">
102
- <SelectValue placeholder={L.keyName} />
103
- </SelectTrigger>
104
- <SelectContent>
105
- {pickable.length === 0 ? (
106
- <div className="text-muted-foreground px-2 py-1.5 text-xs italic">
107
- {L.noMoreKeys}
108
- </div>
109
- ) : (
110
- pickable.map((c) => (
111
- <SelectItem key={c.key} value={c.key} className="py-1.5">
112
- <div className="flex flex-col gap-0.5">
113
- <span className="font-mono text-xs">{c.key}</span>
114
- {c.consumedByWidgets.length + c.consumedBySteps.length > 0 && (
115
- <span className="text-muted-foreground font-mono text-[10px]">
116
- → {[...c.consumedByWidgets, ...c.consumedBySteps].join(", ")}
117
- </span>
118
- )}
119
- </div>
120
- </SelectItem>
121
- ))
122
- )}
123
- </SelectContent>
124
- </Select>
125
- <div className="flex min-w-0 items-center gap-1">
126
- <div className="relative min-w-0 flex-1">
127
- <Input
128
- value={entry.rawValue}
129
- onChange={(e) => onUpdateKey(idx, { rawValue: e.target.value })}
130
- placeholder={livePreview ?? L.keyValue}
131
- className="h-7 pr-10 font-mono text-xs"
132
- />
133
- <span
134
- className="text-muted-foreground pointer-events-none absolute top-1/2 right-2 -translate-y-1/2 font-mono text-[10px] tabular-nums"
135
- title={L.parsedType}
136
- >
137
- {L.valueType(valueTypeLabel(entry.rawValue))}
138
- </span>
139
- </div>
140
- <Button
141
- variant="ghost"
142
- size="icon-xs"
143
- onClick={() => onRemoveKey(idx)}
144
- aria-label={L.removeKey}
145
- >
146
- <X />
147
- </Button>
148
- </div>
149
- </li>
150
- )
151
- })}
152
- </ul>
302
+ <KeyRows
303
+ L={L}
304
+ keyEntries={keyEntries}
305
+ keyCatalog={keyCatalog}
306
+ liveKeys={liveKeys}
307
+ onUpdateKey={onUpdateKey}
308
+ onRemoveKey={onRemoveKey}
309
+ />
153
310
  )}
154
311
  <Button
155
312
  variant="ghost"
@@ -157,90 +314,33 @@ function PipelineStripImpl({
157
314
  onClick={() => onAddKey()}
158
315
  className="text-muted-foreground hover:text-foreground self-start"
159
316
  >
160
- <Plus /> {L.addKey}
317
+ <Plus aria-hidden="true" /> {L.addKey}
161
318
  </Button>
162
319
  </div>
163
320
 
164
321
  <div className="flex flex-col gap-1.5">
165
- <div className="text-muted-foreground flex items-center gap-1.5 text-[11px] font-semibold">
166
- <ArrowDownToLine className="size-3" />
322
+ <div className="text-muted-foreground text-small flex items-center gap-1.5 font-semibold">
323
+ <ArrowDownToLine aria-hidden="true" className="size-3.5" />
167
324
  {L.stepsHeader}
168
- <Badge variant="outline" className="px-1.5 text-[10px]">
325
+ <Badge variant="outline" className="px-1.5">
169
326
  {stepEntries.length}
170
327
  </Badge>
171
328
  </div>
172
329
  {stepEntries.length === 0 ? (
173
- <div className="text-muted-foreground rounded-md border border-dashed px-2 py-1.5 text-xs italic">
330
+ <div className="text-muted-foreground text-small rounded-md border border-dashed px-2 py-1.5 italic">
174
331
  {L.emptySteps}
175
332
  </div>
176
333
  ) : (
177
- <ul className="flex flex-col gap-1">
178
- {stepEntries.map((step, idx) => {
179
- const meta = stepLookup.get(step.step)
180
- return (
181
- <li key={idx} className="flex flex-col gap-0.5">
182
- <div className="flex items-center gap-1">
183
- <Input
184
- value={step.id}
185
- onChange={(e) => onUpdateStep(idx, { id: e.target.value })}
186
- placeholder={L.stepContextId}
187
- className="h-7 w-24 font-mono text-xs"
188
- />
189
- <Select
190
- value={step.step || undefined}
191
- onValueChange={(value) => onUpdateStep(idx, { step: value })}
192
- >
193
- <SelectTrigger className="h-7 flex-1 text-xs">
194
- <SelectValue placeholder={L.stepPickerLabel} />
195
- </SelectTrigger>
196
- <SelectContent>
197
- {stepsByApp.map(([app, items]) => (
198
- <div key={app}>
199
- <div className="text-muted-foreground px-2 py-1 text-[10px] font-semibold tracking-wide uppercase">
200
- {app}
201
- </div>
202
- {items.map((s) => (
203
- <SelectItem key={s.id} value={s.id} className="py-2">
204
- <div className="flex flex-col gap-0.5">
205
- <span className="font-mono text-xs">{s.id}</span>
206
- <div className="text-muted-foreground flex flex-wrap gap-x-2 text-[10px]">
207
- <span className="font-mono">
208
- ← {s.requires.length ? s.requires.join(", ") : L.noInputs}
209
- </span>
210
- <span className="font-mono">
211
- → {s.produces.length ? s.produces.join(", ") : L.noOutputs}
212
- </span>
213
- </div>
214
- </div>
215
- </SelectItem>
216
- ))}
217
- </div>
218
- ))}
219
- </SelectContent>
220
- </Select>
221
- <Button
222
- variant="ghost"
223
- size="icon-xs"
224
- onClick={() => onRemoveStep(idx)}
225
- aria-label={L.removeStep}
226
- >
227
- <X />
228
- </Button>
229
- </div>
230
- {meta && (
231
- <div className="text-muted-foreground ml-1 flex flex-wrap gap-x-2 pl-24 text-[10px]">
232
- <span className="font-mono">
233
- ← {meta.requires.length ? meta.requires.join(", ") : L.noInputs}
234
- </span>
235
- <span className="font-mono">
236
- → {meta.produces.length ? meta.produces.join(", ") : L.noOutputs}
237
- </span>
238
- </div>
239
- )}
240
- </li>
241
- )
242
- })}
243
- </ul>
334
+ <StepRows
335
+ L={L}
336
+ stepEntries={stepEntries}
337
+ stepLookup={stepLookup}
338
+ stepsByApp={stepsByApp}
339
+ locale={locale}
340
+ resolveKey={resolveKey}
341
+ onUpdateStep={onUpdateStep}
342
+ onRemoveStep={onRemoveStep}
343
+ />
244
344
  )}
245
345
  <Button
246
346
  variant="ghost"
@@ -249,7 +349,7 @@ function PipelineStripImpl({
249
349
  disabled={availableSteps.length === 0}
250
350
  className="text-muted-foreground hover:text-foreground self-start"
251
351
  >
252
- <Plus /> {L.addStep}
352
+ <Plus aria-hidden="true" /> {L.addStep}
253
353
  </Button>
254
354
  </div>
255
355
  </div>
@@ -16,10 +16,17 @@ import type { LayoutBuilderLabels } from "./labels.js"
16
16
  // Save dialog
17
17
  // -------------------------------------------------------------------------- //
18
18
 
19
+ /**
20
+ * Names the draft and saves it as a dashboard. Its description mentions Apply
21
+ * only where there is one (`canApply`: the builder has an `onExit`). Opens
22
+ * with the focus on the name field and hands it back to "Save as dashboard"
23
+ * when it closes.
24
+ */
19
25
  export function SaveDialog({
20
26
  L,
21
27
  open,
22
28
  onOpenChange,
29
+ canApply,
23
30
  name,
24
31
  setName,
25
32
  description,
@@ -31,6 +38,8 @@ export function SaveDialog({
31
38
  L: Required<LayoutBuilderLabels>
32
39
  open: boolean
33
40
  onOpenChange: (open: boolean) => void
41
+ /** The builder has a view to apply the draft to (an `onExit`). */
42
+ canApply: boolean
34
43
  name: string
35
44
  setName: (v: string) => void
36
45
  description: string
@@ -44,16 +53,19 @@ export function SaveDialog({
44
53
  <DialogContent>
45
54
  <DialogHeader>
46
55
  <DialogTitle>{L.saveDialogTitle}</DialogTitle>
47
- <DialogDescription>{L.saveDialogDescription}</DialogDescription>
56
+ <DialogDescription>
57
+ {canApply ? L.saveDialogDescription : L.saveDialogDescriptionStandalone}
58
+ </DialogDescription>
48
59
  </DialogHeader>
49
60
  <div className="flex flex-col gap-3">
50
61
  <label className="flex flex-col gap-1 text-sm">
51
62
  <span className="font-medium">{L.saveNameLabel}</span>
63
+ {/* No autoFocus: the dialog focuses this first field itself, and
64
+ only then notes where to hand the focus back on close. */}
52
65
  <Input
53
66
  value={name}
54
67
  onChange={(e) => setName(e.target.value)}
55
68
  placeholder={L.saveNamePlaceholder}
56
- autoFocus
57
69
  />
58
70
  </label>
59
71
  <label className="flex flex-col gap-1 text-sm">