@miragon/mcp-toolkit-ui 2.7.0 → 2.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (387) hide show
  1. package/README.md +7 -4
  2. package/dist/app/adapt-data-widget.d.ts +1 -22
  3. package/dist/app/adapt-data-widget.d.ts.map +1 -1
  4. package/dist/app/adapt-data-widget.js +1 -35
  5. package/dist/app/adapt-data-widget.js.map +1 -1
  6. package/dist/app/builder/BuilderBanners.js +1 -1
  7. package/dist/app/builder/BuilderBanners.js.map +1 -1
  8. package/dist/app/builder/CanvasRow.d.ts +4 -2
  9. package/dist/app/builder/CanvasRow.d.ts.map +1 -1
  10. package/dist/app/builder/CanvasRow.js +21 -7
  11. package/dist/app/builder/CanvasRow.js.map +1 -1
  12. package/dist/app/builder/CatalogueSheet.d.ts.map +1 -1
  13. package/dist/app/builder/CatalogueSheet.js +11 -4
  14. package/dist/app/builder/CatalogueSheet.js.map +1 -1
  15. package/dist/app/builder/CellPropsSheet.d.ts +7 -3
  16. package/dist/app/builder/CellPropsSheet.d.ts.map +1 -1
  17. package/dist/app/builder/CellPropsSheet.js +10 -3
  18. package/dist/app/builder/CellPropsSheet.js.map +1 -1
  19. package/dist/app/builder/DiscardDialog.d.ts +18 -0
  20. package/dist/app/builder/DiscardDialog.d.ts.map +1 -0
  21. package/dist/app/builder/DiscardDialog.js +18 -0
  22. package/dist/app/builder/DiscardDialog.js.map +1 -0
  23. package/dist/app/builder/LayoutSurface.d.ts +33 -9
  24. package/dist/app/builder/LayoutSurface.d.ts.map +1 -1
  25. package/dist/app/builder/LayoutSurface.js +74 -23
  26. package/dist/app/builder/LayoutSurface.js.map +1 -1
  27. package/dist/app/builder/PipelineStrip.d.ts +2 -1
  28. package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
  29. package/dist/app/builder/PipelineStrip.js +26 -13
  30. package/dist/app/builder/PipelineStrip.js.map +1 -1
  31. package/dist/app/builder/SaveDialog.d.ts +9 -1
  32. package/dist/app/builder/SaveDialog.d.ts.map +1 -1
  33. package/dist/app/builder/SaveDialog.js +8 -2
  34. package/dist/app/builder/SaveDialog.js.map +1 -1
  35. package/dist/app/builder/Toolbar.d.ts +12 -4
  36. package/dist/app/builder/Toolbar.d.ts.map +1 -1
  37. package/dist/app/builder/Toolbar.js +18 -7
  38. package/dist/app/builder/Toolbar.js.map +1 -1
  39. package/dist/app/builder/Workspace.d.ts +23 -3
  40. package/dist/app/builder/Workspace.d.ts.map +1 -1
  41. package/dist/app/builder/Workspace.js +58 -8
  42. package/dist/app/builder/Workspace.js.map +1 -1
  43. package/dist/app/builder/builder-model.d.ts +143 -1
  44. package/dist/app/builder/builder-model.d.ts.map +1 -1
  45. package/dist/app/builder/builder-model.js +191 -1
  46. package/dist/app/builder/builder-model.js.map +1 -1
  47. package/dist/app/builder/reveal.d.ts +10 -0
  48. package/dist/app/builder/reveal.d.ts.map +1 -0
  49. package/dist/app/builder/reveal.js +10 -0
  50. package/dist/app/builder/reveal.js.map +1 -0
  51. package/dist/app/builder/use-builder-catalogue.d.ts +4 -1
  52. package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
  53. package/dist/app/builder/use-builder-catalogue.js +44 -17
  54. package/dist/app/builder/use-builder-catalogue.js.map +1 -1
  55. package/dist/app/builder/use-builder-session.d.ts +30 -0
  56. package/dist/app/builder/use-builder-session.d.ts.map +1 -0
  57. package/dist/app/builder/use-builder-session.js +58 -0
  58. package/dist/app/builder/use-builder-session.js.map +1 -0
  59. package/dist/app/builder/use-display-resolver.d.ts +17 -0
  60. package/dist/app/builder/use-display-resolver.d.ts.map +1 -0
  61. package/dist/app/builder/use-display-resolver.js +16 -0
  62. package/dist/app/builder/use-display-resolver.js.map +1 -0
  63. package/dist/app/index.d.ts +8 -3
  64. package/dist/app/index.d.ts.map +1 -1
  65. package/dist/app/index.js +8 -2
  66. package/dist/app/index.js.map +1 -1
  67. package/dist/app/layout-builder.d.ts +13 -25
  68. package/dist/app/layout-builder.d.ts.map +1 -1
  69. package/dist/app/layout-builder.js +75 -81
  70. package/dist/app/layout-builder.js.map +1 -1
  71. package/dist/app/mcp-app-view-chrome.d.ts +12 -3
  72. package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
  73. package/dist/app/mcp-app-view-chrome.js +21 -5
  74. package/dist/app/mcp-app-view-chrome.js.map +1 -1
  75. package/dist/app/mcp-app-view-states.d.ts +11 -3
  76. package/dist/app/mcp-app-view-states.d.ts.map +1 -1
  77. package/dist/app/mcp-app-view-states.js +29 -8
  78. package/dist/app/mcp-app-view-states.js.map +1 -1
  79. package/dist/app/mcp-app-view.d.ts +33 -1
  80. package/dist/app/mcp-app-view.d.ts.map +1 -1
  81. package/dist/app/mcp-app-view.js +181 -127
  82. package/dist/app/mcp-app-view.js.map +1 -1
  83. package/dist/app/mcp-toolkit-app.d.ts +6 -1
  84. package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
  85. package/dist/app/mcp-toolkit-app.js +8 -1
  86. package/dist/app/mcp-toolkit-app.js.map +1 -1
  87. package/dist/app/mcp-use-host-bridge.d.ts +15 -6
  88. package/dist/app/mcp-use-host-bridge.d.ts.map +1 -1
  89. package/dist/app/mcp-use-host-bridge.js +51 -22
  90. package/dist/app/mcp-use-host-bridge.js.map +1 -1
  91. package/dist/app/model-context.d.ts +71 -0
  92. package/dist/app/model-context.d.ts.map +1 -0
  93. package/dist/app/model-context.js +101 -0
  94. package/dist/app/model-context.js.map +1 -0
  95. package/dist/app/use-build-mode-focus.d.ts +33 -0
  96. package/dist/app/use-build-mode-focus.d.ts.map +1 -0
  97. package/dist/app/use-build-mode-focus.js +59 -0
  98. package/dist/app/use-build-mode-focus.js.map +1 -0
  99. package/dist/app/use-view-actions.d.ts +31 -0
  100. package/dist/app/use-view-actions.d.ts.map +1 -0
  101. package/dist/app/use-view-actions.js +81 -0
  102. package/dist/app/use-view-actions.js.map +1 -0
  103. package/dist/app/use-view-lifecycle.d.ts +4 -0
  104. package/dist/app/use-view-lifecycle.d.ts.map +1 -1
  105. package/dist/app/use-view-lifecycle.js +2 -0
  106. package/dist/app/use-view-lifecycle.js.map +1 -1
  107. package/dist/app/view-lifecycle.d.ts +80 -4
  108. package/dist/app/view-lifecycle.d.ts.map +1 -1
  109. package/dist/app/view-lifecycle.js +90 -3
  110. package/dist/app/view-lifecycle.js.map +1 -1
  111. package/dist/app/widget-fixture.d.ts +10 -3
  112. package/dist/app/widget-fixture.d.ts.map +1 -1
  113. package/dist/app/widget-fixture.js +21 -8
  114. package/dist/app/widget-fixture.js.map +1 -1
  115. package/dist/app/widget-props-sheet.d.ts +3 -1
  116. package/dist/app/widget-props-sheet.d.ts.map +1 -1
  117. package/dist/app/widget-props-sheet.js +22 -10
  118. package/dist/app/widget-props-sheet.js.map +1 -1
  119. package/dist/app/widget-renderer.js +1 -1
  120. package/dist/app/widget-renderer.js.map +1 -1
  121. package/dist/components/DrillButton.d.ts +9 -6
  122. package/dist/components/DrillButton.d.ts.map +1 -1
  123. package/dist/components/DrillButton.js +8 -6
  124. package/dist/components/DrillButton.js.map +1 -1
  125. package/dist/components/EmptyState.d.ts.map +1 -1
  126. package/dist/components/EmptyState.js +4 -2
  127. package/dist/components/EmptyState.js.map +1 -1
  128. package/dist/components/ErrorState.d.ts +5 -2
  129. package/dist/components/ErrorState.d.ts.map +1 -1
  130. package/dist/components/ErrorState.js +25 -8
  131. package/dist/components/ErrorState.js.map +1 -1
  132. package/dist/components/FilterBar.d.ts +15 -4
  133. package/dist/components/FilterBar.d.ts.map +1 -1
  134. package/dist/components/FilterBar.js +11 -6
  135. package/dist/components/FilterBar.js.map +1 -1
  136. package/dist/components/KpiGrid.d.ts +66 -21
  137. package/dist/components/KpiGrid.d.ts.map +1 -1
  138. package/dist/components/KpiGrid.js +101 -34
  139. package/dist/components/KpiGrid.js.map +1 -1
  140. package/dist/components/ListFooter.d.ts +31 -4
  141. package/dist/components/ListFooter.d.ts.map +1 -1
  142. package/dist/components/ListFooter.js +30 -11
  143. package/dist/components/ListFooter.js.map +1 -1
  144. package/dist/components/PagedListFooter.d.ts +57 -0
  145. package/dist/components/PagedListFooter.d.ts.map +1 -0
  146. package/dist/components/PagedListFooter.js +27 -0
  147. package/dist/components/PagedListFooter.js.map +1 -0
  148. package/dist/components/Pills.d.ts +27 -7
  149. package/dist/components/Pills.d.ts.map +1 -1
  150. package/dist/components/Pills.js +21 -6
  151. package/dist/components/Pills.js.map +1 -1
  152. package/dist/components/SectionHeading.d.ts +3 -1
  153. package/dist/components/SectionHeading.d.ts.map +1 -1
  154. package/dist/components/SectionHeading.js +6 -2
  155. package/dist/components/SectionHeading.js.map +1 -1
  156. package/dist/components/Toast.d.ts +9 -3
  157. package/dist/components/Toast.d.ts.map +1 -1
  158. package/dist/components/Toast.js +31 -16
  159. package/dist/components/Toast.js.map +1 -1
  160. package/dist/components/WidgetHeader.d.ts +34 -10
  161. package/dist/components/WidgetHeader.d.ts.map +1 -1
  162. package/dist/components/WidgetHeader.js +11 -6
  163. package/dist/components/WidgetHeader.js.map +1 -1
  164. package/dist/hooks/index.d.ts +4 -4
  165. package/dist/hooks/index.d.ts.map +1 -1
  166. package/dist/hooks/index.js +1 -1
  167. package/dist/hooks/index.js.map +1 -1
  168. package/dist/hooks/tool-result-recovery-model.d.ts +155 -0
  169. package/dist/hooks/tool-result-recovery-model.d.ts.map +1 -0
  170. package/dist/hooks/tool-result-recovery-model.js +273 -0
  171. package/dist/hooks/tool-result-recovery-model.js.map +1 -0
  172. package/dist/hooks/use-tool-query.d.ts +56 -14
  173. package/dist/hooks/use-tool-query.d.ts.map +1 -1
  174. package/dist/hooks/use-tool-query.js +102 -25
  175. package/dist/hooks/use-tool-query.js.map +1 -1
  176. package/dist/hooks/use-tool-result-recovery.d.ts +47 -52
  177. package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
  178. package/dist/hooks/use-tool-result-recovery.js +58 -120
  179. package/dist/hooks/use-tool-result-recovery.js.map +1 -1
  180. package/dist/hooks/use-view-data.d.ts +52 -10
  181. package/dist/hooks/use-view-data.d.ts.map +1 -1
  182. package/dist/hooks/use-view-data.js +81 -16
  183. package/dist/hooks/use-view-data.js.map +1 -1
  184. package/dist/hooks/use-view-tool-query.d.ts +12 -7
  185. package/dist/hooks/use-view-tool-query.d.ts.map +1 -1
  186. package/dist/hooks/use-view-tool-query.js +15 -14
  187. package/dist/hooks/use-view-tool-query.js.map +1 -1
  188. package/dist/index.d.ts +17 -10
  189. package/dist/index.d.ts.map +1 -1
  190. package/dist/index.js +18 -6
  191. package/dist/index.js.map +1 -1
  192. package/dist/lib/focus-return.d.ts +61 -0
  193. package/dist/lib/focus-return.d.ts.map +1 -0
  194. package/dist/lib/focus-return.js +46 -0
  195. package/dist/lib/focus-return.js.map +1 -0
  196. package/dist/lib/parse-tool-result.d.ts +23 -1
  197. package/dist/lib/parse-tool-result.d.ts.map +1 -1
  198. package/dist/lib/parse-tool-result.js +38 -2
  199. package/dist/lib/parse-tool-result.js.map +1 -1
  200. package/dist/lib/toast-model.d.ts +41 -1
  201. package/dist/lib/toast-model.d.ts.map +1 -1
  202. package/dist/lib/toast-model.js +67 -1
  203. package/dist/lib/toast-model.js.map +1 -1
  204. package/dist/lib/tone-utils.d.ts +58 -6
  205. package/dist/lib/tone-utils.d.ts.map +1 -1
  206. package/dist/lib/tone-utils.js +66 -4
  207. package/dist/lib/tone-utils.js.map +1 -1
  208. package/dist/lib/tool-query.d.ts +107 -0
  209. package/dist/lib/tool-query.d.ts.map +1 -0
  210. package/dist/lib/tool-query.js +182 -0
  211. package/dist/lib/tool-query.js.map +1 -0
  212. package/dist/lib/tool-result-observer.d.ts +108 -0
  213. package/dist/lib/tool-result-observer.d.ts.map +1 -0
  214. package/dist/lib/tool-result-observer.js +158 -0
  215. package/dist/lib/tool-result-observer.js.map +1 -0
  216. package/dist/lib/typography.d.ts +37 -0
  217. package/dist/lib/typography.d.ts.map +1 -0
  218. package/dist/lib/typography.js +41 -0
  219. package/dist/lib/typography.js.map +1 -0
  220. package/dist/lib/utils.d.ts.map +1 -1
  221. package/dist/lib/utils.js +11 -1
  222. package/dist/lib/utils.js.map +1 -1
  223. package/dist/locale/index.d.ts +1 -1
  224. package/dist/locale/index.d.ts.map +1 -1
  225. package/dist/locale/message-types.d.ts +117 -4
  226. package/dist/locale/message-types.d.ts.map +1 -1
  227. package/dist/locale/messages-de.d.ts.map +1 -1
  228. package/dist/locale/messages-de.js +44 -10
  229. package/dist/locale/messages-de.js.map +1 -1
  230. package/dist/locale/messages-en.d.ts.map +1 -1
  231. package/dist/locale/messages-en.js +44 -10
  232. package/dist/locale/messages-en.js.map +1 -1
  233. package/dist/locale/toolkit-messages.d.ts +19 -1
  234. package/dist/locale/toolkit-messages.d.ts.map +1 -1
  235. package/dist/locale/toolkit-messages.js +54 -1
  236. package/dist/locale/toolkit-messages.js.map +1 -1
  237. package/dist/primitives/alert.d.ts +1 -1
  238. package/dist/primitives/alert.d.ts.map +1 -1
  239. package/dist/primitives/alert.js +2 -0
  240. package/dist/primitives/alert.js.map +1 -1
  241. package/dist/primitives/badge.d.ts +1 -1
  242. package/dist/primitives/badge.d.ts.map +1 -1
  243. package/dist/primitives/badge.js +9 -4
  244. package/dist/primitives/badge.js.map +1 -1
  245. package/dist/primitives/button.d.ts +1 -1
  246. package/dist/primitives/button.js +1 -1
  247. package/dist/primitives/button.js.map +1 -1
  248. package/dist/primitives/dialog.d.ts +1 -1
  249. package/dist/primitives/dialog.d.ts.map +1 -1
  250. package/dist/primitives/dialog.js +10 -3
  251. package/dist/primitives/dialog.js.map +1 -1
  252. package/dist/primitives/select.js +1 -1
  253. package/dist/primitives/select.js.map +1 -1
  254. package/dist/primitives/sheet.d.ts +1 -1
  255. package/dist/primitives/sheet.d.ts.map +1 -1
  256. package/dist/primitives/sheet.js +6 -2
  257. package/dist/primitives/sheet.js.map +1 -1
  258. package/dist/providers/query-provider.d.ts +32 -1
  259. package/dist/providers/query-provider.d.ts.map +1 -1
  260. package/dist/providers/query-provider.js +53 -4
  261. package/dist/providers/query-provider.js.map +1 -1
  262. package/dist/render-cases-primitives.js +1 -1
  263. package/dist/render-cases-primitives.js.map +1 -1
  264. package/dist/render-cases.d.ts.map +1 -1
  265. package/dist/render-cases.js +30 -6
  266. package/dist/render-cases.js.map +1 -1
  267. package/dist/render-effects.d.ts +42 -0
  268. package/dist/render-effects.d.ts.map +1 -0
  269. package/dist/render-effects.js +81 -0
  270. package/dist/render-effects.js.map +1 -0
  271. package/dist/theme/create-theme.d.ts +19 -1
  272. package/dist/theme/create-theme.d.ts.map +1 -1
  273. package/dist/theme/create-theme.js +15 -0
  274. package/dist/theme/create-theme.js.map +1 -1
  275. package/package.json +5 -4
  276. package/src/app/adapt-data-widget.tsx +2 -42
  277. package/src/app/builder/BuilderBanners.tsx +1 -1
  278. package/src/app/builder/CanvasRow.tsx +63 -17
  279. package/src/app/builder/CatalogueSheet.tsx +50 -29
  280. package/src/app/builder/CellPropsSheet.tsx +17 -2
  281. package/src/app/builder/DiscardDialog.tsx +59 -0
  282. package/src/app/builder/LayoutSurface.tsx +206 -66
  283. package/src/app/builder/PipelineStrip.tsx +253 -153
  284. package/src/app/builder/SaveDialog.tsx +14 -2
  285. package/src/app/builder/Toolbar.tsx +144 -59
  286. package/src/app/builder/Workspace.tsx +226 -58
  287. package/src/app/builder/builder-model.ts +341 -2
  288. package/src/app/builder/builder-model.ux.test.ts +456 -0
  289. package/src/app/builder/builder-ux.test.tsx +844 -0
  290. package/src/app/builder/reveal.ts +10 -0
  291. package/src/app/builder/use-builder-catalogue.ts +56 -19
  292. package/src/app/builder/use-builder-session.ts +68 -0
  293. package/src/app/builder/use-display-resolver.ts +24 -0
  294. package/src/app/index.ts +12 -2
  295. package/src/app/layout-builder.tsx +178 -191
  296. package/src/app/mcp-app-view-chrome.test.tsx +141 -1
  297. package/src/app/mcp-app-view-chrome.tsx +56 -6
  298. package/src/app/mcp-app-view-states.tsx +51 -11
  299. package/src/app/mcp-app-view.effects.test.tsx +292 -0
  300. package/src/app/mcp-app-view.test.tsx +222 -2
  301. package/src/app/mcp-app-view.tsx +267 -117
  302. package/src/app/mcp-toolkit-app.test.tsx +40 -0
  303. package/src/app/mcp-toolkit-app.tsx +8 -1
  304. package/src/app/mcp-use-host-bridge.test.tsx +180 -0
  305. package/src/app/mcp-use-host-bridge.tsx +67 -24
  306. package/src/app/model-context.test.tsx +116 -0
  307. package/src/app/model-context.tsx +125 -0
  308. package/src/app/use-build-mode-focus.ts +62 -0
  309. package/src/app/use-view-actions.ts +89 -0
  310. package/src/app/use-view-lifecycle.ts +6 -0
  311. package/src/app/view-lifecycle.test.ts +216 -0
  312. package/src/app/view-lifecycle.ts +165 -5
  313. package/src/app/widget-fixture.effects.test.tsx +51 -0
  314. package/src/app/widget-fixture.render.test.tsx +81 -0
  315. package/src/app/widget-fixture.tsx +34 -11
  316. package/src/app/widget-props-sheet.tsx +57 -16
  317. package/src/app/widget-renderer.tsx +1 -1
  318. package/src/components/DrillButton.tsx +23 -10
  319. package/src/components/EmptyState.tsx +6 -4
  320. package/src/components/ErrorState.tsx +31 -9
  321. package/src/components/FilterBar.test.tsx +82 -0
  322. package/src/components/FilterBar.tsx +52 -26
  323. package/src/components/KpiGrid.test.tsx +279 -0
  324. package/src/components/KpiGrid.tsx +297 -90
  325. package/src/components/ListFooter.test.tsx +116 -0
  326. package/src/components/ListFooter.tsx +102 -15
  327. package/src/components/PagedListFooter.test.tsx +140 -0
  328. package/src/components/PagedListFooter.tsx +107 -0
  329. package/src/components/Pills.test.tsx +77 -0
  330. package/src/components/Pills.tsx +63 -10
  331. package/src/components/SectionHeading.tsx +9 -3
  332. package/src/components/Toast.tsx +37 -19
  333. package/src/components/WidgetHeader.test.tsx +78 -0
  334. package/src/components/WidgetHeader.tsx +63 -16
  335. package/src/components/feedback-states.test.tsx +98 -9
  336. package/src/components/tone-figures.test.tsx +8 -4
  337. package/src/hooks/index.ts +6 -3
  338. package/src/hooks/tool-result-recovery-model.test.ts +744 -0
  339. package/src/hooks/tool-result-recovery-model.ts +418 -0
  340. package/src/hooks/use-tool-query.effects.test.tsx +205 -0
  341. package/src/hooks/use-tool-query.ts +156 -33
  342. package/src/hooks/use-tool-result-recovery.effects.test.tsx +141 -0
  343. package/src/hooks/use-tool-result-recovery.test.ts +3 -4
  344. package/src/hooks/use-tool-result-recovery.ts +84 -142
  345. package/src/hooks/use-view-data.test.tsx +118 -9
  346. package/src/hooks/use-view-data.ts +128 -18
  347. package/src/hooks/use-view-tool-query.ts +25 -19
  348. package/src/i18n-coverage.test.tsx +104 -2
  349. package/src/index.ts +48 -11
  350. package/src/lib/focus-return.test.ts +288 -0
  351. package/src/lib/focus-return.ts +96 -0
  352. package/src/lib/parse-tool-result.test.ts +46 -1
  353. package/src/lib/parse-tool-result.ts +40 -2
  354. package/src/lib/toast-model.test.ts +166 -1
  355. package/src/lib/toast-model.ts +104 -2
  356. package/src/lib/tone-utils.test.ts +86 -10
  357. package/src/lib/tone-utils.ts +89 -8
  358. package/src/lib/tool-query.test.ts +569 -0
  359. package/src/lib/tool-query.ts +253 -0
  360. package/src/lib/tool-result-observer.test.ts +296 -0
  361. package/src/lib/tool-result-observer.ts +211 -0
  362. package/src/lib/typography.test.ts +45 -0
  363. package/src/lib/typography.ts +47 -0
  364. package/src/lib/utils.ts +12 -1
  365. package/src/locale/index.ts +1 -0
  366. package/src/locale/message-types.ts +118 -2
  367. package/src/locale/messages-de.ts +49 -10
  368. package/src/locale/messages-en.ts +49 -10
  369. package/src/locale/toolkit-messages.test.ts +133 -0
  370. package/src/locale/toolkit-messages.ts +63 -2
  371. package/src/primitives/alert.tsx +3 -0
  372. package/src/primitives/badge.tsx +9 -4
  373. package/src/primitives/button.tsx +1 -1
  374. package/src/primitives/dialog.tsx +10 -1
  375. package/src/primitives/select.tsx +1 -1
  376. package/src/primitives/sheet.tsx +7 -0
  377. package/src/providers/query-provider.test.tsx +154 -0
  378. package/src/providers/query-provider.tsx +66 -5
  379. package/src/render-cases-primitives.tsx +1 -1
  380. package/src/render-cases.tsx +38 -6
  381. package/src/render-effects.tsx +96 -0
  382. package/src/theme/cd-tokens.test.ts +3 -1
  383. package/src/theme/create-theme.test.ts +10 -0
  384. package/src/theme/create-theme.ts +28 -0
  385. package/src/theme/theme-css.test.ts +51 -0
  386. package/src/theme.css +31 -1
  387. package/ui-catalog.json +448 -41
