@seed-ship/mcp-ui-solid 6.23.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 (172) hide show
  1. package/CHANGELOG.md +167 -0
  2. package/README.md +154 -2
  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 +406 -70
  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 +407 -71
  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 +35 -3
  30. package/dist/components/DegradedFallback.cjs.map +1 -1
  31. package/dist/components/DegradedFallback.d.ts +7 -0
  32. package/dist/components/DegradedFallback.d.ts.map +1 -1
  33. package/dist/components/DegradedFallback.js +35 -3
  34. package/dist/components/DegradedFallback.js.map +1 -1
  35. package/dist/components/ExpandableWrapper.cjs +10 -7
  36. package/dist/components/ExpandableWrapper.cjs.map +1 -1
  37. package/dist/components/ExpandableWrapper.d.ts.map +1 -1
  38. package/dist/components/ExpandableWrapper.js +10 -7
  39. package/dist/components/ExpandableWrapper.js.map +1 -1
  40. package/dist/components/FormFieldRenderer.cjs +13 -12
  41. package/dist/components/FormFieldRenderer.cjs.map +1 -1
  42. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  43. package/dist/components/FormFieldRenderer.js +13 -12
  44. package/dist/components/FormFieldRenderer.js.map +1 -1
  45. package/dist/components/FormRenderer.cjs +1 -1
  46. package/dist/components/FormRenderer.cjs.map +1 -1
  47. package/dist/components/FormRenderer.js +1 -1
  48. package/dist/components/FormRenderer.js.map +1 -1
  49. package/dist/components/GenerativeUIErrorBoundary.cjs +1 -1
  50. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
  51. package/dist/components/GenerativeUIErrorBoundary.js +1 -1
  52. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
  53. package/dist/components/GhostText.cjs +2 -2
  54. package/dist/components/GhostText.cjs.map +1 -1
  55. package/dist/components/GhostText.js +2 -2
  56. package/dist/components/GhostText.js.map +1 -1
  57. package/dist/components/GraphRenderer.cjs +100 -29
  58. package/dist/components/GraphRenderer.cjs.map +1 -1
  59. package/dist/components/GraphRenderer.d.ts +1 -1
  60. package/dist/components/GraphRenderer.d.ts.map +1 -1
  61. package/dist/components/GraphRenderer.js +100 -29
  62. package/dist/components/GraphRenderer.js.map +1 -1
  63. package/dist/components/MissingValue.cjs +43 -0
  64. package/dist/components/MissingValue.cjs.map +1 -0
  65. package/dist/components/MissingValue.d.ts +27 -0
  66. package/dist/components/MissingValue.d.ts.map +1 -0
  67. package/dist/components/MissingValue.js +43 -0
  68. package/dist/components/MissingValue.js.map +1 -0
  69. package/dist/components/ModalRenderer.cjs +39 -31
  70. package/dist/components/ModalRenderer.cjs.map +1 -1
  71. package/dist/components/ModalRenderer.d.ts.map +1 -1
  72. package/dist/components/ModalRenderer.js +40 -32
  73. package/dist/components/ModalRenderer.js.map +1 -1
  74. package/dist/components/PortalDropdownMenu.cjs +6 -3
  75. package/dist/components/PortalDropdownMenu.cjs.map +1 -1
  76. package/dist/components/PortalDropdownMenu.d.ts.map +1 -1
  77. package/dist/components/PortalDropdownMenu.js +7 -4
  78. package/dist/components/PortalDropdownMenu.js.map +1 -1
  79. package/dist/components/ScratchpadPanel.cjs +38 -44
  80. package/dist/components/ScratchpadPanel.cjs.map +1 -1
  81. package/dist/components/ScratchpadPanel.d.ts.map +1 -1
  82. package/dist/components/ScratchpadPanel.js +38 -44
  83. package/dist/components/ScratchpadPanel.js.map +1 -1
  84. package/dist/components/UIResourceRenderer.cjs +255 -217
  85. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  86. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  87. package/dist/components/UIResourceRenderer.js +255 -217
  88. package/dist/components/UIResourceRenderer.js.map +1 -1
  89. package/dist/components/chart-data-table.cjs +30 -5
  90. package/dist/components/chart-data-table.cjs.map +1 -1
  91. package/dist/components/chart-data-table.d.ts +18 -1
  92. package/dist/components/chart-data-table.d.ts.map +1 -1
  93. package/dist/components/chart-data-table.js +30 -5
  94. package/dist/components/chart-data-table.js.map +1 -1
  95. package/dist/components/chart-missing-plugin.cjs +194 -0
  96. package/dist/components/chart-missing-plugin.cjs.map +1 -0
  97. package/dist/components/chart-missing-plugin.d.ts +129 -0
  98. package/dist/components/chart-missing-plugin.d.ts.map +1 -0
  99. package/dist/components/chart-missing-plugin.js +194 -0
  100. package/dist/components/chart-missing-plugin.js.map +1 -0
  101. package/dist/context/MCPUIStringsContext.cjs +12 -1
  102. package/dist/context/MCPUIStringsContext.cjs.map +1 -1
  103. package/dist/context/MCPUIStringsContext.d.ts +62 -0
  104. package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
  105. package/dist/context/MCPUIStringsContext.js +12 -1
  106. package/dist/context/MCPUIStringsContext.js.map +1 -1
  107. package/dist/services/component-registry.cjs +9 -2
  108. package/dist/services/component-registry.cjs.map +1 -1
  109. package/dist/services/component-registry.d.ts.map +1 -1
  110. package/dist/services/component-registry.js +9 -2
  111. package/dist/services/component-registry.js.map +1 -1
  112. package/dist/services/validation.cjs +31 -8
  113. package/dist/services/validation.cjs.map +1 -1
  114. package/dist/services/validation.d.ts.map +1 -1
  115. package/dist/services/validation.js +31 -8
  116. package/dist/services/validation.js.map +1 -1
  117. package/dist/types/index.d.ts +14 -2
  118. package/dist/types/index.d.ts.map +1 -1
  119. package/dist/utils/degraded-projections.cjs +19 -3
  120. package/dist/utils/degraded-projections.cjs.map +1 -1
  121. package/dist/utils/degraded-projections.d.ts +22 -2
  122. package/dist/utils/degraded-projections.d.ts.map +1 -1
  123. package/dist/utils/degraded-projections.js +19 -3
  124. package/dist/utils/degraded-projections.js.map +1 -1
  125. package/dist/utils/math-markdown.cjs +1 -1
  126. package/dist/utils/math-markdown.cjs.map +1 -1
  127. package/dist/utils/math-markdown.js +1 -1
  128. package/dist/utils/math-markdown.js.map +1 -1
  129. package/dist/utils/missing-value.cjs +60 -0
  130. package/dist/utils/missing-value.cjs.map +1 -0
  131. package/dist/utils/missing-value.d.ts +79 -0
  132. package/dist/utils/missing-value.d.ts.map +1 -0
  133. package/dist/utils/missing-value.js +60 -0
  134. package/dist/utils/missing-value.js.map +1 -0
  135. package/dist/utils/theme.cjs +91 -0
  136. package/dist/utils/theme.cjs.map +1 -0
  137. package/dist/utils/theme.d.ts +11 -0
  138. package/dist/utils/theme.d.ts.map +1 -0
  139. package/dist/utils/theme.js +91 -0
  140. package/dist/utils/theme.js.map +1 -0
  141. package/docs/SECURITY-DEPENDENCIES.md +81 -0
  142. package/docs/THEMING.md +205 -0
  143. package/package.json +7 -5
  144. package/src/components/ActionGroupRenderer.tsx +6 -6
  145. package/src/components/AutocompleteDropdown.tsx +17 -17
  146. package/src/components/AutocompleteFormField.tsx +10 -9
  147. package/src/components/ChartJSRenderer.tsx +609 -212
  148. package/src/components/ChatPrompt.tsx +16 -16
  149. package/src/components/ComponentToolbar.tsx +5 -5
  150. package/src/components/DegradedFallback.tsx +33 -11
  151. package/src/components/ExpandableWrapper.tsx +15 -11
  152. package/src/components/FormFieldRenderer.tsx +52 -51
  153. package/src/components/FormRenderer.tsx +12 -12
  154. package/src/components/GenerativeUIErrorBoundary.tsx +6 -6
  155. package/src/components/GhostText.tsx +7 -7
  156. package/src/components/GraphRenderer.tsx +83 -67
  157. package/src/components/MissingValue.tsx +61 -0
  158. package/src/components/ModalRenderer.tsx +11 -5
  159. package/src/components/PortalDropdownMenu.tsx +6 -2
  160. package/src/components/ScratchpadPanel.tsx +144 -141
  161. package/src/components/UIResourceRenderer.tsx +143 -110
  162. package/src/components/chart-data-table.ts +50 -6
  163. package/src/components/chart-missing-plugin.ts +336 -0
  164. package/src/context/MCPUIStringsContext.tsx +76 -0
  165. package/src/services/component-registry.ts +10 -2
  166. package/src/services/validation.ts +44 -9
  167. package/src/styles/autocomplete.css +53 -53
  168. package/src/types/index.ts +13 -1
  169. package/src/utils/degraded-projections.ts +44 -4
  170. package/src/utils/math-markdown.ts +1 -1
  171. package/src/utils/missing-value.ts +127 -0
  172. package/src/utils/theme.ts +101 -0
