@miragon/mcp-toolkit-ui 2.5.0 → 2.7.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 (348) hide show
  1. package/README.md +8 -2
  2. package/dist/app/builder/BuilderBanners.d.ts +7 -2
  3. package/dist/app/builder/BuilderBanners.d.ts.map +1 -1
  4. package/dist/app/builder/BuilderBanners.js +8 -3
  5. package/dist/app/builder/BuilderBanners.js.map +1 -1
  6. package/dist/app/builder/CanvasRow.d.ts.map +1 -1
  7. package/dist/app/builder/CanvasRow.js +12 -14
  8. package/dist/app/builder/CanvasRow.js.map +1 -1
  9. package/dist/app/builder/CatalogueSheet.d.ts.map +1 -1
  10. package/dist/app/builder/CatalogueSheet.js +6 -5
  11. package/dist/app/builder/CatalogueSheet.js.map +1 -1
  12. package/dist/app/builder/EmptyHint.d.ts +4 -0
  13. package/dist/app/builder/EmptyHint.d.ts.map +1 -1
  14. package/dist/app/builder/EmptyHint.js +6 -1
  15. package/dist/app/builder/EmptyHint.js.map +1 -1
  16. package/dist/app/builder/LayoutSurface.js +3 -3
  17. package/dist/app/builder/LayoutSurface.js.map +1 -1
  18. package/dist/app/builder/PipelineStrip.d.ts +3 -1
  19. package/dist/app/builder/PipelineStrip.d.ts.map +1 -1
  20. package/dist/app/builder/PipelineStrip.js +11 -6
  21. package/dist/app/builder/PipelineStrip.js.map +1 -1
  22. package/dist/app/builder/SaveDialog.d.ts.map +1 -1
  23. package/dist/app/builder/SaveDialog.js +2 -2
  24. package/dist/app/builder/SaveDialog.js.map +1 -1
  25. package/dist/app/builder/Toolbar.d.ts +3 -1
  26. package/dist/app/builder/Toolbar.d.ts.map +1 -1
  27. package/dist/app/builder/Toolbar.js +9 -3
  28. package/dist/app/builder/Toolbar.js.map +1 -1
  29. package/dist/app/builder/Workspace.js +2 -2
  30. package/dist/app/builder/Workspace.js.map +1 -1
  31. package/dist/app/builder/builder-model.d.ts +3 -2
  32. package/dist/app/builder/builder-model.d.ts.map +1 -1
  33. package/dist/app/builder/builder-model.js +5 -4
  34. package/dist/app/builder/builder-model.js.map +1 -1
  35. package/dist/app/builder/labels.d.ts +13 -62
  36. package/dist/app/builder/labels.d.ts.map +1 -1
  37. package/dist/app/builder/labels.js +9 -58
  38. package/dist/app/builder/labels.js.map +1 -1
  39. package/dist/app/builder/status-chip.d.ts.map +1 -1
  40. package/dist/app/builder/status-chip.js +3 -2
  41. package/dist/app/builder/status-chip.js.map +1 -1
  42. package/dist/app/builder/use-builder-catalogue.d.ts +1 -0
  43. package/dist/app/builder/use-builder-catalogue.d.ts.map +1 -1
  44. package/dist/app/builder/use-builder-catalogue.js +6 -0
  45. package/dist/app/builder/use-builder-catalogue.js.map +1 -1
  46. package/dist/app/builder/use-save-dashboard.d.ts +3 -1
  47. package/dist/app/builder/use-save-dashboard.d.ts.map +1 -1
  48. package/dist/app/builder/use-save-dashboard.js +3 -1
  49. package/dist/app/builder/use-save-dashboard.js.map +1 -1
  50. package/dist/app/index.d.ts +1 -1
  51. package/dist/app/index.d.ts.map +1 -1
  52. package/dist/app/index.js.map +1 -1
  53. package/dist/app/layout-builder.d.ts +7 -2
  54. package/dist/app/layout-builder.d.ts.map +1 -1
  55. package/dist/app/layout-builder.js +17 -5
  56. package/dist/app/layout-builder.js.map +1 -1
  57. package/dist/app/mcp-app-view-chrome.d.ts +94 -20
  58. package/dist/app/mcp-app-view-chrome.d.ts.map +1 -1
  59. package/dist/app/mcp-app-view-chrome.js +109 -40
  60. package/dist/app/mcp-app-view-chrome.js.map +1 -1
  61. package/dist/app/mcp-app-view-states.d.ts +15 -0
  62. package/dist/app/mcp-app-view-states.d.ts.map +1 -0
  63. package/dist/app/mcp-app-view-states.js +34 -0
  64. package/dist/app/mcp-app-view-states.js.map +1 -0
  65. package/dist/app/mcp-app-view.d.ts +40 -5
  66. package/dist/app/mcp-app-view.d.ts.map +1 -1
  67. package/dist/app/mcp-app-view.js +174 -128
  68. package/dist/app/mcp-app-view.js.map +1 -1
  69. package/dist/app/mcp-toolkit-app.d.ts +2 -1
  70. package/dist/app/mcp-toolkit-app.d.ts.map +1 -1
  71. package/dist/app/mcp-toolkit-app.js +25 -3
  72. package/dist/app/mcp-toolkit-app.js.map +1 -1
  73. package/dist/app/use-view-lifecycle.d.ts +38 -0
  74. package/dist/app/use-view-lifecycle.d.ts.map +1 -0
  75. package/dist/app/use-view-lifecycle.js +79 -0
  76. package/dist/app/use-view-lifecycle.js.map +1 -0
  77. package/dist/app/view-lifecycle.d.ts +109 -0
  78. package/dist/app/view-lifecycle.d.ts.map +1 -0
  79. package/dist/app/view-lifecycle.js +120 -0
  80. package/dist/app/view-lifecycle.js.map +1 -0
  81. package/dist/app/widget-props-sheet.d.ts +3 -9
  82. package/dist/app/widget-props-sheet.d.ts.map +1 -1
  83. package/dist/app/widget-props-sheet.js +6 -13
  84. package/dist/app/widget-props-sheet.js.map +1 -1
  85. package/dist/app/widget-renderer.d.ts +41 -1
  86. package/dist/app/widget-renderer.d.ts.map +1 -1
  87. package/dist/app/widget-renderer.js +82 -31
  88. package/dist/app/widget-renderer.js.map +1 -1
  89. package/dist/components/DrillButton.d.ts.map +1 -1
  90. package/dist/components/DrillButton.js +2 -1
  91. package/dist/components/DrillButton.js.map +1 -1
  92. package/dist/components/EmptyState.d.ts +33 -0
  93. package/dist/components/EmptyState.d.ts.map +1 -0
  94. package/dist/components/EmptyState.js +17 -0
  95. package/dist/components/EmptyState.js.map +1 -0
  96. package/dist/components/ErrorState.d.ts +50 -0
  97. package/dist/components/ErrorState.d.ts.map +1 -0
  98. package/dist/components/ErrorState.js +60 -0
  99. package/dist/components/ErrorState.js.map +1 -0
  100. package/dist/components/FilterBar.d.ts +1 -1
  101. package/dist/components/FilterBar.d.ts.map +1 -1
  102. package/dist/components/FilterBar.js +7 -4
  103. package/dist/components/FilterBar.js.map +1 -1
  104. package/dist/components/GroupCard.d.ts.map +1 -1
  105. package/dist/components/GroupCard.js +2 -1
  106. package/dist/components/GroupCard.js.map +1 -1
  107. package/dist/components/KpiGrid.d.ts +10 -3
  108. package/dist/components/KpiGrid.d.ts.map +1 -1
  109. package/dist/components/KpiGrid.js +31 -9
  110. package/dist/components/KpiGrid.js.map +1 -1
  111. package/dist/components/ListFooter.d.ts +3 -2
  112. package/dist/components/ListFooter.d.ts.map +1 -1
  113. package/dist/components/ListFooter.js +14 -4
  114. package/dist/components/ListFooter.js.map +1 -1
  115. package/dist/components/Pills.d.ts +10 -6
  116. package/dist/components/Pills.d.ts.map +1 -1
  117. package/dist/components/Pills.js +12 -6
  118. package/dist/components/Pills.js.map +1 -1
  119. package/dist/components/Toast.d.ts +37 -0
  120. package/dist/components/Toast.d.ts.map +1 -0
  121. package/dist/components/Toast.js +91 -0
  122. package/dist/components/Toast.js.map +1 -0
  123. package/dist/components/WidgetHeader.js +1 -1
  124. package/dist/hooks/use-tool-result-recovery.d.ts +23 -1
  125. package/dist/hooks/use-tool-result-recovery.d.ts.map +1 -1
  126. package/dist/hooks/use-tool-result-recovery.js +21 -7
  127. package/dist/hooks/use-tool-result-recovery.js.map +1 -1
  128. package/dist/hooks/use-view-data.d.ts +6 -0
  129. package/dist/hooks/use-view-data.d.ts.map +1 -1
  130. package/dist/hooks/use-view-data.js +6 -1
  131. package/dist/hooks/use-view-data.js.map +1 -1
  132. package/dist/index.d.ts +12 -5
  133. package/dist/index.d.ts.map +1 -1
  134. package/dist/index.js +14 -4
  135. package/dist/index.js.map +1 -1
  136. package/dist/lib/focus-ring.d.ts +18 -0
  137. package/dist/lib/focus-ring.d.ts.map +1 -0
  138. package/dist/lib/focus-ring.js +18 -0
  139. package/dist/lib/focus-ring.js.map +1 -0
  140. package/dist/lib/icon-stroke.d.ts +12 -0
  141. package/dist/lib/icon-stroke.d.ts.map +1 -0
  142. package/dist/lib/icon-stroke.js +12 -0
  143. package/dist/lib/icon-stroke.js.map +1 -0
  144. package/dist/lib/toast-model.d.ts +46 -0
  145. package/dist/lib/toast-model.d.ts.map +1 -0
  146. package/dist/lib/toast-model.js +36 -0
  147. package/dist/lib/toast-model.js.map +1 -0
  148. package/dist/lib/tone-utils.d.ts +43 -9
  149. package/dist/lib/tone-utils.d.ts.map +1 -1
  150. package/dist/lib/tone-utils.js +36 -7
  151. package/dist/lib/tone-utils.js.map +1 -1
  152. package/dist/locale/index.d.ts +3 -1
  153. package/dist/locale/index.d.ts.map +1 -1
  154. package/dist/locale/index.js +2 -1
  155. package/dist/locale/index.js.map +1 -1
  156. package/dist/locale/locale-provider.d.ts +42 -1
  157. package/dist/locale/locale-provider.d.ts.map +1 -1
  158. package/dist/locale/locale-provider.js +44 -3
  159. package/dist/locale/locale-provider.js.map +1 -1
  160. package/dist/locale/message-types.d.ts +223 -0
  161. package/dist/locale/message-types.d.ts.map +1 -0
  162. package/dist/locale/message-types.js +7 -0
  163. package/dist/locale/message-types.js.map +1 -0
  164. package/dist/locale/messages-de.d.ts +9 -0
  165. package/dist/locale/messages-de.d.ts.map +1 -0
  166. package/dist/locale/messages-de.js +151 -0
  167. package/dist/locale/messages-de.js.map +1 -0
  168. package/dist/locale/messages-en.d.ts +8 -0
  169. package/dist/locale/messages-en.d.ts.map +1 -0
  170. package/dist/locale/messages-en.js +150 -0
  171. package/dist/locale/messages-en.js.map +1 -0
  172. package/dist/locale/toolkit-messages.d.ts +39 -0
  173. package/dist/locale/toolkit-messages.d.ts.map +1 -0
  174. package/dist/locale/toolkit-messages.js +50 -0
  175. package/dist/locale/toolkit-messages.js.map +1 -0
  176. package/dist/primitives/alert.d.ts.map +1 -1
  177. package/dist/primitives/alert.js +4 -2
  178. package/dist/primitives/alert.js.map +1 -1
  179. package/dist/primitives/badge.d.ts +1 -1
  180. package/dist/primitives/badge.d.ts.map +1 -1
  181. package/dist/primitives/badge.js +14 -6
  182. package/dist/primitives/badge.js.map +1 -1
  183. package/dist/primitives/button.d.ts.map +1 -1
  184. package/dist/primitives/button.js +12 -8
  185. package/dist/primitives/button.js.map +1 -1
  186. package/dist/primitives/card.js +4 -4
  187. package/dist/primitives/card.js.map +1 -1
  188. package/dist/primitives/dialog.d.ts +7 -3
  189. package/dist/primitives/dialog.d.ts.map +1 -1
  190. package/dist/primitives/dialog.js +14 -7
  191. package/dist/primitives/dialog.js.map +1 -1
  192. package/dist/primitives/input.d.ts.map +1 -1
  193. package/dist/primitives/input.js +4 -1
  194. package/dist/primitives/input.js.map +1 -1
  195. package/dist/primitives/scroll-area.js +1 -1
  196. package/dist/primitives/scroll-area.js.map +1 -1
  197. package/dist/primitives/select.d.ts.map +1 -1
  198. package/dist/primitives/select.js +5 -2
  199. package/dist/primitives/select.js.map +1 -1
  200. package/dist/primitives/sheet.d.ts +3 -1
  201. package/dist/primitives/sheet.d.ts.map +1 -1
  202. package/dist/primitives/sheet.js +12 -6
  203. package/dist/primitives/sheet.js.map +1 -1
  204. package/dist/primitives/skeleton.js +1 -1
  205. package/dist/primitives/skeleton.js.map +1 -1
  206. package/dist/primitives/switch.d.ts.map +1 -1
  207. package/dist/primitives/switch.js +2 -1
  208. package/dist/primitives/switch.js.map +1 -1
  209. package/dist/primitives/tabs.d.ts.map +1 -1
  210. package/dist/primitives/tabs.js +5 -3
  211. package/dist/primitives/tabs.js.map +1 -1
  212. package/dist/render-cases.d.ts.map +1 -1
  213. package/dist/render-cases.js +20 -2
  214. package/dist/render-cases.js.map +1 -1
  215. package/dist/render-scan.d.ts +25 -0
  216. package/dist/render-scan.d.ts.map +1 -0
  217. package/dist/render-scan.js +66 -0
  218. package/dist/render-scan.js.map +1 -0
  219. package/dist/theme/cd-tokens.d.ts +66 -0
  220. package/dist/theme/cd-tokens.d.ts.map +1 -0
  221. package/dist/theme/cd-tokens.js +64 -0
  222. package/dist/theme/cd-tokens.js.map +1 -0
  223. package/dist/theme/create-theme.d.ts +196 -39
  224. package/dist/theme/create-theme.d.ts.map +1 -1
  225. package/dist/theme/create-theme.js +189 -13
  226. package/dist/theme/create-theme.js.map +1 -1
  227. package/dist/theme/fonts.d.ts +38 -0
  228. package/dist/theme/fonts.d.ts.map +1 -0
  229. package/dist/theme/fonts.js +56 -0
  230. package/dist/theme/fonts.js.map +1 -0
  231. package/dist/theme/host-fonts.d.ts +39 -0
  232. package/dist/theme/host-fonts.d.ts.map +1 -0
  233. package/dist/theme/host-fonts.js +44 -0
  234. package/dist/theme/host-fonts.js.map +1 -0
  235. package/dist/theme/index.d.ts +8 -1
  236. package/dist/theme/index.d.ts.map +1 -1
  237. package/dist/theme/index.js +5 -1
  238. package/dist/theme/index.js.map +1 -1
  239. package/dist/theme/portal-container.d.ts +16 -0
  240. package/dist/theme/portal-container.d.ts.map +1 -0
  241. package/dist/theme/portal-container.js +19 -0
  242. package/dist/theme/portal-container.js.map +1 -0
  243. package/dist/theme/presets.d.ts +24 -9
  244. package/dist/theme/presets.d.ts.map +1 -1
  245. package/dist/theme/presets.js +44 -11
  246. package/dist/theme/presets.js.map +1 -1
  247. package/dist/theme/theme-provider.d.ts +27 -9
  248. package/dist/theme/theme-provider.d.ts.map +1 -1
  249. package/dist/theme/theme-provider.js +42 -20
  250. package/dist/theme/theme-provider.js.map +1 -1
  251. package/package.json +13 -8
  252. package/src/app/builder/BuilderBanners.tsx +26 -13
  253. package/src/app/builder/CanvasRow.tsx +22 -21
  254. package/src/app/builder/CatalogueSheet.tsx +16 -14
  255. package/src/app/builder/EmptyHint.tsx +16 -11
  256. package/src/app/builder/LayoutSurface.tsx +7 -7
  257. package/src/app/builder/PipelineStrip.tsx +26 -17
  258. package/src/app/builder/SaveDialog.tsx +11 -12
  259. package/src/app/builder/Toolbar.tsx +19 -7
  260. package/src/app/builder/Workspace.tsx +5 -3
  261. package/src/app/builder/builder-feedback.test.tsx +75 -0
  262. package/src/app/builder/builder-model.test.ts +5 -0
  263. package/src/app/builder/builder-model.ts +5 -4
  264. package/src/app/builder/labels.ts +15 -121
  265. package/src/app/builder/status-chip.tsx +8 -4
  266. package/src/app/builder/use-builder-catalogue.ts +6 -0
  267. package/src/app/builder/use-save-dashboard.ts +5 -0
  268. package/src/app/index.ts +8 -1
  269. package/src/app/layout-builder.tsx +23 -3
  270. package/src/app/mcp-app-view-chrome.test.tsx +347 -14
  271. package/src/app/mcp-app-view-chrome.tsx +278 -100
  272. package/src/app/mcp-app-view-states.tsx +100 -0
  273. package/src/app/mcp-app-view.test.tsx +258 -0
  274. package/src/app/mcp-app-view.tsx +292 -185
  275. package/src/app/mcp-toolkit-app.tsx +31 -7
  276. package/src/app/use-view-lifecycle.ts +116 -0
  277. package/src/app/view-lifecycle.test.ts +227 -0
  278. package/src/app/view-lifecycle.ts +174 -0
  279. package/src/app/widget-props-sheet.tsx +13 -26
  280. package/src/app/widget-renderer.render.test.tsx +131 -0
  281. package/src/app/widget-renderer.tsx +136 -38
  282. package/src/components/DrillButton.tsx +2 -1
  283. package/src/components/EmptyState.tsx +81 -0
  284. package/src/components/ErrorState.tsx +182 -0
  285. package/src/components/FilterBar.tsx +9 -6
  286. package/src/components/GroupCard.tsx +3 -2
  287. package/src/components/KpiGrid.tsx +75 -44
  288. package/src/components/ListFooter.tsx +17 -6
  289. package/src/components/Pills.tsx +20 -11
  290. package/src/components/Toast.tsx +188 -0
  291. package/src/components/WidgetHeader.tsx +1 -1
  292. package/src/components/feedback-states.test.tsx +225 -0
  293. package/src/components/tone-figures.test.tsx +54 -0
  294. package/src/fonts.css +19 -0
  295. package/src/globals.css +9 -165
  296. package/src/hooks/use-tool-result-recovery.test.ts +25 -1
  297. package/src/hooks/use-tool-result-recovery.ts +34 -6
  298. package/src/hooks/use-view-data.test.tsx +60 -0
  299. package/src/hooks/use-view-data.ts +12 -1
  300. package/src/i18n-coverage.test.tsx +323 -0
  301. package/src/index.ts +57 -5
  302. package/src/lib/focus-ring.ts +20 -0
  303. package/src/lib/icon-stroke.test.ts +59 -0
  304. package/src/lib/icon-stroke.ts +13 -0
  305. package/src/lib/toast-model.test.ts +68 -0
  306. package/src/lib/toast-model.ts +63 -0
  307. package/src/lib/tone-utils.test.ts +47 -14
  308. package/src/lib/tone-utils.ts +61 -13
  309. package/src/locale/index.ts +13 -1
  310. package/src/locale/locale-provider.test.tsx +87 -0
  311. package/src/locale/locale-provider.tsx +90 -3
  312. package/src/locale/message-types.ts +221 -0
  313. package/src/locale/messages-de.ts +159 -0
  314. package/src/locale/messages-en.ts +157 -0
  315. package/src/locale/toolkit-messages.test.ts +216 -0
  316. package/src/locale/toolkit-messages.ts +82 -0
  317. package/src/no-hardcoded-copy.test.ts +432 -0
  318. package/src/primitives/alert.tsx +4 -2
  319. package/src/primitives/badge.tsx +14 -7
  320. package/src/primitives/button.tsx +13 -8
  321. package/src/primitives/card.tsx +4 -4
  322. package/src/primitives/dialog.tsx +32 -7
  323. package/src/primitives/input.tsx +5 -3
  324. package/src/primitives/scroll-area.tsx +1 -1
  325. package/src/primitives/select.tsx +6 -3
  326. package/src/primitives/sheet.tsx +26 -6
  327. package/src/primitives/skeleton.tsx +1 -1
  328. package/src/primitives/switch.tsx +4 -2
  329. package/src/primitives/tabs.tsx +9 -6
  330. package/src/render-cases.tsx +45 -1
  331. package/src/render-scan.ts +75 -0
  332. package/src/theme/cd-tokens.generated.css +48 -0
  333. package/src/theme/cd-tokens.test.ts +107 -0
  334. package/src/theme/cd-tokens.ts +67 -0
  335. package/src/theme/create-theme.test.ts +243 -5
  336. package/src/theme/create-theme.ts +313 -41
  337. package/src/theme/fonts.test.ts +85 -0
  338. package/src/theme/fonts.ts +72 -0
  339. package/src/theme/host-fonts.test.ts +135 -0
  340. package/src/theme/host-fonts.ts +52 -0
  341. package/src/theme/index.ts +15 -1
  342. package/src/theme/portal-container.ts +20 -0
  343. package/src/theme/presets.ts +44 -11
  344. package/src/theme/theme-css.test.ts +568 -0
  345. package/src/theme/theme-provider.test.tsx +82 -0
  346. package/src/theme/theme-provider.tsx +60 -24
  347. package/src/theme.css +314 -0
  348. package/ui-catalog.json +344 -17