@@ -1,9 +1,17 @@
1
- import { Plus, X } from "lucide-react"
1
+ import { useId, useRef, useState } from "react"
2
+ import { Pencil, Plus, X } from "lucide-react"
2
3
  import { Button } from "../../primitives/button.js"
3
4
  import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../primitives/tabs.js"
5
+ import { FOCUS_RING } from "../../lib/focus-ring.js"
4
6
  import { cn } from "../../lib/utils.js"
5
- import type { DraftLayout } from "./builder-model.js"
7
+ import {
8
+ createTabRefocus,
9
+ renameFieldKeyAction,
10
+ tabTriggerKeyAction,
11
+ type DraftLayout,
12
+ } from "./builder-model.js"
6
13
  import type { LayoutBuilderLabels } from "./labels.js"
14
+ import { REVEAL_ON_INTENT } from "./reveal.js"
7
15
  import { Workspace, type WorkspaceProps } from "./Workspace.js"
8
16
 
9
17
  // -------------------------------------------------------------------------- //
@@ -14,12 +22,13 @@ import { Workspace, type WorkspaceProps } from "./Workspace.js"
14
22
  /**
15
23
  * The "Layout" view's canvas surface, extracted from `layout-builder.tsx`.
16
24
  *
17
- * Renders either a single `Workspace` (rows draft) or the tab strip with
18
- * the inline-rename editor plus one `Workspace` per tab (tabs draft). All
19
- * state stays in the LayoutBuilder container — rename feedback included —
20
- * so unmounting this surface (e.g. switching to the Pipeline view) loses
21
- * nothing. Props in, callbacks out; the shared `workspace` bag is spread
22
- * into `<Workspace>` untouched so its memo semantics are unchanged.
25
+ * Renders either a single `Workspace` (rows draft, with an "Add tab" next to
26
+ * "Add row") or the tab strip plus one `Workspace` per tab (tabs draft). A tab
27
+ * is renamed with F2, Enter on the active tab, a double-click or its pencil
28
+ * button; Enter commits, Escape cancels, and either returns focus to the tab,
29
+ * also when the new name remounts it (see `TabRefocus`, held here by index).
30
+ * All state stays in the LayoutBuilder container — rename feedback included —
31
+ * so unmounting this surface (e.g. switching to the data sources) loses nothing.
23
32
  */
