// Minimal typings for the YouTube IFrame Player API surface this app actually uses. The API is // loaded at runtime from youtube.com/iframe_api and ships no official npm types; rather than pull in // @types/youtube we declare just the methods/events PlayerModal calls, so tsc flags any new call // that isn't covered here. See [[reference-yt-iframe-api-remote-control-map]] for what's driveable. interface YTVideoData { title: string; author: string; video_id?: string; } export interface YTPlayer { getPlayerState(): number; getCurrentTime(): number; getDuration(): number; getVideoData(): YTVideoData; getIframe(): HTMLIFrameElement; getVolume(): number; isMuted(): boolean; setVolume(volume: number): void; mute(): void; unMute(): void; playVideo(): void; pauseVideo(): void; loadVideoById(opts: { videoId: string; startSeconds?: number }): void; seekTo(seconds: number, allowSeekAhead: boolean): void; destroy(): void; } // The IFrame API fires events carrying a numeric `data` — a player-state code (onStateChange) or an // error code (onError). export interface YTPlayerEvent { data: number; target: YTPlayer; } interface YTPlayerOptions { width?: string | number; height?: string | number; videoId?: string; playerVars?: Record; events?: { onReady?: (e: YTPlayerEvent) => void; onStateChange?: (e: YTPlayerEvent) => void; onError?: (e: YTPlayerEvent) => void; }; } export interface YTNamespace { Player: new (el: HTMLElement, opts: YTPlayerOptions) => YTPlayer; } // The globals the IFrame API script installs on `window` once loaded. declare global { interface Window { YT?: YTNamespace; onYouTubeIframeAPIReady?: () => void; } }