@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
@@ -0,0 +1,67 @@
1
+ /**
2
+ * The Miragon corporate-design tokens (`--cd-*`) as plain TypeScript, for code
3
+ * that cannot read CSS variables — an SVG or canvas renderer (BPMN overlays,
4
+ * chart marks), a server-side image, a test. Keys are the CSS names without the
5
+ * `--cd-` prefix.
6
+ *
7
+ * The source of truth is the vendored `cd-tokens.generated.css` next to this
8
+ * file (miragon-brand 1.8.0, copied unchanged from Miragon/corporate-identity).
9
+ * This module mirrors it value for value; `cd-tokens.test.ts` fails on any
10
+ * drift (modeler-tool-design §13). Never edit a value here without re-vendoring
11
+ * the CSS first.
12
+ *
13
+ * UI code styles through the role tokens (`bg-primary`, `text-link`,
14
+ * `border-danger`, …), never through these constants.
15
+ */
16
+ export const CD_TOKENS = {
17
+ blau: "#335DE5",
18
+ gruen: "#00E676",
19
+ grau: "#F9F7F7",
20
+ schwarz: "#1D1D1D",
21
+ weiss: "#FFFFFF",
22
+ "blau-link": "#2B50D4",
23
+ "blau-hell": "#6B8AFF",
24
+ success: "#00E676",
25
+ "success-soft": "#DAFBEB",
26
+ "success-hell": "#00E676",
27
+ warning: "#FFB000",
28
+ "warning-soft": "#FFF1D2",
29
+ "warning-hell": "#FFB000",
30
+ danger: "#CD1839",
31
+ "danger-soft": "#FBEEF0",
32
+ "danger-hell": "#FB6D73",
33
+ info: "#335DE5",
34
+ "info-soft": "#EEF1FD",
35
+ "info-hell": "#6B8AFF",
36
+ linie: "#E6E2E2",
37
+ kontur: "#8F8A8A",
38
+ "text-leise": "#6B6666",
39
+ "gradient-brand": "linear-gradient(120deg, #335DE5 30%, #00E676)",
40
+ "gradient-format": "linear-gradient(135deg, #335DE5 0%, #00E676 140%)",
41
+ "space-1": "4px",
42
+ "space-2": "8px",
43
+ "space-3": "16px",
44
+ "space-4": "24px",
45
+ "space-5": "32px",
46
+ "space-6": "48px",
47
+ "space-7": "64px",
48
+ "space-8": "96px",
49
+ "radius-sm": "6px",
50
+ "radius-md": "12px",
51
+ "radius-lg": "16px",
52
+ "radius-pill": "999px",
53
+ "shadow-1": "0 1px 2px rgba(29, 29, 29, 0.06), 0 1px 3px rgba(29, 29, 29, 0.10)",
54
+ "shadow-2": "0 4px 12px rgba(29, 29, 29, 0.10)",
55
+ "shadow-3": "0 12px 32px rgba(29, 29, 29, 0.16)",
56
+ "motion-fast": "150ms",
57
+ "motion-base": "250ms",
58
+ "motion-slow": "400ms",
59
+ ease: "cubic-bezier(0.4, 0, 0.2, 1)",
60
+ "ease-out": "cubic-bezier(0, 0, 0.2, 1)",
61
+ } as const
62
+
63
+ /** A key of {@link CD_TOKENS} — the `--cd-*` name without its prefix. */
64
+ export type CdTokenName = keyof typeof CD_TOKENS
65
+
66
+ /** The miragon-brand release the vendored tokens come from. */
67
+ export const CD_TOKENS_VERSION = "1.8.0"
@@ -1,40 +1,129 @@
1
+ // The colours below are a CUSTOMER brand's values (white-label fixtures): test
2
+ // data by design, not Miragon colours. brand-lint is off for this file.
3
+ /* brand-lint-disable */
1
4
  import { describe, expect, it } from "vitest"
2
- import { TOKEN_TO_CSS_VAR, createTheme, tokensToVars, type ThemeTokens } from "./create-theme.js"
5
+ import {
6
+ MODE_INVARIANT_VARS,
7
+ ROLE_TOKENS,
8
+ TOKEN_TO_CSS_VAR,
9
+ createTheme,
10
+ resolveThemeVars,
11
+ tokensToVars,
12
+ type ThemeTokens,
13
+ } from "./create-theme.js"
3
14
 
