@seed-ship/mcp-ui-solid 6.19.0 → 6.20.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.
- package/CHANGELOG.md +532 -0
- package/README.md +798 -1
- package/dist/adapters/connector.cjs +15 -4
- package/dist/adapters/connector.cjs.map +1 -1
- package/dist/adapters/connector.d.ts +38 -0
- package/dist/adapters/connector.d.ts.map +1 -1
- package/dist/adapters/connector.js +15 -4
- package/dist/adapters/connector.js.map +1 -1
- package/dist/adapters/index.d.ts +4 -3
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/macro-run.cjs +25 -13
- package/dist/adapters/macro-run.cjs.map +1 -1
- package/dist/adapters/macro-run.d.ts +37 -2
- package/dist/adapters/macro-run.d.ts.map +1 -1
- package/dist/adapters/macro-run.js +25 -13
- package/dist/adapters/macro-run.js.map +1 -1
- package/dist/adapters.cjs +2 -0
- package/dist/adapters.cjs.map +1 -1
- package/dist/adapters.js +4 -2
- package/dist/components/ActionGroupRenderer.cjs +3 -1
- package/dist/components/ActionGroupRenderer.cjs.map +1 -1
- package/dist/components/ActionGroupRenderer.d.ts.map +1 -1
- package/dist/components/ActionGroupRenderer.js +3 -1
- package/dist/components/ActionGroupRenderer.js.map +1 -1
- package/dist/components/AgentCard.cjs +11 -8
- package/dist/components/AgentCard.cjs.map +1 -1
- package/dist/components/AgentCard.d.ts.map +1 -1
- package/dist/components/AgentCard.js +11 -8
- package/dist/components/AgentCard.js.map +1 -1
- package/dist/components/AgentHandoff.cjs +6 -1
- package/dist/components/AgentHandoff.cjs.map +1 -1
- package/dist/components/AgentHandoff.d.ts.map +1 -1
- package/dist/components/AgentHandoff.js +6 -1
- package/dist/components/AgentHandoff.js.map +1 -1
- package/dist/components/ArtifactRenderer.cjs +25 -6
- package/dist/components/ArtifactRenderer.cjs.map +1 -1
- package/dist/components/ArtifactRenderer.d.ts.map +1 -1
- package/dist/components/ArtifactRenderer.js +25 -6
- package/dist/components/ArtifactRenderer.js.map +1 -1
- package/dist/components/AutocompleteDropdown.cjs +30 -24
- package/dist/components/AutocompleteDropdown.cjs.map +1 -1
- package/dist/components/AutocompleteDropdown.d.ts.map +1 -1
- package/dist/components/AutocompleteDropdown.js +30 -24
- package/dist/components/AutocompleteDropdown.js.map +1 -1
- package/dist/components/AutocompleteFormField.cjs +3 -1
- package/dist/components/AutocompleteFormField.cjs.map +1 -1
- package/dist/components/AutocompleteFormField.d.ts.map +1 -1
- package/dist/components/AutocompleteFormField.js +4 -2
- package/dist/components/AutocompleteFormField.js.map +1 -1
- package/dist/components/BriefingDiff.cjs +45 -39
- package/dist/components/BriefingDiff.cjs.map +1 -1
- package/dist/components/BriefingDiff.d.ts.map +1 -1
- package/dist/components/BriefingDiff.js +45 -39
- package/dist/components/BriefingDiff.js.map +1 -1
- package/dist/components/CarouselRenderer.cjs +8 -2
- package/dist/components/CarouselRenderer.cjs.map +1 -1
- package/dist/components/CarouselRenderer.d.ts.map +1 -1
- package/dist/components/CarouselRenderer.js +8 -2
- package/dist/components/CarouselRenderer.js.map +1 -1
- package/dist/components/ChartJSRenderer.cjs +60 -36
- package/dist/components/ChartJSRenderer.cjs.map +1 -1
- package/dist/components/ChartJSRenderer.d.ts.map +1 -1
- package/dist/components/ChartJSRenderer.js +61 -37
- package/dist/components/ChartJSRenderer.js.map +1 -1
- package/dist/components/ChatPrompt.cjs +15 -9
- package/dist/components/ChatPrompt.cjs.map +1 -1
- package/dist/components/ChatPrompt.d.ts.map +1 -1
- package/dist/components/ChatPrompt.js +15 -9
- package/dist/components/ChatPrompt.js.map +1 -1
- package/dist/components/CodeBlockRenderer.cjs +34 -16
- package/dist/components/CodeBlockRenderer.cjs.map +1 -1
- package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
- package/dist/components/CodeBlockRenderer.js +34 -16
- package/dist/components/CodeBlockRenderer.js.map +1 -1
- package/dist/components/DataPreviewSection.cjs +91 -44
- package/dist/components/DataPreviewSection.cjs.map +1 -1
- package/dist/components/DataPreviewSection.d.ts.map +1 -1
- package/dist/components/DataPreviewSection.js +92 -45
- package/dist/components/DataPreviewSection.js.map +1 -1
- package/dist/components/DegradedFallback.cjs +20 -16
- package/dist/components/DegradedFallback.cjs.map +1 -1
- package/dist/components/DegradedFallback.d.ts.map +1 -1
- package/dist/components/DegradedFallback.js +20 -16
- package/dist/components/DegradedFallback.js.map +1 -1
- package/dist/components/FeedbackInline.cjs +19 -3
- package/dist/components/FeedbackInline.cjs.map +1 -1
- package/dist/components/FeedbackInline.js +19 -3
- package/dist/components/FeedbackInline.js.map +1 -1
- package/dist/components/FooterRenderer.cjs +21 -17
- package/dist/components/FooterRenderer.cjs.map +1 -1
- package/dist/components/FooterRenderer.d.ts.map +1 -1
- package/dist/components/FooterRenderer.js +21 -17
- package/dist/components/FooterRenderer.js.map +1 -1
- package/dist/components/FormFieldRenderer.cjs +116 -93
- package/dist/components/FormFieldRenderer.cjs.map +1 -1
- package/dist/components/FormFieldRenderer.d.ts.map +1 -1
- package/dist/components/FormFieldRenderer.js +116 -93
- package/dist/components/FormFieldRenderer.js.map +1 -1
- package/dist/components/FormRenderer.cjs +55 -31
- package/dist/components/FormRenderer.cjs.map +1 -1
- package/dist/components/FormRenderer.d.ts.map +1 -1
- package/dist/components/FormRenderer.js +55 -31
- package/dist/components/FormRenderer.js.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.cjs +20 -15
- package/dist/components/GenerativeUIErrorBoundary.cjs.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.d.ts.map +1 -1
- package/dist/components/GenerativeUIErrorBoundary.js +20 -15
- package/dist/components/GenerativeUIErrorBoundary.js.map +1 -1
- package/dist/components/GraphRenderer.cjs +56 -33
- package/dist/components/GraphRenderer.cjs.map +1 -1
- package/dist/components/GraphRenderer.d.ts.map +1 -1
- package/dist/components/GraphRenderer.js +56 -33
- package/dist/components/GraphRenderer.js.map +1 -1
- package/dist/components/ImageGalleryRenderer.cjs +13 -4
- package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
- package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
- package/dist/components/ImageGalleryRenderer.js +13 -4
- package/dist/components/ImageGalleryRenderer.js.map +1 -1
- package/dist/components/LightboxOverlay.cjs +16 -8
- package/dist/components/LightboxOverlay.cjs.map +1 -1
- package/dist/components/LightboxOverlay.d.ts.map +1 -1
- package/dist/components/LightboxOverlay.js +17 -9
- package/dist/components/LightboxOverlay.js.map +1 -1
- package/dist/components/MapRenderer.cjs +59 -29
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts +10 -2
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js +60 -30
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/ModalRenderer.cjs +4 -1
- package/dist/components/ModalRenderer.cjs.map +1 -1
- package/dist/components/ModalRenderer.d.ts.map +1 -1
- package/dist/components/ModalRenderer.js +5 -2
- package/dist/components/ModalRenderer.js.map +1 -1
- package/dist/components/ScratchpadPanel.cjs +578 -535
- package/dist/components/ScratchpadPanel.cjs.map +1 -1
- package/dist/components/ScratchpadPanel.d.ts.map +1 -1
- package/dist/components/ScratchpadPanel.js +578 -535
- package/dist/components/ScratchpadPanel.js.map +1 -1
- package/dist/components/StreamingUIRenderer.cjs +92 -28
- package/dist/components/StreamingUIRenderer.cjs.map +1 -1
- package/dist/components/StreamingUIRenderer.d.ts.map +1 -1
- package/dist/components/StreamingUIRenderer.js +92 -28
- package/dist/components/StreamingUIRenderer.js.map +1 -1
- package/dist/components/UIResourceRenderer.cjs +456 -363
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts +21 -0
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +458 -365
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/VerifiedText.cjs +39 -20
- package/dist/components/VerifiedText.cjs.map +1 -1
- package/dist/components/VerifiedText.d.ts +2 -1
- package/dist/components/VerifiedText.d.ts.map +1 -1
- package/dist/components/VerifiedText.js +39 -20
- package/dist/components/VerifiedText.js.map +1 -1
- package/dist/components/VideoRenderer.cjs +10 -5
- package/dist/components/VideoRenderer.cjs.map +1 -1
- package/dist/components/VideoRenderer.d.ts.map +1 -1
- package/dist/components/VideoRenderer.js +10 -5
- package/dist/components/VideoRenderer.js.map +1 -1
- package/dist/components/chart-data-table.cjs +38 -17
- package/dist/components/chart-data-table.cjs.map +1 -1
- package/dist/components/chart-data-table.d.ts +30 -1
- package/dist/components/chart-data-table.d.ts.map +1 -1
- package/dist/components/chart-data-table.js +38 -17
- package/dist/components/chart-data-table.js.map +1 -1
- package/dist/context/MCPActionContext.cjs +3 -1
- package/dist/context/MCPActionContext.cjs.map +1 -1
- package/dist/context/MCPActionContext.d.ts.map +1 -1
- package/dist/context/MCPActionContext.js +3 -1
- package/dist/context/MCPActionContext.js.map +1 -1
- package/dist/context/MCPUIStringsContext.cjs +285 -2
- package/dist/context/MCPUIStringsContext.cjs.map +1 -1
- package/dist/context/MCPUIStringsContext.d.ts +600 -3
- package/dist/context/MCPUIStringsContext.d.ts.map +1 -1
- package/dist/context/MCPUIStringsContext.js +285 -2
- package/dist/context/MCPUIStringsContext.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -2
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/useStreamingUI.cjs +28 -10
- package/dist/hooks/useStreamingUI.cjs.map +1 -1
- package/dist/hooks/useStreamingUI.d.ts +37 -0
- package/dist/hooks/useStreamingUI.d.ts.map +1 -1
- package/dist/hooks/useStreamingUI.js +28 -10
- package/dist/hooks/useStreamingUI.js.map +1 -1
- package/dist/hooks.cjs +1 -0
- package/dist/hooks.cjs.map +1 -1
- package/dist/hooks.js +2 -1
- package/dist/index.cjs +23 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -3
- package/dist/index.js.map +1 -1
- package/dist/services/validation.cjs +41 -16
- package/dist/services/validation.cjs.map +1 -1
- package/dist/services/validation.d.ts +47 -2
- package/dist/services/validation.d.ts.map +1 -1
- package/dist/services/validation.js +41 -16
- package/dist/services/validation.js.map +1 -1
- package/dist/utils/degraded-projections.cjs +37 -12
- package/dist/utils/degraded-projections.cjs.map +1 -1
- package/dist/utils/degraded-projections.d.ts +39 -3
- package/dist/utils/degraded-projections.d.ts.map +1 -1
- package/dist/utils/degraded-projections.js +37 -12
- package/dist/utils/degraded-projections.js.map +1 -1
- package/dist/utils/format-string.cjs +10 -0
- package/dist/utils/format-string.cjs.map +1 -0
- package/dist/utils/format-string.d.ts +26 -0
- package/dist/utils/format-string.d.ts.map +1 -0
- package/dist/utils/format-string.js +10 -0
- package/dist/utils/format-string.js.map +1 -0
- package/dist/validation.cjs +3 -0
- package/dist/validation.cjs.map +1 -1
- package/dist/validation.d.cts +2 -1
- package/dist/validation.d.ts +2 -1
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +4 -1
- package/package.json +1 -1
- package/src/adapters/connector.ts +58 -4
- package/src/adapters/index.ts +12 -2
- package/src/adapters/macro-run.ts +71 -11
- package/src/components/ActionGroupRenderer.tsx +3 -1
- package/src/components/AgentCard.tsx +27 -9
- package/src/components/AgentHandoff.tsx +4 -1
- package/src/components/ArtifactRenderer.tsx +17 -5
- package/src/components/AutocompleteDropdown.tsx +8 -6
- package/src/components/AutocompleteFormField.tsx +5 -1
- package/src/components/BriefingDiff.tsx +11 -3
- package/src/components/CarouselRenderer.tsx +4 -2
- package/src/components/ChartJSRenderer.tsx +18 -9
- package/src/components/ChatPrompt.tsx +13 -8
- package/src/components/CodeBlockRenderer.tsx +12 -10
- package/src/components/DataPreviewSection.tsx +92 -26
- package/src/components/DegradedFallback.tsx +4 -2
- package/src/components/FeedbackInline.tsx +2 -2
- package/src/components/FooterRenderer.tsx +3 -1
- package/src/components/FormFieldRenderer.tsx +34 -19
- package/src/components/FormRenderer.tsx +38 -10
- package/src/components/GenerativeUIErrorBoundary.tsx +8 -3
- package/src/components/GraphRenderer.tsx +31 -16
- package/src/components/ImageGalleryRenderer.tsx +8 -4
- package/src/components/LightboxOverlay.tsx +6 -4
- package/src/components/MapRenderer.tsx +57 -20
- package/src/components/ModalRenderer.tsx +3 -1
- package/src/components/ScratchpadPanel.tsx +95 -44
- package/src/components/StreamingUIRenderer.tsx +41 -11
- package/src/components/UIResourceRenderer.tsx +145 -63
- package/src/components/VerifiedText.tsx +19 -9
- package/src/components/VideoRenderer.tsx +6 -4
- package/src/components/chart-data-table.ts +68 -14
- package/src/context/MCPActionContext.tsx +4 -1
- package/src/context/MCPUIStringsContext.tsx +1004 -1
- package/src/hooks/index.ts +2 -1
- package/src/hooks/useStreamingUI.ts +64 -10
- package/src/index.ts +23 -0
- package/src/services/validation.ts +93 -16
- package/src/utils/degraded-projections.ts +75 -12
- package/src/utils/format-string.ts +33 -0
- package/src/validation.ts +5 -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":";;;;AAkDA,SAASA,cAAcC,KAAwB;AAM7C,QAAMC,eAAeD,IAAIE,MACvB,4EACF;AACA,MAAID,cAAc;AAChB,WAAO;AAAA,MAAEE,UAAU;AAAA,MAAWC,SAASH,aAAa,CAAC;AAAA,IAAA;AAAA,EACvD;AAKA,QAAMI,aAAaL,IAAIE,MAAM,mDAAmD;AAChF,MAAIG,YAAY;AACd,WAAO;AAAA,MAAEF,UAAU;AAAA,MAASC,SAASC,WAAW,CAAC;AAAA,IAAA;AAAA,EACnD;AAGA,SAAO;AAAA,IAAEF,UAAU;AAAA,EAAA;AACrB;AAEO,MAAMG,gBAAgDC,CAAAA,UAAU;AACrE,QAAMC,SAASA,MAAAA;;AAAMD,iBAAMC,YAAWD,WAAME,cAANF,mBAAiBC;AAAAA;AACvD,QAAME,aAAaC,YAAAA;AAEnB,QAAMC,YAAYC,WAAW,MAAA;;AAAMd,2BAAcS,kBAAAA,mBAAUR,QAAO,EAAE;AAAA,GAAC;AAErE,QAAMc,WAAWD,WAAW,MAAM;AAChC,UAAME,OAAOH,UAAAA;AACb,UAAMI,IAAIR,OAAAA;AAEV,QAAI,EAACQ,uBAAGhB,KAAK,QAAO;AAEpB,YAAQe,KAAKZ,UAAAA;AAAAA,MACX,KAAK,WAAW;AACd,cAAMc,WAAW,IAAIC,gBAAgB;AAAA,UACnCC,UAAUH,EAAEG,WAAW,MAAM;AAAA,UAC7BC,UAAUJ,EAAEI,aAAa,QAAQ,MAAM;AAAA,UACvCC,MAAML,EAAEK,OAAO,MAAM;AAAA,UACrBC,MAAMN,EAAEO,QAAQ,MAAM;AAAA,QAAA,CACvB;AACD,YAAIP,EAAEQ,WAAW;AACfP,mBAASQ,IAAI,SAASC,OAAOV,EAAEQ,SAAS,CAAC;AAAA,QAC3C;AAEA,eAAO,0CAA0CT,KAAKX,OAAO,IAAIa,QAAQ;AAAA,MAC3E;AAAA,MAEA,KAAK,SAAS;AACZ,cAAMU,UAAU,IAAIT,gBAAgB;AAAA,UAClCC,UAAUH,EAAEG,WAAW,MAAM;AAAA,UAC7BE,MAAML,EAAEK,OAAO,MAAM;AAAA,UACrBE,OAAOP,EAAEO,QAAQ,MAAM;AAAA,QAAA,CACxB;AACD,eAAO,kCAAkCR,KAAKX,OAAO,IAAIuB,OAAO;AAAA,MAClE;AAAA,MAEA;AACE,eAAO;AAAA,IAAA;AAAA,EAEb,CAAC;AAED,QAAMC,cAAcA,MAAM;;AACxB,aAAQpB,YAAAA,MAAAA,mBAAUqB,aAAAA;AAAAA,MAChB,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,eAAO;AAAA,IAAA;AAAA,EAEb;AAEA,QAAMC,mBAAmBA,CAACC,MAAa;;AACrC,UAAMC,QAAQ,IAAIC,MAAM,sBAAsB;AAC9CC,YAAQF,MAAM,gBAAgBD,CAAC;AAC/BxB,gBAAM4B,YAAN5B,+BAAgByB;AAAAA,EAClB;AAEA,SAAAI,gBACGC,mBAAiB;AAAA,IAAA,IAChBC,QAAK;;AAAA,eAAE9B,YAAAA,MAAAA,mBAAU8B,UAAS;AAAA,IAAO;AAAA,IAAA,IACjCC,WAAQ;;AAAA,eAAE/B,YAAAA,MAAAA,mBAAUR,QAAO;AAAA,IAAE;AAAA,IAC7BwC,WAAS;AAAA,IAAA,IACTC,iBAAc;AAAA,aAAElC,MAAMkC;AAAAA,IAAc;AAAA,IAAA,IAAAC,WAAA;AAAA,UAAAC,OAAAC,eAAAC,OAAA,GAAAC,QAAAH,KAAAI,YAAA,CAAAC,OAAAC,IAAA,IAAAC,cAAAJ,MAAAK,WAAA,GAAAC,QAAAJ,MAAAG,aAAAE,QAAAD,MAAAD,aAAA,CAAAG,OAAAC,KAAA,IAAAL,cAAAG,MAAAF,WAAA;AAAAK,aAAAb,MAAAP,gBAMnCqB,MAAI;AAAA,QAAA,IAACC,OAAI;;AAAA,kBAAElD,kBAAAA,mBAAU8B;AAAAA,QAAK;AAAA,QAAA,IAAAI,WAAA;AAAA,cAAAiB,QAAAf,eAAAgB,MAAA,GAAAC,QAAAF,MAAAZ;AAAAS,iBAAAK,OAAA,MAE0CrD,OAAAA,EAAU8B,KAAK;AAAA,iBAAAqB;AAAAA,QAAA;AAAA,MAAA,CAAA,GAAAX,OAAAC,IAAA;AAAAO,aAAAJ,OAAAhB,gBAMjFqB,MAAI;AAAA,QAAA,IACHC,OAAI;AAAA,iBAAE5C,SAAAA;AAAAA,QAAU;AAAA,QAAA,IAChBgD,WAAQ;AAAA;AAAA;AAAA,aACN,MAAA;AAAA,kBAAAC,SAAAnB,eAAAoB,OAAA;AAAAD,qBAAAE,iBAAA,SAUWnC,gBAAgB;AAAAoC,qBAAAC,CAAAA,QAAA;;AAAA,oBAAAC,QARpB5D,kBAAAA,mBAAUR,KAAGqE,QACV7D,YAAAA,MAAAA,mBAAU8D,QAAMC,QACd/D,kBAAAA,mBAAUW,UAAQqD,SAClBhE,YAAAA,MAAAA,mBAAUY,cAAa,OAAKqD,QAChCjE,kBAAAA,mBAAUa,MAAIqD,QACblE,YAAAA,MAAAA,mBAAUe;AAAK6C,yBAAAD,IAAApC,KAAA4C,aAAAZ,QAAA,OAAAI,IAAApC,IAAAqC,IAAA;AAAAC,yBAAAF,IAAAS,KAAAD,aAAAZ,QAAA,UAAAI,IAAAS,IAAAP,IAAA;AAAAE,yBAAAJ,IAAAU,KAAAC,YAAAf,QAAA,YAAAI,IAAAU,IAAAN,IAAA;AAAAC,yBAAAL,IAAAY,KAAAD,YAAAf,QAAA,YAAAI,IAAAY,IAAAP,IAAA;AAAAC,yBAAAN,IAAAa,KAAAF,YAAAf,QAAA,QAAAI,IAAAa,IAAAP,IAAA;AAAAC,yBAAAP,IAAAc,KAAAH,YAAAf,QAAA,SAAAI,IAAAc,IAAAP,IAAA;AAAA,uBAAAP;AAAAA,cAAA,GAAA;AAAA,gBAAApC,GAAAmD;AAAAA,gBAAAN,GAAAM;AAAAA,gBAAAL,GAAAK;AAAAA,gBAAAH,GAAAG;AAAAA,gBAAAF,GAAAE;AAAAA,gBAAAD,GAAAC;AAAAA,cAAAA,CAAA;AAAA,qBAAAnB;AAAAA,YAAA,GAAA;AAAA;AAAA,QAAA;AAAA,QAAA,IAAArB,WAAA;AAAA,cAAAyC,QAAAvC,eAAAwC,OAAA;AAAAlB,iBAAAC,CAAAA,QAAA;;AAAA,gBAAAkB,MAYnBvE,SAAAA,GAAWwE,SACT9E,YAAAA,MAAAA,mBAAU8B,UAAS;AAAO+C,oBAAAlB,IAAApC,KAAA4C,aAAAQ,OAAA,OAAAhB,IAAApC,IAAAsD,GAAA;AAAAC,qBAAAnB,IAAAS,KAAAD,aAAAQ,OAAA,SAAAhB,IAAAS,IAAAU,IAAA;AAAA,mBAAAnB;AAAAA,UAAA,GAAA;AAAA,YAAApC,GAAAmD;AAAAA,YAAAN,GAAAM;AAAAA,UAAAA,CAAA;AAAA,iBAAAC;AAAAA,QAAA;AAAA,MAAA,CAAA,CAAA;AAAA3B,aAAAb,MAAAP,gBAUtCqB,MAAI;AAAA,QAAA,IAACC,OAAI;;AAAA,kBAAElD,kBAAAA,mBAAU+E;AAAAA,QAAO;AAAA,QAAA,IAAA7C,WAAA;AAAA,cAAA8C,QAAA5C,eAAA6C,OAAA,GAAAC,QAAAF,MAAAzC;AAAAS,iBAAAkC,OAAA,MAE4BlF,OAAAA,EAAU+E,OAAO;AAAA,iBAAAC;AAAAA,QAAA;AAAA,MAAA,CAAA,GAAAlC,OAAAC,KAAA;AAAAW,aAAAC,CAAAA,QAAA;AAAA,YAAAwB,OA/ChE,qHACVjF,WAAAA,IAAe,iCAAiC,EAAE,IAClDkF,OASY,qBAAqBlF,WAAAA,IAAe,mBAAmBkB,aAAa;AAAE+D,iBAAAxB,IAAApC,KAAA8D,UAAAlD,MAAAwB,IAAApC,IAAA4D,IAAA;AAAAC,iBAAAzB,IAAAS,KAAAiB,UAAAzC,OAAAe,IAAAS,IAAAgB,IAAA;AAAA,eAAAzB;AAAAA,MAAA,GAAA;AAAA,QAAApC,GAAAmD;AAAAA,QAAAN,GAAAM;AAAAA,MAAAA,CAAA;AAAA,aAAAvC;AAAAA,IAAA;AAAA,EAAA,CAAA;AA0CxF;AAKO,SAASmD,oBAAoB9F,KAAsB;AACxD,QAAMe,OAAOhB,cAAcC,GAAG;AAC9B,SAAOe,KAAKZ,aAAa,YAAYH,IAAIE,MAAM,wBAAwB,MAAM;AAC/E;AAKO,SAAS6F,iBAAiB/F,KAA4B;AAC3D,SAAOD,cAAcC,GAAG,EAAEG;AAC5B;"}
|
|
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'\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 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 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","strings","useMCPUIStrings","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","_$insert","Show","when","_el$2","_tmpl$","_el$3","fallback","_el$10","_tmpl$5","_el$11","_el$12","_el$13","_co$3","addEventListener","videoUnsupported","_$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,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
|
|
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 =
|
|
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
|
-
|
|
32
|
-
|
|
33
|
-
...hasLabels ? [
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
...hasRadius ? [
|
|
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 ||
|
|
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(
|
|
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(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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(
|
|
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":["
|
|
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":"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"}
|
|
@@ -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":"
|
|
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
|
|
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 =
|
|
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
|
-
|
|
30
|
-
|
|
31
|
-
...hasLabels ? [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
...hasRadius ? [
|
|
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 ||
|
|
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(
|
|
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(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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(
|
|
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":["
|
|
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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"}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const web = require("solid-js/web");
|
|
4
4
|
const solidJs = require("solid-js");
|
|
5
|
+
const MCPUIStringsContext = require("./MCPUIStringsContext.cjs");
|
|
5
6
|
const MCPActionContext = solidJs.createContext();
|
|
6
7
|
const defaultExecutor = async (request) => {
|
|
7
8
|
return new Promise((resolve) => {
|
|
@@ -55,6 +56,7 @@ const defaultExecutor = async (request) => {
|
|
|
55
56
|
});
|
|
56
57
|
};
|
|
57
58
|
const MCPActionProvider = (props) => {
|
|
59
|
+
const strings = MCPUIStringsContext.useMCPUIStrings();
|
|
58
60
|
const [isExecuting, setIsExecuting] = solidJs.createSignal(false);
|
|
59
61
|
const [lastResult, setLastResult] = solidJs.createSignal();
|
|
60
62
|
const [spaceIds, _setSpaceIds] = solidJs.createSignal(props.spaceIds || []);
|
|
@@ -86,7 +88,7 @@ const MCPActionProvider = (props) => {
|
|
|
86
88
|
} catch (error) {
|
|
87
89
|
const errorResult = {
|
|
88
90
|
success: false,
|
|
89
|
-
error: error instanceof Error ? error.message :
|
|
91
|
+
error: error instanceof Error ? error.message : strings.errorUnknown,
|
|
90
92
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
91
93
|
toolName: request.toolName
|
|
92
94
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MCPActionContext.cjs","sources":["../../src/context/MCPActionContext.tsx"],"sourcesContent":["/**\n * MCPActionContext - Context provider for MCP action execution\n * Phase 5.0: Quick Wins - Replaces CustomEvent with typed context for Mastra integration\n */\n\nimport { createContext, createSignal, useContext, ParentComponent, Accessor } from 'solid-js'\n\n/**\n * Action request payload\n */\nexport interface ActionRequest {\n /**\n * MCP tool name to execute. For a `submit` action with no associated\n * tool, renderers pass the sentinel `'submit'` — branch on `action`,\n * not on `toolName`, to tell a submit apart from a tool call.\n */\n toolName: string\n\n /**\n * Tool parameters\n */\n params?: Record<string, any>\n\n /**\n * Optional space IDs for multi-space context\n */\n spaceIds?: string[]\n\n /**\n * Optional macro ID for template execution\n */\n macroId?: string\n\n /**\n * Action kind (v6.6.1). Lets a host `executor` tell a tool call apart\n * from a form-style `submit`. Absent ⇒ treat as `'tool-call'` (backward\n * compatible — every pre-v6.6.1 request omits it).\n *\n * A `submit` action carries its payload in `params` (e.g. `submit_url`,\n * `connector_id`, `feedback_value`) and **must NOT** be executed as a\n * tool call — the host routes it (e.g. POST to `params.submit_url`).\n */\n action?: 'tool-call' | 'submit' | 'link'\n}\n\n/**\n * Action result from execution\n */\nexport interface ActionResult {\n /**\n * Whether the action was successful\n */\n success: boolean\n\n /**\n * Result data (if successful)\n */\n data?: any\n\n /**\n * Error message (if failed)\n */\n error?: string\n\n /**\n * Execution timestamp\n */\n timestamp: string\n\n /**\n * Tool that was executed\n */\n toolName: string\n}\n\n/**\n * Context value interface\n */\nexport interface MCPActionContextValue {\n /**\n * Execute an MCP action\n */\n executeAction: (request: ActionRequest) => Promise<ActionResult>\n\n /**\n * Currently available tools (from MCP server)\n */\n availableTools: Accessor<string[]>\n\n /**\n * Space IDs in current context\n */\n spaceIds: Accessor<string[]>\n\n /**\n * Current macro ID (if executing within a template)\n */\n macroId: Accessor<string | undefined>\n\n /**\n * Whether an action is currently executing\n */\n isExecuting: Accessor<boolean>\n\n /**\n * Last action result\n */\n lastResult: Accessor<ActionResult | undefined>\n}\n\n/**\n * Props for MCPActionProvider\n */\nexport interface MCPActionProviderProps {\n /**\n * Space IDs for multi-space queries\n */\n spaceIds?: string[]\n\n /**\n * Macro ID when executing within a template\n */\n macroId?: string\n\n /**\n * Available MCP tools\n */\n availableTools?: string[]\n\n /**\n * Callback for action execution (for audit logging)\n */\n onAction?: (request: ActionRequest, result: ActionResult) => void\n\n /**\n * Callback for webhook events (n8n, Zapier integration)\n */\n onWebhook?: (event: { type: string; payload: any }) => void\n\n /**\n * Custom action executor (override default)\n */\n executor?: (request: ActionRequest) => Promise<ActionResult>\n}\n\n// Create the context with undefined default\nconst MCPActionContext = createContext<MCPActionContextValue>()\n\n/**\n * Default action executor using CustomEvent fallback\n * This maintains backward compatibility while allowing Context-based usage\n */\nconst defaultExecutor = async (request: ActionRequest): Promise<ActionResult> => {\n return new Promise((resolve) => {\n const timestamp = new Date().toISOString()\n\n // Dispatch CustomEvent for backward compatibility with existing listeners\n if (typeof window !== 'undefined') {\n const event = new CustomEvent('mcp-action', {\n detail: {\n toolName: request.toolName,\n params: request.params || {},\n spaceIds: request.spaceIds,\n macroId: request.macroId,\n // v6.6.1 — action kind so a window-level listener can route a\n // `submit` (POST to params.submit_url) vs a tool call.\n action: request.action ?? 'tool-call',\n },\n bubbles: true,\n })\n\n // Listen for response event\n const responseHandler = (e: Event) => {\n const customEvent = e as CustomEvent\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: customEvent.detail?.success ?? true,\n data: customEvent.detail?.data,\n error: customEvent.detail?.error,\n timestamp,\n toolName: request.toolName,\n })\n }\n\n window.addEventListener('mcp-action-response', responseHandler)\n window.dispatchEvent(event)\n\n // Timeout fallback - resolve as success if no response in 100ms\n // (indicates no listener, action was dispatched)\n setTimeout(() => {\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: true,\n data: { dispatched: true },\n timestamp,\n toolName: request.toolName,\n })\n }, 100)\n } else {\n // Server-side: return immediately\n resolve({\n success: false,\n error: 'Actions not available server-side',\n timestamp,\n toolName: request.toolName,\n })\n }\n })\n}\n\n/**\n * MCPActionProvider - Provides action execution context to child components\n *\n * @example\n * ```tsx\n * <MCPActionProvider\n * spaceIds={['space-123']}\n * macroId=\"sales_overview\"\n * onAction={(req, res) => audit(req, res)}\n * >\n * <UIResourceRenderer layout={layout} />\n * </MCPActionProvider>\n * ```\n */\nexport const MCPActionProvider: ParentComponent<MCPActionProviderProps> = (props) => {\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [spaceIds, _setSpaceIds] = createSignal<string[]>(props.spaceIds || [])\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [macroId, _setMacroId] = createSignal<string | undefined>(props.macroId)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [availableTools, _setAvailableTools] = createSignal<string[]>(props.availableTools || [])\n\n // Update signals when props change\n // Note: This is a simple approach; for more complex scenarios, consider createEffect\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n\n try {\n // Enrich request with context\n const enrichedRequest: ActionRequest = {\n ...request,\n spaceIds: request.spaceIds || spaceIds(),\n macroId: request.macroId || macroId(),\n }\n\n // Execute using custom executor or default\n const executor = props.executor || defaultExecutor\n const result = await executor(enrichedRequest)\n\n setLastResult(result)\n\n // Call audit callback if provided\n props.onAction?.(enrichedRequest, result)\n\n // Trigger webhook if provided and action was successful\n if (result.success && props.onWebhook) {\n props.onWebhook({\n type: 'action-completed',\n payload: {\n request: enrichedRequest,\n result,\n },\n })\n }\n\n return result\n } catch (error) {\n const errorResult: ActionResult = {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n timestamp: new Date().toISOString(),\n toolName: request.toolName,\n }\n\n setLastResult(errorResult)\n props.onAction?.(request, errorResult)\n\n return errorResult\n } finally {\n setIsExecuting(false)\n }\n }\n\n const contextValue: MCPActionContextValue = {\n executeAction,\n availableTools,\n spaceIds,\n macroId,\n isExecuting,\n lastResult,\n }\n\n return (\n <MCPActionContext.Provider value={contextValue}>\n {props.children}\n </MCPActionContext.Provider>\n )\n}\n\n/**\n * Hook to access MCP action context\n * Throws if used outside of MCPActionProvider\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPAction()\n *\n * const handleClick = async () => {\n * const result = await executeAction({\n * toolName: 'search.hub',\n * params: { query: 'revenue Q4' },\n * })\n * }\n * ```\n */\nexport function useMCPAction(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n if (!context) {\n throw new Error('useMCPAction must be used within an MCPActionProvider')\n }\n return context\n}\n\n/**\n * Hook to access MCP action context with fallback for components\n * outside of provider (uses CustomEvent fallback)\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPActionSafe()\n * // Works even without MCPActionProvider\n * ```\n */\nexport function useMCPActionSafe(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n\n if (context) {\n return context\n }\n\n // Fallback implementation for components outside provider\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n try {\n const result = await defaultExecutor(request)\n setLastResult(result)\n return result\n } finally {\n setIsExecuting(false)\n }\n }\n\n return {\n executeAction,\n availableTools: () => [],\n spaceIds: () => [],\n macroId: () => undefined,\n isExecuting,\n lastResult,\n }\n}\n\nexport { MCPActionContext }\n"],"names":["MCPActionContext","createContext","defaultExecutor","request","Promise","resolve","timestamp","Date","toISOString","window","event","CustomEvent","detail","toolName","params","spaceIds","macroId","action","bubbles","responseHandler","e","customEvent","removeEventListener","success","data","error","addEventListener","dispatchEvent","setTimeout","dispatched","MCPActionProvider","props","isExecuting","setIsExecuting","createSignal","lastResult","setLastResult","_setSpaceIds","_setMacroId","availableTools","_setAvailableTools","executeAction","enrichedRequest","executor","result","onAction","onWebhook","type","payload","errorResult","Error","message","contextValue","_$createComponent","Provider","value","children","useMCPAction","context","useContext","useMCPActionSafe","undefined"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"MCPActionContext.cjs","sources":["../../src/context/MCPActionContext.tsx"],"sourcesContent":["/**\n * MCPActionContext - Context provider for MCP action execution\n * Phase 5.0: Quick Wins - Replaces CustomEvent with typed context for Mastra integration\n */\n\nimport { createContext, createSignal, useContext, ParentComponent, Accessor } from 'solid-js'\nimport { useMCPUIStrings } from './MCPUIStringsContext'\n\n/**\n * Action request payload\n */\nexport interface ActionRequest {\n /**\n * MCP tool name to execute. For a `submit` action with no associated\n * tool, renderers pass the sentinel `'submit'` — branch on `action`,\n * not on `toolName`, to tell a submit apart from a tool call.\n */\n toolName: string\n\n /**\n * Tool parameters\n */\n params?: Record<string, any>\n\n /**\n * Optional space IDs for multi-space context\n */\n spaceIds?: string[]\n\n /**\n * Optional macro ID for template execution\n */\n macroId?: string\n\n /**\n * Action kind (v6.6.1). Lets a host `executor` tell a tool call apart\n * from a form-style `submit`. Absent ⇒ treat as `'tool-call'` (backward\n * compatible — every pre-v6.6.1 request omits it).\n *\n * A `submit` action carries its payload in `params` (e.g. `submit_url`,\n * `connector_id`, `feedback_value`) and **must NOT** be executed as a\n * tool call — the host routes it (e.g. POST to `params.submit_url`).\n */\n action?: 'tool-call' | 'submit' | 'link'\n}\n\n/**\n * Action result from execution\n */\nexport interface ActionResult {\n /**\n * Whether the action was successful\n */\n success: boolean\n\n /**\n * Result data (if successful)\n */\n data?: any\n\n /**\n * Error message (if failed)\n */\n error?: string\n\n /**\n * Execution timestamp\n */\n timestamp: string\n\n /**\n * Tool that was executed\n */\n toolName: string\n}\n\n/**\n * Context value interface\n */\nexport interface MCPActionContextValue {\n /**\n * Execute an MCP action\n */\n executeAction: (request: ActionRequest) => Promise<ActionResult>\n\n /**\n * Currently available tools (from MCP server)\n */\n availableTools: Accessor<string[]>\n\n /**\n * Space IDs in current context\n */\n spaceIds: Accessor<string[]>\n\n /**\n * Current macro ID (if executing within a template)\n */\n macroId: Accessor<string | undefined>\n\n /**\n * Whether an action is currently executing\n */\n isExecuting: Accessor<boolean>\n\n /**\n * Last action result\n */\n lastResult: Accessor<ActionResult | undefined>\n}\n\n/**\n * Props for MCPActionProvider\n */\nexport interface MCPActionProviderProps {\n /**\n * Space IDs for multi-space queries\n */\n spaceIds?: string[]\n\n /**\n * Macro ID when executing within a template\n */\n macroId?: string\n\n /**\n * Available MCP tools\n */\n availableTools?: string[]\n\n /**\n * Callback for action execution (for audit logging)\n */\n onAction?: (request: ActionRequest, result: ActionResult) => void\n\n /**\n * Callback for webhook events (n8n, Zapier integration)\n */\n onWebhook?: (event: { type: string; payload: any }) => void\n\n /**\n * Custom action executor (override default)\n */\n executor?: (request: ActionRequest) => Promise<ActionResult>\n}\n\n// Create the context with undefined default\nconst MCPActionContext = createContext<MCPActionContextValue>()\n\n/**\n * Default action executor using CustomEvent fallback\n * This maintains backward compatibility while allowing Context-based usage\n */\nconst defaultExecutor = async (request: ActionRequest): Promise<ActionResult> => {\n return new Promise((resolve) => {\n const timestamp = new Date().toISOString()\n\n // Dispatch CustomEvent for backward compatibility with existing listeners\n if (typeof window !== 'undefined') {\n const event = new CustomEvent('mcp-action', {\n detail: {\n toolName: request.toolName,\n params: request.params || {},\n spaceIds: request.spaceIds,\n macroId: request.macroId,\n // v6.6.1 — action kind so a window-level listener can route a\n // `submit` (POST to params.submit_url) vs a tool call.\n action: request.action ?? 'tool-call',\n },\n bubbles: true,\n })\n\n // Listen for response event\n const responseHandler = (e: Event) => {\n const customEvent = e as CustomEvent\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: customEvent.detail?.success ?? true,\n data: customEvent.detail?.data,\n error: customEvent.detail?.error,\n timestamp,\n toolName: request.toolName,\n })\n }\n\n window.addEventListener('mcp-action-response', responseHandler)\n window.dispatchEvent(event)\n\n // Timeout fallback - resolve as success if no response in 100ms\n // (indicates no listener, action was dispatched)\n setTimeout(() => {\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: true,\n data: { dispatched: true },\n timestamp,\n toolName: request.toolName,\n })\n }, 100)\n } else {\n // Server-side: return immediately\n resolve({\n success: false,\n error: 'Actions not available server-side',\n timestamp,\n toolName: request.toolName,\n })\n }\n })\n}\n\n/**\n * MCPActionProvider - Provides action execution context to child components\n *\n * @example\n * ```tsx\n * <MCPActionProvider\n * spaceIds={['space-123']}\n * macroId=\"sales_overview\"\n * onAction={(req, res) => audit(req, res)}\n * >\n * <UIResourceRenderer layout={layout} />\n * </MCPActionProvider>\n * ```\n */\nexport const MCPActionProvider: ParentComponent<MCPActionProviderProps> = (props) => {\n // The error of a failed action can be rendered by FormRenderer.\n const strings = useMCPUIStrings()\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [spaceIds, _setSpaceIds] = createSignal<string[]>(props.spaceIds || [])\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [macroId, _setMacroId] = createSignal<string | undefined>(props.macroId)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [availableTools, _setAvailableTools] = createSignal<string[]>(props.availableTools || [])\n\n // Update signals when props change\n // Note: This is a simple approach; for more complex scenarios, consider createEffect\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n\n try {\n // Enrich request with context\n const enrichedRequest: ActionRequest = {\n ...request,\n spaceIds: request.spaceIds || spaceIds(),\n macroId: request.macroId || macroId(),\n }\n\n // Execute using custom executor or default\n const executor = props.executor || defaultExecutor\n const result = await executor(enrichedRequest)\n\n setLastResult(result)\n\n // Call audit callback if provided\n props.onAction?.(enrichedRequest, result)\n\n // Trigger webhook if provided and action was successful\n if (result.success && props.onWebhook) {\n props.onWebhook({\n type: 'action-completed',\n payload: {\n request: enrichedRequest,\n result,\n },\n })\n }\n\n return result\n } catch (error) {\n const errorResult: ActionResult = {\n success: false,\n error: error instanceof Error ? error.message : strings.errorUnknown,\n timestamp: new Date().toISOString(),\n toolName: request.toolName,\n }\n\n setLastResult(errorResult)\n props.onAction?.(request, errorResult)\n\n return errorResult\n } finally {\n setIsExecuting(false)\n }\n }\n\n const contextValue: MCPActionContextValue = {\n executeAction,\n availableTools,\n spaceIds,\n macroId,\n isExecuting,\n lastResult,\n }\n\n return (\n <MCPActionContext.Provider value={contextValue}>\n {props.children}\n </MCPActionContext.Provider>\n )\n}\n\n/**\n * Hook to access MCP action context\n * Throws if used outside of MCPActionProvider\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPAction()\n *\n * const handleClick = async () => {\n * const result = await executeAction({\n * toolName: 'search.hub',\n * params: { query: 'revenue Q4' },\n * })\n * }\n * ```\n */\nexport function useMCPAction(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n if (!context) {\n throw new Error('useMCPAction must be used within an MCPActionProvider')\n }\n return context\n}\n\n/**\n * Hook to access MCP action context with fallback for components\n * outside of provider (uses CustomEvent fallback)\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPActionSafe()\n * // Works even without MCPActionProvider\n * ```\n */\nexport function useMCPActionSafe(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n\n if (context) {\n return context\n }\n\n // Fallback implementation for components outside provider\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n try {\n const result = await defaultExecutor(request)\n setLastResult(result)\n return result\n } finally {\n setIsExecuting(false)\n }\n }\n\n return {\n executeAction,\n availableTools: () => [],\n spaceIds: () => [],\n macroId: () => undefined,\n isExecuting,\n lastResult,\n }\n}\n\nexport { MCPActionContext }\n"],"names":["MCPActionContext","createContext","defaultExecutor","request","Promise","resolve","timestamp","Date","toISOString","window","event","CustomEvent","detail","toolName","params","spaceIds","macroId","action","bubbles","responseHandler","e","customEvent","removeEventListener","success","data","error","addEventListener","dispatchEvent","setTimeout","dispatched","MCPActionProvider","props","strings","useMCPUIStrings","isExecuting","setIsExecuting","createSignal","lastResult","setLastResult","_setSpaceIds","_setMacroId","availableTools","_setAvailableTools","executeAction","enrichedRequest","executor","result","onAction","onWebhook","type","payload","errorResult","Error","message","errorUnknown","contextValue","_$createComponent","Provider","value","children","useMCPAction","context","useContext","useMCPActionSafe","undefined"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MCPActionContext.d.ts","sourceRoot":"","sources":["../../src/context/MCPActionContext.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA2C,eAAe,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"MCPActionContext.d.ts","sourceRoot":"","sources":["../../src/context/MCPActionContext.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAA2C,eAAe,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAA;AAG7F;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;IAE5B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IAEnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,WAAW,GAAG,QAAQ,GAAG,MAAM,CAAA;CACzC;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,OAAO,EAAE,OAAO,CAAA;IAEhB;;OAEG;IACH,IAAI,CAAC,EAAE,GAAG,CAAA;IAEV;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd;;OAEG;IACH,SAAS,EAAE,MAAM,CAAA;IAEjB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;OAEG;IACH,aAAa,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;IAEhE;;OAEG;IACH,cAAc,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAElC;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAE5B;;OAEG;IACH,OAAO,EAAE,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;IAErC;;OAEG;IACH,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAA;IAE9B;;OAEG;IACH,UAAU,EAAE,QAAQ,CAAC,YAAY,GAAG,SAAS,CAAC,CAAA;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;IAEnB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;IAEhB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAA;IAEzB;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,YAAY,KAAK,IAAI,CAAA;IAEjE;;OAEG;IACH,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,GAAG,CAAA;KAAE,KAAK,IAAI,CAAA;IAE3D;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,KAAK,OAAO,CAAC,YAAY,CAAC,CAAA;CAC7D;AAGD,QAAA,MAAM,gBAAgB,+DAAyC,CAAA;AAgE/D;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB,EAAE,eAAe,CAAC,sBAAsB,CA8ErE,CAAA;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,IAAI,qBAAqB,CAMpD;AAED;;;;;;;;;GASG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CA8BxD;AAED,OAAO,EAAE,gBAAgB,EAAE,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createComponent } from "solid-js/web";
|
|
2
2
|
import { createContext, createSignal, useContext } from "solid-js";
|
|
3
|
+
import { useMCPUIStrings } from "./MCPUIStringsContext.js";
|
|
3
4
|
const MCPActionContext = createContext();
|
|
4
5
|
const defaultExecutor = async (request) => {
|
|
5
6
|
return new Promise((resolve) => {
|
|
@@ -53,6 +54,7 @@ const defaultExecutor = async (request) => {
|
|
|
53
54
|
});
|
|
54
55
|
};
|
|
55
56
|
const MCPActionProvider = (props) => {
|
|
57
|
+
const strings = useMCPUIStrings();
|
|
56
58
|
const [isExecuting, setIsExecuting] = createSignal(false);
|
|
57
59
|
const [lastResult, setLastResult] = createSignal();
|
|
58
60
|
const [spaceIds, _setSpaceIds] = createSignal(props.spaceIds || []);
|
|
@@ -84,7 +86,7 @@ const MCPActionProvider = (props) => {
|
|
|
84
86
|
} catch (error) {
|
|
85
87
|
const errorResult = {
|
|
86
88
|
success: false,
|
|
87
|
-
error: error instanceof Error ? error.message :
|
|
89
|
+
error: error instanceof Error ? error.message : strings.errorUnknown,
|
|
88
90
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
89
91
|
toolName: request.toolName
|
|
90
92
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MCPActionContext.js","sources":["../../src/context/MCPActionContext.tsx"],"sourcesContent":["/**\n * MCPActionContext - Context provider for MCP action execution\n * Phase 5.0: Quick Wins - Replaces CustomEvent with typed context for Mastra integration\n */\n\nimport { createContext, createSignal, useContext, ParentComponent, Accessor } from 'solid-js'\n\n/**\n * Action request payload\n */\nexport interface ActionRequest {\n /**\n * MCP tool name to execute. For a `submit` action with no associated\n * tool, renderers pass the sentinel `'submit'` — branch on `action`,\n * not on `toolName`, to tell a submit apart from a tool call.\n */\n toolName: string\n\n /**\n * Tool parameters\n */\n params?: Record<string, any>\n\n /**\n * Optional space IDs for multi-space context\n */\n spaceIds?: string[]\n\n /**\n * Optional macro ID for template execution\n */\n macroId?: string\n\n /**\n * Action kind (v6.6.1). Lets a host `executor` tell a tool call apart\n * from a form-style `submit`. Absent ⇒ treat as `'tool-call'` (backward\n * compatible — every pre-v6.6.1 request omits it).\n *\n * A `submit` action carries its payload in `params` (e.g. `submit_url`,\n * `connector_id`, `feedback_value`) and **must NOT** be executed as a\n * tool call — the host routes it (e.g. POST to `params.submit_url`).\n */\n action?: 'tool-call' | 'submit' | 'link'\n}\n\n/**\n * Action result from execution\n */\nexport interface ActionResult {\n /**\n * Whether the action was successful\n */\n success: boolean\n\n /**\n * Result data (if successful)\n */\n data?: any\n\n /**\n * Error message (if failed)\n */\n error?: string\n\n /**\n * Execution timestamp\n */\n timestamp: string\n\n /**\n * Tool that was executed\n */\n toolName: string\n}\n\n/**\n * Context value interface\n */\nexport interface MCPActionContextValue {\n /**\n * Execute an MCP action\n */\n executeAction: (request: ActionRequest) => Promise<ActionResult>\n\n /**\n * Currently available tools (from MCP server)\n */\n availableTools: Accessor<string[]>\n\n /**\n * Space IDs in current context\n */\n spaceIds: Accessor<string[]>\n\n /**\n * Current macro ID (if executing within a template)\n */\n macroId: Accessor<string | undefined>\n\n /**\n * Whether an action is currently executing\n */\n isExecuting: Accessor<boolean>\n\n /**\n * Last action result\n */\n lastResult: Accessor<ActionResult | undefined>\n}\n\n/**\n * Props for MCPActionProvider\n */\nexport interface MCPActionProviderProps {\n /**\n * Space IDs for multi-space queries\n */\n spaceIds?: string[]\n\n /**\n * Macro ID when executing within a template\n */\n macroId?: string\n\n /**\n * Available MCP tools\n */\n availableTools?: string[]\n\n /**\n * Callback for action execution (for audit logging)\n */\n onAction?: (request: ActionRequest, result: ActionResult) => void\n\n /**\n * Callback for webhook events (n8n, Zapier integration)\n */\n onWebhook?: (event: { type: string; payload: any }) => void\n\n /**\n * Custom action executor (override default)\n */\n executor?: (request: ActionRequest) => Promise<ActionResult>\n}\n\n// Create the context with undefined default\nconst MCPActionContext = createContext<MCPActionContextValue>()\n\n/**\n * Default action executor using CustomEvent fallback\n * This maintains backward compatibility while allowing Context-based usage\n */\nconst defaultExecutor = async (request: ActionRequest): Promise<ActionResult> => {\n return new Promise((resolve) => {\n const timestamp = new Date().toISOString()\n\n // Dispatch CustomEvent for backward compatibility with existing listeners\n if (typeof window !== 'undefined') {\n const event = new CustomEvent('mcp-action', {\n detail: {\n toolName: request.toolName,\n params: request.params || {},\n spaceIds: request.spaceIds,\n macroId: request.macroId,\n // v6.6.1 — action kind so a window-level listener can route a\n // `submit` (POST to params.submit_url) vs a tool call.\n action: request.action ?? 'tool-call',\n },\n bubbles: true,\n })\n\n // Listen for response event\n const responseHandler = (e: Event) => {\n const customEvent = e as CustomEvent\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: customEvent.detail?.success ?? true,\n data: customEvent.detail?.data,\n error: customEvent.detail?.error,\n timestamp,\n toolName: request.toolName,\n })\n }\n\n window.addEventListener('mcp-action-response', responseHandler)\n window.dispatchEvent(event)\n\n // Timeout fallback - resolve as success if no response in 100ms\n // (indicates no listener, action was dispatched)\n setTimeout(() => {\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: true,\n data: { dispatched: true },\n timestamp,\n toolName: request.toolName,\n })\n }, 100)\n } else {\n // Server-side: return immediately\n resolve({\n success: false,\n error: 'Actions not available server-side',\n timestamp,\n toolName: request.toolName,\n })\n }\n })\n}\n\n/**\n * MCPActionProvider - Provides action execution context to child components\n *\n * @example\n * ```tsx\n * <MCPActionProvider\n * spaceIds={['space-123']}\n * macroId=\"sales_overview\"\n * onAction={(req, res) => audit(req, res)}\n * >\n * <UIResourceRenderer layout={layout} />\n * </MCPActionProvider>\n * ```\n */\nexport const MCPActionProvider: ParentComponent<MCPActionProviderProps> = (props) => {\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [spaceIds, _setSpaceIds] = createSignal<string[]>(props.spaceIds || [])\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [macroId, _setMacroId] = createSignal<string | undefined>(props.macroId)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [availableTools, _setAvailableTools] = createSignal<string[]>(props.availableTools || [])\n\n // Update signals when props change\n // Note: This is a simple approach; for more complex scenarios, consider createEffect\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n\n try {\n // Enrich request with context\n const enrichedRequest: ActionRequest = {\n ...request,\n spaceIds: request.spaceIds || spaceIds(),\n macroId: request.macroId || macroId(),\n }\n\n // Execute using custom executor or default\n const executor = props.executor || defaultExecutor\n const result = await executor(enrichedRequest)\n\n setLastResult(result)\n\n // Call audit callback if provided\n props.onAction?.(enrichedRequest, result)\n\n // Trigger webhook if provided and action was successful\n if (result.success && props.onWebhook) {\n props.onWebhook({\n type: 'action-completed',\n payload: {\n request: enrichedRequest,\n result,\n },\n })\n }\n\n return result\n } catch (error) {\n const errorResult: ActionResult = {\n success: false,\n error: error instanceof Error ? error.message : 'Unknown error',\n timestamp: new Date().toISOString(),\n toolName: request.toolName,\n }\n\n setLastResult(errorResult)\n props.onAction?.(request, errorResult)\n\n return errorResult\n } finally {\n setIsExecuting(false)\n }\n }\n\n const contextValue: MCPActionContextValue = {\n executeAction,\n availableTools,\n spaceIds,\n macroId,\n isExecuting,\n lastResult,\n }\n\n return (\n <MCPActionContext.Provider value={contextValue}>\n {props.children}\n </MCPActionContext.Provider>\n )\n}\n\n/**\n * Hook to access MCP action context\n * Throws if used outside of MCPActionProvider\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPAction()\n *\n * const handleClick = async () => {\n * const result = await executeAction({\n * toolName: 'search.hub',\n * params: { query: 'revenue Q4' },\n * })\n * }\n * ```\n */\nexport function useMCPAction(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n if (!context) {\n throw new Error('useMCPAction must be used within an MCPActionProvider')\n }\n return context\n}\n\n/**\n * Hook to access MCP action context with fallback for components\n * outside of provider (uses CustomEvent fallback)\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPActionSafe()\n * // Works even without MCPActionProvider\n * ```\n */\nexport function useMCPActionSafe(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n\n if (context) {\n return context\n }\n\n // Fallback implementation for components outside provider\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n try {\n const result = await defaultExecutor(request)\n setLastResult(result)\n return result\n } finally {\n setIsExecuting(false)\n }\n }\n\n return {\n executeAction,\n availableTools: () => [],\n spaceIds: () => [],\n macroId: () => undefined,\n isExecuting,\n lastResult,\n }\n}\n\nexport { MCPActionContext }\n"],"names":["MCPActionContext","createContext","defaultExecutor","request","Promise","resolve","timestamp","Date","toISOString","window","event","CustomEvent","detail","toolName","params","spaceIds","macroId","action","bubbles","responseHandler","e","customEvent","removeEventListener","success","data","error","addEventListener","dispatchEvent","setTimeout","dispatched","MCPActionProvider","props","isExecuting","setIsExecuting","createSignal","lastResult","setLastResult","_setSpaceIds","_setMacroId","availableTools","_setAvailableTools","executeAction","enrichedRequest","executor","result","onAction","onWebhook","type","payload","errorResult","Error","message","contextValue","_$createComponent","Provider","value","children","useMCPAction","context","useContext","useMCPActionSafe","undefined"],"mappings":";;AAkJA,MAAMA,mBAAmBC,cAAAA;AAMzB,MAAMC,kBAAkB,OAAOC,YAAkD;AAC/E,SAAO,IAAIC,QAASC,CAAAA,YAAY;AAC9B,UAAMC,aAAY,oBAAIC,KAAAA,GAAOC,YAAAA;AAG7B,QAAI,OAAOC,WAAW,aAAa;AACjC,YAAMC,QAAQ,IAAIC,YAAY,cAAc;AAAA,QAC1CC,QAAQ;AAAA,UACNC,UAAUV,QAAQU;AAAAA,UAClBC,QAAQX,QAAQW,UAAU,CAAA;AAAA,UAC1BC,UAAUZ,QAAQY;AAAAA,UAClBC,SAASb,QAAQa;AAAAA;AAAAA;AAAAA,UAGjBC,QAAQd,QAAQc,UAAU;AAAA,QAAA;AAAA,QAE5BC,SAAS;AAAA,MAAA,CACV;AAGD,YAAMC,kBAAkBA,CAACC,MAAa;;AACpC,cAAMC,cAAcD;AACpBX,eAAOa,oBAAoB,uBAAuBH,eAAe;AACjEd,gBAAQ;AAAA,UACNkB,WAASF,iBAAYT,WAAZS,mBAAoBE,YAAW;AAAA,UACxCC,OAAMH,iBAAYT,WAAZS,mBAAoBG;AAAAA,UAC1BC,QAAOJ,iBAAYT,WAAZS,mBAAoBI;AAAAA,UAC3BnB;AAAAA,UACAO,UAAUV,QAAQU;AAAAA,QAAAA,CACnB;AAAA,MACH;AAEAJ,aAAOiB,iBAAiB,uBAAuBP,eAAe;AAC9DV,aAAOkB,cAAcjB,KAAK;AAI1BkB,iBAAW,MAAM;AACfnB,eAAOa,oBAAoB,uBAAuBH,eAAe;AACjEd,gBAAQ;AAAA,UACNkB,SAAS;AAAA,UACTC,MAAM;AAAA,YAAEK,YAAY;AAAA,UAAA;AAAA,UACpBvB;AAAAA,UACAO,UAAUV,QAAQU;AAAAA,QAAAA,CACnB;AAAA,MACH,GAAG,GAAG;AAAA,IACR,OAAO;AAELR,cAAQ;AAAA,QACNkB,SAAS;AAAA,QACTE,OAAO;AAAA,QACPnB;AAAAA,QACAO,UAAUV,QAAQU;AAAAA,MAAAA,CACnB;AAAA,IACH;AAAA,EACF,CAAC;AACH;AAgBO,MAAMiB,oBAA8DC,CAAAA,UAAU;AACnF,QAAM,CAACC,aAAaC,cAAc,IAAIC,aAAa,KAAK;AACxD,QAAM,CAACC,YAAYC,aAAa,IAAIF,aAAAA;AAEpC,QAAM,CAACnB,UAAUsB,YAAY,IAAIH,aAAuBH,MAAMhB,YAAY,EAAE;AAE5E,QAAM,CAACC,SAASsB,WAAW,IAAIJ,aAAiCH,MAAMf,OAAO;AAE7E,QAAM,CAACuB,gBAAgBC,kBAAkB,IAAIN,aAAuBH,MAAMQ,kBAAkB,EAAE;AAK9F,QAAME,gBAAgB,OAAOtC,YAAkD;;AAC7E8B,mBAAe,IAAI;AAEnB,QAAI;AAEF,YAAMS,kBAAiC;AAAA,QACrC,GAAGvC;AAAAA,QACHY,UAAUZ,QAAQY,YAAYA,SAAAA;AAAAA,QAC9BC,SAASb,QAAQa,WAAWA,QAAAA;AAAAA,MAAQ;AAItC,YAAM2B,WAAWZ,MAAMY,YAAYzC;AACnC,YAAM0C,SAAS,MAAMD,SAASD,eAAe;AAE7CN,oBAAcQ,MAAM;AAGpBb,kBAAMc,aAANd,+BAAiBW,iBAAiBE;AAGlC,UAAIA,OAAOrB,WAAWQ,MAAMe,WAAW;AACrCf,cAAMe,UAAU;AAAA,UACdC,MAAM;AAAA,UACNC,SAAS;AAAA,YACP7C,SAASuC;AAAAA,YACTE;AAAAA,UAAAA;AAAAA,QACF,CACD;AAAA,MACH;AAEA,aAAOA;AAAAA,IACT,SAASnB,OAAO;AACd,YAAMwB,cAA4B;AAAA,QAChC1B,SAAS;AAAA,QACTE,OAAOA,iBAAiByB,QAAQzB,MAAM0B,UAAU;AAAA,QAChD7C,YAAW,oBAAIC,KAAAA,GAAOC,YAAAA;AAAAA,QACtBK,UAAUV,QAAQU;AAAAA,MAAAA;AAGpBuB,oBAAca,WAAW;AACzBlB,kBAAMc,aAANd,+BAAiB5B,SAAS8C;AAE1B,aAAOA;AAAAA,IACT,UAAA;AACEhB,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAEA,QAAMmB,eAAsC;AAAA,IAC1CX;AAAAA,IACAF;AAAAA,IACAxB;AAAAA,IACAC;AAAAA,IACAgB;AAAAA,IACAG;AAAAA,EAAAA;AAGF,SAAAkB,gBACGrD,iBAAiBsD,UAAQ;AAAA,IAACC,OAAOH;AAAAA,IAAY,IAAAI,WAAA;AAAA,aAC3CzB,MAAMyB;AAAAA,IAAQ;AAAA,EAAA,CAAA;AAGrB;AAkBO,SAASC,eAAsC;AACpD,QAAMC,UAAUC,WAAW3D,gBAAgB;AAC3C,MAAI,CAAC0D,SAAS;AACZ,UAAM,IAAIR,MAAM,uDAAuD;AAAA,EACzE;AACA,SAAOQ;AACT;AAYO,SAASE,mBAA0C;AACxD,QAAMF,UAAUC,WAAW3D,gBAAgB;AAE3C,MAAI0D,SAAS;AACX,WAAOA;AAAAA,EACT;AAGA,QAAM,CAAC1B,aAAaC,cAAc,IAAIC,aAAa,KAAK;AACxD,QAAM,CAACC,YAAYC,aAAa,IAAIF,aAAAA;AAEpC,QAAMO,gBAAgB,OAAOtC,YAAkD;AAC7E8B,mBAAe,IAAI;AACnB,QAAI;AACF,YAAMW,SAAS,MAAM1C,gBAAgBC,OAAO;AAC5CiC,oBAAcQ,MAAM;AACpB,aAAOA;AAAAA,IACT,UAAA;AACEX,qBAAe,KAAK;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AAAA,IACLQ;AAAAA,IACAF,gBAAgBA,MAAM,CAAA;AAAA,IACtBxB,UAAUA,MAAM,CAAA;AAAA,IAChBC,SAASA,MAAM6C;AAAAA,IACf7B;AAAAA,IACAG;AAAAA,EAAAA;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"MCPActionContext.js","sources":["../../src/context/MCPActionContext.tsx"],"sourcesContent":["/**\n * MCPActionContext - Context provider for MCP action execution\n * Phase 5.0: Quick Wins - Replaces CustomEvent with typed context for Mastra integration\n */\n\nimport { createContext, createSignal, useContext, ParentComponent, Accessor } from 'solid-js'\nimport { useMCPUIStrings } from './MCPUIStringsContext'\n\n/**\n * Action request payload\n */\nexport interface ActionRequest {\n /**\n * MCP tool name to execute. For a `submit` action with no associated\n * tool, renderers pass the sentinel `'submit'` — branch on `action`,\n * not on `toolName`, to tell a submit apart from a tool call.\n */\n toolName: string\n\n /**\n * Tool parameters\n */\n params?: Record<string, any>\n\n /**\n * Optional space IDs for multi-space context\n */\n spaceIds?: string[]\n\n /**\n * Optional macro ID for template execution\n */\n macroId?: string\n\n /**\n * Action kind (v6.6.1). Lets a host `executor` tell a tool call apart\n * from a form-style `submit`. Absent ⇒ treat as `'tool-call'` (backward\n * compatible — every pre-v6.6.1 request omits it).\n *\n * A `submit` action carries its payload in `params` (e.g. `submit_url`,\n * `connector_id`, `feedback_value`) and **must NOT** be executed as a\n * tool call — the host routes it (e.g. POST to `params.submit_url`).\n */\n action?: 'tool-call' | 'submit' | 'link'\n}\n\n/**\n * Action result from execution\n */\nexport interface ActionResult {\n /**\n * Whether the action was successful\n */\n success: boolean\n\n /**\n * Result data (if successful)\n */\n data?: any\n\n /**\n * Error message (if failed)\n */\n error?: string\n\n /**\n * Execution timestamp\n */\n timestamp: string\n\n /**\n * Tool that was executed\n */\n toolName: string\n}\n\n/**\n * Context value interface\n */\nexport interface MCPActionContextValue {\n /**\n * Execute an MCP action\n */\n executeAction: (request: ActionRequest) => Promise<ActionResult>\n\n /**\n * Currently available tools (from MCP server)\n */\n availableTools: Accessor<string[]>\n\n /**\n * Space IDs in current context\n */\n spaceIds: Accessor<string[]>\n\n /**\n * Current macro ID (if executing within a template)\n */\n macroId: Accessor<string | undefined>\n\n /**\n * Whether an action is currently executing\n */\n isExecuting: Accessor<boolean>\n\n /**\n * Last action result\n */\n lastResult: Accessor<ActionResult | undefined>\n}\n\n/**\n * Props for MCPActionProvider\n */\nexport interface MCPActionProviderProps {\n /**\n * Space IDs for multi-space queries\n */\n spaceIds?: string[]\n\n /**\n * Macro ID when executing within a template\n */\n macroId?: string\n\n /**\n * Available MCP tools\n */\n availableTools?: string[]\n\n /**\n * Callback for action execution (for audit logging)\n */\n onAction?: (request: ActionRequest, result: ActionResult) => void\n\n /**\n * Callback for webhook events (n8n, Zapier integration)\n */\n onWebhook?: (event: { type: string; payload: any }) => void\n\n /**\n * Custom action executor (override default)\n */\n executor?: (request: ActionRequest) => Promise<ActionResult>\n}\n\n// Create the context with undefined default\nconst MCPActionContext = createContext<MCPActionContextValue>()\n\n/**\n * Default action executor using CustomEvent fallback\n * This maintains backward compatibility while allowing Context-based usage\n */\nconst defaultExecutor = async (request: ActionRequest): Promise<ActionResult> => {\n return new Promise((resolve) => {\n const timestamp = new Date().toISOString()\n\n // Dispatch CustomEvent for backward compatibility with existing listeners\n if (typeof window !== 'undefined') {\n const event = new CustomEvent('mcp-action', {\n detail: {\n toolName: request.toolName,\n params: request.params || {},\n spaceIds: request.spaceIds,\n macroId: request.macroId,\n // v6.6.1 — action kind so a window-level listener can route a\n // `submit` (POST to params.submit_url) vs a tool call.\n action: request.action ?? 'tool-call',\n },\n bubbles: true,\n })\n\n // Listen for response event\n const responseHandler = (e: Event) => {\n const customEvent = e as CustomEvent\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: customEvent.detail?.success ?? true,\n data: customEvent.detail?.data,\n error: customEvent.detail?.error,\n timestamp,\n toolName: request.toolName,\n })\n }\n\n window.addEventListener('mcp-action-response', responseHandler)\n window.dispatchEvent(event)\n\n // Timeout fallback - resolve as success if no response in 100ms\n // (indicates no listener, action was dispatched)\n setTimeout(() => {\n window.removeEventListener('mcp-action-response', responseHandler)\n resolve({\n success: true,\n data: { dispatched: true },\n timestamp,\n toolName: request.toolName,\n })\n }, 100)\n } else {\n // Server-side: return immediately\n resolve({\n success: false,\n error: 'Actions not available server-side',\n timestamp,\n toolName: request.toolName,\n })\n }\n })\n}\n\n/**\n * MCPActionProvider - Provides action execution context to child components\n *\n * @example\n * ```tsx\n * <MCPActionProvider\n * spaceIds={['space-123']}\n * macroId=\"sales_overview\"\n * onAction={(req, res) => audit(req, res)}\n * >\n * <UIResourceRenderer layout={layout} />\n * </MCPActionProvider>\n * ```\n */\nexport const MCPActionProvider: ParentComponent<MCPActionProviderProps> = (props) => {\n // The error of a failed action can be rendered by FormRenderer.\n const strings = useMCPUIStrings()\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [spaceIds, _setSpaceIds] = createSignal<string[]>(props.spaceIds || [])\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [macroId, _setMacroId] = createSignal<string | undefined>(props.macroId)\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const [availableTools, _setAvailableTools] = createSignal<string[]>(props.availableTools || [])\n\n // Update signals when props change\n // Note: This is a simple approach; for more complex scenarios, consider createEffect\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n\n try {\n // Enrich request with context\n const enrichedRequest: ActionRequest = {\n ...request,\n spaceIds: request.spaceIds || spaceIds(),\n macroId: request.macroId || macroId(),\n }\n\n // Execute using custom executor or default\n const executor = props.executor || defaultExecutor\n const result = await executor(enrichedRequest)\n\n setLastResult(result)\n\n // Call audit callback if provided\n props.onAction?.(enrichedRequest, result)\n\n // Trigger webhook if provided and action was successful\n if (result.success && props.onWebhook) {\n props.onWebhook({\n type: 'action-completed',\n payload: {\n request: enrichedRequest,\n result,\n },\n })\n }\n\n return result\n } catch (error) {\n const errorResult: ActionResult = {\n success: false,\n error: error instanceof Error ? error.message : strings.errorUnknown,\n timestamp: new Date().toISOString(),\n toolName: request.toolName,\n }\n\n setLastResult(errorResult)\n props.onAction?.(request, errorResult)\n\n return errorResult\n } finally {\n setIsExecuting(false)\n }\n }\n\n const contextValue: MCPActionContextValue = {\n executeAction,\n availableTools,\n spaceIds,\n macroId,\n isExecuting,\n lastResult,\n }\n\n return (\n <MCPActionContext.Provider value={contextValue}>\n {props.children}\n </MCPActionContext.Provider>\n )\n}\n\n/**\n * Hook to access MCP action context\n * Throws if used outside of MCPActionProvider\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPAction()\n *\n * const handleClick = async () => {\n * const result = await executeAction({\n * toolName: 'search.hub',\n * params: { query: 'revenue Q4' },\n * })\n * }\n * ```\n */\nexport function useMCPAction(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n if (!context) {\n throw new Error('useMCPAction must be used within an MCPActionProvider')\n }\n return context\n}\n\n/**\n * Hook to access MCP action context with fallback for components\n * outside of provider (uses CustomEvent fallback)\n *\n * @example\n * ```tsx\n * const { executeAction, isExecuting } = useMCPActionSafe()\n * // Works even without MCPActionProvider\n * ```\n */\nexport function useMCPActionSafe(): MCPActionContextValue {\n const context = useContext(MCPActionContext)\n\n if (context) {\n return context\n }\n\n // Fallback implementation for components outside provider\n const [isExecuting, setIsExecuting] = createSignal(false)\n const [lastResult, setLastResult] = createSignal<ActionResult>()\n\n const executeAction = async (request: ActionRequest): Promise<ActionResult> => {\n setIsExecuting(true)\n try {\n const result = await defaultExecutor(request)\n setLastResult(result)\n return result\n } finally {\n setIsExecuting(false)\n }\n }\n\n return {\n executeAction,\n availableTools: () => [],\n spaceIds: () => [],\n macroId: () => undefined,\n isExecuting,\n lastResult,\n }\n}\n\nexport { MCPActionContext }\n"],"names":["MCPActionContext","createContext","defaultExecutor","request","Promise","resolve","timestamp","Date","toISOString","window","event","CustomEvent","detail","toolName","params","spaceIds","macroId","action","bubbles","responseHandler","e","customEvent","removeEventListener","success","data","error","addEventListener","dispatchEvent","setTimeout","dispatched","MCPActionProvider","props","strings","useMCPUIStrings","isExecuting","setIsExecuting","createSignal","lastResult","setLastResult","_setSpaceIds","_setMacroId","availableTools","_setAvailableTools","executeAction","enrichedRequest","executor","result","onAction","onWebhook","type","payload","errorResult","Error","message","errorUnknown","contextValue","_$createComponent","Provider","value","children","useMCPAction","context","useContext","useMCPActionSafe","undefined"],"mappings":"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"}
|