UNPKG

@werk1/w1-system-videoblock

Version:

Universal video player supporting YouTube, Vimeo, HLS, DASH with coordination and GSAP integration for W1 System

303 lines (291 loc) 10.7 kB
import React from 'react'; import { StateCreator } from 'zustand'; export { StateCreator } from 'zustand'; interface W1VideoPlayerState { isPlaying: boolean; isBuffering: boolean; currentTime: number; duration: number; volume: number; isMuted: boolean; playbackRate: number; isFullscreen: boolean; isPictureInPicture: boolean; isMobileFullscreen: boolean; bufferedRanges: TimeRanges | []; error: MediaError | null; isLoading: boolean; hasError: boolean; buffered: TimeRanges | null; } interface W1VideoPlayerMethods { play: () => Promise<void>; pause: () => Promise<void>; seek: (time: number) => void; setVolume: (volume: number) => void; setMuted: (muted: boolean) => void; toggleFullscreen: () => void; toggleMobileFullscreen: () => void; togglePictureInPicture: () => void; setPlaybackRate: (rate: number) => void; getVideoElement: () => HTMLVideoElement | null; getWrapperElement: () => HTMLDivElement | null; pauseForCoordination?: () => Promise<void>; } interface W1VideoPlayerProps { src: string; objectFit?: "cover" | "contain" | "fill" | "scale-down" | "none"; muted?: boolean; loop?: boolean; preload?: "none" | "metadata" | "auto"; playsInline?: boolean; autoplay?: boolean; poster?: string; className?: string; style?: React.CSSProperties; onStateChange?: (state: W1VideoPlayerState) => void; onReady?: (video: HTMLVideoElement) => void; onError?: (error: MediaError | null) => void; onPictureInPictureChange?: (isPictureInPicture: boolean) => void; onProgress?: (progress: number) => void; onTimeUpdate?: (currentTime: number) => void; playbackRates?: number[]; skipIntervals?: number; enableStreamingLibs?: boolean; enableKeyboardControls?: boolean; ref?: React.Ref<W1VideoPlayerMethods>; } interface W1VideoControlsMethods { showControls: () => void; } interface W1VideoControlsProps { playerState: W1VideoPlayerState; playerMethods: W1VideoPlayerMethods | null; className?: string; showVolumeControl?: boolean; showPlaybackRate?: boolean; showFullscreen?: boolean; showPictureInPicture?: boolean; showTimeDisplay?: boolean; showProgressBar?: boolean; autoHide?: boolean; autoHideDelay?: number; initiallyVisible?: boolean; showOnInteraction?: boolean; customButtons?: React.ReactNode; theme?: "dark" | "light" | "transparent"; position?: "bottom" | "top" | "overlay"; compact?: boolean; playbackRates?: number[]; skipIntervals?: number; videoBlockId?: string; videoCoordinationStore?: () => VideoCoordinationSlice; enableKeyboardControls?: boolean; isMobileDevice: boolean; ref?: React.Ref<W1VideoControlsMethods>; } interface W1VideoBlockProps extends Omit<W1VideoPlayerProps, "onStateChange" | "isActiveDebounced" | "priority" | "videoCoordinationStore" | "externalVideoBlockId" | "ref"> { showControls?: boolean; isActiveDebounced?: boolean; priority?: number; videoCoordinationStore?: () => VideoCoordinationSlice; onVisibilityChange?: (isActiveDebounced: boolean) => void; onVideoStateChange?: (state: W1VideoPlayerState) => void; allowPipOverride?: boolean; isMobileDevice: boolean; ref?: React.Ref<HTMLDivElement>; } interface VideoBlockInfo { id: string; priority: number; playerRef?: React.RefObject<W1VideoPlayerMethods | null>; autoplay: boolean; isActiveDebounced: boolean; allowPipOverride?: boolean; isExternalPlatform?: boolean; viewportData?: { intersectionRatio?: number; distanceFromCenter?: number; progress?: number; velocity?: number; }; } interface VideoCoordinationSlice { currentlyPlayingVideoBlock: VideoBlockInfo | null; registeredVideoBlocks: Map<string, VideoBlockInfo>; singleVideoMode: boolean; allowManualOverride: boolean; pipVideoBlocks: Set<string>; registerVideoBlock: (id: string, info: VideoBlockInfo) => void; unregisterVideoBlock: (id: string) => void; updateVideoState: (id: string, updates: Partial<Pick<VideoBlockInfo, "autoplay" | "isActiveDebounced" | "viewportData">>) => void; calculateWhoShouldPlay: () => string | null; shouldVideoPlay: (videoId: string) => boolean; recalculateDecisions: () => void; setCurrentlyPlaying: (id: string, info: VideoBlockInfo) => void; clearCurrentlyPlaying: (id?: string) => void; setSingleVideoMode: (enabled: boolean) => void; pauseAllVideos: () => void; pauseAllExcept: (videoBlockId: string) => void; setPipStatus: (videoId: string, isPip: boolean) => void; } /** * W1VideoControls - Full-featured UI controls layer for video player * * Provides comprehensive video controls with auto-hide, themes, positioning, and keyboard shortcuts */ declare const W1VideoControls: React.FC<W1VideoControlsProps>; /** * W1VideoPlayer - Pure video engine with modular hook architecture * * This component focuses solely on video playback functionality. * For complete video solutions with coordination, use W1VideoBlock. * * Features: * - Universal video format support (YouTube, Vimeo, HLS, DASH, MP4/WebM) * - Picture-in-Picture and fullscreen support * - Modular hook architecture for maintainability * - Pure video engine - no coordination concerns */ declare const W1VideoPlayer: React.FC<W1VideoPlayerProps>; /** * W1VideoBlock - Complete video solution with coordination * * This component provides a complete video experience including: * - Video coordination between multiple players * - Click-to-play/pause interaction * - Store management and state coordination * - Visibility management and autoplay control * * GSAP animations are handled externally by parent components. * Uses W1VideoPlayer as the pure video engine underneath. */ declare const W1VideoBlock: React.FC<W1VideoBlockProps>; /** * Props interface for the PlayIcon component */ interface PlayIconProps { /** Color of the icon */ color?: string; /** Size of the icon */ size?: number; /** CSS class name */ className?: string; } /** * Modern SVG play icon component for W1VideoBlock controls * * @component * @param {Object} props - Component props * @param {string} [props.color='currentColor'] - Color of the icon * @param {number} [props.size=20] - Size of the icon in pixels * @param {string} [props.className=''] - Additional CSS class name * @returns {JSX.Element} Rendered play icon */ declare const PlayIcon: React.FC<PlayIconProps>; /** * Props interface for the PauseIcon component */ interface PauseIconProps { /** Color of the icon */ color?: string; /** Size of the icon */ size?: number; /** CSS class name */ className?: string; } /** * Modern SVG pause icon component for W1VideoBlock controls * * @component * @param {Object} props - Component props * @param {string} [props.color='currentColor'] - Color of the icon * @param {number} [props.size=20] - Size of the icon in pixels * @param {string} [props.className=''] - Additional CSS class name * @returns {JSX.Element} Rendered pause icon */ declare const PauseIcon: React.FC<PauseIconProps>; /** * Props interface for the VolumeIcon component */ interface VolumeIconProps { /** Volume level: 0 = muted, 0-0.5 = low, 0.5+ = high */ level: number; /** Whether the volume is muted */ isMuted?: boolean; /** Color of the icon */ color?: string; /** Size of the icon */ size?: number; /** CSS class name */ className?: string; } /** * Modern SVG volume icon component for W1VideoBlock controls * Displays different icons based on volume level and mute state * * @component * @param {Object} props - Component props * @param {number} props.level - Volume level (0-1) * @param {boolean} [props.isMuted=false] - Whether volume is muted * @param {string} [props.color='currentColor'] - Color of the icon * @param {number} [props.size=20] - Size of the icon in pixels * @param {string} [props.className=''] - Additional CSS class name * @returns {JSX.Element} Rendered volume icon */ declare const VolumeIcon: React.FC<VolumeIconProps>; /** * Props interface for the FullscreenIcon component */ interface FullscreenIconProps { /** Whether currently in fullscreen mode */ isFullscreen?: boolean; /** Color of the icon */ color?: string; /** Size of the icon */ size?: number; /** CSS class name */ className?: string; } /** * Modern SVG fullscreen icon component for W1VideoBlock controls * Shows enter or exit fullscreen icon based on current state * * @component * @param {Object} props - Component props * @param {boolean} [props.isFullscreen=false] - Whether currently in fullscreen * @param {string} [props.color='currentColor'] - Color of the icon * @param {number} [props.size=20] - Size of the icon in pixels * @param {string} [props.className=''] - Additional CSS class name * @returns {JSX.Element} Rendered fullscreen icon */ declare const FullscreenIcon: React.FC<FullscreenIconProps>; /** * Props interface for the PictureInPictureIcon component */ interface PictureInPictureIconProps { /** Whether currently in picture-in-picture mode */ isPictureInPicture?: boolean; /** Color of the icon */ color?: string; /** Size of the icon */ size?: number; /** CSS class name */ className?: string; } /** * Modern SVG picture-in-picture icon component for W1VideoBlock controls * Shows enter or exit PiP icon based on current state * * @component * @param {Object} props - Component props * @param {boolean} [props.isPictureInPicture=false] - Whether currently in PiP mode * @param {string} [props.color='currentColor'] - Color of the icon * @param {number} [props.size=20] - Size of the icon in pixels * @param {string} [props.className=''] - Additional CSS class name * @returns {JSX.Element} Rendered picture-in-picture icon */ declare const PictureInPictureIcon: React.FC<PictureInPictureIconProps>; declare const createVideoCoordinationSlice: StateCreator<VideoCoordinationSlice>; export { FullscreenIcon, PauseIcon, PictureInPictureIcon, PlayIcon, VolumeIcon, W1VideoBlock, W1VideoControls, W1VideoPlayer, createVideoCoordinationSlice }; export type { FullscreenIconProps, PauseIconProps, PictureInPictureIconProps, PlayIconProps, VideoBlockInfo, VideoCoordinationSlice, VolumeIconProps, W1VideoBlockProps, W1VideoControlsMethods, W1VideoControlsProps, W1VideoPlayerMethods, W1VideoPlayerProps, W1VideoPlayerState };