@seed-ship/mcp-ui-solid 6.24.0 → 6.25.1

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 (124) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/README.md +47 -0
  3. package/dist/components/ActionGroupRenderer.cjs +6 -6
  4. package/dist/components/ActionGroupRenderer.cjs.map +1 -1
  5. package/dist/components/ActionGroupRenderer.js +6 -6
  6. package/dist/components/ActionGroupRenderer.js.map +1 -1
  7. package/dist/components/AutocompleteDropdown.cjs +6 -6
  8. package/dist/components/AutocompleteDropdown.cjs.map +1 -1
  9. package/dist/components/AutocompleteDropdown.js +6 -6
  10. package/dist/components/AutocompleteDropdown.js.map +1 -1
  11. package/dist/components/AutocompleteFormField.cjs +6 -5
  12. package/dist/components/AutocompleteFormField.cjs.map +1 -1
  13. package/dist/components/AutocompleteFormField.d.ts.map +1 -1
  14. package/dist/components/AutocompleteFormField.js +6 -5
  15. package/dist/components/AutocompleteFormField.js.map +1 -1
  16. package/dist/components/ChartJSRenderer.cjs +216 -6
  17. package/dist/components/ChartJSRenderer.cjs.map +1 -1
  18. package/dist/components/ChartJSRenderer.d.ts.map +1 -1
  19. package/dist/components/ChartJSRenderer.js +217 -7
  20. package/dist/components/ChartJSRenderer.js.map +1 -1
  21. package/dist/components/ChatPrompt.cjs +5 -5
  22. package/dist/components/ChatPrompt.cjs.map +1 -1
  23. package/dist/components/ChatPrompt.js +5 -5
  24. package/dist/components/ChatPrompt.js.map +1 -1
  25. package/dist/components/ComponentToolbar.cjs +5 -5
  26. package/dist/components/ComponentToolbar.cjs.map +1 -1
  27. package/dist/components/ComponentToolbar.js +5 -5
  28. package/dist/components/ComponentToolbar.js.map +1 -1
  29. package/dist/components/DegradedFallback.cjs +1 -1
  30. package/dist/components/DegradedFallback.cjs.map +1 -1
  31. package/dist/components/DegradedFallback.js +1 -1
  32. package/dist/components/DegradedFallback.js.map +1 -1
  33. package/dist/components/ExpandableWrapper.cjs +10 -7
  34. package/dist/components/ExpandableWrapper.cjs.map +1 -1
  35. package/dist/components/ExpandableWrapper.d.ts.map +1 -1
  36. package/dist/components/ExpandableWrapper.js +10 -7
  37. package/dist/components/ExpandableWrapper.js.map +1 -1
  38. package/dist/components/FormFieldRenderer.cjs +13 -12
  39. package/dist/components/FormFieldRenderer.cjs.map +1 -1
  40. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  41. package/dist/components/FormFieldRenderer.js +13 -12
  42. package/dist/components/FormFieldRenderer.js.map +1 -1
  43. package/dist/components/FormRenderer.cjs +1 -1
  44. package/dist/components/FormRenderer.cjs.map +1 -1
  45. package/dist/components/FormRenderer.js +1 -1
  46. package/dist/components/FormRenderer.js.map +1 -1
  47. package/dist/components/GenerativeUIErrorBoundary.cjs +1 -1
  48. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
  49. package/dist/components/GenerativeUIErrorBoundary.js +1 -1
  50. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
  51. package/dist/components/GhostText.cjs +2 -2
  52. package/dist/components/GhostText.cjs.map +1 -1
  53. package/dist/components/GhostText.js +2 -2
  54. package/dist/components/GhostText.js.map +1 -1
  55. package/dist/components/GraphRenderer.cjs +100 -29
  56. package/dist/components/GraphRenderer.cjs.map +1 -1
  57. package/dist/components/GraphRenderer.d.ts +1 -1
  58. package/dist/components/GraphRenderer.d.ts.map +1 -1
  59. package/dist/components/GraphRenderer.js +100 -29
  60. package/dist/components/GraphRenderer.js.map +1 -1
  61. package/dist/components/MissingValue.cjs +2 -2
  62. package/dist/components/MissingValue.cjs.map +1 -1
  63. package/dist/components/MissingValue.js +2 -2
  64. package/dist/components/MissingValue.js.map +1 -1
  65. package/dist/components/ModalRenderer.cjs +39 -31
  66. package/dist/components/ModalRenderer.cjs.map +1 -1
  67. package/dist/components/ModalRenderer.d.ts.map +1 -1
  68. package/dist/components/ModalRenderer.js +40 -32
  69. package/dist/components/ModalRenderer.js.map +1 -1
  70. package/dist/components/PortalDropdownMenu.cjs +6 -3
  71. package/dist/components/PortalDropdownMenu.cjs.map +1 -1
  72. package/dist/components/PortalDropdownMenu.d.ts.map +1 -1
  73. package/dist/components/PortalDropdownMenu.js +7 -4
  74. package/dist/components/PortalDropdownMenu.js.map +1 -1
  75. package/dist/components/ScratchpadPanel.cjs +38 -44
  76. package/dist/components/ScratchpadPanel.cjs.map +1 -1
  77. package/dist/components/ScratchpadPanel.d.ts.map +1 -1
  78. package/dist/components/ScratchpadPanel.js +38 -44
  79. package/dist/components/ScratchpadPanel.js.map +1 -1
  80. package/dist/components/UIResourceRenderer.cjs +20 -20
  81. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  82. package/dist/components/UIResourceRenderer.js +20 -20
  83. package/dist/components/UIResourceRenderer.js.map +1 -1
  84. package/dist/components/chart-missing-plugin.cjs +4 -4
  85. package/dist/components/chart-missing-plugin.cjs.map +1 -1
  86. package/dist/components/chart-missing-plugin.d.ts +3 -1
  87. package/dist/components/chart-missing-plugin.d.ts.map +1 -1
  88. package/dist/components/chart-missing-plugin.js +4 -4
  89. package/dist/components/chart-missing-plugin.js.map +1 -1
  90. package/dist/utils/math-markdown.cjs +1 -1
  91. package/dist/utils/math-markdown.cjs.map +1 -1
  92. package/dist/utils/math-markdown.js +1 -1
  93. package/dist/utils/math-markdown.js.map +1 -1
  94. package/dist/utils/theme.cjs +91 -0
  95. package/dist/utils/theme.cjs.map +1 -0
  96. package/dist/utils/theme.d.ts +11 -0
  97. package/dist/utils/theme.d.ts.map +1 -0
  98. package/dist/utils/theme.js +91 -0
  99. package/dist/utils/theme.js.map +1 -0
  100. package/docs/SECURITY-DEPENDENCIES.md +81 -0
  101. package/docs/THEMING.md +205 -0
  102. package/package.json +5 -3
  103. package/src/components/ActionGroupRenderer.tsx +6 -6
  104. package/src/components/AutocompleteDropdown.tsx +17 -17
  105. package/src/components/AutocompleteFormField.tsx +10 -9
  106. package/src/components/ChartJSRenderer.tsx +483 -239
  107. package/src/components/ChatPrompt.tsx +16 -16
  108. package/src/components/ComponentToolbar.tsx +5 -5
  109. package/src/components/DegradedFallback.tsx +9 -9
  110. package/src/components/ExpandableWrapper.tsx +15 -11
  111. package/src/components/FormFieldRenderer.tsx +52 -51
  112. package/src/components/FormRenderer.tsx +12 -12
  113. package/src/components/GenerativeUIErrorBoundary.tsx +6 -6
  114. package/src/components/GhostText.tsx +7 -7
  115. package/src/components/GraphRenderer.tsx +83 -67
  116. package/src/components/MissingValue.tsx +2 -2
  117. package/src/components/ModalRenderer.tsx +11 -5
  118. package/src/components/PortalDropdownMenu.tsx +6 -2
  119. package/src/components/ScratchpadPanel.tsx +144 -141
  120. package/src/components/UIResourceRenderer.tsx +101 -101
  121. package/src/components/chart-missing-plugin.ts +5 -3
  122. package/src/styles/autocomplete.css +53 -53
  123. package/src/utils/math-markdown.ts +1 -1
  124. package/src/utils/theme.ts +101 -0
