'use client'; import type { Media } from '@videojs/core/dom'; import type { UnknownState, UnknownStore } from '@videojs/store'; import { useStore } from '@videojs/store/react'; import type { Dispatch, HTMLAttributes, ReactNode, SetStateAction } from 'react'; import { createContext, forwardRef, useContext, useEffect, useRef } from 'react'; import { useComposedRefs } from '../utils/use-composed-refs'; export interface PlayerContextValue { store: UnknownStore; media: Media | null; setMedia: Dispatch>; } const PlayerContext = createContext(null); export function PlayerContextProvider({ value, children, }: { value: PlayerContextValue; children: ReactNode; }): ReactNode { return {children}; } export function usePlayerContext(): PlayerContextValue { const ctx = useContext(PlayerContext); if (!ctx) throw new Error('usePlayerContext must be used within a Player Provider'); return ctx; } export function usePlayer(): UnknownStore; export function usePlayer(selector: (state: UnknownState) => R): R; export function usePlayer(selector?: (state: UnknownState) => R) { const { store } = usePlayerContext(); return useStore(store, selector as any); } export function useMedia(): Media | null { const { media } = usePlayerContext(); return media; } export function useMediaRegistration(): Dispatch> | undefined { const ctx = useContext(PlayerContext); return ctx?.setMedia; } export interface ContainerProps extends HTMLAttributes { children?: ReactNode; } export const Container = forwardRef(function Container({ children, ...props }, ref) { const { store, media } = usePlayerContext(); const internalRef = useRef(null); const composedRef = useComposedRefs(ref, internalRef); useEffect(() => { if (!media) return; return store.attach({ media, container: internalRef.current }); }, [media, store]); return (
{children}
); }); export namespace Container { export type Props = ContainerProps; }