@@ -1,35 +1,68 @@
1
1
  import { describe, expect, it } from "vitest"
2
- import { TONE_DOT, TONE_SOFT, TONE_TEXT, type ToneVariant } from "./tone-utils.js"
2
+ import {
3
+ TONE_BORDER,
4
+ TONE_DOT,
5
+ TONE_ICON,
6
+ TONE_SOFT,
7
+ TONE_TEXT,
8
+ type ToneVariant,
9
+ } from "./tone-utils.js"
3
10
 
4
11
  const ALL_TONES: ToneVariant[] = ["neutral", "info", "success", "warning", "danger"]
12
+ const STATUS_TONES = ["info", "success", "warning", "danger"] as const
13
+ const ALL_MAPS = { TONE_SOFT, TONE_DOT, TONE_TEXT, TONE_BORDER, TONE_ICON }
5
14
 
6
15
  describe("tone-utils", () => {
7
16
  it("covers every ToneVariant in each map (no missing tones)", () => {
8
- for (const map of [TONE_SOFT, TONE_DOT, TONE_TEXT]) {
17
+ for (const map of Object.values(ALL_MAPS)) {
9
18
  expect(Object.keys(map).sort()).toEqual([...ALL_TONES].sort())
10
19
  }
11
20
  })
12
21
 
13
22
  it("maps each tone to a non-empty class string in every map", () => {
14
- for (const tone of ALL_TONES) {
15
- expect(TONE_SOFT[tone], `soft:${tone}`).toBeTruthy()
16
- expect(TONE_DOT[tone], `dot:${tone}`).toBeTruthy()
17
- expect(TONE_TEXT[tone], `text:${tone}`).toBeTruthy()
23
+ for (const [name, map] of Object.entries(ALL_MAPS)) {
24
+ for (const tone of ALL_TONES) {
25
+ expect(map[tone], `${name}:${tone}`).toBeTruthy()
26
+ }
18
27
  }
19
28
  })
20
29
 
21
- it("routes each status tone to its matching design token", () => {
22
- expect(TONE_SOFT.danger).toBe("bg-danger-soft text-danger")
23
- expect(TONE_SOFT.warning).toBe("bg-warning-soft text-warning")
24
- expect(TONE_SOFT.success).toBe("bg-success-soft text-success")
25
- expect(TONE_SOFT.info).toBe("bg-info-soft text-info")
26
- expect(TONE_DOT.danger).toBe("bg-danger")
27
- expect(TONE_TEXT.success).toBe("text-success")
30
+ it("routes each status tone to its three roles (colour, tint, ink)", () => {
31
+ for (const tone of STATUS_TONES) {
32
+ expect(TONE_SOFT[tone]).toBe(`bg-${tone}-soft text-foreground`)
33
+ expect(TONE_TEXT[tone]).toBe(`text-${tone}-ink`)
34
+ expect(TONE_DOT[tone]).toBe(`bg-${tone}`)
35
+ expect(TONE_BORDER[tone]).toBe(`border-${tone}`)
36
+ expect(TONE_ICON[tone]).toBe(`text-${tone}`)
37
+ }
38
+ })
39
+
40
+ it("never sets text in a raw status colour outside the icon map (CI §3.3)", () => {
41
+ // Success and warning reach 1.67:1 / 1.83:1 on white; text takes the
42
+ // tone's -ink role. TONE_ICON is the one deliberate exception (SVG
43
+ // currentColor, always next to a readable label).
44
+ const rawStatusText = /\btext-(success|warning|danger|info)(?![-\w])/
45
+ for (const [name, map] of Object.entries({ TONE_SOFT, TONE_DOT, TONE_TEXT, TONE_BORDER })) {
46
+ for (const tone of ALL_TONES) {
47
+ expect(map[tone], `${name}:${tone}`).not.toMatch(rawStatusText)
48
+ }
49
+ }
50
+ })
51
+
52
+ it("puts the foreground on every status tint, never the ink or the status colour (CI §3.3)", () => {
53
+ // "-soft: Text darauf --cd-schwarz, Rand in der Statusfarbe" — the rim
54
+ // (TONE_BORDER) carries the tone, danger/info ink is for plain surfaces.
55
+ for (const tone of STATUS_TONES) {
56
+ expect(TONE_SOFT[tone]).not.toMatch(/\btext-(?:success|warning|danger|info)/)
57
+ expect(TONE_SOFT[tone]).toMatch(/\btext-foreground\b/)
58
+ }
28
59
  })
29
60
 
30
- it("routes the neutral tone to the shadcn muted ramp", () => {
61
+ it("routes the neutral tone to the muted ramp", () => {
31
62
  expect(TONE_SOFT.neutral).toBe("bg-muted text-muted-foreground")
32
63
  expect(TONE_DOT.neutral).toBe("bg-muted-foreground")
33
64
  expect(TONE_TEXT.neutral).toBe("text-foreground")
65
+ expect(TONE_BORDER.neutral).toBe("border-border")
66
+ expect(TONE_ICON.neutral).toBe("text-muted-foreground")
34
67
  })
35
68
  })
@@ -1,25 +1,46 @@
1
1
  /**
2
2
  * Single source of truth for the semantic "tones" used across the tone-aware
3
- * components (`Pills`, `KpiGrid`, `WidgetHeader`, …).
3
+ * components (`Pills`, `KpiGrid`, `WidgetHeader`, `Badge`, …).
4
4
  *
5
- * Each tone maps to the status tokens defined in `globals.css`
6
- * (`--danger`, `--warning`, `--success`, `--info`) plus the shadcn neutral ramp
7
- * for the `neutral` tone. All tokens carry light + dark values, so these class
8
- * strings re-theme automatically — change a tone in one place instead of
9
- * hand-rolling `tone === "x" ? "…" : "…"` ternaries at every call site.
5
+ * Every status tone has THREE roles (Miragon CI §3.3), each its own token in
6
+ * `theme.css` with light and dark values:
7
+ *
8
+ * | Role | Token | Map |
9
+ * | ---------------------------- | --------------- | -------------- |
10
+ * | fill, dot, border, icon | `--<tone>` | `TONE_DOT`, `TONE_BORDER`, `TONE_ICON` |
11
+ * | tint (badge/banner surface) | `--<tone>-soft` | `TONE_SOFT` (text on it: the foreground) |
12
+ * | text on a plain surface | `--<tone>-ink` | `TONE_TEXT` |
13
+ *
14
+ * Status is never text in its own colour: success and warning reach only
15
+ * 1.67:1 / 1.83:1 on white, so their ink is the foreground and the tone shows
16
+ * as a dot, icon or border NEXT to the text. On a tint the text is always the
17
+ * foreground (CI §3.3: "-soft: Text darauf --cd-schwarz, Rand in der
18
+ * Statusfarbe"), so pair `TONE_SOFT` with `TONE_BORDER`. `TONE_TEXT` is for
19
+ * a tone's words on a plain surface (a field error); figures — counts, KPI
20
+ * values, trends — never take it: they stay in the foreground next to a
21
+ * `TONE_DOT`. In dark mode the colours are the `-hell` values and the tints
22
+ * are transparent (no tinted fills on dark). The `neutral` tone reuses the
23
+ * muted ramp.
24
+ *
25
+ * Change a tone here, in one place, instead of hand-rolling
26
+ * `tone === "x" ? "…" : "…"` ternaries at every call site.
10
27
  */
11
28
  export type ToneVariant = "neutral" | "info" | "success" | "warning" | "danger"
12
29
 
13
- /** Tinted background + readable foreground — badges, icon tiles, pills. */
30
+ /**
31
+ * Tinted surface + its text (the foreground: CI §3.3) — badges, pills,
32
+ * banners. Pair it with {@link TONE_BORDER}: the rim carries the tone, and in
33
+ * dark mode (no tints) it is all that does.
34
+ */
14
35
  export const TONE_SOFT: Record<ToneVariant, string> = {
15
36
  neutral: "bg-muted text-muted-foreground",
16
- info: "bg-info-soft text-info",
17
- success: "bg-success-soft text-success",
18
- warning: "bg-warning-soft text-warning",
19
- danger: "bg-danger-soft text-danger",
37
+ info: "bg-info-soft text-foreground",
38
+ success: "bg-success-soft text-foreground",
39
+ warning: "bg-warning-soft text-foreground",
40
+ danger: "bg-danger-soft text-foreground",
20
41
  }
21
42
 
22
- /** Solid dot color — status dots next to a label. */
43
+ /** Solid dot colour — a status dot next to a label. */
23
44
  export const TONE_DOT: Record<ToneVariant, string> = {
24
45
  neutral: "bg-muted-foreground",
25
46
  info: "bg-info",
@@ -28,9 +49,36 @@ export const TONE_DOT: Record<ToneVariant, string> = {
28
49
  danger: "bg-danger",
29
50
  }
30
51
 
31
- /** Foreground-only color — metric values, inline emphasis. */
52
+ /**
53
+ * The tone's TEXT colour (its `-ink` role) for words on a plain surface — a
54
+ * field error, a "missing" label. Success and warning resolve to the
55
+ * foreground on light: pair the text with a {@link TONE_DOT} or
56
+ * {@link TONE_ICON} to show the tone. Never on a tint (use {@link TONE_SOFT})
57
+ * and never for figures (they stay in the foreground next to a dot).
58
+ */
32
59
  export const TONE_TEXT: Record<ToneVariant, string> = {
33
60
  neutral: "text-foreground",
61
+ info: "text-info-ink",
62
+ success: "text-success-ink",
63
+ warning: "text-warning-ink",
64
+ danger: "text-danger-ink",
65
+ }
66
+
67
+ /** Border colour in the tone — the rim of a tinted badge, banner or toast. */
68
+ export const TONE_BORDER: Record<ToneVariant, string> = {
69
+ neutral: "border-border",
70
+ info: "border-info",
71
+ success: "border-success",
72
+ warning: "border-warning",
73
+ danger: "border-danger",
74
+ }
75
+
76
+ /**
77
+ * Icon colour in the tone (SVG `currentColor`). For icons only — never for
78
+ * text: an icon next to its label carries the tone, the label stays readable.
79
+ */
80
+ export const TONE_ICON: Record<ToneVariant, string> = {
81
+ neutral: "text-muted-foreground",
34
82
  info: "text-info",
35
83
  success: "text-success",
36
84
  warning: "text-warning",
@@ -3,5 +3,17 @@
3
3
  // <LocaleProvider> and reads the active locale with useLocale/useTranslate,
4
4
  // without pulling in the host runtime. Pairs with `createTranslator` from
5
5
  // `@miragon/mcp-toolkit-core`.
6
- export { LocaleProvider, useLocale, useTranslate } from "./locale-provider.js"
6
+ export { LocaleProvider, useLocale, useTranslate, useToolkitMessages } from "./locale-provider.js"
7
7
  export type { LocaleContextValue, LocaleProviderProps, BoundTranslate } from "./locale-provider.js"
8
+ export { TOOLKIT_MESSAGES, formatCount, resolveToolkitMessages } from "./toolkit-messages.js"
9
+ export type {
10
+ BuilderMessages,
11
+ CommonMessages,
12
+ ListFooterMessages,
13
+ PropsSheetMessages,
14
+ RendererMessages,
15
+ ToolkitLocale,
16
+ ToolkitMessages,
17
+ ToolkitMessagesOverride,
18
+ ViewMessages,
19
+ } from "./toolkit-messages.js"
@@ -0,0 +1,87 @@
1
+ import type { ReactNode } from "react"
2
+ import { renderToStaticMarkup } from "react-dom/server"
3
+ import { describe, expect, it } from "vitest"
4
+ import { ListFooter } from "../components/ListFooter.js"
5
+ import {
6
+ LocaleProvider,
7
+ ToolkitLocaleFallback,
8
+ useLocale,
9
+ useToolkitLocale,
10
+ useToolkitMessages,
11
+ useTranslate,
12
+ type LocaleContextValue,
13
+ } from "./locale-provider.js"
14
+ import { TOOLKIT_MESSAGES } from "./toolkit-messages.js"
15
+
16
+ /**
17
+ * The locale contract: `LocaleProvider` sets the locale for everyone; the
18
+ * `ToolkitLocaleFallback` McpAppView mounts with the host's locale binds ONLY
19
+ * the toolkit's own strings and number format, so a consumer widget's
20
+ * `useLocale()`/`useTranslate()` keep their outside-a-provider behaviour.
21
+ */
22
+
23
+ function Probe() {
24
+ const messages = useToolkitMessages()
25
+ return (
26
+ <p>
27
+ {`locale=${useLocale()} toolkit=${useToolkitLocale()} t=${useTranslate()("k")} close=${messages.common.close}`}
28
+ </p>
29
+ )
30
+ }
31
+
32
+ const render = (node: ReactNode) => renderToStaticMarkup(node)
33
+
34
+ describe("ToolkitLocaleFallback", () => {
35
+ it("binds the toolkit's strings and number locale, not useLocale/useTranslate", () => {
36
+ expect(
37
+ render(
38
+ <ToolkitLocaleFallback locale="de-DE">
39
+ <Probe />
40
+ </ToolkitLocaleFallback>,
41
+ ),
42
+ ).toContain(`locale=en toolkit=de-DE t=k close=${TOOLKIT_MESSAGES.de.common.close}`)
43
+ })
44
+
45
+ it("yields to a LocaleProvider above or below it", () => {
46
+ const below = render(
47
+ <ToolkitLocaleFallback locale="de-DE">
48
+ <LocaleProvider locale="en-GB">
49
+ <Probe />
50
+ </LocaleProvider>
51
+ </ToolkitLocaleFallback>,
52
+ )
53
+ expect(below).toContain(
54
+ `locale=en-GB toolkit=en-GB t=k close=${TOOLKIT_MESSAGES.en.common.close}`,
55
+ )
56
+ const above = render(
57
+ <LocaleProvider locale="en">
58
+ <ToolkitLocaleFallback locale="de-DE">
59
+ <Probe />
60
+ </ToolkitLocaleFallback>
61
+ </LocaleProvider>,
62
+ )
63
+ expect(above).toContain(`locale=en toolkit=en t=k close=${TOOLKIT_MESSAGES.en.common.close}`)
64
+ })
65
+
66
+ it("keeps the defaults outside any provider", () => {
67
+ expect(render(<Probe />)).toContain(
68
+ `locale=en toolkit=en t=k close=${TOOLKIT_MESSAGES.en.common.close}`,
69
+ )
70
+ })
71
+
72
+ it("formats toolkit counts in the language of the sentence around them", () => {
73
+ const html = render(
74
+ <ToolkitLocaleFallback locale="de-DE">
75
+ <ListFooter shown={1200} total={4500} hasMore={false} onLoadMore={() => {}} />
76
+ </ToolkitLocaleFallback>,
77
+ )
78
+ expect(html).toContain("Zeigt 1.200 von 4.500 Zeilen")
79
+ })
80
+ })
81
+
82
+ describe("LocaleContextValue", () => {
83
+ it("accepts a hand-built value without messages (the field is optional)", () => {
84
+ const value: LocaleContextValue = { locale: "en", t: (key) => key }
85
+ expect(value.messages).toBeUndefined()
86
+ })
87
+ })
@@ -1,5 +1,10 @@
1
1
  import { createContext, useContext, useMemo, type ReactNode } from "react"
2
2
  import type { Translate } from "@miragon/mcp-toolkit-core"
3
+ import {
4
+ resolveToolkitMessages,
5
+ type ToolkitMessages,
6
+ type ToolkitMessagesOverride,
7
+ } from "./toolkit-messages.js"
3
8
 
4
9
  /**
5
10
  * A locale-bound translate: the active locale is already applied, so call sites
@@ -13,6 +18,14 @@ export interface LocaleContextValue {
13
18
  locale: string
14
19
  /** Translate a key in the active locale. */
15
20
  t: BoundTranslate
21
+ /**
22
+ * The toolkit's own strings for the active locale (its shipped `en`/`de`
23
+ * catalog, English for any other locale) with the provider's
24
+ * `toolkitMessages` override applied. Read it with {@link useToolkitMessages}.
25
+ * Optional on the type (a hand-built value may omit it); `LocaleProvider`
26
+ * always sets it.
27
+ */
28
+ messages?: ToolkitMessages
16
29
  }
17
30
 
18
31
  const DEFAULT_LOCALE = "en"
@@ -24,10 +37,22 @@ const DEFAULT_LOCALE = "en"
24
37
  * missing wrapper echoes the key (visible + greppable) instead of crashing a
25
38
  * widget that is perfectly renderable in English.
26
39
  */
27
- const DEFAULT_VALUE: LocaleContextValue = { locale: DEFAULT_LOCALE, t: (key) => key }
40
+ const DEFAULT_VALUE = {
41
+ locale: DEFAULT_LOCALE,
42
+ t: (key) => key,
43
+ messages: resolveToolkitMessages(DEFAULT_LOCALE),
44
+ } satisfies Required<LocaleContextValue>
28
45
 
29
46
  const LocaleContext = createContext<LocaleContextValue | null>(null)
30
47
 
48
+ /** The toolkit-only locale a {@link ToolkitLocaleFallback} binds (no `t`). */
49
+ interface ToolkitLocaleScope {
50
+ locale: string
51
+ messages: ToolkitMessages
52
+ }
53
+
54
+ const ToolkitLocaleFallbackContext = createContext<ToolkitLocaleScope | null>(null)
55
+
31
56
  /** Read the active locale tag from the nearest {@link LocaleProvider}. */
32
57
  export function useLocale(): string {
33
58
  return useContext(LocaleContext)?.locale ?? DEFAULT_VALUE.locale
@@ -42,6 +67,56 @@ export function useTranslate(): BoundTranslate {
42
67
  return useContext(LocaleContext)?.t ?? DEFAULT_VALUE.t
43
68
  }
44
69
 
70
+ /**
71
+ * The toolkit's own UI strings for the nearest {@link LocaleProvider}'s locale
72
+ * (English outside a provider). Every toolkit component reads its captions,
73
+ * labels and accessible names here, so a German locale renders no English
74
+ * toolkit chrome.
75
+ */
76
+ export function useToolkitMessages(): ToolkitMessages {
77
+ const provided = useContext(LocaleContext)
78
+ const fallback = useContext(ToolkitLocaleFallbackContext)
79
+ return provided?.messages ?? fallback?.messages ?? DEFAULT_VALUE.messages
80
+ }
81
+
82
+ /**
83
+ * The locale the toolkit's own text is in: the nearest {@link LocaleProvider}'s,
84
+ * else a {@link ToolkitLocaleFallback}'s (the host's, inside `McpAppView`),
85
+ * else `"en"`. Toolkit components format their numbers with it, so a count
86
+ * always matches the language of the sentence around it. Internal: consumer
87
+ * widgets read {@link useLocale}.
88
+ */
89
+ export function useToolkitLocale(): string {
90
+ const provided = useContext(LocaleContext)
91
+ const fallback = useContext(ToolkitLocaleFallbackContext)
92
+ return provided?.locale ?? fallback?.locale ?? DEFAULT_VALUE.locale
93
+ }
94
+
95
+ /**
96
+ * Binds ONLY the toolkit's own strings and number format to `locale` for a
97
+ * subtree — the fallback `McpAppView` mounts with the host's locale. It is not
98
+ * a {@link LocaleProvider}: {@link useLocale} and {@link useTranslate} keep
99
+ * their outside-a-provider behaviour (`"en"`, echoed keys) for consumer
100
+ * widgets, and any `LocaleProvider` above or below wins over it.
101
+ */
102
+ export function ToolkitLocaleFallback({
103
+ locale,
104
+ children,
105
+ }: {
106
+ locale: string
107
+ children: ReactNode
108
+ }): ReactNode {
109
+ const value = useMemo<ToolkitLocaleScope>(
110
+ () => ({ locale, messages: resolveToolkitMessages(locale) }),
111
+ [locale],
112
+ )
113
+ return (
114
+ <ToolkitLocaleFallbackContext.Provider value={value}>
115
+ {children}
116
+ </ToolkitLocaleFallbackContext.Provider>
117
+ )
118
+ }
119
+
45
120
  export interface LocaleProviderProps {
46
121
  /** The active locale tag (e.g. `"en"`, `"de"`). */
47
122
  locale: string
@@ -51,6 +126,12 @@ export interface LocaleProviderProps {
51
126
  * consumer wires the locale before any catalog exists.
52
127
  */
53
128
  translator?: Translate
129
+ /**
130
+ * Override individual toolkit strings for this subtree, per catalog section
131
+ * (e.g. `{ listFooter: { loadMore: "Show more" } }`). Omitted entries keep the
132
+ * shipped `en`/`de` catalog of `locale`.
133
+ */
134
+ toolkitMessages?: ToolkitMessagesOverride
54
135
  children: ReactNode
55
136
  }
56
137
 
@@ -69,13 +150,19 @@ export interface LocaleProviderProps {
69
150
  * <YourWidget />
70
151
  * </LocaleProvider>
71
152
  */
72
- export function LocaleProvider({ locale, translator, children }: LocaleProviderProps): ReactNode {
153
+ export function LocaleProvider({
154
+ locale,
155
+ translator,
156
+ toolkitMessages,
157
+ children,
158
+ }: LocaleProviderProps): ReactNode {
73
159
  const value = useMemo<LocaleContextValue>(
74
160
  () => ({
75
161
  locale,
76
162
  t: translator ? (key, params) => translator(locale, key, params) : (key) => key,
163
+ messages: resolveToolkitMessages(locale, toolkitMessages),
77
164
  }),
78
- [locale, translator],
165
+ [locale, translator, toolkitMessages],
79
166
  )
80
167
  return <LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>
81
168
  }
@@ -0,0 +1,221 @@
1
+ /**
2
+ * The shapes of the toolkit's message catalogs (see `toolkit-messages.ts`).
3
+ * Types only, kept apart from the catalogs so `messages-en.ts` /
4
+ * `messages-de.ts` can implement them without an import cycle.
5
+ */
6
+
7
+ /** Strings shared by several components. */
8
+ export interface CommonMessages {
9
+ /** Accessible name of the close button in dialogs and sheets. */
10
+ close: string
11
+ /** Retry action of error states. */
12
+ retry: string
13
+ /** Summary of a technical-details disclosure. */
14
+ details: string
15
+ /** Accessible name of a toast's close button. */
16
+ dismiss: string
17
+ /** Accessible name of the toast region. */
18
+ notifications: string
19
+ }
20
+
21
+ /** Strings of the `McpAppView` chrome (placeholder, error state, toolbar, step errors). */
22
+ export interface ViewMessages {
23
+ /** Placeholder text while the view's data is on its way. */
24
+ loading: string
25
+ /** Shown instead of the placeholder when the host cancelled the rendering call. */
26
+ cancelled: string
27
+ /** Accessible name of the refresh icon button. */
28
+ refresh: string
29
+ /** Accessible name of the refresh icon button while a refresh runs. */
30
+ refreshing: string
31
+ /** Accessible name of the fullscreen icon button (inline view). */
32
+ enterFullscreen: string
33
+ /** Accessible name of the fullscreen icon button (fullscreen view). */
34
+ exitFullscreen: string
35
+ /** Label of the button that opens the view builder. */
36
+ build: string
37
+ /** Shown under the placeholder once loading takes longer than `slowHintAfterMs`. */
38
+ slowHint: string
39
+ /** Title of the error state when the view could not be loaded. */
40
+ errorTitle: string
41
+ /** One line under the error title: what you can do next (a retry button follows). */
42
+ errorHint: string
43
+ /**
44
+ * The line under an error title when no retry is offered (the originating
45
+ * tool is unknown, or the view cannot refresh): what you can do instead.
46
+ */
47
+ errorHintNoRetry: string
48
+ /** Retry button of the error state and of the step-error alert. */
49
+ retry: string
50
+ /** Summary of the error's technical-details disclosure. */
51
+ errorDetails: string
52
+ /** Title of the alert that lists the data steps that failed. */
53
+ stepErrorsTitle: string
54
+ /** The line under the step-error title when a retry is offered: what it does. */
55
+ stepErrorsHint: string
56
+ /** Toast title when a refresh failed: what happened, in one short sentence. */
57
+ refreshFailed: string
58
+ /** Toast line under {@link ViewMessages.refreshFailed}: what you see now and can do. */
59
+ refreshFailedHint: string
60
+ /** Toast title when the host rejected a display-mode change. */
61
+ fullscreenFailed: string
62
+ /** Toast line under {@link ViewMessages.fullscreenFailed}: what you can do. */
63
+ fullscreenFailedHint: string
64
+ }
65
+
66
+ /** Strings of `ListFooter`. */
67
+ export interface ListFooterMessages {
68
+ /** The honest count line, e.g. "Showing 8 of 42 tasks". Numbers arrive pre-formatted. */
69
+ showing: (params: { shown: string; total: string; noun: string }) => string
70
+ /** Plural noun used when the caller passes none. */
71
+ defaultNoun: string
72
+ loadMore: string
73
+ loadingMore: string
74
+ }
75
+
76
+ /** Strings of the widget renderer's fallbacks. */
77
+ export interface RendererMessages {
78
+ /** A layout cell names a widget id the bundle does not contain. */
79
+ widgetUnavailable: string
80
+ /** A widget threw while rendering. */
81
+ widgetCrashed: string
82
+ /** Builder canvas/preview: the cell has no data yet. */
83
+ noDataYet: string
84
+ }
85
+
86
+ /** Strings of the visual view builder (`LayoutBuilder`). */
87
+ export interface BuilderMessages {
88
+ title: string
89
+ builderBadge: string
90
+ previewBadge: string
91
+ catalogue: string
92
+ save: string
93
+ done: string
94
+ viewLayoutTab: string
95
+ viewPipelineTab: string
96
+ viewPreviewTab: string
97
+ saveDialogTitle: string
98
+ saveDialogDescription: string
99
+ saveNameLabel: string
100
+ saveDescriptionLabel: string
101
+ saveConfirm: string
102
+ cancel: string
103
+ pipelineHeader: string
104
+ keysHeader: string
105
+ stepsHeader: string
106
+ keyName: string
107
+ keyValue: string
108
+ stepContextId: string
109
+ stepPickerLabel: string
110
+ addKey: string
111
+ addStep: string
112
+ emptyKeys: string
113
+ emptySteps: string
114
+ statusUpToDate: string
115
+ statusPending: string
116
+ statusRefreshing: string
117
+ paletteHeader: string
118
+ paletteEmpty: string
119
+ canvasEmpty: string
120
+ canvasDropHint: string
121
+ addRow: string
122
+ addTab: string
123
+ removeRow: string
124
+ renameTab: string
125
+ removeTab: string
126
+ tabsLabel: string
127
+ catalogueDescription: string
128
+ catalogueKeys: string
129
+ catalogueSteps: string
130
+ catalogueUnreachable: string
131
+ catalogueUnreachableEmpty: string
132
+ catalogueProducedBy: string
133
+ catalogueConsumedBy: string
134
+ catalogueNeedsKeys: string
135
+ cataloguePickKey: string
136
+ catalogueAddProducingStep: string
137
+ catalogueLive: string
138
+ catalogueMissing: string
139
+ /** Title of the error state when the catalogue fetch fails (the raw reason goes under Details). */
140
+ catalogueError: string
141
+ /** What to do when the catalogue fetch fails (the state offers a retry). */
142
+ catalogueErrorHint: string
143
+ /** Heading for the pipeline-validation warning banner. */
144
+ validationWarning: string
145
+ /** Title of the save dialog's error state when a save fails (the raw reason goes under Details). */
146
+ saveError: string
147
+ /** What to do when a save fails (the dialog's Save button is the retry). */
148
+ saveErrorHint: string
149
+ /** Inline message when a tab rename is rejected (duplicate label). */
150
+ renameDuplicate: string
151
+ /** Toolbar stat: keys present in the live context. */
152
+ statsLive: string
153
+ /** Toolbar stat: widgets the current keys and steps can feed. */
154
+ statsReachable: string
155
+ /** Toolbar stat: widgets nothing can feed yet. */
156
+ statsUnreachable: string
157
+ /** Empty layout view: title. */
158
+ emptyHintTitle: string
159
+ /** Empty layout view: what to do. */
160
+ emptyHintBody: string
161
+ /** Empty layout view: button that switches to the data-sources tab. */
162
+ openDataSources: string
163
+ saveNamePlaceholder: string
164
+ saveDescriptionPlaceholder: string
165
+ /** Toast after a successful save. */
166
+ saved: (name: string) => string
167
+ /** Hint next to the tab strip. */
168
+ renameHint: string
169
+ /** Tooltip of a tab trigger. */
170
+ renameTitle: string
171
+ /** Note next to the data-sources header. */
172
+ autoApplies: string
173
+ noMoreKeys: string
174
+ /** Tooltip of the detected value type next to a key value. */
175
+ parsedType: string
176
+ /** Name of a detected value type (`valueTypeLabel` code: str, num, bool, arr, obj, null). */
177
+ valueType: (code: string) => string
178
+ removeKey: string
179
+ removeStep: string
180
+ noInputs: string
181
+ noOutputs: string
182
+ rowLabel: (index: number) => string
183
+ elementCount: (count: number) => string
184
+ moveRowUp: string
185
+ moveRowDown: string
186
+ columnSpan: string
187
+ configureElement: string
188
+ configureElementSet: (count: number) => string
189
+ removeElement: string
190
+ resizeElement: string
191
+ noKeysRegistered: string
192
+ noStepsRegistered: string
193
+ /** Prefix for "used by" lines that list steps. */
194
+ catalogueStepPrefix: string
195
+ /** Prefix for "used by" lines that list widgets. */
196
+ catalogueElementPrefix: string
197
+ }
198
+
199
+ /** Strings of the builder's per-cell props sheet. */
200
+ export interface PropsSheetMessages {
201
+ title: string
202
+ description: string
203
+ apply: string
204
+ cancel: string
205
+ reset: string
206
+ noProps: string
207
+ unsetOption: string
208
+ unsupportedType: (type: string) => string
209
+ }
210
+
211
+ /** One locale's complete toolkit catalog. */
212
+ export interface ToolkitMessages {
213
+ common: CommonMessages
214
+ view: ViewMessages
215
+ listFooter: ListFooterMessages
216
+ filterBar: { searchPlaceholder: string }
217
+ pills: { live: string }
218
+ renderer: RendererMessages
219
+ builder: BuilderMessages
220
+ propsSheet: PropsSheetMessages
221
+ }