@@ -1,5 +1,5 @@
1
1
  import { createComponent, getNextElement, getNextMarker, insert, effect, setAttribute, runHydrationEvents, setProperty, mergeProps, memo, className, style, template, use, delegateEvents } from "solid-js/web";
2
- import { createSignal, createMemo, createUniqueId, createEffect, untrack, onCleanup, Show, For } from "solid-js";
2
+ import { createSignal, onMount, createMemo, createUniqueId, createEffect, untrack, onCleanup, Show, For } from "solid-js";
3
3
  import { ExpandableWrapper, useExpanded } from "./ExpandableWrapper.js";
4
4
  import { DegradedFallback } from "./DegradedFallback.js";
5
5
  import { MissingValueMark, MissingValueLegend } from "./MissingValue.js";
@@ -9,8 +9,181 @@ import { summarizeChartMissing, PART_TO_WHOLE_CHART_TYPES } from "../utils/missi
9
9
  import { useTelemetry } from "../context/MCPUITelemetryContext.js";
10
10
  import { useMCPUIConfig } from "../context/MCPUIConfigContext.js";
11
11
  import { useMCPUIStrings } from "../context/MCPUIStringsContext.js";
12
+ import { observeTheme, readThemeTokens } from "../utils/theme.js";
12
13
  import { formatMCPUIString } from "../utils/format-string.js";