24
33
  export function LayoutSurface({
25
34
  L,
@@ -41,13 +50,18 @@ export function LayoutSurface({
41
50
  editingTabIdx: number | null
42
51
  setEditingTabIdx: (idx: number | null) => void
43
52
  renameRejected: boolean
44
- commitRename: (tabIdx: number, label: string) => void
53
+ /** Commits a rename; `false` when it was rejected and the field stays open. */
54
+ commitRename: (tabIdx: number, label: string) => boolean
45
55
  onAddTab: () => void
46
56
  onRemoveTab: (tabIdx: number) => void
47
- workspace: Omit<WorkspaceProps, "showAddTabButton" | "onAddTab">
57
+ workspace: Omit<WorkspaceProps, "onAddTab">
48
58
  }) {
59
+ const errorId = useId()
60
+ // One per surface, outside the tabs: a tab is keyed by its label, so a
61
+ // rename remounts it, and a focus request held by the tab would go with it.
62
+ const [refocus] = useState(createTabRefocus)
49
63
  if (draft.kind !== "tabs") {
50
- return <Workspace {...workspace} showAddTabButton onAddTab={onAddTab} />
64
+ return <Workspace {...workspace} onAddTab={onAddTab} />
51
65
  }
52
66
  return (
53
67
  <Tabs
@@ -57,59 +71,29 @@ export function LayoutSurface({
57
71
  if (idx >= 0) setActiveTabIndex(idx)
58
72
  }}
59
73
  >
60
- <div className="mb-3 flex items-center gap-1">
61
- <TabsList>
74
+ <div className="mb-3 flex flex-wrap items-center gap-1">
75
+ <TabsList
76
+ aria-label={L.tabsLabel}
77
+ className="flex-wrap group-data-[orientation=horizontal]/tabs:h-auto"
78
+ >
62
79
  {draft.tabs.map((tab, idx) => (
63
- <div key={tab.label} className="group relative inline-flex">
64
- <TabsTrigger
65
- value={tab.label}
66
- className="pr-7"
67
- onDoubleClick={() => setEditingTabIdx(idx)}
68
- title={L.renameTitle}
69
- >
70
- {editingTabIdx === idx ? (
71
- <input
72
- autoFocus
73
- defaultValue={tab.label}
74
- aria-invalid={renameRejected}
75
- onClick={(e) => e.stopPropagation()}
76
- onPointerDown={(e) => e.stopPropagation()}
77
- onKeyDown={(e) => {
78
- if (e.key === "Enter") {
79
- e.preventDefault()
80
- commitRename(idx, e.currentTarget.value)
81
- } else if (e.key === "Escape") {
82
- e.preventDefault()
83
- setEditingTabIdx(null)
84
- }
85
- }}
86
- onBlur={(e) => {
87
- commitRename(idx, e.currentTarget.value)
88
- }}
89
- className={cn(
90
- "focus-visible:ring-focus w-24 rounded-sm border-none bg-transparent p-0 text-inherit outline-hidden focus-visible:ring-2",
91
- renameRejected && "text-danger-ink",
92
- )}
93
- size={Math.max(tab.label.length + 1, 6)}
94
- />
95
- ) : (
96
- <span>{tab.label}</span>
97
- )}
98
- </TabsTrigger>
99
- <button
100
- type="button"
101
- aria-label={L.removeTab}
102
- title={L.removeTab}
103
- onPointerDown={(e) => e.stopPropagation()}
104
- onClick={(e) => {
105
- e.stopPropagation()
106
- onRemoveTab(idx)
107
- }}
108
- className="text-muted-foreground hover:text-foreground absolute top-1/2 right-1 -translate-y-1/2 rounded-sm p-0.5 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100 data-[state=active]:opacity-100"
109
- >
110
- <X className="size-3" />
111
- </button>
112
- </div>
80
+ <TabItem
81
+ key={tab.label}
82
+ L={L}
83
+ label={tab.label}
84
+ active={idx === activeTabIndex}
85
+ editing={editingTabIdx === idx}
86
+ renameRejected={renameRejected}
87
+ errorId={errorId}
88
+ onStartRename={() => {
89
+ setActiveTabIndex(idx)
90
+ setEditingTabIdx(idx)
91
+ }}
92
+ onCommitRename={(label) => commitRename(idx, label)}
93
+ onCancelRename={() => setEditingTabIdx(null)}
94
+ onRemove={() => onRemoveTab(idx)}
95
+ {...refocus.forTab(idx)}
96
+ />
113
97
  ))}
114
98
  </TabsList>
115
99
  <Button
@@ -119,14 +103,14 @@ export function LayoutSurface({
119
103
  aria-label={L.addTab}
120
104
  title={L.addTab}
121
105
  >
122
- <Plus />
106
+ <Plus aria-hidden="true" />
123
107
  </Button>
124
- <span className="text-muted-foreground ml-2 hidden text-[10px] sm:inline">
108
+ <span className="text-muted-foreground text-small ml-2 hidden sm:inline">
125
109
  {L.renameHint}
126
110
  </span>
127
111
  </div>
128
112
  {renameRejected && editingTabIdx !== null && (
129
- <p className="text-danger-ink -mt-1 mb-2 text-[11px]" role="alert">
113
+ <p id={errorId} className="text-danger-ink text-small -mt-1 mb-2" role="alert">
130
114
  {L.renameDuplicate}
131
115
  </p>
132
116
  )}
@@ -138,3 +122,159 @@ export function LayoutSurface({
138
122
  </Tabs>
139
123
  )
140
124
  }
125
+
126
+ // -------------------------------------------------------------------------- //
127
+ // One tab: trigger (or the rename field) plus its rename and remove buttons
128
+ // -------------------------------------------------------------------------- //
129
+
130
+ /**
131
+ * One tab. It holds no state of its own (it is keyed by its label, so a
132
+ * rename remounts it): the focus hand-back after a keyboard rename goes
133
+ * through `onRefocus` and `triggerRef` to the surface's `TabRefocus`.
134
+ * Exported for its tests only.
135
+ */
136
+ export function TabItem({
137
+ L,
138
+ label,
139
+ active,
140
+ editing,
141
+ renameRejected,
142
+ errorId,
143
+ onStartRename,
144
+ onCommitRename,
145
+ onCancelRename,
146
+ onRemove,
147
+ triggerRef,
148
+ onRefocus,
149
+ }: {
150
+ L: Required<LayoutBuilderLabels>
151
+ label: string
152
+ active: boolean
153
+ editing: boolean
154
+ renameRejected: boolean
155
+ errorId: string
156
+ onStartRename: () => void
157
+ onCommitRename: (label: string) => boolean
158
+ onCancelRename: () => void
159
+ onRemove: () => void
160
+ /** The trigger's ref callback: it takes the focus back after a keyboard rename. */
161
+ triggerRef: (el: HTMLButtonElement | null) => void
162
+ /** Asks for the focus to come back to this tab's trigger when it mounts again. */
163
+ onRefocus: () => void
164
+ }) {
165
+ return (
166
+ <div className="group inline-flex items-center" data-slot="builder-tab">
167
+ {editing ? (
168
+ <RenameField
169
+ L={L}
170
+ initial={label}
171
+ invalid={renameRejected}
172
+ errorId={errorId}
173
+ onCommit={(value, byKeyboard) => {
174
+ const accepted = onCommitRename(value)
175
+ // A pointer commit leaves the focus where the pointer went.
176
+ if (accepted && byKeyboard) onRefocus()
177
+ return accepted
178
+ }}
179
+ onCancel={() => {
180
+ onRefocus()
181
+ onCancelRename()
182
+ }}
183
+ />
184
+ ) : (
185
+ <TabsTrigger
186
+ ref={triggerRef}
187
+ value={label}
188
+ title={L.renameTitle}
189
+ onDoubleClick={onStartRename}
190
+ onKeyDown={(e) => {
191
+ if (tabTriggerKeyAction(e.key, active) !== "rename") return
192
+ e.preventDefault()
193
+ onStartRename()
194
+ }}
195
+ >
196
+ {label}
197
+ </TabsTrigger>
198
+ )}
199
+ <div
200
+ data-slot="builder-tab-actions"
201
+ className={cn("flex items-center", active ? "opacity-100" : REVEAL_ON_INTENT)}
202
+ >
203
+ {!editing && (
204
+ <Button
205
+ variant="ghost"
206
+ size="icon-xs"
207
+ aria-label={L.renameTabNamed(label)}
208
+ title={L.renameTab}
209
+ onClick={onStartRename}
210
+ >
211
+ <Pencil aria-hidden="true" />
212
+ </Button>
213
+ )}
214
+ <Button
215
+ variant="ghost"
216
+ size="icon-xs"
217
+ aria-label={L.removeTabNamed(label)}
218
+ title={L.removeTab}
219
+ onClick={onRemove}
220
+ >
221
+ <X aria-hidden="true" />
222
+ </Button>
223
+ </div>
224
+ </div>
225
+ )
226
+ }
227
+
228
+ /**
229
+ * The inline rename field, mounted for one rename. Enter commits (a rejected
230
+ * name keeps it open with the error), Escape cancels; leaving it by pointer
231
+ * commits too. A field that already ended by keyboard ignores the blur that
232
+ * its own unmount may fire.
233
+ */
234
+ function RenameField({
235
+ L,
236
+ initial,
237
+ invalid,
238
+ errorId,
239
+ onCommit,
240
+ onCancel,
241
+ }: {
242
+ L: Required<LayoutBuilderLabels>
243
+ initial: string
244
+ invalid: boolean
245
+ errorId: string
246
+ onCommit: (value: string, byKeyboard: boolean) => boolean
247
+ onCancel: () => void
248
+ }) {
249
+ const ended = useRef(false)
250
+ return (
251
+ <input
252
+ // The field replaces the tab the user just chose to rename: focus follows.
253
+ autoFocus
254
+ defaultValue={initial}
255
+ aria-label={L.renameTab}
256
+ aria-invalid={invalid}
257
+ aria-describedby={invalid ? errorId : undefined}
258
+ onKeyDown={(e) => {
259
+ const action = renameFieldKeyAction(e.key)
260
+ if (action === null) return
261
+ e.preventDefault()
262
+ if (action === "cancel") {
263
+ ended.current = true
264
+ onCancel()
265
+ return
266
+ }
267
+ if (onCommit(e.currentTarget.value, true)) ended.current = true
268
+ }}
269
+ onBlur={(e) => {
270
+ if (!ended.current) onCommit(e.currentTarget.value, false)
271
+ }}
272
+ className={cn(
273
+ "bg-background text-foreground h-7 w-28 rounded-sm border px-1.5 text-sm",
274
+ FOCUS_RING,
275
+ invalid && "border-danger",
276
+ )}
277
+ size={Math.max(initial.length + 1, 6)}
278
+ />
279
+ )
280
+ }