mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 05:37:21 +00:00
fix(react, html): rename MediaProvider (and related) to VideoProvider (#159)
This commit is contained in:
@@ -3,18 +3,18 @@ import '@videojs/html/skins/minimal';
|
||||
|
||||
document.body.innerHTML = /* html */ `
|
||||
<div style="display: flex; flex-direction: column; justify-content: center; min-height: 100vh; gap: 2rem; padding: 1rem; ">
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<media-skin-frosted style="border-radius: 2rem; width: 100%; max-width: 960px; margin: 2rem auto; aspect-ratio: 16/9">
|
||||
<video
|
||||
<video
|
||||
slot="media"
|
||||
src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/high.mp4"
|
||||
poster="https://image.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ/thumbnail.webp"
|
||||
playsinline
|
||||
></video>
|
||||
</media-skin-frosted>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<media-skin-minimal style="border-radius: 0.75rem; width: 100%; max-width: 960px; margin: 2rem auto; aspect-ratio: 16/9">
|
||||
<video
|
||||
slot="media"
|
||||
@@ -23,6 +23,6 @@ document.body.innerHTML = /* html */ `
|
||||
playsinline
|
||||
></video>
|
||||
</media-skin-minimal>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
</div>
|
||||
`;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import './frosted.css';
|
||||
import '@videojs/html/icons';
|
||||
// be sure to import media-provider first
|
||||
import '@videojs/html/define/media-provider';
|
||||
// be sure to import video-provider first
|
||||
import '@videojs/html/define/video-provider';
|
||||
import '@videojs/html/define/media-container';
|
||||
import '@videojs/html/define/media-play-button';
|
||||
import '@videojs/html/define/media-mute-button';
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
padding: 1rem;
|
||||
"
|
||||
>
|
||||
<media-provider style="display: block">
|
||||
<video-provider style="display: block">
|
||||
<media-container
|
||||
style="
|
||||
display: block;
|
||||
@@ -143,7 +143,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</media-container>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
</div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import './minimal.css';
|
||||
import '@videojs/html/icons';
|
||||
// be sure to import media-provider first
|
||||
import '@videojs/html/define/media-provider';
|
||||
// be sure to import video-provider first
|
||||
import '@videojs/html/define/video-provider';
|
||||
import '@videojs/html/define/media-container';
|
||||
import '@videojs/html/define/media-play-button';
|
||||
import '@videojs/html/define/media-mute-button';
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FrostedSkin, MediaProvider, MinimalSkin, Video } from '@videojs/react';
|
||||
import { FrostedSkin, MinimalSkin, Video, VideoProvider } from '@videojs/react';
|
||||
import '@videojs/react/skins/frosted.css';
|
||||
import '@videojs/react/skins/minimal.css';
|
||||
|
||||
@@ -6,19 +6,19 @@ export default function Home() {
|
||||
return (
|
||||
<main className="p-4">
|
||||
<h1 className="text-4xl font-extrabold py-2">Frosted Skin</h1>
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<FrostedSkin>
|
||||
{/* @ts-expect-error -- types are incorrect */}
|
||||
<Video src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ.m3u8" playsInline />
|
||||
</FrostedSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
<h1 className="text-4xl font-extrabold py-2">Minimal Skin</h1>
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MinimalSkin>
|
||||
{/* @ts-expect-error -- types are incorrect */}
|
||||
<Video src="https://stream.mux.com/fXNzVtmtWuyz00xnSrJg4OJH6PyNo6D02UzmgeKGkP5YQ.m3u8" playsInline />
|
||||
</MinimalSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { ChangeEventHandler } from 'react';
|
||||
|
||||
import { FrostedSkin, MediaProvider, MinimalSkin, Video } from '@videojs/react';
|
||||
import { FrostedSkin, MinimalSkin, Video, VideoProvider } from '@videojs/react';
|
||||
import { FullscreenEnterAltIcon, FullscreenExitAltIcon } from '@videojs/react/icons';
|
||||
import clsx from 'clsx';
|
||||
|
||||
@@ -8,7 +8,7 @@ import clsx from 'clsx';
|
||||
// import MinimalSkin from './skins/toasted/MinimalSkin';
|
||||
|
||||
// NOTE: Commented out imports are for testing locally/externally defined skins.
|
||||
// import { MediaProvider, Video } from '@videojs/react';
|
||||
// import { VideoProvider, Video } from '@videojs/react';
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useFullscreen } from './hooks/useFullscreen';
|
||||
import '@videojs/react/skins/frosted.css';
|
||||
@@ -182,12 +182,12 @@ export default function App(): JSX.Element {
|
||||
)}
|
||||
>
|
||||
<div className="w-full max-w-5xl mx-auto p-6">
|
||||
<MediaProvider key={key}>
|
||||
<VideoProvider key={key}>
|
||||
<Skin className={skinClassName}>
|
||||
{/* @ts-expect-error -- types are incorrect */}
|
||||
<Video src={mediaSource} poster={poster} playsInline />
|
||||
</Skin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MediaProvider, Video } from '@videojs/react';
|
||||
import { Video, VideoProvider } from '@videojs/react';
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
@@ -6,7 +6,7 @@ import FrostedSkin from './FrostedSkin';
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<FrostedSkin>
|
||||
<Video
|
||||
// @ts-expect-error -- types are incorrect
|
||||
@@ -15,6 +15,6 @@ createRoot(document.getElementById('root')!).render(
|
||||
playsInline
|
||||
/>
|
||||
</FrostedSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
</StrictMode>,
|
||||
);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MediaProvider, Video } from '@videojs/react';
|
||||
import { Video, VideoProvider } from '@videojs/react';
|
||||
import { StrictMode } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
@@ -6,7 +6,7 @@ import MinimalSkin from './MinimalSkin';
|
||||
|
||||
createRoot(document.getElementById('root')!).render(
|
||||
<StrictMode>
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MinimalSkin>
|
||||
<Video
|
||||
// @ts-expect-error -- types are incorrect
|
||||
@@ -15,6 +15,6 @@ createRoot(document.getElementById('root')!).render(
|
||||
playsInline
|
||||
/>
|
||||
</MinimalSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
</StrictMode>,
|
||||
);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import './media-container';
|
||||
import './media-provider';
|
||||
import './video-provider';
|
||||
import './media-play-button';
|
||||
import './media-mute-button';
|
||||
import './media-volume-slider';
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
import { MediaProviderElement } from '@/media/media-provider';
|
||||
import { defineCustomElement } from '@/utils/custom-element';
|
||||
|
||||
defineCustomElement('media-provider', MediaProviderElement);
|
||||
@@ -0,0 +1,4 @@
|
||||
import { VideoProviderElement } from '@/media/video-provider';
|
||||
import { defineCustomElement } from '@/utils/custom-element';
|
||||
|
||||
defineCustomElement('video-provider', VideoProviderElement);
|
||||
@@ -9,5 +9,5 @@ export { TimeSliderElement } from './elements/time-slider';
|
||||
export { TooltipElement } from './elements/tooltip';
|
||||
export { VolumeSliderElement } from './elements/volume-slider';
|
||||
export { MediaContainerElement } from './media/media-container';
|
||||
export { MediaProviderElement } from './media/media-provider';
|
||||
export { MediaSkinElement } from './media/media-skin';
|
||||
export { VideoProviderElement } from './media/video-provider';
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import { createMediaStore } from '@videojs/core/store';
|
||||
|
||||
const ProviderHTMLElement: Constructor<CustomElement & HTMLElement> = ProviderMixin(HTMLElement);
|
||||
|
||||
export class MediaProviderElement extends ProviderHTMLElement {
|
||||
export class VideoProviderElement extends ProviderHTMLElement {
|
||||
contexts = {
|
||||
mediaStore: (): MediaStore => {
|
||||
return createMediaStore();
|
||||
@@ -2,7 +2,7 @@ import { MediaSkinElement } from '@/media/media-skin';
|
||||
import { defineCustomElement } from '@/utils/custom-element';
|
||||
import styles from './styles.css';
|
||||
import '@/define/media-container';
|
||||
import '@/define/media-provider';
|
||||
import '@/define/video-provider';
|
||||
import '@/define/media-play-button';
|
||||
import '@/define/media-mute-button';
|
||||
import '@/define/media-volume-slider';
|
||||
@@ -56,7 +56,7 @@ export function getTemplateHTML() {
|
||||
</media-time-slider-track>
|
||||
<media-time-slider-thumb class="slider-thumb"></media-time-slider-thumb>
|
||||
</media-time-slider>
|
||||
<media-tooltip
|
||||
<media-tooltip
|
||||
id="time-slider-tooltip"
|
||||
class="surface popup-animation"
|
||||
popover="manual"
|
||||
@@ -76,9 +76,9 @@ export function getTemplateHTML() {
|
||||
<media-volume-low-icon class="icon volume-low-icon"></media-volume-low-icon>
|
||||
<media-volume-off-icon class="icon volume-off-icon"></media-volume-off-icon>
|
||||
</media-mute-button>
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
class="surface popup-animation"
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
class="surface popup-animation"
|
||||
popover="manual"
|
||||
open-on-hover
|
||||
delay="200"
|
||||
@@ -99,7 +99,7 @@ export function getTemplateHTML() {
|
||||
<media-fullscreen-enter-icon class="icon fullscreen-enter-icon"></media-fullscreen-enter-icon>
|
||||
<media-fullscreen-exit-icon class="icon fullscreen-exit-icon"></media-fullscreen-exit-icon>
|
||||
</media-fullscreen-button>
|
||||
<media-tooltip
|
||||
<media-tooltip
|
||||
id="fullscreen-tooltip"
|
||||
class="surface popup-animation"
|
||||
popover="manual"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { MediaSkinElement } from '@/media/media-skin';
|
||||
import { defineCustomElement } from '@/utils/custom-element';
|
||||
import styles from './styles.css';
|
||||
import '@/define/media-container';
|
||||
import '@/define/media-provider';
|
||||
import '@/define/video-provider';
|
||||
import '@/define/media-play-button';
|
||||
import '@/define/media-mute-button';
|
||||
import '@/define/media-volume-slider';
|
||||
@@ -63,7 +63,7 @@ export function getTemplateHTML() {
|
||||
</media-time-slider-track>
|
||||
<media-time-slider-thumb class="slider-thumb"></media-time-slider-thumb>
|
||||
</media-time-slider>
|
||||
<media-tooltip
|
||||
<media-tooltip
|
||||
id="time-slider-tooltip"
|
||||
class="popup-animation"
|
||||
popover="manual"
|
||||
@@ -81,8 +81,8 @@ export function getTemplateHTML() {
|
||||
<media-volume-low-icon class="icon volume-low-icon"></media-volume-low-icon>
|
||||
<media-volume-off-icon class="icon volume-off-icon"></media-volume-off-icon>
|
||||
</media-mute-button>
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
class="popup-animation"
|
||||
popover="manual"
|
||||
open-on-hover
|
||||
@@ -104,8 +104,8 @@ export function getTemplateHTML() {
|
||||
<media-fullscreen-enter-alt-icon class="icon fullscreen-enter-icon"></media-fullscreen-enter-alt-icon>
|
||||
<media-fullscreen-exit-alt-icon class="icon fullscreen-exit-icon"></media-fullscreen-exit-icon>
|
||||
</media-fullscreen-button>
|
||||
<media-tooltip
|
||||
id="fullscreen-tooltip"
|
||||
<media-tooltip
|
||||
id="fullscreen-tooltip"
|
||||
class="popup-animation"
|
||||
popover="manual"
|
||||
delay="500"
|
||||
|
||||
@@ -20,16 +20,16 @@ export type SimpleVideoProps = PropsWithChildren<
|
||||
* without using a playback engine. Use this for simple MP4 files. For HLS/DASH streaming, use the
|
||||
* regular Video component instead.
|
||||
*
|
||||
* This component connects to MediaProvider for play/pause state but sets the src directly on the
|
||||
* This component connects to VideoProvider for play/pause state but sets the src directly on the
|
||||
* video element without going through HLS.js or other playback engines.
|
||||
*
|
||||
* @example
|
||||
* ```tsx
|
||||
* <MediaProvider>
|
||||
* <VideoProvider>
|
||||
* <MediaSkin>
|
||||
* <SimpleVideo src="video.mp4" />
|
||||
* </MediaSkin>
|
||||
* </MediaProvider>
|
||||
* </VideoProvider>
|
||||
* ```
|
||||
*/
|
||||
export const SimpleVideo: React.ForwardRefExoticComponent<
|
||||
|
||||
@@ -69,7 +69,7 @@ const DefaultVideoComponent: ElementType<
|
||||
|
||||
/**
|
||||
* @description This is a "thin wrapper" around the media component whose primary responsibility is to wire up the element
|
||||
* to the <MediaProvider/>'s MediaStore for the media state.
|
||||
* to the <VideoProvider/>'s MediaStore for the media state.
|
||||
* @param props - Identical to both a <video/>'s props and the <Player/> props, with one addition that may be familiar to
|
||||
* MUI users: a `component` prop that allows you to use something other than the <video/> element under the hood.
|
||||
* @returns A media react component (e.g. <video/>), wired up as the media element.
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createContext } from 'react';
|
||||
* used "under the hood" for media ui state updates, state change requests, and the hooks and providers that integrate with this context.
|
||||
* It is unlikely that you will/should be using `MediaContext` directly.
|
||||
*
|
||||
* @see {@link MediaProvider}
|
||||
* @see {@link VideoProvider}
|
||||
* @see {@link useMediaDispatch}
|
||||
* @see {@link useMediaSelector}
|
||||
*/
|
||||
|
||||
@@ -8,8 +8,8 @@ export {
|
||||
useMediaStore,
|
||||
} from './hooks';
|
||||
export {
|
||||
MediaProvider,
|
||||
} from './media-provider';
|
||||
VideoProvider,
|
||||
} from './video-provider';
|
||||
|
||||
export type MediaStore = any;
|
||||
export type MediaState = any;
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import { createMediaStore } from '@videojs/core/store';
|
||||
import { useMemo } from 'react';
|
||||
import { MediaContext } from './context';
|
||||
|
||||
export function MediaProvider({ children }: { children: ReactNode }): JSX.Element {
|
||||
export function VideoProvider({ children }: { children: ReactNode }): JSX.Element {
|
||||
const value = useMemo(() => createMediaStore(), []);
|
||||
|
||||
// useEffect(() => {
|
||||
@@ -7,11 +7,11 @@ import ClientCode from '../Code/ClientCode';
|
||||
function generateHTMLCode(skin: Skin): string {
|
||||
const skinTag = `${skin}-skin`;
|
||||
|
||||
return `<media-provider>
|
||||
return `<video-provider>
|
||||
<${skinTag}>
|
||||
<video src="https://example.com/video.mp4"></video>
|
||||
</${skinTag}>
|
||||
</media-provider>`;
|
||||
</video-provider>`;
|
||||
}
|
||||
|
||||
function generateReactCode(skin: Skin): string {
|
||||
@@ -19,16 +19,16 @@ function generateReactCode(skin: Skin): string {
|
||||
const skinImport = skin === 'frosted' ? 'frosted' : 'minimal';
|
||||
|
||||
return `// npm install @videojs/react@next
|
||||
import { MediaProvider, ${skinComponent}, Video } from '@videojs/react';
|
||||
import { VideoProvider, ${skinComponent}, Video } from '@videojs/react';
|
||||
import '@videojs/react/skins/${skinImport}.css';
|
||||
|
||||
export const VideoPlayer = () => {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<${skinComponent}>
|
||||
<Video src="https://example.com/video.mp4" />
|
||||
</${skinComponent}>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
};`;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useStore } from '@nanostores/react';
|
||||
import { FrostedSkin, MediaProvider, MinimalSkin, Video } from '@videojs/react';
|
||||
import { FrostedSkin, MinimalSkin, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import { skin } from '@/stores/homePageDemos';
|
||||
import '@videojs/react/skins/frosted.css';
|
||||
@@ -11,7 +11,7 @@ export default function HeroVideo({ className, poster }: { className?: string; p
|
||||
const SkinComponent = $skin === 'frosted' ? FrostedSkin : MinimalSkin;
|
||||
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<SkinComponent className={className}>
|
||||
<Video
|
||||
// @ts-expect-error -- types are incorrect
|
||||
@@ -20,6 +20,6 @@ export default function HeroVideo({ className, poster }: { className?: string; p
|
||||
playsInline
|
||||
/>
|
||||
</SkinComponent>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -14,24 +14,24 @@ Video.js v10 is built around a three-tier architecture that separates concerns a
|
||||
### 1. State Management
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
State is handled by `MediaProvider`, which creates a central store that all components can access. When you wrap your player in a `MediaProvider`, components automatically connect to the state.
|
||||
State is handled by `VideoProvider`, which creates a central store that all components can access. When you wrap your player in a `VideoProvider`, components automatically connect to the state.
|
||||
</FrameworkCase>
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
State is handled by `media-provider`, which creates a central store that all components can access. When you wrap your player in a `media-provider`, components automatically connect to the state.
|
||||
State is handled by `video-provider`, which creates a central store that all components can access. When you wrap your player in a `video-provider`, components automatically connect to the state.
|
||||
</FrameworkCase>
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
```tsx
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
{/* All components inside automatically connect to state */}
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
```
|
||||
</FrameworkCase>
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
```html
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<!-- All components inside automatically connect to state -->
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
```
|
||||
</FrameworkCase>
|
||||
|
||||
@@ -74,19 +74,19 @@ Here's a complete example showing all three tiers:
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
```tsx
|
||||
import { MediaProvider, FrostedSkin, Video } from '@videojs/react';
|
||||
import { VideoProvider, FrostedSkin, Video } from '@videojs/react';
|
||||
import '@videojs/react/skins/frosted.css';
|
||||
|
||||
function Player() {
|
||||
return (
|
||||
// Tier 1: State Management
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
{/* Tier 2: User Interface (Skin with components) */}
|
||||
<FrostedSkin>
|
||||
{/* Tier 3: Media Renderer */}
|
||||
<Video src="video.mp4" />
|
||||
</FrostedSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -102,13 +102,13 @@ function Player() {
|
||||
|
||||
```html
|
||||
<!-- Tier 1: State Management -->
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<!-- Tier 2: User Interface (Skin with components) -->
|
||||
<media-skin-frosted>
|
||||
<!-- Tier 3: Media Renderer -->
|
||||
<video slot="media" src="video.mp4"></video>
|
||||
</media-skin-frosted>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
```
|
||||
|
||||
</TabsPanel>
|
||||
|
||||
@@ -32,23 +32,23 @@ A modern, glassy design with backdrop blur effects and polished interactions.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
```tsx
|
||||
import { MediaProvider, FrostedSkin, Video } from '@videojs/react';
|
||||
import { VideoProvider, FrostedSkin, Video } from '@videojs/react';
|
||||
import '@videojs/react/skins/frosted.css';
|
||||
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<FrostedSkin>
|
||||
<Video src="video.mp4" />
|
||||
</FrostedSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
```
|
||||
</FrameworkCase>
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
```html
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<media-skin-frosted>
|
||||
<video slot="media" src="video.mp4"></video>
|
||||
</media-skin-frosted>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
```
|
||||
</FrameworkCase>
|
||||
|
||||
@@ -62,23 +62,23 @@ A clean, straightforward design that focuses on simplicity and clarity.
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
```tsx
|
||||
import { MediaProvider, MinimalSkin, Video } from '@videojs/react';
|
||||
import { VideoProvider, MinimalSkin, Video } from '@videojs/react';
|
||||
import '@videojs/react/skins/minimal.css';
|
||||
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MinimalSkin>
|
||||
<Video src="video.mp4" />
|
||||
</MinimalSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
```
|
||||
</FrameworkCase>
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
```html
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<media-skin-minimal>
|
||||
<video slot="media" src="video.mp4"></video>
|
||||
</media-skin-minimal>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
```
|
||||
</FrameworkCase>
|
||||
|
||||
@@ -134,7 +134,7 @@ export function CustomSkin({ children, className }) {
|
||||
|
||||
<FrameworkCase frameworks={["html"]}>
|
||||
```html
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<media-container class="custom-skin">
|
||||
<slot></slot>
|
||||
<div class="controls">
|
||||
@@ -144,7 +144,7 @@ export function CustomSkin({ children, className }) {
|
||||
</media-time-slider>
|
||||
</div>
|
||||
</media-container>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
```
|
||||
</FrameworkCase>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ Welcome to Video.js v10! This guide will help you get up and running. In it, you
|
||||
|
||||
## 1. Pick Your Framework
|
||||
|
||||
Video.js v10 supports both React and vanilla JavaScript/HTML through Web Components.
|
||||
Video.js v10 supports both React and vanilla JavaScript/HTML through Web Components.
|
||||
|
||||
First, select your preferred framework in the framework selector at the top of the <span class="hidden lg:inline">sidebar</span><span class="lg:hidden">page</span>.
|
||||
|
||||
@@ -78,12 +78,12 @@ More renderers for formats like DASH, and services like YouTube and Vimeo are pl
|
||||
|
||||
<FrameworkCase frameworks={["react"]}>
|
||||
```tsx
|
||||
import { MediaProvider, FrostedSkin, Video } from '@videojs/react';
|
||||
import { VideoProvider, FrostedSkin, Video } from '@videojs/react';
|
||||
import '@videojs/react/skins/frosted.css';
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<FrostedSkin>
|
||||
<Video
|
||||
src="https://stream.mux.com/UZMwOY6MgmhFNXLbSFXAuPKlRPss5XNA.m3u8"
|
||||
@@ -91,7 +91,7 @@ export default function App() {
|
||||
playsInline
|
||||
/>
|
||||
</FrostedSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
```
|
||||
@@ -101,7 +101,7 @@ export default function App() {
|
||||
import '@videojs/html/skins/frosted';
|
||||
|
||||
document.body.innerHTML = `
|
||||
<media-provider>
|
||||
<video-provider>
|
||||
<media-skin-frosted>
|
||||
<video
|
||||
slot="media"
|
||||
@@ -110,7 +110,7 @@ document.body.innerHTML = `
|
||||
playsinline
|
||||
></video>
|
||||
</media-skin-frosted>
|
||||
</media-provider>
|
||||
</video-provider>
|
||||
`;
|
||||
```
|
||||
</FrameworkCase>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FrostedSkin, MediaProvider, Video } from '@videojs/react';
|
||||
import { FrostedSkin, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import '@videojs/react/skins/frosted.css';
|
||||
|
||||
@@ -14,7 +14,7 @@ import '@videojs/react/skins/frosted.css';
|
||||
*/
|
||||
export function FrostedSkinDemo() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<FrostedSkin className="w-full aspect-video rounded-3xl">
|
||||
<Video
|
||||
src={VJS8_DEMO_VIDEO.hls}
|
||||
@@ -22,6 +22,6 @@ export function FrostedSkinDemo() {
|
||||
playsInline
|
||||
/>
|
||||
</FrostedSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import styles from './FullscreenButton.module.css';
|
||||
* - Data attribute state selectors
|
||||
* - Enter/exit fullscreen functionality
|
||||
*
|
||||
* Note: This component must be used within a MediaProvider context.
|
||||
* Note: This component must be used within a VideoProvider context.
|
||||
* See the usage example in the documentation.
|
||||
*/
|
||||
export function BasicFullscreenButton() {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { MediaContainer, MediaProvider, Video } from '@videojs/react';
|
||||
import { MediaContainer, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import { BasicFullscreenButton } from './BasicFullscreenButton';
|
||||
|
||||
/**
|
||||
* Demo showing proper MediaProvider usage with FullscreenButton.
|
||||
* Demo showing proper VideoProvider usage with FullscreenButton.
|
||||
* The FullscreenButton automatically toggles fullscreen mode for
|
||||
* the containing MediaContainer.
|
||||
*/
|
||||
export function FullscreenButtonDemo() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MediaContainer style={{ position: 'relative', zIndex: 10 }}>
|
||||
<Video
|
||||
src={VJS8_DEMO_VIDEO.hls}
|
||||
@@ -20,6 +20,6 @@ export function FullscreenButtonDemo() {
|
||||
<BasicFullscreenButton />
|
||||
</div>
|
||||
</MediaContainer>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { MediaProvider, MinimalSkin, Video } from '@videojs/react';
|
||||
import { MinimalSkin, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import '@videojs/react/skins/minimal.css';
|
||||
|
||||
@@ -13,7 +13,7 @@ import '@videojs/react/skins/minimal.css';
|
||||
*/
|
||||
export function MinimalSkinDemo() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MinimalSkin className="w-full aspect-video">
|
||||
<Video
|
||||
src={VJS8_DEMO_VIDEO.hls}
|
||||
@@ -21,6 +21,6 @@ export function MinimalSkinDemo() {
|
||||
playsInline
|
||||
/>
|
||||
</MinimalSkin>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import styles from './MuteButton.module.css';
|
||||
* - Volume level data attributes
|
||||
* - Smooth icon transitions
|
||||
*
|
||||
* Note: This component must be used within a MediaProvider context.
|
||||
* Note: This component must be used within a VideoProvider context.
|
||||
* See the usage example in the documentation.
|
||||
*/
|
||||
export function BasicMuteButton() {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { MediaContainer, MediaProvider, Video } from '@videojs/react';
|
||||
import { MediaContainer, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import { BasicMuteButton } from './BasicMuteButton';
|
||||
|
||||
/**
|
||||
* Demo showing proper MediaProvider usage with MuteButton.
|
||||
* Demo showing proper VideoProvider usage with MuteButton.
|
||||
* The MuteButton automatically reflects the current volume state
|
||||
* and toggles mute/unmute on click.
|
||||
*/
|
||||
export function MuteButtonDemo() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MediaContainer style={{ position: 'relative', zIndex: 10 }}>
|
||||
<Video
|
||||
src={VJS8_DEMO_VIDEO.hls}
|
||||
@@ -20,6 +20,6 @@ export function MuteButtonDemo() {
|
||||
<BasicMuteButton />
|
||||
</div>
|
||||
</MediaContainer>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import styles from './PlayButton.module.css';
|
||||
* - CSS Modules for scoped styling
|
||||
* - Data attribute selectors for state-based styling
|
||||
*
|
||||
* Note: This component must be used within a MediaProvider context.
|
||||
* Note: This component must be used within a VideoProvider context.
|
||||
* See the usage example in the documentation.
|
||||
*/
|
||||
export function BasicPlayButton() {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { MediaContainer, MediaProvider, Video } from '@videojs/react';
|
||||
import { MediaContainer, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import { BasicPlayButton } from './BasicPlayButton';
|
||||
|
||||
/**
|
||||
* Demo showing proper MediaProvider usage with PlayButton.
|
||||
* The MediaProvider wraps the entire media experience and provides
|
||||
* Demo showing proper VideoProvider usage with PlayButton.
|
||||
* The VideoProvider wraps the entire media experience and provides
|
||||
* the necessary context for all media components.
|
||||
*/
|
||||
export function PlayButtonDemo() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MediaContainer style={{ position: 'relative', zIndex: 10 }}>
|
||||
<Video
|
||||
src={VJS8_DEMO_VIDEO.hls}
|
||||
@@ -20,6 +20,6 @@ export function PlayButtonDemo() {
|
||||
<BasicPlayButton />
|
||||
</div>
|
||||
</MediaContainer>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import styles from './TimeSlider.module.css';
|
||||
* - CSS Modules for scoped styling
|
||||
* - Data attribute selectors for state-based styling
|
||||
*
|
||||
* Note: This component must be used within a MediaProvider context.
|
||||
* Note: This component must be used within a VideoProvider context.
|
||||
* See the usage example in the documentation.
|
||||
*/
|
||||
export function BasicTimeSlider() {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { MediaContainer, MediaProvider, Video } from '@videojs/react';
|
||||
import { MediaContainer, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import { BasicTimeSlider } from './BasicTimeSlider';
|
||||
|
||||
/**
|
||||
* Demo showing proper MediaProvider usage with TimeSlider.
|
||||
* The MediaProvider wraps the entire media experience and provides
|
||||
* Demo showing proper VideoProvider usage with TimeSlider.
|
||||
* The VideoProvider wraps the entire media experience and provides
|
||||
* the necessary context for all media components.
|
||||
*/
|
||||
export function TimeSliderDemo() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MediaContainer style={{ position: 'relative', zIndex: 10 }}>
|
||||
<Video
|
||||
src={VJS8_DEMO_VIDEO.hls}
|
||||
@@ -20,6 +20,6 @@ export function TimeSliderDemo() {
|
||||
<BasicTimeSlider />
|
||||
</div>
|
||||
</MediaContainer>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import styles from './VolumeSlider.module.css';
|
||||
* - CSS Modules for scoped styling
|
||||
* - Data attribute selectors for state-based styling
|
||||
*
|
||||
* Note: This component must be used within a MediaProvider context.
|
||||
* Note: This component must be used within a VideoProvider context.
|
||||
* See the usage example in the documentation.
|
||||
*/
|
||||
export function BasicVolumeSlider() {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { MediaContainer, MediaProvider, Video } from '@videojs/react';
|
||||
import { MediaContainer, Video, VideoProvider } from '@videojs/react';
|
||||
import { VJS8_DEMO_VIDEO } from '@/consts';
|
||||
import { BasicVolumeSlider } from './BasicVolumeSlider';
|
||||
|
||||
/**
|
||||
* Demo showing proper MediaProvider usage with VolumeSlider.
|
||||
* The MediaProvider wraps the entire media experience and provides
|
||||
* Demo showing proper VideoProvider usage with VolumeSlider.
|
||||
* The VideoProvider wraps the entire media experience and provides
|
||||
* the necessary context for all media components.
|
||||
*/
|
||||
export function VolumeSliderDemo() {
|
||||
return (
|
||||
<MediaProvider>
|
||||
<VideoProvider>
|
||||
<MediaContainer style={{ position: 'relative', zIndex: 10 }}>
|
||||
<Video
|
||||
src={VJS8_DEMO_VIDEO.hls}
|
||||
@@ -20,6 +20,6 @@ export function VolumeSliderDemo() {
|
||||
<BasicVolumeSlider />
|
||||
</div>
|
||||
</MediaContainer>
|
||||
</MediaProvider>
|
||||
</VideoProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -973,7 +973,7 @@ export function generateReactCSS(skin: Skin): string {
|
||||
*/
|
||||
export function generateHTMLMarkup(skin: Skin): string {
|
||||
if (skin === 'frosted') {
|
||||
return `<media-provider>
|
||||
return `<video-provider>
|
||||
<media-container>
|
||||
<video
|
||||
slot="media"
|
||||
@@ -1013,7 +1013,7 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
</media-time-slider-track>
|
||||
<media-time-slider-thumb class="slider-thumb"></media-time-slider-thumb>
|
||||
</media-time-slider>
|
||||
<media-tooltip
|
||||
<media-tooltip
|
||||
id="time-slider-tooltip"
|
||||
class="surface popup-animation"
|
||||
popover="manual"
|
||||
@@ -1033,9 +1033,9 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
<media-volume-low-icon class="icon volume-low-icon"></media-volume-low-icon>
|
||||
<media-volume-off-icon class="icon volume-off-icon"></media-volume-off-icon>
|
||||
</media-mute-button>
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
class="surface popup-animation"
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
class="surface popup-animation"
|
||||
popover="manual"
|
||||
open-on-hover
|
||||
delay="200"
|
||||
@@ -1056,7 +1056,7 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
<media-fullscreen-enter-icon class="icon fullscreen-enter-icon"></media-fullscreen-enter-icon>
|
||||
<media-fullscreen-exit-icon class="icon fullscreen-exit-icon"></media-fullscreen-exit-icon>
|
||||
</media-fullscreen-button>
|
||||
<media-tooltip
|
||||
<media-tooltip
|
||||
id="fullscreen-tooltip"
|
||||
class="surface popup-animation"
|
||||
popover="manual"
|
||||
@@ -1070,9 +1070,9 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
</media-tooltip>
|
||||
</div>
|
||||
</media-container>
|
||||
</media-provider>`;
|
||||
</video-provider>`;
|
||||
} else {
|
||||
return `<media-provider>
|
||||
return `<video-provider>
|
||||
<media-container>
|
||||
<video
|
||||
slot="media"
|
||||
@@ -1118,7 +1118,7 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
</media-time-slider-track>
|
||||
<media-time-slider-thumb class="slider-thumb"></media-time-slider-thumb>
|
||||
</media-time-slider>
|
||||
<media-tooltip
|
||||
<media-tooltip
|
||||
id="time-slider-tooltip"
|
||||
class="popup-animation"
|
||||
popover="manual"
|
||||
@@ -1136,8 +1136,8 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
<media-volume-low-icon class="icon volume-low-icon"></media-volume-low-icon>
|
||||
<media-volume-off-icon class="icon volume-off-icon"></media-volume-off-icon>
|
||||
</media-mute-button>
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
<media-popover
|
||||
id="volume-slider-popover"
|
||||
class="popup-animation"
|
||||
popover="manual"
|
||||
open-on-hover
|
||||
@@ -1159,8 +1159,8 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
<media-fullscreen-enter-alt-icon class="icon fullscreen-enter-icon"></media-fullscreen-enter-alt-icon>
|
||||
<media-fullscreen-exit-alt-icon class="icon fullscreen-exit-icon"></media-fullscreen-exit-alt-icon>
|
||||
</media-fullscreen-button>
|
||||
<media-tooltip
|
||||
id="fullscreen-tooltip"
|
||||
<media-tooltip
|
||||
id="fullscreen-tooltip"
|
||||
class="popup-animation"
|
||||
popover="manual"
|
||||
delay="500"
|
||||
@@ -1174,7 +1174,7 @@ export function generateHTMLMarkup(skin: Skin): string {
|
||||
</div>
|
||||
</div>
|
||||
</media-container>
|
||||
</media-provider>`;
|
||||
</video-provider>`;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1916,8 +1916,8 @@ export function generateHTMLJS(skin: Skin): string {
|
||||
|
||||
// npm install @videojs/html@next
|
||||
import '@videojs/html/icons';
|
||||
// be sure to import media-provider first
|
||||
import '@videojs/html/define/media-provider';
|
||||
// be sure to import video-provider first
|
||||
import '@videojs/html/define/video-provider';
|
||||
import '@videojs/html/define/media-container';
|
||||
import '@videojs/html/define/media-play-button';
|
||||
import '@videojs/html/define/media-mute-button';
|
||||
|
||||
Reference in New Issue
Block a user