@seed-ship/mcp-ui-solid 6.19.1 → 6.21.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 (282) hide show
  1. package/CHANGELOG.md +663 -0
  2. package/README.md +911 -4
  3. package/dist/adapters/connector.cjs +15 -4
  4. package/dist/adapters/connector.cjs.map +1 -1
  5. package/dist/adapters/connector.d.ts +38 -0
  6. package/dist/adapters/connector.d.ts.map +1 -1
  7. package/dist/adapters/connector.js +15 -4
  8. package/dist/adapters/connector.js.map +1 -1
  9. package/dist/adapters/index.d.ts +4 -3
  10. package/dist/adapters/index.d.ts.map +1 -1
  11. package/dist/adapters/macro-run.cjs +25 -13
  12. package/dist/adapters/macro-run.cjs.map +1 -1
  13. package/dist/adapters/macro-run.d.ts +37 -2
  14. package/dist/adapters/macro-run.d.ts.map +1 -1
  15. package/dist/adapters/macro-run.js +25 -13
  16. package/dist/adapters/macro-run.js.map +1 -1
  17. package/dist/adapters.cjs +2 -0
  18. package/dist/adapters.cjs.map +1 -1
  19. package/dist/adapters.js +4 -2
  20. package/dist/components/ActionGroupRenderer.cjs +3 -1
  21. package/dist/components/ActionGroupRenderer.cjs.map +1 -1
  22. package/dist/components/ActionGroupRenderer.d.ts.map +1 -1
  23. package/dist/components/ActionGroupRenderer.js +3 -1
  24. package/dist/components/ActionGroupRenderer.js.map +1 -1
  25. package/dist/components/AgentCard.cjs +11 -8
  26. package/dist/components/AgentCard.cjs.map +1 -1
  27. package/dist/components/AgentCard.d.ts.map +1 -1
  28. package/dist/components/AgentCard.js +11 -8
  29. package/dist/components/AgentCard.js.map +1 -1
  30. package/dist/components/AgentHandoff.cjs +6 -1
  31. package/dist/components/AgentHandoff.cjs.map +1 -1
  32. package/dist/components/AgentHandoff.d.ts.map +1 -1
  33. package/dist/components/AgentHandoff.js +6 -1
  34. package/dist/components/AgentHandoff.js.map +1 -1
  35. package/dist/components/ArtifactRenderer.cjs +25 -6
  36. package/dist/components/ArtifactRenderer.cjs.map +1 -1
  37. package/dist/components/ArtifactRenderer.d.ts.map +1 -1
  38. package/dist/components/ArtifactRenderer.js +25 -6
  39. package/dist/components/ArtifactRenderer.js.map +1 -1
  40. package/dist/components/AutocompleteDropdown.cjs +30 -24
  41. package/dist/components/AutocompleteDropdown.cjs.map +1 -1
  42. package/dist/components/AutocompleteDropdown.d.ts.map +1 -1
  43. package/dist/components/AutocompleteDropdown.js +30 -24
  44. package/dist/components/AutocompleteDropdown.js.map +1 -1
  45. package/dist/components/AutocompleteFormField.cjs +3 -1
  46. package/dist/components/AutocompleteFormField.cjs.map +1 -1
  47. package/dist/components/AutocompleteFormField.d.ts.map +1 -1
  48. package/dist/components/AutocompleteFormField.js +4 -2
  49. package/dist/components/AutocompleteFormField.js.map +1 -1
  50. package/dist/components/BriefingDiff.cjs +45 -39
  51. package/dist/components/BriefingDiff.cjs.map +1 -1
  52. package/dist/components/BriefingDiff.d.ts.map +1 -1
  53. package/dist/components/BriefingDiff.js +45 -39
  54. package/dist/components/BriefingDiff.js.map +1 -1
  55. package/dist/components/CarouselRenderer.cjs +8 -2
  56. package/dist/components/CarouselRenderer.cjs.map +1 -1
  57. package/dist/components/CarouselRenderer.d.ts.map +1 -1
  58. package/dist/components/CarouselRenderer.js +8 -2
  59. package/dist/components/CarouselRenderer.js.map +1 -1
  60. package/dist/components/ChartJSRenderer.cjs +60 -36
  61. package/dist/components/ChartJSRenderer.cjs.map +1 -1
  62. package/dist/components/ChartJSRenderer.d.ts.map +1 -1
  63. package/dist/components/ChartJSRenderer.js +61 -37
  64. package/dist/components/ChartJSRenderer.js.map +1 -1
  65. package/dist/components/ChatPrompt.cjs +15 -9
  66. package/dist/components/ChatPrompt.cjs.map +1 -1
  67. package/dist/components/ChatPrompt.d.ts.map +1 -1
  68. package/dist/components/ChatPrompt.js +15 -9
  69. package/dist/components/ChatPrompt.js.map +1 -1
  70. package/dist/components/CodeBlockRenderer.cjs +34 -16
  71. package/dist/components/CodeBlockRenderer.cjs.map +1 -1
  72. package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
  73. package/dist/components/CodeBlockRenderer.js +34 -16
  74. package/dist/components/CodeBlockRenderer.js.map +1 -1
  75. package/dist/components/DataPreviewSection.cjs +91 -44
  76. package/dist/components/DataPreviewSection.cjs.map +1 -1
  77. package/dist/components/DataPreviewSection.d.ts.map +1 -1
  78. package/dist/components/DataPreviewSection.js +92 -45
  79. package/dist/components/DataPreviewSection.js.map +1 -1
  80. package/dist/components/DegradedFallback.cjs +20 -16
  81. package/dist/components/DegradedFallback.cjs.map +1 -1
  82. package/dist/components/DegradedFallback.d.ts.map +1 -1
  83. package/dist/components/DegradedFallback.js +20 -16
  84. package/dist/components/DegradedFallback.js.map +1 -1
  85. package/dist/components/FooterRenderer.cjs +21 -17
  86. package/dist/components/FooterRenderer.cjs.map +1 -1
  87. package/dist/components/FooterRenderer.d.ts.map +1 -1
  88. package/dist/components/FooterRenderer.js +21 -17
  89. package/dist/components/FooterRenderer.js.map +1 -1
  90. package/dist/components/FormFieldRenderer.cjs +116 -93
  91. package/dist/components/FormFieldRenderer.cjs.map +1 -1
  92. package/dist/components/FormFieldRenderer.d.ts.map +1 -1
  93. package/dist/components/FormFieldRenderer.js +116 -93
  94. package/dist/components/FormFieldRenderer.js.map +1 -1
  95. package/dist/components/FormRenderer.cjs +55 -31
  96. package/dist/components/FormRenderer.cjs.map +1 -1
  97. package/dist/components/FormRenderer.d.ts.map +1 -1
  98. package/dist/components/FormRenderer.js +55 -31
  99. package/dist/components/FormRenderer.js.map +1 -1
  100. package/dist/components/GenerativeUIErrorBoundary.cjs +20 -15
  101. package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
  102. package/dist/components/GenerativeUIErrorBoundary.d.ts.map +1 -1
  103. package/dist/components/GenerativeUIErrorBoundary.js +20 -15
  104. package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
  105. package/dist/components/GraphRenderer.cjs +56 -33
  106. package/dist/components/GraphRenderer.cjs.map +1 -1
  107. package/dist/components/GraphRenderer.d.ts.map +1 -1
  108. package/dist/components/GraphRenderer.js +56 -33
  109. package/dist/components/GraphRenderer.js.map +1 -1
  110. package/dist/components/IframeFallbackLink.cjs +37 -0
  111. package/dist/components/IframeFallbackLink.cjs.map +1 -0
  112. package/dist/components/IframeFallbackLink.d.ts +23 -0
  113. package/dist/components/IframeFallbackLink.d.ts.map +1 -0
  114. package/dist/components/IframeFallbackLink.js +37 -0
  115. package/dist/components/IframeFallbackLink.js.map +1 -0
  116. package/dist/components/ImageGalleryRenderer.cjs +13 -4
  117. package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
  118. package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
  119. package/dist/components/ImageGalleryRenderer.js +13 -4
  120. package/dist/components/ImageGalleryRenderer.js.map +1 -1
  121. package/dist/components/LightboxOverlay.cjs +16 -8
  122. package/dist/components/LightboxOverlay.cjs.map +1 -1
  123. package/dist/components/LightboxOverlay.d.ts.map +1 -1
  124. package/dist/components/LightboxOverlay.js +17 -9
  125. package/dist/components/LightboxOverlay.js.map +1 -1
  126. package/dist/components/MapRenderer.cjs +59 -29
  127. package/dist/components/MapRenderer.cjs.map +1 -1
  128. package/dist/components/MapRenderer.d.ts +10 -2
  129. package/dist/components/MapRenderer.d.ts.map +1 -1
  130. package/dist/components/MapRenderer.js +60 -30
  131. package/dist/components/MapRenderer.js.map +1 -1
  132. package/dist/components/ModalRenderer.cjs +4 -1
  133. package/dist/components/ModalRenderer.cjs.map +1 -1
  134. package/dist/components/ModalRenderer.d.ts.map +1 -1
  135. package/dist/components/ModalRenderer.js +5 -2
  136. package/dist/components/ModalRenderer.js.map +1 -1
  137. package/dist/components/ScratchpadPanel.cjs +578 -535
  138. package/dist/components/ScratchpadPanel.cjs.map +1 -1
  139. package/dist/components/ScratchpadPanel.d.ts.map +1 -1
  140. package/dist/components/ScratchpadPanel.js +578 -535
  141. package/dist/components/ScratchpadPanel.js.map +1 -1
  142. package/dist/components/StreamingUIRenderer.cjs +92 -28
  143. package/dist/components/StreamingUIRenderer.cjs.map +1 -1
  144. package/dist/components/StreamingUIRenderer.d.ts.map +1 -1
  145. package/dist/components/StreamingUIRenderer.js +92 -28
  146. package/dist/components/StreamingUIRenderer.js.map +1 -1
  147. package/dist/components/UIResourceRenderer.cjs +481 -365
  148. package/dist/components/UIResourceRenderer.cjs.map +1 -1
  149. package/dist/components/UIResourceRenderer.d.ts +21 -0
  150. package/dist/components/UIResourceRenderer.d.ts.map +1 -1
  151. package/dist/components/UIResourceRenderer.js +484 -368
  152. package/dist/components/UIResourceRenderer.js.map +1 -1
  153. package/dist/components/VerifiedText.cjs +39 -20
  154. package/dist/components/VerifiedText.cjs.map +1 -1
  155. package/dist/components/VerifiedText.d.ts +2 -1
  156. package/dist/components/VerifiedText.d.ts.map +1 -1
  157. package/dist/components/VerifiedText.js +39 -20
  158. package/dist/components/VerifiedText.js.map +1 -1
  159. package/dist/components/VideoRenderer.cjs +51 -20
  160. package/dist/components/VideoRenderer.cjs.map +1 -1
  161. package/dist/components/VideoRenderer.d.ts.map +1 -1
  162. package/dist/components/VideoRenderer.js +51 -20
  163. package/dist/components/VideoRenderer.js.map +1 -1
  164. package/dist/components/chart-data-table.cjs +38 -17
  165. package/dist/components/chart-data-table.cjs.map +1 -1
  166. package/dist/components/chart-data-table.d.ts +30 -1
  167. package/dist/components/chart-data-table.d.ts.map +1 -1
  168. package/dist/components/chart-data-table.js +38 -17
  169. package/dist/components/chart-data-table.js.map +1 -1
  170. package/dist/context/MCPActionContext.cjs +3 -1
  171. package/dist/context/MCPActionContext.cjs.map +1 -1
  172. package/dist/context/MCPActionContext.d.ts.map +1 -1
  173. package/dist/context/MCPActionContext.js +3 -1
  174. package/dist/context/MCPActionContext.js.map +1 -1
  175. package/dist/context/MCPUIConfigContext.cjs +29 -0
  176. package/dist/context/MCPUIConfigContext.cjs.map +1 -0
  177. package/dist/context/MCPUIConfigContext.d.ts +124 -0
  178. package/dist/context/MCPUIConfigContext.d.ts.map +1 -0
  179. package/dist/context/MCPUIConfigContext.js +29 -0
  180. package/dist/context/MCPUIConfigContext.js.map +1 -0
  181. package/dist/context/MCPUIStringsContext.cjs +287 -2
  182. package/dist/context/MCPUIStringsContext.cjs.map +1 -1
  183. package/dist/context/MCPUIStringsContext.d.ts +607 -3
  184. package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
  185. package/dist/context/MCPUIStringsContext.js +287 -2
  186. package/dist/context/MCPUIStringsContext.js.map +1 -1
  187. package/dist/hooks/index.d.ts +2 -2
  188. package/dist/hooks/index.d.ts.map +1 -1
  189. package/dist/hooks/useStreamingUI.cjs +28 -10
  190. package/dist/hooks/useStreamingUI.cjs.map +1 -1
  191. package/dist/hooks/useStreamingUI.d.ts +37 -0
  192. package/dist/hooks/useStreamingUI.d.ts.map +1 -1
  193. package/dist/hooks/useStreamingUI.js +28 -10
  194. package/dist/hooks/useStreamingUI.js.map +1 -1
  195. package/dist/hooks.cjs +1 -0
  196. package/dist/hooks.cjs.map +1 -1
  197. package/dist/hooks.js +2 -1
  198. package/dist/index.cjs +29 -8
  199. package/dist/index.cjs.map +1 -1
  200. package/dist/index.d.cts +12 -4
  201. package/dist/index.d.ts +12 -4
  202. package/dist/index.d.ts.map +1 -1
  203. package/dist/index.js +24 -3
  204. package/dist/index.js.map +1 -1
  205. package/dist/services/index.d.ts +1 -1
  206. package/dist/services/index.d.ts.map +1 -1
  207. package/dist/services/validation.cjs +52 -26
  208. package/dist/services/validation.cjs.map +1 -1
  209. package/dist/services/validation.d.ts +67 -2
  210. package/dist/services/validation.d.ts.map +1 -1
  211. package/dist/services/validation.js +52 -26
  212. package/dist/services/validation.js.map +1 -1
  213. package/dist/utils/degraded-projections.cjs +37 -12
  214. package/dist/utils/degraded-projections.cjs.map +1 -1
  215. package/dist/utils/degraded-projections.d.ts +39 -3
  216. package/dist/utils/degraded-projections.d.ts.map +1 -1
  217. package/dist/utils/degraded-projections.js +37 -12
  218. package/dist/utils/degraded-projections.js.map +1 -1
  219. package/dist/utils/format-string.cjs +10 -0
  220. package/dist/utils/format-string.cjs.map +1 -0
  221. package/dist/utils/format-string.d.ts +26 -0
  222. package/dist/utils/format-string.d.ts.map +1 -0
  223. package/dist/utils/format-string.js +10 -0
  224. package/dist/utils/format-string.js.map +1 -0
  225. package/dist/utils/iframe-coep.cjs +30 -0
  226. package/dist/utils/iframe-coep.cjs.map +1 -0
  227. package/dist/utils/iframe-coep.d.ts +46 -0
  228. package/dist/utils/iframe-coep.d.ts.map +1 -0
  229. package/dist/utils/iframe-coep.js +30 -0
  230. package/dist/utils/iframe-coep.js.map +1 -0
  231. package/dist/validation.cjs +5 -0
  232. package/dist/validation.cjs.map +1 -1
  233. package/dist/validation.d.cts +2 -1
  234. package/dist/validation.d.ts +2 -1
  235. package/dist/validation.d.ts.map +1 -1
  236. package/dist/validation.js +6 -1
  237. package/package.json +1 -1
  238. package/src/adapters/connector.ts +58 -4
  239. package/src/adapters/index.ts +12 -2
  240. package/src/adapters/macro-run.ts +71 -11
  241. package/src/components/ActionGroupRenderer.tsx +3 -1
  242. package/src/components/AgentCard.tsx +27 -9
  243. package/src/components/AgentHandoff.tsx +4 -1
  244. package/src/components/ArtifactRenderer.tsx +17 -5
  245. package/src/components/AutocompleteDropdown.tsx +8 -6
  246. package/src/components/AutocompleteFormField.tsx +5 -1
  247. package/src/components/BriefingDiff.tsx +11 -3
  248. package/src/components/CarouselRenderer.tsx +4 -2
  249. package/src/components/ChartJSRenderer.tsx +18 -9
  250. package/src/components/ChatPrompt.tsx +13 -8
  251. package/src/components/CodeBlockRenderer.tsx +12 -10
  252. package/src/components/DataPreviewSection.tsx +92 -26
  253. package/src/components/DegradedFallback.tsx +4 -2
  254. package/src/components/FooterRenderer.tsx +3 -1
  255. package/src/components/FormFieldRenderer.tsx +34 -19
  256. package/src/components/FormRenderer.tsx +38 -10
  257. package/src/components/GenerativeUIErrorBoundary.tsx +8 -3
  258. package/src/components/GraphRenderer.tsx +31 -16
  259. package/src/components/IframeFallbackLink.tsx +57 -0
  260. package/src/components/ImageGalleryRenderer.tsx +8 -4
  261. package/src/components/LightboxOverlay.tsx +6 -4
  262. package/src/components/MapRenderer.tsx +57 -20
  263. package/src/components/ModalRenderer.tsx +3 -1
  264. package/src/components/ScratchpadPanel.tsx +95 -44
  265. package/src/components/StreamingUIRenderer.tsx +41 -11
  266. package/src/components/UIResourceRenderer.tsx +176 -67
  267. package/src/components/VerifiedText.tsx +19 -9
  268. package/src/components/VideoRenderer.tsx +26 -4
  269. package/src/components/chart-data-table.ts +68 -14
  270. package/src/context/MCPActionContext.tsx +4 -1
  271. package/src/context/MCPUIConfigContext.tsx +151 -0
  272. package/src/context/MCPUIStringsContext.tsx +1014 -1
  273. package/src/hooks/index.ts +2 -1
  274. package/src/hooks/useStreamingUI.ts +64 -10
  275. package/src/index.ts +38 -0
  276. package/src/services/index.ts +1 -0
  277. package/src/services/validation.ts +131 -32
  278. package/src/solid-jsx-attrs.d.ts +24 -0
  279. package/src/utils/degraded-projections.ts +75 -12
  280. package/src/utils/format-string.ts +33 -0
  281. package/src/utils/iframe-coep.ts +74 -0
  282. package/src/validation.ts +9 -0