4
15
  describe("tokensToVars (token → CSS-var mapping)", () => {
5
16
  it("maps every curated token to its real CSS variable name", () => {
6
17
  const full: Required<ThemeTokens> = {
7
18
  primary: "oklch(0.55 0.2 264)",
8
19
  primaryForeground: "oklch(0.99 0 0)",
20
+ primaryHover: "oklch(0.5 0.2 264)",
21
+ link: "oklch(0.45 0.2 264)",
9
22
  accent: "oklch(0.95 0.03 264)",
10
23
  accentForeground: "oklch(0.3 0.1 264)",
11
24
  background: "#ffffff",
12
25
  foreground: "#101010",
13
26
  card: "hsl(0 0% 100%)",
14
27
  cardForeground: "hsl(0 0% 6%)",
28
+ popover: "#fefefe",
29
+ muted: "#f5f5f5",
30
+ mutedForeground: "#666666",
31
+ secondary: "#eeeeee",
15
32
  border: "oklch(0.92 0 0)",
33
+ input: "#888888",
16
34
  ring: "oklch(0.7 0 0)",
35
+ focus: "#2222ff",
36
+ destructive: "#cc0000",
37
+ destructiveForeground: "#fffff0",
38
+ success: "#00aa00",
39
+ successSoft: "#eeffee",
40
+ successInk: "#003300",
41
+ warning: "#ffaa00",
42
+ warningSoft: "#fff5e0",
43
+ warningInk: "#332200",
44
+ danger: "#dd0000",
45
+ dangerSoft: "#ffeeee",
46
+ dangerInk: "#990000",
47
+ info: "#0000dd",
48
+ infoSoft: "#eeeeff",
49
+ infoInk: "#000099",
17
50
  radius: "0.5rem",
51
+ radiusSm: "4px",
52
+ radiusMd: "8px",
53
+ radiusLg: "12px",
54
+ radiusPill: "9999px",
55
+ shadow1: "0 1px 2px #0001",
56
+ shadow2: "0 4px 8px #0002",
57
+ shadow3: "0 8px 24px #0003",
58
+ scrim: "#0008",
59
+ motionFast: "100ms",
60
+ motionBase: "200ms",
61
+ motionSlow: "300ms",
62
+ ease: "ease-in-out",
18
63
  fontSans: "Inter, sans-serif",
64
+ fontMono: "JetBrains Mono, monospace",
19
65
  fontHeading: "Sora, sans-serif",
20
66
  }
21
67
  expect(tokensToVars(full)).toEqual({
22
68
  "--primary": "oklch(0.55 0.2 264)",
23
69
  "--primary-foreground": "oklch(0.99 0 0)",
70
+ "--primary-hover": "oklch(0.5 0.2 264)",
71
+ "--link": "oklch(0.45 0.2 264)",
24
72
  "--accent": "oklch(0.95 0.03 264)",
25
73
  "--accent-foreground": "oklch(0.3 0.1 264)",
26
74
  "--background": "#ffffff",
27
75
  "--foreground": "#101010",
28
76
  "--card": "hsl(0 0% 100%)",
29
77
  "--card-foreground": "hsl(0 0% 6%)",
78
+ "--popover": "#fefefe",
79
+ "--muted": "#f5f5f5",
80
+ "--muted-foreground": "#666666",
81
+ "--secondary": "#eeeeee",
30
82
  "--border": "oklch(0.92 0 0)",
83
+ "--input": "#888888",
31
84
  "--ring": "oklch(0.7 0 0)",
85
+ "--focus": "#2222ff",
86
+ "--destructive": "#cc0000",
87
+ "--destructive-foreground": "#fffff0",
88
+ "--success": "#00aa00",
89
+ "--success-soft": "#eeffee",
90
+ "--success-ink": "#003300",
91
+ "--warning": "#ffaa00",
92
+ "--warning-soft": "#fff5e0",
93
+ "--warning-ink": "#332200",
94
+ "--danger": "#dd0000",
95
+ "--danger-soft": "#ffeeee",
96
+ "--danger-ink": "#990000",
97
+ "--info": "#0000dd",
98
+ "--info-soft": "#eeeeff",
99
+ "--info-ink": "#000099",
32
100
  "--radius": "0.5rem",
101
+ "--radius-sm": "4px",
102
+ "--radius-md": "8px",
103
+ "--radius-lg": "12px",
104
+ "--radius-pill": "9999px",
105
+ "--shadow-1": "0 1px 2px #0001",
106
+ "--shadow-2": "0 4px 8px #0002",
107
+ "--shadow-3": "0 8px 24px #0003",
108
+ "--scrim": "#0008",
109
+ "--motion-fast": "100ms",
110
+ "--motion-base": "200ms",
111
+ "--motion-slow": "300ms",
112
+ "--ease": "ease-in-out",
33
113
  "--font-sans": "Inter, sans-serif",
114
+ "--font-mono": "JetBrains Mono, monospace",
34
115
  "--font-heading": "Sora, sans-serif",
35
116
  })
36
117
  })
37
118
 
119
+ it("exposes every role of the role-token contract as a ThemeTokens field", () => {
120
+ const mapped = new Set<string>(Object.values(TOKEN_TO_CSS_VAR))
121
+ for (const role of ROLE_TOKENS) {
122
+ expect(mapped.has(role), `${role} has no ThemeTokens field`).toBe(true)
123
+ }
124
+ expect(new Set(ROLE_TOKENS).size).toBe(ROLE_TOKENS.length)
125
+ })
126
+
38
127
  it("emits only the variables for the fields that are set (partial tokens)", () => {
39
128
  expect(tokensToVars({ primary: "#6d28d9", radius: "0.75rem" })).toEqual({
40
129
  "--primary": "#6d28d9",
@@ -74,13 +163,30 @@ describe("createTheme", () => {
74
163
  it("returns a serializable definition with vars and a toStyle helper", () => {
75
164
  const theme = createTheme({ primary: "#6d28d9", radius: "0.5rem" })
76
165
  expect(theme.vars).toEqual({ "--primary": "#6d28d9", "--radius": "0.5rem" })
77
- expect(theme.toStyle()).toEqual({ "--primary": "#6d28d9", "--radius": "0.5rem" })
166
+ expect(theme.toStyle()).toEqual({
167
+ "--primary": "#6d28d9",
168
+ "--primary-hover": "color-mix(in srgb, #6d28d9 90%, transparent)",
169
+ "--link": "#6d28d9",
170
+ "--radius": "0.5rem",
171
+ "--radius-sm": "calc(0.5rem * 0.5)",
172
+ "--radius-md": "0.5rem",
173
+ "--radius-lg": "calc(0.5rem * 4 / 3)",
174
+ })
78
175
  expect(theme.darkVars).toBeUndefined()
79
176
  })
80
177
 
81
- it("toStyle mirrors vars (CSS custom properties as a style object)", () => {
82
- const theme = createTheme({ background: "#fff", foreground: "#000" })
83
- expect(theme.toStyle()).toEqual(theme.vars)
178
+ it("toStyle applies what ThemeProvider applies in light mode (resolveThemeVars)", () => {
179
+ const plain = createTheme({ background: "#fff", foreground: "#000" })
180
+ expect(plain.toStyle()).toEqual(plain.vars)
181
+ const legacy = createTheme({ primary: "#0f766e", ring: "#0f766e", radius: "0px" })
182
+ expect(legacy.toStyle()).toEqual(resolveThemeVars(legacy, "light"))
183
+ })
184
+
185
+ it("toStyle reshapes rounded-sm/md/lg from a legacy base radius (square corners)", () => {
186
+ const style = createTheme({ radius: "0px" }).toStyle() as Record<string, string>
187
+ expect(style["--radius-md"]).toBe("0px")
188
+ expect(style["--radius-sm"]).toBe("calc(0px * 0.5)")
189
+ expect(style["--radius-lg"]).toBe("calc(0px * 4 / 3)")
84
190
  })
85
191
 
86
192
  it("maps dark token overrides to darkVars", () => {
@@ -106,3 +212,135 @@ describe("createTheme", () => {
106
212
  expect(theme.toStyle()).toEqual({})
107
213
  })
108
214
  })
215
+
216
+ describe("resolveThemeVars (what a theme scope applies per mode — #178 N35)", () => {
217
+ // Built inside each test (see fonts.test.ts): keeps mutants visible to it.
218
+ const brand = () =>
219
+ createTheme(
220
+ { primary: "#0f766e", accent: "#ccfbf1", background: "#fafafa", fontSans: "Inter" },
221
+ { dark: { accent: "#134e4a" } },
222
+ )
223
+
224
+ it("returns {} without a theme (the toolkit defaults apply)", () => {
225
+ expect(resolveThemeVars(undefined, "light")).toEqual({})
226
+ expect(resolveThemeVars(null, "dark")).toEqual({})
227
+ })
228
+
229
+ it("applies the light vars in light mode (plus what the legacy primary derives)", () => {
230
+ expect(resolveThemeVars(brand(), "light")).toEqual({
231
+ "--primary": "#0f766e",
232
+ "--primary-hover": "color-mix(in srgb, #0f766e 90%, transparent)",
233
+ "--link": "#0f766e",
234
+ "--accent": "#ccfbf1",
235
+ "--background": "#fafafa",
236
+ "--font-sans": "Inter",
237
+ })
238
+ })
239
+
240
+ it("never carries a mode-dependent light value into dark mode", () => {
241
+ const dark = resolveThemeVars(brand(), "dark")
242
+ // background is a surface: its light value would beat the toolkit's dark
243
+ // default and put a light surface into a dark scope.
244
+ expect(dark).not.toHaveProperty("--background")
245
+ // accent comes from the theme's dark tokens.
246
+ expect(dark["--accent"]).toBe("#134e4a")
247
+ })
248
+
249
+ it("carries mode-invariant light values (brand button colour, fonts) into dark mode", () => {
250
+ expect(resolveThemeVars(brand(), "dark")).toEqual({
251
+ "--primary": "#0f766e",
252
+ "--primary-hover": "color-mix(in srgb, #0f766e 90%, transparent)",
253
+ "--link": "#0f766e",
254
+ "--font-sans": "Inter",
255
+ "--accent": "#134e4a",
256
+ })
257
+ })
258
+
259
+ it("lets a dark token override a carried mode-invariant one (and derives from it)", () => {
260
+ const theme = createTheme({ primary: "#111111" }, { dark: { primary: "#eeeeee" } })
261
+ expect(resolveThemeVars(theme, "dark")).toEqual({
262
+ "--primary": "#eeeeee",
263
+ "--primary-hover": "color-mix(in srgb, #eeeeee 90%, transparent)",
264
+ "--link": "#eeeeee",
265
+ })
266
+ })
267
+
268
+ it("applies only mode-invariant vars in dark mode when a theme has no dark tokens", () => {
269
+ const theme = createTheme({
270
+ primary: "#111111",
271
+ primaryHover: "#222222",
272
+ card: "#ffffff",
273
+ link: "#0000ee",
274
+ })
275
+ expect(resolveThemeVars(theme, "dark")).toEqual({
276
+ "--primary": "#111111",
277
+ "--primary-hover": "#222222",
278
+ })
279
+ })
280
+
281
+ it("derives the sm/md/lg radii from a legacy base radius in both modes", () => {
282
+ const theme = createTheme({ radius: "8px" })
283
+ const derived = {
284
+ "--radius": "8px",
285
+ "--radius-sm": "calc(8px * 0.5)",
286
+ "--radius-md": "8px",
287
+ "--radius-lg": "calc(8px * 4 / 3)",
288
+ }
289
+ expect(resolveThemeVars(theme, "light")).toEqual(derived)
290
+ expect(resolveThemeVars(theme, "dark")).toEqual(derived)
291
+ })
292
+
293
+ it("keeps an explicit radius step over the derived one", () => {
294
+ const theme = createTheme({ radius: "8px", radiusMd: "10px" })
295
+ expect(resolveThemeVars(theme, "light")["--radius-md"]).toBe("10px")
296
+ expect(resolveThemeVars(theme, "light")["--radius-sm"]).toBe("calc(8px * 0.5)")
297
+ })
298
+
299
+ it("derives nothing without a base radius", () => {
300
+ const theme = createTheme({ radiusSm: "2px" })
301
+ expect(resolveThemeVars(theme, "light")).toEqual({ "--radius-sm": "2px" })
302
+ })
303
+
304
+ it("derives hover and link from a legacy primary, and focus from a legacy ring", () => {
305
+ const theme = createTheme({ primary: "#0f766e", ring: "#115e59" })
306
+ expect(resolveThemeVars(theme, "light")).toEqual({
307
+ "--primary": "#0f766e",
308
+ "--primary-hover": "color-mix(in srgb, #0f766e 90%, transparent)",
309
+ "--link": "#0f766e",
310
+ "--ring": "#115e59",
311
+ "--focus": "#115e59",
312
+ })
313
+ })
314
+
315
+ it("never derives a role the theme sets itself, in either mode", () => {
316
+ const theme = createTheme(
317
+ { primary: "#0f766e", ring: "#115e59" },
318
+ { dark: { primaryHover: "#99f6e4", link: "#5eead4", focus: "#5eead4" } },
319
+ )
320
+ // Set only in dark: light keeps the toolkit default for those roles.
321
+ expect(resolveThemeVars(theme, "light")).toEqual({
322
+ "--primary": "#0f766e",
323
+ "--ring": "#115e59",
324
+ })
325
+ expect(resolveThemeVars(theme, "dark")).toEqual({
326
+ "--primary": "#0f766e",
327
+ "--primary-hover": "#99f6e4",
328
+ "--link": "#5eead4",
329
+ "--focus": "#5eead4",
330
+ })
331
+ })
332
+
333
+ it("derives nothing for the interactive roles without primary or ring", () => {
334
+ const theme = createTheme({ background: "#fafafa" }, { dark: { background: "#111111" } })
335
+ expect(resolveThemeVars(theme, "light")).toEqual({ "--background": "#fafafa" })
336
+ expect(resolveThemeVars(theme, "dark")).toEqual({ "--background": "#111111" })
337
+ })
338
+
339
+ it("classifies every mode-invariant var as a real theming variable", () => {
340
+ const mapped = new Set<string>(Object.values(TOKEN_TO_CSS_VAR))
341
+ for (const name of MODE_INVARIANT_VARS) {
342
+ expect(mapped.has(name), `${name} is not a ThemeTokens variable`).toBe(true)
343
+ }
344
+ })
345
+ })
346
+ /* brand-lint-enable */