@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,56 @@
1
+ /**
2
+ * Opt-in Geist delivery by URL. The toolkit's font tokens name "Geist" and
3
+ * "Geist Mono" first but load no font: an app either imports
4
+ * `@miragon/mcp-toolkit-ui/fonts.css` (bundled by the build) or serves the
5
+ * woff2 files itself and declares them with {@link fontFaces}. The second path
6
+ * keeps MCP App views small — the files are fetched once and cached instead of
7
+ * inlined as base64 into every view; allow their origin in the view's CSP
8
+ * `resourceDomains`. Where the fonts never load, the host's font renders (if
9
+ * the host sends one, see `adoptHostFontVariables`), else the system stack.
10
+ */
11
+ /** The latin variable woff2 files, as `@fontsource-variable/geist(-mono)` ship them. */
12
+ export const GEIST_FONT_FILES = {
13
+ sans: "geist-latin-wght-normal.woff2",
14
+ mono: "geist-mono-latin-wght-normal.woff2",
15
+ };
16
+ /** The latin subset both files cover (identical to fontsource's `latin` range). */
17
+ const LATIN_UNICODE_RANGE = "U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD";
18
+ /** Characters that could break out of the CSS `url("…")` the helper writes. */
19
+ const UNSAFE_URL_CHARS = /["'\\()\s<>]/;
20
+ function fontUrl(baseUrl, file) {
21
+ const url = `${baseUrl.replace(/\/+$/, "")}/${file.replace(/^\/+/, "")}`;
22
+ if (UNSAFE_URL_CHARS.test(url)) {
23
+ throw new Error(`fontFaces: refusing a font URL with quote, bracket or whitespace: ${url}`);
24
+ }
25
+ return url;
26
+ }
27
+ function face(family, url, display) {
28
+ return [
29
+ "@font-face {",
30
+ ` font-family: "${family}";`,
31
+ " font-style: normal;",
32
+ ` font-display: ${display};`,
33
+ " font-weight: 100 900;",
34
+ ` src: url("${url}") format("woff2");`,
35
+ ` unicode-range: ${LATIN_UNICODE_RANGE};`,
36
+ "}",
37
+ ].join("\n");
38
+ }
39
+ /**
40
+ * The `@font-face` rules for Geist and Geist Mono (latin, variable weight
41
+ * 100–900) served from `baseUrl`. Pure — inject the string where your app
42
+ * builds its document, e.g. `<style>{fontFaces({ baseUrl })}</style>`.
43
+ *
44
+ * @example
45
+ * fontFaces({ baseUrl: "https://mcp.example.com/fonts" })
46
+ * // @font-face { font-family: "Geist"; … src: url("https://mcp.example.com/fonts/geist-latin-wght-normal.woff2") … }
47
+ */
48
+ export function fontFaces({ baseUrl, files, display = "swap" }) {
49
+ const sans = files?.sans ?? GEIST_FONT_FILES.sans;
50
+ const mono = files?.mono ?? GEIST_FONT_FILES.mono;
51
+ return [
52
+ face("Geist", fontUrl(baseUrl, sans), display),
53
+ face("Geist Mono", fontUrl(baseUrl, mono), display),
54
+ ].join("\n");
55
+ }
56
+ //# sourceMappingURL=fonts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fonts.js","sourceRoot":"","sources":["../../src/theme/fonts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,wFAAwF;AACxF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,IAAI,EAAE,+BAA+B;IACrC,IAAI,EAAE,oCAAoC;CAClC,CAAA;AAEV,mFAAmF;AACnF,MAAM,mBAAmB,GACvB,0JAA0J,CAAA;AAY5J,+EAA+E;AAC/E,MAAM,gBAAgB,GAAG,cAAc,CAAA;AAEvC,SAAS,OAAO,CAAC,OAAe,EAAE,IAAY;IAC5C,MAAM,GAAG,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,CAAA;IACxE,IAAI,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,qEAAqE,GAAG,EAAE,CAAC,CAAA;IAC7F,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,IAAI,CAAC,MAAc,EAAE,GAAW,EAAE,OAAe;IACxD,OAAO;QACL,cAAc;QACd,mBAAmB,MAAM,IAAI;QAC7B,uBAAuB;QACvB,mBAAmB,OAAO,GAAG;QAC7B,yBAAyB;QACzB,eAAe,GAAG,qBAAqB;QACvC,oBAAoB,mBAAmB,GAAG;QAC1C,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,SAAS,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,EAAoB;IAC9E,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAA;IACjD,MAAM,IAAI,GAAG,KAAK,EAAE,IAAI,IAAI,gBAAgB,CAAC,IAAI,CAAA;IACjD,OAAO;QACL,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAC9C,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC;KACpD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC"}
@@ -0,0 +1,39 @@
1
+ /**
2
+ * The host's font, demoted to the fallback slot of the font roles.
3
+ *
4
+ * SEP-1865 hosts send their fonts as the style variables `--font-sans` and
5
+ * `--font-mono`, the same names as the toolkit's font roles. mcp-use writes
6
+ * them inline on `<html>`, where they beat the role stacks in `theme.css` and
7
+ * replace them whole, so Geist never renders even when it is loaded. The
8
+ * toolkit's rule is Geist first, the host's font next, the system stack last:
9
+ * {@link adoptHostFontVariables} moves the host's value to
10
+ * `--host-font-sans` / `--host-font-mono`, which the role stacks name right
11
+ * after Geist. `McpToolkitApp` runs it after every host-context update; an app
12
+ * with its own document layer calls it after it applied the host variables.
13
+ */
14
+ /** Each host font variable (SEP-1865 name) → where the toolkit keeps it. */
15
+ export declare const HOST_FONT_VARIABLES: {
16
+ readonly "--font-sans": "--host-font-sans";
17
+ readonly "--font-mono": "--host-font-mono";
18
+ };
19
+ /** The slice of `CSSStyleDeclaration` the helper touches (`element.style`). */
20
+ export interface InlineStyleTarget {
21
+ getPropertyValue(property: string): string;
22
+ setProperty(property: string, value: string): void;
23
+ removeProperty(property: string): string;
24
+ }
25
+ /**
26
+ * Move the host's font variables off the role names on `style` (normally
27
+ * `document.documentElement.style`, where the host variables were applied):
28
+ * each non-empty `--font-sans` / `--font-mono` in `hostVariables` is written
29
+ * to its {@link HOST_FONT_VARIABLES} slot, and the role is cleared when it
30
+ * still holds exactly the host's value — an app's own inline brand font
31
+ * stays. Idempotent; a no-op without host variables.
32
+ *
33
+ * @example
34
+ * applyHostStyleVariables(vars) // the host layer writes --font-sans on <html>
35
+ * adoptHostFontVariables(document.documentElement.style, vars)
36
+ * // --font-sans: "Geist", "Geist Variable", <host font>, system-ui, sans-serif
37
+ */
38
+ export declare function adoptHostFontVariables(style: InlineStyleTarget, hostVariables: Readonly<Record<string, string | undefined>> | null | undefined): void;
39
+ //# sourceMappingURL=host-fonts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-fonts.d.ts","sourceRoot":"","sources":["../../src/theme/host-fonts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,mBAAmB;;;CAGtB,CAAA;AAEV,+EAA+E;AAC/E,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;IAC1C,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IAClD,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAA;CACzC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,iBAAiB,EACxB,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,IAAI,GAAG,SAAS,GAC7E,IAAI,CAQN"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The host's font, demoted to the fallback slot of the font roles.
3
+ *
4
+ * SEP-1865 hosts send their fonts as the style variables `--font-sans` and
5
+ * `--font-mono`, the same names as the toolkit's font roles. mcp-use writes
6
+ * them inline on `<html>`, where they beat the role stacks in `theme.css` and
7
+ * replace them whole, so Geist never renders even when it is loaded. The
8
+ * toolkit's rule is Geist first, the host's font next, the system stack last:
9
+ * {@link adoptHostFontVariables} moves the host's value to
10
+ * `--host-font-sans` / `--host-font-mono`, which the role stacks name right
11
+ * after Geist. `McpToolkitApp` runs it after every host-context update; an app
12
+ * with its own document layer calls it after it applied the host variables.
13
+ */
14
+ /** Each host font variable (SEP-1865 name) → where the toolkit keeps it. */
15
+ export const HOST_FONT_VARIABLES = {
16
+ "--font-sans": "--host-font-sans",
17
+ "--font-mono": "--host-font-mono",
18
+ };
19
+ /**
20
+ * Move the host's font variables off the role names on `style` (normally
21
+ * `document.documentElement.style`, where the host variables were applied):
22
+ * each non-empty `--font-sans` / `--font-mono` in `hostVariables` is written
23
+ * to its {@link HOST_FONT_VARIABLES} slot, and the role is cleared when it
24
+ * still holds exactly the host's value — an app's own inline brand font
25
+ * stays. Idempotent; a no-op without host variables.
26
+ *
27
+ * @example
28
+ * applyHostStyleVariables(vars) // the host layer writes --font-sans on <html>
29
+ * adoptHostFontVariables(document.documentElement.style, vars)
30
+ * // --font-sans: "Geist", "Geist Variable", <host font>, system-ui, sans-serif
31
+ */
32
+ export function adoptHostFontVariables(style, hostVariables) {
33
+ if (!hostVariables)
34
+ return;
35
+ for (const [role, slot] of Object.entries(HOST_FONT_VARIABLES)) {
36
+ const value = hostVariables[role]?.trim();
37
+ if (!value)
38
+ continue;
39
+ style.setProperty(slot, value);
40
+ if (style.getPropertyValue(role).trim() === value)
41
+ style.removeProperty(role);
42
+ }
43
+ }
44
+ //# sourceMappingURL=host-fonts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"host-fonts.js","sourceRoot":"","sources":["../../src/theme/host-fonts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,4EAA4E;AAC5E,MAAM,CAAC,MAAM,mBAAmB,GAAG;IACjC,aAAa,EAAE,kBAAkB;IACjC,aAAa,EAAE,kBAAkB;CACzB,CAAA;AASV;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAwB,EACxB,aAA8E;IAE9E,IAAI,CAAC,aAAa;QAAE,OAAM;IAC1B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC/D,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAA;QACzC,IAAI,CAAC,KAAK;YAAE,SAAQ;QACpB,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;QAC9B,IAAI,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,KAAK;YAAE,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAA;IAC/E,CAAC;AACH,CAAC"}
@@ -1,7 +1,14 @@
1
- export { createTheme, tokensToVars, TOKEN_TO_CSS_VAR } from "./create-theme.js";
1
+ export { createTheme, tokensToVars, resolveThemeVars, TOKEN_TO_CSS_VAR, ROLE_TOKENS, MODE_INVARIANT_VARS, } from "./create-theme.js";
2
2
  export type { ThemeTokens, ThemeDefinition, ThemeVars, CreateThemeOptions } from "./create-theme.js";
3
3
  export { ThemeProvider, useTheme } from "./theme-provider.js";
4
4
  export type { ThemeMode, ThemeContextValue, ThemeProviderProps } from "./theme-provider.js";
5
+ export { usePortalContainer } from "./portal-container.js";
5
6
  export { themePresets } from "./presets.js";
6
7
  export type { ThemePresetId } from "./presets.js";
8
+ export { CD_TOKENS, CD_TOKENS_VERSION } from "./cd-tokens.js";
9
+ export type { CdTokenName } from "./cd-tokens.js";
10
+ export { fontFaces, GEIST_FONT_FILES } from "./fonts.js";
11
+ export type { FontFacesOptions } from "./fonts.js";
12
+ export { adoptHostFontVariables, HOST_FONT_VARIABLES } from "./host-fonts.js";
13
+ export type { InlineStyleTarget } from "./host-fonts.js";
7
14
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAC/E,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACpG,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC7D,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC3F,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACpG,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAC7D,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAC3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAC3C,YAAY,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAC7D,YAAY,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AACxD,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC7E,YAAY,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -1,7 +1,11 @@
1
1
  // White-label theming. Browser-safe (React + DOM only, no `mcp-use/react`), so
2
2
  // it is re-exported from the root barrel — a consumer can theme the toolkit's
3
3
  // primitives without pulling in the host runtime.
4
- export { createTheme, tokensToVars, TOKEN_TO_CSS_VAR } from "./create-theme.js";
4
+ export { createTheme, tokensToVars, resolveThemeVars, TOKEN_TO_CSS_VAR, ROLE_TOKENS, MODE_INVARIANT_VARS, } from "./create-theme.js";
5
5
  export { ThemeProvider, useTheme } from "./theme-provider.js";
6
+ export { usePortalContainer } from "./portal-container.js";
6
7
  export { themePresets } from "./presets.js";
8
+ export { CD_TOKENS, CD_TOKENS_VERSION } from "./cd-tokens.js";
9
+ export { fontFaces, GEIST_FONT_FILES } from "./fonts.js";
10
+ export { adoptHostFontVariables, HOST_FONT_VARIABLES } from "./host-fonts.js";
7
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,kDAAkD;AAClD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAE/E,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/theme/index.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,8EAA8E;AAC9E,kDAAkD;AAClD,OAAO,EACL,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,mBAAmB,GACpB,MAAM,mBAAmB,CAAA;AAE1B,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAE3C,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAE7D,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAExD,OAAO,EAAE,sBAAsB,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The element portaled overlays (Dialog, Sheet, Select) render into. A
3
+ * {@link ThemeProvider} provides a node INSIDE its scope, so overlays opened
4
+ * from a themed subtree keep the theme's variables and its light/dark mode
5
+ * instead of falling back to `document.body` and the `:root` defaults
6
+ * (mcp-toolkit#178 N36). `null` — no provider, or before it mounted — means
7
+ * the overlay library's default (`document.body`).
8
+ */
9
+ export declare const PortalContainerContext: import("react").Context<HTMLElement | null>;
10
+ /**
11
+ * The portal container of the nearest {@link ThemeProvider}, or `null`. Pass it
12
+ * as `container` to a portal of your own so it stays inside the theme scope;
13
+ * the toolkit's Dialog, Sheet and Select already do.
14
+ */
15
+ export declare function usePortalContainer(): HTMLElement | null;
16
+ //# sourceMappingURL=portal-container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-container.d.ts","sourceRoot":"","sources":["../../src/theme/portal-container.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,6CAA0C,CAAA;AAE7E;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,WAAW,GAAG,IAAI,CAEvD"}
@@ -0,0 +1,19 @@
1
+ import { createContext, useContext } from "react";
2
+ /**
3
+ * The element portaled overlays (Dialog, Sheet, Select) render into. A
4
+ * {@link ThemeProvider} provides a node INSIDE its scope, so overlays opened
5
+ * from a themed subtree keep the theme's variables and its light/dark mode
6
+ * instead of falling back to `document.body` and the `:root` defaults
7
+ * (mcp-toolkit#178 N36). `null` — no provider, or before it mounted — means
8
+ * the overlay library's default (`document.body`).
9
+ */
10
+ export const PortalContainerContext = createContext(null);
11
+ /**
12
+ * The portal container of the nearest {@link ThemeProvider}, or `null`. Pass it
13
+ * as `container` to a portal of your own so it stays inside the theme scope;
14
+ * the toolkit's Dialog, Sheet and Select already do.
15
+ */
16
+ export function usePortalContainer() {
17
+ return useContext(PortalContainerContext);
18
+ }
19
+ //# sourceMappingURL=portal-container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portal-container.js","sourceRoot":"","sources":["../../src/theme/portal-container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAEjD;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,aAAa,CAAqB,IAAI,CAAC,CAAA;AAE7E;;;;GAIG;AACH,MAAM,UAAU,kBAAkB;IAChC,OAAO,UAAU,CAAC,sBAAsB,CAAC,CAAA;AAC3C,CAAC"}
@@ -1,21 +1,36 @@
1
1
  import { type ThemeDefinition } from "./create-theme.js";
2
2
  /**
3
3
  * Ready-made white-label themes — a demonstration of {@link createTheme} and a
4
- * starting point a client can fork. Each preset sets a distinct brand `primary`,
5
- * a matching `ring`/`accent`, and a `radius`, plus a `dark` override that
6
- * brightens the brand colour for legibility on dark surfaces (mirroring how
7
- * `globals.css` brightens tokens under `.dark`).
4
+ * starting point a client can fork. Each preset sets its whole interactive
5
+ * family from one brand hue, in light AND dark: `primary` with its
6
+ * `primaryForeground` and `primaryHover`, `link`, `focus` (plus the legacy
7
+ * `ring`), a matching `accent`, and a `radius`. The dark side brightens the
8
+ * brand colour for legibility on dark surfaces. Every preset meets the same
9
+ * contrast bar as the default theme in both modes (`theme-css.test.ts`).
8
10
  *
9
- * Colours are authored in `oklch` to stay consistent with the toolkit's token
10
- * palette in `globals.css`. Apply one with `<ThemeProvider theme={themePresets.violet}>`.
11
+ * The toolkit's DEFAULT is the Miragon theme (theme.css, built on the vendored
12
+ * corporate-design tokens); it needs no preset. A full customer brand may set
13
+ * more roles than these presets do (the status `*Ink` colours); see
14
+ * docs/guides/white-labeling.md. Apply one with
15
+ * `<ThemeProvider theme={themePresets.emerald}>`.
11
16
  */
12
17
  export declare const themePresets: {
13
18
  /**
14
- * The toolkit's own brand: a confident indigo-blue with a slightly tighter
15
- * radius. A sensible default when a client has no brand of their own yet.
19
+ * An approximation of the Miragon blue from before the toolkit shipped the
20
+ * Miragon corporate design.
21
+ *
22
+ * @deprecated The Miragon theme is now the toolkit's default: render without
23
+ * a theme (or `<ThemeProvider>` without `theme`) to get the exact CI values.
24
+ * This preset is off-palette and will be removed in the next major.
16
25
  */
17
26
  miragon: ThemeDefinition;
18
- /** A vivid violet brand with rounder corners — playful, consumer-facing. */
27
+ /**
28
+ * A vivid violet brand with rounder corners — playful, consumer-facing.
29
+ *
30
+ * @deprecated The violet tech default is the look the Miragon design system
31
+ * rules out (anti-slop U9). Fork {@link createTheme} with your own brand
32
+ * values instead. Will be removed in the next major.
33
+ */
19
34
  violet: ThemeDefinition;
20
35
  /** A grounded emerald brand with a crisp, near-square radius — enterprise. */
21
36
  emerald: ThemeDefinition;
@@ -1 +1 @@
1
- {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/theme/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAErE;;;;;;;;;GASG;AACH,eAAO,MAAM,YAAY;IACvB;;;OAGG;;IAqBH,4EAA4E;;IAqB5E,8EAA8E;;CAoBrC,CAAA;AAE3C,2DAA2D;AAC3D,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,YAAY,CAAA"}
1
+ {"version":3,"file":"presets.d.ts","sourceRoot":"","sources":["../../src/theme/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAErE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY;IACvB;;;;;;;OAOG;;IA2BH;;;;;;OAMG;;IA2BH,8EAA8E;;CA0BrC,CAAA;AAE3C,2DAA2D;AAC3D,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,YAAY,CAAA"}
@@ -1,22 +1,34 @@
1
1
  import { createTheme } from "./create-theme.js";
2
2
  /**
3
3
  * Ready-made white-label themes — a demonstration of {@link createTheme} and a
4
- * starting point a client can fork. Each preset sets a distinct brand `primary`,
5
- * a matching `ring`/`accent`, and a `radius`, plus a `dark` override that
6
- * brightens the brand colour for legibility on dark surfaces (mirroring how
7
- * `globals.css` brightens tokens under `.dark`).
4
+ * starting point a client can fork. Each preset sets its whole interactive
5
+ * family from one brand hue, in light AND dark: `primary` with its
6
+ * `primaryForeground` and `primaryHover`, `link`, `focus` (plus the legacy
7
+ * `ring`), a matching `accent`, and a `radius`. The dark side brightens the
8
+ * brand colour for legibility on dark surfaces. Every preset meets the same
9
+ * contrast bar as the default theme in both modes (`theme-css.test.ts`).
8
10
  *
9
- * Colours are authored in `oklch` to stay consistent with the toolkit's token
10
- * palette in `globals.css`. Apply one with `<ThemeProvider theme={themePresets.violet}>`.
11
+ * The toolkit's DEFAULT is the Miragon theme (theme.css, built on the vendored
12
+ * corporate-design tokens); it needs no preset. A full customer brand may set
13
+ * more roles than these presets do (the status `*Ink` colours); see
14
+ * docs/guides/white-labeling.md. Apply one with
15
+ * `<ThemeProvider theme={themePresets.emerald}>`.
11
16
  */
12
17
  export const themePresets = {
13
18
  /**
14
- * The toolkit's own brand: a confident indigo-blue with a slightly tighter
15
- * radius. A sensible default when a client has no brand of their own yet.
19
+ * An approximation of the Miragon blue from before the toolkit shipped the
20
+ * Miragon corporate design.
21
+ *
22
+ * @deprecated The Miragon theme is now the toolkit's default: render without
23
+ * a theme (or `<ThemeProvider>` without `theme`) to get the exact CI values.
24
+ * This preset is off-palette and will be removed in the next major.
16
25
  */
17
26
  miragon: createTheme({
18
27
  primary: "oklch(0.52 0.21 264)",
19
28
  primaryForeground: "oklch(0.985 0 0)",
29
+ primaryHover: "oklch(0.46 0.2 264)",
30
+ link: "oklch(0.52 0.21 264)",
31
+ focus: "oklch(0.52 0.21 264)",
20
32
  accent: "oklch(0.95 0.03 264)",
21
33
  accentForeground: "oklch(0.32 0.12 264)",
22
34
  ring: "oklch(0.52 0.21 264)",
@@ -25,15 +37,27 @@ export const themePresets = {
25
37
  dark: {
26
38
  primary: "oklch(0.7 0.16 264)",
27
39
  primaryForeground: "oklch(0.18 0.02 264)",
40
+ primaryHover: "oklch(0.76 0.13 264)",
41
+ link: "oklch(0.7 0.16 264)",
42
+ focus: "oklch(0.7 0.16 264)",
28
43
  accent: "oklch(0.32 0.06 264)",
29
44
  accentForeground: "oklch(0.97 0 0)",
30
45
  ring: "oklch(0.7 0.16 264)",
31
46
  },
32
47
  }),
33
- /** A vivid violet brand with rounder corners — playful, consumer-facing. */
48
+ /**
49
+ * A vivid violet brand with rounder corners — playful, consumer-facing.
50
+ *
51
+ * @deprecated The violet tech default is the look the Miragon design system
52
+ * rules out (anti-slop U9). Fork {@link createTheme} with your own brand
53
+ * values instead. Will be removed in the next major.
54
+ */
34
55
  violet: createTheme({
35
56
  primary: "oklch(0.55 0.24 295)",
36
57
  primaryForeground: "oklch(0.985 0 0)",
58
+ primaryHover: "oklch(0.49 0.23 295)",
59
+ link: "oklch(0.55 0.24 295)",
60
+ focus: "oklch(0.55 0.24 295)",
37
61
  accent: "oklch(0.95 0.04 295)",
38
62
  accentForeground: "oklch(0.34 0.14 295)",
39
63
  ring: "oklch(0.55 0.24 295)",
@@ -42,6 +66,9 @@ export const themePresets = {
42
66
  dark: {
43
67
  primary: "oklch(0.72 0.18 295)",
44
68
  primaryForeground: "oklch(0.18 0.03 295)",
69
+ primaryHover: "oklch(0.78 0.15 295)",
70
+ link: "oklch(0.72 0.18 295)",
71
+ focus: "oklch(0.72 0.18 295)",
45
72
  accent: "oklch(0.33 0.08 295)",
46
73
  accentForeground: "oklch(0.97 0 0)",
47
74
  ring: "oklch(0.72 0.18 295)",
@@ -49,16 +76,22 @@ export const themePresets = {
49
76
  }),
50
77
  /** A grounded emerald brand with a crisp, near-square radius — enterprise. */
51
78
  emerald: createTheme({
52
- primary: "oklch(0.58 0.15 162)",
79
+ primary: "oklch(0.5 0.12 162)",
53
80
  primaryForeground: "oklch(0.985 0 0)",
81
+ primaryHover: "oklch(0.44 0.11 162)",
82
+ link: "oklch(0.5 0.12 162)",
83
+ focus: "oklch(0.5 0.12 162)",
54
84
  accent: "oklch(0.95 0.04 162)",
55
85
  accentForeground: "oklch(0.34 0.1 162)",
56
- ring: "oklch(0.58 0.15 162)",
86
+ ring: "oklch(0.5 0.12 162)",
57
87
  radius: "0.375rem",
58
88
  }, {
59
89
  dark: {
60
90
  primary: "oklch(0.72 0.15 162)",
61
91
  primaryForeground: "oklch(0.17 0.03 162)",
92
+ primaryHover: "oklch(0.78 0.14 162)",
93
+ link: "oklch(0.72 0.15 162)",
94
+ focus: "oklch(0.72 0.15 162)",
62
95
  accent: "oklch(0.32 0.07 162)",
63
96
  accentForeground: "oklch(0.97 0 0)",
64
97
  ring: "oklch(0.72 0.15 162)",
@@ -1 +1 @@
1
- {"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/theme/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwB,MAAM,mBAAmB,CAAA;AAErE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;;;OAGG;IACH,OAAO,EAAE,WAAW,CAClB;QACE,OAAO,EAAE,sBAAsB;QAC/B,iBAAiB,EAAE,kBAAkB;QACrC,MAAM,EAAE,sBAAsB;QAC9B,gBAAgB,EAAE,sBAAsB;QACxC,IAAI,EAAE,sBAAsB;QAC5B,MAAM,EAAE,QAAQ;KACjB,EACD;QACE,IAAI,EAAE;YACJ,OAAO,EAAE,qBAAqB;YAC9B,iBAAiB,EAAE,sBAAsB;YACzC,MAAM,EAAE,sBAAsB;YAC9B,gBAAgB,EAAE,iBAAiB;YACnC,IAAI,EAAE,qBAAqB;SAC5B;KACF,CACF;IAED,4EAA4E;IAC5E,MAAM,EAAE,WAAW,CACjB;QACE,OAAO,EAAE,sBAAsB;QAC/B,iBAAiB,EAAE,kBAAkB;QACrC,MAAM,EAAE,sBAAsB;QAC9B,gBAAgB,EAAE,sBAAsB;QACxC,IAAI,EAAE,sBAAsB;QAC5B,MAAM,EAAE,UAAU;KACnB,EACD;QACE,IAAI,EAAE;YACJ,OAAO,EAAE,sBAAsB;YAC/B,iBAAiB,EAAE,sBAAsB;YACzC,MAAM,EAAE,sBAAsB;YAC9B,gBAAgB,EAAE,iBAAiB;YACnC,IAAI,EAAE,sBAAsB;SAC7B;KACF,CACF;IAED,8EAA8E;IAC9E,OAAO,EAAE,WAAW,CAClB;QACE,OAAO,EAAE,sBAAsB;QAC/B,iBAAiB,EAAE,kBAAkB;QACrC,MAAM,EAAE,sBAAsB;QAC9B,gBAAgB,EAAE,qBAAqB;QACvC,IAAI,EAAE,sBAAsB;QAC5B,MAAM,EAAE,UAAU;KACnB,EACD;QACE,IAAI,EAAE;YACJ,OAAO,EAAE,sBAAsB;YAC/B,iBAAiB,EAAE,sBAAsB;YACzC,MAAM,EAAE,sBAAsB;YAC9B,gBAAgB,EAAE,iBAAiB;YACnC,IAAI,EAAE,sBAAsB;SAC7B;KACF,CACF;CACwC,CAAA"}
1
+ {"version":3,"file":"presets.js","sourceRoot":"","sources":["../../src/theme/presets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAwB,MAAM,mBAAmB,CAAA;AAErE;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B;;;;;;;OAOG;IACH,OAAO,EAAE,WAAW,CAClB;QACE,OAAO,EAAE,sBAAsB;QAC/B,iBAAiB,EAAE,kBAAkB;QACrC,YAAY,EAAE,qBAAqB;QACnC,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,sBAAsB;QAC7B,MAAM,EAAE,sBAAsB;QAC9B,gBAAgB,EAAE,sBAAsB;QACxC,IAAI,EAAE,sBAAsB;QAC5B,MAAM,EAAE,QAAQ;KACjB,EACD;QACE,IAAI,EAAE;YACJ,OAAO,EAAE,qBAAqB;YAC9B,iBAAiB,EAAE,sBAAsB;YACzC,YAAY,EAAE,sBAAsB;YACpC,IAAI,EAAE,qBAAqB;YAC3B,KAAK,EAAE,qBAAqB;YAC5B,MAAM,EAAE,sBAAsB;YAC9B,gBAAgB,EAAE,iBAAiB;YACnC,IAAI,EAAE,qBAAqB;SAC5B;KACF,CACF;IAED;;;;;;OAMG;IACH,MAAM,EAAE,WAAW,CACjB;QACE,OAAO,EAAE,sBAAsB;QAC/B,iBAAiB,EAAE,kBAAkB;QACrC,YAAY,EAAE,sBAAsB;QACpC,IAAI,EAAE,sBAAsB;QAC5B,KAAK,EAAE,sBAAsB;QAC7B,MAAM,EAAE,sBAAsB;QAC9B,gBAAgB,EAAE,sBAAsB;QACxC,IAAI,EAAE,sBAAsB;QAC5B,MAAM,EAAE,UAAU;KACnB,EACD;QACE,IAAI,EAAE;YACJ,OAAO,EAAE,sBAAsB;YAC/B,iBAAiB,EAAE,sBAAsB;YACzC,YAAY,EAAE,sBAAsB;YACpC,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,sBAAsB;YAC7B,MAAM,EAAE,sBAAsB;YAC9B,gBAAgB,EAAE,iBAAiB;YACnC,IAAI,EAAE,sBAAsB;SAC7B;KACF,CACF;IAED,8EAA8E;IAC9E,OAAO,EAAE,WAAW,CAClB;QACE,OAAO,EAAE,qBAAqB;QAC9B,iBAAiB,EAAE,kBAAkB;QACrC,YAAY,EAAE,sBAAsB;QACpC,IAAI,EAAE,qBAAqB;QAC3B,KAAK,EAAE,qBAAqB;QAC5B,MAAM,EAAE,sBAAsB;QAC9B,gBAAgB,EAAE,qBAAqB;QACvC,IAAI,EAAE,qBAAqB;QAC3B,MAAM,EAAE,UAAU;KACnB,EACD;QACE,IAAI,EAAE;YACJ,OAAO,EAAE,sBAAsB;YAC/B,iBAAiB,EAAE,sBAAsB;YACzC,YAAY,EAAE,sBAAsB;YACpC,IAAI,EAAE,sBAAsB;YAC5B,KAAK,EAAE,sBAAsB;YAC7B,MAAM,EAAE,sBAAsB;YAC9B,gBAAgB,EAAE,iBAAiB;YACnC,IAAI,EAAE,sBAAsB;SAC7B;KACF,CACF;CACwC,CAAA"}
@@ -1,5 +1,5 @@
1
1
  import { type ReactNode } from "react";
2
- import type { ThemeDefinition } from "./create-theme.js";
2
+ import { type ThemeDefinition } from "./create-theme.js";
3
3
  /**
4
4
  * How the `.dark` class is resolved on the theme scope:
5
5
  * - `"light"` / `"dark"` — forced, ignores the OS preference.
@@ -27,8 +27,11 @@ export declare function useTheme(): ThemeContextValue;
27
27
  /** Props for {@link ThemeProvider}. */
28
28
  export interface ThemeProviderProps {
29
29
  /**
30
- * The white-label theme to apply (from {@link createTheme} or `themePresets`).
31
- * Omit to manage only the light/dark `mode` against the toolkit defaults.
30
+ * The white-label theme to apply (from {@link createTheme}). Omit to keep the
31
+ * theme of the nearest enclosing `ThemeProvider` (re-applied in this
32
+ * provider's mode, so a light island inside a dark branded scope stays on
33
+ * the brand), or, at the top, to manage only the light/dark `mode` against
34
+ * the toolkit defaults (the Miragon theme).
32
35
  */
33
36
  theme?: ThemeDefinition;
34
37
  /**
@@ -49,19 +52,34 @@ export interface ThemeProviderProps {
49
52
  /**
50
53
  * Apply a white-label {@link ThemeDefinition} to a subtree. Renders a wrapper
51
54
  * element carrying the theme's CSS variables as inline `style`, so they override
52
- * the `:root` defaults for every descendant — `Card`, `Button`, `bg-card`,
53
- * `text-primary`, and `rounded-lg` all re-skin without touching the widgets.
55
+ * the toolkit's defaults (the Miragon theme) for every descendant — `Card`,
56
+ * `Button`, `bg-card`, `text-link`, and `rounded-md` all re-skin without
57
+ * touching the widgets.
54
58
  *
55
- * Dark mode is handled at the scope: the `.dark` class is toggled on the wrapper
56
- * (not `<html>`) per the resolved {@link ThemeMode}, and the theme's `darkVars`
57
- * are layered on under it. This keeps theming local — two differently themed
59
+ * Dark mode is handled at the scope: the `.dark` class and `data-theme-mode`
60
+ * are set on the wrapper (not `<html>`) per the resolved {@link ThemeMode}. In
61
+ * dark mode the wrapper gets the toolkit's dark roles plus the theme's dark
62
+ * tokens and its mode-invariant light tokens ({@link resolveThemeVars}) — a
63
+ * light surface colour never leaks into a dark scope (mcp-toolkit#178 N35). A
64
+ * light scope inside a dark scope stays light: there, `data-theme-mode="light"`
65
+ * re-declares the toolkit's light roles. A light scope in a light document
66
+ * re-declares nothing and keeps what the document set (a consumer's `:root`
67
+ * brand). A nested provider without `theme` re-applies the enclosing one's
68
+ * theme in its own mode. This keeps theming local — two differently themed
58
69
  * subtrees (e.g. a brand preview gallery) coexist on one page.
59
70
  *
71
+ * Overlays opened inside the scope (Dialog, Sheet, Select) portal into a node
72
+ * within it, so they wear the same theme and mode (#178 N36,
73
+ * {@link usePortalContainer}). That node is the wrapper's FIRST child, an empty
74
+ * `display: contents` element: it draws no box, and `space-*`, `divide-*`,
75
+ * `gap` and `last:` on the wrapper see only your children. Only selectors on
76
+ * the wrapper's first/nth child (`first:`, `odd:`) count it.
77
+ *
60
78
  * Uses only React + the DOM (no `mcp-use/react`), so it ships from the root
61
79
  * barrel and works in a host-free standalone app, a host, or SSR alike.
62
80
  *
63
81
  * @example
64
- * <ThemeProvider theme={themePresets.violet} mode={host.theme ?? "system"}>
82
+ * <ThemeProvider theme={brand} mode={host.theme ?? "system"}>
65
83
  * <YourWidget />
66
84
  * </ThemeProvider>
67
85
  */
@@ -1 +1 @@
1
- {"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEnD,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,KAAK,EAAE,eAAe,GAAG,IAAI,CAAA;IAC7B,iEAAiE;IACjE,IAAI,EAAE,SAAS,CAAA;IACf,+EAA+E;IAC/E,YAAY,EAAE,OAAO,GAAG,MAAM,CAAA;CAC/B;AAID;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C;AA6BD,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC;;;OAGG;IACH,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;OAIG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;IACxC,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,IAAc,EACd,EAAE,EAAE,EAAU,EACd,SAAS,EACT,QAAQ,GACT,EAAE,kBAAkB,GAAG,SAAS,CA8BhC"}
1
+ {"version":3,"file":"theme-provider.d.ts","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAA;AACd,OAAO,EAAoB,KAAK,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAG1E;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;AAEnD,6CAA6C;AAC7C,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,KAAK,EAAE,eAAe,GAAG,IAAI,CAAA;IAC7B,iEAAiE;IACjE,IAAI,EAAE,SAAS,CAAA;IACf,+EAA+E;IAC/E,YAAY,EAAE,OAAO,GAAG,MAAM,CAAA;CAC/B;AAID;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C;AA6BD,uCAAuC;AACvC,MAAM,WAAW,kBAAkB;IACjC;;;;;;OAMG;IACH,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;OAIG;IACH,EAAE,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;IACxC,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,SAAS,CAAA;CACpB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,aAAa,CAAC,EAC5B,KAAK,EACL,IAAc,EACd,EAAE,EAAE,EAAU,EACd,SAAS,EACT,QAAQ,GACT,EAAE,kBAAkB,GAAG,SAAS,CA+ChC"}
@@ -1,5 +1,7 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { createContext, useContext, useEffect, useMemo, useState, } from "react";
3
+ import { resolveThemeVars } from "./create-theme.js";
4
+ import { PortalContainerContext } from "./portal-container.js";
3
5
  const ThemeContext = createContext(null);
4
6
  /**
5
7
  * Read the active theme/mode from the nearest {@link ThemeProvider}. Throws when
@@ -41,39 +43,59 @@ function useResolvedMode(mode) {
41
43
  /**
42
44
  * Apply a white-label {@link ThemeDefinition} to a subtree. Renders a wrapper
43
45
  * element carrying the theme's CSS variables as inline `style`, so they override
44
- * the `:root` defaults for every descendant — `Card`, `Button`, `bg-card`,
45
- * `text-primary`, and `rounded-lg` all re-skin without touching the widgets.
46
+ * the toolkit's defaults (the Miragon theme) for every descendant — `Card`,
47
+ * `Button`, `bg-card`, `text-link`, and `rounded-md` all re-skin without
48
+ * touching the widgets.
46
49
  *
47
- * Dark mode is handled at the scope: the `.dark` class is toggled on the wrapper
48
- * (not `<html>`) per the resolved {@link ThemeMode}, and the theme's `darkVars`
49
- * are layered on under it. This keeps theming local — two differently themed
50
+ * Dark mode is handled at the scope: the `.dark` class and `data-theme-mode`
51
+ * are set on the wrapper (not `<html>`) per the resolved {@link ThemeMode}. In
52
+ * dark mode the wrapper gets the toolkit's dark roles plus the theme's dark
53
+ * tokens and its mode-invariant light tokens ({@link resolveThemeVars}) — a
54
+ * light surface colour never leaks into a dark scope (mcp-toolkit#178 N35). A
55
+ * light scope inside a dark scope stays light: there, `data-theme-mode="light"`
56
+ * re-declares the toolkit's light roles. A light scope in a light document
57
+ * re-declares nothing and keeps what the document set (a consumer's `:root`
58
+ * brand). A nested provider without `theme` re-applies the enclosing one's
59
+ * theme in its own mode. This keeps theming local — two differently themed
50
60
  * subtrees (e.g. a brand preview gallery) coexist on one page.
51
61
  *
62
+ * Overlays opened inside the scope (Dialog, Sheet, Select) portal into a node
63
+ * within it, so they wear the same theme and mode (#178 N36,
64
+ * {@link usePortalContainer}). That node is the wrapper's FIRST child, an empty
65
+ * `display: contents` element: it draws no box, and `space-*`, `divide-*`,
66
+ * `gap` and `last:` on the wrapper see only your children. Only selectors on
67
+ * the wrapper's first/nth child (`first:`, `odd:`) count it.
68
+ *
52
69
  * Uses only React + the DOM (no `mcp-use/react`), so it ships from the root
53
70
  * barrel and works in a host-free standalone app, a host, or SSR alike.
54
71
  *
55
72
  * @example
56
- * <ThemeProvider theme={themePresets.violet} mode={host.theme ?? "system"}>
73
+ * <ThemeProvider theme={brand} mode={host.theme ?? "system"}>
57
74
  * <YourWidget />
58
75
  * </ThemeProvider>
59
76
  */
60
77
  export function ThemeProvider({ theme, mode = "light", as: As = "div", className, children, }) {
61
78
  const resolvedMode = useResolvedMode(mode);
62
79
  const isDark = resolvedMode === "dark";
63
- // Merge the light vars with the dark overrides only when dark is active, so a
64
- // dark scope gets the brand's dark palette on top of `.dark`'s defaults.
65
- const style = useMemo(() => {
66
- if (!theme)
67
- return {};
68
- if (isDark && theme.darkVars) {
69
- return { ...theme.vars, ...theme.darkVars };
70
- }
71
- return theme.vars;
72
- }, [theme, isDark]);
73
- const value = useMemo(() => ({ theme: theme ?? null, mode, resolvedMode }), [theme, mode, resolvedMode]);
74
- const classes = [isDark ? "dark" : undefined, "bg-background text-foreground", className]
80
+ const [portalContainer, setPortalContainer] = useState(null);
81
+ // Without its own theme a nested provider keeps the enclosing one's brand.
82
+ const enclosing = useContext(ThemeContext);
83
+ const activeTheme = theme ?? enclosing?.theme ?? null;
84
+ const style = useMemo(() => resolveThemeVars(activeTheme, resolvedMode), [activeTheme, resolvedMode]);
85
+ const value = useMemo(() => ({ theme: activeTheme, mode, resolvedMode }), [activeTheme, mode, resolvedMode]);
86
+ const classes = [
87
+ isDark ? "dark" : undefined,
88
+ "bg-background text-foreground font-sans",
89
+ className,
90
+ ]
75
91
  .filter(Boolean)
76
92
  .join(" ");
77
- return (_jsx(ThemeContext.Provider, { value: value, children: _jsx(As, { className: classes, style: style, "data-theme-mode": resolvedMode, children: children }) }));
93
+ // The portal node OPENS the scope as an empty `display: contents` element:
94
+ // it draws no box, yet overlays portaled into it inherit the scope's
95
+ // variables and its `.dark` / `data-theme-mode`. First, not last: Tailwind's
96
+ // `space-*`/`divide-*` and `last:` target the last child, so a trailing node
97
+ // would hand the real last child a margin or divider it never had.
98
+ const PortalRoot = As === "span" ? "span" : "div";
99
+ return (_jsx(ThemeContext.Provider, { value: value, children: _jsx(PortalContainerContext.Provider, { value: portalContainer, children: _jsxs(As, { className: classes, style: style, "data-theme-mode": resolvedMode, children: [_jsx(PortalRoot, { ref: setPortalContainer, "data-slot": "theme-portal", style: { display: "contents" } }), children] }) }) }));
78
100
  }
79
101
  //# sourceMappingURL=theme-provider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"theme-provider.js","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"theme-provider.js","sourceRoot":"","sources":["../../src/theme/theme-provider.tsx"],"names":[],"mappings":"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"}