13
- var _tmpl$ = /* @__PURE__ */ template(`<h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$2 = /* @__PURE__ */ template(`<button type=button class="opacity-60 hover:opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm"><svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15">`), _tmpl$3 = /* @__PURE__ */ template(`<div class="inline-flex items-center gap-1"><button type=button class="opacity-60 hover:opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm"><svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM13.5 10.5h-6"></path></svg></button><button type=button class="opacity-60 hover:opacity-100 px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm"><svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM10.5 7.5v6m3-3h-6"></path></svg></button><!$><!/>`), _tmpl$4 = /* @__PURE__ */ template(`<button type=button class="opacity-0 group-hover:opacity-60 hover:!opacity-100 disabled:!opacity-30 disabled:cursor-not-allowed px-2 py-1 bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-600 rounded-full hover:bg-gray-100 dark:hover:bg-gray-700 transition-all shadow-sm"><svg class="w-3 h-3 text-gray-500 dark:text-gray-400"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">`), _tmpl$5 = /* @__PURE__ */ template(`<tr><td class="px-3 py-6 text-center text-gray-500 dark:text-gray-400">`), _tmpl$6 = /* @__PURE__ */ template(`<div><table class="w-full border-collapse text-left text-sm"><caption class=sr-only><!$><!/> — <!$><!/></caption><thead class="bg-gray-50 dark:bg-gray-900/40"><tr></tr></thead><tbody><!$><!/><!$><!/>`), _tmpl$7 = /* @__PURE__ */ template(`<div class="absolute inset-0 flex items-center justify-center bg-white/80 dark:bg-gray-800/80"><div class="flex flex-col items-center gap-2"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600"></div><span class="text-sm text-gray-500 dark:text-gray-400">`), _tmpl$8 = /* @__PURE__ */ template(`<p>`), _tmpl$9 = /* @__PURE__ */ template(`<p data-mcp-chart-note=no-data>`), _tmpl$0 = /* @__PURE__ */ template(`<div data-mcp-chart-notes class="mt-2 space-y-0.5 text-xs text-gray-600 dark:text-gray-400"><!$><!/><!$><!/>`), _tmpl$1 = /* @__PURE__ */ template(`<div><div class="flex items-center justify-between gap-3 mb-3 flex-shrink-0"><div class=min-w-0></div><div class="flex items-center gap-2"><div class="inline-flex rounded-md border border-gray-200 p-0.5 dark:border-gray-600"role=group><button type=button></button><button type=button></button></div><!$><!/><!$><!/></div></div><p class=sr-only><!$><!/>. <!$><!/></p><!$><!/><!$><!/><div><canvas role=img></canvas><!$><!/></div><!$><!/>`), _tmpl$10 = /* @__PURE__ */ template(`<th scope=col class="px-3 py-2 font-medium text-gray-900 dark:text-gray-100">`), _tmpl$11 = /* @__PURE__ */ template(`<tr class="border-t border-gray-100 dark:border-gray-700">`), _tmpl$12 = /* @__PURE__ */ template(`<td class="px-3 py-2 text-gray-700 dark:text-gray-300">`);
14
+ var _tmpl$ = /* @__PURE__ */ template(`<h3 class="text-sm font-semibold text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-white,#fff))]">`), _tmpl$2 = /* @__PURE__ */ template(`<button type=button class="opacity-60 hover:opacity-100 px-2 py-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]"><svg class="w-3 h-3 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15">`), _tmpl$3 = /* @__PURE__ */ template(`<div class="inline-flex items-center gap-1"><button type=button class="opacity-60 hover:opacity-100 px-2 py-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]"><svg class="w-3 h-3 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM13.5 10.5h-6"></path></svg></button><button type=button class="opacity-60 hover:opacity-100 px-2 py-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]"><svg class="w-3 h-3 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607zM10.5 7.5v6m3-3h-6"></path></svg></button><!$><!/>`), _tmpl$4 = /* @__PURE__ */ template(`<button type=button class="opacity-0 group-hover:opacity-60 hover:!opacity-100 disabled:!opacity-30 disabled:cursor-not-allowed px-2 py-1 bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))] rounded-full hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))] transition-all shadow-[var(--mcp-ui-shadow,var(--shadow-sm))]"><svg class="w-3 h-3 text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"fill=none viewBox="0 0 24 24"stroke=currentColor><path stroke-linecap=round stroke-linejoin=round stroke-width=2 d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z">`), _tmpl$5 = /* @__PURE__ */ template(`<tr><td class="px-3 py-6 text-center text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]">`), _tmpl$6 = /* @__PURE__ */ template(`<div><table class="w-full border-collapse text-left text-sm"><caption class=sr-only><!$><!/> — <!$><!/></caption><thead class="bg-[color:var(--mcp-ui-surface-muted,var(--color-gray-50,#f9fafb))] dark:bg-[color:var(--mcp-ui-surface,color-mix(in_oklab,var(--color-gray-900,#111827)_40%,transparent))]"><tr></tr></thead><tbody><!$><!/><!$><!/>`), _tmpl$7 = /* @__PURE__ */ template(`<div class="absolute inset-0 flex items-center justify-center bg-[color:var(--mcp-ui-surface,color-mix(in_oklab,var(--color-white,#fff)_80%,transparent))] dark:bg-[color:var(--mcp-ui-surface,color-mix(in_oklab,var(--color-gray-800,#1f2937)_80%,transparent))]"><div class="flex flex-col items-center gap-2"><div class="animate-spin rounded-full h-8 w-8 border-b-2 border-[color:var(--mcp-ui-accent-border,var(--color-blue-600))]"></div><span class="text-sm text-[color:var(--mcp-ui-fg-muted,var(--color-gray-500,#6b7280))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]">`), _tmpl$8 = /* @__PURE__ */ template(`<p>`), _tmpl$9 = /* @__PURE__ */ template(`<p data-mcp-chart-note=no-data>`), _tmpl$0 = /* @__PURE__ */ template(`<div data-mcp-chart-notes class="mt-2 space-y-0.5 text-xs text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] dark:text-[color:var(--mcp-ui-fg-subtle,var(--color-gray-400,#9ca3af))]"><!$><!/><!$><!/>`), _tmpl$1 = /* @__PURE__ */ template(`<div><div class="flex items-center justify-between gap-3 mb-3 flex-shrink-0"><div class=min-w-0></div><div class="flex items-center gap-2"><div class="inline-flex rounded-md border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] p-0.5 dark:border-[color:var(--mcp-ui-border,var(--color-gray-600,#4b5563))]"role=group><button type=button></button><button type=button></button></div><!$><!/><!$><!/></div></div><p class=sr-only><!$><!/>. <!$><!/></p><!$><!/><!$><!/><div><canvas role=img></canvas><!$><!/></div><!$><!/>`), _tmpl$10 = /* @__PURE__ */ template(`<th scope=col class="px-3 py-2 font-medium text-[color:var(--mcp-ui-fg,var(--color-gray-900,#111827))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-100,#f3f4f6))]">`), _tmpl$11 = /* @__PURE__ */ template(`<tr class="border-t border-[color:var(--mcp-ui-border,var(--color-gray-100,#f3f4f6))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))]">`), _tmpl$12 = /* @__PURE__ */ template(`<td class="px-3 py-2 text-[color:var(--mcp-ui-fg,var(--color-gray-700,#374151))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))]">`);
15
+ const CHART_THEME_TOKENS = [...Array.from({
16
+ length: 8
17
+ }, (_, i) => `--mcp-ui-chart-${i + 1}`), "--mcp-ui-chart-grid", "--mcp-ui-chart-axis", "--mcp-ui-chart-label", "--mcp-ui-surface", "--mcp-ui-fg", "--mcp-ui-border"];
18
+ function createChartTheme(params, baseOptions, root, chartConfig) {
19
+ let tokens = readThemeTokens(root, CHART_THEME_TOKENS);
20
+ const originalDatasets = params.data.datasets.map((dataset) => ({
21
+ ...dataset
22
+ }));
23
+ let engineColors;
24
+ const sharedPaintOptions = /* @__PURE__ */ new WeakMap();
25
+ const paths = [{
26
+ path: ["plugins", "legend", "labels", "color"],
27
+ token: "--mcp-ui-chart-label"
28
+ }, {
29
+ path: ["plugins", "tooltip", "backgroundColor"],
30
+ token: "--mcp-ui-surface"
31
+ }, {
32
+ path: ["plugins", "tooltip", "titleColor"],
33
+ token: "--mcp-ui-fg"
34
+ }, {
35
+ path: ["plugins", "tooltip", "bodyColor"],
36
+ token: "--mcp-ui-fg"
37
+ }, {
38
+ path: ["plugins", "tooltip", "footerColor"],
39
+ token: "--mcp-ui-fg"
40
+ }, {
41
+ path: ["plugins", "tooltip", "borderColor"],
42
+ token: "--mcp-ui-border"
43
+ }];
44
+ const configuredScales = Object.keys(baseOptions.scales ?? {});
45
+ const scales = configuredScales.length ? configuredScales : params.type === "radar" || params.type === "polarArea" ? ["r"] : params.type === "pie" || params.type === "doughnut" ? [] : ["x", "y"];
46
+ const knownScales = /* @__PURE__ */ new Set();
47
+ const addScalePaths = (names) => {
48
+ for (const scale of names) {
49
+ if (knownScales.has(scale)) continue;
50
+ knownScales.add(scale);
51
+ for (const [part, token] of [["grid", "--mcp-ui-chart-grid"], ["border", "--mcp-ui-chart-axis"], ["ticks", "--mcp-ui-chart-label"], ["title", "--mcp-ui-chart-label"], ...scale === "r" ? [["angleLines", "--mcp-ui-chart-grid"], ["pointLabels", "--mcp-ui-chart-label"]] : []]) paths.push({
52
+ path: ["scales", scale, part, "color"],
53
+ token
54
+ });
55
+ }
56
+ };
57
+ addScalePaths(scales);
58
+ const read = (value, path) => path.reduce((part, key) => part == null ? void 0 : part[key], value);
59
+ const owned = /* @__PURE__ */ new Set();
60
+ const applyOptions = (options) => {
61
+ var _a;
62
+ for (const {
63
+ path,
64
+ token
65
+ } of paths) {
66
+ if (read(baseOptions, path) !== void 0) continue;
67
+ if (token === "--mcp-ui-chart-label" && ((_a = params.options) == null ? void 0 : _a.color) !== void 0) continue;
68
+ let blocked = false;
69
+ for (let i = 1; i < path.length; i++) {
70
+ const part = read(baseOptions, path.slice(0, i));
71
+ if (part === false || part === null) blocked = true;
72
+ }
73
+ if (blocked) continue;
74
+ const key = path.join(".");
75
+ const color = tokens[token];
76
+ if (!color && !owned.has(key)) continue;
77
+ let target = options;
78
+ for (const part of path.slice(0, -1)) {
79
+ target[part] = {
80
+ ...target[part]
81
+ };
82
+ target = target[part];
83
+ }
84
+ if (color) {
85
+ target[path.at(-1)] = color;
86
+ owned.add(key);
87
+ } else {
88
+ delete target[path.at(-1)];
89
+ owned.delete(key);
90
+ }
91
+ }
92
+ };
93
+ const plugin = {
94
+ id: "mcp-ui-theme",
95
+ beforeInit(chart) {
96
+ addScalePaths(Object.keys(chart.config.options.scales ?? {}));
97
+ applyOptions(chart.config.options);
98
+ },
99
+ // Global Colors runs first. Capture its actual output rather than copying
100
+ // a version-specific 7-color palette (or changing its opt-out semantics).
101
+ beforeLayout(chart) {
102
+ const datasets = chart.data.datasets;
103
+ engineColors ?? (engineColors = datasets.map((dataset) => ({
104
+ backgroundColor: Array.isArray(dataset.backgroundColor) ? [...dataset.backgroundColor] : dataset.backgroundColor,
105
+ borderColor: Array.isArray(dataset.borderColor) ? [...dataset.borderColor] : dataset.borderColor
106
+ })));
107
+ const callerOptions = params.options;
108
+ let pointOffset = 0;
109
+ datasets.forEach((dataset, index) => {
110
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
111
+ const original = originalDatasets[index];
112
+ const baseline = engineColors[index];
113
+ if (!original || !baseline) return;
114
+ const datasetType = original.type ?? params.type;
115
+ const perPoint = ["pie", "doughnut", "polarArea"].includes(datasetType);
116
+ const lineWithPoints = datasetType === "line" || datasetType === "radar";
117
+ const elementKinds = datasetType === "bar" ? ["bar"] : perPoint ? ["arc"] : lineWithPoints ? ["line"] : ["point"];
118
+ const hasSeriesToken = perPoint ? dataset.data.some((_, i) => tokens[`--mcp-ui-chart-${(pointOffset + i) % 8 + 1}`]) : Boolean(tokens[`--mcp-ui-chart-${index % 8 + 1}`]);
119
+ for (const field of ["backgroundColor", "borderColor"]) {
120
+ if (original[field] !== void 0) continue;
121
+ const callerDatasetColor = (_b = (_a = callerOptions == null ? void 0 : callerOptions.datasets) == null ? void 0 : _a[datasetType]) == null ? void 0 : _b[field];
122
+ if (callerDatasetColor !== void 0) {
123
+ const color = hasSeriesToken ? callerDatasetColor : baseline[field];
124
+ if (color !== void 0) dataset[field] = color;
125
+ else delete dataset[field];
126
+ continue;
127
+ }
128
+ if ((callerOptions == null ? void 0 : callerOptions[field]) !== void 0 || elementKinds.some((kind) => {
129
+ var _a2, _b2;
130
+ return ((_b2 = (_a2 = callerOptions == null ? void 0 : callerOptions.elements) == null ? void 0 : _a2[kind]) == null ? void 0 : _b2[field]) !== void 0;
131
+ })) continue;
132
+ if (lineWithPoints && hasSeriesToken) {
133
+ const pointField = field === "borderColor" ? "pointBorderColor" : "pointBackgroundColor";
134
+ const scopedPointPaint = (_f = (_e = (_d = (_c = callerOptions == null ? void 0 : callerOptions.datasets) == null ? void 0 : _c[datasetType]) == null ? void 0 : _d.elements) == null ? void 0 : _e.point) == null ? void 0 : _f[field];
135
+ const pointPaint = scopedPointPaint !== void 0 ? scopedPointPaint : (_h = (_g = callerOptions == null ? void 0 : callerOptions.elements) == null ? void 0 : _g.point) == null ? void 0 : _h[field];
136
+ if (original[pointField] === void 0 && ((_j = (_i = callerOptions == null ? void 0 : callerOptions.datasets) == null ? void 0 : _i[datasetType]) == null ? void 0 : _j[pointField]) === void 0 && (callerOptions == null ? void 0 : callerOptions[pointField]) === void 0 && pointPaint !== void 0) {
137
+ dataset[pointField] = pointPaint;
138
+ }
139
+ }
140
+ if (perPoint && field === "borderColor") continue;
141
+ if (perPoint) {
142
+ const previous = baseline[field];
143
+ const colors = dataset.data.map((_, i) => tokens[`--mcp-ui-chart-${(pointOffset + i) % 8 + 1}`] ?? (Array.isArray(previous) ? previous[i % previous.length] : previous));
144
+ dataset[field] = colors.some((_, i) => tokens[`--mcp-ui-chart-${(pointOffset + i) % 8 + 1}`]) ? colors : previous;
145
+ } else {
146
+ const color = tokens[`--mcp-ui-chart-${index % 8 + 1}`];
147
+ if (color || baseline[field] !== void 0) dataset[field] = color ?? baseline[field];
148
+ else delete dataset[field];
149
+ }
150
+ }
151
+ if (perPoint) pointOffset += dataset.data.length;
152
+ });
153
+ },
154
+ afterDatasetUpdate(_chart, args) {
155
+ var _a, _b;
156
+ const meta = args.meta;
157
+ if (!((_a = meta == null ? void 0 : meta.data) == null ? void 0 : _a.length) || typeof ((_b = meta.controller) == null ? void 0 : _b.getStyle) !== "function") return;
158
+ const index = meta.data.findIndex((element) => {
159
+ var _a2;
160
+ return ((_a2 = element.options) == null ? void 0 : _a2.$shared) && !element.active;
161
+ });
162
+ if (index >= 0 && !Object.isFrozen(meta.data[index].options)) {
163
+ sharedPaintOptions.set(meta.controller, meta.data[index].options);
164
+ }
165
+ if (args.mode !== "none") return;
166
+ const shared = sharedPaintOptions.get(meta.controller);
167
+ if (!shared) return;
168
+ const resolved = meta.controller.getStyle(index >= 0 ? index : 0, false);
169
+ if (!resolved.$shared) return;
170
+ shared.backgroundColor = resolved.backgroundColor;
171
+ shared.borderColor = resolved.borderColor;
172
+ }
173
+ };
174
+ chartConfig.plugins = [...chartConfig.plugins ?? [], plugin];
175
+ return {
176
+ applyOptions,
177
+ refresh(chart) {
178
+ const next = readThemeTokens(root, CHART_THEME_TOKENS);
179
+ if (CHART_THEME_TOKENS.every((name) => next[name] === tokens[name])) return;
180
+ tokens = next;
181
+ addScalePaths(Object.keys(chart.scales ?? chart.config.options.scales ?? {}));
182
+ applyOptions(chart.config.options);
183
+ chart.update("none");
184
+ }
185
+ };
186
+ }
14
187
  let ChartJS = null;
15
188
  let chartJSLoadPromise = null;
16
189
  const loadChartJS = async () => {
@@ -101,8 +274,18 @@ const ChartJSRenderer = (props) => {
101
274
  const [zoomPlugin, setZoomPlugin] = createSignal(null);
102
275
  const [isZoomed, setIsZoomed] = createSignal(false);
103
276
  let canvasRef;
277
+ let themeRoot;
104
278
  let chartInstance;
279
+ let chartTheme;
105
280
  let renderVersion = 0;
281
+ onMount(() => {
282
+ if (themeRoot) {
283
+ const stop = observeTheme(themeRoot, () => {
284
+ if (chartInstance) chartTheme == null ? void 0 : chartTheme.refresh(chartInstance);
285
+ });
286
+ onCleanup(stop);
287
+ }
288
+ });
106
289
  const params = () => props.component.params;
107
290
  const telemetry = useTelemetry();
108
291
  const config = useMCPUIConfig();
@@ -274,7 +457,15 @@ const ChartJSRenderer = (props) => {
274
457
  applyUnitAxisTitle(baseOptions, chartParams.type, chartUnit);
275
458
  const chartConfig = {
276
459
  type: chartParams.type,
277
- data: chartParams.data,
460
+ // The Colors plugin writes its generated palette onto datasets. Never
461
+ // let that turn a shared payload into caller-supplied colors for the
462
+ // next renderer, nor mutate data owned by a host application.
463
+ data: {
464
+ ...chartParams.data,
465
+ datasets: chartParams.data.datasets.map((dataset) => ({
466
+ ...dataset
467
+ }))
468
+ },
278
469
  options: baseOptions
279
470
  };
280
471
  if (chartUnit !== void 0 || chartMissing.hasMissing) {
@@ -307,9 +498,26 @@ const ChartJSRenderer = (props) => {
307
498
  getFontFamily: () => {
308
499
  var _a2, _b2;
309
500
  return (_b2 = (_a2 = Chart == null ? void 0 : Chart.defaults) == null ? void 0 : _a2.font) == null ? void 0 : _b2.family;
501
+ },
502
+ getTextColor: () => {
503
+ var _a2;
504
+ return ((_a2 = chartParams.options) == null ? void 0 : _a2.color) ?? readThemeTokens(themeRoot, ["--mcp-ui-chart-label"])["--mcp-ui-chart-label"];
310
505
  }
311
506
  })];
312
507
  }
508
+ if (themeRoot) {
509
+ const originalOptions = {
510
+ ...baseOptions,
511
+ plugins: {
512
+ ...baseOptions.plugins
513
+ },
514
+ scales: baseOptions.scales ? {
515
+ ...baseOptions.scales
516
+ } : void 0
517
+ };
518
+ chartTheme = createChartTheme(chartParams, originalOptions, themeRoot, chartConfig);
519
+ chartTheme.applyOptions(baseOptions);
520
+ }
313
521
  chartInstance = new Chart(canvasRef, chartConfig);
314
522
  setIsZoomed(false);
315
523
  setIsLoading(false);
@@ -360,6 +568,8 @@ const ChartJSRenderer = (props) => {
360
568
  return createComponent(ContextAwareChartLayout, {
361
569
  render: (isExpanded2) => (() => {
362
570
  var _el$ = getNextElement(_tmpl$1), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$5 = _el$3.nextSibling, _el$6 = _el$5.firstChild, _el$7 = _el$6.firstChild, _el$8 = _el$7.nextSibling, _el$14 = _el$6.nextSibling, [_el$15, _co$2] = getNextMarker(_el$14.nextSibling), _el$16 = _el$15.nextSibling, [_el$17, _co$3] = getNextMarker(_el$16.nextSibling), _el$18 = _el$2.nextSibling, _el$20 = _el$18.firstChild, [_el$21, _co$4] = getNextMarker(_el$20.nextSibling), _el$19 = _el$21.nextSibling, _el$22 = _el$19.nextSibling, [_el$23, _co$5] = getNextMarker(_el$22.nextSibling), _el$56 = _el$18.nextSibling, [_el$57, _co$11] = getNextMarker(_el$56.nextSibling), _el$58 = _el$57.nextSibling, [_el$59, _co$12] = getNextMarker(_el$58.nextSibling), _el$41 = _el$59.nextSibling, _el$42 = _el$41.firstChild, _el$47 = _el$42.nextSibling, [_el$48, _co$0] = getNextMarker(_el$47.nextSibling), _el$60 = _el$41.nextSibling, [_el$61, _co$13] = getNextMarker(_el$60.nextSibling);
571
+ var _ref$ = themeRoot;
572
+ typeof _ref$ === "function" ? use(_ref$, _el$) : themeRoot = _el$;
363
573
  insert(_el$3, createComponent(Show, {
364
574
  get when() {
365
575
  return params().title;
@@ -522,7 +732,7 @@ const ChartJSRenderer = (props) => {
522
732
  }
523
733
  }), _el$40, _co$9);
524
734
  effect((_p$) => {
525
- var _v$0 = `w-full overflow-auto rounded border border-gray-200 dark:border-gray-700 ${isExpanded2() ? "flex-1 min-h-0" : ""}`, _v$1 = isExpanded2() ? void 0 : {
735
+ var _v$0 = `w-full overflow-auto rounded border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))] ${isExpanded2() ? "flex-1 min-h-0" : ""}`, _v$1 = isExpanded2() ? void 0 : {
526
736
  height: params().height || "250px",
527
737
  "max-height": "70vh"
528
738
  };
@@ -546,8 +756,8 @@ const ChartJSRenderer = (props) => {
546
756
  })];
547
757
  }
548
758
  }), _el$59, _co$12);
549
- var _ref$ = canvasRef;
550
- typeof _ref$ === "function" ? use(_ref$, _el$42) : canvasRef = _el$42;
759
+ var _ref$2 = canvasRef;
760
+ typeof _ref$2 === "function" ? use(_ref$2, _el$42) : canvasRef = _el$42;
551
761
  insert(_el$41, createComponent(Show, {
552
762
  get when() {
553
763
  return memo(() => !!isLoading())() && activeView() === "chart";
@@ -595,7 +805,7 @@ const ChartJSRenderer = (props) => {
595
805
  }
596
806
  }), _el$61, _co$13);
597
807
  effect((_p$) => {
598
- var _v$10 = `relative w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden p-4 group ${isExpanded2() ? "flex-1 min-h-0 flex flex-col" : ""} ${params().className || ""}`, _v$11 = strings.chartViewSelector, _v$12 = activeView() === "chart", _v$13 = `rounded px-2 py-1 text-xs font-medium transition-colors ${activeView() === "chart" ? "bg-gray-900 text-white dark:bg-gray-100 dark:text-gray-900" : "text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700"}`, _v$14 = activeView() === "data", _v$15 = `rounded px-2 py-1 text-xs font-medium transition-colors ${activeView() === "data" ? "bg-gray-900 text-white dark:bg-gray-100 dark:text-gray-900" : "text-gray-600 hover:bg-gray-100 dark:text-gray-300 dark:hover:bg-gray-700"}`, _v$16 = `relative w-full ${isExpanded2() ? "flex-1 min-h-0" : ""}`, _v$17 = error() || activeView() === "data" ? {
808
+ var _v$10 = `mcp-ui-root relative w-full bg-[color:var(--mcp-ui-surface,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-surface,var(--color-gray-800,#1f2937))] rounded-lg shadow-[var(--mcp-ui-shadow,var(--shadow-sm))] border border-[color:var(--mcp-ui-border,var(--color-gray-200,#e5e7eb))] dark:border-[color:var(--mcp-ui-border,var(--color-gray-700,#374151))] overflow-hidden p-4 group ${isExpanded2() ? "flex-1 min-h-0 flex flex-col" : ""} ${params().className || ""}`, _v$11 = strings.chartViewSelector, _v$12 = activeView() === "chart", _v$13 = `rounded px-2 py-1 text-xs font-medium transition-colors ${activeView() === "chart" ? "bg-[color:var(--mcp-ui-accent,var(--color-gray-900,#111827))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-accent,var(--color-gray-100,#f3f4f6))] dark:text-[color:var(--mcp-ui-accent-fg,var(--color-gray-900,#111827))]" : "text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))]"}`, _v$14 = activeView() === "data", _v$15 = `rounded px-2 py-1 text-xs font-medium transition-colors ${activeView() === "data" ? "bg-[color:var(--mcp-ui-accent,var(--color-gray-900,#111827))] text-[color:var(--mcp-ui-accent-fg,var(--color-white,#fff))] dark:bg-[color:var(--mcp-ui-accent,var(--color-gray-100,#f3f4f6))] dark:text-[color:var(--mcp-ui-accent-fg,var(--color-gray-900,#111827))]" : "text-[color:var(--mcp-ui-fg-muted,var(--color-gray-600,#4b5563))] hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-100,#f3f4f6))] dark:text-[color:var(--mcp-ui-fg,var(--color-gray-300,#d1d5db))] dark:hover:bg-[color:var(--mcp-ui-surface-hover,var(--color-gray-700,#374151))]"}`, _v$16 = `relative w-full ${isExpanded2() ? "flex-1 min-h-0" : ""}`, _v$17 = error() || activeView() === "data" ? {
599
809
  display: "none"
600
810
  } : isExpanded2() ? {
601
811
  height: "100%",