mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
147 lines
4.8 KiB
TypeScript
147 lines
4.8 KiB
TypeScript
import { useStore } from '@nanostores/react';
|
|
import ClientCode from '@/components/Code/ClientCode';
|
|
import { Tab, TabsList, TabsPanel, TabsRoot } from '@/components/Tabs';
|
|
import type { Renderer, Skin, UseCase } from '@/stores/installation';
|
|
import { renderer, skin, useCase } from '@/stores/installation';
|
|
|
|
function getRendererComponent(renderer: Renderer): string {
|
|
const map: Record<Renderer, string> = {
|
|
'background-video': 'BackgroundVideo',
|
|
// cloudflare: 'CloudflareVideo',
|
|
// dash: 'DashVideo',
|
|
hls: 'HlsVideo',
|
|
'html5-audio': 'Audio',
|
|
'html5-video': 'Video',
|
|
// jwplayer: 'JwplayerVideo',
|
|
// mux-audio: 'MuxAudio',
|
|
// mux-background-video: 'MuxBackgroundVideo',
|
|
// mux-video: 'MuxVideo',
|
|
// shaka: 'ShakaVideo',
|
|
// spotify: 'SpotifyAudio',
|
|
// vimeo: 'VimeoVideo',
|
|
// wistia: 'WistiaVideo',
|
|
// youtube: 'YoutubeVideo',
|
|
};
|
|
return map[renderer];
|
|
}
|
|
|
|
function getSkinComponent(skin: Skin): string {
|
|
const map: Record<Skin, string> = {
|
|
video: 'VideoSkin',
|
|
audio: 'AudioSkin',
|
|
'minimal-video': 'MinimalVideoSkin',
|
|
'minimal-audio': 'MinimalAudioSkin',
|
|
};
|
|
return map[skin];
|
|
}
|
|
|
|
function getSkinImportParts(skin: Skin): { group: string; skinFile: string } {
|
|
if (skin === 'minimal-video') return { group: 'video', skinFile: 'minimal-skin' };
|
|
if (skin === 'minimal-audio') return { group: 'audio', skinFile: 'minimal-skin' };
|
|
return { group: skin, skinFile: 'skin' };
|
|
}
|
|
|
|
function getUseCaseFeatures(useCase: UseCase): string {
|
|
const map: Record<UseCase, string> = {
|
|
'default-video': 'videoFeatures',
|
|
'default-audio': 'audioFeatures',
|
|
'background-video': 'backgroundFeatures',
|
|
};
|
|
return map[useCase];
|
|
}
|
|
|
|
function isPresetRenderer(renderer: Renderer): boolean {
|
|
return renderer === 'html5-video' || renderer === 'html5-audio' || renderer === 'background-video';
|
|
}
|
|
|
|
function getRendererMediaSubpath(renderer: Renderer): string {
|
|
const map: Partial<Record<Renderer, string>> = {
|
|
// cloudflare: 'cloudflare-video',
|
|
// dash: 'dash-video',
|
|
hls: 'hls-video',
|
|
// jwplayer: 'jwplayer-video',
|
|
// 'mux-audio': 'mux-audio',
|
|
// 'mux-background-video': 'mux-background-video',
|
|
// 'mux-video': 'mux-video',
|
|
// spotify: 'spotify-audio',
|
|
// vimeo: 'vimeo-video',
|
|
// wistia: 'wistia-video',
|
|
// youtube: 'youtube-video',
|
|
};
|
|
return map[renderer] ?? renderer;
|
|
}
|
|
|
|
function generateReactCode(useCase: UseCase, skin: Skin, renderer: Renderer): string {
|
|
const rendererComponent = getRendererComponent(renderer);
|
|
const featureType = getUseCaseFeatures(useCase);
|
|
|
|
// Background video has fixed skin and subpath imports, others use skin picker value
|
|
const isBackgroundVideo = useCase === 'background-video';
|
|
const skinComponent = isBackgroundVideo ? 'BackgroundVideoSkin' : getSkinComponent(skin);
|
|
const { group, skinFile } = getSkinImportParts(skin);
|
|
const skinCssImport = isBackgroundVideo
|
|
? '@videojs/react/background/skin.css'
|
|
: `@videojs/react/${group}/${skinFile}.css`;
|
|
|
|
// Preset subpath where skin + default media components live
|
|
const presetSubpath = isBackgroundVideo ? 'background' : group;
|
|
|
|
// Skin and media imports — preset renderers share a subpath with the skin
|
|
let presetImport: string;
|
|
let mediaImport: string | null = null;
|
|
|
|
if (isPresetRenderer(renderer)) {
|
|
presetImport = `import { ${skinComponent}, ${rendererComponent} } from '@videojs/react/${presetSubpath}';`;
|
|
} else {
|
|
presetImport = `import { ${skinComponent} } from '@videojs/react/${presetSubpath}';`;
|
|
mediaImport = `import { ${rendererComponent} } from '@videojs/react/media/${getRendererMediaSubpath(renderer)}';`;
|
|
}
|
|
|
|
// Determine props — mux variants use src with stream.mux.com URL
|
|
const propsInterface = 'interface MyPlayerProps {\n src: string;\n}';
|
|
const destructuredProp = 'src';
|
|
const rendererJsx = `<${rendererComponent} src={src} />`;
|
|
|
|
const imports = [
|
|
`import '${skinCssImport}';`,
|
|
`import { createPlayer, ${featureType} } from '@videojs/react';`,
|
|
presetImport,
|
|
...(mediaImport ? [mediaImport] : []),
|
|
].join('\n');
|
|
|
|
return `${imports}
|
|
|
|
const Player = createPlayer({ features: ${featureType} });
|
|
|
|
${propsInterface}
|
|
|
|
export const MyPlayer = ({ ${destructuredProp} }: MyPlayerProps) => {
|
|
return (
|
|
<Player.Provider>
|
|
<${skinComponent}>
|
|
${rendererJsx}
|
|
</${skinComponent}>
|
|
</Player.Provider>
|
|
);
|
|
};`;
|
|
}
|
|
|
|
export default function ReactCreateCodeBlock() {
|
|
const $useCase = useStore(useCase);
|
|
const $skin = useStore(skin);
|
|
const $renderer = useStore(renderer);
|
|
|
|
return (
|
|
<TabsRoot maxWidth={false}>
|
|
<TabsList label="React implementation">
|
|
<Tab value="react" initial>
|
|
./components/player/index.tsx
|
|
</Tab>
|
|
</TabsList>
|
|
<TabsPanel value="react" initial>
|
|
<ClientCode code={generateReactCode($useCase, $skin, $renderer)} lang="tsx" />
|
|
</TabsPanel>
|
|
</TabsRoot>
|
|
);
|
|
}
|