@@ -1 +1 @@
1
- {"version":3,"file":"VideoRenderer.cjs","sources":["../../src/components/VideoRenderer.tsx"],"sourcesContent":["/**\n * VideoRenderer - Video embed component\n * Sprint 5: Media Components\n *\n * Supports YouTube, Vimeo, and direct video files\n */\n\nimport { Component, createMemo, Show } from 'solid-js'\nimport type { UIComponent, VideoComponentParams } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\n\nexport interface VideoRendererProps {\n /**\n * UIComponent containing video params\n */\n component?: UIComponent\n\n /**\n * Direct video params (alternative to component)\n */\n params?: VideoComponentParams\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible'\n}\n\n/**\n * Video provider type\n */\ntype VideoProvider = 'youtube' | 'vimeo' | 'direct'\n\n/**\n * Parsed video info\n */\ninterface VideoInfo {\n provider: VideoProvider\n videoId?: string\n}\n\n/**\n * Extract video ID and provider from URL\n */\nfunction parseVideoUrl(url: string): VideoInfo {\n // YouTube patterns:\n // - youtube.com/watch?v=VIDEO_ID\n // - youtube.com/embed/VIDEO_ID\n // - youtube.com/v/VIDEO_ID\n // - youtu.be/VIDEO_ID\n const youtubeMatch = url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/\n )\n if (youtubeMatch) {\n return { provider: 'youtube', videoId: youtubeMatch[1] }\n }\n\n // Vimeo patterns:\n // - vimeo.com/VIDEO_ID\n // - player.vimeo.com/video/VIDEO_ID\n const vimeoMatch = url.match(/(?:vimeo\\.com\\/|player\\.vimeo\\.com\\/video\\/)(\\d+)/)\n if (vimeoMatch) {\n return { provider: 'vimeo', videoId: vimeoMatch[1] }\n }\n\n // Direct video file\n return { provider: 'direct' }\n}\n\nexport const VideoRenderer: Component<VideoRendererProps> = (props) => {\n const params = () => props.params || (props.component?.params as VideoComponentParams)\n const isExpanded = useExpanded()\n\n const videoInfo = createMemo(() => parseVideoUrl(params()?.url || ''))\n\n const embedUrl = createMemo(() => {\n const info = videoInfo()\n const p = params()\n\n if (!p?.url) return null\n\n switch (info.provider) {\n case 'youtube': {\n const ytParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n controls: p.controls !== false ? '1' : '0',\n loop: p.loop ? '1' : '0',\n mute: p.muted ? '1' : '0',\n })\n if (p.startTime) {\n ytParams.set('start', String(p.startTime))\n }\n // Use youtube-nocookie.com for privacy\n return `https://www.youtube-nocookie.com/embed/${info.videoId}?${ytParams}`\n }\n\n case 'vimeo': {\n const vParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n loop: p.loop ? '1' : '0',\n muted: p.muted ? '1' : '0',\n })\n return `https://player.vimeo.com/video/${info.videoId}?${vParams}`\n }\n\n default:\n return null\n }\n })\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '4:3':\n return 'aspect-[4/3]'\n case '21:9':\n return 'aspect-[21/9]'\n default:\n return 'aspect-video' // 16:9\n }\n }\n\n const handleVideoError = (e: Event) => {\n const error = new Error('Video failed to load')\n console.error('Video error:', e)\n props.onError?.(error)\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || 'Video'}\n copyData={params()?.url || ''}\n copyLabel=\"Copy video URL\"\n toolbarVariant={props.toolbarVariant}\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Video Container — when expanded, fill remaining space (override aspect ratio) */}\n <div class={`relative bg-black ${isExpanded() ? 'flex-1 min-h-0' : aspectClass()}`}>\n <Show\n when={embedUrl()}\n fallback={\n // Direct video file\n <video\n src={params()?.url}\n poster={params()?.poster}\n autoplay={params()?.autoplay}\n controls={params()?.controls !== false}\n loop={params()?.loop}\n muted={params()?.muted}\n playsinline\n class=\"absolute inset-0 w-full h-full object-contain\"\n onError={handleVideoError}\n >\n <track kind=\"captions\" />\n Your browser does not support the video tag.\n </video>\n }\n >\n {/* YouTube/Vimeo embed */}\n <iframe\n src={embedUrl()!}\n title={params()?.title || 'Video'}\n class=\"absolute inset-0 w-full h-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowfullscreen\n loading=\"lazy\"\n />\n </Show>\n </div>\n\n {/* Caption */}\n <Show when={params()?.caption}>\n <div class=\"px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400\">{params()!.caption}</p>\n </div>\n </Show>\n </div>\n </ExpandableWrapper>\n )\n}\n\n/**\n * Check if a URL is from a supported video provider\n */\nexport function isSupportedVideoUrl(url: string): boolean {\n const info = parseVideoUrl(url)\n return info.provider !== 'direct' || url.match(/\\.(mp4|webm|ogg|mov)$/i) !== null\n}\n\n/**\n * Get video provider from URL\n */\nexport function getVideoProvider(url: string): VideoProvider {\n return parseVideoUrl(url).provider\n}\n"],"names":["parseVideoUrl","url","youtubeMatch","match","provider","videoId","vimeoMatch","VideoRenderer","props","params","component","isExpanded","useExpanded","videoInfo","createMemo","embedUrl","info","p","ytParams","URLSearchParams","autoplay","controls","loop","mute","muted","startTime","set","String","vParams","aspectClass","aspectRatio","handleVideoError","e","error","Error","console","onError","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","fallback","_el$10","_tmpl$5","addEventListener","_$effect","_p$","_v$5","_v$6","poster","_v$7","_v$8","_v$9","_v$0","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","caption","_el$6","_tmpl$3","_el$7","_v$3","_v$4","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
1
+ {"version":3,"file":"VideoRenderer.cjs","sources":["../../src/components/VideoRenderer.tsx"],"sourcesContent":["/**\n * VideoRenderer - Video embed component\n * Sprint 5: Media Components\n *\n * Supports YouTube, Vimeo, and direct video files\n */\n\nimport { Component, createMemo, Show } from 'solid-js'\nimport type { UIComponent, VideoComponentParams } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\nimport { useMCPUIConfig } from '../context/MCPUIConfigContext'\nimport { shouldSetCredentialless } from '../utils/iframe-coep'\nimport { IframeFallbackLink } from './IframeFallbackLink'\n\nexport interface VideoRendererProps {\n /**\n * UIComponent containing video params\n */\n component?: UIComponent\n\n /**\n * Direct video params (alternative to component)\n */\n params?: VideoComponentParams\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible'\n}\n\n/**\n * Video provider type\n */\ntype VideoProvider = 'youtube' | 'vimeo' | 'direct'\n\n/**\n * Parsed video info\n */\ninterface VideoInfo {\n provider: VideoProvider\n videoId?: string\n}\n\n/**\n * Extract video ID and provider from URL\n */\nfunction parseVideoUrl(url: string): VideoInfo {\n // YouTube patterns:\n // - youtube.com/watch?v=VIDEO_ID\n // - youtube.com/embed/VIDEO_ID\n // - youtube.com/v/VIDEO_ID\n // - youtu.be/VIDEO_ID\n const youtubeMatch = url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/\n )\n if (youtubeMatch) {\n return { provider: 'youtube', videoId: youtubeMatch[1] }\n }\n\n // Vimeo patterns:\n // - vimeo.com/VIDEO_ID\n // - player.vimeo.com/video/VIDEO_ID\n const vimeoMatch = url.match(/(?:vimeo\\.com\\/|player\\.vimeo\\.com\\/video\\/)(\\d+)/)\n if (vimeoMatch) {\n return { provider: 'vimeo', videoId: vimeoMatch[1] }\n }\n\n // Direct video file\n return { provider: 'direct' }\n}\n\nexport const VideoRenderer: Component<VideoRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n const config = useMCPUIConfig()\n const params = () => props.params || (props.component?.params as VideoComponentParams)\n const isExpanded = useExpanded()\n\n const videoInfo = createMemo(() => parseVideoUrl(params()?.url || ''))\n\n const embedUrl = createMemo(() => {\n const info = videoInfo()\n const p = params()\n\n if (!p?.url) return null\n\n switch (info.provider) {\n case 'youtube': {\n const ytParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n controls: p.controls !== false ? '1' : '0',\n loop: p.loop ? '1' : '0',\n mute: p.muted ? '1' : '0',\n })\n if (p.startTime) {\n ytParams.set('start', String(p.startTime))\n }\n // Use youtube-nocookie.com for privacy\n return `https://www.youtube-nocookie.com/embed/${info.videoId}?${ytParams}`\n }\n\n case 'vimeo': {\n const vParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n loop: p.loop ? '1' : '0',\n muted: p.muted ? '1' : '0',\n })\n return `https://player.vimeo.com/video/${info.videoId}?${vParams}`\n }\n\n default:\n return null\n }\n })\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '4:3':\n return 'aspect-[4/3]'\n case '21:9':\n return 'aspect-[21/9]'\n default:\n return 'aspect-video' // 16:9\n }\n }\n\n const handleVideoError = (e: Event) => {\n const error = new Error('Video failed to load')\n console.error('Video error:', e)\n props.onError?.(error)\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || strings.videoTitle}\n copyData={params()?.url || ''}\n copyLabel={strings.videoCopy}\n toolbarVariant={props.toolbarVariant}\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Video Container — when expanded, fill remaining space (override aspect ratio) */}\n <div class={`relative bg-black ${isExpanded() ? 'flex-1 min-h-0' : aspectClass()}`}>\n <Show\n when={embedUrl()}\n fallback={\n // Direct video file\n <video\n src={params()?.url}\n poster={params()?.poster}\n autoplay={params()?.autoplay}\n controls={params()?.controls !== false}\n loop={params()?.loop}\n muted={params()?.muted}\n playsinline\n class=\"absolute inset-0 w-full h-full object-contain\"\n onError={handleVideoError}\n >\n <track kind=\"captions\" />\n {strings.videoUnsupported}\n </video>\n }\n >\n {/* YouTube/Vimeo embed */}\n <iframe\n src={embedUrl()!}\n title={params()?.title || strings.videoTitle}\n class=\"absolute inset-0 w-full h-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowfullscreen\n // v6.21.0 — youtube-nocookie / player.vimeo are not trusted hosts,\n // so under COEP `credentialless` is what lets them load at all.\n // `attr:` + `true | undefined` — see the note in `IframeRenderer`.\n attr:credentialless={\n // No sandbox here: a YouTube/Vimeo embed keeps its provider\n // cookies, so `'auto'` leaves it alone and a COEP host opts in\n // with `iframeCredentialless: 'always'`.\n shouldSetCredentialless(embedUrl()!, config, {\n sandboxedWithoutSameOrigin: false,\n }) || undefined\n }\n loading=\"lazy\"\n />\n </Show>\n </div>\n\n {/* v6.21.0 — a COEP-blocked embed is silent; this link is the way out. */}\n <Show when={embedUrl()}>\n <IframeFallbackLink url={params()?.url || ''} />\n </Show>\n\n {/* Caption */}\n <Show when={params()?.caption}>\n <div class=\"px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400\">{params()!.caption}</p>\n </div>\n </Show>\n </div>\n </ExpandableWrapper>\n )\n}\n\n/**\n * Check if a URL is from a supported video provider\n */\nexport function isSupportedVideoUrl(url: string): boolean {\n const info = parseVideoUrl(url)\n return info.provider !== 'direct' || url.match(/\\.(mp4|webm|ogg|mov)$/i) !== null\n}\n\n/**\n * Get video provider from URL\n */\nexport function getVideoProvider(url: string): VideoProvider {\n return parseVideoUrl(url).provider\n}\n"],"names":["parseVideoUrl","url","youtubeMatch","match","provider","videoId","vimeoMatch","VideoRenderer","props","strings","useMCPUIStrings","config","useMCPUIConfig","params","component","isExpanded","useExpanded","videoInfo","createMemo","embedUrl","info","p","ytParams","URLSearchParams","autoplay","controls","loop","mute","muted","startTime","set","String","vParams","aspectClass","aspectRatio","handleVideoError","e","error","Error","console","onError","_$createComponent","ExpandableWrapper","title","videoTitle","copyData","copyLabel","videoCopy","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_el$10","_el$11","_co$3","_$insert","Show","when","_el$2","_tmpl$","_el$3","fallback","_el$12","_tmpl$5","_el$13","_el$14","_el$15","_co$4","addEventListener","videoUnsupported","_$effect","_p$","_v$6","_v$7","poster","_v$8","_v$9","_v$0","_v$1","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","_v$3","shouldSetCredentialless","sandboxedWithoutSameOrigin","IframeFallbackLink","caption","_el$6","_tmpl$3","_el$7","_v$4","_v$5","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"VideoRenderer.d.ts","sourceRoot":"","sources":["../../src/components/VideoRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAoB,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAGjE,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAE7B;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAA;CAC5C;AAED;;GAEG;AACH,KAAK,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAA;AAsCnD,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,kBAAkB,CAwHvD,CAAA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAE3D"}
1
+ {"version":3,"file":"VideoRenderer.d.ts","sourceRoot":"","sources":["../../src/components/VideoRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAoB,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAOjE,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAE7B;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;IAEhC;;;OAGG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,gBAAgB,CAAA;CAC5C;AAED;;GAEG;AACH,KAAK,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAA;AAsCnD,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,kBAAkB,CA0IvD,CAAA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAE3D"}
@@ -1,7 +1,11 @@
1
1
  import { createComponent, getNextElement, getNextMarker, insert, effect, setAttribute, setProperty, className, template } from "solid-js/web";
2
2
  import { createMemo, Show } from "solid-js";
3
3
  import { useExpanded, ExpandableWrapper } from "./ExpandableWrapper.js";
4
- var _tmpl$ = /* @__PURE__ */ template(`<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$2 = /* @__PURE__ */ template(`<iframe class="absolute inset-0 w-full h-full"allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"allowfullscreen loading=lazy>`, true, false, false), _tmpl$3 = /* @__PURE__ */ template(`<div class="px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0"><p class="text-sm text-gray-600 dark:text-gray-400">`), _tmpl$4 = /* @__PURE__ */ template(`<div><!$><!/><div></div><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<video playsinline class="absolute inset-0 w-full h-full object-contain"><track kind=captions>Your browser does not support the video tag.`);
4
+ import { useMCPUIStrings } from "../context/MCPUIStringsContext.js";
5
+ import { useMCPUIConfig } from "../context/MCPUIConfigContext.js";
6
+ import { shouldSetCredentialless } from "../utils/iframe-coep.js";
7
+ import { IframeFallbackLink } from "./IframeFallbackLink.js";
8
+ var _tmpl$ = /* @__PURE__ */ template(`<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$2 = /* @__PURE__ */ template(`<iframe class="absolute inset-0 w-full h-full"allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"allowfullscreen loading=lazy>`, true, false, false), _tmpl$3 = /* @__PURE__ */ template(`<div class="px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0"><p class="text-sm text-gray-600 dark:text-gray-400">`), _tmpl$4 = /* @__PURE__ */ template(`<div><!$><!/><div></div><!$><!/><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<video playsinline class="absolute inset-0 w-full h-full object-contain"><track kind=captions><!$><!/>`);
5
9
  function parseVideoUrl(url) {
6
10
  const youtubeMatch = url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|v\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
7
11
  if (youtubeMatch) {
@@ -22,6 +26,8 @@ function parseVideoUrl(url) {
22
26
  };
23
27
  }
24
28
  const VideoRenderer = (props) => {
29
+ const strings = useMCPUIStrings();
30
+ const config = useMCPUIConfig();
25
31
  const params = () => {
26
32
  var _a;
27
33
  return props.params || ((_a = props.component) == null ? void 0 : _a.params);
@@ -82,18 +88,20 @@ const VideoRenderer = (props) => {
82
88
  return createComponent(ExpandableWrapper, {
83
89
  get title() {
84
90
  var _a;
85
- return ((_a = params()) == null ? void 0 : _a.title) || "Video";
91
+ return ((_a = params()) == null ? void 0 : _a.title) || strings.videoTitle;
86
92
  },
87
93
  get copyData() {
88
94
  var _a;
89
95
  return ((_a = params()) == null ? void 0 : _a.url) || "";
90
96
  },
91
- copyLabel: "Copy video URL",
97
+ get copyLabel() {
98
+ return strings.videoCopy;
99
+ },
92
100
  get toolbarVariant() {
93
101
  return props.toolbarVariant;
94
102
  },
95
103
  get children() {
96
- var _el$ = getNextElement(_tmpl$4), _el$8 = _el$.firstChild, [_el$9, _co$] = getNextMarker(_el$8.nextSibling), _el$4 = _el$9.nextSibling, _el$0 = _el$4.nextSibling, [_el$1, _co$2] = getNextMarker(_el$0.nextSibling);
104
+ var _el$ = getNextElement(_tmpl$4), _el$8 = _el$.firstChild, [_el$9, _co$] = getNextMarker(_el$8.nextSibling), _el$4 = _el$9.nextSibling, _el$0 = _el$4.nextSibling, [_el$1, _co$2] = getNextMarker(_el$0.nextSibling), _el$10 = _el$1.nextSibling, [_el$11, _co$3] = getNextMarker(_el$10.nextSibling);
97
105
  insert(_el$, createComponent(Show, {
98
106
  get when() {
99
107
  var _a;
@@ -113,17 +121,18 @@ const VideoRenderer = (props) => {
113
121
  return (
114
122
  // Direct video file
115
123
  (() => {
116
- var _el$10 = getNextElement(_tmpl$5);
117
- _el$10.addEventListener("error", handleVideoError);
124
+ var _el$12 = getNextElement(_tmpl$5), _el$13 = _el$12.firstChild, _el$14 = _el$13.nextSibling, [_el$15, _co$4] = getNextMarker(_el$14.nextSibling);
125
+ _el$12.addEventListener("error", handleVideoError);
126
+ insert(_el$12, () => strings.videoUnsupported, _el$15, _co$4);
118
127
  effect((_p$) => {
119
128
  var _a, _b, _c, _d, _e, _f;
120
- var _v$5 = (_a = params()) == null ? void 0 : _a.url, _v$6 = (_b = params()) == null ? void 0 : _b.poster, _v$7 = (_c = params()) == null ? void 0 : _c.autoplay, _v$8 = ((_d = params()) == null ? void 0 : _d.controls) !== false, _v$9 = (_e = params()) == null ? void 0 : _e.loop, _v$0 = (_f = params()) == null ? void 0 : _f.muted;
121
- _v$5 !== _p$.e && setAttribute(_el$10, "src", _p$.e = _v$5);
122
- _v$6 !== _p$.t && setAttribute(_el$10, "poster", _p$.t = _v$6);
123
- _v$7 !== _p$.a && setProperty(_el$10, "autoplay", _p$.a = _v$7);
124
- _v$8 !== _p$.o && setProperty(_el$10, "controls", _p$.o = _v$8);
125
- _v$9 !== _p$.i && setProperty(_el$10, "loop", _p$.i = _v$9);
126
- _v$0 !== _p$.n && setProperty(_el$10, "muted", _p$.n = _v$0);
129
+ var _v$6 = (_a = params()) == null ? void 0 : _a.url, _v$7 = (_b = params()) == null ? void 0 : _b.poster, _v$8 = (_c = params()) == null ? void 0 : _c.autoplay, _v$9 = ((_d = params()) == null ? void 0 : _d.controls) !== false, _v$0 = (_e = params()) == null ? void 0 : _e.loop, _v$1 = (_f = params()) == null ? void 0 : _f.muted;
130
+ _v$6 !== _p$.e && setAttribute(_el$12, "src", _p$.e = _v$6);
131
+ _v$7 !== _p$.t && setAttribute(_el$12, "poster", _p$.t = _v$7);
132
+ _v$8 !== _p$.a && setProperty(_el$12, "autoplay", _p$.a = _v$8);
133
+ _v$9 !== _p$.o && setProperty(_el$12, "controls", _p$.o = _v$9);
134
+ _v$0 !== _p$.i && setProperty(_el$12, "loop", _p$.i = _v$0);
135
+ _v$1 !== _p$.n && setProperty(_el$12, "muted", _p$.n = _v$1);
127
136
  return _p$;
128
137
  }, {
129
138
  e: void 0,
@@ -133,7 +142,7 @@ const VideoRenderer = (props) => {
133
142
  i: void 0,
134
143
  n: void 0
135
144
  });
136
- return _el$10;
145
+ return _el$12;
137
146
  })()
138
147
  );
139
148
  },
@@ -141,17 +150,39 @@ const VideoRenderer = (props) => {
141
150
  var _el$5 = getNextElement(_tmpl$2);
142
151
  effect((_p$) => {
143
152
  var _a;
144
- var _v$ = embedUrl(), _v$2 = ((_a = params()) == null ? void 0 : _a.title) || "Video";
153
+ var _v$ = embedUrl(), _v$2 = ((_a = params()) == null ? void 0 : _a.title) || strings.videoTitle, _v$3 = (
154
+ // No sandbox here: a YouTube/Vimeo embed keeps its provider
155
+ // cookies, so `'auto'` leaves it alone and a COEP host opts in
156
+ // with `iframeCredentialless: 'always'`.
157
+ shouldSetCredentialless(embedUrl(), config, {
158
+ sandboxedWithoutSameOrigin: false
159
+ }) || void 0
160
+ );
145
161
  _v$ !== _p$.e && setAttribute(_el$5, "src", _p$.e = _v$);
146
162
  _v$2 !== _p$.t && setAttribute(_el$5, "title", _p$.t = _v$2);
163
+ _v$3 !== _p$.a && setAttribute(_el$5, "credentialless", _p$.a = _v$3);
147
164
  return _p$;
148
165
  }, {
149
166
  e: void 0,
150
- t: void 0
167
+ t: void 0,
168
+ a: void 0
151
169
  });
152
170
  return _el$5;
153
171
  }
154
172
  }));
173
+ insert(_el$, createComponent(Show, {
174
+ get when() {
175
+ return embedUrl();
176
+ },
177
+ get children() {
178
+ return createComponent(IframeFallbackLink, {
179
+ get url() {
180
+ var _a;
181
+ return ((_a = params()) == null ? void 0 : _a.url) || "";
182
+ }
183
+ });
184
+ }
185
+ }), _el$1, _co$2);
155
186
  insert(_el$, createComponent(Show, {
156
187
  get when() {
157
188
  var _a;
@@ -162,11 +193,11 @@ const VideoRenderer = (props) => {
162
193
  insert(_el$7, () => params().caption);
163
194
  return _el$6;
164
195
  }
165
- }), _el$1, _co$2);
196
+ }), _el$11, _co$3);
166
197
  effect((_p$) => {
167
- var _v$3 = `w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : ""}`, _v$4 = `relative bg-black ${isExpanded() ? "flex-1 min-h-0" : aspectClass()}`;
168
- _v$3 !== _p$.e && className(_el$, _p$.e = _v$3);
169
- _v$4 !== _p$.t && className(_el$4, _p$.t = _v$4);
198
+ var _v$4 = `w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : ""}`, _v$5 = `relative bg-black ${isExpanded() ? "flex-1 min-h-0" : aspectClass()}`;
199
+ _v$4 !== _p$.e && className(_el$, _p$.e = _v$4);
200
+ _v$5 !== _p$.t && className(_el$4, _p$.t = _v$5);
170
201
  return _p$;
171
202
  }, {
172
203
  e: void 0,
@@ -1 +1 @@
1
- {"version":3,"file":"VideoRenderer.js","sources":["../../src/components/VideoRenderer.tsx"],"sourcesContent":["/**\n * VideoRenderer - Video embed component\n * Sprint 5: Media Components\n *\n * Supports YouTube, Vimeo, and direct video files\n */\n\nimport { Component, createMemo, Show } from 'solid-js'\nimport type { UIComponent, VideoComponentParams } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\n\nexport interface VideoRendererProps {\n /**\n * UIComponent containing video params\n */\n component?: UIComponent\n\n /**\n * Direct video params (alternative to component)\n */\n params?: VideoComponentParams\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible'\n}\n\n/**\n * Video provider type\n */\ntype VideoProvider = 'youtube' | 'vimeo' | 'direct'\n\n/**\n * Parsed video info\n */\ninterface VideoInfo {\n provider: VideoProvider\n videoId?: string\n}\n\n/**\n * Extract video ID and provider from URL\n */\nfunction parseVideoUrl(url: string): VideoInfo {\n // YouTube patterns:\n // - youtube.com/watch?v=VIDEO_ID\n // - youtube.com/embed/VIDEO_ID\n // - youtube.com/v/VIDEO_ID\n // - youtu.be/VIDEO_ID\n const youtubeMatch = url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/\n )\n if (youtubeMatch) {\n return { provider: 'youtube', videoId: youtubeMatch[1] }\n }\n\n // Vimeo patterns:\n // - vimeo.com/VIDEO_ID\n // - player.vimeo.com/video/VIDEO_ID\n const vimeoMatch = url.match(/(?:vimeo\\.com\\/|player\\.vimeo\\.com\\/video\\/)(\\d+)/)\n if (vimeoMatch) {\n return { provider: 'vimeo', videoId: vimeoMatch[1] }\n }\n\n // Direct video file\n return { provider: 'direct' }\n}\n\nexport const VideoRenderer: Component<VideoRendererProps> = (props) => {\n const params = () => props.params || (props.component?.params as VideoComponentParams)\n const isExpanded = useExpanded()\n\n const videoInfo = createMemo(() => parseVideoUrl(params()?.url || ''))\n\n const embedUrl = createMemo(() => {\n const info = videoInfo()\n const p = params()\n\n if (!p?.url) return null\n\n switch (info.provider) {\n case 'youtube': {\n const ytParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n controls: p.controls !== false ? '1' : '0',\n loop: p.loop ? '1' : '0',\n mute: p.muted ? '1' : '0',\n })\n if (p.startTime) {\n ytParams.set('start', String(p.startTime))\n }\n // Use youtube-nocookie.com for privacy\n return `https://www.youtube-nocookie.com/embed/${info.videoId}?${ytParams}`\n }\n\n case 'vimeo': {\n const vParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n loop: p.loop ? '1' : '0',\n muted: p.muted ? '1' : '0',\n })\n return `https://player.vimeo.com/video/${info.videoId}?${vParams}`\n }\n\n default:\n return null\n }\n })\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '4:3':\n return 'aspect-[4/3]'\n case '21:9':\n return 'aspect-[21/9]'\n default:\n return 'aspect-video' // 16:9\n }\n }\n\n const handleVideoError = (e: Event) => {\n const error = new Error('Video failed to load')\n console.error('Video error:', e)\n props.onError?.(error)\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || 'Video'}\n copyData={params()?.url || ''}\n copyLabel=\"Copy video URL\"\n toolbarVariant={props.toolbarVariant}\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Video Container — when expanded, fill remaining space (override aspect ratio) */}\n <div class={`relative bg-black ${isExpanded() ? 'flex-1 min-h-0' : aspectClass()}`}>\n <Show\n when={embedUrl()}\n fallback={\n // Direct video file\n <video\n src={params()?.url}\n poster={params()?.poster}\n autoplay={params()?.autoplay}\n controls={params()?.controls !== false}\n loop={params()?.loop}\n muted={params()?.muted}\n playsinline\n class=\"absolute inset-0 w-full h-full object-contain\"\n onError={handleVideoError}\n >\n <track kind=\"captions\" />\n Your browser does not support the video tag.\n </video>\n }\n >\n {/* YouTube/Vimeo embed */}\n <iframe\n src={embedUrl()!}\n title={params()?.title || 'Video'}\n class=\"absolute inset-0 w-full h-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowfullscreen\n loading=\"lazy\"\n />\n </Show>\n </div>\n\n {/* Caption */}\n <Show when={params()?.caption}>\n <div class=\"px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400\">{params()!.caption}</p>\n </div>\n </Show>\n </div>\n </ExpandableWrapper>\n )\n}\n\n/**\n * Check if a URL is from a supported video provider\n */\nexport function isSupportedVideoUrl(url: string): boolean {\n const info = parseVideoUrl(url)\n return info.provider !== 'direct' || url.match(/\\.(mp4|webm|ogg|mov)$/i) !== null\n}\n\n/**\n * Get video provider from URL\n */\nexport function getVideoProvider(url: string): VideoProvider {\n return parseVideoUrl(url).provider\n}\n"],"names":["parseVideoUrl","url","youtubeMatch","match","provider","videoId","vimeoMatch","VideoRenderer","props","params","component","isExpanded","useExpanded","videoInfo","createMemo","embedUrl","info","p","ytParams","URLSearchParams","autoplay","controls","loop","mute","muted","startTime","set","String","vParams","aspectClass","aspectRatio","handleVideoError","e","error","Error","console","onError","_$createComponent","ExpandableWrapper","title","copyData","copyLabel","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","fallback","_el$10","_tmpl$5","addEventListener","_$effect","_p$","_v$5","_v$6","poster","_v$7","_v$8","_v$9","_v$0","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","caption","_el$6","_tmpl$3","_el$7","_v$3","_v$4","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
1
+ {"version":3,"file":"VideoRenderer.js","sources":["../../src/components/VideoRenderer.tsx"],"sourcesContent":["/**\n * VideoRenderer - Video embed component\n * Sprint 5: Media Components\n *\n * Supports YouTube, Vimeo, and direct video files\n */\n\nimport { Component, createMemo, Show } from 'solid-js'\nimport type { UIComponent, VideoComponentParams } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\nimport { useMCPUIStrings } from '../context/MCPUIStringsContext'\nimport { useMCPUIConfig } from '../context/MCPUIConfigContext'\nimport { shouldSetCredentialless } from '../utils/iframe-coep'\nimport { IframeFallbackLink } from './IframeFallbackLink'\n\nexport interface VideoRendererProps {\n /**\n * UIComponent containing video params\n */\n component?: UIComponent\n\n /**\n * Direct video params (alternative to component)\n */\n params?: VideoComponentParams\n\n /**\n * Error callback\n */\n onError?: (error: Error) => void\n\n /**\n * Forwarded to the underlying `<ExpandableWrapper>` (v6.3.1).\n * @see ExpandableWrapperProps.toolbarVariant\n */\n toolbarVariant?: 'hover' | 'always-visible'\n}\n\n/**\n * Video provider type\n */\ntype VideoProvider = 'youtube' | 'vimeo' | 'direct'\n\n/**\n * Parsed video info\n */\ninterface VideoInfo {\n provider: VideoProvider\n videoId?: string\n}\n\n/**\n * Extract video ID and provider from URL\n */\nfunction parseVideoUrl(url: string): VideoInfo {\n // YouTube patterns:\n // - youtube.com/watch?v=VIDEO_ID\n // - youtube.com/embed/VIDEO_ID\n // - youtube.com/v/VIDEO_ID\n // - youtu.be/VIDEO_ID\n const youtubeMatch = url.match(\n /(?:youtube\\.com\\/(?:watch\\?v=|embed\\/|v\\/)|youtu\\.be\\/)([a-zA-Z0-9_-]{11})/\n )\n if (youtubeMatch) {\n return { provider: 'youtube', videoId: youtubeMatch[1] }\n }\n\n // Vimeo patterns:\n // - vimeo.com/VIDEO_ID\n // - player.vimeo.com/video/VIDEO_ID\n const vimeoMatch = url.match(/(?:vimeo\\.com\\/|player\\.vimeo\\.com\\/video\\/)(\\d+)/)\n if (vimeoMatch) {\n return { provider: 'vimeo', videoId: vimeoMatch[1] }\n }\n\n // Direct video file\n return { provider: 'direct' }\n}\n\nexport const VideoRenderer: Component<VideoRendererProps> = (props) => {\n const strings = useMCPUIStrings()\n const config = useMCPUIConfig()\n const params = () => props.params || (props.component?.params as VideoComponentParams)\n const isExpanded = useExpanded()\n\n const videoInfo = createMemo(() => parseVideoUrl(params()?.url || ''))\n\n const embedUrl = createMemo(() => {\n const info = videoInfo()\n const p = params()\n\n if (!p?.url) return null\n\n switch (info.provider) {\n case 'youtube': {\n const ytParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n controls: p.controls !== false ? '1' : '0',\n loop: p.loop ? '1' : '0',\n mute: p.muted ? '1' : '0',\n })\n if (p.startTime) {\n ytParams.set('start', String(p.startTime))\n }\n // Use youtube-nocookie.com for privacy\n return `https://www.youtube-nocookie.com/embed/${info.videoId}?${ytParams}`\n }\n\n case 'vimeo': {\n const vParams = new URLSearchParams({\n autoplay: p.autoplay ? '1' : '0',\n loop: p.loop ? '1' : '0',\n muted: p.muted ? '1' : '0',\n })\n return `https://player.vimeo.com/video/${info.videoId}?${vParams}`\n }\n\n default:\n return null\n }\n })\n\n const aspectClass = () => {\n switch (params()?.aspectRatio) {\n case '1:1':\n return 'aspect-square'\n case '4:3':\n return 'aspect-[4/3]'\n case '21:9':\n return 'aspect-[21/9]'\n default:\n return 'aspect-video' // 16:9\n }\n }\n\n const handleVideoError = (e: Event) => {\n const error = new Error('Video failed to load')\n console.error('Video error:', e)\n props.onError?.(error)\n }\n\n return (\n <ExpandableWrapper\n title={params()?.title || strings.videoTitle}\n copyData={params()?.url || ''}\n copyLabel={strings.videoCopy}\n toolbarVariant={props.toolbarVariant}\n >\n <div class={`w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${\n isExpanded() ? 'flex-1 min-h-0 flex flex-col' : ''\n }`}>\n {/* Title */}\n <Show when={params()?.title}>\n <div class=\"px-4 py-3 border-b border-gray-200 dark:border-gray-700\">\n <h3 class=\"text-sm font-semibold text-gray-900 dark:text-white\">{params()!.title}</h3>\n </div>\n </Show>\n\n {/* Video Container — when expanded, fill remaining space (override aspect ratio) */}\n <div class={`relative bg-black ${isExpanded() ? 'flex-1 min-h-0' : aspectClass()}`}>\n <Show\n when={embedUrl()}\n fallback={\n // Direct video file\n <video\n src={params()?.url}\n poster={params()?.poster}\n autoplay={params()?.autoplay}\n controls={params()?.controls !== false}\n loop={params()?.loop}\n muted={params()?.muted}\n playsinline\n class=\"absolute inset-0 w-full h-full object-contain\"\n onError={handleVideoError}\n >\n <track kind=\"captions\" />\n {strings.videoUnsupported}\n </video>\n }\n >\n {/* YouTube/Vimeo embed */}\n <iframe\n src={embedUrl()!}\n title={params()?.title || strings.videoTitle}\n class=\"absolute inset-0 w-full h-full\"\n allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\"\n allowfullscreen\n // v6.21.0 — youtube-nocookie / player.vimeo are not trusted hosts,\n // so under COEP `credentialless` is what lets them load at all.\n // `attr:` + `true | undefined` — see the note in `IframeRenderer`.\n attr:credentialless={\n // No sandbox here: a YouTube/Vimeo embed keeps its provider\n // cookies, so `'auto'` leaves it alone and a COEP host opts in\n // with `iframeCredentialless: 'always'`.\n shouldSetCredentialless(embedUrl()!, config, {\n sandboxedWithoutSameOrigin: false,\n }) || undefined\n }\n loading=\"lazy\"\n />\n </Show>\n </div>\n\n {/* v6.21.0 — a COEP-blocked embed is silent; this link is the way out. */}\n <Show when={embedUrl()}>\n <IframeFallbackLink url={params()?.url || ''} />\n </Show>\n\n {/* Caption */}\n <Show when={params()?.caption}>\n <div class=\"px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400\">{params()!.caption}</p>\n </div>\n </Show>\n </div>\n </ExpandableWrapper>\n )\n}\n\n/**\n * Check if a URL is from a supported video provider\n */\nexport function isSupportedVideoUrl(url: string): boolean {\n const info = parseVideoUrl(url)\n return info.provider !== 'direct' || url.match(/\\.(mp4|webm|ogg|mov)$/i) !== null\n}\n\n/**\n * Get video provider from URL\n */\nexport function getVideoProvider(url: string): VideoProvider {\n return parseVideoUrl(url).provider\n}\n"],"names":["parseVideoUrl","url","youtubeMatch","match","provider","videoId","vimeoMatch","VideoRenderer","props","strings","useMCPUIStrings","config","useMCPUIConfig","params","component","isExpanded","useExpanded","videoInfo","createMemo","embedUrl","info","p","ytParams","URLSearchParams","autoplay","controls","loop","mute","muted","startTime","set","String","vParams","aspectClass","aspectRatio","handleVideoError","e","error","Error","console","onError","_$createComponent","ExpandableWrapper","title","videoTitle","copyData","copyLabel","videoCopy","toolbarVariant","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_el$10","_el$11","_co$3","_$insert","Show","when","_el$2","_tmpl$","_el$3","fallback","_el$12","_tmpl$5","_el$13","_el$14","_el$15","_co$4","addEventListener","videoUnsupported","_$effect","_p$","_v$6","_v$7","poster","_v$8","_v$9","_v$0","_v$1","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","_v$3","shouldSetCredentialless","sandboxedWithoutSameOrigin","IframeFallbackLink","caption","_el$6","_tmpl$3","_el$7","_v$4","_v$5","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
@@ -1,5 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const formatString = require("../utils/format-string.cjs");
4
+ const CHART_DATA_TABLE_LABELS = {
5
+ series: "Series",
6
+ point: "Point",
7
+ label: "Label",
8
+ seriesName: "Series {n}",
9
+ x: "x",
10
+ y: "y",
11
+ r: "r"
12
+ };
3
13
  function tableCell(value) {
4
14
  if (value == null) return "";
5
15
  if (typeof value === "string" || typeof value === "number") return value;
@@ -13,37 +23,38 @@ function tableCell(value) {
13
23
  function isPoint(value) {
14
24
  return value !== null && typeof value === "object" && !Array.isArray(value) && ("x" in value || "y" in value || "r" in value);
15
25
  }
16
- function chartToDataTable(params) {
26
+ function chartToDataTable(params, labels) {
17
27
  var _a, _b;
28
+ const l = { ...CHART_DATA_TABLE_LABELS, ...labels };
18
29
  const datasets = ((_a = params.data) == null ? void 0 : _a.datasets) ?? [];
19
- const labels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
30
+ const dataLabels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
20
31
  const pointData = params.type === "scatter" || params.type === "bubble" || datasets.some((dataset) => {
21
32
  var _a2;
22
33
  return (_a2 = dataset.data) == null ? void 0 : _a2.some(isPoint);
23
34
  });
24
35
  if (pointData) {
25
- const hasLabels = labels.length > 0;
36
+ const hasLabels = dataLabels.length > 0;
26
37
  const hasRadius = params.type === "bubble" || datasets.some((dataset) => {
27
38
  var _a2;
28
39
  return (_a2 = dataset.data) == null ? void 0 : _a2.some((value) => isPoint(value) && "r" in value);
29
40
  });
30
41
  const columns2 = [
31
- "Series",
32
- "Point",
33
- ...hasLabels ? ["Label"] : [],
34
- "x",
35
- "y",
36
- ...hasRadius ? ["r"] : []
42
+ l.series,
43
+ l.point,
44
+ ...hasLabels ? [l.label] : [],
45
+ l.x,
46
+ l.y,
47
+ ...hasRadius ? [l.r] : []
37
48
  ];
38
49
  const rows2 = [];
39
50
  datasets.forEach((dataset, datasetIndex) => {
40
- const series = dataset.label || `Series ${datasetIndex + 1}`;
51
+ const series = dataset.label || formatString.formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });
41
52
  (dataset.data ?? []).forEach((value, pointIndex) => {
42
53
  const point = isPoint(value) ? value : { y: value };
43
54
  rows2.push([
44
55
  series,
45
56
  pointIndex + 1,
46
- ...hasLabels ? [tableCell(labels[pointIndex])] : [],
57
+ ...hasLabels ? [tableCell(dataLabels[pointIndex])] : [],
47
58
  tableCell(point.x),
48
59
  tableCell(point.y),
49
60
  ...hasRadius ? [tableCell(point.r)] : []
@@ -52,15 +63,24 @@ function chartToDataTable(params) {
52
63
  });
53
64
  return { columns: columns2, rows: rows2 };
54
65
  }
55
- const rowCount = Math.max(labels.length, ...datasets.map((dataset) => {
56
- var _a2;
57
- return ((_a2 = dataset.data) == null ? void 0 : _a2.length) ?? 0;
58
- }), 0);
59
- const columns = ["Label", ...datasets.map((dataset, index) => dataset.label || `Series ${index + 1}`)];
66
+ const rowCount = Math.max(
67
+ dataLabels.length,
68
+ ...datasets.map((dataset) => {
69
+ var _a2;
70
+ return ((_a2 = dataset.data) == null ? void 0 : _a2.length) ?? 0;
71
+ }),
72
+ 0
73
+ );
74
+ const columns = [
75
+ l.label,
76
+ ...datasets.map(
77
+ (dataset, index) => dataset.label || formatString.formatMCPUIString(l.seriesName, { n: index + 1 })
78
+ )
79
+ ];
60
80
  const rows = [];
61
81
  for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
62
82
  rows.push([
63
- tableCell(labels[rowIndex] ?? rowIndex + 1),
83
+ tableCell(dataLabels[rowIndex] ?? rowIndex + 1),
64
84
  ...datasets.map((dataset) => {
65
85
  var _a2;
66
86
  return tableCell((_a2 = dataset.data) == null ? void 0 : _a2[rowIndex]);
@@ -69,5 +89,6 @@ function chartToDataTable(params) {
69
89
  }
70
90
  return { columns, rows };
71
91
  }
92
+ exports.CHART_DATA_TABLE_LABELS = CHART_DATA_TABLE_LABELS;
72
93
  exports.chartToDataTable = chartToDataTable;
73
94
  //# sourceMappingURL=chart-data-table.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-data-table.cjs","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["export interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(params: ChartDataLike): ChartDataTable {\n const datasets = params.data?.datasets ?? [];\n const labels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = labels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n 'Series',\n 'Point',\n ...(hasLabels ? ['Label'] : []),\n 'x',\n 'y',\n ...(hasRadius ? ['r'] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || `Series ${datasetIndex + 1}`;\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(labels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n });\n });\n\n return { columns, rows };\n }\n\n const rowCount = Math.max(labels.length, ...datasets.map((dataset) => dataset.data?.length ?? 0), 0);\n const columns = ['Label', ...datasets.map((dataset, index) => dataset.label || `Series ${index + 1}`)];\n const rows: Array<Array<string | number>> = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(labels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n }\n\n return { columns, rows };\n}\n"],"names":["_a","columns","rows"],"mappings":";;AAkBA,SAAS,UAAU,OAAiC;AAClD,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO;AACnE,MAAI,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AACnD,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAEA,SAAS,QAAQ,OAAkD;AACjE,SACE,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,KAAK,MACnB,OAAO,SAAS,OAAO,SAAS,OAAO;AAE5C;AAOO,SAAS,iBAAiB,QAAuC;;AACtE,QAAM,aAAW,YAAO,SAAP,mBAAa,aAAY,CAAA;AAC1C,QAAM,WAAS,YAAO,SAAP,mBAAa,WAAU,CAAA;AACtC,QAAM,YACJ,OAAO,SAAS,aAChB,OAAO,SAAS,YAChB,SAAS,KAAK,CAAC,YAAA;;AAAY,YAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,KAAK;AAAA,GAAQ;AAExD,MAAI,WAAW;AACb,UAAM,YAAY,OAAO,SAAS;AAClC,UAAM,YACJ,OAAO,SAAS,YAChB,SAAS,KAAK,CAAC,YAAA;;AAAY,cAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,KAAK,CAAC,UAAU,QAAQ,KAAK,KAAK,OAAO;AAAA,KAAM;AAC1F,UAAMC,WAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA,GAAI,YAAY,CAAC,OAAO,IAAI,CAAA;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,GAAI,YAAY,CAAC,GAAG,IAAI,CAAA;AAAA,IAAC;AAE3B,UAAMC,QAAsC,CAAA;AAE5C,aAAS,QAAQ,CAAC,SAAS,iBAAiB;AAC1C,YAAM,SAAS,QAAQ,SAAS,UAAU,eAAe,CAAC;AAC1D,OAAC,QAAQ,QAAQ,CAAA,GAAI,QAAQ,CAAC,OAAO,eAAe;AAClD,cAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,EAAE,GAAG,MAAA;AAC5CA,cAAK,KAAK;AAAA,UACR;AAAA,UACA,aAAa;AAAA,UACb,GAAI,YAAY,CAAC,UAAU,OAAO,UAAU,CAAC,CAAC,IAAI,CAAA;AAAA,UAClD,UAAU,MAAM,CAAC;AAAA,UACjB,UAAU,MAAM,CAAC;AAAA,UACjB,GAAI,YAAY,CAAC,UAAU,MAAM,CAAC,CAAC,IAAI,CAAA;AAAA,QAAC,CACzC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAED,WAAO,EAAE,SAAAD,UAAS,MAAAC,MAAAA;AAAAA,EACpB;AAEA,QAAM,WAAW,KAAK,IAAI,OAAO,QAAQ,GAAG,SAAS,IAAI,CAAC;;AAAY,aAAAF,MAAA,QAAQ,SAAR,gBAAAA,IAAc,WAAU;AAAA,GAAC,GAAG,CAAC;AACnG,QAAM,UAAU,CAAC,SAAS,GAAG,SAAS,IAAI,CAAC,SAAS,UAAU,QAAQ,SAAS,UAAU,QAAQ,CAAC,EAAE,CAAC;AACrG,QAAM,OAAsC,CAAA;AAE5C,WAAS,WAAW,GAAG,WAAW,UAAU,YAAY,GAAG;AACzD,SAAK,KAAK;AAAA,MACR,UAAU,OAAO,QAAQ,KAAK,WAAW,CAAC;AAAA,MAC1C,GAAG,SAAS,IAAI,CAAC,YAAA;;AAAY,0BAAUA,MAAA,QAAQ,SAAR,gBAAAA,IAAe,SAAS;AAAA,OAAC;AAAA,IAAA,CACjE;AAAA,EACH;AAEA,SAAO,EAAE,SAAS,KAAA;AACpB;;"}
1
+ {"version":3,"file":"chart-data-table.cjs","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["import { formatMCPUIString } from '../utils/format-string';\n\n/**\n * Column headers and series names of the accessible chart data table.\n *\n * `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so\n * the wording is injected: it takes an optional trailing `labels` partial,\n * which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point\n * property NAMES the cells mirror, not prose.\n *\n * @since v6.20.0\n */\nexport interface ChartDataTableLabels {\n /** Series column of the per-point table. */\n series: string;\n /** Point-index column of the per-point table. */\n point: string;\n /** Label column (categorical table, and per-point table when labelled). */\n label: string;\n /** Fallback dataset name. Template — `{n}`. */\n seriesName: string;\n /** Chart.js point property names — machine tokens, rarely overridden. */\n x: string;\n y: string;\n r: string;\n}\n\n/** English defaults for {@link ChartDataTableLabels}. */\nexport const CHART_DATA_TABLE_LABELS: ChartDataTableLabels = {\n series: 'Series',\n point: 'Point',\n label: 'Label',\n seriesName: 'Series {n}',\n x: 'x',\n y: 'y',\n r: 'r',\n};\n\nexport interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(\n params: ChartDataLike,\n labels?: Partial<ChartDataTableLabels>\n): ChartDataTable {\n const l: ChartDataTableLabels = { ...CHART_DATA_TABLE_LABELS, ...labels };\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = dataLabels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n l.series,\n l.point,\n ...(hasLabels ? [l.label] : []),\n l.x,\n l.y,\n ...(hasRadius ? [l.r] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(dataLabels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n });\n });\n\n return { columns, rows };\n }\n\n const rowCount = Math.max(\n dataLabels.length,\n ...datasets.map((dataset) => dataset.data?.length ?? 0),\n 0\n );\n const columns = [\n l.label,\n ...datasets.map(\n (dataset, index) => dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 })\n ),\n ];\n const rows: Array<Array<string | number>> = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(dataLabels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n }\n\n return { columns, rows };\n}\n"],"names":["_a","columns","rows","formatMCPUIString"],"mappings":";;;AA+BO,MAAM,0BAAgD;AAAA,EAC3D,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,OAAO;AAAA,EACP,YAAY;AAAA,EACZ,GAAG;AAAA,EACH,GAAG;AAAA,EACH,GAAG;AACL;AAoBA,SAAS,UAAU,OAAiC;AAClD,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO;AACnE,MAAI,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AACnD,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAEA,SAAS,QAAQ,OAAkD;AACjE,SACE,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,KAAK,MACnB,OAAO,SAAS,OAAO,SAAS,OAAO;AAE5C;AAOO,SAAS,iBACd,QACA,QACgB;;AAChB,QAAM,IAA0B,EAAE,GAAG,yBAAyB,GAAG,OAAA;AACjE,QAAM,aAAW,YAAO,SAAP,mBAAa,aAAY,CAAA;AAC1C,QAAM,eAAa,YAAO,SAAP,mBAAa,WAAU,CAAA;AAC1C,QAAM,YACJ,OAAO,SAAS,aAChB,OAAO,SAAS,YAChB,SAAS,KAAK,CAAC,YAAA;;AAAY,YAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,KAAK;AAAA,GAAQ;AAExD,MAAI,WAAW;AACb,UAAM,YAAY,WAAW,SAAS;AACtC,UAAM,YACJ,OAAO,SAAS,YAChB,SAAS,KAAK,CAAC,YAAA;;AAAY,cAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,KAAK,CAAC,UAAU,QAAQ,KAAK,KAAK,OAAO;AAAA,KAAM;AAC1F,UAAMC,WAAU;AAAA,MACd,EAAE;AAAA,MACF,EAAE;AAAA,MACF,GAAI,YAAY,CAAC,EAAE,KAAK,IAAI,CAAA;AAAA,MAC5B,EAAE;AAAA,MACF,EAAE;AAAA,MACF,GAAI,YAAY,CAAC,EAAE,CAAC,IAAI,CAAA;AAAA,IAAC;AAE3B,UAAMC,QAAsC,CAAA;AAE5C,aAAS,QAAQ,CAAC,SAAS,iBAAiB;AAC1C,YAAM,SAAS,QAAQ,SAASC,+BAAkB,EAAE,YAAY,EAAE,GAAG,eAAe,GAAG;AACvF,OAAC,QAAQ,QAAQ,CAAA,GAAI,QAAQ,CAAC,OAAO,eAAe;AAClD,cAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,EAAE,GAAG,MAAA;AAC5CD,cAAK,KAAK;AAAA,UACR;AAAA,UACA,aAAa;AAAA,UACb,GAAI,YAAY,CAAC,UAAU,WAAW,UAAU,CAAC,CAAC,IAAI,CAAA;AAAA,UACtD,UAAU,MAAM,CAAC;AAAA,UACjB,UAAU,MAAM,CAAC;AAAA,UACjB,GAAI,YAAY,CAAC,UAAU,MAAM,CAAC,CAAC,IAAI,CAAA;AAAA,QAAC,CACzC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAED,WAAO,EAAE,SAAAD,UAAS,MAAAC,MAAAA;AAAAA,EACpB;AAEA,QAAM,WAAW,KAAK;AAAA,IACpB,WAAW;AAAA,IACX,GAAG,SAAS,IAAI,CAAC;;AAAY,eAAAF,MAAA,QAAQ,SAAR,gBAAAA,IAAc,WAAU;AAAA,KAAC;AAAA,IACtD;AAAA,EAAA;AAEF,QAAM,UAAU;AAAA,IACd,EAAE;AAAA,IACF,GAAG,SAAS;AAAA,MACV,CAAC,SAAS,UAAU,QAAQ,SAASG,aAAAA,kBAAkB,EAAE,YAAY,EAAE,GAAG,QAAQ,EAAA,CAAG;AAAA,IAAA;AAAA,EACvF;AAEF,QAAM,OAAsC,CAAA;AAE5C,WAAS,WAAW,GAAG,WAAW,UAAU,YAAY,GAAG;AACzD,SAAK,KAAK;AAAA,MACR,UAAU,WAAW,QAAQ,KAAK,WAAW,CAAC;AAAA,MAC9C,GAAG,SAAS,IAAI,CAAC,YAAA;;AAAY,0BAAUH,MAAA,QAAQ,SAAR,gBAAAA,IAAe,SAAS;AAAA,OAAC;AAAA,IAAA,CACjE;AAAA,EACH;AAEA,SAAO,EAAE,SAAS,KAAA;AACpB;;;"}
@@ -1,3 +1,32 @@
1
+ /**
2
+ * Column headers and series names of the accessible chart data table.
3
+ *
4
+ * `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so
5
+ * the wording is injected: it takes an optional trailing `labels` partial,
6
+ * which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the
7
+ * English defaults below apply — the pre-v6.20.0 behaviour.
8
+ *
9
+ * `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point
10
+ * property NAMES the cells mirror, not prose.
11
+ *
12
+ * @since v6.20.0
13
+ */
14
+ export interface ChartDataTableLabels {
15
+ /** Series column of the per-point table. */
16
+ series: string;
17
+ /** Point-index column of the per-point table. */
18
+ point: string;
19
+ /** Label column (categorical table, and per-point table when labelled). */
20
+ label: string;
21
+ /** Fallback dataset name. Template — `{n}`. */
22
+ seriesName: string;
23
+ /** Chart.js point property names — machine tokens, rarely overridden. */
24
+ x: string;
25
+ y: string;
26
+ r: string;
27
+ }
28
+ /** English defaults for {@link ChartDataTableLabels}. */
29
+ export declare const CHART_DATA_TABLE_LABELS: ChartDataTableLabels;
1
30
  export interface ChartDataTable {
2
31
  columns: string[];
3
32
  rows: Array<Array<string | number>>;
@@ -18,6 +47,6 @@ export interface ChartDataLike {
18
47
  * coordinates. Categorical charts use a compact wide table; scatter, bubble,
19
48
  * and object-valued line charts use one row per point so x/y/r remain distinct.
20
49
  */
21
- export declare function chartToDataTable(params: ChartDataLike): ChartDataTable;
50
+ export declare function chartToDataTable(params: ChartDataLike, labels?: Partial<ChartDataTableLabels>): ChartDataTable;
22
51
  export {};
23
52
  //# sourceMappingURL=chart-data-table.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-data-table.d.ts","sourceRoot":"","sources":["../../src/components/chart-data-table.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;CACrC;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAC/B,CAAC;CACH;AAsBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,cAAc,CAqDtE"}
1
+ {"version":3,"file":"chart-data-table.d.ts","sourceRoot":"","sources":["../../src/components/chart-data-table.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,oBAAoB;IACnC,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;IACd,2EAA2E;IAC3E,KAAK,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED,yDAAyD;AACzD,eAAO,MAAM,uBAAuB,EAAE,oBAQrC,CAAC;AAEF,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;CACrC;AAED,UAAU,gBAAgB;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE;QACL,MAAM,CAAC,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;QAChC,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAC;KAC/B,CAAC;CACH;AAsBD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,aAAa,EACrB,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,GACrC,cAAc,CA+DhB"}
@@ -1,3 +1,13 @@
1
+ import { formatMCPUIString } from "../utils/format-string.js";
2
+ const CHART_DATA_TABLE_LABELS = {
3
+ series: "Series",
4
+ point: "Point",
5
+ label: "Label",
6
+ seriesName: "Series {n}",
7
+ x: "x",
8
+ y: "y",
9
+ r: "r"
10
+ };
1
11
  function tableCell(value) {
2
12
  if (value == null) return "";
3
13
  if (typeof value === "string" || typeof value === "number") return value;
@@ -11,37 +21,38 @@ function tableCell(value) {
11
21
  function isPoint(value) {
12
22
  return value !== null && typeof value === "object" && !Array.isArray(value) && ("x" in value || "y" in value || "r" in value);
13
23
  }
14
- function chartToDataTable(params) {
24
+ function chartToDataTable(params, labels) {
15
25
  var _a, _b;
26
+ const l = { ...CHART_DATA_TABLE_LABELS, ...labels };
16
27
  const datasets = ((_a = params.data) == null ? void 0 : _a.datasets) ?? [];
17
- const labels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
28
+ const dataLabels = ((_b = params.data) == null ? void 0 : _b.labels) ?? [];
18
29
  const pointData = params.type === "scatter" || params.type === "bubble" || datasets.some((dataset) => {
19
30
  var _a2;
20
31
  return (_a2 = dataset.data) == null ? void 0 : _a2.some(isPoint);
21
32
  });
22
33
  if (pointData) {
23
- const hasLabels = labels.length > 0;
34
+ const hasLabels = dataLabels.length > 0;
24
35
  const hasRadius = params.type === "bubble" || datasets.some((dataset) => {
25
36
  var _a2;
26
37
  return (_a2 = dataset.data) == null ? void 0 : _a2.some((value) => isPoint(value) && "r" in value);
27
38
  });
28
39
  const columns2 = [
29
- "Series",
30
- "Point",
31
- ...hasLabels ? ["Label"] : [],
32
- "x",
33
- "y",
34
- ...hasRadius ? ["r"] : []
40
+ l.series,
41
+ l.point,
42
+ ...hasLabels ? [l.label] : [],
43
+ l.x,
44
+ l.y,
45
+ ...hasRadius ? [l.r] : []
35
46
  ];
36
47
  const rows2 = [];
37
48
  datasets.forEach((dataset, datasetIndex) => {
38
- const series = dataset.label || `Series ${datasetIndex + 1}`;
49
+ const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });
39
50
  (dataset.data ?? []).forEach((value, pointIndex) => {
40
51
  const point = isPoint(value) ? value : { y: value };
41
52
  rows2.push([
42
53
  series,
43
54
  pointIndex + 1,
44
- ...hasLabels ? [tableCell(labels[pointIndex])] : [],
55
+ ...hasLabels ? [tableCell(dataLabels[pointIndex])] : [],
45
56
  tableCell(point.x),
46
57
  tableCell(point.y),
47
58
  ...hasRadius ? [tableCell(point.r)] : []
@@ -50,15 +61,24 @@ function chartToDataTable(params) {
50
61
  });
51
62
  return { columns: columns2, rows: rows2 };
52
63
  }
53
- const rowCount = Math.max(labels.length, ...datasets.map((dataset) => {
54
- var _a2;
55
- return ((_a2 = dataset.data) == null ? void 0 : _a2.length) ?? 0;
56
- }), 0);
57
- const columns = ["Label", ...datasets.map((dataset, index) => dataset.label || `Series ${index + 1}`)];
64
+ const rowCount = Math.max(
65
+ dataLabels.length,
66
+ ...datasets.map((dataset) => {
67
+ var _a2;
68
+ return ((_a2 = dataset.data) == null ? void 0 : _a2.length) ?? 0;
69
+ }),
70
+ 0
71
+ );
72
+ const columns = [
73
+ l.label,
74
+ ...datasets.map(
75
+ (dataset, index) => dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 })
76
+ )
77
+ ];
58
78
  const rows = [];
59
79
  for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {
60
80
  rows.push([
61
- tableCell(labels[rowIndex] ?? rowIndex + 1),
81
+ tableCell(dataLabels[rowIndex] ?? rowIndex + 1),
62
82
  ...datasets.map((dataset) => {
63
83
  var _a2;
64
84
  return tableCell((_a2 = dataset.data) == null ? void 0 : _a2[rowIndex]);
@@ -68,6 +88,7 @@ function chartToDataTable(params) {
68
88
  return { columns, rows };
69
89
  }
70
90
  export {
91
+ CHART_DATA_TABLE_LABELS,
71
92
  chartToDataTable
72
93
  };
73
94
  //# sourceMappingURL=chart-data-table.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"chart-data-table.js","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["export interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(params: ChartDataLike): ChartDataTable {\n const datasets = params.data?.datasets ?? [];\n const labels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = labels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n 'Series',\n 'Point',\n ...(hasLabels ? ['Label'] : []),\n 'x',\n 'y',\n ...(hasRadius ? ['r'] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || `Series ${datasetIndex + 1}`;\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(labels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n });\n });\n\n return { columns, rows };\n }\n\n const rowCount = Math.max(labels.length, ...datasets.map((dataset) => dataset.data?.length ?? 0), 0);\n const columns = ['Label', ...datasets.map((dataset, index) => dataset.label || `Series ${index + 1}`)];\n const rows: Array<Array<string | number>> = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(labels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n }\n\n return { columns, rows };\n}\n"],"names":["_a","columns","rows"],"mappings":"AAkBA,SAAS,UAAU,OAAiC;AAClD,MAAI,SAAS,KAAM,QAAO;AAC1B,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,SAAU,QAAO;AACnE,MAAI,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AACnD,MAAI;AACF,WAAO,KAAK,UAAU,KAAK;AAAA,EAC7B,QAAQ;AACN,WAAO,OAAO,KAAK;AAAA,EACrB;AACF;AAEA,SAAS,QAAQ,OAAkD;AACjE,SACE,UAAU,QACV,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,KAAK,MACnB,OAAO,SAAS,OAAO,SAAS,OAAO;AAE5C;AAOO,SAAS,iBAAiB,QAAuC;AAzBxE;AA0BE,QAAM,aAAW,YAAO,SAAP,mBAAa,aAAY,CAAA;AAC1C,QAAM,WAAS,YAAO,SAAP,mBAAa,WAAU,CAAA;AACtC,QAAM,YACJ,OAAO,SAAS,aAChB,OAAO,SAAS,YAChB,SAAS,KAAK,CAAC,YAAA;AA/BnB,QAAAA;AA+B+B,YAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,KAAK;AAAA,GAAQ;AAExD,MAAI,WAAW;AACb,UAAM,YAAY,OAAO,SAAS;AAClC,UAAM,YACJ,OAAO,SAAS,YAChB,SAAS,KAAK,CAAC,YAAA;AArCrB,UAAAA;AAqCiC,cAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,KAAK,CAAC,UAAU,QAAQ,KAAK,KAAK,OAAO;AAAA,KAAM;AAC1F,UAAMC,WAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA,GAAI,YAAY,CAAC,OAAO,IAAI,CAAA;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,GAAI,YAAY,CAAC,GAAG,IAAI,CAAA;AAAA,IAAC;AAE3B,UAAMC,QAAsC,CAAA;AAE5C,aAAS,QAAQ,CAAC,SAAS,iBAAiB;AAC1C,YAAM,SAAS,QAAQ,SAAS,UAAU,eAAe,CAAC;AAC1D,OAAC,QAAQ,QAAQ,CAAA,GAAI,QAAQ,CAAC,OAAO,eAAe;AAClD,cAAM,QAAQ,QAAQ,KAAK,IAAI,QAAQ,EAAE,GAAG,MAAA;AAC5CA,cAAK,KAAK;AAAA,UACR;AAAA,UACA,aAAa;AAAA,UACb,GAAI,YAAY,CAAC,UAAU,OAAO,UAAU,CAAC,CAAC,IAAI,CAAA;AAAA,UAClD,UAAU,MAAM,CAAC;AAAA,UACjB,UAAU,MAAM,CAAC;AAAA,UACjB,GAAI,YAAY,CAAC,UAAU,MAAM,CAAC,CAAC,IAAI,CAAA;AAAA,QAAC,CACzC;AAAA,MACH,CAAC;AAAA,IACH,CAAC;AAED,WAAO,EAAE,SAAAD,UAAS,MAAAC,MAAAA;AAAAA,EACpB;AAEA,QAAM,WAAW,KAAK,IAAI,OAAO,QAAQ,GAAG,SAAS,IAAI,CAAC;AAlE5D,QAAAF;AAkEwE,aAAAA,MAAA,QAAQ,SAAR,gBAAAA,IAAc,WAAU;AAAA,GAAC,GAAG,CAAC;AACnG,QAAM,UAAU,CAAC,SAAS,GAAG,SAAS,IAAI,CAAC,SAAS,UAAU,QAAQ,SAAS,UAAU,QAAQ,CAAC,EAAE,CAAC;AACrG,QAAM,OAAsC,CAAA;AAE5C,WAAS,WAAW,GAAG,WAAW,UAAU,YAAY,GAAG;AACzD,SAAK,KAAK;AAAA,MACR,UAAU,OAAO,QAAQ,KAAK,WAAW,CAAC;AAAA,MAC1C,GAAG,SAAS,IAAI,CAAC,YAAA;AAzEvB,YAAAA;AAyEmC,0BAAUA,MAAA,QAAQ,SAAR,gBAAAA,IAAe,SAAS;AAAA,OAAC;AAAA,IAAA,CACjE;AAAA,EACH;AAEA,SAAO,EAAE,SAAS,KAAA;AACpB;"}
1
+ {"version":3,"file":"chart-data-table.js","sources":["../../src/components/chart-data-table.ts"],"sourcesContent":["import { formatMCPUIString } from '../utils/format-string';\n\n/**\n * Column headers and series names of the accessible chart data table.\n *\n * `chartToDataTable` is a pure helper with no access to `MCPUIStrings`, so\n * the wording is injected: it takes an optional trailing `labels` partial,\n * which `ChartJSRenderer` feeds from `useMCPUIStrings()`. Left out, the\n * English defaults below apply — the pre-v6.20.0 behaviour.\n *\n * `x` / `y` / `r` stay untranslated on purpose: they are the Chart.js point\n * property NAMES the cells mirror, not prose.\n *\n * @since v6.20.0\n */\nexport interface ChartDataTableLabels {\n /** Series column of the per-point table. */\n series: string;\n /** Point-index column of the per-point table. */\n point: string;\n /** Label column (categorical table, and per-point table when labelled). */\n label: string;\n /** Fallback dataset name. Template — `{n}`. */\n seriesName: string;\n /** Chart.js point property names — machine tokens, rarely overridden. */\n x: string;\n y: string;\n r: string;\n}\n\n/** English defaults for {@link ChartDataTableLabels}. */\nexport const CHART_DATA_TABLE_LABELS: ChartDataTableLabels = {\n series: 'Series',\n point: 'Point',\n label: 'Label',\n seriesName: 'Series {n}',\n x: 'x',\n y: 'y',\n r: 'r',\n};\n\nexport interface ChartDataTable {\n columns: string[];\n rows: Array<Array<string | number>>;\n}\n\ninterface ChartDatasetLike {\n label?: string;\n data?: unknown[];\n}\n\nexport interface ChartDataLike {\n type?: string;\n data?: {\n labels?: Array<string | number>;\n datasets?: ChartDatasetLike[];\n };\n}\n\nfunction tableCell(value: unknown): string | number {\n if (value == null) return '';\n if (typeof value === 'string' || typeof value === 'number') return value;\n if (typeof value === 'boolean') return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nfunction isPoint(value: unknown): value is Record<string, unknown> {\n return (\n value !== null &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n ('x' in value || 'y' in value || 'r' in value)\n );\n}\n\n/**\n * Project Chart.js data into an accessible table without flattening point\n * coordinates. Categorical charts use a compact wide table; scatter, bubble,\n * and object-valued line charts use one row per point so x/y/r remain distinct.\n */\nexport function chartToDataTable(\n params: ChartDataLike,\n labels?: Partial<ChartDataTableLabels>\n): ChartDataTable {\n const l: ChartDataTableLabels = { ...CHART_DATA_TABLE_LABELS, ...labels };\n const datasets = params.data?.datasets ?? [];\n const dataLabels = params.data?.labels ?? [];\n const pointData =\n params.type === 'scatter' ||\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some(isPoint));\n\n if (pointData) {\n const hasLabels = dataLabels.length > 0;\n const hasRadius =\n params.type === 'bubble' ||\n datasets.some((dataset) => dataset.data?.some((value) => isPoint(value) && 'r' in value));\n const columns = [\n l.series,\n l.point,\n ...(hasLabels ? [l.label] : []),\n l.x,\n l.y,\n ...(hasRadius ? [l.r] : []),\n ];\n const rows: Array<Array<string | number>> = [];\n\n datasets.forEach((dataset, datasetIndex) => {\n const series = dataset.label || formatMCPUIString(l.seriesName, { n: datasetIndex + 1 });\n (dataset.data ?? []).forEach((value, pointIndex) => {\n const point = isPoint(value) ? value : { y: value };\n rows.push([\n series,\n pointIndex + 1,\n ...(hasLabels ? [tableCell(dataLabels[pointIndex])] : []),\n tableCell(point.x),\n tableCell(point.y),\n ...(hasRadius ? [tableCell(point.r)] : []),\n ]);\n });\n });\n\n return { columns, rows };\n }\n\n const rowCount = Math.max(\n dataLabels.length,\n ...datasets.map((dataset) => dataset.data?.length ?? 0),\n 0\n );\n const columns = [\n l.label,\n ...datasets.map(\n (dataset, index) => dataset.label || formatMCPUIString(l.seriesName, { n: index + 1 })\n ),\n ];\n const rows: Array<Array<string | number>> = [];\n\n for (let rowIndex = 0; rowIndex < rowCount; rowIndex += 1) {\n rows.push([\n tableCell(dataLabels[rowIndex] ?? rowIndex + 1),\n ...datasets.map((dataset) => tableCell(dataset.data?.[rowIndex])),\n ]);\n }\n\n return { columns, rows };\n}\n"],"names":["_a","columns","rows"],"mappings":"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"}