@@ -1,13 +1,189 @@
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
+ import { MissingValueMark, MissingValueLegend } from "./MissingValue.js";
5
6
  import { chartToDataTable } from "./chart-data-table.js";
7
+ import { missingNoteKind, applyUnitAxisTitle, createTooltipLabel, withDatasetsNoGapSpan, createMissingLegendGenerator, createMissingValuesPlugin } from "./chart-missing-plugin.js";
8
+ import { summarizeChartMissing, PART_TO_WHOLE_CHART_TYPES } from "../utils/missing-value.js";
6
9
  import { useTelemetry } from "../context/MCPUITelemetryContext.js";
7
10
  import { useMCPUIConfig } from "../context/MCPUIConfigContext.js";
8
11
  import { useMCPUIStrings } from "../context/MCPUIStringsContext.js";
12
+ import { observeTheme, readThemeTokens } from "../utils/theme.js";
9
13
  import { formatMCPUIString } from "../utils/format-string.js";
10
- 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(`<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><!$><!/>`), _tmpl$9 = /* @__PURE__ */ template(`<th scope=col class="px-3 py-2 font-medium text-gray-900 dark:text-gray-100">`), _tmpl$0 = /* @__PURE__ */ template(`<tr class="border-t border-gray-100 dark:border-gray-700">`), _tmpl$1 = /* @__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
+ }
11
187
  let ChartJS = null;
12
188
  let chartJSLoadPromise = null;
13
189
  const loadChartJS = async () => {
@@ -98,8 +274,18 @@ const ChartJSRenderer = (props) => {
98
274
  const [zoomPlugin, setZoomPlugin] = createSignal(null);
99
275
  const [isZoomed, setIsZoomed] = createSignal(false);
100
276
  let canvasRef;
277
+ let themeRoot;
101
278
  let chartInstance;
279
+ let chartTheme;
102
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
+ });
103
289
  const params = () => props.component.params;
104
290
  const telemetry = useTelemetry();
105
291
  const config = useMCPUIConfig();
@@ -108,9 +294,33 @@ const ChartJSRenderer = (props) => {
108
294
  series: strings.chartTableSeries,
109
295
  point: strings.chartTablePoint,
110
296
  label: strings.degradedColLabel,
111
- seriesName: strings.degradedSeries
297
+ seriesName: strings.degradedSeries,
298
+ withUnit: strings.chartLabelWithUnit
112
299
  }));
300
+ const missingSummary = createMemo(() => summarizeChartMissing(params()));
301
+ const unit = () => {
302
+ const value = params().unit;
303
+ return typeof value === "string" && value !== "" ? value : void 0;
304
+ };
305
+ const anyMissingCell = () => tableData().missing.some((row) => row.some(Boolean));
306
+ const notesShown = () => missingSummary().hasMissing && !PART_TO_WHOLE_CHART_TYPES.has(params().type) && activeView() === "chart" && !error();
307
+ const noteKind = () => missingNoteKind(params().type, params().options);
308
+ const conventionNoteShown = () => noteKind() === "bars" ? missingSummary().hasMissing : missingSummary().partiallyMissing.some(Boolean);
309
+ const noDataSeries = () => {
310
+ var _a;
311
+ const names = (((_a = params().data) == null ? void 0 : _a.datasets) ?? []).map((dataset, index) => missingSummary().fullyMissing[index] ? (dataset == null ? void 0 : dataset.label) || formatMCPUIString(strings.degradedSeries, {
312
+ n: index + 1
313
+ }) : null).filter((name) => name !== null);
314
+ try {
315
+ return new Intl.ListFormat(strings.locale, {
316
+ type: "conjunction"
317
+ }).format(names);
318
+ } catch {
319
+ return names.join(", ");
320
+ }
321
+ };
113
322
  const descriptionId = createUniqueId();
323
+ const notesId = createUniqueId();
114
324
  const title = () => params().title || strings.chartView;
115
325
  const exportEnabled = () => params().exportable !== false;
116
326
  const copyDataJSON = () => JSON.stringify({
@@ -180,9 +390,11 @@ const ChartJSRenderer = (props) => {
180
390
  a.click();
181
391
  };
182
392
  createEffect(async () => {
183
- var _a, _b, _c, _d, _e, _f, _g, _h;
393
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p;
184
394
  if (!canvasRef) return;
185
395
  const chartParams = params();
396
+ const chartMissing = missingSummary();
397
+ const chartUnit = unit();
186
398
  const zoom = zoomOptions();
187
399
  const version = ++renderVersion;
188
400
  setIsLoading(true);
@@ -194,6 +406,9 @@ const ChartJSRenderer = (props) => {
194
406
  chartInstance.destroy();
195
407
  chartInstance = null;
196
408
  }
409
+ if (chartMissing.hasMissing && PART_TO_WHOLE_CHART_TYPES.has(chartParams.type)) {
410
+ throw new Error(strings.chartMissingUnsupported);
411
+ }
197
412
  const hostZoomOptions = (_b = (_a = chartParams.options) == null ? void 0 : _a.plugins) == null ? void 0 : _b.zoom;
198
413
  const baseOptions = {
199
414
  responsive: true,
@@ -239,11 +454,71 @@ const ChartJSRenderer = (props) => {
239
454
  }
240
455
  };
241
456
  }
242
- chartInstance = new Chart(canvasRef, {
457
+ applyUnitAxisTitle(baseOptions, chartParams.type, chartUnit);
458
+ const chartConfig = {
243
459
  type: chartParams.type,
244
- 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
+ },
245
469
  options: baseOptions
246
- });
470
+ };
471
+ if (chartUnit !== void 0 || chartMissing.hasMissing) {
472
+ const tooltip = baseOptions.plugins.tooltip;
473
+ if (tooltip !== false && tooltip !== null && !((_g = tooltip == null ? void 0 : tooltip.callbacks) == null ? void 0 : _g.label)) {
474
+ baseOptions.plugins.tooltip = {
475
+ ...tooltip,
476
+ callbacks: {
477
+ ...tooltip == null ? void 0 : tooltip.callbacks,
478
+ label: createTooltipLabel(() => strings, chartUnit, chartParams.type)
479
+ }
480
+ };
481
+ }
482
+ }
483
+ if (chartMissing.hasMissing) {
484
+ chartConfig.data = withDatasetsNoGapSpan(chartParams.data);
485
+ const defaultGenerate = ((_i = (_h = baseOptions.plugins.legend) == null ? void 0 : _h.labels) == null ? void 0 : _i.generateLabels) ?? ((_m = (_l = (_k = (_j = Chart == null ? void 0 : Chart.defaults) == null ? void 0 : _j.plugins) == null ? void 0 : _k.legend) == null ? void 0 : _l.labels) == null ? void 0 : _m.generateLabels);
486
+ if (typeof defaultGenerate === "function") {
487
+ baseOptions.plugins.legend = {
488
+ ...baseOptions.plugins.legend,
489
+ labels: {
490
+ ...(_n = baseOptions.plugins.legend) == null ? void 0 : _n.labels,
491
+ generateLabels: createMissingLegendGenerator(defaultGenerate, chartMissing.fullyMissing, () => strings)
492
+ }
493
+ };
494
+ }
495
+ chartConfig.plugins = [createMissingValuesPlugin({
496
+ allMissing: chartMissing.allMissing,
497
+ getNoDataText: () => strings.chartNoData,
498
+ getFontFamily: () => {
499
+ var _a2, _b2;
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"];
505
+ }
506
+ })];
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
+ }
521
+ chartInstance = new Chart(canvasRef, chartConfig);
247
522
  setIsZoomed(false);
248
523
  setIsLoading(false);
249
524
  } catch (err) {
@@ -254,11 +529,11 @@ const ChartJSRenderer = (props) => {
254
529
  telemetry == null ? void 0 : telemetry.dispatch({
255
530
  type: "render:error",
256
531
  errorMessage: error2.message,
257
- id: ((_g = props.component) == null ? void 0 : _g.id) ?? "",
532
+ id: ((_o = props.component) == null ? void 0 : _o.id) ?? "",
258
533
  componentType: "chart",
259
534
  ts: Date.now()
260
535
  });
261
- (_h = props.onError) == null ? void 0 : _h.call(props, error2);
536
+ (_p = props.onError) == null ? void 0 : _p.call(props, error2);
262
537
  }
263
538
  });
264
539
  createEffect(() => {
@@ -292,7 +567,9 @@ const ChartJSRenderer = (props) => {
292
567
  get children() {
293
568
  return createComponent(ContextAwareChartLayout, {
294
569
  render: (isExpanded2) => (() => {
295
- var _el$ = getNextElement(_tmpl$8), _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$49 = _el$18.nextSibling, [_el$50, _co$1] = getNextMarker(_el$49.nextSibling), _el$51 = _el$50.nextSibling, [_el$52, _co$10] = getNextMarker(_el$51.nextSibling), _el$41 = _el$52.nextSibling, _el$42 = _el$41.firstChild, _el$47 = _el$42.nextSibling, [_el$48, _co$0] = getNextMarker(_el$47.nextSibling);
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$;
296
573
  insert(_el$3, createComponent(Show, {
297
574
  get when() {
298
575
  return params().title;
@@ -393,73 +670,94 @@ const ChartJSRenderer = (props) => {
393
670
  }
394
671
  }, tableData));
395
672
  }
396
- }), _el$50, _co$1);
673
+ }), _el$57, _co$11);
397
674
  insert(_el$, createComponent(Show, {
398
675
  get when() {
399
676
  return activeView() === "data";
400
677
  },
401
678
  get children() {
402
- var _el$24 = getNextElement(_tmpl$6), _el$25 = _el$24.firstChild, _el$26 = _el$25.firstChild, _el$28 = _el$26.firstChild, [_el$29, _co$6] = getNextMarker(_el$28.nextSibling), _el$27 = _el$29.nextSibling, _el$30 = _el$27.nextSibling, [_el$31, _co$7] = getNextMarker(_el$30.nextSibling), _el$32 = _el$26.nextSibling, _el$33 = _el$32.firstChild, _el$34 = _el$32.nextSibling, _el$37 = _el$34.firstChild, [_el$38, _co$8] = getNextMarker(_el$37.nextSibling), _el$39 = _el$38.nextSibling, [_el$40, _co$9] = getNextMarker(_el$39.nextSibling);
403
- insert(_el$26, title, _el$29, _co$6);
404
- insert(_el$26, () => strings.chartDataTable, _el$31, _co$7);
405
- insert(_el$33, createComponent(For, {
406
- get each() {
407
- return tableData().columns;
408
- },
409
- children: (column) => (() => {
410
- var _el$53 = getNextElement(_tmpl$9);
411
- insert(_el$53, column);
412
- return _el$53;
413
- })()
414
- }));
415
- insert(_el$34, createComponent(For, {
416
- get each() {
417
- return tableData().rows;
418
- },
419
- children: (row) => (() => {
420
- var _el$54 = getNextElement(_tmpl$0);
421
- insert(_el$54, createComponent(For, {
422
- get each() {
423
- return tableData().columns;
424
- },
425
- children: (_column, index) => (() => {
426
- var _el$55 = getNextElement(_tmpl$1);
427
- insert(_el$55, () => String(row[index()] ?? ""));
428
- return _el$55;
429
- })()
430
- }));
431
- return _el$54;
432
- })()
433
- }), _el$38, _co$8);
434
- insert(_el$34, createComponent(Show, {
679
+ return [(() => {
680
+ var _el$24 = getNextElement(_tmpl$6), _el$25 = _el$24.firstChild, _el$26 = _el$25.firstChild, _el$28 = _el$26.firstChild, [_el$29, _co$6] = getNextMarker(_el$28.nextSibling), _el$27 = _el$29.nextSibling, _el$30 = _el$27.nextSibling, [_el$31, _co$7] = getNextMarker(_el$30.nextSibling), _el$32 = _el$26.nextSibling, _el$33 = _el$32.firstChild, _el$34 = _el$32.nextSibling, _el$37 = _el$34.firstChild, [_el$38, _co$8] = getNextMarker(_el$37.nextSibling), _el$39 = _el$38.nextSibling, [_el$40, _co$9] = getNextMarker(_el$39.nextSibling);
681
+ insert(_el$26, title, _el$29, _co$6);
682
+ insert(_el$26, () => strings.chartDataTable, _el$31, _co$7);
683
+ insert(_el$33, createComponent(For, {
684
+ get each() {
685
+ return tableData().columns;
686
+ },
687
+ children: (column) => (() => {
688
+ var _el$62 = getNextElement(_tmpl$10);
689
+ insert(_el$62, column);
690
+ return _el$62;
691
+ })()
692
+ }));
693
+ insert(_el$34, createComponent(For, {
694
+ get each() {
695
+ return tableData().rows;
696
+ },
697
+ children: (row, rowIndex) => (() => {
698
+ var _el$63 = getNextElement(_tmpl$11);
699
+ insert(_el$63, createComponent(For, {
700
+ get each() {
701
+ return tableData().columns;
702
+ },
703
+ children: (_column, index) => (() => {
704
+ var _el$64 = getNextElement(_tmpl$12);
705
+ insert(_el$64, createComponent(Show, {
706
+ get when() {
707
+ var _a;
708
+ return (_a = tableData().missing[rowIndex()]) == null ? void 0 : _a[index()];
709
+ },
710
+ get fallback() {
711
+ return String(row[index()] ?? "");
712
+ },
713
+ get children() {
714
+ return createComponent(MissingValueMark, {});
715
+ }
716
+ }));
717
+ return _el$64;
718
+ })()
719
+ }));
720
+ return _el$63;
721
+ })()
722
+ }), _el$38, _co$8);
723
+ insert(_el$34, createComponent(Show, {
724
+ get when() {
725
+ return tableData().rows.length === 0;
726
+ },
727
+ get children() {
728
+ var _el$35 = getNextElement(_tmpl$5), _el$36 = _el$35.firstChild;
729
+ insert(_el$36, () => strings.chartNoData);
730
+ effect(() => setAttribute(_el$36, "colspan", Math.max(1, tableData().columns.length)));
731
+ return _el$35;
732
+ }
733
+ }), _el$40, _co$9);
734
+ effect((_p$) => {
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 : {
736
+ height: params().height || "250px",
737
+ "max-height": "70vh"
738
+ };
739
+ _v$0 !== _p$.e && className(_el$24, _p$.e = _v$0);
740
+ _p$.t = style(_el$24, _v$1, _p$.t);
741
+ return _p$;
742
+ }, {
743
+ e: void 0,
744
+ t: void 0
745
+ });
746
+ return _el$24;
747
+ })(), createComponent(Show, {
435
748
  get when() {
436
- return tableData().rows.length === 0;
749
+ return anyMissingCell();
437
750
  },
438
751
  get children() {
439
- var _el$35 = getNextElement(_tmpl$5), _el$36 = _el$35.firstChild;
440
- insert(_el$36, () => strings.chartNoData);
441
- effect(() => setAttribute(_el$36, "colspan", Math.max(1, tableData().columns.length)));
442
- return _el$35;
752
+ return createComponent(MissingValueLegend, {
753
+ "class": "mt-2"
754
+ });
443
755
  }
444
- }), _el$40, _co$9);
445
- effect((_p$) => {
446
- 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 : {
447
- height: params().height || "250px",
448
- "max-height": "70vh"
449
- };
450
- _v$0 !== _p$.e && className(_el$24, _p$.e = _v$0);
451
- _p$.t = style(_el$24, _v$1, _p$.t);
452
- return _p$;
453
- }, {
454
- e: void 0,
455
- t: void 0
456
- });
457
- return _el$24;
756
+ })];
458
757
  }
459
- }), _el$52, _co$10);
460
- var _ref$ = canvasRef;
461
- typeof _ref$ === "function" ? use(_ref$, _el$42) : canvasRef = _el$42;
462
- setAttribute(_el$42, "aria-describedby", descriptionId);
758
+ }), _el$59, _co$12);
759
+ var _ref$2 = canvasRef;
760
+ typeof _ref$2 === "function" ? use(_ref$2, _el$42) : canvasRef = _el$42;
463
761
  insert(_el$41, createComponent(Show, {
464
762
  get when() {
465
763
  return memo(() => !!isLoading())() && activeView() === "chart";
@@ -470,8 +768,44 @@ const ChartJSRenderer = (props) => {
470
768
  return _el$43;
471
769
  }
472
770
  }), _el$48, _co$0);
771
+ insert(_el$, createComponent(Show, {
772
+ get when() {
773
+ return notesShown();
774
+ },
775
+ get children() {
776
+ var _el$49 = getNextElement(_tmpl$0), _el$52 = _el$49.firstChild, [_el$53, _co$1] = getNextMarker(_el$52.nextSibling), _el$54 = _el$53.nextSibling, [_el$55, _co$10] = getNextMarker(_el$54.nextSibling);
777
+ setAttribute(_el$49, "id", notesId);
778
+ insert(_el$49, createComponent(Show, {
779
+ get when() {
780
+ return conventionNoteShown();
781
+ },
782
+ get children() {
783
+ var _el$50 = getNextElement(_tmpl$8);
784
+ insert(_el$50, (() => {
785
+ var _c$ = memo(() => noteKind() === "bars");
786
+ return () => _c$() ? strings.chartMissingBars : memo(() => noteKind() === "omitted")() ? strings.chartMissingPoints : strings.chartMissingGaps;
787
+ })());
788
+ effect(() => setAttribute(_el$50, "data-mcp-chart-note", noteKind()));
789
+ return _el$50;
790
+ }
791
+ }), _el$53, _co$1);
792
+ insert(_el$49, createComponent(Show, {
793
+ get when() {
794
+ return missingSummary().fullyMissing.some(Boolean);
795
+ },
796
+ get children() {
797
+ var _el$51 = getNextElement(_tmpl$9);
798
+ insert(_el$51, () => formatMCPUIString(strings.chartSeriesNoData, {
799
+ series: noDataSeries()
800
+ }));
801
+ return _el$51;
802
+ }
803
+ }), _el$55, _co$10);
804
+ return _el$49;
805
+ }
806
+ }), _el$61, _co$13);
473
807
  effect((_p$) => {
474
- 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" ? {
475
809
  display: "none"
476
810
  } : isExpanded2() ? {
477
811
  height: "100%",
@@ -479,7 +813,7 @@ const ChartJSRenderer = (props) => {
479
813
  } : {
480
814
  height: params().height || "250px",
481
815
  display: "block"
482
- }, _v$18 = title(), _v$19 = activeView() !== "chart" || Boolean(error());
816
+ }, _v$18 = title(), _v$19 = notesShown() ? `${descriptionId} ${notesId}` : descriptionId, _v$20 = activeView() !== "chart" || Boolean(error());
483
817
  _v$10 !== _p$.e && className(_el$, _p$.e = _v$10);
484
818
  _v$11 !== _p$.t && setAttribute(_el$6, "aria-label", _p$.t = _v$11);
485
819
  _v$12 !== _p$.a && setAttribute(_el$7, "aria-pressed", _p$.a = _v$12);
@@ -489,7 +823,8 @@ const ChartJSRenderer = (props) => {
489
823
  _v$16 !== _p$.s && className(_el$41, _p$.s = _v$16);
490
824
  _p$.h = style(_el$41, _v$17, _p$.h);
491
825
  _v$18 !== _p$.r && setAttribute(_el$42, "aria-label", _p$.r = _v$18);
492
- _v$19 !== _p$.d && setAttribute(_el$42, "aria-hidden", _p$.d = _v$19);
826
+ _v$19 !== _p$.d && setAttribute(_el$42, "aria-describedby", _p$.d = _v$19);
827
+ _v$20 !== _p$.l && setAttribute(_el$42, "aria-hidden", _p$.l = _v$20);
493
828
  return _p$;
494
829
  }, {
495
830
  e: void 0,
@@ -501,7 +836,8 @@ const ChartJSRenderer = (props) => {
501
836
  s: void 0,
502
837
  h: void 0,
503
838
  r: void 0,
504
- d: void 0
839
+ d: void 0,
840
+ l: void 0
505
841
  });
506
842
  runHydrationEvents();
507
843
  return _el$;