@seed-ship/mcp-ui-solid 6.1.0 → 6.3.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 +118 -0
- package/dist/components/CarouselRenderer.cjs +41 -30
- package/dist/components/CarouselRenderer.cjs.map +1 -1
- package/dist/components/CarouselRenderer.d.ts.map +1 -1
- package/dist/components/CarouselRenderer.js +42 -31
- package/dist/components/CarouselRenderer.js.map +1 -1
- package/dist/components/CodeBlockRenderer.cjs +88 -25
- package/dist/components/CodeBlockRenderer.cjs.map +1 -1
- package/dist/components/CodeBlockRenderer.d.ts.map +1 -1
- package/dist/components/CodeBlockRenderer.js +89 -26
- package/dist/components/CodeBlockRenderer.js.map +1 -1
- package/dist/components/ExpandableWrapper.cjs +2 -1
- package/dist/components/ExpandableWrapper.cjs.map +1 -1
- package/dist/components/ExpandableWrapper.d.ts +10 -0
- package/dist/components/ExpandableWrapper.d.ts.map +1 -1
- package/dist/components/ExpandableWrapper.js +3 -2
- package/dist/components/ExpandableWrapper.js.map +1 -1
- package/dist/components/ImageGalleryRenderer.cjs +101 -77
- package/dist/components/ImageGalleryRenderer.cjs.map +1 -1
- package/dist/components/ImageGalleryRenderer.d.ts.map +1 -1
- package/dist/components/ImageGalleryRenderer.js +102 -78
- package/dist/components/ImageGalleryRenderer.js.map +1 -1
- package/dist/components/MapRenderer.cjs +94 -34
- package/dist/components/MapRenderer.cjs.map +1 -1
- package/dist/components/MapRenderer.d.ts.map +1 -1
- package/dist/components/MapRenderer.js +107 -47
- package/dist/components/MapRenderer.js.map +1 -1
- package/dist/components/UIResourceRenderer.cjs +27 -12
- package/dist/components/UIResourceRenderer.cjs.map +1 -1
- package/dist/components/UIResourceRenderer.d.ts.map +1 -1
- package/dist/components/UIResourceRenderer.js +27 -12
- package/dist/components/UIResourceRenderer.js.map +1 -1
- package/dist/components/VideoRenderer.cjs +95 -74
- package/dist/components/VideoRenderer.cjs.map +1 -1
- package/dist/components/VideoRenderer.d.ts.map +1 -1
- package/dist/components/VideoRenderer.js +96 -75
- package/dist/components/VideoRenderer.js.map +1 -1
- package/dist/index.cjs +3 -3
- package/dist/index.js +1 -1
- package/dist/mcp-ui-spec/dist/schemas.cjs +8 -1
- package/dist/mcp-ui-spec/dist/schemas.cjs.map +1 -1
- package/dist/mcp-ui-spec/dist/schemas.js +8 -1
- package/dist/mcp-ui-spec/dist/schemas.js.map +1 -1
- package/dist/types/index.d.ts +11 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types.d.cts +11 -0
- package/dist/types.d.ts +11 -0
- package/package.json +2 -2
- package/src/components/CarouselRenderer.tsx +9 -1
- package/src/components/CodeBlockRenderer.tsx +65 -5
- package/src/components/ExpandableWrapper.tsx +16 -2
- package/src/components/ImageGalleryRenderer.test.tsx +18 -7
- package/src/components/ImageGalleryRenderer.tsx +22 -3
- package/src/components/MapRenderer.tsx +68 -14
- package/src/components/UIResourceRenderer.tsx +19 -10
- package/src/components/VideoRenderer.tsx +14 -4
- package/src/types/index.ts +11 -0
- package/tsconfig.tsbuildinfo +1 -1
|
@@ -2,7 +2,8 @@
|
|
|
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
|
-
|
|
5
|
+
const ExpandableWrapper = require("./ExpandableWrapper.cjs");
|
|
6
|
+
var _tmpl$ = /* @__PURE__ */ web.template(`<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$2 = /* @__PURE__ */ web.template(`<iframe class="absolute inset-0 w-full h-full"allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"allowfullscreen loading=lazy>`, true, false, false), _tmpl$3 = /* @__PURE__ */ web.template(`<div class="px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0"><p class="text-sm text-gray-600 dark:text-gray-400">`), _tmpl$4 = /* @__PURE__ */ web.template(`<div><!$><!/><div></div><!$><!/>`), _tmpl$5 = /* @__PURE__ */ web.template(`<video playsinline class="absolute inset-0 w-full h-full object-contain"><track kind=captions>Your browser does not support the video tag.`);
|
|
6
7
|
function parseVideoUrl(url) {
|
|
7
8
|
const youtubeMatch = url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|v\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
|
|
8
9
|
if (youtubeMatch) {
|
|
@@ -27,6 +28,7 @@ const VideoRenderer = (props) => {
|
|
|
27
28
|
var _a;
|
|
28
29
|
return props.params || ((_a = props.component) == null ? void 0 : _a.params);
|
|
29
30
|
};
|
|
31
|
+
const isExpanded = ExpandableWrapper.useExpanded();
|
|
30
32
|
const videoInfo = solidJs.createMemo(() => {
|
|
31
33
|
var _a;
|
|
32
34
|
return parseVideoUrl(((_a = params()) == null ? void 0 : _a.url) || "");
|
|
@@ -79,80 +81,99 @@ const VideoRenderer = (props) => {
|
|
|
79
81
|
console.error("Video error:", e);
|
|
80
82
|
(_a = props.onError) == null ? void 0 : _a.call(props, error);
|
|
81
83
|
};
|
|
82
|
-
return (
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
get when() {
|
|
97
|
-
return embedUrl();
|
|
98
|
-
},
|
|
99
|
-
get fallback() {
|
|
100
|
-
return (
|
|
101
|
-
// Direct video file
|
|
102
|
-
(() => {
|
|
103
|
-
var _el$10 = web.getNextElement(_tmpl$5);
|
|
104
|
-
_el$10.addEventListener("error", handleVideoError);
|
|
105
|
-
web.effect((_p$) => {
|
|
106
|
-
var _a, _b, _c, _d, _e, _f;
|
|
107
|
-
var _v$3 = (_a = params()) == null ? void 0 : _a.url, _v$4 = (_b = params()) == null ? void 0 : _b.poster, _v$5 = (_c = params()) == null ? void 0 : _c.autoplay, _v$6 = ((_d = params()) == null ? void 0 : _d.controls) !== false, _v$7 = (_e = params()) == null ? void 0 : _e.loop, _v$8 = (_f = params()) == null ? void 0 : _f.muted;
|
|
108
|
-
_v$3 !== _p$.e && web.setAttribute(_el$10, "src", _p$.e = _v$3);
|
|
109
|
-
_v$4 !== _p$.t && web.setAttribute(_el$10, "poster", _p$.t = _v$4);
|
|
110
|
-
_v$5 !== _p$.a && web.setProperty(_el$10, "autoplay", _p$.a = _v$5);
|
|
111
|
-
_v$6 !== _p$.o && web.setProperty(_el$10, "controls", _p$.o = _v$6);
|
|
112
|
-
_v$7 !== _p$.i && web.setProperty(_el$10, "loop", _p$.i = _v$7);
|
|
113
|
-
_v$8 !== _p$.n && web.setProperty(_el$10, "muted", _p$.n = _v$8);
|
|
114
|
-
return _p$;
|
|
115
|
-
}, {
|
|
116
|
-
e: void 0,
|
|
117
|
-
t: void 0,
|
|
118
|
-
a: void 0,
|
|
119
|
-
o: void 0,
|
|
120
|
-
i: void 0,
|
|
121
|
-
n: void 0
|
|
122
|
-
});
|
|
123
|
-
return _el$10;
|
|
124
|
-
})()
|
|
125
|
-
);
|
|
126
|
-
},
|
|
127
|
-
get children() {
|
|
128
|
-
var _el$5 = web.getNextElement(_tmpl$2);
|
|
129
|
-
web.effect((_p$) => {
|
|
84
|
+
return web.createComponent(ExpandableWrapper.ExpandableWrapper, {
|
|
85
|
+
get title() {
|
|
86
|
+
var _a;
|
|
87
|
+
return ((_a = params()) == null ? void 0 : _a.title) || "Video";
|
|
88
|
+
},
|
|
89
|
+
get copyData() {
|
|
90
|
+
var _a;
|
|
91
|
+
return ((_a = params()) == null ? void 0 : _a.url) || "";
|
|
92
|
+
},
|
|
93
|
+
copyLabel: "Copy video URL",
|
|
94
|
+
get children() {
|
|
95
|
+
var _el$ = web.getNextElement(_tmpl$4), _el$8 = _el$.firstChild, [_el$9, _co$] = web.getNextMarker(_el$8.nextSibling), _el$4 = _el$9.nextSibling, _el$0 = _el$4.nextSibling, [_el$1, _co$2] = web.getNextMarker(_el$0.nextSibling);
|
|
96
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
97
|
+
get when() {
|
|
130
98
|
var _a;
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
99
|
+
return (_a = params()) == null ? void 0 : _a.title;
|
|
100
|
+
},
|
|
101
|
+
get children() {
|
|
102
|
+
var _el$2 = web.getNextElement(_tmpl$), _el$3 = _el$2.firstChild;
|
|
103
|
+
web.insert(_el$3, () => params().title);
|
|
104
|
+
return _el$2;
|
|
105
|
+
}
|
|
106
|
+
}), _el$9, _co$);
|
|
107
|
+
web.insert(_el$4, web.createComponent(solidJs.Show, {
|
|
108
|
+
get when() {
|
|
109
|
+
return embedUrl();
|
|
110
|
+
},
|
|
111
|
+
get fallback() {
|
|
112
|
+
return (
|
|
113
|
+
// Direct video file
|
|
114
|
+
(() => {
|
|
115
|
+
var _el$10 = web.getNextElement(_tmpl$5);
|
|
116
|
+
_el$10.addEventListener("error", handleVideoError);
|
|
117
|
+
web.effect((_p$) => {
|
|
118
|
+
var _a, _b, _c, _d, _e, _f;
|
|
119
|
+
var _v$5 = (_a = params()) == null ? void 0 : _a.url, _v$6 = (_b = params()) == null ? void 0 : _b.poster, _v$7 = (_c = params()) == null ? void 0 : _c.autoplay, _v$8 = ((_d = params()) == null ? void 0 : _d.controls) !== false, _v$9 = (_e = params()) == null ? void 0 : _e.loop, _v$0 = (_f = params()) == null ? void 0 : _f.muted;
|
|
120
|
+
_v$5 !== _p$.e && web.setAttribute(_el$10, "src", _p$.e = _v$5);
|
|
121
|
+
_v$6 !== _p$.t && web.setAttribute(_el$10, "poster", _p$.t = _v$6);
|
|
122
|
+
_v$7 !== _p$.a && web.setProperty(_el$10, "autoplay", _p$.a = _v$7);
|
|
123
|
+
_v$8 !== _p$.o && web.setProperty(_el$10, "controls", _p$.o = _v$8);
|
|
124
|
+
_v$9 !== _p$.i && web.setProperty(_el$10, "loop", _p$.i = _v$9);
|
|
125
|
+
_v$0 !== _p$.n && web.setProperty(_el$10, "muted", _p$.n = _v$0);
|
|
126
|
+
return _p$;
|
|
127
|
+
}, {
|
|
128
|
+
e: void 0,
|
|
129
|
+
t: void 0,
|
|
130
|
+
a: void 0,
|
|
131
|
+
o: void 0,
|
|
132
|
+
i: void 0,
|
|
133
|
+
n: void 0
|
|
134
|
+
});
|
|
135
|
+
return _el$10;
|
|
136
|
+
})()
|
|
137
|
+
);
|
|
138
|
+
},
|
|
139
|
+
get children() {
|
|
140
|
+
var _el$5 = web.getNextElement(_tmpl$2);
|
|
141
|
+
web.effect((_p$) => {
|
|
142
|
+
var _a;
|
|
143
|
+
var _v$ = embedUrl(), _v$2 = ((_a = params()) == null ? void 0 : _a.title) || "Video";
|
|
144
|
+
_v$ !== _p$.e && web.setAttribute(_el$5, "src", _p$.e = _v$);
|
|
145
|
+
_v$2 !== _p$.t && web.setAttribute(_el$5, "title", _p$.t = _v$2);
|
|
146
|
+
return _p$;
|
|
147
|
+
}, {
|
|
148
|
+
e: void 0,
|
|
149
|
+
t: void 0
|
|
150
|
+
});
|
|
151
|
+
return _el$5;
|
|
152
|
+
}
|
|
153
|
+
}));
|
|
154
|
+
web.insert(_el$, web.createComponent(solidJs.Show, {
|
|
155
|
+
get when() {
|
|
156
|
+
var _a;
|
|
157
|
+
return (_a = params()) == null ? void 0 : _a.caption;
|
|
158
|
+
},
|
|
159
|
+
get children() {
|
|
160
|
+
var _el$6 = web.getNextElement(_tmpl$3), _el$7 = _el$6.firstChild;
|
|
161
|
+
web.insert(_el$7, () => params().caption);
|
|
162
|
+
return _el$6;
|
|
163
|
+
}
|
|
164
|
+
}), _el$1, _co$2);
|
|
165
|
+
web.effect((_p$) => {
|
|
166
|
+
var _v$3 = `w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : ""}`, _v$4 = `relative bg-black ${isExpanded() ? "flex-1 min-h-0" : aspectClass()}`;
|
|
167
|
+
_v$3 !== _p$.e && web.className(_el$, _p$.e = _v$3);
|
|
168
|
+
_v$4 !== _p$.t && web.className(_el$4, _p$.t = _v$4);
|
|
169
|
+
return _p$;
|
|
170
|
+
}, {
|
|
171
|
+
e: void 0,
|
|
172
|
+
t: void 0
|
|
173
|
+
});
|
|
174
|
+
return _el$;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
156
177
|
};
|
|
157
178
|
function isSupportedVideoUrl(url) {
|
|
158
179
|
const info = parseVideoUrl(url);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoRenderer.cjs","sources":["../../src/components/VideoRenderer.tsx"],"sourcesContent":["/**\n * VideoRenderer - Video embed component\n * Sprint 5: Media Components\n *\n * Supports YouTube, Vimeo, and direct video files\n */\n\nimport { Component, createMemo, Show } from 'solid-js'\nimport type { UIComponent, VideoComponentParams } from '../types'\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/**\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\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 <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 {/* 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 */}\n <div class={`relative ${aspectClass()} bg-black`}>\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\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400\">{params()!.caption}</p>\n </div>\n </Show>\n </div>\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","videoInfo","createMemo","embedUrl","info","p","ytParams","URLSearchParams","autoplay","controls","loop","mute","muted","startTime","set","String","vParams","aspectClass","aspectRatio","handleVideoError","e","error","Error","console","onError","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_$insert","_$createComponent","Show","when","title","children","_el$2","_tmpl$","_el$3","fallback","_el$10","_tmpl$5","addEventListener","_$effect","_p$","_v$3","_v$4","poster","_v$5","_v$6","_v$7","_v$8","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","caption","_el$6","_tmpl$3","_el$7","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VideoRenderer.cjs","sources":["../../src/components/VideoRenderer.tsx"],"sourcesContent":["/**\n * VideoRenderer - Video embed component\n * Sprint 5: Media Components\n *\n * Supports YouTube, Vimeo, and direct video files\n */\n\nimport { Component, createMemo, Show } from 'solid-js'\nimport type { UIComponent, VideoComponentParams } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\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/**\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 >\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","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","fallback","_el$10","_tmpl$5","addEventListener","_$effect","_p$","_v$5","_v$6","poster","_v$7","_v$8","_v$9","_v$0","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","caption","_el$6","_tmpl$3","_el$7","_v$3","_v$4","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VideoRenderer.d.ts","sourceRoot":"","sources":["../../src/components/VideoRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAoB,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;
|
|
1
|
+
{"version":3,"file":"VideoRenderer.d.ts","sourceRoot":"","sources":["../../src/components/VideoRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAoB,MAAM,UAAU,CAAA;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAA;AAGjE,MAAM,WAAW,kBAAkB;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,WAAW,CAAA;IAEvB;;OAEG;IACH,MAAM,CAAC,EAAE,oBAAoB,CAAA;IAE7B;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAA;CACjC;AAED;;GAEG;AACH,KAAK,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAA;AAsCnD,eAAO,MAAM,aAAa,EAAE,SAAS,CAAC,kBAAkB,CAuHvD,CAAA;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGxD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAE3D"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { getNextElement, template, getNextMarker, insert,
|
|
1
|
+
import { createComponent, getNextElement, template, getNextMarker, insert, effect, setAttribute, setProperty, className } from "solid-js/web";
|
|
2
2
|
import { createMemo, Show } from "solid-js";
|
|
3
|
-
|
|
3
|
+
import { useExpanded, ExpandableWrapper } from "./ExpandableWrapper.js";
|
|
4
|
+
var _tmpl$ = /* @__PURE__ */ template(`<div class="px-4 py-3 border-b border-gray-200 dark:border-gray-700"><h3 class="text-sm font-semibold text-gray-900 dark:text-white">`), _tmpl$2 = /* @__PURE__ */ template(`<iframe class="absolute inset-0 w-full h-full"allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"allowfullscreen loading=lazy>`, true, false, false), _tmpl$3 = /* @__PURE__ */ template(`<div class="px-4 py-3 border-t border-gray-200 dark:border-gray-700 flex-shrink-0"><p class="text-sm text-gray-600 dark:text-gray-400">`), _tmpl$4 = /* @__PURE__ */ template(`<div><!$><!/><div></div><!$><!/>`), _tmpl$5 = /* @__PURE__ */ template(`<video playsinline class="absolute inset-0 w-full h-full object-contain"><track kind=captions>Your browser does not support the video tag.`);
|
|
4
5
|
function parseVideoUrl(url) {
|
|
5
6
|
const youtubeMatch = url.match(/(?:youtube\.com\/(?:watch\?v=|embed\/|v\/)|youtu\.be\/)([a-zA-Z0-9_-]{11})/);
|
|
6
7
|
if (youtubeMatch) {
|
|
@@ -25,6 +26,7 @@ const VideoRenderer = (props) => {
|
|
|
25
26
|
var _a;
|
|
26
27
|
return props.params || ((_a = props.component) == null ? void 0 : _a.params);
|
|
27
28
|
};
|
|
29
|
+
const isExpanded = useExpanded();
|
|
28
30
|
const videoInfo = createMemo(() => {
|
|
29
31
|
var _a;
|
|
30
32
|
return parseVideoUrl(((_a = params()) == null ? void 0 : _a.url) || "");
|
|
@@ -77,80 +79,99 @@ const VideoRenderer = (props) => {
|
|
|
77
79
|
console.error("Video error:", e);
|
|
78
80
|
(_a = props.onError) == null ? void 0 : _a.call(props, error);
|
|
79
81
|
};
|
|
80
|
-
return (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
get when() {
|
|
95
|
-
return embedUrl();
|
|
96
|
-
},
|
|
97
|
-
get fallback() {
|
|
98
|
-
return (
|
|
99
|
-
// Direct video file
|
|
100
|
-
(() => {
|
|
101
|
-
var _el$10 = getNextElement(_tmpl$5);
|
|
102
|
-
_el$10.addEventListener("error", handleVideoError);
|
|
103
|
-
effect((_p$) => {
|
|
104
|
-
var _a, _b, _c, _d, _e, _f;
|
|
105
|
-
var _v$3 = (_a = params()) == null ? void 0 : _a.url, _v$4 = (_b = params()) == null ? void 0 : _b.poster, _v$5 = (_c = params()) == null ? void 0 : _c.autoplay, _v$6 = ((_d = params()) == null ? void 0 : _d.controls) !== false, _v$7 = (_e = params()) == null ? void 0 : _e.loop, _v$8 = (_f = params()) == null ? void 0 : _f.muted;
|
|
106
|
-
_v$3 !== _p$.e && setAttribute(_el$10, "src", _p$.e = _v$3);
|
|
107
|
-
_v$4 !== _p$.t && setAttribute(_el$10, "poster", _p$.t = _v$4);
|
|
108
|
-
_v$5 !== _p$.a && setProperty(_el$10, "autoplay", _p$.a = _v$5);
|
|
109
|
-
_v$6 !== _p$.o && setProperty(_el$10, "controls", _p$.o = _v$6);
|
|
110
|
-
_v$7 !== _p$.i && setProperty(_el$10, "loop", _p$.i = _v$7);
|
|
111
|
-
_v$8 !== _p$.n && setProperty(_el$10, "muted", _p$.n = _v$8);
|
|
112
|
-
return _p$;
|
|
113
|
-
}, {
|
|
114
|
-
e: void 0,
|
|
115
|
-
t: void 0,
|
|
116
|
-
a: void 0,
|
|
117
|
-
o: void 0,
|
|
118
|
-
i: void 0,
|
|
119
|
-
n: void 0
|
|
120
|
-
});
|
|
121
|
-
return _el$10;
|
|
122
|
-
})()
|
|
123
|
-
);
|
|
124
|
-
},
|
|
125
|
-
get children() {
|
|
126
|
-
var _el$5 = getNextElement(_tmpl$2);
|
|
127
|
-
effect((_p$) => {
|
|
82
|
+
return createComponent(ExpandableWrapper, {
|
|
83
|
+
get title() {
|
|
84
|
+
var _a;
|
|
85
|
+
return ((_a = params()) == null ? void 0 : _a.title) || "Video";
|
|
86
|
+
},
|
|
87
|
+
get copyData() {
|
|
88
|
+
var _a;
|
|
89
|
+
return ((_a = params()) == null ? void 0 : _a.url) || "";
|
|
90
|
+
},
|
|
91
|
+
copyLabel: "Copy video URL",
|
|
92
|
+
get children() {
|
|
93
|
+
var _el$ = getNextElement(_tmpl$4), _el$8 = _el$.firstChild, [_el$9, _co$] = getNextMarker(_el$8.nextSibling), _el$4 = _el$9.nextSibling, _el$0 = _el$4.nextSibling, [_el$1, _co$2] = getNextMarker(_el$0.nextSibling);
|
|
94
|
+
insert(_el$, createComponent(Show, {
|
|
95
|
+
get when() {
|
|
128
96
|
var _a;
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
97
|
+
return (_a = params()) == null ? void 0 : _a.title;
|
|
98
|
+
},
|
|
99
|
+
get children() {
|
|
100
|
+
var _el$2 = getNextElement(_tmpl$), _el$3 = _el$2.firstChild;
|
|
101
|
+
insert(_el$3, () => params().title);
|
|
102
|
+
return _el$2;
|
|
103
|
+
}
|
|
104
|
+
}), _el$9, _co$);
|
|
105
|
+
insert(_el$4, createComponent(Show, {
|
|
106
|
+
get when() {
|
|
107
|
+
return embedUrl();
|
|
108
|
+
},
|
|
109
|
+
get fallback() {
|
|
110
|
+
return (
|
|
111
|
+
// Direct video file
|
|
112
|
+
(() => {
|
|
113
|
+
var _el$10 = getNextElement(_tmpl$5);
|
|
114
|
+
_el$10.addEventListener("error", handleVideoError);
|
|
115
|
+
effect((_p$) => {
|
|
116
|
+
var _a, _b, _c, _d, _e, _f;
|
|
117
|
+
var _v$5 = (_a = params()) == null ? void 0 : _a.url, _v$6 = (_b = params()) == null ? void 0 : _b.poster, _v$7 = (_c = params()) == null ? void 0 : _c.autoplay, _v$8 = ((_d = params()) == null ? void 0 : _d.controls) !== false, _v$9 = (_e = params()) == null ? void 0 : _e.loop, _v$0 = (_f = params()) == null ? void 0 : _f.muted;
|
|
118
|
+
_v$5 !== _p$.e && setAttribute(_el$10, "src", _p$.e = _v$5);
|
|
119
|
+
_v$6 !== _p$.t && setAttribute(_el$10, "poster", _p$.t = _v$6);
|
|
120
|
+
_v$7 !== _p$.a && setProperty(_el$10, "autoplay", _p$.a = _v$7);
|
|
121
|
+
_v$8 !== _p$.o && setProperty(_el$10, "controls", _p$.o = _v$8);
|
|
122
|
+
_v$9 !== _p$.i && setProperty(_el$10, "loop", _p$.i = _v$9);
|
|
123
|
+
_v$0 !== _p$.n && setProperty(_el$10, "muted", _p$.n = _v$0);
|
|
124
|
+
return _p$;
|
|
125
|
+
}, {
|
|
126
|
+
e: void 0,
|
|
127
|
+
t: void 0,
|
|
128
|
+
a: void 0,
|
|
129
|
+
o: void 0,
|
|
130
|
+
i: void 0,
|
|
131
|
+
n: void 0
|
|
132
|
+
});
|
|
133
|
+
return _el$10;
|
|
134
|
+
})()
|
|
135
|
+
);
|
|
136
|
+
},
|
|
137
|
+
get children() {
|
|
138
|
+
var _el$5 = getNextElement(_tmpl$2);
|
|
139
|
+
effect((_p$) => {
|
|
140
|
+
var _a;
|
|
141
|
+
var _v$ = embedUrl(), _v$2 = ((_a = params()) == null ? void 0 : _a.title) || "Video";
|
|
142
|
+
_v$ !== _p$.e && setAttribute(_el$5, "src", _p$.e = _v$);
|
|
143
|
+
_v$2 !== _p$.t && setAttribute(_el$5, "title", _p$.t = _v$2);
|
|
144
|
+
return _p$;
|
|
145
|
+
}, {
|
|
146
|
+
e: void 0,
|
|
147
|
+
t: void 0
|
|
148
|
+
});
|
|
149
|
+
return _el$5;
|
|
150
|
+
}
|
|
151
|
+
}));
|
|
152
|
+
insert(_el$, createComponent(Show, {
|
|
153
|
+
get when() {
|
|
154
|
+
var _a;
|
|
155
|
+
return (_a = params()) == null ? void 0 : _a.caption;
|
|
156
|
+
},
|
|
157
|
+
get children() {
|
|
158
|
+
var _el$6 = getNextElement(_tmpl$3), _el$7 = _el$6.firstChild;
|
|
159
|
+
insert(_el$7, () => params().caption);
|
|
160
|
+
return _el$6;
|
|
161
|
+
}
|
|
162
|
+
}), _el$1, _co$2);
|
|
163
|
+
effect((_p$) => {
|
|
164
|
+
var _v$3 = `w-full bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700 overflow-hidden ${isExpanded() ? "flex-1 min-h-0 flex flex-col" : ""}`, _v$4 = `relative bg-black ${isExpanded() ? "flex-1 min-h-0" : aspectClass()}`;
|
|
165
|
+
_v$3 !== _p$.e && className(_el$, _p$.e = _v$3);
|
|
166
|
+
_v$4 !== _p$.t && className(_el$4, _p$.t = _v$4);
|
|
167
|
+
return _p$;
|
|
168
|
+
}, {
|
|
169
|
+
e: void 0,
|
|
170
|
+
t: void 0
|
|
171
|
+
});
|
|
172
|
+
return _el$;
|
|
173
|
+
}
|
|
174
|
+
});
|
|
154
175
|
};
|
|
155
176
|
function isSupportedVideoUrl(url) {
|
|
156
177
|
const info = parseVideoUrl(url);
|
|
@@ -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'\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/**\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\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 <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 {/* 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 */}\n <div class={`relative ${aspectClass()} bg-black`}>\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\">\n <p class=\"text-sm text-gray-600 dark:text-gray-400\">{params()!.caption}</p>\n </div>\n </Show>\n </div>\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","videoInfo","createMemo","embedUrl","info","p","ytParams","URLSearchParams","autoplay","controls","loop","mute","muted","startTime","set","String","vParams","aspectClass","aspectRatio","handleVideoError","e","error","Error","console","onError","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_$insert","_$createComponent","Show","when","title","children","_el$2","_tmpl$","_el$3","fallback","_el$10","_tmpl$5","addEventListener","_$effect","_p$","_v$3","_v$4","poster","_v$5","_v$6","_v$7","_v$8","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","caption","_el$6","_tmpl$3","_el$7","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VideoRenderer.js","sources":["../../src/components/VideoRenderer.tsx"],"sourcesContent":["/**\n * VideoRenderer - Video embed component\n * Sprint 5: Media Components\n *\n * Supports YouTube, Vimeo, and direct video files\n */\n\nimport { Component, createMemo, Show } from 'solid-js'\nimport type { UIComponent, VideoComponentParams } from '../types'\nimport { ExpandableWrapper, useExpanded } from './ExpandableWrapper'\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/**\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 >\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","children","_el$","_$getNextElement","_tmpl$4","_el$8","firstChild","_el$9","_co$","_$getNextMarker","nextSibling","_el$4","_el$0","_el$1","_co$2","_$insert","Show","when","_el$2","_tmpl$","_el$3","fallback","_el$10","_tmpl$5","addEventListener","_$effect","_p$","_v$5","_v$6","poster","_v$7","_v$8","_v$9","_v$0","_$setAttribute","t","a","_$setProperty","o","i","n","undefined","_el$5","_tmpl$2","_v$","_v$2","caption","_el$6","_tmpl$3","_el$7","_v$3","_v$4","_$className","isSupportedVideoUrl","getVideoProvider"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -15,6 +15,7 @@ require("./components/ActionGroupRenderer.cjs");
|
|
|
15
15
|
require("./components/ChartJSRenderer.cjs");
|
|
16
16
|
require("./components/LightboxOverlay.cjs");
|
|
17
17
|
require("./components/ImageGalleryRenderer.cjs");
|
|
18
|
+
const ExpandableWrapper = require("./components/ExpandableWrapper.cjs");
|
|
18
19
|
require("./components/CodeBlockRenderer.cjs");
|
|
19
20
|
const AgentCard = require("./components/AgentCard.cjs");
|
|
20
21
|
const SplitStepper = require("./components/SplitStepper.cjs");
|
|
@@ -26,7 +27,6 @@ const ElicitationForm = require("./components/ElicitationForm.cjs");
|
|
|
26
27
|
const DraggableGridItem = require("./components/DraggableGridItem.cjs");
|
|
27
28
|
const ResizeHandle = require("./components/ResizeHandle.cjs");
|
|
28
29
|
const EditableUIResourceRenderer = require("./components/EditableUIResourceRenderer.cjs");
|
|
29
|
-
const ExpandableWrapper = require("./components/ExpandableWrapper.cjs");
|
|
30
30
|
const ComponentToolbar = require("./components/ComponentToolbar.cjs");
|
|
31
31
|
const FeedbackInline = require("./components/FeedbackInline.cjs");
|
|
32
32
|
const useChatBus = require("./hooks/useChatBus.cjs");
|
|
@@ -66,6 +66,8 @@ exports.UIResourceRenderer = UIResourceRenderer.UIResourceRenderer;
|
|
|
66
66
|
exports.renderCellValue = UIResourceRenderer.renderCellValue;
|
|
67
67
|
exports.StreamingUIRenderer = StreamingUIRenderer.StreamingUIRenderer;
|
|
68
68
|
exports.GenerativeUIErrorBoundary = GenerativeUIErrorBoundary.GenerativeUIErrorBoundary;
|
|
69
|
+
exports.ExpandableWrapper = ExpandableWrapper.ExpandableWrapper;
|
|
70
|
+
exports.useExpanded = ExpandableWrapper.useExpanded;
|
|
69
71
|
exports.AgentCard = AgentCard.AgentCard;
|
|
70
72
|
exports.AgentStatusBadge = AgentCard.AgentStatusBadge;
|
|
71
73
|
exports.SplitStepper = SplitStepper.SplitStepper;
|
|
@@ -77,8 +79,6 @@ exports.ElicitationForm = ElicitationForm.ElicitationForm;
|
|
|
77
79
|
exports.DraggableGridItem = DraggableGridItem.DraggableGridItem;
|
|
78
80
|
exports.ResizeHandle = ResizeHandle.ResizeHandle;
|
|
79
81
|
exports.EditableUIResourceRenderer = EditableUIResourceRenderer.EditableUIResourceRenderer;
|
|
80
|
-
exports.ExpandableWrapper = ExpandableWrapper.ExpandableWrapper;
|
|
81
|
-
exports.useExpanded = ExpandableWrapper.useExpanded;
|
|
82
82
|
exports.ComponentToolbar = ComponentToolbar.ComponentToolbar;
|
|
83
83
|
exports.FeedbackInline = FeedbackInline.FeedbackInline;
|
|
84
84
|
exports.ChatBusProvider = useChatBus.ChatBusProvider;
|
package/dist/index.js
CHANGED
|
@@ -13,6 +13,7 @@ import "./components/ActionGroupRenderer.js";
|
|
|
13
13
|
import "./components/ChartJSRenderer.js";
|
|
14
14
|
import "./components/LightboxOverlay.js";
|
|
15
15
|
import "./components/ImageGalleryRenderer.js";
|
|
16
|
+
import { ExpandableWrapper, useExpanded } from "./components/ExpandableWrapper.js";
|
|
16
17
|
import "./components/CodeBlockRenderer.js";
|
|
17
18
|
import { AgentCard, AgentStatusBadge } from "./components/AgentCard.js";
|
|
18
19
|
import { SplitStepper } from "./components/SplitStepper.js";
|
|
@@ -24,7 +25,6 @@ import { ElicitationForm } from "./components/ElicitationForm.js";
|
|
|
24
25
|
import { DraggableGridItem } from "./components/DraggableGridItem.js";
|
|
25
26
|
import { ResizeHandle } from "./components/ResizeHandle.js";
|
|
26
27
|
import { EditableUIResourceRenderer } from "./components/EditableUIResourceRenderer.js";
|
|
27
|
-
import { ExpandableWrapper, useExpanded } from "./components/ExpandableWrapper.js";
|
|
28
28
|
import { ComponentToolbar } from "./components/ComponentToolbar.js";
|
|
29
29
|
import { FeedbackInline } from "./components/FeedbackInline.js";
|
|
30
30
|
import { ChatBusProvider, useChatBus } from "./hooks/useChatBus.js";
|
|
@@ -434,7 +434,14 @@ types.object({
|
|
|
434
434
|
exportable: TableExportableSchema.optional(),
|
|
435
435
|
className: types.string().optional(),
|
|
436
436
|
// v5.0.3 — opt-in citation chip rendering inside cells
|
|
437
|
-
citationMap: types.record(types.string(), CitationEntrySchema).optional()
|
|
437
|
+
citationMap: types.record(types.string(), CitationEntrySchema).optional(),
|
|
438
|
+
// v5.0.5 — opt-out of the inline-mode max-height cap. The library defaults
|
|
439
|
+
// a `max-height: 400px` (or 500px when virtualizing) on tables with > 8
|
|
440
|
+
// rows so they don't blow out a chat-stream layout. Pass `'auto'` to
|
|
441
|
+
// disable the cap (when the consumer's wrapping container handles
|
|
442
|
+
// overflow), a number (interpreted as `${n}px`), or any CSS length string
|
|
443
|
+
// to override the value.
|
|
444
|
+
maxHeight: types.union([types.literal("auto"), types.number(), types.string()]).optional()
|
|
438
445
|
});
|
|
439
446
|
const MetricTrendSchema = types.object({
|
|
440
447
|
value: types.number(),
|