mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
feat(core): add vimeo media host and html/react components (#1667)
This commit is contained in:
@@ -12,4 +12,5 @@ export const PRESETS = [
|
||||
'dash-video',
|
||||
'audio',
|
||||
'background-video',
|
||||
'vimeo-video',
|
||||
] as const;
|
||||
|
||||
@@ -79,6 +79,8 @@ export const DEFAULT_DASH_SOURCE: SourceId = 'dash-1';
|
||||
|
||||
export const BACKGROUND_VIDEO_SRC = 'https://stream.mux.com/Sc89iWAyNkhJ3P1rQ02nrEdCFTnfT01CZ2KmaEcxXfB008/low.mp4';
|
||||
|
||||
export const VIMEO_VIDEO_SRC = 'https://vimeo.com/648359100';
|
||||
|
||||
/** Returns true when the given source represents a live stream and should use the live-video skin. */
|
||||
export function isLiveSource(id: SourceId): boolean {
|
||||
return (SOURCES[id] as { live?: boolean }).live === true;
|
||||
|
||||
@@ -18,6 +18,7 @@ import { Preview } from './preview';
|
||||
function getPagePath(platform: Platform, preset: Preset): string {
|
||||
if (platform === 'cdn') return '/cdn/';
|
||||
if (preset === 'background-video') return `/${platform}-background-video/`;
|
||||
if (preset === 'vimeo-video') return `/${platform}-vimeo-video/`;
|
||||
return `/${platform}-${preset}/`;
|
||||
}
|
||||
|
||||
@@ -113,9 +114,9 @@ export function App() {
|
||||
}
|
||||
}, [preset, source, setSource]);
|
||||
|
||||
// CDN and background video do not have a Tailwind skin variant.
|
||||
// CDN, background video, and vimeo video do not have a Tailwind skin variant.
|
||||
useEffect(() => {
|
||||
if ((platform === 'cdn' || preset === 'background-video') && styling === 'tailwind') {
|
||||
if ((platform === 'cdn' || preset === 'background-video' || preset === 'vimeo-video') && styling === 'tailwind') {
|
||||
setStyling('css');
|
||||
}
|
||||
}, [platform, preset, styling]);
|
||||
@@ -151,6 +152,7 @@ export function App() {
|
||||
isSimpleHls={preset.startsWith('simple-hls-')}
|
||||
isMuxVideo={preset === 'mux-video'}
|
||||
isMuxAudio={preset === 'mux-audio'}
|
||||
isVimeoVideo={preset === 'vimeo-video'}
|
||||
platforms={PLATFORMS}
|
||||
stylings={STYLINGS}
|
||||
presets={PRESETS}
|
||||
|
||||
@@ -28,6 +28,7 @@ type NavbarProps = {
|
||||
isSimpleHls: boolean;
|
||||
isMuxVideo: boolean;
|
||||
isMuxAudio: boolean;
|
||||
isVimeoVideo: boolean;
|
||||
platforms: readonly Platform[];
|
||||
stylings: readonly Styling[];
|
||||
presets: readonly Preset[];
|
||||
@@ -53,6 +54,7 @@ const PRESET_LABELS: Record<Preset, string> = {
|
||||
'dash-video': 'DASH Video',
|
||||
audio: 'Audio',
|
||||
'background-video': 'Background Video',
|
||||
'vimeo-video': 'Vimeo Video',
|
||||
};
|
||||
|
||||
export function Navbar({
|
||||
@@ -79,6 +81,7 @@ export function Navbar({
|
||||
isSimpleHls,
|
||||
isMuxVideo,
|
||||
isMuxAudio,
|
||||
isVimeoVideo,
|
||||
platforms,
|
||||
stylings,
|
||||
presets,
|
||||
@@ -107,7 +110,7 @@ export function Navbar({
|
||||
options={stylings.map((s) => ({
|
||||
value: s,
|
||||
label: s === 'css' ? 'CSS' : 'Tailwind',
|
||||
disabled: s === 'tailwind' && (isBackgroundVideo || platform === 'cdn'),
|
||||
disabled: s === 'tailwind' && (isBackgroundVideo || isVimeoVideo || platform === 'cdn'),
|
||||
}))}
|
||||
/>
|
||||
|
||||
@@ -137,7 +140,7 @@ export function Navbar({
|
||||
return true;
|
||||
})
|
||||
.map((id) => ({ value: id, label: sources[id].label }))}
|
||||
disabled={isBackgroundVideo}
|
||||
disabled={isBackgroundVideo || isVimeoVideo}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sandbox — HTML Vimeo Video</title>
|
||||
<link rel="preconnect" href="https://rsms.me/" />
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||
</head>
|
||||
<body class="font-sans p-2">
|
||||
<div id="root" class="flex justify-center items-center min-h-screen"></div>
|
||||
<script type="module" src="./main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,32 @@
|
||||
import '@app/styles.css';
|
||||
import '@videojs/html/video/player';
|
||||
import '@videojs/html/media/vimeo-video';
|
||||
import { createHtmlSandboxState, createLatestLoader } from '@app/shared/html/sandbox-state';
|
||||
import { loadVideoSkinTag } from '@app/shared/html/skins';
|
||||
import { onSkinChange } from '@app/shared/sandbox-listener';
|
||||
import { VIMEO_VIDEO_SRC } from '@app/shared/sources';
|
||||
|
||||
const html = String.raw;
|
||||
|
||||
const state = createHtmlSandboxState();
|
||||
const loadLatest = createLatestLoader();
|
||||
|
||||
async function render() {
|
||||
const tag = await loadLatest(() => loadVideoSkinTag(state.skin, state.styling));
|
||||
if (!tag) return;
|
||||
|
||||
document.getElementById('root')!.innerHTML = html`
|
||||
<video-player>
|
||||
<${tag} class="aspect-video max-w-4xl mx-auto">
|
||||
<vimeo-video class="block w-full h-full" src="${VIMEO_VIDEO_SRC}" playsinline></vimeo-video>
|
||||
</${tag}>
|
||||
</video-player>
|
||||
`;
|
||||
}
|
||||
|
||||
render();
|
||||
|
||||
onSkinChange((skin) => {
|
||||
state.skin = skin;
|
||||
render();
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Sandbox — React Vimeo Video</title>
|
||||
<link rel="preconnect" href="https://rsms.me/" />
|
||||
<link rel="stylesheet" href="https://rsms.me/inter/inter.css" />
|
||||
</head>
|
||||
<body class="font-sans p-2">
|
||||
<div id="root" class="flex justify-center items-center min-h-screen"></div>
|
||||
<script type="module" src="./main.tsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,28 @@
|
||||
import '@app/styles.css';
|
||||
import { VideoProvider } from '@app/shared/react/providers';
|
||||
import { VideoSkinComponent } from '@app/shared/react/skins';
|
||||
import { useSkin } from '@app/shared/react/use-skin';
|
||||
import { VIMEO_VIDEO_SRC } from '@app/shared/sources';
|
||||
import type { Styling } from '@app/types';
|
||||
import { VimeoVideo } from '@videojs/react/media/vimeo-video';
|
||||
import { useMemo } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
function readStyling(): Styling {
|
||||
return new URLSearchParams(location.search).get('styling') === 'tailwind' ? 'tailwind' : 'css';
|
||||
}
|
||||
|
||||
function App() {
|
||||
const skin = useSkin();
|
||||
const styling = useMemo(readStyling, []);
|
||||
|
||||
return (
|
||||
<VideoProvider>
|
||||
<VideoSkinComponent skin={skin} styling={styling} className="aspect-video max-w-4xl mx-auto">
|
||||
<VimeoVideo className="block w-full h-full" src={VIMEO_VIDEO_SRC} playsInline />
|
||||
</VideoSkinComponent>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById('root')!).render(<App />);
|
||||
Reference in New Issue
Block a user