strataplayer 1.2.19 → 1.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/core/StrataCore.d.ts +10 -2
- package/dist/strataplayer.cjs.js +17 -9
- package/dist/strataplayer.cjs.js.map +1 -1
- package/dist/strataplayer.es.js +1412 -1258
- package/dist/strataplayer.es.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/ui/Icons.d.ts +6 -0
- package/dist/ui/components/SubtitleOverlay.d.ts +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"strataplayer.cjs.js","sources":["../core/EventBus.ts","../core/NanoStore.ts","../core/AudioEngine.ts","../utils/playerUtils.ts","../core/StrataCore.ts","../ui/hooks/useTransition.tsx","../ui/Icons.tsx","../ui/components/NotificationContainer.tsx","../ui/components/SubtitleOverlay.tsx","../ui/components/SettingsPrimitives.tsx","../ui/components/Menu.tsx","../ui/components/SubtitleMenu.tsx","../ui/components/ContextMenu.tsx","../ui/components/VideoInfo.tsx","../ui/StrataPlayer.tsx","../lib.ts"],"sourcesContent":["\nexport type EventCallback<T = any> = (data: T) => void;\n\nexport class EventBus {\n private events: Map<string, EventCallback[]>;\n\n constructor() {\n this.events = new Map();\n }\n\n on<T>(event: string, callback: EventCallback<T>): () => void {\n if (!this.events.has(event)) {\n this.events.set(event, []);\n }\n this.events.get(event)?.push(callback);\n\n // Return unsubscriber\n return () => this.off(event, callback);\n }\n\n off<T>(event: string, callback: EventCallback<T>): void {\n const subscribers = this.events.get(event);\n if (subscribers) {\n this.events.set(\n event,\n subscribers.filter((cb) => cb !== callback)\n );\n }\n }\n\n emit<T>(event: string, data?: T): void {\n const subscribers = this.events.get(event);\n if (subscribers) {\n subscribers.forEach((cb) => cb(data));\n }\n }\n\n destroy() {\n this.events.clear();\n }\n}\n","\nexport type Listener<T> = (state: T, prevState: T) => void;\n\nexport class NanoStore<T> {\n private state: T;\n private listeners: Set<Listener<T>>;\n\n constructor(initialState: T) {\n this.state = initialState;\n this.listeners = new Set();\n }\n\n get(): T {\n return this.state;\n }\n\n setState(partial: Partial<T> | ((prev: T) => Partial<T>)) {\n const prevState = this.state;\n const update = typeof partial === 'function' ? (partial as any)(prevState) : partial;\n this.state = { ...prevState, ...update };\n \n this.listeners.forEach((listener) => listener(this.state, prevState));\n }\n\n subscribe(listener: Listener<T>): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n destroy() {\n this.listeners.clear();\n }\n}\n","\nexport class AudioEngine {\n private context: AudioContext | null = null;\n private source: MediaElementAudioSourceNode | null = null;\n private gainNode: GainNode | null = null;\n private video: HTMLVideoElement;\n private isInitialized = false;\n\n constructor(video: HTMLVideoElement) {\n this.video = video;\n }\n\n /**\n * Initialize the AudioContext. Must be called after user interaction.\n */\n init() {\n if (this.isInitialized) return;\n \n const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;\n if (!AudioContextClass) return;\n\n this.context = new AudioContext();\n this.gainNode = this.context.createGain();\n \n // Connect video -> gain -> destination\n try {\n this.source = this.context.createMediaElementSource(this.video);\n this.source.connect(this.gainNode);\n this.gainNode.connect(this.context.destination);\n this.isInitialized = true;\n } catch (e) {\n console.warn(\"StrataPlayer: Failed to initialize AudioEngine\", e);\n }\n }\n\n setGain(value: number) {\n // Lazy init on first boost attempt\n if (!this.isInitialized) this.init();\n \n if (this.gainNode && this.context) {\n this.gainNode.gain.value = value;\n \n // Web Audio context might be suspended by browser policy\n if (this.context.state === 'suspended') {\n this.context.resume();\n }\n }\n }\n\n destroy() {\n if (this.context) {\n this.context.close();\n }\n this.isInitialized = false;\n }\n}\n","\r\nexport const formatTime = (seconds: number) => {\r\n if (isNaN(seconds)) return '00:00';\r\n const h = Math.floor(seconds / 3600);\r\n const m = Math.floor((seconds % 3600) / 60);\r\n const s = Math.floor(seconds % 60);\r\n if (h > 0) return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;\r\n return `${m}:${s.toString().padStart(2, '0')}`;\r\n};\r\n\r\nconst fetchVttWithRetry = async (url: string, retries = 3, timeout = 20000): Promise<string> => {\r\n for (let i = 0; i < retries; i++) {\r\n const controller = new AbortController();\r\n const id = setTimeout(() => controller.abort(), timeout);\r\n try {\r\n const res = await fetch(url, { signal: controller.signal });\r\n clearTimeout(id);\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n return await res.text();\r\n } catch (e: any) {\r\n clearTimeout(id);\r\n if (i === retries - 1) throw e;\r\n await new Promise(r => setTimeout(r, 1000));\r\n }\r\n }\r\n throw new Error('Failed');\r\n}\r\n\r\nexport interface ThumbnailCue {\r\n start: number;\r\n end: number;\r\n url: string;\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\nexport const parseVTT = async (url: string, notify: (msg: any) => void, timeout: number = 20000): Promise<ThumbnailCue[]> => {\r\n try {\r\n const text = await fetchVttWithRetry(url, 3, timeout);\r\n const lines = text.split('\\n');\r\n const cues: ThumbnailCue[] = [];\r\n let start: number | null = null;\r\n let end: number | null = null;\r\n const baseUrl = url.substring(0, url.lastIndexOf('/') + 1);\r\n const parseTime = (t: string) => {\r\n const parts = t.split(':');\r\n let s = 0;\r\n if (parts.length === 3) {\r\n s += parseFloat(parts[0]) * 3600;\r\n s += parseFloat(parts[1]) * 60;\r\n s += parseFloat(parts[2]);\r\n } else {\r\n s += parseFloat(parts[0]) * 60;\r\n s += parseFloat(parts[1]);\r\n }\r\n return s;\r\n };\r\n for (let line of lines) {\r\n line = line.trim();\r\n if (line.includes('-->')) {\r\n const times = line.split('-->');\r\n start = parseTime(times[0].trim());\r\n end = parseTime(times[1].trim());\r\n } else if (start !== null && end !== null && line.length > 0) {\r\n let [urlPart, hash] = line.split('#');\r\n if (!urlPart.match(/^https?:\\/\\//) && !urlPart.startsWith('data:')) urlPart = baseUrl + urlPart;\r\n let x = 0, y = 0, w = 0, h = 0;\r\n if (hash && hash.startsWith('xywh=')) {\r\n const coords = hash.replace('xywh=', '').split(',');\r\n if (coords.length === 4) {\r\n x = parseInt(coords[0]); y = parseInt(coords[1]); w = parseInt(coords[2]); h = parseInt(coords[3]);\r\n }\r\n }\r\n if (w > 0 && h > 0) cues.push({ start, end, url: urlPart, x, y, w, h });\r\n start = null; end = null;\r\n }\r\n }\r\n return cues;\r\n } catch (e: any) {\r\n notify({ type: 'warning', message: `Failed to load thumbnails`, duration: 4000 });\r\n return [];\r\n }\r\n};\r\n\r\nexport const injectLibraryResources = () => {\r\n if (typeof document === 'undefined') return;\r\n\r\n // 1. Google Fonts\r\n if (!document.getElementById('strata-fonts')) {\r\n // Preconnects for performance\r\n const pre1 = document.createElement('link');\r\n pre1.rel = 'preconnect';\r\n pre1.href = 'https://fonts.googleapis.com';\r\n document.head.appendChild(pre1);\r\n\r\n const pre2 = document.createElement('link');\r\n pre2.rel = 'preconnect';\r\n pre2.href = 'https://fonts.gstatic.com';\r\n pre2.crossOrigin = 'anonymous';\r\n document.head.appendChild(pre2);\r\n\r\n // Main Font Sheet\r\n const link = document.createElement('link');\r\n link.id = 'strata-fonts';\r\n link.rel = 'stylesheet';\r\n link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Press+Start+2P&family=Cinzel:wght@400;600;700&display=swap';\r\n document.head.appendChild(link);\r\n }\r\n\r\n // 2. Google Cast SDK\r\n // Ensure we don't inject if already present\r\n if (!document.querySelector('script[src*=\"cast_sender.js\"]') && !(window as any).cast) {\r\n const script = document.createElement('script');\r\n script.src = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\r\n document.head.appendChild(script);\r\n }\r\n};\r\n","\r\nimport { EventBus, EventCallback } from './EventBus';\r\nimport { NanoStore } from './NanoStore';\r\nimport { AudioEngine } from './AudioEngine';\r\nimport { injectLibraryResources } from '../utils/playerUtils';\r\nimport React from 'react';\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type: 'info' | 'success' | 'warning' | 'error' | 'loading';\r\n duration?: number; // ms, if null then persistent\r\n progress?: number; // 0-100\r\n action?: {\r\n label: string;\r\n onClick: () => void;\r\n };\r\n}\r\n\r\nexport interface TextTrackConfig {\r\n src: string;\r\n label: string;\r\n srcLang?: string;\r\n default?: boolean;\r\n kind?: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';\r\n}\r\n\r\nexport interface SubtitleTrackState extends TextTrackConfig {\r\n index: number;\r\n status: 'idle' | 'loading' | 'success' | 'error';\r\n isDefault?: boolean;\r\n}\r\n\r\nexport interface SubtitleSettings {\r\n useNative: boolean; // \"Native video subtitle\"\r\n fixCapitalization: boolean;\r\n backgroundOpacity: number; // 0-100\r\n backgroundBlur: boolean;\r\n backgroundBlurAmount: number; // px\r\n textSize: number; // % (100 = 1em)\r\n textStyle: 'none' | 'outline' | 'raised' | 'depressed' | 'shadow';\r\n isBold: boolean;\r\n textColor: string;\r\n verticalOffset: number; // px from bottom\r\n}\r\n\r\nexport const DEFAULT_SUBTITLE_SETTINGS: SubtitleSettings = {\r\n useNative: false,\r\n fixCapitalization: false,\r\n backgroundOpacity: 50,\r\n backgroundBlur: false,\r\n backgroundBlurAmount: 4,\r\n textSize: 100,\r\n textStyle: 'shadow',\r\n isBold: false,\r\n textColor: '#ffffff',\r\n verticalOffset: 40,\r\n};\r\n\r\nexport type PlayerTheme = 'default' | 'pixel' | 'game' | 'hacker';\r\n\r\nexport interface PlayerSource {\r\n url: string;\r\n type?: 'hls' | 'mp4' | 'webm' | 'dash' | 'mpegts' | 'webtorrent' | string;\r\n name?: string;\r\n}\r\n\r\nexport interface Highlight {\r\n time: number;\r\n text: string;\r\n}\r\n\r\nexport interface LayerConfig {\r\n name?: string;\r\n html: string | React.ReactNode;\r\n style?: React.CSSProperties;\r\n className?: string;\r\n click?: () => void;\r\n mounted?: (element: HTMLElement) => void;\r\n}\r\n\r\nexport interface ContextMenuItem {\r\n html?: string | React.ReactNode;\r\n disabled?: boolean;\r\n icon?: string | React.ReactNode;\r\n onClick?: (close: () => void) => void;\r\n click?: (close: () => void) => void;\r\n checked?: boolean;\r\n separator?: boolean;\r\n isLabel?: boolean;\r\n showBorder?: boolean;\r\n}\r\n\r\nexport interface SettingItem {\r\n id?: string;\r\n html?: string | React.ReactNode; // Optional to support separators\r\n icon?: string | React.ReactNode;\r\n tooltip?: string;\r\n separator?: boolean; // New: Divider support\r\n isLabel?: boolean; // Header label\r\n\r\n // State\r\n active?: boolean; // Visual \"check\" state\r\n value?: any; // Value identifier for selection logic\r\n\r\n // Toggle Switch\r\n switch?: boolean;\r\n onSwitch?: (item: SettingItem, checked: boolean) => void;\r\n\r\n // Range Slider\r\n range?: boolean;\r\n min?: number;\r\n max?: number;\r\n step?: number;\r\n onRange?: (value: number) => void;\r\n formatValue?: (value: number) => string;\r\n\r\n // Action\r\n onClick?: (item: SettingItem) => void;\r\n click?: (item: SettingItem) => void; // Alias\r\n\r\n // Recursion (Nested Menu)\r\n children?: SettingItem[];\r\n currentLabel?: React.ReactNode; // Label to show in parent (e.g. \"1080p\") next to arrow\r\n}\r\n\r\nexport interface ControlItem {\r\n id?: string;\r\n position: 'left' | 'right' | 'center';\r\n index: number;\r\n html?: string | React.ReactNode;\r\n tooltip?: string;\r\n onClick?: (core: StrataCore) => void;\r\n click?: (core: StrataCore) => void;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n isBuiltIn?: boolean;\r\n\r\n // Nested Menu Support for Controls\r\n children?: SettingItem[];\r\n}\r\n\r\nexport interface PlayerState {\r\n isPlaying: boolean;\r\n isBuffering: boolean;\r\n isLive: boolean;\r\n currentTime: number;\r\n duration: number;\r\n buffered: { start: number; end: number }[];\r\n volume: number;\r\n isMuted: boolean;\r\n audioGain: number;\r\n playbackRate: number;\r\n qualityLevels: { height: number; bitrate: number; index: number }[];\r\n currentQuality: number;\r\n audioTracks: { label: string; language: string; index: number }[];\r\n currentAudioTrack: number;\r\n error: string | null;\r\n isFullscreen: boolean;\r\n isWebFullscreen: boolean;\r\n isPip: boolean;\r\n subtitleTracks: SubtitleTrackState[];\r\n currentSubtitle: number;\r\n subtitleOffset: number; // in seconds\r\n subtitleSettings: SubtitleSettings;\r\n activeCues: string[]; // For custom rendering\r\n viewMode: 'normal' | 'theater' | 'pip';\r\n notifications: Notification[];\r\n // Appearance\r\n iconSize: 'small' | 'medium' | 'large';\r\n themeColor: string;\r\n theme: PlayerTheme;\r\n // Sources\r\n sources: PlayerSource[];\r\n currentSourceIndex: number;\r\n sourceStatuses: Record<number, 'success' | 'error' | undefined>;\r\n\r\n // Phase 1 New Features State\r\n isLocked: boolean;\r\n flipState: { horizontal: boolean; vertical: boolean };\r\n aspectRatio: string; // 'default', '16:9', '4:3'\r\n isAutoSized: boolean; // tracks if autoSize (cover) is currently applied\r\n isLooping: boolean; // Track loop state reactively\r\n\r\n // UI State reflected in Core\r\n controlsVisible: boolean;\r\n}\r\n\r\nexport interface StrataConfig {\r\n // Basic\r\n container?: string; // Class for container\r\n id?: string;\r\n\r\n // Playback\r\n volume?: number;\r\n muted?: boolean;\r\n playbackRate?: number;\r\n audioGain?: number;\r\n loop?: boolean;\r\n playsInline?: boolean;\r\n isLive?: boolean;\r\n poster?: string; // Added to Config for Core access\r\n fetchTimeout?: number; // Default 30000ms\r\n\r\n // Appearance\r\n theme?: PlayerTheme;\r\n themeColor?: string;\r\n iconSize?: 'small' | 'medium' | 'large';\r\n backdrop?: boolean; // Blur effect\r\n autoSize?: boolean; // object-fit: cover logic\r\n\r\n // Subtitles\r\n subtitleSettings?: Partial<SubtitleSettings>;\r\n\r\n // UI Toggles\r\n screenshot?: boolean;\r\n setting?: boolean;\r\n pip?: boolean;\r\n fullscreen?: boolean;\r\n fullscreenWeb?: boolean;\r\n flip?: boolean;\r\n aspectRatio?: boolean;\r\n highlight?: Highlight[];\r\n centerControls?: boolean; // Default true\r\n\r\n // Controls / Mobile\r\n hotKey?: boolean;\r\n lock?: boolean; // Mobile lock button\r\n gesture?: boolean; // Mobile gestures\r\n gestureSeek?: boolean; // Drag to seek on mobile. Default false.\r\n fastForward?: boolean; // Long press\r\n autoOrientation?: boolean; // Mobile landscape lock (default: true)\r\n\r\n // Phase 2: Customization\r\n layers?: LayerConfig[];\r\n contextmenu?: ContextMenuItem[];\r\n controls?: ControlItem[];\r\n settings?: SettingItem[]; // Append to main menu\r\n\r\n // System\r\n useSSR?: boolean;\r\n disablePersistence?: boolean;\r\n}\r\n\r\nconst STORAGE_KEY = 'strata-settings';\r\n\r\nexport const DEFAULT_STATE: PlayerState = {\r\n isPlaying: false,\r\n isBuffering: false,\r\n isLive: false,\r\n currentTime: 0,\r\n duration: 0,\r\n buffered: [],\r\n volume: 1,\r\n isMuted: false,\r\n audioGain: 1,\r\n playbackRate: 1,\r\n qualityLevels: [],\r\n currentQuality: -1,\r\n audioTracks: [],\r\n currentAudioTrack: -1,\r\n error: null,\r\n isFullscreen: false,\r\n isWebFullscreen: false,\r\n isPip: false,\r\n subtitleTracks: [],\r\n currentSubtitle: -1,\r\n subtitleOffset: 0,\r\n subtitleSettings: DEFAULT_SUBTITLE_SETTINGS,\r\n activeCues: [],\r\n viewMode: 'normal',\r\n notifications: [],\r\n iconSize: 'medium',\r\n themeColor: '#6366f1',\r\n theme: 'default',\r\n sources: [],\r\n currentSourceIndex: -1,\r\n sourceStatuses: {},\r\n // New State Defaults\r\n isLocked: false,\r\n flipState: { horizontal: false, vertical: false },\r\n aspectRatio: 'default',\r\n isAutoSized: false,\r\n isLooping: false,\r\n controlsVisible: true\r\n};\r\n\r\n// Helper to merge Defaults -> LocalStorage -> Config\r\nexport const getResolvedState = (config: StrataConfig = {}): PlayerState => {\r\n let saved: any = {};\r\n if (!config.disablePersistence && typeof window !== 'undefined') {\r\n try {\r\n const raw = localStorage.getItem(STORAGE_KEY);\r\n if (raw) saved = JSON.parse(raw);\r\n } catch (e) { /* ignore */ }\r\n }\r\n\r\n const mergedSubtitleSettings = {\r\n ...DEFAULT_SUBTITLE_SETTINGS,\r\n ...(saved.subtitleSettings || {}),\r\n ...(config.subtitleSettings || {})\r\n };\r\n\r\n return {\r\n ...DEFAULT_STATE,\r\n ...saved, // Load saved first\r\n // Override with config if present (not undefined)\r\n volume: config.volume ?? saved.volume ?? DEFAULT_STATE.volume,\r\n isMuted: config.muted ?? saved.isMuted ?? DEFAULT_STATE.isMuted,\r\n playbackRate: config.playbackRate ?? saved.playbackRate ?? DEFAULT_STATE.playbackRate,\r\n audioGain: config.audioGain ?? saved.audioGain ?? DEFAULT_STATE.audioGain,\r\n theme: config.theme ?? saved.theme ?? DEFAULT_STATE.theme,\r\n themeColor: config.themeColor ?? saved.themeColor ?? DEFAULT_STATE.themeColor,\r\n iconSize: config.iconSize ?? saved.iconSize ?? DEFAULT_STATE.iconSize,\r\n subtitleSettings: mergedSubtitleSettings,\r\n // Config overrides state for these visual modes\r\n isAutoSized: config.autoSize ?? DEFAULT_STATE.isAutoSized,\r\n isLive: config.isLive ?? saved.isLive ?? DEFAULT_STATE.isLive,\r\n isLooping: config.loop ?? saved.isLooping ?? DEFAULT_STATE.isLooping,\r\n sourceStatuses: {} // Never persist statuses\r\n };\r\n};\r\n\r\nexport interface IPlugin {\r\n name: string;\r\n init(core: StrataCore): void;\r\n destroy?(): void;\r\n}\r\n\r\nexport class StrataCore {\r\n public video: HTMLVideoElement;\r\n public container: HTMLElement | null = null;\r\n public events: EventBus;\r\n public store: NanoStore<PlayerState>;\r\n private plugins: Map<string, IPlugin> = new Map();\r\n private audioEngine: AudioEngine;\r\n public config: StrataConfig;\r\n private resizeObserver: ResizeObserver | null = null;\r\n\r\n // Retry Logic\r\n private retryCount = 0;\r\n private maxRetries = 5;\r\n private retryTimer: any = null;\r\n private currentSource: PlayerSource | null = null;\r\n private currentSrc: string = '';\r\n // Track configs from setSources are stored here to lazy load\r\n private trackConfigs: TextTrackConfig[] = [];\r\n\r\n // Download Control\r\n private currentDownloadController: AbortController | null = null;\r\n\r\n // Cast\r\n private castInitialized = false;\r\n\r\n private boundCueChange: () => void;\r\n private boundFullscreenChange: () => void;\r\n\r\n constructor(config: StrataConfig = {}, videoElement?: HTMLVideoElement) {\r\n injectLibraryResources(); // Ensure fonts and external SDKs are loaded\r\n this.config = config;\r\n // Set Defaults\r\n this.config.autoOrientation = this.config.autoOrientation ?? true;\r\n this.config.fetchTimeout = this.config.fetchTimeout ?? 30000;\r\n this.config.centerControls = this.config.centerControls ?? true;\r\n this.config.gestureSeek = this.config.gestureSeek ?? false;\r\n\r\n this.video = videoElement || document.createElement('video');\r\n this.video.crossOrigin = \"anonymous\";\r\n\r\n // Init Config Props to Video\r\n if (config.playsInline !== false) this.video.playsInline = true;\r\n\r\n this.events = new EventBus();\r\n\r\n // Initialize Store with resolved state\r\n const initialState = getResolvedState(config);\r\n this.store = new NanoStore(initialState);\r\n\r\n this.audioEngine = new AudioEngine(this.video);\r\n this.boundCueChange = this.handleCueChange.bind(this);\r\n\r\n // Bind fullscreen listener once\r\n this.boundFullscreenChange = () => {\r\n const isFs = !!document.fullscreenElement;\r\n this.store.setState({ isFullscreen: isFs });\r\n this.emit('resize');\r\n this.emit(isFs ? 'fullscreen' : 'fullscreen_exit');\r\n\r\n // Auto Orientation logic\r\n if (isFs && this.config.autoOrientation && screen.orientation && 'lock' in screen.orientation) {\r\n // Basic logic: if video width > height, lock landscape\r\n const isLandscape = this.video.videoWidth > this.video.videoHeight;\r\n const lockType = isLandscape ? 'landscape' : 'portrait';\r\n try {\r\n // @ts-ignore\r\n screen.orientation.lock(lockType).catch(() => { });\r\n } catch (e) { }\r\n } else if (!isFs && screen.orientation && 'unlock' in screen.orientation) {\r\n // @ts-ignore\r\n screen.orientation.unlock();\r\n }\r\n };\r\n\r\n // Apply initial state to video element\r\n this.video.volume = initialState.volume;\r\n this.video.muted = initialState.isMuted;\r\n this.video.playbackRate = initialState.playbackRate;\r\n this.video.loop = initialState.isLooping; // Apply loop state\r\n\r\n if (initialState.audioGain > 1) {\r\n this.audioEngine.setGain(initialState.audioGain);\r\n }\r\n // Apply AutoSize\r\n if (initialState.isAutoSized) {\r\n this.video.style.objectFit = 'cover';\r\n }\r\n\r\n this.initVideoListeners();\r\n this.initMediaSession();\r\n this.initCast();\r\n\r\n // Persistence Subscriber\r\n if (!config.disablePersistence) {\r\n this.store.subscribe((state) => {\r\n const settings = {\r\n volume: state.volume,\r\n isMuted: state.isMuted,\r\n playbackRate: state.playbackRate,\r\n subtitleSettings: state.subtitleSettings,\r\n iconSize: state.iconSize,\r\n themeColor: state.themeColor,\r\n theme: state.theme,\r\n isLive: state.isLive,\r\n isLooping: state.isLooping\r\n };\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));\r\n });\r\n }\r\n }\r\n\r\n // --- Instance Properties ---\r\n\r\n get playing() { return !this.video.paused && !this.video.ended && this.video.readyState > 2; }\r\n\r\n get currentTime() { return this.video.currentTime; }\r\n set currentTime(val: number) { this.seek(val); }\r\n\r\n get duration() { return this.video.duration || 0; }\r\n\r\n get paused() { return this.video.paused; }\r\n\r\n get volume() { return this.video.volume; }\r\n set volume(val: number) { this.setVolume(val); }\r\n\r\n get muted() { return this.video.muted; }\r\n set muted(val: boolean) {\r\n this.video.muted = val;\r\n this.store.setState({ isMuted: val });\r\n }\r\n\r\n get playbackRate() { return this.video.playbackRate; }\r\n set playbackRate(val: number) { this.video.playbackRate = val; }\r\n\r\n get loop() { return this.video.loop; }\r\n set loop(val: boolean) {\r\n this.video.loop = val;\r\n this.store.setState({ isLooping: val });\r\n }\r\n\r\n // --- Instance Methods ---\r\n\r\n forward(seconds: number = 10) { this.skip(seconds); }\r\n backward(seconds: number = 10) { this.skip(-seconds); }\r\n\r\n // --- Event API ---\r\n\r\n on(event: string, callback: EventCallback) { return this.events.on(event, callback); }\r\n off(event: string, callback: EventCallback) { return this.events.off(event, callback); }\r\n emit(event: string, data?: any) { return this.events.emit(event, data); }\r\n\r\n private initVideoListeners() {\r\n const s = (partial: Partial<PlayerState>) => this.store.setState(partial);\r\n\r\n const events = [\r\n 'abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'ended', 'error',\r\n 'loadeddata', 'loadedmetadata', 'loadstart', 'pause', 'play', 'playing', 'progress',\r\n 'ratechange', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'volumechange', 'waiting'\r\n ];\r\n\r\n // Standard video event proxying\r\n events.forEach(event => {\r\n this.video.addEventListener(event, (e) => {\r\n // 1. Emit namespaced event (e.g. video:timeupdate)\r\n this.emit(`video:${event}`, e);\r\n\r\n // 2. Emit core events (e.g. play, pause)\r\n if (event === 'play') this.emit('play');\r\n if (event === 'pause') this.emit('pause');\r\n if (event === 'ended') this.emit('ended');\r\n if (event === 'error') this.emit('error', this.video.error);\r\n if (event === 'seeked') this.emit('seek');\r\n\r\n // 3. Update internal store for UI\r\n switch (event) {\r\n case 'play':\r\n s({ isPlaying: true });\r\n if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'playing';\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'pause':\r\n s({ isPlaying: false });\r\n if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'paused';\r\n break;\r\n case 'ended':\r\n s({ isPlaying: false });\r\n if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'paused';\r\n break;\r\n\r\n case 'waiting':\r\n s({ isBuffering: true });\r\n this.emit('loading', true);\r\n break;\r\n case 'playing':\r\n s({ isBuffering: false });\r\n this.emit('loading', false);\r\n break;\r\n case 'canplay':\r\n s({ isBuffering: false });\r\n this.emit('loading', false);\r\n // Mark source as success\r\n this.updateSourceStatus('success');\r\n break;\r\n\r\n case 'loadeddata':\r\n s({ isBuffering: false });\r\n this.retryCount = 0;\r\n this.removeNotification('retry');\r\n if (this.store.get().error) s({ error: null });\r\n // Mark source as success\r\n this.updateSourceStatus('success');\r\n break;\r\n case 'loadedmetadata':\r\n this.updateMediaSessionMetadata();\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'timeupdate':\r\n if (!this.video.seeking) s({ currentTime: this.video.currentTime });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'seeked':\r\n s({ currentTime: this.video.currentTime });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'durationchange':\r\n s({ duration: this.video.duration });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'volumechange': s({ volume: this.video.volume, isMuted: this.video.muted }); break;\r\n case 'ratechange':\r\n s({ playbackRate: this.video.playbackRate });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'error': this.handleError(); break;\r\n case 'progress': this.updateBuffer(); break;\r\n case 'enterpictureinpicture': s({ isPip: true }); break;\r\n case 'leavepictureinpicture': s({ isPip: false }); break;\r\n }\r\n });\r\n });\r\n\r\n // PiP events are not in the standard list above usually\r\n this.video.addEventListener('enterpictureinpicture', () => {\r\n s({ isPip: true });\r\n this.emit('pip', true);\r\n });\r\n this.video.addEventListener('leavepictureinpicture', () => {\r\n s({ isPip: false });\r\n this.emit('pip', false);\r\n });\r\n\r\n // Global fullscreen listener to catch Esc key or browser button\r\n document.addEventListener('fullscreenchange', this.boundFullscreenChange);\r\n }\r\n\r\n private updateSourceStatus(status: 'success' | 'error') {\r\n const idx = this.store.get().currentSourceIndex;\r\n if (idx !== -1) {\r\n this.store.setState((prev) => ({\r\n sourceStatuses: { ...prev.sourceStatuses, [idx]: status }\r\n }));\r\n }\r\n }\r\n\r\n // --- Media Session API ---\r\n\r\n private initMediaSession() {\r\n if (!('mediaSession' in navigator)) return;\r\n\r\n const ms = navigator.mediaSession;\r\n\r\n ms.setActionHandler('play', () => this.play());\r\n ms.setActionHandler('pause', () => this.pause());\r\n ms.setActionHandler('seekbackward', (details) => this.skip(details.seekOffset ? -details.seekOffset : -10));\r\n ms.setActionHandler('seekforward', (details) => this.skip(details.seekOffset || 10));\r\n ms.setActionHandler('seekto', (details) => {\r\n if (details.seekTime !== undefined) this.seek(details.seekTime);\r\n });\r\n ms.setActionHandler('stop', () => {\r\n this.pause();\r\n this.seek(0);\r\n });\r\n // Playlist controls\r\n ms.setActionHandler('previoustrack', () => {\r\n const idx = this.store.get().currentSourceIndex;\r\n if (idx > 0) this.switchSource(idx - 1);\r\n });\r\n ms.setActionHandler('nexttrack', () => {\r\n const idx = this.store.get().currentSourceIndex;\r\n const total = this.store.get().sources.length;\r\n if (idx < total - 1) this.switchSource(idx + 1);\r\n });\r\n }\r\n\r\n private updateMediaSessionMetadata() {\r\n if (!('mediaSession' in navigator)) return;\r\n\r\n const title = this.currentSource?.name || this.currentSource?.url.split('/').pop() || 'Video';\r\n\r\n const artwork = [];\r\n\r\n // 1. Prioritize configured poster or source-specific poster\r\n if (this.config.poster) {\r\n artwork.push({ src: this.config.poster, sizes: '512x512', type: 'image/jpeg' });\r\n }\r\n\r\n // 2. Fallback to relative logo path.\r\n // This avoids using import.meta.env.BASE_URL which crashes in some environments.\r\n // The browser resolves this relative to the current document's base URL.\r\n artwork.push({ src: 'logo.png', sizes: '512x512', type: 'image/png' });\r\n\r\n navigator.mediaSession.metadata = new MediaMetadata({\r\n title: title,\r\n artist: 'StrataPlayer',\r\n artwork: artwork\r\n });\r\n }\r\n\r\n private updateMediaSessionPosition() {\r\n if (!('mediaSession' in navigator)) return;\r\n\r\n const duration = this.video.duration;\r\n const position = this.video.currentTime;\r\n const playbackRate = this.video.playbackRate;\r\n\r\n if (!isNaN(duration) && isFinite(duration) && !isNaN(position)) {\r\n try {\r\n navigator.mediaSession.setPositionState({\r\n duration: Math.max(0, duration),\r\n playbackRate,\r\n position: Math.max(0, Math.min(position, duration)) // Ensure within [0, duration]\r\n });\r\n } catch (e) {\r\n console.warn(\"MediaSession Position Error:\", e);\r\n }\r\n }\r\n }\r\n\r\n public triggerError(message: string, isFatal: boolean = false) {\r\n if (isFatal) {\r\n this.handleError(message);\r\n } else {\r\n this.notify({ type: 'warning', message: `Warning: ${message}`, duration: 5000 });\r\n }\r\n }\r\n\r\n private handleError(customMessage?: string) {\r\n const error = this.video.error;\r\n const message = customMessage || error?.message || (error ? `Code ${error.code}` : 'Unknown Error');\r\n\r\n this.removeNotification('retry');\r\n this.emit('video:error', error); // Emitting video:error separately\r\n\r\n if (this.retryCount < this.maxRetries) {\r\n this.retryCount++;\r\n const delay = Math.pow(2, this.retryCount - 1) * 1500;\r\n\r\n this.notify({\r\n id: 'retry',\r\n type: 'loading',\r\n message: `Error: ${message}. Retrying (${this.retryCount}/${this.maxRetries})...`,\r\n });\r\n\r\n console.warn(`[StrataPlayer] Error: ${message}. Retrying in ${delay}ms...`);\r\n\r\n if (this.retryTimer) clearTimeout(this.retryTimer);\r\n this.retryTimer = setTimeout(() => {\r\n if (this.currentSource) {\r\n this.load(this.currentSource, this.trackConfigs, true); // True = isRetry\r\n\r\n const time = this.store.get().currentTime;\r\n if (time > 0) {\r\n const onCanPlay = () => {\r\n this.video.currentTime = time;\r\n this.video.removeEventListener('canplay', onCanPlay);\r\n };\r\n this.video.addEventListener('canplay', onCanPlay);\r\n }\r\n }\r\n }, delay);\r\n } else {\r\n // Final failure\r\n this.removeNotification('retry');\r\n const finalMsg = `Failed to play after ${this.maxRetries} attempts: ${message}`;\r\n this.store.setState({ error: finalMsg });\r\n this.emit('error', finalMsg);\r\n // Mark source as error\r\n this.updateSourceStatus('error');\r\n }\r\n }\r\n\r\n private updateBuffer() {\r\n const buffered: { start: number; end: number }[] = [];\r\n for (let i = 0; i < this.video.buffered.length; i++) {\r\n buffered.push({\r\n start: this.video.buffered.start(i),\r\n end: this.video.buffered.end(i)\r\n });\r\n }\r\n this.store.setState({ buffered });\r\n }\r\n\r\n private updateSubtitleTrackState(index: number, partial: Partial<SubtitleTrackState>) {\r\n this.store.setState((prev) => {\r\n const newTracks = [...prev.subtitleTracks];\r\n if (newTracks[index]) {\r\n newTracks[index] = { ...newTracks[index], ...partial };\r\n }\r\n return { subtitleTracks: newTracks };\r\n });\r\n }\r\n\r\n // --- Utility ---\r\n\r\n async fetchWithRetry(url: string, retries = 3, timeout?: number, signal?: AbortSignal): Promise<Response> {\r\n const effectiveTimeout = timeout ?? this.config.fetchTimeout ?? 30000;\r\n for (let i = 0; i < retries; i++) {\r\n // Create local controller only if external signal not provided\r\n const localController = signal ? null : new AbortController();\r\n const fetchSignal = signal || localController?.signal;\r\n\r\n const id = setTimeout(() => localController?.abort(), effectiveTimeout);\r\n try {\r\n const res = await fetch(url, { signal: fetchSignal });\r\n clearTimeout(id);\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n return res;\r\n } catch (e: any) {\r\n clearTimeout(id);\r\n if (signal?.aborted) throw new Error('Aborted');\r\n if (i === retries - 1) throw e;\r\n // If it's an abort error, warn\r\n if (e.name === 'AbortError') {\r\n if (signal?.aborted) throw e; // Pass up external aborts\r\n console.warn(`Fetch timeout (${effectiveTimeout}ms) for ${url}`);\r\n }\r\n await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));\r\n }\r\n }\r\n throw new Error('Fetch failed');\r\n }\r\n\r\n // Helper to ensure subtitle content is VTT\r\n private convertToVTT(content: string): string {\r\n // Check for SRT style timestamps or lack of header\r\n if (!content.trim().startsWith('WEBVTT')) {\r\n // Replace SRT comma timestamps (00:00:20,000) with VTT dot timestamps (00:00:20.000)\r\n let vtt = content.replace(/(\\d{2}:\\d{2}:\\d{2}),(\\d{3})/g, '$1.$2');\r\n return 'WEBVTT\\n\\n' + vtt;\r\n }\r\n return content;\r\n }\r\n\r\n // --- Core Methods ---\r\n\r\n attach(container: HTMLElement) {\r\n // 1. Cleanup old observer to prevent memory leaks or zombie updates\r\n if (this.resizeObserver) {\r\n this.resizeObserver.disconnect();\r\n }\r\n\r\n this.container = container;\r\n\r\n // 2. Force append the video to the new container. \r\n // appendChild moves the node if it is already in the DOM, solving the portal detach issue.\r\n this.container.appendChild(this.video);\r\n\r\n // 3. Re-apply critical styles to ensure the video fills the new container\r\n this.video.style.width = '100%';\r\n this.video.style.height = '100%';\r\n this.video.style.objectFit = this.store.get().isAutoSized ? 'cover' : 'contain';\r\n this.video.style.backgroundColor = 'black';\r\n\r\n // Apply potentially persisted aspect ratio\r\n this.updateAspectRatio();\r\n\r\n // 4. Setup new Resize Observer\r\n this.resizeObserver = new ResizeObserver((entries) => {\r\n for (const entry of entries) {\r\n this.emit('resize', { width: entry.contentRect.width, height: entry.contentRect.height });\r\n this.updateAspectRatio();\r\n }\r\n });\r\n this.resizeObserver.observe(this.container);\r\n\r\n // Emit ready event\r\n this.emit('ready');\r\n }\r\n\r\n use(plugin: IPlugin) {\r\n if (this.plugins.has(plugin.name)) return;\r\n plugin.init(this);\r\n this.plugins.set(plugin.name, plugin);\r\n }\r\n\r\n setSources(sources: PlayerSource[], tracks: TextTrackConfig[] = []) {\r\n this.store.setState({ sources });\r\n this.trackConfigs = tracks;\r\n if (sources.length > 0) {\r\n this.load(sources[0], tracks);\r\n }\r\n }\r\n\r\n switchSource(index: number) {\r\n const sources = this.store.get().sources;\r\n if (index >= 0 && index < sources.length) {\r\n const time = this.video.currentTime;\r\n const wasPlaying = !this.video.paused;\r\n\r\n this.load(sources[index], this.trackConfigs);\r\n\r\n const onCanPlay = () => {\r\n this.video.currentTime = time;\r\n if (wasPlaying) this.video.play();\r\n this.video.removeEventListener('canplay', onCanPlay);\r\n };\r\n this.video.addEventListener('canplay', onCanPlay);\r\n }\r\n }\r\n\r\n load(source: PlayerSource | string, tracks: TextTrackConfig[] = [], isRetry = false) {\r\n if (this.retryTimer) clearTimeout(this.retryTimer);\r\n\r\n // Normalize string input to PlayerSource\r\n const srcObj: PlayerSource = typeof source === 'string' ? { url: source, type: 'auto' } : source;\r\n\r\n if (!isRetry) {\r\n this.retryCount = 0;\r\n this.store.setState({ error: null });\r\n this.removeNotification('retry');\r\n }\r\n\r\n this.currentSrc = srcObj.url;\r\n this.currentSource = srcObj;\r\n this.trackConfigs = tracks;\r\n\r\n // Update index state if part of playlist\r\n const allSources = this.store.get().sources;\r\n const index = allSources.findIndex(s => s.url === srcObj.url);\r\n\r\n // Prepare initial subtitle tracks state based on configuration\r\n const initialSubtitleTracks: SubtitleTrackState[] = tracks.map((t, i) => ({\r\n ...t,\r\n index: i,\r\n status: 'idle',\r\n isDefault: !!t.default\r\n }));\r\n\r\n this.store.setState({\r\n isBuffering: true,\r\n qualityLevels: [],\r\n currentQuality: -1, // Reset quality to Auto on source switch\r\n audioTracks: [],\r\n currentAudioTrack: -1, // Reset audio track\r\n subtitleTracks: initialSubtitleTracks,\r\n currentSubtitle: -1,\r\n currentSourceIndex: index\r\n });\r\n\r\n // Update Metadata early\r\n this.updateMediaSessionMetadata();\r\n\r\n // Determine type if auto\r\n let type = srcObj.type || 'auto';\r\n if (type === 'auto') {\r\n if (srcObj.url.includes('.m3u8')) type = 'hls';\r\n else if (srcObj.url.includes('.mpd')) type = 'dash';\r\n else if (srcObj.url.includes('.flv') || srcObj.url.includes('.ts')) type = 'mpegts';\r\n else if (srcObj.url.startsWith('magnet:') || srcObj.url.includes('.torrent')) type = 'webtorrent';\r\n else type = 'mp4';\r\n }\r\n\r\n // Emit load event with source details so plugins can decide to act\r\n this.events.emit('load', { url: srcObj.url, type });\r\n\r\n // Clear existing tracks from DOM\r\n const oldTracks = this.video.getElementsByTagName('track');\r\n while (oldTracks.length > 0) {\r\n oldTracks[0].remove();\r\n }\r\n\r\n // Lazy load default subtitle if present\r\n const defaultTrackIndex = initialSubtitleTracks.findIndex(t => t.default);\r\n if (defaultTrackIndex !== -1) {\r\n this.setSubtitle(defaultTrackIndex);\r\n }\r\n\r\n // If it's standard MP4/WebM, set src directly. Plugins handle HLS/Dash/Mpegts/WebTorrent.\r\n if (type === 'mp4' || type === 'webm' || type === 'ogg') {\r\n this.video.src = srcObj.url;\r\n }\r\n }\r\n\r\n // Wrapper for external subtitle API\r\n public loadSubtitle(url: string, label: string = 'Subtitle') {\r\n // Add to state list dynamically\r\n const newIndex = this.store.get().subtitleTracks.length;\r\n const newTrack: SubtitleTrackState = {\r\n src: url,\r\n label,\r\n srcLang: 'user',\r\n default: true,\r\n kind: 'subtitles',\r\n index: newIndex,\r\n status: 'idle',\r\n isDefault: true\r\n };\r\n\r\n this.store.setState(prev => ({\r\n subtitleTracks: [...prev.subtitleTracks, newTrack]\r\n }));\r\n\r\n this.setSubtitle(newIndex);\r\n }\r\n\r\n public addTextTrack(file: File, label: string) {\r\n const reader = new FileReader();\r\n reader.onload = (e) => {\r\n if (!e.target?.result) return;\r\n let content = e.target.result as string;\r\n content = this.convertToVTT(content);\r\n\r\n const blob = new Blob([content], { type: 'text/vtt' });\r\n const url = URL.createObjectURL(blob);\r\n\r\n this.loadSubtitle(url, label);\r\n this.notify({ type: 'success', message: 'Subtitle uploaded', duration: 3000 });\r\n };\r\n reader.onerror = () => {\r\n this.notify({ type: 'error', message: 'Failed to read file', duration: 3000 });\r\n };\r\n reader.readAsText(file);\r\n }\r\n\r\n private addTextTrackInternal(src: string, label: string, lang: string = '', isDefault: boolean = false) {\r\n const track = document.createElement('track');\r\n track.kind = 'subtitles';\r\n track.label = label;\r\n track.src = src;\r\n track.srclang = lang;\r\n if (isDefault) track.default = true;\r\n this.video.appendChild(track);\r\n }\r\n\r\n play() { return this.video.play(); }\r\n pause() { return this.video.pause(); }\r\n togglePlay() { this.video.paused ? this.play() : this.pause(); }\r\n\r\n seek(time: number) {\r\n if (isNaN(time)) return;\r\n const t = Math.max(0, Math.min(time, this.video.duration));\r\n this.store.setState({ currentTime: t });\r\n this.video.currentTime = t;\r\n }\r\n\r\n skip(seconds: number) {\r\n this.seek(this.video.currentTime + seconds);\r\n }\r\n\r\n setVolume(vol: number) {\r\n const safeVol = Math.max(0, Math.min(vol, 1));\r\n this.video.volume = safeVol;\r\n if (safeVol > 0 && this.video.muted) this.video.muted = false;\r\n if (safeVol === 0) this.video.muted = true;\r\n }\r\n\r\n toggleMute() {\r\n this.video.muted = !this.video.muted;\r\n }\r\n\r\n setAudioGain(gain: number) {\r\n this.store.setState({ audioGain: gain });\r\n this.audioEngine.setGain(gain);\r\n }\r\n\r\n setQuality(index: number) {\r\n this.store.setState({ currentQuality: index });\r\n this.events.emit('quality-request', index);\r\n }\r\n\r\n setAudioTrack(index: number) {\r\n this.store.setState({ currentAudioTrack: index });\r\n this.events.emit('audio-track-request', index);\r\n }\r\n\r\n setControlsVisible(visible: boolean) {\r\n if (this.store.get().controlsVisible !== visible) {\r\n this.store.setState({ controlsVisible: visible });\r\n this.emit('control', visible);\r\n }\r\n }\r\n\r\n async toggleFullscreen() {\r\n if (!this.container) return;\r\n\r\n // 1. If currently native fullscreen, exit it.\r\n if (document.fullscreenElement) {\r\n await document.exitFullscreen().catch(() => { });\r\n // Orientation lock handled in event listener\r\n return;\r\n }\r\n\r\n // 2. If currently web fullscreen, toggle it off.\r\n if (this.store.get().isWebFullscreen) {\r\n this.toggleWebFullscreen();\r\n return;\r\n }\r\n\r\n // 3. Try to enter native fullscreen.\r\n try {\r\n await this.container.requestFullscreen();\r\n // Orientation lock handled in boundFullscreenChange\r\n } catch (err) {\r\n // 4. Fallback: If native fails (e.g. inside restrictive iframe), force Web Fullscreen.\r\n // This ensures the user gets a fullscreen-like experience regardless of browser limitations.\r\n console.warn('Native fullscreen failed, falling back to Web Fullscreen', err);\r\n this.toggleWebFullscreen();\r\n }\r\n }\r\n\r\n toggleWebFullscreen() {\r\n const isWebFs = this.store.get().isWebFullscreen;\r\n\r\n // If native fullscreen is active, exit it first to avoid conflicts\r\n if (document.fullscreenElement) {\r\n document.exitFullscreen().catch(() => { });\r\n }\r\n\r\n const newState = !isWebFs;\r\n this.store.setState({ isWebFullscreen: newState });\r\n\r\n // Lock body scroll when in web fullscreen\r\n if (typeof document !== 'undefined') {\r\n document.body.style.overflow = newState ? 'hidden' : '';\r\n }\r\n\r\n this.emit('webfullscreen', newState);\r\n }\r\n\r\n togglePip() {\r\n if (document.pictureInPictureElement) {\r\n document.exitPictureInPicture();\r\n } else if (this.video !== document.pictureInPictureElement && (this.video as any).requestPictureInPicture) {\r\n (this.video as any).requestPictureInPicture();\r\n }\r\n }\r\n\r\n screenshot() {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = this.video.videoWidth;\r\n canvas.height = this.video.videoHeight;\r\n const ctx = canvas.getContext('2d');\r\n if (ctx) {\r\n ctx.drawImage(this.video, 0, 0, canvas.width, canvas.height);\r\n try {\r\n const url = canvas.toDataURL('image/png');\r\n const a = document.createElement('a');\r\n a.download = `screenshot-${new Date().toISOString()}.png`;\r\n a.href = url;\r\n a.click();\r\n this.notify({ type: 'success', message: 'Screenshot saved', duration: 2000 });\r\n } catch (e) {\r\n this.notify({ type: 'error', message: 'Failed to take screenshot', duration: 3000 });\r\n }\r\n }\r\n }\r\n\r\n toggleLock() {\r\n this.store.setState((prev) => ({ isLocked: !prev.isLocked }));\r\n }\r\n\r\n toggleLoop() {\r\n this.video.loop = !this.video.loop;\r\n this.store.setState({ isLooping: this.video.loop });\r\n this.notify({ type: 'info', message: `Loop: ${this.video.loop ? 'On' : 'Off'}`, duration: 1500 });\r\n }\r\n\r\n setFlip(direction: 'horizontal' | 'vertical') {\r\n const current = this.store.get().flipState;\r\n const newState = {\r\n ...current,\r\n [direction]: !current[direction]\r\n };\r\n this.store.setState({ flipState: newState });\r\n\r\n const scaleX = newState.horizontal ? -1 : 1;\r\n const scaleY = newState.vertical ? -1 : 1;\r\n this.video.style.transform = `scale(${scaleX}, ${scaleY})`;\r\n }\r\n\r\n setAspectRatio(ratio: string) {\r\n this.store.setState({ aspectRatio: ratio });\r\n this.updateAspectRatio();\r\n\r\n if (ratio !== 'default') {\r\n this.notify({ type: 'info', message: `Aspect Ratio: ${ratio}`, duration: 2000 });\r\n }\r\n }\r\n\r\n private updateAspectRatio() {\r\n if (!this.container) return;\r\n const { aspectRatio, isAutoSized } = this.store.get();\r\n\r\n if (aspectRatio === 'default') {\r\n this.video.style.width = '100%';\r\n this.video.style.height = '100%';\r\n this.video.style.objectFit = isAutoSized ? 'cover' : 'contain';\r\n return;\r\n }\r\n\r\n const [w, h] = aspectRatio.split(':').map(Number);\r\n if (!w || !h) return;\r\n\r\n const targetRatio = w / h;\r\n const rect = this.container.getBoundingClientRect();\r\n if (rect.width === 0 || rect.height === 0) return;\r\n\r\n const containerRatio = rect.width / rect.height;\r\n\r\n let finalW, finalH;\r\n\r\n // To maintain aspect ratio completely visible within container but stretched to fill that ratio\r\n // We size the box to the largest rectangle of targetRatio that fits in container.\r\n if (containerRatio > targetRatio) {\r\n // Container is wider (e.g. 21:9 container, 16:9 video)\r\n // Video height = container height. Video width = height * ratio.\r\n finalH = rect.height;\r\n finalW = finalH * targetRatio;\r\n } else {\r\n // Container is narrower (e.g. 4:3 container, 16:9 video)\r\n // Video width = container width. Video height = width / ratio.\r\n finalW = rect.width;\r\n finalH = finalW / targetRatio;\r\n }\r\n\r\n this.video.style.width = `${finalW}px`;\r\n this.video.style.height = `${finalH}px`;\r\n this.video.style.objectFit = 'fill';\r\n }\r\n\r\n private initCast() {\r\n const w = window as any;\r\n const initializeCastApi = () => {\r\n if (this.castInitialized) return;\r\n try {\r\n if (w.cast && w.cast.framework && w.chrome && w.chrome.cast) {\r\n const CastContext = w.cast.framework.CastContext;\r\n CastContext.getInstance().setOptions({\r\n receiverApplicationId: w.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,\r\n autoJoinPolicy: w.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED\r\n });\r\n this.castInitialized = true;\r\n }\r\n } catch (e) {\r\n console.warn('Cast Init Error or already initialized', e);\r\n }\r\n };\r\n\r\n if (w.cast && w.cast.framework) {\r\n initializeCastApi();\r\n } else {\r\n w.__onGCastApiAvailable = (isAvailable: boolean) => {\r\n if (isAvailable) initializeCastApi();\r\n };\r\n }\r\n }\r\n\r\n requestCast() {\r\n const w = window as any;\r\n if (w.cast && w.cast.framework) {\r\n try {\r\n if (!this.castInitialized) this.initCast();\r\n w.cast.framework.CastContext.getInstance().requestSession()\r\n .then(() => {\r\n this.loadMediaToCast();\r\n })\r\n .catch((e: any) => {\r\n if (e !== 'cancel') this.notify({ type: 'error', message: 'Cast failed: ' + e, duration: 3000 });\r\n });\r\n } catch (e) {\r\n this.notify({ type: 'warning', message: 'Cast not available yet', duration: 3000 });\r\n }\r\n } else {\r\n this.notify({ type: 'warning', message: 'Cast API not loaded', duration: 3000 });\r\n }\r\n }\r\n\r\n private loadMediaToCast() {\r\n const w = window as any;\r\n try {\r\n const castSession = w.cast.framework.CastContext.getInstance().getCurrentSession();\r\n if (!castSession) return;\r\n const mediaInfo = new w.chrome.cast.media.MediaInfo(this.currentSrc, this.currentSrc.includes('.m3u8') ? 'application/x-mpegurl' : 'video/mp4');\r\n const request = new w.chrome.cast.media.LoadRequest(mediaInfo);\r\n castSession.loadMedia(request).then(() => {\r\n this.notify({ type: 'success', message: 'Casting...', duration: 3000 });\r\n }).catch((e: any) => console.error('Cast load error', e));\r\n } catch (e) {\r\n console.error(\"Failed to load media into Cast session\", e);\r\n }\r\n }\r\n\r\n private handleCueChange() {\r\n const state = this.store.get();\r\n if (state.currentSubtitle === -1) {\r\n this.store.setState({ activeCues: [] });\r\n return;\r\n }\r\n\r\n // Find active track in DOM\r\n const tracks = Array.from(this.video.textTracks).filter(t => t.kind === 'subtitles' || t.kind === 'captions');\r\n // We need to match the DOM track with our state index.\r\n // Since we only add tracks that are \"loaded\", the index in DOM matches the filter of loaded tracks in our state.\r\n // However, simplest is to look for the track with mode='showing'.\r\n const activeTrack = tracks.find(t => t.mode === 'showing' || t.mode === 'hidden'); // Hidden is used for custom render\r\n\r\n if (activeTrack && activeTrack.activeCues) {\r\n const cues = Array.from(activeTrack.activeCues).map((c: any) => c.text);\r\n this.store.setState({ activeCues: cues });\r\n } else {\r\n this.store.setState({ activeCues: [] });\r\n }\r\n }\r\n\r\n async setSubtitle(index: number) {\r\n const state = this.store.get();\r\n const targetTrack = state.subtitleTracks[index];\r\n\r\n // 1. Disable all current tracks\r\n Array.from(this.video.textTracks).forEach(t => {\r\n t.removeEventListener('cuechange', this.boundCueChange);\r\n t.mode = 'disabled'; // Use disabled to stop fetching/processing events for unused tracks\r\n });\r\n this.store.setState({ currentSubtitle: index, subtitleOffset: 0, activeCues: [] });\r\n\r\n if (index === -1) return;\r\n if (!targetTrack) return;\r\n\r\n // 2. Check if loaded. If not, fetch it.\r\n if (targetTrack.status === 'idle' || targetTrack.status === 'error') {\r\n this.updateSubtitleTrackState(index, { status: 'loading' });\r\n\r\n try {\r\n // Fetch blob to ensure valid response and handle CORS if needed\r\n const response = await this.fetchWithRetry(targetTrack.src);\r\n let text = await response.text();\r\n\r\n // Auto-convert SRT to VTT if needed\r\n text = this.convertToVTT(text);\r\n\r\n // Convert to Blob for safe addition (fixes some CORS issues with native track element)\r\n const blob = new Blob([text], { type: 'text/vtt' });\r\n const blobUrl = URL.createObjectURL(blob);\r\n\r\n // Add to DOM\r\n this.addTextTrackInternal(blobUrl, targetTrack.label, targetTrack.srcLang, targetTrack.isDefault || false);\r\n this.updateSubtitleTrackState(index, { status: 'success' });\r\n } catch (e) {\r\n this.updateSubtitleTrackState(index, { status: 'error' });\r\n console.error(\"Failed to load subtitle\", e);\r\n return;\r\n }\r\n }\r\n\r\n // 3. Enable the track in DOM\r\n // We find the track by label/srclang since DOM index might vary\r\n const domTracks = Array.from(this.video.textTracks);\r\n const track = domTracks.find(t => t.label === targetTrack.label && t.language === targetTrack.srcLang);\r\n\r\n if (track) {\r\n const settings = this.store.get().subtitleSettings;\r\n track.mode = settings.useNative ? 'showing' : 'hidden';\r\n track.addEventListener('cuechange', this.boundCueChange);\r\n this.handleCueChange();\r\n }\r\n }\r\n\r\n updateSubtitleSettings(settings: Partial<SubtitleSettings>) {\r\n const current = this.store.get().subtitleSettings;\r\n const newSettings = { ...current, ...settings };\r\n this.store.setState({ subtitleSettings: newSettings });\r\n\r\n // If switching native/custom, re-apply track mode\r\n if (settings.useNative !== undefined) {\r\n // Re-trigger setSubtitle to apply correct mode (hidden vs showing)\r\n // We don't need to re-fetch since status is already success\r\n const idx = this.store.get().currentSubtitle;\r\n if (idx !== -1) {\r\n // Find active track and update mode directly\r\n const state = this.store.get();\r\n const target = state.subtitleTracks[idx];\r\n const track = Array.from(this.video.textTracks).find(t => t.label === target.label && t.language === target.srcLang);\r\n if (track) {\r\n track.mode = settings.useNative ? 'showing' : 'hidden';\r\n }\r\n }\r\n }\r\n }\r\n\r\n resetSubtitleSettings() {\r\n this.store.setState({ subtitleSettings: DEFAULT_SUBTITLE_SETTINGS });\r\n this.updateSubtitleSettings({ useNative: false }); // Trigger mode update\r\n }\r\n\r\n setSubtitleOffset(offset: number) {\r\n const currentOffset = this.store.get().subtitleOffset;\r\n const delta = offset - currentOffset;\r\n\r\n if (Math.abs(delta) < 0.001) return;\r\n\r\n Array.from(this.video.textTracks).forEach((track) => {\r\n // If custom (hidden) or native (showing), we adjust cues\r\n if ((track.mode === 'showing' || track.mode === 'hidden') && track.cues) {\r\n Array.from(track.cues).forEach((cue: any) => {\r\n cue.startTime += delta;\r\n cue.endTime += delta;\r\n });\r\n }\r\n });\r\n\r\n this.store.setState({ subtitleOffset: offset });\r\n this.notify({ type: 'info', message: `Subtitle Offset: ${offset > 0 ? '+' : ''}${offset.toFixed(1)}s`, duration: 1500 });\r\n }\r\n\r\n cancelDownload() {\r\n if (this.currentDownloadController) {\r\n this.currentDownloadController.abort();\r\n this.currentDownloadController = null;\r\n this.notify({ type: 'info', message: 'Download cancelled', duration: 2000 });\r\n }\r\n }\r\n\r\n async download(options: { format?: 'ts' | 'mp4' } = {}) {\r\n // Prefer the original source URL if available, as video.src might be a blob (MSE)\r\n const src = this.currentSource?.url || this.video.src;\r\n if (!src) return;\r\n\r\n // 1. Handle HLS or DASH explicitly if current source type matches\r\n // We check both the URL extension and the explicit type from the source config\r\n if (src.includes('.m3u8') || this.currentSource?.type === 'hls') {\r\n this.downloadHls(src, options.format || 'ts');\r\n return;\r\n }\r\n\r\n if (src.startsWith('blob:')) {\r\n this.notify({ type: 'warning', message: 'Stream download not supported in browser.', duration: 4000 });\r\n return;\r\n }\r\n\r\n // Abort previous download if active\r\n if (this.currentDownloadController) {\r\n this.currentDownloadController.abort();\r\n }\r\n\r\n this.currentDownloadController = new AbortController();\r\n const signal = this.currentDownloadController.signal;\r\n\r\n const notifId = this.notify({\r\n type: 'loading',\r\n message: 'Preparing download...',\r\n progress: 0,\r\n action: {\r\n label: 'Cancel',\r\n onClick: () => this.cancelDownload()\r\n }\r\n });\r\n\r\n try {\r\n const response = await this.fetchWithRetry(src, 3, undefined, signal);\r\n if (!response.body) throw new Error('No body');\r\n const reader = response.body.getReader();\r\n const contentLength = response.headers.get('Content-Length');\r\n const total = contentLength ? parseInt(contentLength, 10) : 0;\r\n let loaded = 0;\r\n const chunks = [];\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n loaded += value.length;\r\n if (total) {\r\n const percent = Math.round((loaded / total) * 100);\r\n this.notify({\r\n id: notifId,\r\n type: 'loading',\r\n message: `Downloading... ${percent}%`,\r\n progress: percent,\r\n action: {\r\n label: 'Cancel',\r\n onClick: () => this.cancelDownload()\r\n }\r\n });\r\n }\r\n }\r\n const blob = new Blob(chunks);\r\n const url = window.URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n a.style.display = 'none';\r\n a.href = url;\r\n a.download = src.split('/').pop()?.split('?')[0] || 'video.mp4';\r\n document.body.appendChild(a);\r\n a.click();\r\n window.URL.revokeObjectURL(url);\r\n document.body.removeChild(a);\r\n this.notify({ id: notifId, type: 'success', message: 'Saved!', duration: 3000 });\r\n } catch (e: any) {\r\n if (signal.aborted) {\r\n this.removeNotification(notifId); // Handled by cancelDownload notify usually, but ensure cleanup\r\n } else {\r\n this.notify({ id: notifId, type: 'error', message: 'Download failed.', duration: 4000 });\r\n // Fallback\r\n window.open(src, '_blank');\r\n }\r\n } finally {\r\n this.currentDownloadController = null;\r\n }\r\n }\r\n\r\n async downloadHls(url: string, format: 'ts' | 'mp4') {\r\n if (this.currentDownloadController) this.currentDownloadController.abort();\r\n this.currentDownloadController = new AbortController();\r\n const signal = this.currentDownloadController.signal;\r\n\r\n const notifId = this.notify({\r\n type: 'loading',\r\n message: 'Analyzing HLS stream...',\r\n progress: 0,\r\n action: { label: 'Cancel', onClick: () => this.cancelDownload() }\r\n });\r\n\r\n try {\r\n // 1. Fetch Playlist\r\n let response = await this.fetchWithRetry(url, 3, undefined, signal);\r\n let content = await response.text();\r\n let baseUrl = url.substring(0, url.lastIndexOf('/') + 1);\r\n\r\n // 2. Check for Master Playlist\r\n if (content.includes('#EXT-X-STREAM-INF')) {\r\n this.notify({ id: notifId, type: 'loading', message: 'Selecting best quality...', progress: 0 });\r\n // Parse variants\r\n const lines = content.split('\\n');\r\n let bestBandwidth = 0;\r\n let bestUrl = '';\r\n for (let i = 0; i < lines.length; i++) {\r\n if (lines[i].includes('#EXT-X-STREAM-INF')) {\r\n const bandwidthMatch = lines[i].match(/BANDWIDTH=(\\d+)/);\r\n if (bandwidthMatch) {\r\n const bandwidth = parseInt(bandwidthMatch[1]);\r\n // Next line is URL\r\n let nextLine = lines[i + 1]?.trim();\r\n if (nextLine && !nextLine.startsWith('#')) {\r\n if (bandwidth > bestBandwidth) {\r\n bestBandwidth = bandwidth;\r\n bestUrl = nextLine;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (bestUrl) {\r\n // Handle relative URL\r\n if (!bestUrl.startsWith('http')) {\r\n bestUrl = baseUrl + bestUrl;\r\n }\r\n // Fetch best variant playlist\r\n response = await this.fetchWithRetry(bestUrl, 3, undefined, signal);\r\n content = await response.text();\r\n baseUrl = bestUrl.substring(0, bestUrl.lastIndexOf('/') + 1);\r\n }\r\n }\r\n\r\n // 3. Parse Segments\r\n if (content.includes('#EXT-X-KEY')) {\r\n throw new Error('Encrypted HLS streams are not supported for download.');\r\n }\r\n\r\n const lines = content.split('\\n');\r\n const segments: string[] = [];\r\n for (let line of lines) {\r\n line = line.trim();\r\n if (line && !line.startsWith('#')) {\r\n if (!line.startsWith('http')) {\r\n segments.push(baseUrl + line);\r\n } else {\r\n segments.push(line);\r\n }\r\n }\r\n }\r\n\r\n if (segments.length === 0) throw new Error('No segments found.');\r\n\r\n // 4. Determine Output Format\r\n let extension = format === 'mp4' ? 'mp4' : 'ts';\r\n let mime = format === 'mp4' ? 'video/mp4' : 'video/mp2t';\r\n\r\n // 5. Setup Writer (File System API or Memory)\r\n let fileHandle: any = null;\r\n let writable: any = null;\r\n let memoryBlobs: Blob[] = [];\r\n const useFileSystem = 'showSaveFilePicker' in window;\r\n\r\n if (useFileSystem) {\r\n try {\r\n // @ts-ignore\r\n fileHandle = await window.showSaveFilePicker({\r\n suggestedName: `video.${extension}`,\r\n types: [{\r\n description: format === 'mp4' ? 'MPEG-4 Video' : 'MPEG Transport Stream',\r\n accept: { [mime]: [`.${extension}`] },\r\n }],\r\n });\r\n writable = await fileHandle.createWritable();\r\n } catch (e) {\r\n // User cancelled or not supported, fallback to memory\r\n console.warn('File System API cancelled or failed, falling back to memory', e);\r\n }\r\n }\r\n\r\n // 6. Download Loop\r\n let isTsContent = false;\r\n\r\n for (let i = 0; i < segments.length; i++) {\r\n if (signal.aborted) break;\r\n\r\n const progress = Math.round(((i + 1) / segments.length) * 100);\r\n this.notify({\r\n id: notifId,\r\n type: 'loading',\r\n message: `Downloading segment ${i + 1}/${segments.length}...`,\r\n progress: progress,\r\n action: { label: 'Cancel', onClick: () => this.cancelDownload() }\r\n });\r\n\r\n const segRes = await this.fetchWithRetry(segments[i], 3, undefined, signal);\r\n const buffer = await segRes.arrayBuffer();\r\n\r\n // 7. Check content type on first segment\r\n if (i === 0) {\r\n const bytes = new Uint8Array(buffer.slice(0, 4));\r\n // TS Sync Byte is 0x47\r\n if (bytes[0] === 0x47) {\r\n isTsContent = true;\r\n if (format === 'mp4') {\r\n this.notify({\r\n type: 'info',\r\n message: 'Stream is MPEG-TS. Downloading as .ts to prevent corruption.',\r\n duration: 5000\r\n });\r\n // Fallback to TS extension if we can't transmux\r\n // If using File System API, filename is already set, so we just write raw bytes\r\n // Ideally we should warn BEFORE saving but here we just process.\r\n extension = 'ts';\r\n mime = 'video/mp2t';\r\n }\r\n }\r\n }\r\n\r\n const blob = new Blob([buffer]);\r\n if (writable) {\r\n await writable.write(blob);\r\n } else {\r\n memoryBlobs.push(blob);\r\n }\r\n }\r\n\r\n if (signal.aborted) {\r\n if (writable) await writable.abort();\r\n throw new Error('Aborted');\r\n }\r\n\r\n if (writable) {\r\n await writable.close();\r\n this.notify({ id: notifId, type: 'success', message: 'Download complete!', duration: 3000 });\r\n } else {\r\n // Combine blobs and download\r\n this.notify({ id: notifId, type: 'loading', message: 'Stitching video...', progress: 100 });\r\n const finalBlob = new Blob(memoryBlobs, { type: mime });\r\n const url = window.URL.createObjectURL(finalBlob);\r\n const a = document.createElement('a');\r\n a.style.display = 'none';\r\n a.href = url;\r\n // If content was TS but requested MP4, fallback extension\r\n const finalExt = (format === 'mp4' && isTsContent) ? 'ts' : extension;\r\n a.download = `video.${finalExt}`;\r\n document.body.appendChild(a);\r\n a.click();\r\n window.URL.revokeObjectURL(url);\r\n document.body.removeChild(a);\r\n this.notify({ id: notifId, type: 'success', message: 'Saved!', duration: 3000 });\r\n }\r\n\r\n } catch (e: any) {\r\n if (signal.aborted) {\r\n this.removeNotification(notifId);\r\n } else {\r\n this.notify({ id: notifId, type: 'error', message: `Download failed: ${e.message}`, duration: 4000 });\r\n }\r\n } finally {\r\n this.currentDownloadController = null;\r\n }\r\n }\r\n\r\n notify(n: Omit<Notification, 'id'> & { id?: string }) {\r\n const id = n.id || Math.random().toString(36).substr(2, 9);\r\n const newNotification: Notification = { ...n, id };\r\n\r\n // If update, replace. If new, append.\r\n this.store.setState(prev => {\r\n const exists = prev.notifications.find(existing => existing.id === id);\r\n if (exists) {\r\n return { notifications: prev.notifications.map(existing => existing.id === id ? newNotification : existing) };\r\n }\r\n return { notifications: [...prev.notifications, newNotification] };\r\n });\r\n\r\n if (n.duration) setTimeout(() => this.removeNotification(id), n.duration);\r\n return id;\r\n }\r\n\r\n removeNotification(id: string) {\r\n const current = this.store.get().notifications;\r\n this.store.setState({ notifications: current.filter(n => n.id !== id) });\r\n }\r\n\r\n setAppearance(settings: { iconSize?: 'small' | 'medium' | 'large', themeColor?: string, theme?: PlayerTheme }) {\r\n this.store.setState(prev => ({\r\n ...prev,\r\n ...settings\r\n }));\r\n }\r\n\r\n destroy() {\r\n if (this.retryTimer) clearTimeout(this.retryTimer);\r\n if (this.resizeObserver) {\r\n this.resizeObserver.disconnect();\r\n this.resizeObserver = null;\r\n }\r\n if (this.currentDownloadController) {\r\n this.currentDownloadController.abort();\r\n }\r\n\r\n // Clean up web fullscreen scroll lock if active\r\n if (this.store.get().isWebFullscreen && typeof document !== 'undefined') {\r\n document.body.style.overflow = '';\r\n }\r\n\r\n document.removeEventListener('fullscreenchange', this.boundFullscreenChange);\r\n this.video.pause();\r\n this.video.src = '';\r\n const oldTracks = this.video.getElementsByTagName('track');\r\n while (oldTracks.length > 0) oldTracks[0].remove();\r\n this.emit('destroy');\r\n this.events.destroy();\r\n this.store.destroy();\r\n this.plugins.forEach(p => p.destroy && p.destroy());\r\n this.plugins.clear();\r\n this.video.remove();\r\n this.audioEngine.destroy();\r\n }\r\n}\r\n","\r\nimport { useState, useEffect } from 'react';\r\n\r\n// Hook to manage CSS transitions for mounting/unmounting\r\nexport const useTransition = (isActive: boolean, duration: number = 200) => {\r\n const [isMounted, setIsMounted] = useState(isActive);\r\n const [isVisible, setIsVisible] = useState(false);\r\n\r\n useEffect(() => {\r\n if (isActive) {\r\n setIsMounted(true);\r\n // Double RAF ensures the browser paints the initial state before applying the active state\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n setIsVisible(true);\r\n });\r\n });\r\n } else {\r\n setIsVisible(false);\r\n const timer = setTimeout(() => {\r\n setIsMounted(false);\r\n }, duration);\r\n return () => clearTimeout(timer);\r\n }\r\n }, [isActive, duration]);\r\n\r\n return { isMounted, isVisible };\r\n};\r\n","import React from \"react\";\r\n\r\n// Base SVG Wrapper matching Lucide defaults\r\nconst Icon = ({\r\n className,\r\n children,\r\n fill = \"none\",\r\n strokeWidth = 2,\r\n viewBox = \"0 0 24 24\",\r\n}: {\r\n className?: string;\r\n children: React.ReactNode;\r\n fill?: string;\r\n strokeWidth?: number;\r\n viewBox?: string;\r\n}) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox={viewBox}\r\n fill={fill}\r\n stroke=\"currentColor\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n >\r\n {children}\r\n </svg>\r\n);\r\n\r\nexport const PlayIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"5 3 19 12 5 21 5 3\" />\r\n </Icon>\r\n);\r\n\r\nexport const PauseIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"4\" height=\"16\" x=\"6\" y=\"4\" rx=\"1\" />\r\n <rect width=\"4\" height=\"16\" x=\"14\" y=\"4\" rx=\"1\" />\r\n </Icon>\r\n);\r\n\r\nexport const VolumeHighIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\r\n <path d=\"M19.07 4.93a10 10 0 0 1 0 14.14\" />\r\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\r\n </Icon>\r\n);\r\n\r\nexport const VolumeLowIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\r\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\r\n </Icon>\r\n);\r\n\r\nexport const VolumeMuteIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\r\n <line x1=\"23\" x2=\"17\" y1=\"9\" y2=\"15\" />\r\n <line x1=\"17\" x2=\"23\" y1=\"9\" y2=\"15\" />\r\n </Icon>\r\n);\r\n\r\nexport const MaximizeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\r\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\r\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\r\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\r\n </Icon>\r\n);\r\n\r\nexport const MinimizeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\r\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\r\n <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\r\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\r\n </Icon>\r\n);\r\n\r\nexport const SettingsIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.09a2 2 0 0 1-1-1.74v-.47a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const CheckIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M20 6 9 17l-5-5\" />\r\n </Icon>\r\n);\r\n\r\nexport const PipIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4\" />\r\n <rect x=\"12\" y=\"13\" width=\"10\" height=\"7\" rx=\"2\" />\r\n </Icon>\r\n);\r\n\r\nexport const SubtitleIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"18\" height=\"14\" x=\"3\" y=\"5\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M7 15h4\" />\r\n <path d=\"M15 15h2\" />\r\n <path d=\"M7 11h2\" />\r\n <path d=\"M13 11h4\" />\r\n </Icon>\r\n);\r\n\r\nexport const DownloadIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"7 10 12 15 17 10\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"15\" y2=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const UploadIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"17 8 12 3 7 8\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"3\" y2=\"15\" />\r\n </Icon>\r\n);\r\n\r\nexport const ArrowLeftIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m12 19-7-7 7-7\" />\r\n <path d=\"M19 12H5\" />\r\n </Icon>\r\n);\r\n\r\nexport const LoaderIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\r\n </Icon>\r\n);\r\n\r\nexport const CastIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M2 16.1A5 5 0 0 1 5.9 20\" />\r\n <path d=\"M2 12.05A9 9 0 0 1 9.95 20\" />\r\n <path d=\"M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6\" />\r\n <line x1=\"2\" x2=\"2.01\" y1=\"20\" y2=\"20\" />\r\n </Icon>\r\n);\r\n\r\nexport const UsersIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\r\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\r\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\r\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\r\n </Icon>\r\n);\r\n\r\nexport const ClockIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <polyline points=\"12 6 12 12 16 14\" />\r\n </Icon>\r\n);\r\n\r\nexport const MinusIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M5 12h14\" />\r\n </Icon>\r\n);\r\n\r\nexport const PlusIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M5 12h14\" />\r\n <path d=\"M12 5v14\" />\r\n </Icon>\r\n);\r\n\r\nexport const CustomizeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M4 21v-7\" />\r\n <path d=\"M4 10V3\" />\r\n <path d=\"M12 21v-9\" />\r\n <path d=\"M12 8V3\" />\r\n <path d=\"M20 21v-5\" />\r\n <path d=\"M20 12V3\" />\r\n <path d=\"M1 14h6\" />\r\n <path d=\"M9 8h6\" />\r\n <path d=\"M17 16h6\" />\r\n </Icon>\r\n);\r\n\r\nexport const TypeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polyline points=\"4 7 4 4 20 4 20 7\" />\r\n <line x1=\"9\" x2=\"15\" y1=\"20\" y2=\"20\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"4\" y2=\"20\" />\r\n </Icon>\r\n);\r\n\r\nexport const PaletteIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\" />\r\n <circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\" />\r\n <circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\" />\r\n <circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\" />\r\n <path d=\"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z\" />\r\n </Icon>\r\n);\r\n\r\nexport const EyeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const MoveVerticalIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polyline points=\"8 18 12 22 16 18\" />\r\n <polyline points=\"8 6 12 2 16 6\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"2\" y2=\"22\" />\r\n </Icon>\r\n);\r\n\r\nexport const ResetIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\r\n <path d=\"M3 3v5h5\" />\r\n </Icon>\r\n);\r\n\r\nexport const BoldIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\r\n <path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\r\n </Icon>\r\n);\r\n\r\nexport const CaseUpperIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m3 17 4-10 4 10\" />\r\n <path d=\"M4 13h6\" />\r\n <path d=\"M15 12h4.5a2.5 2.5 0 0 1 0 5H15V7h4a2.5 2.5 0 0 1 0 5h-4\" />\r\n </Icon>\r\n);\r\n\r\nexport const BlurIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z\" />\r\n </Icon>\r\n);\r\n\r\nexport const CameraIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\" />\r\n <circle cx=\"12\" cy=\"13\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const LockIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\r\n </Icon>\r\n);\r\n\r\nexport const UnlockIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M7 11V7a5 5 0 0 1 9.9-1\" />\r\n </Icon>\r\n);\r\n\r\nexport const WebFullscreenIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\r\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\r\n </Icon>\r\n);\r\n\r\nexport const FastForwardIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"13 19 22 12 13 5 13 19\" />\r\n <polygon points=\"2 19 11 12 2 5 2 19\" />\r\n </Icon>\r\n);\r\n\r\nexport const ZapIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\" />\r\n </Icon>\r\n);\r\n\r\nexport const RatioIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"5\" rx=\"2\" />\r\n <line x1=\"2\" x2=\"22\" y1=\"12\" y2=\"12\" />\r\n </Icon>\r\n);\r\n\r\nexport const ExpandIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m21 21-6-6m6 6v-4.8m0 4.8h-4.8\" />\r\n <path d=\"M3 16.2V21m0 0h4.8M3 21l6-6\" />\r\n <path d=\"M21 7.8V3m0 0h-4.8M21 3l-6 6\" />\r\n <path d=\"M3 7.8V3m0 0h4.8M3 3l6 6\" />\r\n </Icon>\r\n);\r\n\r\nexport const CloseIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M18 6 6 18\" />\r\n <path d=\"m6 6 12 12\" />\r\n </Icon>\r\n);\r\n\r\nexport const InfoIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <path d=\"M12 16v-4\" />\r\n <path d=\"M12 8h.01\" />\r\n </Icon>\r\n);\r\n\r\nexport const CopyIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\r\n </Icon>\r\n);\r\n\r\nexport const MenuIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\r\n <line x1=\"4\" x2=\"20\" y1=\"6\" y2=\"6\" />\r\n <line x1=\"4\" x2=\"20\" y1=\"18\" y2=\"18\" />\r\n </Icon>\r\n);\r\n\r\nexport const ChevronRightIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m9 18 6-6-6-6\" />\r\n </Icon>\r\n);\r\n\r\nexport const ServerIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\" />\r\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\" />\r\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\" />\r\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\" />\r\n </Icon>\r\n);\r\n\r\nexport const LayersIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"12 2 2 7 12 12 22 7 12 2\" />\r\n <polyline points=\"2 17 12 22 22 17\" />\r\n <polyline points=\"2 12 12 17 22 12\" />\r\n </Icon>\r\n);\r\n\r\nexport const CropIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M6 2v14a2 2 0 0 0 2 2h14\" />\r\n <path d=\"M18 22V8a2 2 0 0 0-2-2H2\" />\r\n </Icon>\r\n);\r\n\r\nexport const SpeakerIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"16\" height=\"20\" x=\"4\" y=\"2\" rx=\"2\" />\r\n <circle cx=\"12\" cy=\"14\" r=\"4\" />\r\n <line x1=\"12\" x2=\"12.01\" y1=\"6\" y2=\"6\" />\r\n </Icon>\r\n);\r\n\r\nexport const GaugeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m12 14 4-4\" />\r\n <path d=\"M3.34 19a10 10 0 1 1 17.32 0\" />\r\n </Icon>\r\n);\r\n\r\nexport const SlidersIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <line x1=\"4\" x2=\"4\" y1=\"21\" y2=\"14\" />\r\n <line x1=\"4\" x2=\"4\" y1=\"10\" y2=\"3\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"21\" y2=\"12\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"3\" />\r\n <line x1=\"20\" x2=\"20\" y1=\"21\" y2=\"16\" />\r\n <line x1=\"20\" x2=\"20\" y1=\"12\" y2=\"3\" />\r\n <line x1=\"2\" x2=\"6\" y1=\"14\" y2=\"14\" />\r\n <line x1=\"10\" x2=\"14\" y1=\"8\" y2=\"8\" />\r\n <line x1=\"18\" x2=\"22\" y1=\"16\" y2=\"16\" />\r\n </Icon>\r\n);\r\n\r\nexport const MusicIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M9 18V5l12-2v13\" />\r\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\r\n <circle cx=\"18\" cy=\"16\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const FlipIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polyline points=\"16 16 12 20 8 16\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"20\" y2=\"10\" />\r\n <path d=\"M12 4a8 8 0 0 1 8 8\" />\r\n <path d=\"M20 4v8\" />\r\n <path d=\"M4 4v8\" />\r\n <path d=\"M4 12a8 8 0 0 1 8-8\" />\r\n </Icon>\r\n);\r\n\r\nexport const WifiIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M5 12.55a11 11 0 0 1 14.08 0\" />\r\n <path d=\"M1.42 9a16 16 0 0 1 21.16 0\" />\r\n <path d=\"M8.53 16.11a6 6 0 0 1 6.95 0\" />\r\n <line x1=\"12\" x2=\"12.01\" y1=\"20\" y2=\"20\" />\r\n </Icon>\r\n);\r\n\r\nexport const AlertCircleIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\r\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\r\n </Icon>\r\n);\r\n\r\nexport const QualityIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M2 20h.01\" />\r\n <path d=\"M7 20v-4\" />\r\n <path d=\"M12 20v-8\" />\r\n <path d=\"M17 20V8\" />\r\n <path d=\"M22 20V4\" />\r\n </Icon>\r\n);\r\n\r\nexport const VideoFlipIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 7v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\r\n <path d=\"M16 2v4\" />\r\n <path d=\"M8 2v4\" />\r\n <path d=\"M3 12h18\" />\r\n </Icon>\r\n);\r\n\r\nexport const SearchIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\r\n <path d=\"m21 21-4.3-4.3\" />\r\n </Icon>\r\n);\r\n\r\nexport const XIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M18 6 6 18\" />\r\n <path d=\"m6 6 12 12\" />\r\n </Icon>\r\n);\r\n\r\nexport const FileCheckIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\" />\r\n <polyline points=\"14 2 14 8 20 8\" />\r\n <path d=\"m9 15 2 2 4-4\" />\r\n </Icon>\r\n);\r\n\r\nexport const FileWarningIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\" />\r\n <polyline points=\"14 2 14 8 20 8\" />\r\n <path d=\"M12 18h.01\" />\r\n <path d=\"M12 12v4\" />\r\n </Icon>\r\n);\r\n\r\n// Custom Composite Icons (Reusing Base Icons + Text)\r\nexport const Replay10Icon = ({ className }: { className?: string }) => (\r\n <div className={`relative flex items-center justify-center ${className}`}>\r\n <Icon className=\"w-full h-full\">\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\r\n <path d=\"M3 3v5h5\" />\r\n </Icon>\r\n <span className=\"absolute inset-0 flex items-center justify-center text-[32%] font-bold select-none mt-[1px]\">\r\n 10\r\n </span>\r\n </div>\r\n);\r\n\r\nexport const Forward10Icon = ({ className }: { className?: string }) => (\r\n <div className={`relative flex items-center justify-center ${className}`}>\r\n <Icon className=\"w-full h-full\">\r\n <path d=\"M21 12a9 9 0 1 1-9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\r\n <path d=\"M21 3v5h-5\" />\r\n </Icon>\r\n <span className=\"absolute inset-0 flex items-center justify-center text-[32%] font-bold select-none mt-[1px]\">\r\n 10\r\n </span>\r\n </div>\r\n);\r\n\r\nexport const StrataLogo = ({ className }: { className?: string }) => {\r\n const base = import.meta.env?.BASE_URL || \"/\";\r\n const src = `${base}logo.png`;\r\n return <img src={src} alt=\"StrataPlayer Logo\" className={className} />;\r\n};\r\n","import React from \"react\";\r\nimport { PlayerState } from \"../../core/StrataCore\";\r\nimport {\r\n LoaderIcon,\r\n CheckIcon,\r\n AlertCircleIcon,\r\n DownloadIcon,\r\n CloseIcon,\r\n} from \"../Icons\";\r\n\r\nexport const NotificationContainer = ({\r\n notifications,\r\n}: {\r\n notifications: PlayerState[\"notifications\"];\r\n}) => {\r\n return (\r\n <div className=\"absolute top-4 left-4 z-[100] flex flex-col gap-2 pointer-events-none font-sans max-w-[85%] md:max-w-[280px]\">\r\n {notifications.map((n) => {\r\n const isProgress = typeof n.progress === \"number\";\r\n\r\n return (\r\n <div\r\n key={n.id}\r\n className={`\r\n relative overflow-hidden bg-zinc-950/80 backdrop-blur-xl border border-white/10 text-zinc-100 shadow-2xl rounded-lg pointer-events-auto\r\n animate-in slide-in-from-left-4 fade-in duration-300\r\n ${isProgress ? \"w-64\" : \"w-auto max-w-full px-3 py-2.5\"}\r\n `}\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n {isProgress ? (\r\n <div className=\"p-3\">\r\n <div className=\"flex items-start gap-3\">\r\n <div className=\"w-7 h-7 rounded-full bg-white/10 flex items-center justify-center text-[var(--accent)] shrink-0\">\r\n <DownloadIcon className=\"w-3.5 h-3.5\" />\r\n </div>\r\n <div className=\"flex-1 min-w-0 pt-0.5\">\r\n <div className=\"flex justify-between items-baseline mb-1\">\r\n <span className=\"text-xs font-bold text-white tracking-tight\">\r\n Downloading\r\n </span>\r\n <span className=\"text-[10px] font-mono text-zinc-400\">\r\n {n.progress}%\r\n </span>\r\n </div>\r\n <p className=\"text-[10px] text-zinc-400 truncate mb-2 leading-tight\">\r\n {n.message.replace(/Downloading\\.\\.\\. \\d+%/, \"\").trim() ||\r\n \"Processing...\"}\r\n </p>\r\n <div className=\"h-0.5 w-full bg-white/10 rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-[var(--accent)] transition-all duration-300 ease-out\"\r\n style={{ width: `${n.progress}%` }}\r\n />\r\n </div>\r\n </div>\r\n {n.action && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n n.action?.onClick();\r\n }}\r\n className=\"text-zinc-500 hover:text-zinc-200 transition-colors p-1 -mt-1.5 -mr-1.5\"\r\n title={n.action.label}\r\n >\r\n <CloseIcon className=\"w-3.5 h-3.5\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"flex items-start gap-2.5\">\r\n {n.type === \"loading\" && (\r\n <LoaderIcon className=\"w-3.5 h-3.5 animate-spin text-[var(--accent)] shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"success\" && (\r\n <CheckIcon className=\"w-3.5 h-3.5 text-emerald-500 shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"error\" && (\r\n <AlertCircleIcon className=\"w-3.5 h-3.5 text-red-500 shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"warning\" && (\r\n <AlertCircleIcon className=\"w-3.5 h-3.5 text-amber-500 shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"info\" && (\r\n <div className=\"w-1.5 h-1.5 rounded-full bg-[var(--accent)] mt-1.5 shrink-0\" />\r\n )}\r\n\r\n <div className=\"flex flex-col gap-0.5 min-w-0\">\r\n <span className=\"text-xs font-medium leading-snug break-words text-zinc-200\">\r\n {n.message}\r\n </span>\r\n {n.action && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n n.action?.onClick();\r\n }}\r\n className=\"mt-1 self-start text-[10px] font-bold text-[var(--accent)] hover:text-white transition-colors uppercase tracking-wider\"\r\n >\r\n {n.action.label}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n","\r\nimport React from 'react';\r\nimport { SubtitleSettings } from '../../core/StrataCore';\r\n\r\nexport const SubtitleOverlay = ({ cues, settings }: { cues: string[], settings: SubtitleSettings }) => {\r\n if (settings.useNative || cues.length === 0) return null;\r\n\r\n const getTextShadow = () => {\r\n switch (settings.textStyle) {\r\n case 'outline': return '0px 0px 4px black, 0px 0px 4px black'; // Simplified stroke\r\n case 'raised': return '0 -1px 1px black, 0 -2px 2px black'; // Pseudo 3D raised\r\n case 'depressed': return '0 1px 1px white, 0 2px 2px black'; // Pseudo 3D depressed\r\n case 'shadow': return '2px 2px 2px rgba(0,0,0,0.8)';\r\n default: return 'none';\r\n }\r\n };\r\n\r\n return (\r\n <div\r\n className=\"absolute inset-x-0 flex flex-col items-center justify-end text-center z-10 pointer-events-none transition-all duration-200\"\r\n style={{\r\n bottom: `${settings.verticalOffset}px`\r\n }}\r\n >\r\n {cues.map((text, i) => (\r\n <div\r\n key={i}\r\n className=\"mb-1 inline-block max-w-[80%]\"\r\n style={{\r\n fontSize: `${settings.textSize}%`,\r\n color: settings.textColor,\r\n fontWeight: settings.isBold ? 'bold' : 'normal',\r\n textTransform: settings.fixCapitalization ? 'capitalize' : 'none',\r\n textShadow: getTextShadow(),\r\n lineHeight: 1.4\r\n }}\r\n >\r\n <span\r\n className=\"px-2 py-0.5 rounded\"\r\n style={{\r\n backgroundColor: `rgba(0, 0, 0, ${settings.backgroundOpacity / 100})`,\r\n backdropFilter: settings.backgroundBlur ? `blur(${settings.backgroundBlurAmount}px)` : 'none',\r\n }}\r\n dangerouslySetInnerHTML={{ __html: text }} // VTT supports some HTML-like tags\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n};\r\n","\r\nimport React from 'react';\r\n\r\n// Helper for rendering string/node safely (duplicated from Menu for isolation)\r\nconst RenderContent = ({ content }: { content: string | React.ReactNode }) => {\r\n if (typeof content === 'string') {\r\n if (content.trim().startsWith('<')) return <span dangerouslySetInnerHTML={{ __html: content }} />;\r\n return <span>{content}</span>;\r\n }\r\n return <>{content}</>;\r\n};\r\n\r\nexport const Toggle = ({ label, checked, onChange, icon, tooltip }: any) => (\r\n <div\r\n className=\"flex items-center justify-between py-2.5 px-3 hover:bg-white/5 group transition-colors\"\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n {icon && <span className=\"text-zinc-500 group-hover:text-zinc-400 transition-colors flex items-center justify-center w-4 h-4\"><RenderContent content={icon} /></span>}\r\n <div className=\"flex flex-col\">\r\n <span className=\"text-sm text-zinc-300 font-medium group-hover:text-white transition-colors flex items-center\">\r\n <RenderContent content={label} />\r\n </span>\r\n {tooltip && <span className=\"text-[10px] text-zinc-500\">{tooltip}</span>}\r\n </div>\r\n </div>\r\n <button\r\n onClick={() => onChange(!checked)}\r\n className={`w-11 h-6 shrink-0 transition-colors relative focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-zinc-900 ${checked ? 'bg-[var(--accent)]' : 'bg-zinc-700'}`}\r\n style={{\r\n '--tw-ring-color': 'var(--accent)',\r\n borderRadius: 'var(--radius-full)',\r\n borderWidth: 'var(--border-width)',\r\n borderColor: 'rgba(255,255,255,0.1)'\r\n } as React.CSSProperties}\r\n >\r\n <div\r\n className={`absolute top-1/2 -translate-y-1/2 left-1 w-4 h-4 transition-transform shadow-sm ${checked ? 'translate-x-5' : 'translate-x-0'}`}\r\n style={{\r\n borderRadius: 'var(--radius-full)',\r\n backgroundColor: checked ? 'var(--accent-contrast)' : '#ffffff'\r\n }}\r\n />\r\n </button>\r\n </div>\r\n);\r\n\r\nexport const Slider = ({ label, value, min, max, step, onChange, formatValue, icon }: any) => (\r\n <div\r\n className=\"py-2.5 px-3 hover:bg-white/5 group transition-colors\"\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex justify-between items-center mb-2\">\r\n <div className=\"flex items-center gap-3\">\r\n {icon && <span className=\"text-zinc-500 group-hover:text-zinc-400 transition-colors flex items-center justify-center w-4 h-4\"><RenderContent content={icon} /></span>}\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">{label}</span>\r\n </div>\r\n <span\r\n className=\"text-[10px] font-mono font-medium text-zinc-300 bg-white/10 px-1.5 py-0.5 tabular-nums\"\r\n style={{ borderRadius: 'var(--radius-sm)' }}\r\n >{formatValue ? formatValue(value) : value}</span>\r\n </div>\r\n <div className=\"relative h-4 flex items-center px-1\">\r\n <input\r\n type=\"range\"\r\n min={min} max={max} step={step}\r\n value={value}\r\n onChange={(e) => onChange(parseFloat(e.target.value))}\r\n className=\"w-full h-1.5 appearance-none cursor-pointer focus:outline-none focus:ring-2 strata-range-input\"\r\n style={{\r\n borderRadius: 'var(--radius-full)',\r\n background: `linear-gradient(to right, var(--accent) 0%, var(--accent) ${(value - min) / (max - min) * 100}%, #3f3f46 ${(value - min) / (max - min) * 100}%, #3f3f46 100%)`,\r\n '--tw-ring-color': 'var(--accent)'\r\n } as React.CSSProperties}\r\n />\r\n <style>{`\r\n .strata-range-input::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n height: 14px;\r\n width: 14px;\r\n background: #ffffff;\r\n cursor: pointer;\r\n box-shadow: 0 1px 3px rgba(0,0,0,0.5);\r\n transition: transform 0.1s;\r\n border-radius: var(--radius-full);\r\n border: var(--border-width) solid rgba(0,0,0,0.1);\r\n }\r\n .strata-range-input::-webkit-slider-thumb:hover {\r\n transform: scale(1.1);\r\n }\r\n /* Pixel theme specific overrides are handled by global css */\r\n `}</style>\r\n </div>\r\n </div>\r\n);\r\n\r\nexport const Select = ({ label, value, options, onChange, icon }: any) => (\r\n <div\r\n className=\"py-2.5 px-3 hover:bg-white/5 group transition-colors\"\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex items-center gap-3 mb-2\">\r\n {icon && <span className=\"text-zinc-500 group-hover:text-zinc-400 transition-colors flex items-center justify-center w-4 h-4\"><RenderContent content={icon} /></span>}\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">{label}</span>\r\n </div>\r\n <div className=\"relative\">\r\n <select\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n className=\"w-full bg-zinc-800 border-[length:var(--border-width)] border-white/10 px-3 py-2 text-sm text-zinc-200 focus:outline-none focus:ring-2 appearance-none hover:bg-zinc-700 transition-colors cursor-pointer\"\r\n style={{ '--tw-ring-color': 'var(--accent)', borderRadius: 'var(--radius)' } as React.CSSProperties}\r\n >\r\n {options.map((opt: any) => (\r\n <option key={opt.value} value={opt.value}>{opt.label}</option>\r\n ))}\r\n </select>\r\n <div className=\"absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-zinc-400\">\r\n <svg width=\"10\" height=\"6\" viewBox=\"0 0 10 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1 1L5 5L9 1\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>\r\n </div>\r\n </div>\r\n </div>\r\n);\r\n\r\nexport const SettingsGroup = ({ title, children }: any) => (\r\n <div className=\"py-2\">\r\n {title && <h4 className=\"px-3 text-[10px] font-bold text-[var(--accent)] uppercase tracking-wider mb-1 mt-2\">{title}</h4>}\r\n <div className=\"space-y-0.5\">\r\n {children}\r\n </div>\r\n </div>\r\n);\r\n","import React, { useRef, useLayoutEffect, useState, useEffect } from \"react\";\r\nimport { ArrowLeftIcon, CheckIcon } from \"../Icons\";\r\nimport { SettingItem } from \"../../core/StrataCore\";\r\nimport { Toggle, Slider, SettingsGroup } from \"./SettingsPrimitives\";\r\n\r\nexport const Menu = ({\r\n children,\r\n onClose,\r\n align = \"right\",\r\n maxHeight,\r\n className,\r\n}: {\r\n children?: React.ReactNode;\r\n onClose: () => void;\r\n align?: \"right\" | \"center\";\r\n maxHeight?: number;\r\n className?: string;\r\n}) => {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const contentRef = useRef<HTMLDivElement>(null);\r\n const [height, setHeight] = useState<number | \"auto\">(\"auto\");\r\n\r\n const positionClasses =\r\n align === \"center\"\r\n ? \"left-1/2 -translate-x-1/2 origin-bottom\"\r\n : \"right-0 origin-bottom-right\";\r\n\r\n // Smooth height animation logic\r\n useLayoutEffect(() => {\r\n if (!contentRef.current) return;\r\n\r\n const updateHeight = () => {\r\n if (contentRef.current) {\r\n setHeight(contentRef.current.offsetHeight);\r\n }\r\n };\r\n\r\n const observer = new ResizeObserver(updateHeight);\r\n observer.observe(contentRef.current);\r\n\r\n // Initial measure\r\n updateHeight();\r\n\r\n return () => observer.disconnect();\r\n }, []);\r\n\r\n // Constrain dynamic height by maxHeight prop if provided\r\n const calculatedStyle = {\r\n height: height === \"auto\" ? \"auto\" : `${height + 14}px`, // + padding\r\n maxHeight: maxHeight ? `${maxHeight}px` : undefined,\r\n };\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={`absolute bottom-full mb-4 ${positionClasses} bg-[var(--bg-panel)] backdrop-blur-xl border-[length:var(--border-width)] border-white/10 shadow-2xl overflow-hidden w-[300px] max-w-[calc(100vw-32px)] text-sm z-50 ring-1 ring-white/5 font-[family-name:var(--font-main)] flex flex-col p-1.5 transition-[height,opacity,transform] duration-300 ease-out ${className}`}\r\n style={{ ...calculatedStyle, borderRadius: \"var(--radius-lg)\" }}\r\n onClick={(e) => e.stopPropagation()}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n >\r\n <div\r\n className=\"overflow-y-auto hide-scrollbar flex-1\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <div ref={contentRef}>{children}</div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// Helper for rendering string/node safely\r\nconst RenderContent = ({\r\n content,\r\n className,\r\n}: {\r\n content: string | React.ReactNode;\r\n className?: string;\r\n}) => {\r\n if (typeof content === \"string\") {\r\n // If it looks like HTML, use dangerous. Otherwise regular text.\r\n if (content.trim().startsWith(\"<\"))\r\n return (\r\n <span\r\n className={className}\r\n dangerouslySetInnerHTML={{ __html: content }}\r\n />\r\n );\r\n return <span className={className}>{content}</span>;\r\n }\r\n return <span className={className}>{content}</span>;\r\n};\r\n\r\nexport const MenuItem = ({\r\n label,\r\n value,\r\n active,\r\n onClick,\r\n hasSubmenu,\r\n icon,\r\n rightIcon,\r\n}: any) => (\r\n <button\r\n onClick={onClick}\r\n className=\"w-full flex items-center justify-between px-3 py-2.5 hover:bg-white/10 transition-colors text-left text-zinc-200 active:bg-white/5 focus:outline-none focus:bg-white/10 group overflow-hidden my-0.5\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <div className=\"flex items-center gap-3 overflow-hidden\">\r\n {icon && (\r\n <span className=\"text-zinc-400 shrink-0 group-hover:text-zinc-300 transition-colors flex items-center justify-center w-4 h-4\">\r\n <RenderContent content={icon} />\r\n </span>\r\n )}\r\n <span\r\n className={`font-medium truncate text-sm flex items-center ${active ? \"text-[var(--accent)]\" : \"\"}`}\r\n title={typeof label === \"string\" ? label : undefined}\r\n >\r\n <RenderContent content={label} />\r\n </span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-zinc-400 shrink-0\">\r\n {value && (\r\n <span\r\n className=\"text-xs font-medium truncate max-w-[60px]\"\r\n title={value}\r\n >\r\n <RenderContent content={value} />\r\n </span>\r\n )}\r\n {rightIcon}\r\n {active && (\r\n <CheckIcon className=\"w-4 h-4 text-[var(--accent)] shrink-0\" />\r\n )}\r\n {hasSubmenu && (\r\n <span className=\"text-xs group-hover:translate-x-0.5 transition-transform text-zinc-500 shrink-0\">\r\n ›\r\n </span>\r\n )}\r\n </div>\r\n </button>\r\n);\r\n\r\nexport const MenuHeader = ({\r\n label,\r\n onBack,\r\n rightAction,\r\n}: {\r\n label: string | React.ReactNode;\r\n onBack: () => void;\r\n rightAction?: React.ReactNode;\r\n}) => (\r\n <div\r\n className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <button\r\n className=\"flex items-center gap-2 hover:text-white transition-colors focus:outline-none\"\r\n onClick={onBack}\r\n >\r\n <ArrowLeftIcon className=\"w-3 h-3\" />\r\n <span>\r\n <RenderContent content={label} />\r\n </span>\r\n </button>\r\n {rightAction}\r\n </div>\r\n);\r\n\r\nexport const MenuDivider = () => (\r\n <div className=\"h-px bg-white/5 mx-2 my-1\"></div>\r\n);\r\n\r\n// --- Recursive Menu Explorer ---\r\n\r\nexport const MenuExplorer = ({\r\n items,\r\n onClose,\r\n title,\r\n maxHeight,\r\n className,\r\n}: {\r\n items: SettingItem[];\r\n onClose: () => void;\r\n title?: string;\r\n maxHeight?: number;\r\n className?: string;\r\n}) => {\r\n const [history, setHistory] = useState<SettingItem[]>([]);\r\n\r\n // Current view context\r\n const currentItem = history.length > 0 ? history[history.length - 1] : null;\r\n const currentList = currentItem ? currentItem.children || [] : items;\r\n const currentTitle = currentItem ? currentItem.html : title || \"Menu\";\r\n\r\n const goBack = () => {\r\n setHistory((prev) => prev.slice(0, -1));\r\n };\r\n\r\n const navigateTo = (item: SettingItem) => {\r\n if (item.children) {\r\n setHistory((prev) => [...prev, item]);\r\n }\r\n };\r\n\r\n return (\r\n <Menu onClose={onClose} maxHeight={maxHeight} className={className}>\r\n <div className=\"animate-in fade-in slide-in-from-right-4 duration-200\">\r\n {/* Header (Only if deep or title exists and is root) */}\r\n {history.length > 0 ? (\r\n <MenuHeader label={currentTitle || \"Menu\"} onBack={goBack} />\r\n ) : (\r\n title && (\r\n <div\r\n className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <span>{title}</span>\r\n </div>\r\n )\r\n )}\r\n\r\n <div className=\"pb-1\">\r\n {currentList.map((item, i) => {\r\n // Case 0: Separator\r\n if (item.separator) {\r\n return <MenuDivider key={i} />;\r\n }\r\n\r\n // Case 0.5: Label\r\n if (item.isLabel) {\r\n return (\r\n <div\r\n key={i}\r\n className=\"px-3 py-1.5 text-[10px] font-bold text-zinc-500 uppercase tracking-wider select-none\"\r\n >\r\n <RenderContent content={item.html || \"\"} />\r\n </div>\r\n );\r\n }\r\n\r\n // Case 1: Range (Slider)\r\n if (item.range) {\r\n return (\r\n <div key={i} className=\"px-1\">\r\n <Slider\r\n label={item.html}\r\n icon={item.icon}\r\n value={item.value ?? item.min ?? 0}\r\n min={item.min ?? 0}\r\n max={item.max ?? 100}\r\n step={item.step ?? 1}\r\n onChange={(val: number) =>\r\n item.onRange && item.onRange(val)\r\n }\r\n formatValue={item.formatValue}\r\n />\r\n </div>\r\n );\r\n }\r\n\r\n // Case 2: Toggle Switch\r\n if (item.switch !== undefined) {\r\n return (\r\n <div key={i} className=\"px-1\">\r\n <Toggle\r\n label={item.html}\r\n icon={item.icon}\r\n checked={item.switch}\r\n tooltip={item.tooltip}\r\n onChange={(val: boolean) =>\r\n item.onSwitch && item.onSwitch(item, val)\r\n }\r\n />\r\n </div>\r\n );\r\n }\r\n\r\n // Case 3: Navigation (Children) or Action\r\n return (\r\n <React.Fragment key={i}>\r\n <MenuItem\r\n label={item.html}\r\n icon={item.icon}\r\n value={item.currentLabel || item.value}\r\n active={item.active}\r\n hasSubmenu={!!item.children}\r\n onClick={() => {\r\n if (item.children) {\r\n navigateTo(item);\r\n } else if (item.onClick) {\r\n item.onClick(item);\r\n if (!item.switch && !item.range) {\r\n // Close on standard actions\r\n onClose();\r\n }\r\n } else if (item.click) {\r\n item.click(item);\r\n onClose();\r\n }\r\n }}\r\n />\r\n </React.Fragment>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </Menu>\r\n );\r\n};\r\n","import React, { useState, useRef, useMemo } from \"react\";\r\nimport { SubtitleSettings, SubtitleTrackState } from \"../../core/StrataCore\";\r\nimport { Menu, MenuItem, MenuHeader } from \"./Menu\";\r\nimport { SettingsGroup, Toggle, Slider, Select } from \"./SettingsPrimitives\";\r\nimport {\r\n UploadIcon,\r\n CustomizeIcon,\r\n ResetIcon,\r\n ClockIcon,\r\n MinusIcon,\r\n PlusIcon,\r\n MoveVerticalIcon,\r\n TypeIcon,\r\n PaletteIcon,\r\n BoldIcon,\r\n CaseUpperIcon,\r\n EyeIcon,\r\n BlurIcon,\r\n SearchIcon,\r\n LoaderIcon,\r\n FileCheckIcon,\r\n FileWarningIcon,\r\n} from \"../Icons\";\r\n\r\nexport const SubtitleMenu = ({\r\n tracks,\r\n current,\r\n onSelect,\r\n onUpload,\r\n onClose,\r\n settings,\r\n onSettingsChange,\r\n onReset,\r\n offset,\r\n onOffsetChange,\r\n maxHeight,\r\n animationClass,\r\n}: {\r\n tracks: SubtitleTrackState[];\r\n current: number;\r\n onSelect: (index: number) => void;\r\n onUpload: (file: File) => void;\r\n onClose: () => void;\r\n settings: SubtitleSettings;\r\n onSettingsChange: (settings: Partial<SubtitleSettings>) => void;\r\n onReset: () => void;\r\n offset: number;\r\n onOffsetChange: (val: number) => void;\r\n maxHeight: number;\r\n animationClass: string;\r\n}) => {\r\n const [view, setView] = useState<\"main\" | \"customize\">(\"main\");\r\n const [search, setSearch] = useState(\"\");\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n const filteredTracks = useMemo(() => {\r\n if (!search) return tracks;\r\n return tracks.filter(\r\n (t) =>\r\n t.label.toLowerCase().includes(search.toLowerCase()) ||\r\n (t.srcLang && t.srcLang.toLowerCase().includes(search.toLowerCase())),\r\n );\r\n }, [tracks, search]);\r\n\r\n return (\r\n <Menu\r\n onClose={onClose}\r\n align=\"right\"\r\n maxHeight={maxHeight}\r\n className={animationClass}\r\n >\r\n {view === \"main\" && (\r\n <div className=\"animate-in slide-in-from-left-4 fade-in duration-200 flex flex-col h-full\">\r\n <div\r\n className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md shrink-0\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <span>Subtitles</span>\r\n </div>\r\n\r\n <div className=\"px-1.5 pb-2 shrink-0\">\r\n <MenuItem\r\n label=\"Upload Subtitle\"\r\n icon={<UploadIcon className=\"w-4 h-4\" />}\r\n onClick={() => fileInputRef.current?.click()}\r\n />\r\n <input\r\n type=\"file\"\r\n accept=\".vtt,.srt\"\r\n ref={fileInputRef}\r\n className=\"hidden\"\r\n onChange={(e) => {\r\n if (e.target.files?.[0]) onUpload(e.target.files[0]);\r\n }}\r\n />\r\n <MenuItem\r\n label=\"Customize\"\r\n icon={<CustomizeIcon className=\"w-4 h-4\" />}\r\n onClick={() => setView(\"customize\")}\r\n hasSubmenu\r\n />\r\n <div className=\"h-px bg-white/5 mx-2 my-1\"></div>\r\n <MenuItem\r\n label=\"Off\"\r\n active={current === -1}\r\n onClick={() => {\r\n onSelect(-1);\r\n onClose();\r\n }}\r\n />\r\n\r\n <div className=\"relative mt-2\">\r\n <input\r\n type=\"text\"\r\n placeholder=\"Search subtitles...\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n className=\"w-full bg-zinc-800/50 border border-white/10 rounded-md py-1.5 pl-8 pr-3 text-xs text-zinc-200 focus:outline-none focus:border-white/20 transition-colors\"\r\n />\r\n <SearchIcon className=\"w-3.5 h-3.5 text-zinc-500 absolute left-2.5 top-1/2 -translate-y-1/2 pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n <div className=\"overflow-y-auto hide-scrollbar flex-1\">\r\n {filteredTracks.map((track) => {\r\n let rightIcon = null;\r\n if (track.status === \"loading\") {\r\n rightIcon = (\r\n <LoaderIcon className=\"w-3.5 h-3.5 animate-spin text-[var(--accent)]\" />\r\n );\r\n } else if (track.status === \"error\") {\r\n rightIcon = (\r\n <FileWarningIcon className=\"w-3.5 h-3.5 text-red-500\" />\r\n );\r\n } else if (track.status === \"success\") {\r\n rightIcon = (\r\n <FileCheckIcon className=\"w-3.5 h-3.5 text-emerald-500\" />\r\n );\r\n }\r\n\r\n return (\r\n <MenuItem\r\n key={track.index}\r\n label={track.label}\r\n value={track.srcLang}\r\n active={current === track.index}\r\n rightIcon={rightIcon}\r\n onClick={() => {\r\n onSelect(track.index);\r\n onClose();\r\n }}\r\n />\r\n );\r\n })}\r\n {filteredTracks.length === 0 && search && (\r\n <div className=\"px-4 py-3 text-center text-xs text-zinc-500\">\r\n No results found\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {view === \"customize\" && (\r\n <div className=\"animate-in slide-in-from-right-4 fade-in duration-200\">\r\n <MenuHeader\r\n label=\"Customize\"\r\n onBack={() => setView(\"main\")}\r\n rightAction={\r\n <button\r\n onClick={onReset}\r\n className=\"p-1.5 text-zinc-400 hover:text-white transition-colors rounded-md hover:bg-white/10\"\r\n title=\"Reset All\"\r\n >\r\n <ResetIcon className=\"w-4 h-4\" />\r\n </button>\r\n }\r\n />\r\n\r\n <div className=\"pb-1\">\r\n <SettingsGroup>\r\n <Toggle\r\n label=\"Native Video Subtitle\"\r\n checked={settings.useNative}\r\n onChange={(val: boolean) =>\r\n onSettingsChange({ useNative: val })\r\n }\r\n />\r\n </SettingsGroup>\r\n\r\n {!settings.useNative && (\r\n <>\r\n <SettingsGroup title=\"Sync & Position\">\r\n <div className=\"py-2.5 px-3 rounded-lg hover:bg-white/5 group transition-colors\">\r\n <div className=\"flex justify-between items-center mb-2\">\r\n <div className=\"flex items-center gap-3\">\r\n <ClockIcon className=\"w-4 h-4 text-zinc-500 group-hover:text-zinc-400 transition-colors\" />\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">\r\n Sync Offset\r\n </span>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() =>\r\n onOffsetChange(Math.round((offset - 0.1) * 10) / 10)\r\n }\r\n className=\"w-8 h-8 flex items-center justify-center bg-zinc-800 rounded-lg hover:bg-zinc-700 text-zinc-300 transition-colors active:scale-95\"\r\n >\r\n <MinusIcon className=\"w-4 h-4\" />\r\n </button>\r\n <div className=\"flex-1 bg-zinc-900 border border-white/5 rounded-lg h-8 flex items-center justify-center text-xs font-mono font-medium text-[var(--accent)]\">\r\n {offset > 0 ? \"+\" : \"\"}\r\n {offset?.toFixed(1) || \"0.0\"}s\r\n </div>\r\n <button\r\n onClick={() =>\r\n onOffsetChange(Math.round((offset + 0.1) * 10) / 10)\r\n }\r\n className=\"w-8 h-8 flex items-center justify-center bg-zinc-800 rounded-lg hover:bg-zinc-700 text-zinc-300 transition-colors active:scale-95\"\r\n >\r\n <PlusIcon className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <Slider\r\n label=\"Vertical Position\"\r\n icon={<MoveVerticalIcon className=\"w-4 h-4\" />}\r\n value={settings.verticalOffset}\r\n min={0}\r\n max={200}\r\n step={5}\r\n onChange={(val: number) =>\r\n onSettingsChange({ verticalOffset: val })\r\n }\r\n formatValue={(v: number) => `${v}px`}\r\n />\r\n </SettingsGroup>\r\n\r\n <SettingsGroup title=\"Appearance\">\r\n <Slider\r\n label=\"Text Size\"\r\n icon={<TypeIcon className=\"w-4 h-4\" />}\r\n value={settings.textSize}\r\n min={50}\r\n max={200}\r\n step={10}\r\n onChange={(val: number) =>\r\n onSettingsChange({ textSize: val })\r\n }\r\n formatValue={(v: number) => `${v}%`}\r\n />\r\n\r\n <div className=\"py-2.5 px-3 rounded-lg hover:bg-white/5 group transition-colors\">\r\n <div className=\"flex items-center gap-3 mb-2\">\r\n <PaletteIcon className=\"w-4 h-4 text-zinc-500 group-hover:text-zinc-400 transition-colors\" />\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">\r\n Text Color\r\n </span>\r\n </div>\r\n <div className=\"flex items-center justify-between gap-2 p-1 bg-zinc-800/50 rounded-lg\">\r\n {[\r\n \"#ffffff\",\r\n \"#ffff00\",\r\n \"#00ffff\",\r\n \"#ff00ff\",\r\n \"#ff0000\",\r\n \"#00ff00\",\r\n ].map((c) => (\r\n <button\r\n key={c}\r\n onClick={() => onSettingsChange({ textColor: c })}\r\n className={`w-6 h-6 rounded-full border border-white/10 transition-transform hover:scale-110 ${settings.textColor === c ? \"ring-2 scale-110\" : \"\"}`}\r\n style={\r\n {\r\n backgroundColor: c,\r\n \"--tw-ring-color\": \"var(--accent)\",\r\n } as any\r\n }\r\n />\r\n ))}\r\n <div className=\"w-px h-6 bg-white/10 mx-1\"></div>\r\n <div className=\"relative w-6 h-6 rounded-full overflow-hidden ring-1 ring-white/20 cursor-pointer\">\r\n <input\r\n type=\"color\"\r\n value={settings.textColor}\r\n onChange={(e) =>\r\n onSettingsChange({ textColor: e.target.value })\r\n }\r\n className=\"absolute inset-[-4px] w-[150%] h-[150%] cursor-pointer p-0 border-0\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <Select\r\n label=\"Text Style\"\r\n value={settings.textStyle}\r\n options={[\r\n { label: \"None\", value: \"none\" },\r\n { label: \"Outline\", value: \"outline\" },\r\n { label: \"Raised\", value: \"raised\" },\r\n { label: \"Depressed\", value: \"depressed\" },\r\n { label: \"Drop Shadow\", value: \"shadow\" },\r\n ]}\r\n onChange={(val: string) =>\r\n onSettingsChange({\r\n textStyle: val as SubtitleSettings[\"textStyle\"],\r\n })\r\n }\r\n />\r\n\r\n <div className=\"grid grid-cols-2 gap-2 mt-1 px-1\">\r\n <Toggle\r\n label=\"Bold\"\r\n icon={<BoldIcon className=\"w-4 h-4\" />}\r\n checked={settings.isBold}\r\n onChange={(v: boolean) => onSettingsChange({ isBold: v })}\r\n />\r\n <Toggle\r\n label=\"Fix Caps\"\r\n icon={<CaseUpperIcon className=\"w-4 h-4\" />}\r\n checked={settings.fixCapitalization}\r\n onChange={(v: boolean) =>\r\n onSettingsChange({ fixCapitalization: v })\r\n }\r\n />\r\n </div>\r\n </SettingsGroup>\r\n\r\n <SettingsGroup title=\"Background\">\r\n <Slider\r\n label=\"Opacity\"\r\n icon={<EyeIcon className=\"w-4 h-4\" />}\r\n value={settings.backgroundOpacity}\r\n min={0}\r\n max={100}\r\n step={5}\r\n onChange={(val: number) =>\r\n onSettingsChange({ backgroundOpacity: val })\r\n }\r\n formatValue={(v: number) => `${v}%`}\r\n />\r\n\r\n <Toggle\r\n label=\"Blur Background\"\r\n icon={<BlurIcon className=\"w-4 h-4\" />}\r\n checked={settings.backgroundBlur}\r\n onChange={(v: boolean) =>\r\n onSettingsChange({ backgroundBlur: v })\r\n }\r\n />\r\n\r\n {settings.backgroundBlur && (\r\n <Slider\r\n label=\"Blur Intensity\"\r\n value={settings.backgroundBlurAmount}\r\n min={0}\r\n max={20}\r\n step={1}\r\n onChange={(val: number) =>\r\n onSettingsChange({ backgroundBlurAmount: val })\r\n }\r\n formatValue={(v: number) => `${v}px`}\r\n />\r\n )}\r\n </SettingsGroup>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </Menu>\r\n );\r\n};\r\n","\r\nimport React, { useRef, useEffect, useState, useLayoutEffect } from 'react';\r\nimport { ContextMenuItem } from '../../core/StrataCore';\r\nimport { CheckIcon } from '../Icons';\r\n\r\ninterface ContextMenuProps {\r\n x: number;\r\n y: number;\r\n items: ContextMenuItem[];\r\n onClose: () => void;\r\n containerWidth: number;\r\n containerHeight: number;\r\n}\r\n\r\nconst RenderContent = ({ content }: { content: string | React.ReactNode }) => {\r\n if (typeof content === 'string') {\r\n if (content.trim().startsWith('<')) return <span dangerouslySetInnerHTML={{ __html: content }} />;\r\n return <span>{content}</span>;\r\n }\r\n return <>{content}</>;\r\n};\r\n\r\nexport const ContextMenu = ({ x, y, items, onClose, containerWidth, containerHeight }: ContextMenuProps) => {\r\n const menuRef = useRef<HTMLDivElement>(null);\r\n const [layout, setLayout] = useState<{ top: number, left: number, maxHeight?: number, opacity: number }>({\r\n top: y,\r\n left: x,\r\n opacity: 0\r\n });\r\n\r\n useLayoutEffect(() => {\r\n if (!menuRef.current) return;\r\n\r\n const rect = menuRef.current.getBoundingClientRect();\r\n const width = rect.width;\r\n // Since we render all items initially, height is accurate\r\n const height = rect.height;\r\n\r\n let newLeft = x;\r\n let newTop = y;\r\n\r\n // Horizontal Logic: Flip left if overflowing right\r\n if (x + width > containerWidth - 10) {\r\n newLeft = x - width;\r\n }\r\n // Clamp left edge\r\n if (newLeft < 10) newLeft = 10;\r\n if (newLeft + width > containerWidth) newLeft = Math.max(10, containerWidth - width - 10);\r\n\r\n // Vertical Logic: Flip up if overflowing bottom\r\n if (y + height > containerHeight - 10) {\r\n newTop = y - height;\r\n }\r\n\r\n let availableHeight = containerHeight - 20;\r\n\r\n // Clamp top edge\r\n if (newTop < 10) newTop = 10;\r\n\r\n // If after flipping/clamping it still overflows bottom, we must shift up or limit height\r\n if (newTop + height > containerHeight - 10) {\r\n newTop = Math.max(10, containerHeight - height - 10);\r\n // If even at top it overflows, height is capped by container\r\n }\r\n\r\n setLayout({\r\n top: newTop,\r\n left: newLeft,\r\n maxHeight: availableHeight,\r\n opacity: 1\r\n });\r\n\r\n }, [x, y, items, containerWidth, containerHeight]);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\r\n onClose();\r\n }\r\n };\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, [onClose]);\r\n\r\n return (\r\n <div\r\n ref={menuRef}\r\n className=\"absolute z-50 min-w-[200px] bg-[var(--bg-panel)] backdrop-blur-xl border-[length:var(--border-width)] border-white/10 shadow-2xl p-1.5 font-[family-name:var(--font-main)] overflow-y-auto hide-scrollbar flex flex-col\"\r\n style={{\r\n top: layout.top,\r\n left: layout.left,\r\n maxHeight: layout.maxHeight,\r\n opacity: layout.opacity,\r\n borderRadius: 'var(--radius-lg)'\r\n }}\r\n onClick={(e) => e.stopPropagation()}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n >\r\n {items.map((item, index) => {\r\n // Separator Logic: 0 height with top border for a crisp line\r\n if (item.separator) {\r\n return <div key={index} className=\"h-0 border-t border-white/10 mx-2 my-1.5\" />;\r\n }\r\n\r\n // Label Logic\r\n if (item.isLabel) {\r\n return (\r\n <div key={index} className=\"px-3 py-1.5 text-[10px] font-bold text-zinc-500 uppercase tracking-wider select-none\">\r\n <RenderContent content={item.html || ''} />\r\n </div>\r\n );\r\n }\r\n\r\n // Standard Interactive Item\r\n return (\r\n <React.Fragment key={index}>\r\n <button\r\n onClick={() => {\r\n if (!item.disabled) {\r\n if (item.click) item.click(onClose);\r\n else if (item.onClick) item.onClick(onClose);\r\n }\r\n }}\r\n disabled={item.disabled}\r\n className={`w-full text-left px-3 py-2.5 flex items-center justify-between hover:bg-white/10 focus:bg-white/10 focus:outline-none transition-colors text-sm text-zinc-200 disabled:opacity-50 disabled:cursor-not-allowed group my-0.5`}\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex items-center gap-3 overflow-hidden\">\r\n {item.icon && <span className=\"text-zinc-400 w-4 h-4 flex items-center justify-center shrink-0 group-hover:text-zinc-300 transition-colors\"><RenderContent content={item.icon} /></span>}\r\n <span className={`flex items-center font-medium truncate ${item.checked ? 'text-[var(--accent)]' : ''}`}><RenderContent content={item.html || ''} /></span>\r\n </div>\r\n {item.checked && <CheckIcon className=\"w-4 h-4 text-[var(--accent)] shrink-0 ml-2\" />}\r\n </button>\r\n {/* Legacy support for showBorder, though item.separator is preferred now */}\r\n {item.showBorder && <div className=\"h-0 border-t border-white/10 mx-2 my-1\" />}\r\n </React.Fragment>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n","\r\nimport React, { useEffect, useState } from 'react';\r\nimport { StrataCore } from '../../core/StrataCore';\r\nimport { CloseIcon } from '../Icons';\r\n\r\nexport const VideoInfo = ({ player, onClose }: { player: StrataCore, onClose: () => void }) => {\r\n const [stats, setStats] = useState<Record<string, string | number>>({});\r\n\r\n useEffect(() => {\r\n const update = () => {\r\n if (!player.video) return;\r\n const v = player.video;\r\n const q = (v as any).getVideoPlaybackQuality ? (v as any).getVideoPlaybackQuality() : null;\r\n\r\n setStats({\r\n 'Player Size': `${v.offsetWidth} x ${v.offsetHeight}`,\r\n 'Video Resolution': `${v.videoWidth} x ${v.videoHeight}`,\r\n 'Current Time': `${v.currentTime.toFixed(3)}s`,\r\n 'Duration': `${v.duration.toFixed(3)}s`,\r\n 'Volume': `${Math.round(v.volume * 100)}%`,\r\n 'Dropped Frames': q ? q.droppedVideoFrames : 'N/A',\r\n 'Buffer': v.buffered.length > 0 ? `${(v.buffered.end(v.buffered.length - 1) - v.currentTime).toFixed(2)}s` : '0s',\r\n 'Engine': player.store.get().sources[player.store.get().currentSourceIndex]?.type || 'native',\r\n 'URL': v.currentSrc\r\n });\r\n };\r\n update();\r\n const timer = setInterval(update, 1000);\r\n return () => clearInterval(timer);\r\n }, [player]);\r\n\r\n return (\r\n <div className=\"absolute inset-0 z-[60] flex items-center justify-center bg-black/60 backdrop-blur-sm p-4 animate-in fade-in duration-200\">\r\n <div\r\n className=\"bg-[var(--bg-panel)] border border-white/10 rounded-xl w-full max-w-md shadow-2xl relative font-mono text-xs text-zinc-300 flex flex-col\"\r\n style={{ borderRadius: 'var(--radius)', maxHeight: '90%' }}\r\n >\r\n <div className=\"p-5 pb-0 flex-shrink-0 relative\">\r\n <button\r\n onClick={(e) => { e.stopPropagation(); onClose(); }}\r\n className=\"absolute top-3 right-3 p-1.5 text-zinc-400 hover:text-white hover:bg-white/10 rounded-full transition-colors\"\r\n >\r\n <CloseIcon className=\"w-4 h-4\" />\r\n </button>\r\n <h3 className=\"text-sm font-bold text-white mb-4 uppercase tracking-wider border-b border-white/10 pb-2\">Video Statistics</h3>\r\n </div>\r\n\r\n <div className=\"overflow-y-auto hide-scrollbar p-5 pt-0 space-y-2.5 flex-1 min-h-0\">\r\n {Object.entries(stats).map(([k, v]) => (\r\n <div key={k} className=\"flex flex-col sm:flex-row sm:justify-between sm:items-center gap-1\">\r\n <span className=\"text-zinc-500 font-bold shrink-0\">{k}</span>\r\n <span className=\"text-zinc-200 truncate select-all font-medium bg-white/5 px-1.5 py-0.5 rounded break-all text-right\" title={String(v)}>{String(v)}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\r\nimport React, { useEffect, useRef, useState, useSyncExternalStore, useCallback, useMemo, useLayoutEffect } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { StrataCore, PlayerState, TextTrackConfig, SubtitleSettings, PlayerTheme, StrataConfig, getResolvedState, DEFAULT_STATE, IPlugin, PlayerSource, ControlItem, ContextMenuItem, SettingItem } from '../core/StrataCore';\r\nimport { formatTime, parseVTT, ThumbnailCue } from '../utils/playerUtils';\r\nimport { useTransition } from './hooks/useTransition';\r\nimport { NotificationContainer } from './components/NotificationContainer';\r\nimport { SubtitleOverlay } from './components/SubtitleOverlay';\r\nimport { Menu, MenuItem, MenuHeader, MenuDivider, MenuExplorer } from './components/Menu';\r\nimport { SubtitleMenu } from './components/SubtitleMenu';\r\nimport { ContextMenu } from './components/ContextMenu';\r\nimport { VideoInfo } from './components/VideoInfo';\r\nimport { SettingsGroup, Toggle, Slider, Select } from './components/SettingsPrimitives';\r\nimport {\r\n PlayIcon, PauseIcon, VolumeHighIcon, VolumeLowIcon, VolumeMuteIcon,\r\n MaximizeIcon, MinimizeIcon, SettingsIcon, PipIcon,\r\n SubtitleIcon, DownloadIcon, Replay10Icon, Forward10Icon,\r\n LoaderIcon, CastIcon, UsersIcon, PaletteIcon, CheckIcon,\r\n CustomizeIcon, CameraIcon, LockIcon, UnlockIcon, WebFullscreenIcon,\r\n FastForwardIcon, RatioIcon, ExpandIcon, InfoIcon,\r\n ServerIcon, LayersIcon, CropIcon, SpeakerIcon, FlipIcon, GaugeIcon, MusicIcon, WifiIcon, AlertCircleIcon, QualityIcon, VideoFlipIcon, FileCheckIcon\r\n} from './Icons';\r\n\r\ndeclare module 'react' {\r\n namespace JSX {\r\n interface IntrinsicElements {\r\n 'google-cast-launcher': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;\r\n }\r\n }\r\n}\r\n\r\n// Helper to determine best contrast color (black or white) for a given hex background\r\nfunction getContrastColor(hex: string) {\r\n if (!hex) return '#ffffff';\r\n hex = hex.replace('#', '');\r\n if (hex.length === 3) {\r\n hex = hex.split('').map(char => char + char).join('');\r\n }\r\n const r = parseInt(hex.substring(0, 2), 16);\r\n const g = parseInt(hex.substring(2, 4), 16);\r\n const b = parseInt(hex.substring(4, 6), 16);\r\n const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;\r\n return (yiq >= 128) ? '#000000' : '#ffffff';\r\n}\r\n\r\n// --- Main Player Component ---\r\n\r\ninterface StrataPlayerProps extends StrataConfig {\r\n src?: string; // Optional if sources are provided\r\n type?: string; // Optional: Explicitly define type for the src (e.g. 'hls', 'dash')\r\n sources?: PlayerSource[]; // Array of sources\r\n poster?: string;\r\n thumbnails?: string; // URL to VTT thumbnails\r\n textTracks?: TextTrackConfig[];\r\n plugins?: IPlugin[]; // Allow injecting plugins from outside\r\n autoPlay?: boolean; // Added prop\r\n onGetInstance?: (core: StrataCore) => void; // Expose instance\r\n}\r\n\r\nconst THEME_COLORS = [\r\n { label: 'Strata', value: '#6366f1' },\r\n { label: 'Emerald', value: '#10b981' },\r\n { label: 'Rose', value: '#f43f5e' },\r\n { label: 'Amber', value: '#f59e0b' },\r\n { label: 'Sky', value: '#0ea5e9' },\r\n { label: 'Violet', value: '#8b5cf6' },\r\n];\r\n\r\nconst THEMES: { label: string, value: PlayerTheme, color: string }[] = [\r\n { label: 'Default', value: 'default', color: '#6366f1' },\r\n { label: 'Pixel', value: 'pixel', color: '#ef4444' },\r\n { label: 'Game', value: 'game', color: '#eab308' },\r\n { label: 'Hacker', value: 'hacker', color: '#22c55e' },\r\n];\r\n\r\n// Helper to render HTML strings safely or pass nodes through\r\nconst HtmlOrNode = ({ content, className, style }: { content: string | React.ReactNode, className?: string, style?: React.CSSProperties }) => {\r\n if (typeof content === 'string') {\r\n if (content.trim().startsWith('<')) {\r\n return <div className={className} style={style} dangerouslySetInnerHTML={{ __html: content }} />;\r\n }\r\n return <div className={className} style={style}>{content}</div>;\r\n }\r\n return <div className={className} style={style}>{content}</div>;\r\n};\r\n\r\nexport const StrataPlayer = (props: StrataPlayerProps) => {\r\n const { src, type, sources, poster, autoPlay, thumbnails, textTracks, plugins, onGetInstance, ...config } = props;\r\n\r\n // Default configs for optionals\r\n const useScreenshot = config.screenshot ?? false;\r\n const usePip = config.pip ?? true;\r\n const useSetting = config.setting ?? true;\r\n const useFullscreen = config.fullscreen ?? true;\r\n const useFullscreenWeb = config.fullscreenWeb ?? false;\r\n const useLock = config.lock ?? false;\r\n const useFastForward = config.fastForward ?? true;\r\n const useFlip = config.flip ?? true;\r\n const useAspectRatio = config.aspectRatio ?? true;\r\n const useHotKey = config.hotKey ?? true;\r\n const isBackdrop = config.backdrop ?? true;\r\n const useGestureSeek = config.gestureSeek ?? false;\r\n const useCenterControls = config.centerControls ?? true;\r\n const fetchTimeout = config.fetchTimeout ?? 30000;\r\n\r\n // Default AutoOrientation to true\r\n const useAutoOrientation = config.autoOrientation ?? true;\r\n\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const [player, setPlayer] = useState<StrataCore | null>(null);\r\n const [hasPlayed, setHasPlayed] = useState(false);\r\n const [playerHeight, setPlayerHeight] = useState(0);\r\n const [playerWidth, setPlayerWidth] = useState(0);\r\n const [isMobile, setIsMobile] = useState(false);\r\n\r\n // Resolve initial state based on props + defaults + localStorage BEFORE mounting\r\n const initialState = useMemo(() => getResolvedState(config), []);\r\n\r\n const state = useSyncExternalStore<PlayerState>(\r\n useCallback((cb) => player ? player.store.subscribe(cb) : () => { }, [player]),\r\n () => player ? player.store.get() : initialState,\r\n () => initialState\r\n );\r\n\r\n const accentContrast = useMemo(() => getContrastColor(state.themeColor), [state.themeColor]);\r\n\r\n const [settingsOpen, setSettingsOpen] = useState(false);\r\n const [subtitleMenuOpen, setSubtitleMenuOpen] = useState(false);\r\n // Active menu in Settings. Supports built-ins + dynamic 'custom-{index}' for user settings\r\n const [activeMenu, setActiveMenu] = useState<string>('main');\r\n\r\n // State for Custom Control Popovers (track ID of open control)\r\n const [activeControlId, setActiveControlId] = useState<string | null>(null);\r\n // Ref to track last active control for exit animations\r\n const lastActiveControlId = useRef<string | null>(null);\r\n if (activeControlId) lastActiveControlId.current = activeControlId;\r\n\r\n // Context Menu State\r\n const [contextMenu, setContextMenu] = useState<{ x: number, y: number, visible: boolean }>({ x: 0, y: 0, visible: false });\r\n const [showVideoInfo, setShowVideoInfo] = useState(false);\r\n\r\n // Transition States - Increased to 300ms to match CSS transition-duration\r\n const settingsTransition = useTransition(settingsOpen, 300);\r\n const subtitleTransition = useTransition(subtitleMenuOpen, 300);\r\n const controlTransition = useTransition(!!activeControlId, 300);\r\n\r\n // Helper to close all menus\r\n const closeAllMenus = useCallback(() => {\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n setSettingsOpen(false);\r\n setSubtitleMenuOpen(false);\r\n setActiveControlId(null);\r\n setContextMenu(prev => ({ ...prev, visible: false }));\r\n }\r\n }, [settingsOpen, subtitleMenuOpen, activeControlId, contextMenu.visible]);\r\n\r\n // Global listener to close popovers on outside click (e.g. layers, empty control bar space)\r\n useEffect(() => {\r\n const handleGlobalClick = (e: MouseEvent | TouchEvent) => {\r\n // Since Menu components stop propagation, any click reaching document is \"outside\"\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n closeAllMenus();\r\n }\r\n };\r\n\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n document.addEventListener('click', handleGlobalClick);\r\n document.addEventListener('touchstart', handleGlobalClick);\r\n }\r\n \r\n return () => {\r\n document.removeEventListener('click', handleGlobalClick);\r\n document.removeEventListener('touchstart', handleGlobalClick);\r\n };\r\n }, [settingsOpen, subtitleMenuOpen, activeControlId, contextMenu.visible, closeAllMenus]);\r\n\r\n // Seek & Scrubbing State\r\n const [isScrubbing, setIsScrubbing] = useState(false);\r\n const [scrubbingTime, setScrubbingTime] = useState(0);\r\n const [isVolumeScrubbing, setIsVolumeScrubbing] = useState(false);\r\n const [isVolumeHovered, setIsVolumeHovered] = useState(false);\r\n const [isVolumeLocked, setIsVolumeLocked] = useState(false); // For mobile/touch\r\n\r\n const [thumbnailCues, setThumbnailCues] = useState<ThumbnailCue[]>([]);\r\n const [hoverTime, setHoverTime] = useState<number | null>(null);\r\n const [hoverPos, setHoverPos] = useState<number>(0);\r\n const [currentThumbnail, setCurrentThumbnail] = useState<ThumbnailCue | null>(null);\r\n const [seekAnimation, setSeekAnimation] = useState<{ type: 'forward' | 'rewind', id: number } | null>(null);\r\n const [skipTrigger, setSkipTrigger] = useState<'forward' | 'rewind' | null>(null);\r\n\r\n // Fast Forward State\r\n const [isFastForwarding, setIsFastForwarding] = useState(false);\r\n const fastForwardTimerRef = useRef<any>(null);\r\n const originalRateRef = useRef<number>(1);\r\n\r\n // Gesture Refs\r\n const touchStartX = useRef<number | null>(null);\r\n const touchStartTime = useRef<number>(0);\r\n const isDraggingRef = useRef(false);\r\n\r\n const clickTimeoutRef = useRef<any>(null);\r\n const controlsTimeoutRef = useRef<any>(null);\r\n const progressBarRef = useRef<HTMLDivElement>(null);\r\n const volumeBarRef = useRef<HTMLDivElement>(null);\r\n const animationCleanupRef = useRef<any>(null);\r\n\r\n // Force re-attach player to container when WebFullscreen toggles (Portal)\r\n useLayoutEffect(() => {\r\n if (player && containerRef.current) {\r\n player.attach(containerRef.current);\r\n }\r\n }, [player, state.isWebFullscreen]);\r\n\r\n // Separate ResizeObserver to ensure it tracks the correct DOM node through portal transitions\r\n useLayoutEffect(() => {\r\n if (!containerRef.current) return;\r\n\r\n const updateDims = () => {\r\n if (containerRef.current) {\r\n setPlayerHeight(containerRef.current.clientHeight);\r\n setPlayerWidth(containerRef.current.clientWidth);\r\n }\r\n };\r\n\r\n // Initialize size immediately\r\n updateDims();\r\n\r\n const observer = new ResizeObserver((entries) => {\r\n for (const entry of entries) {\r\n setPlayerHeight(entry.contentRect.height);\r\n setPlayerWidth(entry.contentRect.width);\r\n }\r\n });\r\n observer.observe(containerRef.current);\r\n\r\n return () => {\r\n observer.disconnect();\r\n };\r\n }, [state.isWebFullscreen]); // Re-bind when portal state changes\r\n\r\n useEffect(() => {\r\n setIsMobile('ontouchstart' in window || navigator.maxTouchPoints > 0);\r\n\r\n if (!containerRef.current) return;\r\n // Pass poster into core config so metadata can use it\r\n const core = new StrataCore({ ...config, poster });\r\n\r\n // Register plugins\r\n if (plugins && plugins.length > 0) {\r\n plugins.forEach(p => core.use(p));\r\n }\r\n\r\n core.attach(containerRef.current);\r\n setPlayer(core);\r\n if (onGetInstance) onGetInstance(core);\r\n\r\n // Core Init complete\r\n\r\n return () => {\r\n core.destroy();\r\n setPlayer(null);\r\n };\r\n }, []); // Only runs once on mount to setup Core\r\n\r\n // Reactive Prop Updates\r\n useEffect(() => {\r\n if (!player) return;\r\n const updates: any = {};\r\n if (config.theme !== undefined && config.theme !== state.theme) updates.theme = config.theme;\r\n if (config.themeColor !== undefined && config.themeColor !== state.themeColor) updates.themeColor = config.themeColor;\r\n if (config.iconSize !== undefined && config.iconSize !== state.iconSize) updates.iconSize = config.iconSize;\r\n\r\n if (Object.keys(updates).length > 0) {\r\n player.setAppearance(updates);\r\n }\r\n\r\n if (config.volume !== undefined && Math.abs(config.volume - state.volume) > 0.01) player.setVolume(config.volume);\r\n if (config.muted !== undefined && config.muted !== state.isMuted) {\r\n if (config.muted) player.video.muted = true;\r\n else { player.video.muted = false; }\r\n }\r\n }, [player, config.theme, config.themeColor, config.iconSize, config.volume, config.muted]);\r\n\r\n useEffect(() => {\r\n if (!player) return;\r\n const tracks = textTracks || [];\r\n if (sources && sources.length > 0) {\r\n setHasPlayed(false);\r\n player.setSources(sources, tracks);\r\n } else if (src) {\r\n setHasPlayed(false);\r\n player.setSources([{ url: src, type: type || 'auto' }], tracks);\r\n }\r\n }, [src, type, sources, textTracks, player]);\r\n\r\n useEffect(() => {\r\n if (player && autoPlay) {\r\n player.play().catch(() => {\r\n // Autoplay blocked handling\r\n player.pause(); // Ensure UI state is consistent\r\n player.notify({ type: 'warning', message: 'Autoplay blocked by browser. Click play to start.', duration: 5000 });\r\n });\r\n }\r\n }, [player, autoPlay]);\r\n\r\n useEffect(() => {\r\n if (state.isPlaying && !hasPlayed) setHasPlayed(true);\r\n }, [state.isPlaying, hasPlayed]);\r\n\r\n useEffect(() => {\r\n if (thumbnails && player) {\r\n parseVTT(thumbnails, player.notify.bind(player), fetchTimeout).then(setCues => setThumbnailCues(setCues));\r\n } else setThumbnailCues([]);\r\n }, [thumbnails, player, fetchTimeout]);\r\n\r\n // Safety cleanup for seek animation if onAnimationEnd fails\r\n useEffect(() => {\r\n if (seekAnimation) {\r\n if (animationCleanupRef.current) clearTimeout(animationCleanupRef.current);\r\n animationCleanupRef.current = setTimeout(() => {\r\n setSeekAnimation(null);\r\n }, 600); // slightly longer than 500ms animation\r\n }\r\n return () => {\r\n if (animationCleanupRef.current) clearTimeout(animationCleanupRef.current);\r\n };\r\n }, [seekAnimation]);\r\n\r\n useEffect(() => {\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (!player || !useHotKey) return;\r\n if (document.activeElement?.tagName === 'INPUT') return;\r\n const key = e.key.toLowerCase();\r\n switch (key) {\r\n case ' ': case 'k': e.preventDefault(); player.togglePlay(); break;\r\n case 'arrowright': e.preventDefault(); player.skip(5); break;\r\n case 'arrowleft': e.preventDefault(); player.skip(-5); break;\r\n case 'arrowup': e.preventDefault(); player.setVolume(player.video.volume + 0.1); break;\r\n case 'arrowdown': e.preventDefault(); player.setVolume(player.video.volume - 0.1); break;\r\n case 'f': e.preventDefault(); player.toggleFullscreen(); break;\r\n case 'm': e.preventDefault(); player.toggleMute(); break;\r\n case 'escape':\r\n // Check store directly to avoid stale state in closure\r\n if (player.store.get().isWebFullscreen) {\r\n e.preventDefault();\r\n player.toggleWebFullscreen();\r\n }\r\n break;\r\n }\r\n };\r\n window.addEventListener('keydown', handleKeyDown);\r\n return () => window.removeEventListener('keydown', handleKeyDown);\r\n }, [player, useHotKey]);\r\n\r\n const handleMouseMove = () => {\r\n if (!player) return;\r\n // Even if locked, we want to wake up controls so the lock button becomes visible\r\n player.setControlsVisible(true);\r\n if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) return;\r\n controlsTimeoutRef.current = setTimeout(() => {\r\n if (!state.isPlaying || settingsOpen || subtitleMenuOpen || activeControlId) return;\r\n player.setControlsVisible(false);\r\n }, 2500);\r\n };\r\n\r\n useEffect(() => {\r\n if (!player) return;\r\n if (!settingsOpen && !subtitleMenuOpen && !activeControlId && state.isPlaying) handleMouseMove();\r\n else if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n player.setControlsVisible(true);\r\n if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);\r\n }\r\n }, [settingsOpen, subtitleMenuOpen, activeControlId, state.isPlaying, player]);\r\n\r\n // --- Fast Forward Logic ---\r\n const startFastForward = useCallback(() => {\r\n if (!useFastForward || !player || !state.isPlaying || state.isLocked) return;\r\n\r\n // Prevent gestures if menus are open\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n return;\r\n }\r\n\r\n originalRateRef.current = player.video.playbackRate;\r\n fastForwardTimerRef.current = setTimeout(() => {\r\n player.video.playbackRate = 2;\r\n setIsFastForwarding(true);\r\n }, 500); // 500ms delay for long press\r\n }, [useFastForward, player, state.isPlaying, state.isLocked, settingsOpen, subtitleMenuOpen, activeControlId]);\r\n\r\n const stopFastForward = useCallback(() => {\r\n if (fastForwardTimerRef.current) clearTimeout(fastForwardTimerRef.current);\r\n if (isFastForwarding && player) {\r\n player.video.playbackRate = originalRateRef.current; // Restore original rate\r\n setIsFastForwarding(false);\r\n }\r\n }, [isFastForwarding, player]);\r\n\r\n // --- Gesture Seek Logic ---\r\n const handleTouchStart = (e: React.TouchEvent) => {\r\n startFastForward();\r\n\r\n // Prevent gestures if menus are open\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n return;\r\n }\r\n\r\n if (useGestureSeek && !state.isLocked) {\r\n touchStartX.current = e.touches[0].clientX;\r\n touchStartTime.current = state.currentTime;\r\n isDraggingRef.current = false;\r\n }\r\n };\r\n\r\n const handleTouchMove = (e: React.TouchEvent) => {\r\n if (state.isLocked) return;\r\n\r\n // If we are moving and gesture seek is enabled\r\n if (useGestureSeek && touchStartX.current !== null) {\r\n const deltaX = e.touches[0].clientX - touchStartX.current;\r\n\r\n // Threshold to start dragging\r\n if (Math.abs(deltaX) > 10) {\r\n // If we start dragging, cancel any pending fast forward\r\n stopFastForward();\r\n\r\n isDraggingRef.current = true;\r\n setIsScrubbing(true);\r\n\r\n if (containerRef.current && state.duration) {\r\n const rect = containerRef.current.getBoundingClientRect();\r\n // Sensitivity: map drag distance to timeline progress directly relative to container width\r\n const deltaRatio = deltaX / rect.width;\r\n const newTime = Math.max(0, Math.min(state.duration, touchStartTime.current + (deltaRatio * state.duration)));\r\n setScrubbingTime(newTime);\r\n }\r\n }\r\n }\r\n };\r\n\r\n const handleTouchEnd = (e: React.TouchEvent) => {\r\n stopFastForward();\r\n\r\n if (useGestureSeek && isDraggingRef.current) {\r\n player?.seek(scrubbingTime);\r\n setIsScrubbing(false);\r\n isDraggingRef.current = false;\r\n touchStartX.current = null;\r\n // Prevent subsequent click event from toggling play\r\n return;\r\n }\r\n\r\n touchStartX.current = null;\r\n };\r\n\r\n const calculateTimeFromEvent = (e: React.MouseEvent | React.TouchEvent | MouseEvent | TouchEvent) => {\r\n if (!progressBarRef.current || !state.duration) return 0;\r\n const rect = progressBarRef.current.getBoundingClientRect();\r\n const clientX = 'touches' in e ? (e as TouchEvent).touches[0].clientX : (e as MouseEvent).clientX;\r\n const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\r\n return pct * state.duration;\r\n };\r\n\r\n const handleSeekStart = (e: React.MouseEvent | React.TouchEvent) => {\r\n e.stopPropagation();\r\n if (state.isLocked) return;\r\n\r\n // Ensure menus close when interacting with progress bar\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n }\r\n\r\n setIsScrubbing(true);\r\n setScrubbingTime(calculateTimeFromEvent(e));\r\n const handleMove = (moveEvent: MouseEvent | TouchEvent) => setScrubbingTime(calculateTimeFromEvent(moveEvent));\r\n const handleUp = (upEvent: MouseEvent | TouchEvent) => {\r\n player?.seek(calculateTimeFromEvent(upEvent));\r\n setIsScrubbing(false);\r\n document.removeEventListener('mousemove', handleMove); document.removeEventListener('touchmove', handleMove);\r\n document.removeEventListener('mouseup', handleUp); document.removeEventListener('touchend', handleUp);\r\n };\r\n document.addEventListener('mousemove', handleMove); document.addEventListener('touchmove', handleMove);\r\n document.addEventListener('mouseup', handleUp); document.addEventListener('touchend', handleUp);\r\n };\r\n\r\n const calculateVolumeFromEvent = (e: React.MouseEvent | React.TouchEvent | MouseEvent | TouchEvent) => {\r\n if (!volumeBarRef.current) return 0;\r\n const rect = volumeBarRef.current.getBoundingClientRect();\r\n const clientX = 'touches' in e ? (e as TouchEvent).touches[0].clientX : (e as MouseEvent).clientX;\r\n return Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\r\n };\r\n\r\n const handleVolumeStart = (e: React.MouseEvent | React.TouchEvent) => {\r\n e.stopPropagation();\r\n if (!player || state.isLocked) return;\r\n setIsVolumeScrubbing(true);\r\n player.setVolume(calculateVolumeFromEvent(e));\r\n const handleMove = (moveEvent: MouseEvent | TouchEvent) => player.setVolume(calculateVolumeFromEvent(moveEvent));\r\n const handleUp = () => {\r\n setIsVolumeScrubbing(false);\r\n document.removeEventListener('mousemove', handleMove); document.removeEventListener('touchmove', handleMove);\r\n document.removeEventListener('mouseup', handleUp); document.removeEventListener('touchend', handleUp);\r\n };\r\n document.addEventListener('mousemove', handleMove); document.addEventListener('touchmove', handleMove);\r\n document.addEventListener('mouseup', handleUp); document.addEventListener('touchend', handleUp);\r\n };\r\n\r\n const handleProgressMove = (e: React.MouseEvent<HTMLDivElement>) => {\r\n if (!state.duration || state.isLive) return;\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n const percent = (e.clientX - rect.left) / rect.width;\r\n const time = percent * state.duration;\r\n setHoverPos(percent * 100);\r\n setHoverTime(time);\r\n if (thumbnailCues.length > 0) setCurrentThumbnail(thumbnailCues.find(c => time >= c.start && time < c.end) || null);\r\n };\r\n\r\n const triggerSkip = (direction: 'forward' | 'rewind') => {\r\n if (!player || state.isLocked) return;\r\n player.skip(direction === 'forward' ? 10 : -10);\r\n setSkipTrigger(direction);\r\n setTimeout(() => setSkipTrigger(null), 300);\r\n };\r\n\r\n const handleContainerClick = (e: React.MouseEvent<HTMLDivElement>) => {\r\n if (!player) return;\r\n\r\n // If we just finished a drag gesture, ignore the click\r\n if (isDraggingRef.current) {\r\n isDraggingRef.current = false;\r\n return;\r\n }\r\n\r\n // Priority 1: Close menus on outside click.\r\n // If a menu is open, clicking the container should ONLY close the menu, NOT toggle play/pause.\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n closeAllMenus();\r\n return;\r\n }\r\n\r\n if (isVolumeLocked) setIsVolumeLocked(false);\r\n\r\n // Wake up controls so lock button is visible if locked\r\n player.setControlsVisible(true);\r\n if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);\r\n controlsTimeoutRef.current = setTimeout(() => {\r\n if (!state.isPlaying || settingsOpen || subtitleMenuOpen || activeControlId) return;\r\n player.setControlsVisible(false);\r\n }, 2500);\r\n\r\n // If locked, do nothing else (prevent play/pause, seek, double tap)\r\n if (state.isLocked) return;\r\n\r\n // Priority 2: Toggle Play/Pause or handle gestures\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n const x = e.clientX - rect.left;\r\n const width = rect.width;\r\n const now = Date.now();\r\n\r\n if (clickTimeoutRef.current) {\r\n clearTimeout(clickTimeoutRef.current);\r\n clickTimeoutRef.current = null;\r\n // Double Click Logic\r\n if (x < width * 0.35) { triggerSkip('rewind'); setSeekAnimation({ type: 'rewind', id: now }); }\r\n else if (x > width * 0.65) { triggerSkip('forward'); setSeekAnimation({ type: 'forward', id: now }); }\r\n else player.toggleFullscreen();\r\n } else {\r\n // Single Click Logic (Delayed to wait for potential double click)\r\n clickTimeoutRef.current = setTimeout(() => {\r\n player.togglePlay();\r\n clickTimeoutRef.current = null;\r\n }, 250);\r\n }\r\n };\r\n\r\n const handleContextMenu = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation(); // Prevent container click from firing\r\n if (state.isLocked) return;\r\n\r\n // Close other menus first\r\n closeAllMenus();\r\n\r\n const rect = containerRef.current?.getBoundingClientRect();\r\n if (!rect) return;\r\n\r\n // Small timeout to allow state updates (closeAllMenus) to propagate\r\n // before opening the new context menu\r\n requestAnimationFrame(() => {\r\n setContextMenu({\r\n visible: true,\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top\r\n });\r\n });\r\n };\r\n\r\n const handleVolumeIconClick = (e: React.MouseEvent | React.TouchEvent) => {\r\n e.stopPropagation();\r\n closeAllMenus(); // Close context menu if open\r\n\r\n if (isVolumeLocked) {\r\n setIsVolumeLocked(false);\r\n return;\r\n }\r\n\r\n if (isMobile) {\r\n setIsVolumeLocked(true);\r\n } else {\r\n // Desktop default behavior: Mute toggle\r\n player?.toggleMute();\r\n }\r\n };\r\n\r\n const VolIcon = state.isMuted || state.volume === 0 ? VolumeMuteIcon : state.volume < 0.5 ? VolumeLowIcon : VolumeHighIcon;\r\n\r\n const menuMaxHeight = Math.max(100, playerHeight - 120);\r\n\r\n const getIconClass = () => {\r\n switch (state.iconSize) {\r\n case 'small': return 'w-4 h-4';\r\n case 'large': return 'w-6 h-6';\r\n default: return 'w-5 h-5';\r\n }\r\n }\r\n const getButtonClass = () => {\r\n switch (state.iconSize) {\r\n case 'small': return 'p-2 min-w-[32px] min-h-[32px]';\r\n case 'large': return 'p-3 min-w-[44px] min-h-[44px]'; // Larger touch targets\r\n default: return 'p-2.5 min-w-[36px] min-h-[36px]';\r\n }\r\n }\r\n const iconClass = getIconClass();\r\n const btnClass = getButtonClass();\r\n\r\n const getCenterSizes = () => {\r\n switch (state.iconSize) {\r\n case 'small':\r\n return {\r\n playBtn: 'w-14 h-14',\r\n playIcon: 'w-6 h-6',\r\n skipBtn: 'w-10 h-10',\r\n skipIcon: 'w-5 h-5'\r\n };\r\n case 'large':\r\n return {\r\n playBtn: 'w-24 h-24',\r\n playIcon: 'w-12 h-12',\r\n skipBtn: 'w-16 h-16',\r\n skipIcon: 'w-8 h-8'\r\n };\r\n default: // medium\r\n return {\r\n playBtn: 'w-20 h-20',\r\n playIcon: 'w-9 h-9',\r\n skipBtn: 'w-12 h-12',\r\n skipIcon: 'w-6 h-6'\r\n };\r\n }\r\n }\r\n const center = getCenterSizes();\r\n\r\n // Bottom Controls Visibility: Show if paused, or actively showing controls, or menus open. \r\n // HIDDEN IF LOCKED.\r\n // Use state.controlsVisible from Core to sync with external listeners (like ArtPlayer consumers)\r\n const isControlsVisible = !state.isLocked && (state.controlsVisible || !state.isPlaying || settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible);\r\n const isVolumeVisible = isVolumeHovered || isVolumeScrubbing || isVolumeLocked;\r\n\r\n const backdropClass = isBackdrop ? 'backdrop-blur-xl bg-black/80' : 'bg-black/95';\r\n\r\n // --- Dynamic Controls Rendering ---\r\n const controls: ControlItem[] = useMemo(() => {\r\n const items: ControlItem[] = [\r\n { id: 'play', position: 'left', index: 10, isBuiltIn: true },\r\n { id: 'volume', position: 'left', index: 20, isBuiltIn: true },\r\n { id: 'time', position: 'left', index: 30, isBuiltIn: true },\r\n { id: 'subtitle', position: 'right', index: 80, isBuiltIn: true },\r\n { id: 'screenshot', position: 'right', index: 85, isBuiltIn: true },\r\n { id: 'pip', position: 'right', index: 90, isBuiltIn: true },\r\n { id: 'download', position: 'right', index: 95, isBuiltIn: true },\r\n { id: 'settings', position: 'right', index: 100, isBuiltIn: true },\r\n { id: 'fullscreenWeb', position: 'right', index: 110, isBuiltIn: true },\r\n { id: 'fullscreen', position: 'right', index: 120, isBuiltIn: true },\r\n ];\r\n\r\n if (config.controls) {\r\n // Merge user controls\r\n config.controls.forEach(c => {\r\n const existing = items.find(i => i.id === c.id);\r\n if (existing) {\r\n Object.assign(existing, c); // Override\r\n } else {\r\n items.push(c);\r\n }\r\n });\r\n }\r\n\r\n // Detect HLS source for Download Menu Options\r\n const currentSource = state.sources[state.currentSourceIndex] || { url: src || '', type: type || 'auto' };\r\n const isHls = currentSource.type === 'hls' || currentSource.url.includes('.m3u8');\r\n\r\n // Apply Download Menu logic if HLS\r\n const downloadControl = items.find(i => i.id === 'download');\r\n if (downloadControl) {\r\n if (isHls) {\r\n downloadControl.children = [\r\n { html: 'Download Format', isLabel: true },\r\n { \r\n html: 'MPEG-TS', \r\n value: 'Original Stream', \r\n icon: <FileCheckIcon className=\"w-3.5 h-3.5\" />,\r\n onClick: () => player?.download({ format: 'ts' }) \r\n },\r\n { \r\n html: 'MP4', \r\n value: 'Converted', \r\n icon: <CustomizeIcon className=\"w-3.5 h-3.5\" />,\r\n onClick: () => player?.download({ format: 'mp4' }) \r\n }\r\n ];\r\n downloadControl.onClick = undefined; // Ensure toggle logic works by removing click handler\r\n } else {\r\n downloadControl.children = undefined;\r\n downloadControl.onClick = (p) => p.download();\r\n }\r\n }\r\n\r\n // Filter based on config toggles\r\n return items.filter(c => {\r\n if (c.id === 'screenshot' && !useScreenshot) return false;\r\n if (c.id === 'pip' && !usePip) return false;\r\n if (c.id === 'settings' && !useSetting) return false;\r\n if (c.id === 'fullscreen' && !useFullscreen) return false;\r\n if (c.id === 'fullscreenWeb' && !useFullscreenWeb) return false;\r\n return true;\r\n }).sort((a, b) => a.index - b.index);\r\n }, [config.controls, useScreenshot, usePip, useSetting, useFullscreen, useFullscreenWeb, state.currentSourceIndex, state.sources, src, type]);\r\n\r\n const renderControl = (item: ControlItem) => {\r\n if (!item.isBuiltIn) {\r\n // Render custom user control\r\n const controlId = item.id || `ctrl-${item.index}`;\r\n const isMenuOpen = activeControlId === controlId;\r\n\r\n // Allow rendering if it's the active one OR if it was the last active one during the unmount phase\r\n const shouldRenderMenu = isMenuOpen || (controlTransition.isMounted && lastActiveControlId.current === controlId);\r\n\r\n return (\r\n <div key={item.index} className=\"relative\">\r\n <button\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n if (item.children) {\r\n // Toggle logic: If click same button, toggle off. If click diff button, close old, open new.\r\n const wasOpen = isMenuOpen;\r\n closeAllMenus();\r\n if (!wasOpen) setActiveControlId(controlId);\r\n } else {\r\n closeAllMenus(); // Close context menu\r\n if (item.click) item.click(player!);\r\n else if (item.onClick) item.onClick(player!);\r\n }\r\n }}\r\n className={`strata-control-btn transition-colors focus:outline-none flex items-center justify-center ${btnClass} ${isMenuOpen ? 'text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'} ${item.className || ''}`}\r\n style={{ borderRadius: 'var(--radius)', ...item.style }}\r\n title={item.tooltip}\r\n >\r\n <HtmlOrNode content={item.html || ''} />\r\n </button>\r\n {/* Use MenuExplorer for nested controls */}\r\n {item.children && shouldRenderMenu && (\r\n <MenuExplorer\r\n items={item.children}\r\n onClose={closeAllMenus}\r\n maxHeight={menuMaxHeight}\r\n className={`strata-backdrop ${backdropClass} ${controlTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}\r\n />\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n // Built-ins\r\n switch (item.id) {\r\n case 'play':\r\n return (\r\n <button key=\"play\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.togglePlay(); }} className={`strata-control-btn text-zinc-300 hover:text-white transition-colors hover:bg-white/10 focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}>\r\n {state.isPlaying ? <PauseIcon className={`${iconClass} fill-current`} /> : <PlayIcon className={`${iconClass} fill-current`} />}\r\n </button>\r\n );\r\n case 'volume':\r\n return (\r\n <div key=\"volume\" className=\"flex items-center gap-2 group/vol relative\"\r\n onMouseEnter={() => { if (window.matchMedia('(hover: hover)').matches) setIsVolumeHovered(true); }}\r\n onMouseLeave={() => { if (window.matchMedia('(hover: hover)').matches) setIsVolumeHovered(false); }}\r\n >\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={handleVolumeIconClick} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}>\r\n <VolIcon className={iconClass} />\r\n </button>\r\n <div className={`relative h-8 flex items-center transition-all duration-300 ease-out overflow-hidden ${isVolumeVisible ? 'w-28 opacity-100 ml-1' : 'w-0 opacity-0'}`}>\r\n <div ref={volumeBarRef} className=\"relative w-full h-full flex items-center cursor-pointer px-2\" onMouseDown={handleVolumeStart} onTouchStart={handleVolumeStart}>\r\n <div className=\"w-full h-1 bg-white/20 overflow-hidden\" style={{ borderRadius: 'var(--radius-full)' }}>\r\n <div className=\"h-full bg-white\" style={{ width: `${(state.isMuted ? 0 : state.volume) * 100}%`, borderRadius: 'var(--radius-full)' }}></div>\r\n </div>\r\n <div className=\"absolute h-3 w-3 bg-white shadow-md top-1/2 -translate-y-1/2 pointer-events-none\" style={{ left: `calc(${(state.isMuted ? 0 : state.volume) * 100}% * 0.85 + 4px)`, borderRadius: 'var(--radius-full)' }} />\r\n </div>\r\n </div>\r\n {isVolumeVisible && <div className=\"strata-tooltip absolute bottom-full mb-2 px-1.5 py-0.5 rounded text-[10px] font-bold font-mono shadow-lg pointer-events-none whitespace-nowrap z-50 transform -translate-x-1/2\" style={{ left: `calc(52px + ${(state.isMuted ? 0 : state.volume) * 80}px)` }}>{state.isMuted ? '0%' : `${Math.round(state.volume * 100)}%`}</div>}\r\n </div>\r\n );\r\n case 'time':\r\n return config.isLive ? (\r\n <div key=\"live\" className=\"flex items-center gap-2 px-2 py-0.5 rounded-md border border-white/10\" style={{ backgroundColor: `${state.themeColor}1a`, borderColor: `${state.themeColor}33` }}>\r\n <div className=\"w-2 h-2 rounded-full animate-pulse\" style={{ backgroundColor: state.themeColor }} />\r\n <span className=\"text-[10px] font-bold tracking-wider\" style={{ color: state.themeColor }}>LIVE</span>\r\n </div>\r\n ) : (\r\n <div key=\"time\" className=\"text-xs font-medium text-zinc-400 font-mono select-none hidden sm:block tabular-nums\">{formatTime(isScrubbing ? scrubbingTime : state.currentTime)} <span className=\"text-zinc-600\">/</span> {formatTime(state.duration)}</div>\r\n );\r\n case 'subtitle':\r\n return (\r\n <div key=\"subtitle\" className=\"relative\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); const wasOpen = subtitleMenuOpen; closeAllMenus(); if (!wasOpen) setSubtitleMenuOpen(true); }} className={`strata-control-btn transition-colors focus:outline-none ${btnClass} ${subtitleMenuOpen ? 'text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'}`} style={{ borderRadius: 'var(--radius)' }}><SubtitleIcon className={iconClass} /></button>\r\n {subtitleTransition.isMounted && (\r\n <SubtitleMenu\r\n tracks={state.subtitleTracks} current={state.currentSubtitle} onSelect={(idx: number) => player?.setSubtitle(idx)}\r\n onUpload={(file: File) => player?.addTextTrack(file, file.name)} onClose={closeAllMenus}\r\n settings={state.subtitleSettings} onSettingsChange={(s: Partial<SubtitleSettings>) => player?.updateSubtitleSettings(s)}\r\n onReset={() => player?.resetSubtitleSettings()} offset={state.subtitleOffset} onOffsetChange={(val: number) => player?.setSubtitleOffset(val)}\r\n maxHeight={menuMaxHeight} animationClass={`strata-backdrop ${backdropClass} ${subtitleTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}\r\n />\r\n )}\r\n </div>\r\n );\r\n case 'screenshot': return <button key=\"ss\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.screenshot(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 transition-colors hidden sm:block focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }} title=\"Screenshot\"><CameraIcon className={iconClass} /></button>;\r\n case 'pip': return <button key=\"pip\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.togglePip(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 transition-colors hidden sm:block focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}><PipIcon className={iconClass} /></button>;\r\n \r\n // Modified Download Handler with Menu Support via Built-in Extension\r\n case 'download': \r\n if (item.children) {\r\n const isMenuOpen = activeControlId === 'download-menu';\r\n const shouldRenderMenu = isMenuOpen || (controlTransition.isMounted && lastActiveControlId.current === 'download-menu');\r\n return (\r\n <div key=\"dl\" className=\"relative\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { \r\n e.stopPropagation(); \r\n const wasOpen = isMenuOpen;\r\n closeAllMenus(); \r\n if (!wasOpen) setActiveControlId('download-menu');\r\n }} className={`strata-control-btn transition-colors hidden sm:block focus:outline-none ${btnClass} ${isMenuOpen ? 'text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'}`} style={{ borderRadius: 'var(--radius)' }}><DownloadIcon className={iconClass} /></button>\r\n \r\n {shouldRenderMenu && (\r\n <MenuExplorer\r\n items={item.children}\r\n onClose={closeAllMenus}\r\n maxHeight={menuMaxHeight}\r\n className={`strata-backdrop ${backdropClass} ${controlTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}\r\n />\r\n )}\r\n </div>\r\n );\r\n }\r\n return <button key=\"dl\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.download(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 transition-colors hidden sm:block focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}><DownloadIcon className={iconClass} /></button>;\r\n \r\n case 'fullscreen': return <button key=\"fs\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.toggleFullscreen(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 rounded-lg transition-transform focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}>{(state.isFullscreen || state.isWebFullscreen) ? <MinimizeIcon className={iconClass} /> : <MaximizeIcon className={iconClass} />}</button>;\r\n case 'fullscreenWeb': return <button key=\"fsw\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.toggleWebFullscreen(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 hidden sm:block focus:outline-none ${btnClass} ${state.isWebFullscreen ? 'text-[var(--accent)]' : ''}`} style={{ borderRadius: 'var(--radius)' }} title=\"Web Fullscreen\"><WebFullscreenIcon className={iconClass} /></button>;\r\n case 'settings':\r\n return (\r\n <div key=\"settings\" className=\"relative\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); const wasOpen = settingsOpen; closeAllMenus(); if (!wasOpen) { setSettingsOpen(true); setActiveMenu('main'); } }} className={`strata-control-btn transition-all duration-300 focus:outline-none ${btnClass} ${settingsOpen ? 'rotate-90 text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'}`} style={{ borderRadius: 'var(--radius)' }}><SettingsIcon className={iconClass} /></button>\r\n {settingsTransition.isMounted && (<Menu onClose={closeAllMenus} align=\"right\" maxHeight={menuMaxHeight} className={`strata-backdrop ${backdropClass} ${settingsTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}><div className=\"w-full\">\r\n {activeMenu === 'main' && (\r\n <div className=\"animate-in slide-in-from-left-4 fade-in duration-200\">\r\n <div className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md\" style={{ borderRadius: 'var(--radius)' }}><span>Settings</span></div>\r\n\r\n {/* Source - Top Priority */}\r\n {state.sources.length > 1 && (\r\n <>\r\n <MenuItem label=\"Source\" icon={<ServerIcon className=\"w-4 h-4\" />} value={state.sources[state.currentSourceIndex]?.name || `Source ${state.currentSourceIndex + 1}`} onClick={() => setActiveMenu('sources')} hasSubmenu />\r\n <MenuDivider />\r\n </>\r\n )}\r\n\r\n {/* Playback Configuration */}\r\n <MenuItem label=\"Quality\" icon={<QualityIcon className=\"w-4 h-4\" />} value={state.currentQuality === -1 ? 'Auto' : `${state.qualityLevels[state.currentQuality]?.height}p`} onClick={() => setActiveMenu('quality')} hasSubmenu />\r\n <MenuItem label=\"Speed\" icon={<GaugeIcon className=\"w-4 h-4\" />} value={`${state.playbackRate}x`} onClick={() => setActiveMenu('speed')} hasSubmenu />\r\n <MenuItem label=\"Audio\" icon={<MusicIcon className=\"w-4 h-4\" />} value={state.audioTracks[state.currentAudioTrack]?.label || 'Default'} onClick={() => setActiveMenu('audio')} hasSubmenu />\r\n\r\n <MenuDivider />\r\n\r\n {/* Visual Adjustments */}\r\n {useFlip && <MenuItem label=\"Flip\" icon={<VideoFlipIcon className=\"w-4 h-4\" />} value={state.flipState.horizontal ? 'H' : state.flipState.vertical ? 'V' : 'Normal'} onClick={() => setActiveMenu('flip')} hasSubmenu />}\r\n {useAspectRatio && <MenuItem label=\"Aspect Ratio\" icon={<CropIcon className=\"w-4 h-4\" />} value={state.aspectRatio} onClick={() => setActiveMenu('ratio')} hasSubmenu />}\r\n\r\n {/* Audio Tools */}\r\n <MenuItem label=\"Audio Boost\" icon={<SpeakerIcon className=\"w-4 h-4\" />} value={state.audioGain > 1 ? `${state.audioGain}x` : 'Off'} onClick={() => setActiveMenu('boost')} hasSubmenu />\r\n\r\n <MenuDivider />\r\n\r\n {/* Network & Social */}\r\n <MenuItem label=\"Watch Party\" icon={<UsersIcon className=\"w-4 h-4\" />} onClick={() => setActiveMenu('party')} hasSubmenu />\r\n <MenuItem label=\"Cast to Device\" icon={<CastIcon className=\"w-4 h-4\" />} onClick={() => { player?.requestCast(); closeAllMenus(); }} />\r\n\r\n {/* Custom User Settings (Nested Support Added Here) */}\r\n {config.settings && config.settings.length > 0 && <MenuDivider />}\r\n {config.settings?.map((s, i) => (\r\n s.switch !== undefined ? (\r\n <div key={`cust-${i}`} className=\"px-1\">\r\n <Toggle\r\n label={s.html}\r\n icon={s.icon}\r\n checked={s.switch}\r\n tooltip={s.tooltip}\r\n onChange={(val: boolean) => { if (s.onSwitch) s.onSwitch(s, val); }}\r\n />\r\n </div>\r\n ) : (\r\n <MenuItem\r\n key={`cust-${i}`}\r\n label={s.html}\r\n icon={s.icon}\r\n value={s.currentLabel || s.value}\r\n hasSubmenu={!!s.children}\r\n onClick={() => {\r\n if (s.children) {\r\n setActiveMenu(`custom-${i}`);\r\n } else {\r\n if (s.click) s.click(s);\r\n else if (s.onClick) s.onClick(s);\r\n closeAllMenus();\r\n }\r\n }}\r\n />\r\n )\r\n ))}\r\n\r\n <MenuDivider />\r\n\r\n {/* Appearance - Bottom */}\r\n <MenuItem label=\"Appearance\" icon={<PaletteIcon className=\"w-4 h-4\" />} onClick={() => setActiveMenu('appearance')} hasSubmenu />\r\n </div>\r\n )}\r\n\r\n {/* Render Nested Custom Setting Menu if active */}\r\n {activeMenu.startsWith('custom-') && (() => {\r\n const idx = parseInt(activeMenu.split('-')[1]);\r\n const item = config.settings?.[idx];\r\n if (!item || !item.children) return null;\r\n return (\r\n <div className=\"animate-in slide-in-from-right-4 fade-in duration-200\">\r\n <MenuHeader label={item.html || 'Menu'} onBack={() => setActiveMenu('main')} />\r\n {item.children.map((child, k) => (\r\n <React.Fragment key={k}>\r\n {child.separator && <MenuDivider />}\r\n {child.switch !== undefined && (\r\n <div className=\"px-1\"><Toggle label={child.html} checked={child.switch} onChange={(v: boolean) => child.onSwitch && child.onSwitch(child, v)} /></div>\r\n )}\r\n {!child.separator && child.switch === undefined && (\r\n <MenuItem\r\n label={child.html}\r\n icon={child.icon}\r\n value={child.value}\r\n active={child.active}\r\n onClick={() => {\r\n if (child.onClick) child.onClick(child);\r\n else if (child.click) child.click(child);\r\n closeAllMenus();\r\n }}\r\n />\r\n )}\r\n </React.Fragment>\r\n ))}\r\n </div>\r\n );\r\n })()}\r\n\r\n {['speed', 'quality', 'audio', 'boost', 'party', 'appearance', 'sources', 'flip', 'ratio'].includes(activeMenu) && (\r\n <div className=\"animate-in slide-in-from-right-4 fade-in duration-200\">\r\n {activeMenu === 'sources' && (\r\n <>\r\n <MenuHeader label=\"Select Source\" onBack={() => setActiveMenu('main')} />\r\n {state.sources.map((src, i) => {\r\n const status = state.sourceStatuses[i];\r\n const statusIcon = status === 'success'\r\n ? <WifiIcon className=\"w-3.5 h-3.5 text-emerald-500\" />\r\n : status === 'error'\r\n ? <AlertCircleIcon className=\"w-3.5 h-3.5 text-red-500\" />\r\n : null;\r\n return (\r\n <MenuItem\r\n key={i}\r\n label={src.name || `Source ${i + 1}`}\r\n value={src.type}\r\n active={state.currentSourceIndex === i}\r\n rightIcon={statusIcon}\r\n onClick={() => player?.switchSource(i)}\r\n />\r\n );\r\n })}\r\n </>\r\n )}\r\n {activeMenu === 'speed' && (<><MenuHeader label=\"Speed\" onBack={() => setActiveMenu('main')} />{[0.5, 1, 1.5, 2].map(rate => (<MenuItem key={rate} label={`${rate}x`} active={state.playbackRate === rate} onClick={() => player!.video.playbackRate = rate} />))}</>)}\r\n {activeMenu === 'quality' && (<><MenuHeader label=\"Quality\" onBack={() => setActiveMenu('main')} /><MenuItem label=\"Auto\" active={state.currentQuality === -1} onClick={() => player?.setQuality(-1)} />{state.qualityLevels.map((lvl) => (<MenuItem key={lvl.index} label={`${lvl.height}p`} value={`${Math.round(lvl.bitrate / 1000)}k`} active={state.currentQuality === lvl.index} onClick={() => player?.setQuality(lvl.index)} />))}</>)}\r\n {activeMenu === 'audio' && (<><MenuHeader label=\"Audio Track\" onBack={() => setActiveMenu('main')} />{state.audioTracks.length === 0 && <div className=\"px-4 py-3 text-zinc-500 text-xs text-center\">No tracks available</div>}{state.audioTracks.map((track) => (<MenuItem key={track.index} label={track.label} value={track.language} active={state.currentAudioTrack === track.index} onClick={() => player?.setAudioTrack(track.index)} />))}</>)}\r\n {activeMenu === 'boost' && (<><MenuHeader label=\"Audio Boost\" onBack={() => setActiveMenu('main')} />{[1, 1.5, 2, 3].map(gain => (<MenuItem key={gain} label={gain === 1 ? 'Off' : `${gain}x`} active={state.audioGain === gain} onClick={() => player?.setAudioGain(gain)} />))}</>)}\r\n {activeMenu === 'flip' && (\r\n <>\r\n <MenuHeader label=\"Video Flip\" onBack={() => setActiveMenu('main')} />\r\n <div className=\"p-2 space-y-1\">\r\n <Toggle label=\"Horizontal Flip\" checked={state.flipState.horizontal} onChange={() => player?.setFlip('horizontal')} />\r\n <Toggle label=\"Vertical Flip\" checked={state.flipState.vertical} onChange={() => player?.setFlip('vertical')} />\r\n </div>\r\n </>\r\n )}\r\n {activeMenu === 'ratio' && (\r\n <>\r\n <MenuHeader label=\"Aspect Ratio\" onBack={() => setActiveMenu('main')} />\r\n {['default', '16:9', '4:3'].map(r => (\r\n <MenuItem key={r} label={r === 'default' ? 'Default' : r} active={state.aspectRatio === r} onClick={() => player?.setAspectRatio(r)} />\r\n ))}\r\n </>\r\n )}\r\n {activeMenu === 'party' && (<><MenuHeader label=\"Watch Party\" onBack={() => setActiveMenu('main')} /><div className=\"p-4 space-y-3\"><p className=\"text-xs text-zinc-400 leading-relaxed\">Create a synchronized room on WatchParty.me to watch together.</p><a href={`https://www.watchparty.me/create?video=${encodeURIComponent(state.sources[state.currentSourceIndex]?.url || src || '')}`} target=\"_blank\" rel=\"noopener noreferrer\" className=\"flex items-center justify-center w-full py-2.5 bg-[var(--accent)] hover:opacity-90 text-white font-medium transition-opacity text-xs\" style={{ borderRadius: 'var(--radius)' }}>Create Room</a></div></>)}\r\n {activeMenu === 'appearance' && (\r\n <>\r\n <MenuHeader label=\"Appearance\" onBack={() => setActiveMenu('main')} />\r\n <div className=\"pb-1\">\r\n <SettingsGroup title=\"Theme\">\r\n <div className=\"grid grid-cols-2 gap-2 px-3\">\r\n {THEMES.map(theme => (\r\n <button key={theme.value} onClick={() => player?.setAppearance({ theme: theme.value, themeColor: theme.color })} className={`py-2 text-xs font-bold uppercase tracking-wide transition-colors border-[length:var(--border-width)] border-white/10 ${state.theme === theme.value ? 'bg-[var(--accent)] text-white' : 'bg-white/5 text-zinc-400 hover:text-white'}`} style={{ borderRadius: 'var(--radius)' }}>{theme.label}</button>\r\n ))}\r\n </div>\r\n </SettingsGroup>\r\n <SettingsGroup title=\"Icon Size\">\r\n <div className=\"grid grid-cols-3 gap-1 px-3\">\r\n {(['small', 'medium', 'large'] as const).map(s => (\r\n <button key={s} onClick={() => player?.setAppearance({ iconSize: s })} className={`py-1.5 text-xs font-medium transition-colors ${state.iconSize === s ? 'bg-white text-black' : 'bg-white/5 text-zinc-400 hover:text-zinc-200'}`} style={{ borderRadius: 'var(--radius)' }}>{s.charAt(0).toUpperCase() + s.slice(1)}</button>\r\n ))}\r\n </div>\r\n </SettingsGroup>\r\n <SettingsGroup title=\"Theme Color\">\r\n <div className=\"grid grid-cols-6 gap-2 px-3\">\r\n {THEME_COLORS.map(c => (\r\n <button key={c.value} title={c.label} onClick={() => player?.setAppearance({ themeColor: c.value })} className={`w-6 h-6 transition-transform hover:scale-110 ${state.themeColor === c.value ? 'ring-2 ring-white scale-110' : 'ring-1 ring-white/10'}`} style={{ backgroundColor: c.value, borderRadius: 'var(--radius-full)' }}>{state.themeColor === c.value && <CheckIcon className=\"w-3 h-3 text-white mx-auto stroke-[3]\" />}</button>\r\n ))}\r\n </div>\r\n <div className=\"px-3 pt-4\">\r\n <div className=\"flex items-center gap-3 bg-white/5 p-2 hover:bg-white/10 transition-colors group\" style={{ borderRadius: 'var(--radius)' }}>\r\n <div className=\"relative w-6 h-6 overflow-hidden ring-1 ring-white/20\" style={{ borderRadius: 'var(--radius-full)' }}>\r\n <input type=\"color\" value={state.themeColor} onChange={(e) => player?.setAppearance({ themeColor: e.target.value })} className=\"absolute inset-[-4px] w-[150%] h-[150%] cursor-pointer p-0 border-0\" />\r\n </div>\r\n <span className=\"text-xs text-zinc-400 font-medium group-hover:text-zinc-200\">Custom Color</span>\r\n <span className=\"text-[10px] font-mono text-zinc-500 ml-auto uppercase\">{state.themeColor}</span>\r\n </div>\r\n </div>\r\n </SettingsGroup>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div></Menu>)}\r\n </div>\r\n );\r\n default: return null;\r\n }\r\n };\r\n\r\n // --- Dynamic Context Menu ---\r\n const contextMenuItems: ContextMenuItem[] = useMemo(() => {\r\n const items: ContextMenuItem[] = [\r\n // Loop (Playback Group)\r\n { html: 'Playback', isLabel: true },\r\n {\r\n html: 'Loop',\r\n checked: state.isLooping,\r\n onClick: () => player?.toggleLoop()\r\n },\r\n { separator: true },\r\n\r\n // Flip (Transform Group)\r\n { html: 'Transform', isLabel: true },\r\n { html: 'Flip Horizontal', onClick: () => player?.setFlip('horizontal') },\r\n { html: 'Flip Vertical', onClick: () => player?.setFlip('vertical') },\r\n { separator: true },\r\n\r\n // Aspect Ratio Group\r\n { html: 'Aspect Ratio', isLabel: true },\r\n { html: 'Default', checked: state.aspectRatio === 'default', onClick: () => player?.setAspectRatio('default') },\r\n { html: '16:9', checked: state.aspectRatio === '16:9', onClick: () => player?.setAspectRatio('16:9') },\r\n { html: '4:3', checked: state.aspectRatio === '4:3', onClick: () => player?.setAspectRatio('4:3') },\r\n { separator: true },\r\n\r\n // Stats\r\n {\r\n html: 'Video Info',\r\n icon: <InfoIcon className=\"w-3.5 h-3.5\" />,\r\n onClick: () => setShowVideoInfo(true)\r\n },\r\n { separator: true }\r\n ];\r\n\r\n if (config.contextmenu) {\r\n items.push(...config.contextmenu);\r\n }\r\n\r\n // Branding\r\n items.push({\r\n html: <span className=\"text-zinc-500 text-xs font-semibold tracking-wide\">StrataPlayer</span>,\r\n disabled: true\r\n });\r\n\r\n // Always append Close at the very end\r\n items.push({\r\n html: 'Close',\r\n onClick: (close) => close(), // Wrapper handles close\r\n icon: <div className=\"text-red-400\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M18 6 6 18\" /><path d=\"m6 6 12 12\" /></svg></div>\r\n });\r\n\r\n return items;\r\n }, [config.contextmenu, state.aspectRatio, state.isLooping, player]);\r\n\r\n const isWebFs = state.isWebFullscreen;\r\n\r\n const playerContent = (\r\n <div\r\n id={config.id}\r\n ref={containerRef}\r\n className={`group bg-black overflow-hidden select-none font-[family-name:var(--font-main)] outline-none text-zinc-100 strata-player-reset flex items-center justify-center ${isWebFs ? 'fixed inset-0 z-[2147483647] w-screen h-screen rounded-none' : 'relative w-full h-full rounded-[var(--radius)]'} ${config.container || ''}`}\r\n // touch-action: manipulation improves tap response\r\n style={{ touchAction: 'manipulation', '--accent': state.themeColor, '--accent-contrast': accentContrast } as React.CSSProperties}\r\n onMouseMove={handleMouseMove}\r\n onMouseLeave={() => { if (state.isPlaying && !settingsOpen && !subtitleMenuOpen && !activeControlId && player) player.setControlsVisible(false); }}\r\n\r\n // Mouse Events\r\n onMouseDown={startFastForward}\r\n onMouseUp={stopFastForward}\r\n\r\n // Touch Events (Unified Gesture Logic)\r\n onTouchStart={handleTouchStart}\r\n onTouchMove={handleTouchMove}\r\n onTouchEnd={handleTouchEnd}\r\n\r\n onContextMenu={handleContextMenu}\r\n tabIndex={0}\r\n role=\"region\"\r\n aria-label=\"Video Player\"\r\n data-theme={state.theme}\r\n >\r\n {/* Same styles block as before */}\r\n <style>{`\r\n [data-theme=\"default\"] {\r\n --radius: 0.75rem;\r\n --radius-lg: 0.75rem;\r\n --radius-sm: 0.375rem;\r\n --radius-full: 9999px;\r\n --font-main: \"Inter\", sans-serif;\r\n --border-width: 0px;\r\n --bg-panel: rgba(9, 9, 11, 0.95);\r\n --tooltip-bg: #ffffff;\r\n --tooltip-text: #000000;\r\n --tooltip-border: 0px solid transparent;\r\n }\r\n [data-theme=\"pixel\"] {\r\n --radius: 0px;\r\n --radius-lg: 0px;\r\n --radius-sm: 0px;\r\n --radius-full: 0px;\r\n --font-main: \"Press Start 2P\", cursive;\r\n --border-width: 2px;\r\n --bg-panel: #000000;\r\n --tooltip-bg: #000000;\r\n --tooltip-text: #ffffff;\r\n --tooltip-border: 2px solid #ffffff;\r\n image-rendering: pixelated;\r\n }\r\n [data-theme=\"game\"] {\r\n --radius: 4px;\r\n --radius-lg: 6px;\r\n --radius-sm: 2px;\r\n --radius-full: 4px;\r\n --font-main: \"Cinzel\", serif;\r\n --border-width: 1px;\r\n --bg-panel: #0a0a0a;\r\n --tooltip-bg: #1a1a1a;\r\n --tooltip-text: #ffffff;\r\n --tooltip-border: 1px solid var(--accent);\r\n }\r\n [data-theme=\"hacker\"] {\r\n --radius: 0px;\r\n --radius-lg: 0px;\r\n --radius-sm: 0px;\r\n --radius-full: 0px;\r\n --font-main: \"JetBrains Mono\", monospace;\r\n --border-width: 1px;\r\n --bg-panel: #000000;\r\n --tooltip-bg: #000000;\r\n --tooltip-text: var(--accent);\r\n --tooltip-border: 1px solid var(--accent);\r\n text-shadow: 0 0 5px var(--accent);\r\n }\r\n \r\n [data-theme=\"pixel\"] .strata-control-btn {\r\n border: 2px solid white;\r\n background: black;\r\n }\r\n [data-theme=\"pixel\"] .strata-control-btn:hover {\r\n background: white;\r\n color: black;\r\n }\r\n [data-theme=\"pixel\"] .strata-range-input::-webkit-slider-thumb {\r\n border-radius: 0 !important;\r\n height: 16px !important;\r\n width: 16px !important;\r\n box-shadow: none !important;\r\n }\r\n \r\n [data-theme=\"hacker\"] .strata-scanlines {\r\n background: linear-gradient(\r\n to bottom,\r\n rgba(255,255,255,0),\r\n rgba(255,255,255,0) 50%,\r\n rgba(0,0,0,0.2) 50%,\r\n rgba(0,0,0,0.2)\r\n );\r\n background-size: 100% 4px;\r\n position: absolute;\r\n inset: 0;\r\n pointer-events: none;\r\n z-index: 40;\r\n }\r\n\r\n .strata-tooltip {\r\n background-color: var(--tooltip-bg);\r\n color: var(--tooltip-text);\r\n border: var(--tooltip-border);\r\n border-radius: var(--radius-sm);\r\n font-family: var(--font-main);\r\n }\r\n \r\n /* Override Backdrop for specific themes if needed */\r\n [data-theme=\"pixel\"] .strata-backdrop { backdrop-filter: none; background: #000; }\r\n [data-theme=\"hacker\"] .strata-backdrop { backdrop-filter: none; background: #000; }\r\n `}</style>\r\n\r\n {state.theme === 'hacker' && <div className=\"strata-scanlines\" />}\r\n\r\n {!player && <div className=\"absolute inset-0 flex items-center justify-center bg-zinc-950 z-50\"><LoaderIcon className=\"w-10 h-10 text-[var(--accent)] animate-spin\" /></div>}\r\n\r\n {player && (\r\n <>\r\n {/* Custom Layers */}\r\n {config.layers?.map((layer, idx) => (\r\n <div\r\n key={idx}\r\n className={`absolute inset-0 pointer-events-none z-10 ${layer.className || ''}`}\r\n style={layer.style}\r\n >\r\n <HtmlOrNode content={layer.html || ''} className=\"w-full h-full\" />\r\n </div>\r\n ))}\r\n\r\n <NotificationContainer notifications={state.notifications} />\r\n <SubtitleOverlay cues={state.activeCues} settings={state.subtitleSettings} />\r\n\r\n {/* Main Interaction Layer (z-[1]) - Sits ABOVE video (which is appended at z-0/auto) to capture clicks */}\r\n <div \r\n className=\"absolute inset-0 z-[1] cursor-pointer\" \r\n onClick={handleContainerClick} \r\n aria-hidden=\"true\" \r\n role=\"button\"\r\n tabIndex={-1}\r\n />\r\n\r\n {poster && !hasPlayed && (\r\n <div\r\n className=\"absolute inset-0 bg-cover bg-center z-[5] pointer-events-none strata-poster\"\r\n style={{ backgroundImage: `url(${poster})` }}\r\n />\r\n )}\r\n\r\n {/* Context Menu */}\r\n {contextMenu.visible && (\r\n <ContextMenu\r\n x={contextMenu.x}\r\n y={contextMenu.y}\r\n items={contextMenuItems}\r\n onClose={closeAllMenus}\r\n containerWidth={playerWidth}\r\n containerHeight={playerHeight}\r\n />\r\n )}\r\n\r\n {/* Video Info Modal */}\r\n {showVideoInfo && player && (\r\n <VideoInfo player={player} onClose={() => setShowVideoInfo(false)} />\r\n )}\r\n\r\n {/* Fast Forward Overlay */}\r\n {isFastForwarding && (\r\n <div className=\"absolute top-8 left-1/2 -translate-x-1/2 bg-black/50 backdrop-blur-md px-4 py-2 rounded-full flex items-center gap-2 z-40 animate-in fade-in zoom-in duration-200 pointer-events-none\">\r\n <FastForwardIcon className=\"w-4 h-4 text-[var(--accent)] fill-current\" />\r\n <span className=\"text-xs font-bold tracking-wider\">2x Speed</span>\r\n </div>\r\n )}\r\n\r\n {/* Mobile Lock Button */}\r\n {useLock && isMobile && state.controlsVisible && (\r\n <button\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n onClick={(e) => { e.stopPropagation(); player.toggleLock(); }}\r\n className={`absolute left-4 md:left-6 bottom-24 md:bottom-28 z-50 p-3 rounded-full bg-black/50 backdrop-blur-md border border-white/10 text-white transition-all active:scale-95 ${state.isLocked ? 'text-[var(--accent)] bg-white/10' : 'hover:bg-white/10'}`}\r\n >\r\n {state.isLocked ? <LockIcon className=\"w-5 h-5\" /> : <UnlockIcon className=\"w-5 h-5\" />}\r\n </button>\r\n )}\r\n\r\n {seekAnimation && (\r\n <div\r\n key={seekAnimation.id}\r\n className={`absolute top-0 bottom-0 flex items-center justify-center w-[35%] z-20 bg-white/5 backdrop-blur-[1px] animate-out fade-out duration-500 fill-mode-forwards pointer-events-none ${seekAnimation.type === 'rewind' ? 'left-0 rounded-r-[4rem]' : 'right-0 rounded-l-[4rem]'}`}\r\n onAnimationEnd={() => setSeekAnimation(null)}\r\n >\r\n <div className=\"flex flex-col items-center text-white drop-shadow-lg\">\r\n {seekAnimation.type === 'rewind' ? <Replay10Icon className=\"w-12 h-12 animate-pulse\" /> : <Forward10Icon className=\"w-12 h-12 animate-pulse\" />}\r\n <span className=\"font-bold text-sm mt-2 font-mono\">{seekAnimation.type === 'rewind' ? '-10s' : '+10s'}</span>\r\n </div>\r\n </div>\r\n )}\r\n {state.isBuffering && <div className=\"absolute inset-0 flex items-center justify-center z-20 pointer-events-none\"><LoaderIcon className=\"w-12 h-12 text-[var(--accent)] animate-spin drop-shadow-lg\" /></div>}\r\n {state.error && <div className=\"absolute inset-0 flex items-center justify-center z-30 bg-black/90 backdrop-blur-md animate-in fade-in\"><div className=\"flex flex-col items-center gap-4 text-red-500 p-8 max-w-md text-center\"><span className=\"text-5xl mb-2\">⚠️</span><h3 className=\"text-xl font-bold text-white\">Playback Error</h3><p className=\"text-zinc-400 text-sm\">{state.error}</p><button onClick={() => player.load(player.store.get().sources[player.store.get().currentSourceIndex] || { url: src || '', type: type || 'auto' }, textTracks)} className=\"px-6 py-2 bg-[var(--accent)] text-white font-medium rounded-full hover:opacity-90 transition-opacity mt-4 shadow-lg\">Try Again</button></div></div>}\r\n\r\n {/* Center Controls - Hidden if locked or configured off */}\r\n {useCenterControls && !state.isLocked && (((!state.isPlaying && !state.isBuffering && !state.error) || state.controlsVisible) && !state.isBuffering) ? (\r\n <div\r\n className={`absolute inset-0 flex items-center justify-center z-10 transition-opacity duration-300 pointer-events-none ${state.controlsVisible || !state.isPlaying ? 'opacity-100' : 'opacity-0'}`}\r\n >\r\n <div className=\"flex items-center gap-8 md:gap-16 pointer-events-auto\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); triggerSkip('rewind'); }} className={`group flex items-center justify-center rounded-full bg-black/40 hover:bg-black/60 border border-white/10 transition-all duration-300 active:scale-125 active:opacity-80 text-white/90 focus:outline-none backdrop-blur-sm ${center.skipBtn}`}><Replay10Icon className={center.skipIcon} /></button>\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player.togglePlay(); }} className={`group relative flex items-center justify-center rounded-full bg-white/10 hover:bg-[var(--accent)] border border-white/10 shadow-2xl transition-all duration-300 active:scale-90 active:opacity-80 focus:outline-none backdrop-blur-md ${center.playBtn}`}>{state.isPlaying ? <PauseIcon className={`${center.playIcon} text-white fill-current`} /> : <PlayIcon className={`${center.playIcon} text-white ml-1 fill-current`} />}</button>\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); triggerSkip('forward'); }} className={`group flex items-center justify-center rounded-full bg-black/40 hover:bg-black/60 border border-white/10 transition-all duration-300 active:scale-125 active:opacity-80 text-white/90 focus:outline-none backdrop-blur-sm ${center.skipBtn}`}><Forward10Icon className={center.skipIcon} /></button>\r\n </div>\r\n </div>\r\n ) : null}\r\n\r\n {/* Bottom Control Bar - Hidden if locked */}\r\n <div\r\n className={`absolute inset-x-0 bottom-0 z-30 transition-all duration-300 px-4 md:px-6 py-4 bg-gradient-to-t from-black/90 via-black/50 to-transparent ${isControlsVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4 pointer-events-none'}`}\r\n onClick={(e) => {\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n }\r\n // Stop prop to prevent play toggle, but allow menu closing logic above to run first\r\n if (e.target === e.currentTarget) {\r\n setIsVolumeLocked(false);\r\n }\r\n e.stopPropagation();\r\n }}\r\n >\r\n {/* Progress Bar (Hidden in Live Mode) */}\r\n {!config.isLive && (\r\n <div\r\n ref={progressBarRef}\r\n className=\"relative w-full h-3 group/slider mb-3 cursor-pointer touch-none flex items-center\"\r\n onMouseMove={handleProgressMove}\r\n onMouseLeave={() => { setHoverTime(null); setCurrentThumbnail(null); }}\r\n onMouseDown={handleSeekStart}\r\n onTouchStart={handleSeekStart}\r\n >\r\n {/* Highlights */}\r\n {config.highlight?.map((h, i) => (\r\n <div key={i} className=\"absolute top-1/2 -translate-y-1/2 w-1.5 h-1.5 bg-yellow-400 rounded-full z-10 pointer-events-none\" style={{ left: `${(h.time / state.duration) * 100}%` }} title={h.text} />\r\n ))}\r\n\r\n {hoverTime !== null && (<div className=\"absolute bottom-full mb-1.5 flex flex-col items-center transform -translate-x-1/2 z-40 pointer-events-none transition-opacity duration-150\" style={{ left: `clamp(70px, ${hoverPos}%, calc(100% - 70px))` }}>{currentThumbnail && (<div className=\"bg-black/90 border border-white/10 shadow-2xl overflow-hidden backdrop-blur-sm\" style={{ width: `${currentThumbnail.w * 0.5}px`, height: `${currentThumbnail.h * 0.5}px`, borderRadius: 'var(--radius)' }}><div style={{ backgroundImage: `url(\"${currentThumbnail.url}\")`, width: `${currentThumbnail.w}px`, height: `${currentThumbnail.h}px`, backgroundPosition: `-${currentThumbnail.x}px -${currentThumbnail.y}px`, backgroundRepeat: 'no-repeat', transform: 'scale(0.5)', transformOrigin: 'top left' }} /></div>)}<div className=\"strata-tooltip px-2 py-0.5 text-[11px] font-bold font-mono shadow-lg tabular-nums mt-1\">{formatTime(hoverTime)}</div></div>)}\r\n\r\n {/* Track */}\r\n <div className=\"w-full h-1 bg-white/20 overflow-hidden relative backdrop-blur-sm border-[length:var(--border-width)] border-white/10\" style={{ borderRadius: 'var(--radius-full)' }}>\r\n {state.duration > 0 && state.buffered.map((range, i) => (<div key={i} className=\"absolute top-0 bottom-0 bg-white/20\" style={{ left: `${(range.start / state.duration) * 100}%`, width: `${((range.end - range.start) / state.duration) * 100}%` }} />))}\r\n <div className=\"absolute left-0 top-0 bottom-0 bg-[var(--accent)]\" style={{ width: `${((isScrubbing ? scrubbingTime : state.currentTime) / state.duration) * 100}%` }} />\r\n </div>\r\n\r\n {/* Thumb */}\r\n <div\r\n className=\"absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-3.5 h-3.5 bg-white shadow-md scale-0 group-hover/slider:scale-100 transition-transform duration-100 z-10\"\r\n style={{\r\n left: `${((isScrubbing ? scrubbingTime : state.currentTime) / state.duration) * 100}%`,\r\n borderRadius: 'var(--radius-full)'\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n <div className=\"flex items-center justify-between pointer-events-auto\">\r\n <div className=\"flex items-center gap-3\">\r\n {controls.filter(c => c.position === 'left' || c.position === 'center').map(renderControl)}\r\n </div>\r\n\r\n <div className=\"flex items-center gap-1\">\r\n {controls.filter(c => c.position === 'right').map(renderControl)}\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n \r\n if (state.isWebFullscreen && typeof document !== 'undefined') {\r\n return createPortal(playerContent, document.body);\r\n }\r\n \r\n return playerContent;\r\n};\r\n","\r\nimport './index.css';\r\nimport React from 'react';\r\nimport { createRoot } from 'react-dom/client';\r\nimport { StrataPlayer } from './ui/StrataPlayer';\r\nimport {\r\n StrataCore,\r\n PlayerState,\r\n PlayerSource,\r\n StrataConfig,\r\n TextTrackConfig,\r\n IPlugin,\r\n SubtitleSettings,\r\n PlayerTheme,\r\n Highlight,\r\n LayerConfig,\r\n ContextMenuItem,\r\n ControlItem,\r\n SettingItem,\r\n Notification\r\n} from './core/StrataCore';\r\n\r\n// Export React Component\r\nexport { StrataPlayer };\r\n\r\n// Export Core & Plugins for advanced usage\r\nexport { StrataCore };\r\nexport type {\r\n PlayerState,\r\n PlayerSource,\r\n StrataConfig,\r\n TextTrackConfig,\r\n IPlugin,\r\n SubtitleSettings,\r\n PlayerTheme,\r\n Highlight,\r\n LayerConfig,\r\n ContextMenuItem,\r\n ControlItem,\r\n SettingItem,\r\n Notification\r\n};\r\n\r\n// Export Vanilla JS / Framework Agnostic Mounting Helper\r\nexport interface StrataPlayerInstance {\r\n unmount: () => void;\r\n update: (props: any) => void;\r\n}\r\n\r\nexport const mountStrataPlayer = (container: HTMLElement, props: any): StrataPlayerInstance => {\r\n const root = createRoot(container);\r\n\r\n // Initial Render\r\n root.render(React.createElement(StrataPlayer, props));\r\n\r\n return {\r\n unmount: () => {\r\n root.unmount();\r\n },\r\n update: (newProps: any) => {\r\n // Merge props or replace depending on needs, here we merge with original + new\r\n root.render(React.createElement(StrataPlayer, { ...props, ...newProps }));\r\n }\r\n };\r\n};\r\n"],"names":["EventBus","__publicField","event","callback","_a","subscribers","cb","data","NanoStore","initialState","partial","prevState","update","listener","AudioEngine","video","e","value","formatTime","seconds","h","m","s","fetchVttWithRetry","url","retries","timeout","i","controller","id","res","r","parseVTT","notify","lines","cues","start","end","baseUrl","parseTime","t","parts","line","times","urlPart","hash","x","y","w","coords","injectLibraryResources","pre1","pre2","link","script","DEFAULT_SUBTITLE_SETTINGS","STORAGE_KEY","DEFAULT_STATE","getResolvedState","config","saved","raw","mergedSubtitleSettings","StrataCore","videoElement","isFs","lockType","state","settings","val","status","idx","prev","ms","details","total","title","_b","artwork","duration","position","playbackRate","message","isFatal","customMessage","error","delay","time","onCanPlay","finalMsg","buffered","index","newTracks","signal","effectiveTimeout","localController","fetchSignal","content","container","entries","entry","plugin","sources","tracks","wasPlaying","source","isRetry","srcObj","initialSubtitleTracks","type","oldTracks","defaultTrackIndex","label","newIndex","newTrack","file","reader","blob","src","lang","isDefault","track","vol","safeVol","gain","visible","err","isWebFs","newState","canvas","ctx","a","direction","current","scaleX","scaleY","ratio","aspectRatio","isAutoSized","targetRatio","rect","containerRatio","finalW","finalH","initializeCastApi","isAvailable","castSession","mediaInfo","request","activeTrack","c","targetTrack","text","blobUrl","newSettings","target","offset","currentOffset","delta","cue","options","notifId","response","contentLength","loaded","chunks","done","percent","_c","format","bestBandwidth","bestUrl","bandwidthMatch","bandwidth","nextLine","segments","extension","mime","fileHandle","writable","memoryBlobs","isTsContent","progress","buffer","finalBlob","finalExt","n","newNotification","existing","p","useTransition","isActive","isMounted","setIsMounted","useState","isVisible","setIsVisible","useEffect","timer","Icon","className","children","fill","strokeWidth","viewBox","jsx","PlayIcon","PauseIcon","jsxs","VolumeHighIcon","VolumeLowIcon","VolumeMuteIcon","MaximizeIcon","MinimizeIcon","SettingsIcon","CheckIcon","PipIcon","SubtitleIcon","DownloadIcon","UploadIcon","ArrowLeftIcon","LoaderIcon","CastIcon","UsersIcon","ClockIcon","MinusIcon","PlusIcon","CustomizeIcon","TypeIcon","PaletteIcon","EyeIcon","MoveVerticalIcon","ResetIcon","BoldIcon","CaseUpperIcon","BlurIcon","CameraIcon","LockIcon","UnlockIcon","WebFullscreenIcon","FastForwardIcon","CloseIcon","InfoIcon","ServerIcon","CropIcon","SpeakerIcon","GaugeIcon","MusicIcon","WifiIcon","AlertCircleIcon","QualityIcon","VideoFlipIcon","SearchIcon","FileCheckIcon","FileWarningIcon","Replay10Icon","Forward10Icon","NotificationContainer","notifications","isProgress","SubtitleOverlay","getTextShadow","RenderContent","Toggle","checked","onChange","icon","tooltip","Slider","min","max","step","formatValue","Select","opt","SettingsGroup","Menu","onClose","align","maxHeight","containerRef","useRef","contentRef","height","setHeight","positionClasses","useLayoutEffect","updateHeight","observer","calculatedStyle","MenuItem","active","onClick","hasSubmenu","rightIcon","MenuHeader","onBack","rightAction","MenuDivider","MenuExplorer","items","history","setHistory","currentItem","currentList","currentTitle","goBack","navigateTo","item","React","SubtitleMenu","onSelect","onUpload","onSettingsChange","onReset","onOffsetChange","animationClass","view","setView","search","setSearch","fileInputRef","filteredTracks","useMemo","Fragment","v","ContextMenu","containerWidth","containerHeight","menuRef","layout","setLayout","width","newLeft","newTop","availableHeight","handleClickOutside","VideoInfo","player","stats","setStats","q","k","getContrastColor","hex","char","g","b","THEME_COLORS","THEMES","HtmlOrNode","style","StrataPlayer","props","poster","autoPlay","thumbnails","textTracks","plugins","onGetInstance","useScreenshot","usePip","useSetting","useFullscreen","useFullscreenWeb","useLock","useFastForward","useFlip","useAspectRatio","useHotKey","isBackdrop","useGestureSeek","useCenterControls","fetchTimeout","setPlayer","hasPlayed","setHasPlayed","playerHeight","setPlayerHeight","playerWidth","setPlayerWidth","isMobile","setIsMobile","useSyncExternalStore","useCallback","accentContrast","settingsOpen","setSettingsOpen","subtitleMenuOpen","setSubtitleMenuOpen","activeMenu","setActiveMenu","activeControlId","setActiveControlId","lastActiveControlId","contextMenu","setContextMenu","showVideoInfo","setShowVideoInfo","settingsTransition","subtitleTransition","controlTransition","closeAllMenus","handleGlobalClick","isScrubbing","setIsScrubbing","scrubbingTime","setScrubbingTime","isVolumeScrubbing","setIsVolumeScrubbing","isVolumeHovered","setIsVolumeHovered","isVolumeLocked","setIsVolumeLocked","thumbnailCues","setThumbnailCues","hoverTime","setHoverTime","hoverPos","setHoverPos","currentThumbnail","setCurrentThumbnail","seekAnimation","setSeekAnimation","skipTrigger","setSkipTrigger","isFastForwarding","setIsFastForwarding","fastForwardTimerRef","originalRateRef","touchStartX","touchStartTime","isDraggingRef","clickTimeoutRef","controlsTimeoutRef","progressBarRef","volumeBarRef","animationCleanupRef","core","updates","setCues","handleKeyDown","handleMouseMove","startFastForward","stopFastForward","handleTouchStart","handleTouchMove","deltaX","deltaRatio","newTime","handleTouchEnd","calculateTimeFromEvent","clientX","handleSeekStart","handleMove","moveEvent","handleUp","upEvent","calculateVolumeFromEvent","handleVolumeStart","handleProgressMove","triggerSkip","handleContainerClick","now","handleContextMenu","handleVolumeIconClick","VolIcon","menuMaxHeight","getIconClass","getButtonClass","iconClass","btnClass","center","isControlsVisible","isVolumeVisible","backdropClass","controls","currentSource","isHls","downloadControl","renderControl","controlId","isMenuOpen","shouldRenderMenu","wasOpen","_d","child","statusIcon","rate","lvl","_e","theme","contextMenuItems","close","playerContent","layer","range","createPortal","mountStrataPlayer","root","createRoot","newProps"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"strataplayer.cjs.js","sources":["../core/EventBus.ts","../core/NanoStore.ts","../core/AudioEngine.ts","../utils/playerUtils.ts","../core/StrataCore.ts","../ui/hooks/useTransition.tsx","../ui/Icons.tsx","../ui/components/NotificationContainer.tsx","../ui/components/SubtitleOverlay.tsx","../ui/components/SettingsPrimitives.tsx","../ui/components/Menu.tsx","../ui/components/SubtitleMenu.tsx","../ui/components/ContextMenu.tsx","../ui/components/VideoInfo.tsx","../ui/StrataPlayer.tsx","../lib.ts"],"sourcesContent":["\nexport type EventCallback<T = any> = (data: T) => void;\n\nexport class EventBus {\n private events: Map<string, EventCallback[]>;\n\n constructor() {\n this.events = new Map();\n }\n\n on<T>(event: string, callback: EventCallback<T>): () => void {\n if (!this.events.has(event)) {\n this.events.set(event, []);\n }\n this.events.get(event)?.push(callback);\n\n // Return unsubscriber\n return () => this.off(event, callback);\n }\n\n off<T>(event: string, callback: EventCallback<T>): void {\n const subscribers = this.events.get(event);\n if (subscribers) {\n this.events.set(\n event,\n subscribers.filter((cb) => cb !== callback)\n );\n }\n }\n\n emit<T>(event: string, data?: T): void {\n const subscribers = this.events.get(event);\n if (subscribers) {\n subscribers.forEach((cb) => cb(data));\n }\n }\n\n destroy() {\n this.events.clear();\n }\n}\n","\nexport type Listener<T> = (state: T, prevState: T) => void;\n\nexport class NanoStore<T> {\n private state: T;\n private listeners: Set<Listener<T>>;\n\n constructor(initialState: T) {\n this.state = initialState;\n this.listeners = new Set();\n }\n\n get(): T {\n return this.state;\n }\n\n setState(partial: Partial<T> | ((prev: T) => Partial<T>)) {\n const prevState = this.state;\n const update = typeof partial === 'function' ? (partial as any)(prevState) : partial;\n this.state = { ...prevState, ...update };\n \n this.listeners.forEach((listener) => listener(this.state, prevState));\n }\n\n subscribe(listener: Listener<T>): () => void {\n this.listeners.add(listener);\n return () => this.listeners.delete(listener);\n }\n\n destroy() {\n this.listeners.clear();\n }\n}\n","\nexport class AudioEngine {\n private context: AudioContext | null = null;\n private source: MediaElementAudioSourceNode | null = null;\n private gainNode: GainNode | null = null;\n private video: HTMLVideoElement;\n private isInitialized = false;\n\n constructor(video: HTMLVideoElement) {\n this.video = video;\n }\n\n /**\n * Initialize the AudioContext. Must be called after user interaction.\n */\n init() {\n if (this.isInitialized) return;\n \n const AudioContextClass = window.AudioContext || (window as any).webkitAudioContext;\n if (!AudioContextClass) return;\n\n this.context = new AudioContext();\n this.gainNode = this.context.createGain();\n \n // Connect video -> gain -> destination\n try {\n this.source = this.context.createMediaElementSource(this.video);\n this.source.connect(this.gainNode);\n this.gainNode.connect(this.context.destination);\n this.isInitialized = true;\n } catch (e) {\n console.warn(\"StrataPlayer: Failed to initialize AudioEngine\", e);\n }\n }\n\n setGain(value: number) {\n // Lazy init on first boost attempt\n if (!this.isInitialized) this.init();\n \n if (this.gainNode && this.context) {\n this.gainNode.gain.value = value;\n \n // Web Audio context might be suspended by browser policy\n if (this.context.state === 'suspended') {\n this.context.resume();\n }\n }\n }\n\n destroy() {\n if (this.context) {\n this.context.close();\n }\n this.isInitialized = false;\n }\n}\n","\r\nexport const formatTime = (seconds: number) => {\r\n if (isNaN(seconds)) return '00:00';\r\n const h = Math.floor(seconds / 3600);\r\n const m = Math.floor((seconds % 3600) / 60);\r\n const s = Math.floor(seconds % 60);\r\n if (h > 0) return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;\r\n return `${m}:${s.toString().padStart(2, '0')}`;\r\n};\r\n\r\nconst fetchVttWithRetry = async (url: string, retries = 3, timeout = 20000): Promise<string> => {\r\n for (let i = 0; i < retries; i++) {\r\n const controller = new AbortController();\r\n const id = setTimeout(() => controller.abort(), timeout);\r\n try {\r\n const res = await fetch(url, { signal: controller.signal });\r\n clearTimeout(id);\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n return await res.text();\r\n } catch (e: any) {\r\n clearTimeout(id);\r\n if (i === retries - 1) throw e;\r\n await new Promise(r => setTimeout(r, 1000));\r\n }\r\n }\r\n throw new Error('Failed');\r\n}\r\n\r\nexport interface ThumbnailCue {\r\n start: number;\r\n end: number;\r\n url: string;\r\n x: number;\r\n y: number;\r\n w: number;\r\n h: number;\r\n}\r\n\r\nexport const parseVTT = async (url: string, notify: (msg: any) => void, timeout: number = 20000): Promise<ThumbnailCue[]> => {\r\n try {\r\n const text = await fetchVttWithRetry(url, 3, timeout);\r\n const lines = text.split('\\n');\r\n const cues: ThumbnailCue[] = [];\r\n let start: number | null = null;\r\n let end: number | null = null;\r\n const baseUrl = url.substring(0, url.lastIndexOf('/') + 1);\r\n const parseTime = (t: string) => {\r\n const parts = t.split(':');\r\n let s = 0;\r\n if (parts.length === 3) {\r\n s += parseFloat(parts[0]) * 3600;\r\n s += parseFloat(parts[1]) * 60;\r\n s += parseFloat(parts[2]);\r\n } else {\r\n s += parseFloat(parts[0]) * 60;\r\n s += parseFloat(parts[1]);\r\n }\r\n return s;\r\n };\r\n for (let line of lines) {\r\n line = line.trim();\r\n if (line.includes('-->')) {\r\n const times = line.split('-->');\r\n start = parseTime(times[0].trim());\r\n end = parseTime(times[1].trim());\r\n } else if (start !== null && end !== null && line.length > 0) {\r\n let [urlPart, hash] = line.split('#');\r\n if (!urlPart.match(/^https?:\\/\\//) && !urlPart.startsWith('data:')) urlPart = baseUrl + urlPart;\r\n let x = 0, y = 0, w = 0, h = 0;\r\n if (hash && hash.startsWith('xywh=')) {\r\n const coords = hash.replace('xywh=', '').split(',');\r\n if (coords.length === 4) {\r\n x = parseInt(coords[0]); y = parseInt(coords[1]); w = parseInt(coords[2]); h = parseInt(coords[3]);\r\n }\r\n }\r\n if (w > 0 && h > 0) cues.push({ start, end, url: urlPart, x, y, w, h });\r\n start = null; end = null;\r\n }\r\n }\r\n return cues;\r\n } catch (e: any) {\r\n notify({ type: 'warning', message: `Failed to load thumbnails`, duration: 4000 });\r\n return [];\r\n }\r\n};\r\n\r\nexport const injectLibraryResources = () => {\r\n if (typeof document === 'undefined') return;\r\n\r\n // 1. Google Fonts\r\n if (!document.getElementById('strata-fonts')) {\r\n // Preconnects for performance\r\n const pre1 = document.createElement('link');\r\n pre1.rel = 'preconnect';\r\n pre1.href = 'https://fonts.googleapis.com';\r\n document.head.appendChild(pre1);\r\n\r\n const pre2 = document.createElement('link');\r\n pre2.rel = 'preconnect';\r\n pre2.href = 'https://fonts.gstatic.com';\r\n pre2.crossOrigin = 'anonymous';\r\n document.head.appendChild(pre2);\r\n\r\n // Main Font Sheet\r\n const link = document.createElement('link');\r\n link.id = 'strata-fonts';\r\n link.rel = 'stylesheet';\r\n link.href = 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&family=Press+Start+2P&family=Cinzel:wght@400;600;700&display=swap';\r\n document.head.appendChild(link);\r\n }\r\n\r\n // 2. Google Cast SDK\r\n // Ensure we don't inject if already present\r\n if (!document.querySelector('script[src*=\"cast_sender.js\"]') && !(window as any).cast) {\r\n const script = document.createElement('script');\r\n script.src = 'https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1';\r\n document.head.appendChild(script);\r\n }\r\n};\r\n","\r\nimport { EventBus, EventCallback } from './EventBus';\r\nimport { NanoStore } from './NanoStore';\r\nimport { AudioEngine } from './AudioEngine';\r\nimport { injectLibraryResources } from '../utils/playerUtils';\r\nimport React from 'react';\r\n\r\nexport interface Notification {\r\n id: string;\r\n message: string;\r\n type: 'info' | 'success' | 'warning' | 'error' | 'loading';\r\n duration?: number; // ms, if null then persistent\r\n progress?: number; // 0-100\r\n action?: {\r\n label: string;\r\n onClick: () => void;\r\n };\r\n}\r\n\r\nexport interface TextTrackConfig {\r\n src: string;\r\n label: string;\r\n srcLang?: string;\r\n default?: boolean;\r\n kind?: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';\r\n}\r\n\r\nexport interface SubtitleTrackState extends TextTrackConfig {\r\n index: number;\r\n status: 'idle' | 'loading' | 'success' | 'error';\r\n isDefault?: boolean;\r\n}\r\n\r\nexport interface SubtitleSettings {\r\n useNative: boolean; // \"Native video subtitle\"\r\n fixCapitalization: boolean;\r\n backgroundOpacity: number; // 0-100\r\n backgroundBlur: boolean;\r\n backgroundBlurAmount: number; // px\r\n textSize: number; // % (100 = 1em)\r\n textStyle: 'none' | 'outline' | 'raised' | 'depressed' | 'shadow';\r\n isBold: boolean;\r\n textColor: string;\r\n verticalOffset: number; // px from bottom\r\n}\r\n\r\nexport const DEFAULT_SUBTITLE_SETTINGS: SubtitleSettings = {\r\n useNative: false,\r\n fixCapitalization: false,\r\n backgroundOpacity: 50,\r\n backgroundBlur: false,\r\n backgroundBlurAmount: 4,\r\n textSize: 100,\r\n textStyle: 'shadow',\r\n isBold: false,\r\n textColor: '#ffffff',\r\n verticalOffset: 40,\r\n};\r\n\r\nexport type PlayerTheme = 'default' | 'pixel' | 'game' | 'hacker';\r\nexport type VideoFit = 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';\r\n\r\nexport interface PlayerSource {\r\n url: string;\r\n type?: 'hls' | 'mp4' | 'webm' | 'dash' | 'mpegts' | 'webtorrent' | string;\r\n name?: string;\r\n}\r\n\r\nexport interface Highlight {\r\n time: number;\r\n text: string;\r\n}\r\n\r\nexport interface LayerConfig {\r\n name?: string;\r\n html: string | React.ReactNode;\r\n style?: React.CSSProperties;\r\n className?: string;\r\n click?: () => void;\r\n mounted?: (element: HTMLElement) => void;\r\n}\r\n\r\nexport interface ContextMenuItem {\r\n html?: string | React.ReactNode;\r\n disabled?: boolean;\r\n icon?: string | React.ReactNode;\r\n onClick?: (close: () => void) => void;\r\n click?: (close: () => void) => void;\r\n checked?: boolean;\r\n separator?: boolean;\r\n isLabel?: boolean;\r\n showBorder?: boolean;\r\n}\r\n\r\nexport interface SettingItem {\r\n id?: string;\r\n html?: string | React.ReactNode; // Optional to support separators\r\n icon?: string | React.ReactNode;\r\n tooltip?: string;\r\n separator?: boolean; // New: Divider support\r\n isLabel?: boolean; // Header label\r\n\r\n // State\r\n active?: boolean; // Visual \"check\" state\r\n value?: any; // Value identifier for selection logic\r\n\r\n // Toggle Switch\r\n switch?: boolean;\r\n onSwitch?: (item: SettingItem, checked: boolean) => void;\r\n\r\n // Range Slider\r\n range?: boolean;\r\n min?: number;\r\n max?: number;\r\n step?: number;\r\n onRange?: (value: number) => void;\r\n formatValue?: (value: number) => string;\r\n\r\n // Action\r\n onClick?: (item: SettingItem) => void;\r\n click?: (item: SettingItem) => void; // Alias\r\n\r\n // Recursion (Nested Menu)\r\n children?: SettingItem[];\r\n currentLabel?: React.ReactNode; // Label to show in parent (e.g. \"1080p\") next to arrow\r\n}\r\n\r\nexport interface ControlItem {\r\n id?: string;\r\n position: 'left' | 'right' | 'center';\r\n index: number;\r\n html?: string | React.ReactNode;\r\n tooltip?: string;\r\n onClick?: (core: StrataCore) => void;\r\n click?: (core: StrataCore) => void;\r\n className?: string;\r\n style?: React.CSSProperties;\r\n isBuiltIn?: boolean;\r\n\r\n // Nested Menu Support for Controls\r\n children?: SettingItem[];\r\n}\r\n\r\nexport interface PlayerState {\r\n isPlaying: boolean;\r\n isBuffering: boolean;\r\n isLive: boolean;\r\n currentTime: number;\r\n duration: number;\r\n buffered: { start: number; end: number }[];\r\n volume: number;\r\n isMuted: boolean;\r\n audioGain: number;\r\n playbackRate: number;\r\n qualityLevels: { height: number; bitrate: number; index: number }[];\r\n currentQuality: number;\r\n audioTracks: { label: string; language: string; index: number }[];\r\n currentAudioTrack: number;\r\n error: string | null;\r\n isFullscreen: boolean;\r\n isWebFullscreen: boolean;\r\n isPip: boolean;\r\n subtitleTracks: SubtitleTrackState[];\r\n currentSubtitle: number;\r\n subtitleOffset: number; // in seconds\r\n subtitleSettings: SubtitleSettings;\r\n activeCues: string[]; // For custom rendering\r\n viewMode: 'normal' | 'theater' | 'pip';\r\n notifications: Notification[];\r\n // Appearance\r\n iconSize: 'small' | 'medium' | 'large';\r\n themeColor: string;\r\n theme: PlayerTheme;\r\n // Sources\r\n sources: PlayerSource[];\r\n currentSourceIndex: number;\r\n sourceStatuses: Record<number, 'success' | 'error' | undefined>;\r\n\r\n // Phase 1 New Features State\r\n isLocked: boolean;\r\n flipState: { horizontal: boolean; vertical: boolean };\r\n aspectRatio: string; // 'default', '16:9', '4:3', etc\r\n videoFit: VideoFit;\r\n brightness: number; // 1.0 is default (100%)\r\n isAutoSized: boolean; // tracks if autoSize (cover) is currently applied (legacy prop, now maps to videoFit=cover)\r\n isLooping: boolean; // Track loop state reactively\r\n\r\n // UI State reflected in Core\r\n controlsVisible: boolean;\r\n}\r\n\r\nexport interface StrataConfig {\r\n // Basic\r\n container?: string; // Class for container\r\n id?: string;\r\n\r\n // Playback\r\n volume?: number;\r\n muted?: boolean;\r\n playbackRate?: number;\r\n audioGain?: number;\r\n loop?: boolean;\r\n playsInline?: boolean;\r\n isLive?: boolean;\r\n poster?: string; // Added to Config for Core access\r\n fetchTimeout?: number; // Default 30000ms\r\n\r\n // Appearance\r\n theme?: PlayerTheme;\r\n themeColor?: string;\r\n iconSize?: 'small' | 'medium' | 'large';\r\n backdrop?: boolean; // Blur effect\r\n autoSize?: boolean; // object-fit: cover logic (Legacy)\r\n brightness?: number; // Initial brightness\r\n videoFit?: VideoFit; // Initial video fit\r\n\r\n // Subtitles\r\n subtitleSettings?: Partial<SubtitleSettings>;\r\n\r\n // UI Toggles\r\n screenshot?: boolean;\r\n setting?: boolean;\r\n pip?: boolean;\r\n fullscreen?: boolean;\r\n fullscreenWeb?: boolean;\r\n flip?: boolean;\r\n aspectRatio?: boolean;\r\n highlight?: Highlight[];\r\n centerControls?: boolean; // Default true\r\n\r\n // Controls / Mobile\r\n hotKey?: boolean;\r\n lock?: boolean; // Mobile lock button\r\n gesture?: boolean; // Mobile gestures\r\n gestureSeek?: boolean; // Drag to seek on mobile. Default false.\r\n fastForward?: boolean; // Long press\r\n autoOrientation?: boolean; // Mobile landscape lock (default: true)\r\n\r\n // Phase 2: Customization\r\n layers?: LayerConfig[];\r\n contextmenu?: ContextMenuItem[];\r\n controls?: ControlItem[];\r\n settings?: SettingItem[]; // Append to main menu\r\n\r\n // System\r\n useSSR?: boolean;\r\n disablePersistence?: boolean;\r\n}\r\n\r\nconst STORAGE_KEY = 'strata-settings';\r\n\r\nexport const DEFAULT_STATE: PlayerState = {\r\n isPlaying: false,\r\n isBuffering: false,\r\n isLive: false,\r\n currentTime: 0,\r\n duration: 0,\r\n buffered: [],\r\n volume: 1,\r\n isMuted: false,\r\n audioGain: 1,\r\n playbackRate: 1,\r\n qualityLevels: [],\r\n currentQuality: -1,\r\n audioTracks: [],\r\n currentAudioTrack: -1,\r\n error: null,\r\n isFullscreen: false,\r\n isWebFullscreen: false,\r\n isPip: false,\r\n subtitleTracks: [],\r\n currentSubtitle: -1,\r\n subtitleOffset: 0,\r\n subtitleSettings: DEFAULT_SUBTITLE_SETTINGS,\r\n activeCues: [],\r\n viewMode: 'normal',\r\n notifications: [],\r\n iconSize: 'medium',\r\n themeColor: '#6366f1',\r\n theme: 'default',\r\n sources: [],\r\n currentSourceIndex: -1,\r\n sourceStatuses: {},\r\n // New State Defaults\r\n isLocked: false,\r\n flipState: { horizontal: false, vertical: false },\r\n aspectRatio: 'default',\r\n videoFit: 'contain',\r\n brightness: 1,\r\n isAutoSized: false,\r\n isLooping: false,\r\n controlsVisible: true\r\n};\r\n\r\n// Helper to merge Defaults -> LocalStorage -> Config\r\nexport const getResolvedState = (config: StrataConfig = {}): PlayerState => {\r\n let saved: any = {};\r\n if (!config.disablePersistence && typeof window !== 'undefined') {\r\n try {\r\n const raw = localStorage.getItem(STORAGE_KEY);\r\n if (raw) saved = JSON.parse(raw);\r\n } catch (e) { /* ignore */ }\r\n }\r\n\r\n const mergedSubtitleSettings = {\r\n ...DEFAULT_SUBTITLE_SETTINGS,\r\n ...(saved.subtitleSettings || {}),\r\n ...(config.subtitleSettings || {})\r\n };\r\n\r\n // Determine initial video fit (Priority: config.videoFit > config.autoSize > saved.videoFit > default)\r\n const resolvedVideoFit = config.videoFit ?? (config.autoSize ? 'cover' : undefined) ?? saved.videoFit ?? DEFAULT_STATE.videoFit;\r\n\r\n return {\r\n ...DEFAULT_STATE,\r\n ...saved, // Load saved first\r\n // Override with config if present (not undefined)\r\n volume: config.volume ?? saved.volume ?? DEFAULT_STATE.volume,\r\n isMuted: config.muted ?? saved.isMuted ?? DEFAULT_STATE.isMuted,\r\n playbackRate: config.playbackRate ?? saved.playbackRate ?? DEFAULT_STATE.playbackRate,\r\n audioGain: config.audioGain ?? saved.audioGain ?? DEFAULT_STATE.audioGain,\r\n theme: config.theme ?? saved.theme ?? DEFAULT_STATE.theme,\r\n themeColor: config.themeColor ?? saved.themeColor ?? DEFAULT_STATE.themeColor,\r\n iconSize: config.iconSize ?? saved.iconSize ?? DEFAULT_STATE.iconSize,\r\n subtitleSettings: mergedSubtitleSettings,\r\n // Config overrides state for these visual modes\r\n isAutoSized: config.autoSize ?? DEFAULT_STATE.isAutoSized,\r\n videoFit: resolvedVideoFit,\r\n brightness: config.brightness ?? saved.brightness ?? DEFAULT_STATE.brightness,\r\n isLive: config.isLive ?? saved.isLive ?? DEFAULT_STATE.isLive,\r\n isLooping: config.loop ?? saved.isLooping ?? DEFAULT_STATE.isLooping,\r\n sourceStatuses: {} // Never persist statuses\r\n };\r\n};\r\n\r\nexport interface IPlugin {\r\n name: string;\r\n init(core: StrataCore): void;\r\n destroy?(): void;\r\n}\r\n\r\nexport class StrataCore {\r\n public video: HTMLVideoElement;\r\n public container: HTMLElement | null = null;\r\n public events: EventBus;\r\n public store: NanoStore<PlayerState>;\r\n private plugins: Map<string, IPlugin> = new Map();\r\n private audioEngine: AudioEngine;\r\n public config: StrataConfig;\r\n private resizeObserver: ResizeObserver | null = null;\r\n\r\n // Retry Logic\r\n private retryCount = 0;\r\n private maxRetries = 5;\r\n private retryTimer: any = null;\r\n private currentSource: PlayerSource | null = null;\r\n private currentSrc: string = '';\r\n // Track configs from setSources are stored here to lazy load\r\n private trackConfigs: TextTrackConfig[] = [];\r\n\r\n // Download Control\r\n private activeDownloads = new Map<string, AbortController>();\r\n\r\n // Cast\r\n private castInitialized = false;\r\n\r\n private boundCueChange: () => void;\r\n private boundFullscreenChange: () => void;\r\n\r\n constructor(config: StrataConfig = {}, videoElement?: HTMLVideoElement) {\r\n injectLibraryResources(); // Ensure fonts and external SDKs are loaded\r\n this.config = config;\r\n // Set Defaults\r\n this.config.autoOrientation = this.config.autoOrientation ?? true;\r\n this.config.fetchTimeout = this.config.fetchTimeout ?? 30000;\r\n this.config.centerControls = this.config.centerControls ?? true;\r\n this.config.gestureSeek = this.config.gestureSeek ?? false;\r\n\r\n this.video = videoElement || document.createElement('video');\r\n this.video.crossOrigin = \"anonymous\";\r\n\r\n // Aggressive Buffering: \r\n // Setting preload=\"auto\" hints the browser to buffer as much as possible.\r\n // While we can't force chunk size on native mp4 without MSE, this is the best native setting.\r\n this.video.preload = \"auto\";\r\n\r\n // Init Config Props to Video\r\n if (config.playsInline !== false) this.video.playsInline = true;\r\n\r\n this.events = new EventBus();\r\n\r\n // Initialize Store with resolved state\r\n const initialState = getResolvedState(config);\r\n this.store = new NanoStore(initialState);\r\n\r\n this.audioEngine = new AudioEngine(this.video);\r\n this.boundCueChange = this.handleCueChange.bind(this);\r\n\r\n // Bind fullscreen listener once\r\n this.boundFullscreenChange = () => {\r\n const isFs = !!document.fullscreenElement;\r\n this.store.setState({ isFullscreen: isFs });\r\n this.emit('resize');\r\n this.emit(isFs ? 'fullscreen' : 'fullscreen_exit');\r\n\r\n // Auto Orientation logic\r\n if (isFs && this.config.autoOrientation && screen.orientation && 'lock' in screen.orientation) {\r\n // Basic logic: if video width > height, lock landscape\r\n const isLandscape = this.video.videoWidth > this.video.videoHeight;\r\n const lockType = isLandscape ? 'landscape' : 'portrait';\r\n try {\r\n // @ts-ignore\r\n screen.orientation.lock(lockType).catch(() => { });\r\n } catch (e) { }\r\n } else if (!isFs && screen.orientation && 'unlock' in screen.orientation) {\r\n // @ts-ignore\r\n screen.orientation.unlock();\r\n }\r\n };\r\n\r\n // Apply initial state to video element\r\n this.video.volume = initialState.volume;\r\n this.video.muted = initialState.isMuted;\r\n this.video.playbackRate = initialState.playbackRate;\r\n this.video.loop = initialState.isLooping; // Apply loop state\r\n\r\n // Apply brightness\r\n this.video.style.filter = `brightness(${initialState.brightness})`;\r\n\r\n if (initialState.audioGain > 1) {\r\n this.audioEngine.setGain(initialState.audioGain);\r\n }\r\n\r\n // Apply Video Fit (replaces simple object-fit)\r\n this.video.style.objectFit = initialState.videoFit;\r\n\r\n this.initVideoListeners();\r\n this.initMediaSession();\r\n this.initCast();\r\n\r\n // Persistence Subscriber\r\n if (!config.disablePersistence) {\r\n this.store.subscribe((state) => {\r\n const settings = {\r\n volume: state.volume,\r\n isMuted: state.isMuted,\r\n playbackRate: state.playbackRate,\r\n subtitleSettings: state.subtitleSettings,\r\n iconSize: state.iconSize,\r\n themeColor: state.themeColor,\r\n theme: state.theme,\r\n isLive: state.isLive,\r\n isLooping: state.isLooping,\r\n brightness: state.brightness,\r\n videoFit: state.videoFit,\r\n };\r\n localStorage.setItem(STORAGE_KEY, JSON.stringify(settings));\r\n });\r\n }\r\n }\r\n\r\n // --- Instance Properties ---\r\n\r\n get playing() { return !this.video.paused && !this.video.ended && this.video.readyState > 2; }\r\n\r\n get currentTime() { return this.video.currentTime; }\r\n set currentTime(val: number) { this.seek(val); }\r\n\r\n get duration() { return this.video.duration || 0; }\r\n\r\n get paused() { return this.video.paused; }\r\n\r\n get volume() { return this.video.volume; }\r\n set volume(val: number) { this.setVolume(val); }\r\n\r\n get muted() { return this.video.muted; }\r\n set muted(val: boolean) {\r\n this.video.muted = val;\r\n this.store.setState({ isMuted: val });\r\n }\r\n\r\n get playbackRate() { return this.video.playbackRate; }\r\n set playbackRate(val: number) { this.video.playbackRate = val; }\r\n\r\n get loop() { return this.video.loop; }\r\n set loop(val: boolean) {\r\n this.video.loop = val;\r\n this.store.setState({ isLooping: val });\r\n }\r\n\r\n // --- Instance Methods ---\r\n\r\n forward(seconds: number = 10) { this.skip(seconds); }\r\n backward(seconds: number = 10) { this.skip(-seconds); }\r\n\r\n // --- Event API ---\r\n\r\n on(event: string, callback: EventCallback) { return this.events.on(event, callback); }\r\n off(event: string, callback: EventCallback) { return this.events.off(event, callback); }\r\n emit(event: string, data?: any) { return this.events.emit(event, data); }\r\n\r\n private initVideoListeners() {\r\n const s = (partial: Partial<PlayerState>) => this.store.setState(partial);\r\n\r\n const events = [\r\n 'abort', 'canplay', 'canplaythrough', 'durationchange', 'emptied', 'ended', 'error',\r\n 'loadeddata', 'loadedmetadata', 'loadstart', 'pause', 'play', 'playing', 'progress',\r\n 'ratechange', 'seeked', 'seeking', 'stalled', 'suspend', 'timeupdate', 'volumechange', 'waiting'\r\n ];\r\n\r\n // Standard video event proxying\r\n events.forEach(event => {\r\n this.video.addEventListener(event, (e) => {\r\n // 1. Emit namespaced event (e.g. video:timeupdate)\r\n this.emit(`video:${event}`, e);\r\n\r\n // 2. Emit core events (e.g. play, pause)\r\n if (event === 'play') this.emit('play');\r\n if (event === 'pause') this.emit('pause');\r\n if (event === 'ended') this.emit('ended');\r\n if (event === 'error') this.emit('error', this.video.error);\r\n if (event === 'seeked') this.emit('seek');\r\n\r\n // 3. Update internal store for UI\r\n switch (event) {\r\n case 'play':\r\n s({ isPlaying: true });\r\n if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'playing';\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'pause':\r\n s({ isPlaying: false });\r\n if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'paused';\r\n break;\r\n case 'ended':\r\n s({ isPlaying: false });\r\n if ('mediaSession' in navigator) navigator.mediaSession.playbackState = 'paused';\r\n break;\r\n\r\n case 'waiting':\r\n s({ isBuffering: true });\r\n this.emit('loading', true);\r\n break;\r\n case 'playing':\r\n s({ isBuffering: false });\r\n this.emit('loading', false);\r\n break;\r\n case 'canplay':\r\n s({ isBuffering: false });\r\n this.emit('loading', false);\r\n // Mark source as success\r\n this.updateSourceStatus('success');\r\n break;\r\n\r\n case 'loadeddata':\r\n s({ isBuffering: false });\r\n this.retryCount = 0;\r\n this.removeNotification('retry');\r\n if (this.store.get().error) s({ error: null });\r\n // Mark source as success\r\n this.updateSourceStatus('success');\r\n break;\r\n case 'loadedmetadata':\r\n this.updateMediaSessionMetadata();\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'timeupdate':\r\n if (!this.video.seeking) s({ currentTime: this.video.currentTime });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'seeked':\r\n s({ currentTime: this.video.currentTime });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'durationchange':\r\n s({ duration: this.video.duration });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'volumechange': s({ volume: this.video.volume, isMuted: this.video.muted }); break;\r\n case 'ratechange':\r\n s({ playbackRate: this.video.playbackRate });\r\n this.updateMediaSessionPosition();\r\n break;\r\n case 'error': this.handleError(); break;\r\n case 'progress': this.updateBuffer(); break;\r\n case 'enterpictureinpicture': s({ isPip: true }); break;\r\n case 'leavepictureinpicture': s({ isPip: false }); break;\r\n }\r\n });\r\n });\r\n\r\n // PiP events are not in the standard list above usually\r\n this.video.addEventListener('enterpictureinpicture', () => {\r\n s({ isPip: true });\r\n this.emit('pip', true);\r\n });\r\n this.video.addEventListener('leavepictureinpicture', () => {\r\n s({ isPip: false });\r\n this.emit('pip', false);\r\n });\r\n\r\n // Global fullscreen listener to catch Esc key or browser button\r\n document.addEventListener('fullscreenchange', this.boundFullscreenChange);\r\n }\r\n\r\n private updateSourceStatus(status: 'success' | 'error') {\r\n const idx = this.store.get().currentSourceIndex;\r\n if (idx !== -1) {\r\n this.store.setState((prev) => ({\r\n sourceStatuses: { ...prev.sourceStatuses, [idx]: status }\r\n }));\r\n }\r\n }\r\n\r\n // --- Media Session API ---\r\n\r\n private initMediaSession() {\r\n if (!('mediaSession' in navigator)) return;\r\n\r\n const ms = navigator.mediaSession;\r\n\r\n ms.setActionHandler('play', () => this.play());\r\n ms.setActionHandler('pause', () => this.pause());\r\n ms.setActionHandler('seekbackward', (details) => this.skip(details.seekOffset ? -details.seekOffset : -10));\r\n ms.setActionHandler('seekforward', (details) => this.skip(details.seekOffset || 10));\r\n ms.setActionHandler('seekto', (details) => {\r\n if (details.seekTime !== undefined) this.seek(details.seekTime);\r\n });\r\n ms.setActionHandler('stop', () => {\r\n this.pause();\r\n this.seek(0);\r\n });\r\n // Playlist controls\r\n ms.setActionHandler('previoustrack', () => {\r\n const idx = this.store.get().currentSourceIndex;\r\n if (idx > 0) this.switchSource(idx - 1);\r\n });\r\n ms.setActionHandler('nexttrack', () => {\r\n const idx = this.store.get().currentSourceIndex;\r\n const total = this.store.get().sources.length;\r\n if (idx < total - 1) this.switchSource(idx + 1);\r\n });\r\n }\r\n\r\n private updateMediaSessionMetadata() {\r\n if (!('mediaSession' in navigator)) return;\r\n\r\n const title = this.currentSource?.name || this.currentSource?.url.split('/').pop() || 'Video';\r\n\r\n const artwork = [];\r\n\r\n // 1. Prioritize configured poster or source-specific poster\r\n if (this.config.poster) {\r\n artwork.push({ src: this.config.poster, sizes: '512x512', type: 'image/jpeg' });\r\n }\r\n\r\n // 2. Fallback to relative logo path.\r\n artwork.push({ src: 'logo.png', sizes: '512x512', type: 'image/png' });\r\n\r\n navigator.mediaSession.metadata = new MediaMetadata({\r\n title: title,\r\n artist: 'StrataPlayer',\r\n artwork: artwork\r\n });\r\n }\r\n\r\n private updateMediaSessionPosition() {\r\n if (!('mediaSession' in navigator)) return;\r\n\r\n const duration = this.video.duration;\r\n const position = this.video.currentTime;\r\n const playbackRate = this.video.playbackRate;\r\n\r\n if (!isNaN(duration) && isFinite(duration) && !isNaN(position)) {\r\n try {\r\n navigator.mediaSession.setPositionState({\r\n duration: Math.max(0, duration),\r\n playbackRate,\r\n position: Math.max(0, Math.min(position, duration)) // Ensure within [0, duration]\r\n });\r\n } catch (e) {\r\n console.warn(\"MediaSession Position Error:\", e);\r\n }\r\n }\r\n }\r\n\r\n public triggerError(message: string, isFatal: boolean = false) {\r\n if (isFatal) {\r\n this.handleError(message);\r\n } else {\r\n this.notify({ type: 'warning', message: `Warning: ${message}`, duration: 5000 });\r\n }\r\n }\r\n\r\n private handleError(customMessage?: string) {\r\n const error = this.video.error;\r\n const message = customMessage || error?.message || (error ? `Code ${error.code}` : 'Unknown Error');\r\n\r\n this.removeNotification('retry');\r\n this.emit('video:error', error); // Emitting video:error separately\r\n\r\n if (this.retryCount < this.maxRetries) {\r\n this.retryCount++;\r\n const delay = Math.pow(2, this.retryCount - 1) * 1500;\r\n\r\n this.notify({\r\n id: 'retry',\r\n type: 'loading',\r\n // Cleaned up formatting with newline\r\n message: `Error: ${message}.\\nRetrying (${this.retryCount}/${this.maxRetries})`,\r\n });\r\n\r\n console.warn(`[StrataPlayer] Error: ${message}. Retrying in ${delay}ms...`);\r\n\r\n if (this.retryTimer) clearTimeout(this.retryTimer);\r\n this.retryTimer = setTimeout(() => {\r\n if (this.currentSource) {\r\n this.load(this.currentSource, this.trackConfigs, true); // True = isRetry\r\n\r\n const time = this.store.get().currentTime;\r\n if (time > 0) {\r\n const onCanPlay = () => {\r\n this.video.currentTime = time;\r\n this.video.removeEventListener('canplay', onCanPlay);\r\n };\r\n this.video.addEventListener('canplay', onCanPlay);\r\n }\r\n }\r\n }, delay);\r\n } else {\r\n // Final failure\r\n this.removeNotification('retry');\r\n const finalMsg = `Failed to play after ${this.maxRetries} attempts: ${message}`;\r\n this.store.setState({ error: finalMsg });\r\n this.emit('error', finalMsg);\r\n // Mark source as error\r\n this.updateSourceStatus('error');\r\n }\r\n }\r\n\r\n private updateBuffer() {\r\n const buffered: { start: number; end: number }[] = [];\r\n for (let i = 0; i < this.video.buffered.length; i++) {\r\n buffered.push({\r\n start: this.video.buffered.start(i),\r\n end: this.video.buffered.end(i)\r\n });\r\n }\r\n this.store.setState({ buffered });\r\n }\r\n\r\n private updateSubtitleTrackState(index: number, partial: Partial<SubtitleTrackState>) {\r\n this.store.setState((prev) => {\r\n const newTracks = [...prev.subtitleTracks];\r\n if (newTracks[index]) {\r\n newTracks[index] = { ...newTracks[index], ...partial };\r\n }\r\n return { subtitleTracks: newTracks };\r\n });\r\n }\r\n\r\n // --- Utility ---\r\n\r\n async fetchWithRetry(url: string, retries = 3, timeout?: number, signal?: AbortSignal): Promise<Response> {\r\n const effectiveTimeout = timeout ?? this.config.fetchTimeout ?? 30000;\r\n for (let i = 0; i < retries; i++) {\r\n // Create local controller only if external signal not provided\r\n const localController = signal ? null : new AbortController();\r\n const fetchSignal = signal || localController?.signal;\r\n\r\n const id = setTimeout(() => localController?.abort(), effectiveTimeout);\r\n try {\r\n const res = await fetch(url, { signal: fetchSignal });\r\n clearTimeout(id);\r\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\r\n return res;\r\n } catch (e: any) {\r\n clearTimeout(id);\r\n if (signal?.aborted) throw new Error('Aborted');\r\n if (i === retries - 1) throw e;\r\n // If it's an abort error, warn\r\n if (e.name === 'AbortError') {\r\n if (signal?.aborted) throw e; // Pass up external aborts\r\n console.warn(`Fetch timeout (${effectiveTimeout}ms) for ${url}`);\r\n }\r\n await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));\r\n }\r\n }\r\n throw new Error('Fetch failed');\r\n }\r\n\r\n // Helper to ensure subtitle content is VTT\r\n private convertToVTT(content: string): string {\r\n let text = content.trim();\r\n if (!text.startsWith('WEBVTT')) {\r\n // Replace SRT comma timestamps (00:00:20,000) with VTT dot timestamps (00:00:20.000)\r\n // Robust Regex for SRT -> VTT: (\\d+:\\d{2}:\\d{2}),(\\d{3}) -> 1:02:03.400 (Flexible hours)\r\n let vtt = text.replace(/(\\d+:\\d{2}:\\d{2}),(\\d{3})/g, '$1.$2');\r\n // Regex: (\\d{2}:\\d{2}),(\\d{3}) -> 02:03.400 (MM:SS,mmm - optional hours)\r\n vtt = vtt.replace(/(\\d{2}:\\d{2}),(\\d{3})/g, '$1.$2');\r\n return 'WEBVTT\\n\\n' + vtt;\r\n }\r\n return text;\r\n }\r\n\r\n // Enhanced Format Duration: Days, Hours, Minutes, Seconds\r\n private formatDuration(ms: number): string {\r\n if (!isFinite(ms) || ms <= 0) return '';\r\n const totalSeconds = Math.floor(ms / 1000);\r\n const d = Math.floor(totalSeconds / (3600 * 24));\r\n const h = Math.floor((totalSeconds % (3600 * 24)) / 3600);\r\n const m = Math.floor((totalSeconds % 3600) / 60);\r\n const s = totalSeconds % 60;\r\n\r\n const parts = [];\r\n if (d > 0) parts.push(`${d}d`);\r\n if (h > 0) parts.push(`${h}h`);\r\n if (m > 0) parts.push(`${m}m`);\r\n parts.push(`${s}s`);\r\n\r\n return parts.join(' ');\r\n }\r\n\r\n // --- Core Methods ---\r\n\r\n attach(container: HTMLElement) {\r\n // 1. Cleanup old observer to prevent memory leaks or zombie updates\r\n if (this.resizeObserver) {\r\n this.resizeObserver.disconnect();\r\n }\r\n\r\n this.container = container;\r\n\r\n // 2. Force append the video to the new container. \r\n // appendChild moves the node if it is already in the DOM, solving the portal detach issue.\r\n this.container.appendChild(this.video);\r\n\r\n // 3. Re-apply critical styles to ensure the video fills the new container\r\n this.video.style.width = '100%';\r\n this.video.style.height = '100%';\r\n this.video.style.objectFit = this.store.get().videoFit;\r\n this.video.style.backgroundColor = 'black';\r\n\r\n // Apply potentially persisted aspect ratio\r\n this.updateAspectRatio();\r\n\r\n // 4. Setup new Resize Observer\r\n this.resizeObserver = new ResizeObserver((entries) => {\r\n for (const entry of entries) {\r\n this.emit('resize', { width: entry.contentRect.width, height: entry.contentRect.height });\r\n this.updateAspectRatio();\r\n }\r\n });\r\n this.resizeObserver.observe(this.container);\r\n\r\n // Emit ready event\r\n this.emit('ready');\r\n }\r\n\r\n use(plugin: IPlugin) {\r\n if (this.plugins.has(plugin.name)) return;\r\n plugin.init(this);\r\n this.plugins.set(plugin.name, plugin);\r\n }\r\n\r\n setSources(sources: PlayerSource[], tracks: TextTrackConfig[] = []) {\r\n this.store.setState({ sources });\r\n this.trackConfigs = tracks;\r\n if (sources.length > 0) {\r\n this.load(sources[0], tracks);\r\n }\r\n }\r\n\r\n switchSource(index: number) {\r\n const sources = this.store.get().sources;\r\n if (index >= 0 && index < sources.length) {\r\n const time = this.video.currentTime;\r\n const wasPlaying = !this.video.paused;\r\n\r\n this.load(sources[index], this.trackConfigs);\r\n\r\n const onCanPlay = () => {\r\n this.video.currentTime = time;\r\n if (wasPlaying) this.video.play();\r\n this.video.removeEventListener('canplay', onCanPlay);\r\n };\r\n this.video.addEventListener('canplay', onCanPlay);\r\n }\r\n }\r\n\r\n load(source: PlayerSource | string, tracks: TextTrackConfig[] = [], isRetry = false) {\r\n if (this.retryTimer) clearTimeout(this.retryTimer);\r\n\r\n // Normalize string input to PlayerSource\r\n const srcObj: PlayerSource = typeof source === 'string' ? { url: source, type: 'auto' } : source;\r\n\r\n if (!isRetry) {\r\n this.retryCount = 0;\r\n this.store.setState({ error: null });\r\n this.removeNotification('retry');\r\n }\r\n\r\n this.currentSrc = srcObj.url;\r\n this.currentSource = srcObj;\r\n this.trackConfigs = tracks;\r\n\r\n // Update index state if part of playlist\r\n const allSources = this.store.get().sources;\r\n const index = allSources.findIndex(s => s.url === srcObj.url);\r\n\r\n // Prepare initial subtitle tracks state based on configuration\r\n const initialSubtitleTracks: SubtitleTrackState[] = tracks.map((t, i) => ({\r\n ...t,\r\n index: i,\r\n status: 'idle',\r\n isDefault: !!t.default\r\n }));\r\n\r\n this.store.setState({\r\n isBuffering: true,\r\n qualityLevels: [],\r\n currentQuality: -1, // Reset quality to Auto on source switch\r\n audioTracks: [],\r\n currentAudioTrack: -1, // Reset audio track\r\n subtitleTracks: initialSubtitleTracks,\r\n currentSubtitle: -1,\r\n currentSourceIndex: index\r\n });\r\n\r\n // Update Metadata early\r\n this.updateMediaSessionMetadata();\r\n\r\n // Determine type if auto\r\n let type = srcObj.type || 'auto';\r\n if (type === 'auto') {\r\n if (srcObj.url.includes('.m3u8')) type = 'hls';\r\n else if (srcObj.url.includes('.mpd')) type = 'dash';\r\n else if (srcObj.url.includes('.flv') || srcObj.url.includes('.ts')) type = 'mpegts';\r\n else if (srcObj.url.startsWith('magnet:') || srcObj.url.includes('.torrent')) type = 'webtorrent';\r\n else type = 'mp4';\r\n }\r\n\r\n // Emit load event with source details so plugins can decide to act\r\n this.events.emit('load', { url: srcObj.url, type });\r\n\r\n // Clear existing tracks from DOM\r\n const oldTracks = this.video.getElementsByTagName('track');\r\n while (oldTracks.length > 0) {\r\n oldTracks[0].remove();\r\n }\r\n\r\n // Lazy load default subtitle if present\r\n const defaultTrackIndex = initialSubtitleTracks.findIndex(t => t.default);\r\n if (defaultTrackIndex !== -1) {\r\n this.setSubtitle(defaultTrackIndex);\r\n }\r\n\r\n // If it's standard MP4/WebM, set src directly. Plugins handle HLS/Dash/Mpegts/WebTorrent.\r\n if (type === 'mp4' || type === 'webm' || type === 'ogg') {\r\n this.video.src = srcObj.url;\r\n }\r\n }\r\n\r\n // Wrapper for external subtitle API\r\n public loadSubtitle(url: string, label: string = 'Subtitle') {\r\n // Add to state list dynamically\r\n const newIndex = this.store.get().subtitleTracks.length;\r\n const newTrack: SubtitleTrackState = {\r\n src: url,\r\n label,\r\n srcLang: 'user',\r\n default: true,\r\n kind: 'subtitles',\r\n index: newIndex,\r\n status: 'idle',\r\n isDefault: true\r\n };\r\n\r\n this.store.setState(prev => ({\r\n subtitleTracks: [...prev.subtitleTracks, newTrack]\r\n }));\r\n\r\n this.setSubtitle(newIndex);\r\n }\r\n\r\n public addTextTrack(file: File, label: string) {\r\n const reader = new FileReader();\r\n reader.onload = (e) => {\r\n if (!e.target?.result) return;\r\n let content = e.target.result as string;\r\n content = this.convertToVTT(content);\r\n\r\n const blob = new Blob([content], { type: 'text/vtt' });\r\n const url = URL.createObjectURL(blob);\r\n\r\n this.loadSubtitle(url, label);\r\n this.notify({ type: 'success', message: 'Subtitle uploaded', duration: 3000 });\r\n };\r\n reader.onerror = () => {\r\n this.notify({ type: 'error', message: 'Failed to read file', duration: 3000 });\r\n };\r\n reader.readAsText(file);\r\n }\r\n\r\n private addTextTrackInternal(src: string, label: string, lang: string = '', isDefault: boolean = false) {\r\n const track = document.createElement('track');\r\n track.kind = 'subtitles';\r\n track.label = label;\r\n track.src = src;\r\n track.srclang = lang;\r\n if (isDefault) track.default = true;\r\n this.video.appendChild(track);\r\n }\r\n\r\n play() { return this.video.play(); }\r\n pause() { return this.video.pause(); }\r\n togglePlay() { this.video.paused ? this.play() : this.pause(); }\r\n\r\n seek(time: number) {\r\n if (isNaN(time)) return;\r\n const t = Math.max(0, Math.min(time, this.video.duration));\r\n this.store.setState({ currentTime: t });\r\n this.video.currentTime = t;\r\n }\r\n\r\n skip(seconds: number) {\r\n this.seek(this.video.currentTime + seconds);\r\n }\r\n\r\n setVolume(vol: number) {\r\n const safeVol = Math.max(0, Math.min(vol, 1));\r\n this.video.volume = safeVol;\r\n if (safeVol > 0 && this.video.muted) this.video.muted = false;\r\n if (safeVol === 0) this.video.muted = true;\r\n }\r\n\r\n toggleMute() {\r\n this.video.muted = !this.video.muted;\r\n }\r\n\r\n setAudioGain(gain: number) {\r\n this.store.setState({ audioGain: gain });\r\n this.audioEngine.setGain(gain);\r\n }\r\n\r\n setQuality(index: number) {\r\n this.store.setState({ currentQuality: index });\r\n this.events.emit('quality-request', index);\r\n }\r\n\r\n setAudioTrack(index: number) {\r\n this.store.setState({ currentAudioTrack: index });\r\n this.events.emit('audio-track-request', index);\r\n }\r\n\r\n setControlsVisible(visible: boolean) {\r\n if (this.store.get().controlsVisible !== visible) {\r\n this.store.setState({ controlsVisible: visible });\r\n this.emit('control', visible);\r\n }\r\n }\r\n\r\n async toggleFullscreen() {\r\n if (!this.container) return;\r\n\r\n // 1. If currently native fullscreen, exit it.\r\n if (document.fullscreenElement) {\r\n await document.exitFullscreen().catch(() => { });\r\n // Orientation lock handled in event listener\r\n return;\r\n }\r\n\r\n // 2. If currently web fullscreen, toggle it off.\r\n if (this.store.get().isWebFullscreen) {\r\n this.toggleWebFullscreen();\r\n return;\r\n }\r\n\r\n // 3. Try to enter native fullscreen.\r\n try {\r\n await this.container.requestFullscreen();\r\n // Orientation lock handled in boundFullscreenChange\r\n } catch (err) {\r\n // 4. Fallback: If native fails (e.g. inside restrictive iframe), force Web Fullscreen.\r\n // This ensures the user gets a fullscreen-like experience regardless of browser limitations.\r\n console.warn('Native fullscreen failed, falling back to Web Fullscreen', err);\r\n this.toggleWebFullscreen();\r\n }\r\n }\r\n\r\n toggleWebFullscreen() {\r\n const isWebFs = this.store.get().isWebFullscreen;\r\n\r\n // If native fullscreen is active, exit it first to avoid conflicts\r\n if (document.fullscreenElement) {\r\n document.exitFullscreen().catch(() => { });\r\n }\r\n\r\n const newState = !isWebFs;\r\n this.store.setState({ isWebFullscreen: newState });\r\n\r\n // Lock body scroll when in web fullscreen\r\n if (typeof document !== 'undefined') {\r\n document.body.style.overflow = newState ? 'hidden' : '';\r\n }\r\n\r\n this.emit('webfullscreen', newState);\r\n }\r\n\r\n togglePip() {\r\n if (document.pictureInPictureElement) {\r\n document.exitPictureInPicture();\r\n } else if (this.video !== document.pictureInPictureElement && (this.video as any).requestPictureInPicture) {\r\n (this.video as any).requestPictureInPicture();\r\n }\r\n }\r\n\r\n screenshot() {\r\n const canvas = document.createElement('canvas');\r\n canvas.width = this.video.videoWidth;\r\n canvas.height = this.video.videoHeight;\r\n const ctx = canvas.getContext('2d');\r\n if (ctx) {\r\n ctx.drawImage(this.video, 0, 0, canvas.width, canvas.height);\r\n try {\r\n const url = canvas.toDataURL('image/png');\r\n const a = document.createElement('a');\r\n a.download = `screenshot-${new Date().toISOString()}.png`;\r\n a.href = url;\r\n a.click();\r\n this.notify({ type: 'success', message: 'Screenshot saved', duration: 2000 });\r\n } catch (e) {\r\n this.notify({ type: 'error', message: 'Failed to take screenshot', duration: 3000 });\r\n }\r\n }\r\n }\r\n\r\n toggleLock() {\r\n this.store.setState((prev) => ({ isLocked: !prev.isLocked }));\r\n }\r\n\r\n toggleLoop() {\r\n this.video.loop = !this.video.loop;\r\n this.store.setState({ isLooping: this.video.loop });\r\n this.notify({ type: 'info', message: `Loop: ${this.video.loop ? 'On' : 'Off'}`, duration: 1500 });\r\n }\r\n\r\n setFlip(direction: 'horizontal' | 'vertical') {\r\n const current = this.store.get().flipState;\r\n const newState = {\r\n ...current,\r\n [direction]: !current[direction]\r\n };\r\n this.store.setState({ flipState: newState });\r\n\r\n const scaleX = newState.horizontal ? -1 : 1;\r\n const scaleY = newState.vertical ? -1 : 1;\r\n this.video.style.transform = `scale(${scaleX}, ${scaleY})`;\r\n }\r\n\r\n setAspectRatio(ratio: string) {\r\n this.store.setState({ aspectRatio: ratio });\r\n this.updateAspectRatio();\r\n\r\n if (ratio !== 'default') {\r\n this.notify({ type: 'info', message: `Aspect Ratio: ${ratio}`, duration: 2000 });\r\n }\r\n }\r\n\r\n setVideoFit(fit: VideoFit) {\r\n this.store.setState({ videoFit: fit });\r\n this.video.style.objectFit = fit;\r\n // We also re-trigger aspect ratio calculation as it depends on container/video sizes\r\n this.updateAspectRatio();\r\n }\r\n\r\n setBrightness(val: number) {\r\n const safe = Math.max(0, Math.min(val, 2)); // Cap at 200%\r\n this.store.setState({ brightness: safe });\r\n this.video.style.filter = `brightness(${safe})`;\r\n }\r\n\r\n private updateAspectRatio() {\r\n if (!this.container) return;\r\n const { aspectRatio, videoFit } = this.store.get();\r\n\r\n if (aspectRatio === 'default') {\r\n this.video.style.width = '100%';\r\n this.video.style.height = '100%';\r\n this.video.style.objectFit = videoFit;\r\n return;\r\n }\r\n\r\n const [w, h] = aspectRatio.split(':').map(Number);\r\n if (!w || !h) return;\r\n\r\n const targetRatio = w / h;\r\n const rect = this.container.getBoundingClientRect();\r\n if (rect.width === 0 || rect.height === 0) return;\r\n\r\n const containerRatio = rect.width / rect.height;\r\n\r\n let finalW, finalH;\r\n\r\n // To maintain aspect ratio completely visible within container but stretched to fill that ratio\r\n // We size the box to the largest rectangle of targetRatio that fits in container.\r\n if (containerRatio > targetRatio) {\r\n // Container is wider (e.g. 21:9 container, 16:9 video)\r\n // Video height = container height. Video width = height * ratio.\r\n finalH = rect.height;\r\n finalW = finalH * targetRatio;\r\n } else {\r\n // Container is narrower (e.g. 4:3 container, 16:9 video)\r\n // Video width = container width. Video height = width / ratio.\r\n finalW = rect.width;\r\n finalH = finalW / targetRatio;\r\n }\r\n\r\n this.video.style.width = `${finalW}px`;\r\n this.video.style.height = `${finalH}px`;\r\n this.video.style.objectFit = 'fill'; // When forcing aspect ratio box, we usually want fill\r\n }\r\n\r\n private initCast() {\r\n const w = window as any;\r\n const initializeCastApi = () => {\r\n if (this.castInitialized) return;\r\n try {\r\n if (w.cast && w.cast.framework && w.chrome && w.chrome.cast) {\r\n const CastContext = w.cast.framework.CastContext;\r\n CastContext.getInstance().setOptions({\r\n receiverApplicationId: w.chrome.cast.media.DEFAULT_MEDIA_RECEIVER_APP_ID,\r\n autoJoinPolicy: w.chrome.cast.AutoJoinPolicy.ORIGIN_SCOPED\r\n });\r\n this.castInitialized = true;\r\n }\r\n } catch (e) {\r\n console.warn('Cast Init Error or already initialized', e);\r\n }\r\n };\r\n\r\n if (w.cast && w.cast.framework) {\r\n initializeCastApi();\r\n } else {\r\n w.__onGCastApiAvailable = (isAvailable: boolean) => {\r\n if (isAvailable) initializeCastApi();\r\n };\r\n }\r\n }\r\n\r\n requestCast() {\r\n const w = window as any;\r\n if (w.cast && w.cast.framework) {\r\n try {\r\n if (!this.castInitialized) this.initCast();\r\n w.cast.framework.CastContext.getInstance().requestSession()\r\n .then(() => {\r\n this.loadMediaToCast();\r\n })\r\n .catch((e: any) => {\r\n if (e !== 'cancel') this.notify({ type: 'error', message: 'Cast failed: ' + e, duration: 3000 });\r\n });\r\n } catch (e) {\r\n this.notify({ type: 'warning', message: 'Cast not available yet', duration: 3000 });\r\n }\r\n } else {\r\n this.notify({ type: 'warning', message: 'Cast API not loaded', duration: 3000 });\r\n }\r\n }\r\n\r\n private loadMediaToCast() {\r\n const w = window as any;\r\n try {\r\n const castSession = w.cast.framework.CastContext.getInstance().getCurrentSession();\r\n if (!castSession) return;\r\n const mediaInfo = new w.chrome.cast.media.MediaInfo(this.currentSrc, this.currentSrc.includes('.m3u8') ? 'application/x-mpegurl' : 'video/mp4');\r\n const request = new w.chrome.cast.media.LoadRequest(mediaInfo);\r\n castSession.loadMedia(request).then(() => {\r\n this.notify({ type: 'success', message: 'Casting...', duration: 3000 });\r\n }).catch((e: any) => console.error('Cast load error', e));\r\n } catch (e) {\r\n console.error(\"Failed to load media into Cast session\", e);\r\n }\r\n }\r\n\r\n private handleCueChange() {\r\n const state = this.store.get();\r\n if (state.currentSubtitle === -1) {\r\n this.store.setState({ activeCues: [] });\r\n return;\r\n }\r\n\r\n // Find active track in DOM\r\n const tracks = Array.from(this.video.textTracks).filter(t => t.kind === 'subtitles' || t.kind === 'captions');\r\n // We need to match the DOM track with our state index.\r\n // Since we only add tracks that are \"loaded\", the index in DOM matches the filter of loaded tracks in our state.\r\n // However, simplest is to look for the track with mode='showing'.\r\n const activeTrack = tracks.find(t => t.mode === 'showing' || t.mode === 'hidden'); // Hidden is used for custom render\r\n\r\n if (activeTrack && activeTrack.activeCues) {\r\n const cues = Array.from(activeTrack.activeCues).map((c: any) => c.text);\r\n this.store.setState({ activeCues: cues });\r\n } else {\r\n this.store.setState({ activeCues: [] });\r\n }\r\n }\r\n\r\n async setSubtitle(index: number) {\r\n const state = this.store.get();\r\n const targetTrack = state.subtitleTracks[index];\r\n\r\n // 1. Disable all current tracks\r\n Array.from(this.video.textTracks).forEach(t => {\r\n t.removeEventListener('cuechange', this.boundCueChange);\r\n t.mode = 'disabled'; // Use disabled to stop fetching/processing events for unused tracks\r\n });\r\n this.store.setState({ currentSubtitle: index, subtitleOffset: 0, activeCues: [] });\r\n\r\n if (index === -1) return;\r\n if (!targetTrack) return;\r\n\r\n // 2. Check if loaded. If not, fetch it.\r\n if (targetTrack.status === 'idle' || targetTrack.status === 'error') {\r\n this.updateSubtitleTrackState(index, { status: 'loading' });\r\n\r\n try {\r\n // Fetch blob to ensure valid response and handle CORS if needed\r\n const response = await this.fetchWithRetry(targetTrack.src);\r\n let text = await response.text();\r\n\r\n // Auto-convert SRT to VTT if needed\r\n text = this.convertToVTT(text);\r\n\r\n // Convert to Blob for safe addition (fixes some CORS issues with native track element)\r\n const blob = new Blob([text], { type: 'text/vtt' });\r\n const blobUrl = URL.createObjectURL(blob);\r\n\r\n // Add to DOM\r\n // Don't set isDefault here to avoid browser auto-enabling it before we set the correct mode\r\n this.addTextTrackInternal(blobUrl, targetTrack.label, targetTrack.srcLang, false);\r\n this.updateSubtitleTrackState(index, { status: 'success' });\r\n } catch (e) {\r\n this.updateSubtitleTrackState(index, { status: 'error' });\r\n console.error(\"Failed to load subtitle\", e);\r\n return;\r\n }\r\n }\r\n\r\n // 3. Enable the track in DOM\r\n // We find the track by label/srclang since DOM index might vary\r\n // If multiple tracks match, we try to use the one that is currently disabled (not active) or just the last one added\r\n const domTracks = Array.from(this.video.textTracks);\r\n\r\n // Robust finding: prefer matching label AND lang, fallback to label only\r\n let track = domTracks.find(t => t.label === targetTrack.label && t.language === targetTrack.srcLang);\r\n if (!track) {\r\n track = domTracks.find(t => t.label === targetTrack.label);\r\n }\r\n\r\n if (track) {\r\n const settings = this.store.get().subtitleSettings;\r\n track.mode = settings.useNative ? 'showing' : 'hidden';\r\n track.addEventListener('cuechange', this.boundCueChange);\r\n this.handleCueChange();\r\n }\r\n }\r\n\r\n updateSubtitleSettings(settings: Partial<SubtitleSettings>) {\r\n const current = this.store.get().subtitleSettings;\r\n const newSettings = { ...current, ...settings };\r\n this.store.setState({ subtitleSettings: newSettings });\r\n\r\n // If switching native/custom, re-apply track mode\r\n if (settings.useNative !== undefined) {\r\n // Re-trigger setSubtitle to apply correct mode (hidden vs showing)\r\n // We don't need to re-fetch since status is already success\r\n const idx = this.store.get().currentSubtitle;\r\n if (idx !== -1) {\r\n // Find active track and update mode directly\r\n const state = this.store.get();\r\n const target = state.subtitleTracks[idx];\r\n const track = Array.from(this.video.textTracks).find(t => t.label === target.label && t.language === target.srcLang);\r\n if (track) {\r\n track.mode = settings.useNative ? 'showing' : 'hidden';\r\n }\r\n }\r\n }\r\n }\r\n\r\n resetSubtitleSettings() {\r\n this.store.setState({ subtitleSettings: DEFAULT_SUBTITLE_SETTINGS });\r\n this.updateSubtitleSettings({ useNative: false }); // Trigger mode update\r\n }\r\n\r\n setSubtitleOffset(offset: number) {\r\n const currentOffset = this.store.get().subtitleOffset;\r\n const delta = offset - currentOffset;\r\n\r\n if (Math.abs(delta) < 0.001) return;\r\n\r\n Array.from(this.video.textTracks).forEach((track) => {\r\n // If custom (hidden) or native (showing), we adjust cues\r\n if ((track.mode === 'showing' || track.mode === 'hidden') && track.cues) {\r\n Array.from(track.cues).forEach((cue: any) => {\r\n cue.startTime += delta;\r\n cue.endTime += delta;\r\n });\r\n }\r\n });\r\n\r\n this.store.setState({ subtitleOffset: offset });\r\n this.notify({ type: 'info', message: `Subtitle Offset: ${offset > 0 ? '+' : ''}${offset.toFixed(1)}s`, duration: 1500 });\r\n }\r\n\r\n cancelDownload(id?: string) {\r\n if (id && this.activeDownloads.has(id)) {\r\n this.activeDownloads.get(id)?.abort();\r\n this.activeDownloads.delete(id);\r\n this.notify({ type: 'info', message: 'Download cancelled', duration: 2000 });\r\n this.removeNotification(id);\r\n } else if (!id) {\r\n // Legacy/Fallback: cancel all\r\n if (this.activeDownloads.size > 0) {\r\n this.activeDownloads.forEach(c => c.abort());\r\n this.activeDownloads.clear();\r\n this.notify({ type: 'info', message: 'All downloads cancelled', duration: 2000 });\r\n }\r\n }\r\n }\r\n\r\n async download(options: { format?: 'ts' | 'mp4' } = {}) {\r\n // Prefer the original source URL if available, as video.src might be a blob (MSE)\r\n const src = this.currentSource?.url || this.video.src;\r\n if (!src) return;\r\n\r\n // 1. Handle HLS or DASH explicitly if current source type matches\r\n // We check both the URL extension and the explicit type from the source config\r\n if (src.includes('.m3u8') || this.currentSource?.type === 'hls') {\r\n this.downloadHls(src, options.format || 'ts');\r\n return;\r\n }\r\n\r\n if (src.startsWith('blob:')) {\r\n this.notify({ type: 'warning', message: 'Stream download not supported in browser.', duration: 4000 });\r\n return;\r\n }\r\n\r\n const notifId = Math.random().toString(36).substr(2, 9);\r\n const controller = new AbortController();\r\n this.activeDownloads.set(notifId, controller);\r\n const signal = controller.signal;\r\n\r\n this.notify({\r\n id: notifId,\r\n type: 'loading',\r\n message: 'Preparing download',\r\n progress: 0,\r\n action: {\r\n label: 'Cancel',\r\n onClick: () => this.cancelDownload(notifId)\r\n }\r\n });\r\n\r\n try {\r\n const response = await this.fetchWithRetry(src, 3, undefined, signal);\r\n if (!response.body) throw new Error('No body');\r\n const reader = response.body.getReader();\r\n const contentLength = response.headers.get('Content-Length');\r\n const total = contentLength ? parseInt(contentLength, 10) : 0;\r\n let loaded = 0;\r\n const chunks = [];\r\n const startTime = Date.now();\r\n\r\n // Sliding window for smoothing speed: Store [timestamp, totalLoaded]\r\n const progressSamples: { time: number, loaded: number }[] = [];\r\n let lastUpdate = 0;\r\n\r\n while (true) {\r\n const { done, value } = await reader.read();\r\n if (done) break;\r\n chunks.push(value);\r\n loaded += value.length;\r\n if (total) {\r\n const now = Date.now();\r\n\r\n // Debounce updates: update every 800ms or if complete\r\n if (now - lastUpdate > 800 || loaded === total) {\r\n lastUpdate = now;\r\n const percent = Math.round((loaded / total) * 100);\r\n\r\n // Add sample\r\n progressSamples.push({ time: now, loaded });\r\n\r\n // Remove samples older than 5 seconds\r\n while (progressSamples.length > 0 && now - progressSamples[0].time > 5000) {\r\n progressSamples.shift();\r\n }\r\n\r\n let etaSuffix = '';\r\n\r\n // Calculate speed based on sliding window\r\n let rate = 0; // bytes per ms\r\n\r\n if (progressSamples.length > 1) {\r\n const oldest = progressSamples[0];\r\n const newest = progressSamples[progressSamples.length - 1];\r\n const timeDiff = newest.time - oldest.time;\r\n const bytesDiff = newest.loaded - oldest.loaded;\r\n if (timeDiff > 0) rate = bytesDiff / timeDiff;\r\n } else {\r\n // Fallback to overall average if not enough samples\r\n const elapsed = now - startTime;\r\n if (elapsed > 0) rate = loaded / elapsed;\r\n }\r\n\r\n if (rate > 0) {\r\n const remaining = total - loaded;\r\n const etaMs = remaining / rate;\r\n // Format with newline for visibility\r\n etaSuffix = `\\n${this.formatDuration(etaMs)} remaining`;\r\n }\r\n\r\n this.notify({\r\n id: notifId,\r\n type: 'loading',\r\n // Cleaned string\r\n message: `${etaSuffix}`,\r\n progress: percent,\r\n action: {\r\n label: 'Cancel',\r\n onClick: () => this.cancelDownload(notifId)\r\n }\r\n });\r\n }\r\n }\r\n }\r\n const blob = new Blob(chunks);\r\n const url = window.URL.createObjectURL(blob);\r\n const a = document.createElement('a');\r\n a.style.display = 'none';\r\n a.href = url;\r\n a.download = src.split('/').pop()?.split('?')[0] || 'video.mp4';\r\n document.body.appendChild(a);\r\n a.click();\r\n window.URL.revokeObjectURL(url);\r\n document.body.removeChild(a);\r\n this.notify({ id: notifId, type: 'success', message: 'Saved!', duration: 3000 });\r\n } catch (e: any) {\r\n if (signal.aborted) {\r\n this.removeNotification(notifId); // Handled by cancelDownload notify usually, but ensure cleanup\r\n } else {\r\n this.notify({ id: notifId, type: 'error', message: 'Download failed.', duration: 4000 });\r\n // Fallback\r\n window.open(src, '_blank');\r\n }\r\n } finally {\r\n this.activeDownloads.delete(notifId);\r\n }\r\n }\r\n\r\n async downloadHls(url: string, format: 'ts' | 'mp4') {\r\n const notifId = Math.random().toString(36).substr(2, 9);\r\n const controller = new AbortController();\r\n this.activeDownloads.set(notifId, controller);\r\n const signal = controller.signal;\r\n\r\n this.notify({\r\n id: notifId,\r\n type: 'loading',\r\n message: 'Analyzing HLS stream',\r\n progress: 0,\r\n action: { label: 'Cancel', onClick: () => this.cancelDownload(notifId) }\r\n });\r\n\r\n try {\r\n // 1. Fetch Playlist\r\n let response = await this.fetchWithRetry(url, 3, undefined, signal);\r\n let content = await response.text();\r\n let baseUrl = url.substring(0, url.lastIndexOf('/') + 1);\r\n\r\n // 2. Check for Master Playlist\r\n if (content.includes('#EXT-X-STREAM-INF')) {\r\n this.notify({ id: notifId, type: 'loading', message: 'Selecting best quality', progress: 0 }); // Removed ...\r\n // Parse variants\r\n const lines = content.split('\\n');\r\n let bestBandwidth = 0;\r\n let bestUrl = '';\r\n for (let i = 0; i < lines.length; i++) {\r\n if (lines[i].includes('#EXT-X-STREAM-INF')) {\r\n const bandwidthMatch = lines[i].match(/BANDWIDTH=(\\d+)/);\r\n if (bandwidthMatch) {\r\n const bandwidth = parseInt(bandwidthMatch[1]);\r\n // Next line is URL\r\n let nextLine = lines[i + 1]?.trim();\r\n if (nextLine && !nextLine.startsWith('#')) {\r\n if (bandwidth > bestBandwidth) {\r\n bestBandwidth = bandwidth;\r\n bestUrl = nextLine;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (bestUrl) {\r\n // Handle relative URL\r\n if (!bestUrl.startsWith('http')) {\r\n bestUrl = baseUrl + bestUrl;\r\n }\r\n // Fetch best variant playlist\r\n response = await this.fetchWithRetry(bestUrl, 3, undefined, signal);\r\n content = await response.text();\r\n baseUrl = bestUrl.substring(0, bestUrl.lastIndexOf('/') + 1);\r\n }\r\n }\r\n\r\n // 3. Parse Segments\r\n if (content.includes('#EXT-X-KEY')) {\r\n throw new Error('Encrypted HLS streams are not supported for download.');\r\n }\r\n\r\n const lines = content.split('\\n');\r\n const segments: string[] = [];\r\n for (let line of lines) {\r\n line = line.trim();\r\n if (line && !line.startsWith('#')) {\r\n if (!line.startsWith('http')) {\r\n segments.push(baseUrl + line);\r\n } else {\r\n segments.push(line);\r\n }\r\n }\r\n }\r\n\r\n if (segments.length === 0) throw new Error('No segments found.');\r\n\r\n // 4. Determine Output Format\r\n let extension = format === 'mp4' ? 'mp4' : 'ts';\r\n let mime = format === 'mp4' ? 'video/mp4' : 'video/mp2t';\r\n\r\n // 5. Setup Writer (File System API or Memory)\r\n let fileHandle: any = null;\r\n let writable: any = null;\r\n let memoryBlobs: Blob[] = [];\r\n const useFileSystem = 'showSaveFilePicker' in window;\r\n\r\n if (useFileSystem) {\r\n try {\r\n // @ts-ignore\r\n fileHandle = await window.showSaveFilePicker({\r\n suggestedName: `video.${extension}`,\r\n types: [{\r\n description: format === 'mp4' ? 'MPEG-4 Video' : 'MPEG Transport Stream',\r\n accept: { [mime]: [`.${extension}`] },\r\n }],\r\n });\r\n writable = await fileHandle.createWritable();\r\n } catch (e: any) {\r\n if (e.name === 'AbortError') {\r\n this.removeNotification(notifId);\r\n this.notify({ type: 'info', message: 'Download cancelled', duration: 2000 });\r\n this.activeDownloads.delete(notifId);\r\n return;\r\n }\r\n // User cancelled or not supported, fallback to memory\r\n console.warn('File System API cancelled or failed, falling back to memory', e);\r\n }\r\n }\r\n\r\n // 6. Download Loop\r\n let isTsContent = false;\r\n const startTime = Date.now();\r\n\r\n // Sliding window for segment processing speed\r\n const segmentSamples: { time: number, count: number }[] = [];\r\n let lastUpdate = 0;\r\n\r\n for (let i = 0; i < segments.length; i++) {\r\n if (signal.aborted) break;\r\n\r\n const now = Date.now();\r\n // Debounce: update every 800ms or first/last segment\r\n if (now - lastUpdate > 800 || i === 0 || i === segments.length - 1) {\r\n lastUpdate = now;\r\n const progress = Math.round(((i + 1) / segments.length) * 100);\r\n\r\n // Add sample\r\n segmentSamples.push({ time: now, count: i + 1 });\r\n\r\n // Remove samples older than 5 seconds\r\n while (segmentSamples.length > 0 && now - segmentSamples[0].time > 5000) {\r\n segmentSamples.shift();\r\n }\r\n\r\n let etaSuffix = '';\r\n\r\n if (segmentSamples.length > 1) {\r\n const oldest = segmentSamples[0];\r\n const newest = segmentSamples[segmentSamples.length - 1];\r\n const timeDiff = newest.time - oldest.time;\r\n const countDiff = newest.count - oldest.count;\r\n\r\n if (timeDiff > 0 && countDiff > 0) {\r\n const msPerSegment = timeDiff / countDiff;\r\n const remainingSegments = segments.length - (i + 1);\r\n const etaMs = remainingSegments * msPerSegment;\r\n etaSuffix = `\\n${this.formatDuration(etaMs)} remaining`;\r\n }\r\n } else if (i > 0) {\r\n // Fallback\r\n const elapsed = now - startTime;\r\n const avgTime = elapsed / i;\r\n const remaining = segments.length - i;\r\n const etaMs = remaining * avgTime;\r\n etaSuffix = `\\n${this.formatDuration(etaMs)} remaining`;\r\n }\r\n\r\n this.notify({\r\n id: notifId,\r\n type: 'loading',\r\n // Cleaned string\r\n message: `Downloading segment ${i + 1}/${segments.length}${etaSuffix}`,\r\n progress: progress,\r\n action: { label: 'Cancel', onClick: () => this.cancelDownload(notifId) }\r\n });\r\n }\r\n\r\n const segRes = await this.fetchWithRetry(segments[i], 3, undefined, signal);\r\n const buffer = await segRes.arrayBuffer();\r\n\r\n // 7. Check content type on first segment\r\n if (i === 0) {\r\n const bytes = new Uint8Array(buffer.slice(0, 4));\r\n // TS Sync Byte is 0x47\r\n if (bytes[0] === 0x47) {\r\n isTsContent = true;\r\n if (format === 'mp4') {\r\n this.notify({\r\n type: 'info',\r\n message: 'Stream is MPEG-TS. Downloading as .ts to prevent corruption.',\r\n duration: 5000\r\n });\r\n // Fallback to TS extension if we can't transmux\r\n // If using File System API, filename is already set, so we just write raw bytes\r\n // Ideally we should warn BEFORE saving but here we just process.\r\n extension = 'ts';\r\n mime = 'video/mp2t';\r\n }\r\n }\r\n }\r\n\r\n const blob = new Blob([buffer]);\r\n if (writable) {\r\n await writable.write(blob);\r\n } else {\r\n memoryBlobs.push(blob);\r\n }\r\n }\r\n\r\n if (signal.aborted) {\r\n if (writable) await writable.abort();\r\n throw new Error('Aborted');\r\n }\r\n\r\n if (writable) {\r\n await writable.close();\r\n this.notify({ id: notifId, type: 'success', message: 'Download complete!', duration: 3000 });\r\n } else {\r\n // Combine blobs and download\r\n this.notify({ id: notifId, type: 'loading', message: 'Stitching video', progress: 100 }); // Removed ...\r\n const finalBlob = new Blob(memoryBlobs, { type: mime });\r\n const url = window.URL.createObjectURL(finalBlob);\r\n const a = document.createElement('a');\r\n a.style.display = 'none';\r\n a.href = url;\r\n // If content was TS but requested MP4, fallback extension\r\n const finalExt = (format === 'mp4' && isTsContent) ? 'ts' : extension;\r\n a.download = `video.${finalExt}`;\r\n document.body.appendChild(a);\r\n a.click();\r\n window.URL.revokeObjectURL(url);\r\n document.body.removeChild(a);\r\n this.notify({ id: notifId, type: 'success', message: 'Saved!', duration: 3000 });\r\n }\r\n\r\n } catch (e: any) {\r\n if (signal.aborted) {\r\n this.removeNotification(notifId);\r\n } else {\r\n this.notify({ id: notifId, type: 'error', message: `Download failed: ${e.message}`, duration: 4000 });\r\n }\r\n } finally {\r\n this.activeDownloads.delete(notifId);\r\n }\r\n }\r\n\r\n notify(n: Omit<Notification, 'id'> & { id?: string }) {\r\n const id = n.id || Math.random().toString(36).substr(2, 9);\r\n const newNotification: Notification = { ...n, id };\r\n\r\n // If update, replace. If new, append.\r\n this.store.setState(prev => {\r\n const exists = prev.notifications.find(existing => existing.id === id);\r\n if (exists) {\r\n return { notifications: prev.notifications.map(existing => existing.id === id ? newNotification : existing) };\r\n }\r\n return { notifications: [...prev.notifications, newNotification] };\r\n });\r\n\r\n if (n.duration) setTimeout(() => this.removeNotification(id), n.duration);\r\n return id;\r\n }\r\n\r\n removeNotification(id: string) {\r\n const current = this.store.get().notifications;\r\n this.store.setState({ notifications: current.filter(n => n.id !== id) });\r\n }\r\n\r\n setAppearance(settings: { iconSize?: 'small' | 'medium' | 'large', themeColor?: string, theme?: PlayerTheme }) {\r\n this.store.setState(prev => ({\r\n ...prev,\r\n ...settings\r\n }));\r\n }\r\n\r\n destroy() {\r\n if (this.retryTimer) clearTimeout(this.retryTimer);\r\n if (this.resizeObserver) {\r\n this.resizeObserver.disconnect();\r\n this.resizeObserver = null;\r\n }\r\n // Cancel all downloads\r\n this.activeDownloads.forEach(c => c.abort());\r\n this.activeDownloads.clear();\r\n\r\n // Clean up web fullscreen scroll lock if active\r\n if (this.store.get().isWebFullscreen && typeof document !== 'undefined') {\r\n document.body.style.overflow = '';\r\n }\r\n\r\n document.removeEventListener('fullscreenchange', this.boundFullscreenChange);\r\n this.video.pause();\r\n this.video.src = '';\r\n const oldTracks = this.video.getElementsByTagName('track');\r\n while (oldTracks.length > 0) oldTracks[0].remove();\r\n this.emit('destroy');\r\n this.events.destroy();\r\n this.store.destroy();\r\n this.plugins.forEach(p => p.destroy && p.destroy());\r\n this.plugins.clear();\r\n this.video.remove();\r\n this.audioEngine.destroy();\r\n }\r\n}\r\n","\r\nimport { useState, useEffect } from 'react';\r\n\r\n// Hook to manage CSS transitions for mounting/unmounting\r\nexport const useTransition = (isActive: boolean, duration: number = 200) => {\r\n const [isMounted, setIsMounted] = useState(isActive);\r\n const [isVisible, setIsVisible] = useState(false);\r\n\r\n useEffect(() => {\r\n if (isActive) {\r\n setIsMounted(true);\r\n // Double RAF ensures the browser paints the initial state before applying the active state\r\n requestAnimationFrame(() => {\r\n requestAnimationFrame(() => {\r\n setIsVisible(true);\r\n });\r\n });\r\n } else {\r\n setIsVisible(false);\r\n const timer = setTimeout(() => {\r\n setIsMounted(false);\r\n }, duration);\r\n return () => clearTimeout(timer);\r\n }\r\n }, [isActive, duration]);\r\n\r\n return { isMounted, isVisible };\r\n};\r\n","import React from \"react\";\r\n\r\n// Base SVG Wrapper matching Lucide defaults\r\nconst Icon = ({\r\n className,\r\n children,\r\n fill = \"none\",\r\n strokeWidth = 2,\r\n viewBox = \"0 0 24 24\",\r\n}: {\r\n className?: string;\r\n children: React.ReactNode;\r\n fill?: string;\r\n strokeWidth?: number;\r\n viewBox?: string;\r\n}) => (\r\n <svg\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n viewBox={viewBox}\r\n fill={fill}\r\n stroke=\"currentColor\"\r\n strokeWidth={strokeWidth}\r\n strokeLinecap=\"round\"\r\n strokeLinejoin=\"round\"\r\n className={className}\r\n >\r\n {children}\r\n </svg>\r\n);\r\n\r\nexport const PlayIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"5 3 19 12 5 21 5 3\" />\r\n </Icon>\r\n);\r\n\r\nexport const PauseIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"4\" height=\"16\" x=\"6\" y=\"4\" rx=\"1\" />\r\n <rect width=\"4\" height=\"16\" x=\"14\" y=\"4\" rx=\"1\" />\r\n </Icon>\r\n);\r\n\r\nexport const VolumeHighIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\r\n <path d=\"M19.07 4.93a10 10 0 0 1 0 14.14\" />\r\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\r\n </Icon>\r\n);\r\n\r\nexport const VolumeLowIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\r\n <path d=\"M15.54 8.46a5 5 0 0 1 0 7.07\" />\r\n </Icon>\r\n);\r\n\r\nexport const VolumeMuteIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"11 5 6 9 2 9 2 15 6 15 11 19 11 5\" />\r\n <line x1=\"23\" x2=\"17\" y1=\"9\" y2=\"15\" />\r\n <line x1=\"17\" x2=\"23\" y1=\"9\" y2=\"15\" />\r\n </Icon>\r\n);\r\n\r\nexport const MaximizeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M8 3H5a2 2 0 0 0-2 2v3\" />\r\n <path d=\"M21 8V5a2 2 0 0 0-2-2h-3\" />\r\n <path d=\"M3 16v3a2 2 0 0 0 2 2h3\" />\r\n <path d=\"M16 21h3a2 2 0 0 0 2-2v-3\" />\r\n </Icon>\r\n);\r\n\r\nexport const MinimizeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M8 3v3a2 2 0 0 1-2 2H3\" />\r\n <path d=\"M21 8h-3a2 2 0 0 1-2-2V3\" />\r\n <path d=\"M3 16h3a2 2 0 0 1 2 2v3\" />\r\n <path d=\"M16 21v-3a2 2 0 0 1 2-2h3\" />\r\n </Icon>\r\n);\r\n\r\nexport const SettingsIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.09a2 2 0 0 1-1-1.74v-.47a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const CheckIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M20 6 9 17l-5-5\" />\r\n </Icon>\r\n);\r\n\r\nexport const PipIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 9V6a2 2 0 0 0-2-2H4a2 2 0 0 0-2 2v10c0 1.1.9 2 2 2h4\" />\r\n <rect x=\"12\" y=\"13\" width=\"10\" height=\"7\" rx=\"2\" />\r\n </Icon>\r\n);\r\n\r\nexport const SubtitleIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"18\" height=\"14\" x=\"3\" y=\"5\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M7 15h4\" />\r\n <path d=\"M15 15h2\" />\r\n <path d=\"M7 11h2\" />\r\n <path d=\"M13 11h4\" />\r\n </Icon>\r\n);\r\n\r\nexport const DownloadIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"7 10 12 15 17 10\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"15\" y2=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const UploadIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4\" />\r\n <polyline points=\"17 8 12 3 7 8\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"3\" y2=\"15\" />\r\n </Icon>\r\n);\r\n\r\nexport const ArrowLeftIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m12 19-7-7 7-7\" />\r\n <path d=\"M19 12H5\" />\r\n </Icon>\r\n);\r\n\r\nexport const LoaderIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\r\n </Icon>\r\n);\r\n\r\nexport const CastIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M2 16.1A5 5 0 0 1 5.9 20\" />\r\n <path d=\"M2 12.05A9 9 0 0 1 9.95 20\" />\r\n <path d=\"M2 8V6a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2h-6\" />\r\n <line x1=\"2\" x2=\"2.01\" y1=\"20\" y2=\"20\" />\r\n </Icon>\r\n);\r\n\r\nexport const UsersIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2\" />\r\n <circle cx=\"9\" cy=\"7\" r=\"4\" />\r\n <path d=\"M22 21v-2a4 4 0 0 0-3-3.87\" />\r\n <path d=\"M16 3.13a4 4 0 0 1 0 7.75\" />\r\n </Icon>\r\n);\r\n\r\nexport const ClockIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <polyline points=\"12 6 12 12 16 14\" />\r\n </Icon>\r\n);\r\n\r\nexport const MinusIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M5 12h14\" />\r\n </Icon>\r\n);\r\n\r\nexport const PlusIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M5 12h14\" />\r\n <path d=\"M12 5v14\" />\r\n </Icon>\r\n);\r\n\r\nexport const CustomizeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M4 21v-7\" />\r\n <path d=\"M4 10V3\" />\r\n <path d=\"M12 21v-9\" />\r\n <path d=\"M12 8V3\" />\r\n <path d=\"M20 21v-5\" />\r\n <path d=\"M20 12V3\" />\r\n <path d=\"M1 14h6\" />\r\n <path d=\"M9 8h6\" />\r\n <path d=\"M17 16h6\" />\r\n </Icon>\r\n);\r\n\r\nexport const TypeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polyline points=\"4 7 4 4 20 4 20 7\" />\r\n <line x1=\"9\" x2=\"15\" y1=\"20\" y2=\"20\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"4\" y2=\"20\" />\r\n </Icon>\r\n);\r\n\r\nexport const PaletteIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"13.5\" cy=\"6.5\" r=\".5\" fill=\"currentColor\" />\r\n <circle cx=\"17.5\" cy=\"10.5\" r=\".5\" fill=\"currentColor\" />\r\n <circle cx=\"8.5\" cy=\"7.5\" r=\".5\" fill=\"currentColor\" />\r\n <circle cx=\"6.5\" cy=\"12.5\" r=\".5\" fill=\"currentColor\" />\r\n <path d=\"M12 2C6.5 2 2 6.5 2 12s4.5 10 10 10c.926 0 1.648-.746 1.648-1.688 0-.437-.18-.835-.437-1.125-.29-.289-.438-.652-.438-1.125a1.64 1.64 0 0 1 1.668-1.668h1.996c3.051 0 5.555-2.503 5.555-5.554C21.965 6.012 17.461 2 12 2z\" />\r\n </Icon>\r\n);\r\n\r\nexport const EyeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M2 12s3-7 10-7 10 7 10 7-3 7-10 7-10-7-10-7Z\" />\r\n <circle cx=\"12\" cy=\"12\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const MoveVerticalIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polyline points=\"8 18 12 22 16 18\" />\r\n <polyline points=\"8 6 12 2 16 6\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"2\" y2=\"22\" />\r\n </Icon>\r\n);\r\n\r\nexport const ResetIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\r\n <path d=\"M3 3v5h5\" />\r\n </Icon>\r\n);\r\n\r\nexport const BoldIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M6 4h8a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\r\n <path d=\"M6 12h9a4 4 0 0 1 4 4 4 4 0 0 1-4 4H6z\" />\r\n </Icon>\r\n);\r\n\r\nexport const CaseUpperIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m3 17 4-10 4 10\" />\r\n <path d=\"M4 13h6\" />\r\n <path d=\"M15 12h4.5a2.5 2.5 0 0 1 0 5H15V7h4a2.5 2.5 0 0 1 0 5h-4\" />\r\n </Icon>\r\n);\r\n\r\nexport const BlurIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M12 22a7 7 0 0 0 7-7c0-2-1-3.9-3-5.5s-3.5-4-4-6.5c-.5 2.5-2 4.9-4 6.5C6 11.1 5 13 5 15a7 7 0 0 0 7 7z\" />\r\n </Icon>\r\n);\r\n\r\nexport const CameraIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z\" />\r\n <circle cx=\"12\" cy=\"13\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const LockIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M7 11V7a5 5 0 0 1 10 0v4\" />\r\n </Icon>\r\n);\r\n\r\nexport const UnlockIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"18\" height=\"11\" x=\"3\" y=\"11\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M7 11V7a5 5 0 0 1 9.9-1\" />\r\n </Icon>\r\n);\r\n\r\nexport const WebFullscreenIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"3\" rx=\"2\" />\r\n <line x1=\"8\" x2=\"16\" y1=\"21\" y2=\"21\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"17\" y2=\"21\" />\r\n </Icon>\r\n);\r\n\r\nexport const FastForwardIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"13 19 22 12 13 5 13 19\" />\r\n <polygon points=\"2 19 11 12 2 5 2 19\" />\r\n </Icon>\r\n);\r\n\r\nexport const ZapIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"13 2 3 14 12 14 11 22 21 10 12 10 13 2\" />\r\n </Icon>\r\n);\r\n\r\nexport const RatioIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"20\" height=\"14\" x=\"2\" y=\"5\" rx=\"2\" />\r\n <line x1=\"2\" x2=\"22\" y1=\"12\" y2=\"12\" />\r\n </Icon>\r\n);\r\n\r\nexport const ExpandIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m21 21-6-6m6 6v-4.8m0 4.8h-4.8\" />\r\n <path d=\"M3 16.2V21m0 0h4.8M3 21l6-6\" />\r\n <path d=\"M21 7.8V3m0 0h-4.8M21 3l-6 6\" />\r\n <path d=\"M3 7.8V3m0 0h4.8M3 3l6 6\" />\r\n </Icon>\r\n);\r\n\r\nexport const CloseIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M18 6 6 18\" />\r\n <path d=\"m6 6 12 12\" />\r\n </Icon>\r\n);\r\n\r\nexport const InfoIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <path d=\"M12 16v-4\" />\r\n <path d=\"M12 8h.01\" />\r\n </Icon>\r\n);\r\n\r\nexport const CopyIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\" />\r\n <path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\" />\r\n </Icon>\r\n);\r\n\r\nexport const MenuIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <line x1=\"4\" x2=\"20\" y1=\"12\" y2=\"12\" />\r\n <line x1=\"4\" x2=\"20\" y1=\"6\" y2=\"6\" />\r\n <line x1=\"4\" x2=\"20\" y1=\"18\" y2=\"18\" />\r\n </Icon>\r\n);\r\n\r\nexport const ChevronRightIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m9 18 6-6-6-6\" />\r\n </Icon>\r\n);\r\n\r\nexport const ServerIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"2\" rx=\"2\" ry=\"2\" />\r\n <rect width=\"20\" height=\"8\" x=\"2\" y=\"14\" rx=\"2\" ry=\"2\" />\r\n <line x1=\"6\" x2=\"6.01\" y1=\"6\" y2=\"6\" />\r\n <line x1=\"6\" x2=\"6.01\" y1=\"18\" y2=\"18\" />\r\n </Icon>\r\n);\r\n\r\nexport const LayersIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polygon points=\"12 2 2 7 12 12 22 7 12 2\" />\r\n <polyline points=\"2 17 12 22 22 17\" />\r\n <polyline points=\"2 12 12 17 22 12\" />\r\n </Icon>\r\n);\r\n\r\nexport const CropIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M6 2v14a2 2 0 0 0 2 2h14\" />\r\n <path d=\"M18 22V8a2 2 0 0 0-2-2H2\" />\r\n </Icon>\r\n);\r\n\r\nexport const SpeakerIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"16\" height=\"20\" x=\"4\" y=\"2\" rx=\"2\" />\r\n <circle cx=\"12\" cy=\"14\" r=\"4\" />\r\n <line x1=\"12\" x2=\"12.01\" y1=\"6\" y2=\"6\" />\r\n </Icon>\r\n);\r\n\r\nexport const GaugeIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"m12 14 4-4\" />\r\n <path d=\"M3.34 19a10 10 0 1 1 17.32 0\" />\r\n </Icon>\r\n);\r\n\r\nexport const SlidersIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <line x1=\"4\" x2=\"4\" y1=\"21\" y2=\"14\" />\r\n <line x1=\"4\" x2=\"4\" y1=\"10\" y2=\"3\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"21\" y2=\"12\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"3\" />\r\n <line x1=\"20\" x2=\"20\" y1=\"21\" y2=\"16\" />\r\n <line x1=\"20\" x2=\"20\" y1=\"12\" y2=\"3\" />\r\n <line x1=\"2\" x2=\"6\" y1=\"14\" y2=\"14\" />\r\n <line x1=\"10\" x2=\"14\" y1=\"8\" y2=\"8\" />\r\n <line x1=\"18\" x2=\"22\" y1=\"16\" y2=\"16\" />\r\n </Icon>\r\n);\r\n\r\nexport const MusicIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M9 18V5l12-2v13\" />\r\n <circle cx=\"6\" cy=\"18\" r=\"3\" />\r\n <circle cx=\"18\" cy=\"16\" r=\"3\" />\r\n </Icon>\r\n);\r\n\r\nexport const FlipIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <polyline points=\"16 16 12 20 8 16\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"20\" y2=\"10\" />\r\n <path d=\"M12 4a8 8 0 0 1 8 8\" />\r\n <path d=\"M20 4v8\" />\r\n <path d=\"M4 4v8\" />\r\n <path d=\"M4 12a8 8 0 0 1 8-8\" />\r\n </Icon>\r\n);\r\n\r\nexport const WifiIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M5 12.55a11 11 0 0 1 14.08 0\" />\r\n <path d=\"M1.42 9a16 16 0 0 1 21.16 0\" />\r\n <path d=\"M8.53 16.11a6 6 0 0 1 6.95 0\" />\r\n <line x1=\"12\" x2=\"12.01\" y1=\"20\" y2=\"20\" />\r\n </Icon>\r\n);\r\n\r\nexport const AlertCircleIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\r\n <line x1=\"12\" x2=\"12\" y1=\"8\" y2=\"12\" />\r\n <line x1=\"12\" x2=\"12.01\" y1=\"16\" y2=\"16\" />\r\n </Icon>\r\n);\r\n\r\nexport const QualityIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M2 20h.01\" />\r\n <path d=\"M7 20v-4\" />\r\n <path d=\"M12 20v-8\" />\r\n <path d=\"M17 20V8\" />\r\n <path d=\"M22 20V4\" />\r\n </Icon>\r\n);\r\n\r\nexport const VideoFlipIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M21 7v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\r\n <path d=\"M16 2v4\" />\r\n <path d=\"M8 2v4\" />\r\n <path d=\"M3 12h18\" />\r\n </Icon>\r\n);\r\n\r\nexport const SearchIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"11\" cy=\"11\" r=\"8\" />\r\n <path d=\"m21 21-4.3-4.3\" />\r\n </Icon>\r\n);\r\n\r\nexport const XIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M18 6 6 18\" />\r\n <path d=\"m6 6 12 12\" />\r\n </Icon>\r\n);\r\n\r\nexport const FileCheckIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\" />\r\n <polyline points=\"14 2 14 8 20 8\" />\r\n <path d=\"m9 15 2 2 4-4\" />\r\n </Icon>\r\n);\r\n\r\nexport const FileWarningIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <path d=\"M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z\" />\r\n <polyline points=\"14 2 14 8 20 8\" />\r\n <path d=\"M12 18h.01\" />\r\n <path d=\"M12 12v4\" />\r\n </Icon>\r\n);\r\n\r\nexport const SunIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <circle cx=\"12\" cy=\"12\" r=\"5\" />\r\n <path d=\"M12 1v2\" />\r\n <path d=\"M12 21v2\" />\r\n <path d=\"M4.22 4.22l1.42 1.42\" />\r\n <path d=\"M18.36 18.36l1.42 1.42\" />\r\n <path d=\"M1 12h2\" />\r\n <path d=\"M21 12h2\" />\r\n <path d=\"M4.22 19.78l1.42-1.42\" />\r\n <path d=\"M18.36 5.64l1.42-1.42\" />\r\n </Icon>\r\n);\r\n\r\nexport const LayoutTemplateIcon = ({ className }: { className?: string }) => (\r\n <Icon className={className}>\r\n <rect width=\"18\" height=\"7\" x=\"3\" y=\"3\" rx=\"1\" />\r\n <rect width=\"9\" height=\"7\" x=\"3\" y=\"14\" rx=\"1\" />\r\n <rect width=\"5\" height=\"7\" x=\"16\" y=\"14\" rx=\"1\" />\r\n </Icon>\r\n);\r\n\r\n// Custom Composite Icons (Reusing Base Icons + Text)\r\nexport const Replay10Icon = ({ className }: { className?: string }) => (\r\n <div className={`relative flex items-center justify-center ${className}`}>\r\n <Icon className=\"w-full h-full\">\r\n <path d=\"M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8\" />\r\n <path d=\"M3 3v5h5\" />\r\n </Icon>\r\n <span className=\"absolute inset-0 flex items-center justify-center text-[32%] font-bold select-none mt-[1px]\">\r\n 10\r\n </span>\r\n </div>\r\n);\r\n\r\nexport const Forward10Icon = ({ className }: { className?: string }) => (\r\n <div className={`relative flex items-center justify-center ${className}`}>\r\n <Icon className=\"w-full h-full\">\r\n <path d=\"M21 12a9 9 0 1 1-9-9 9.75 9.75 0 0 1 6.74 2.74L21 8\" />\r\n <path d=\"M21 3v5h-5\" />\r\n </Icon>\r\n <span className=\"absolute inset-0 flex items-center justify-center text-[32%] font-bold select-none mt-[1px]\">\r\n 10\r\n </span>\r\n </div>\r\n);\r\n\r\nexport const StrataLogo = ({ className }: { className?: string }) => {\r\n const base = import.meta.env?.BASE_URL || \"/\";\r\n const src = `${base}logo.png`;\r\n return <img src={src} alt=\"StrataPlayer Logo\" className={className} />;\r\n};\r\n","import React from \"react\";\r\nimport { PlayerState } from \"../../core/StrataCore\";\r\nimport {\r\n LoaderIcon,\r\n CheckIcon,\r\n AlertCircleIcon,\r\n DownloadIcon,\r\n CloseIcon,\r\n} from \"../Icons\";\r\n\r\nexport const NotificationContainer = ({\r\n notifications,\r\n}: {\r\n notifications: PlayerState[\"notifications\"];\r\n}) => {\r\n return (\r\n <div className=\"absolute top-4 left-4 z-[100] flex flex-col gap-2 pointer-events-none font-sans max-w-[85%] md:max-w-[280px]\">\r\n {notifications.map((n) => {\r\n const isProgress = typeof n.progress === \"number\";\r\n\r\n return (\r\n <div\r\n key={n.id}\r\n className={`\r\n relative overflow-hidden bg-zinc-950/80 backdrop-blur-xl border border-white/10 text-zinc-100 shadow-2xl rounded-lg pointer-events-auto\r\n animate-in slide-in-from-left-4 fade-in duration-300\r\n ${isProgress ? \"w-64\" : \"w-auto max-w-full px-3 py-2.5\"}\r\n `}\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n {isProgress ? (\r\n <div className=\"p-3\">\r\n <div className=\"flex items-start gap-3\">\r\n <div className=\"w-7 h-7 rounded-full bg-white/10 flex items-center justify-center text-[var(--accent)] shrink-0\">\r\n <DownloadIcon className=\"w-3.5 h-3.5\" />\r\n </div>\r\n <div className=\"flex-1 min-w-0 pt-0.5\">\r\n <div className=\"flex justify-between items-baseline mb-1\">\r\n <span className=\"text-xs font-bold text-white tracking-tight\">\r\n Downloading\r\n </span>\r\n <span className=\"text-[10px] font-mono text-zinc-400\">\r\n {n.progress}%\r\n </span>\r\n </div>\r\n {/* Removed truncate, added whitespace-pre-wrap to support newlines for ETA */}\r\n <p className=\"text-[10px] text-zinc-400 mb-2 leading-tight whitespace-pre-wrap\">\r\n {n.message.replace(/Downloading\\.\\.\\. \\d+%/, \"\").trim() ||\r\n \"Processing...\"}\r\n </p>\r\n <div className=\"h-0.5 w-full bg-white/10 rounded-full overflow-hidden\">\r\n <div\r\n className=\"h-full bg-[var(--accent)] transition-all duration-300 ease-out\"\r\n style={{ width: `${n.progress}%` }}\r\n />\r\n </div>\r\n </div>\r\n {n.action && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n n.action?.onClick();\r\n }}\r\n className=\"text-zinc-500 hover:text-zinc-200 transition-colors p-1 -mt-1.5 -mr-1.5\"\r\n title={n.action.label}\r\n >\r\n <CloseIcon className=\"w-3.5 h-3.5\" />\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n ) : (\r\n <div className=\"flex items-start gap-2.5\">\r\n {n.type === \"loading\" && (\r\n <LoaderIcon className=\"w-3.5 h-3.5 animate-spin text-[var(--accent)] shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"success\" && (\r\n <CheckIcon className=\"w-3.5 h-3.5 text-emerald-500 shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"error\" && (\r\n <AlertCircleIcon className=\"w-3.5 h-3.5 text-red-500 shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"warning\" && (\r\n <AlertCircleIcon className=\"w-3.5 h-3.5 text-amber-500 shrink-0 mt-0.5\" />\r\n )}\r\n {n.type === \"info\" && (\r\n <div className=\"w-1.5 h-1.5 rounded-full bg-[var(--accent)] mt-1.5 shrink-0\" />\r\n )}\r\n\r\n <div className=\"flex flex-col gap-0.5 min-w-0\">\r\n <span className=\"text-xs font-medium leading-snug break-words text-zinc-200 whitespace-pre-wrap\">\r\n {n.message}\r\n </span>\r\n {n.action && (\r\n <button\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n n.action?.onClick();\r\n }}\r\n className=\"mt-1 self-start text-[10px] font-bold text-[var(--accent)] hover:text-white transition-colors uppercase tracking-wider\"\r\n >\r\n {n.action.label}\r\n </button>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n","import React from \"react\";\r\nimport { SubtitleSettings } from \"../../core/StrataCore\";\r\n\r\nexport const SubtitleOverlay = ({\r\n cues,\r\n settings,\r\n}: {\r\n cues: string[];\r\n settings: SubtitleSettings;\r\n}) => {\r\n if (settings.useNative || cues.length === 0) return null;\r\n\r\n const getTextShadow = () => {\r\n switch (settings.textStyle) {\r\n case \"outline\":\r\n return \"0px 0px 4px black, 0px 0px 4px black\"; // Simplified stroke\r\n case \"raised\":\r\n return \"0 -1px 1px black, 0 -2px 2px black\"; // Pseudo 3D raised\r\n case \"depressed\":\r\n return \"0 1px 1px white, 0 2px 2px black\"; // Pseudo 3D depressed\r\n case \"shadow\":\r\n return \"2px 2px 2px rgba(0,0,0,0.8)\";\r\n default:\r\n return \"none\";\r\n }\r\n };\r\n\r\n return (\r\n <div\r\n className=\"absolute inset-x-0 flex flex-col items-center justify-end text-center z-10 pointer-events-none transition-all duration-200 strata-subtitle-overlay\"\r\n style={{\r\n bottom: `${settings.verticalOffset}px`,\r\n }}\r\n >\r\n {cues.map((text, i) => (\r\n <div\r\n key={i}\r\n className=\"mb-1 inline-block max-w-[80%]\"\r\n style={{\r\n fontSize: `${settings.textSize}%`,\r\n color: settings.textColor,\r\n fontWeight: settings.isBold ? \"bold\" : \"normal\",\r\n textTransform: settings.fixCapitalization ? \"capitalize\" : \"none\",\r\n textShadow: getTextShadow(),\r\n lineHeight: 1.4,\r\n whiteSpace: \"pre-line\",\r\n }}\r\n >\r\n <span\r\n className=\"px-2 py-0.5 rounded\"\r\n style={{\r\n backgroundColor: `rgba(0, 0, 0, ${settings.backgroundOpacity / 100})`,\r\n backdropFilter: settings.backgroundBlur\r\n ? `blur(${settings.backgroundBlurAmount}px)`\r\n : \"none\",\r\n }}\r\n dangerouslySetInnerHTML={{ __html: text }} // VTT supports some HTML-like tags\r\n />\r\n </div>\r\n ))}\r\n </div>\r\n );\r\n};\r\n","\r\nimport React from 'react';\r\n\r\n// Helper for rendering string/node safely (duplicated from Menu for isolation)\r\nconst RenderContent = ({ content }: { content: string | React.ReactNode }) => {\r\n if (typeof content === 'string') {\r\n if (content.trim().startsWith('<')) return <span dangerouslySetInnerHTML={{ __html: content }} />;\r\n return <span>{content}</span>;\r\n }\r\n return <>{content}</>;\r\n};\r\n\r\nexport const Toggle = ({ label, checked, onChange, icon, tooltip }: any) => (\r\n <div\r\n className=\"flex items-center justify-between py-2.5 px-3 hover:bg-white/5 group transition-colors\"\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex items-center gap-3\">\r\n {icon && <span className=\"text-zinc-500 group-hover:text-zinc-400 transition-colors flex items-center justify-center w-4 h-4\"><RenderContent content={icon} /></span>}\r\n <div className=\"flex flex-col\">\r\n <span className=\"text-sm text-zinc-300 font-medium group-hover:text-white transition-colors flex items-center\">\r\n <RenderContent content={label} />\r\n </span>\r\n {tooltip && <span className=\"text-[10px] text-zinc-500\">{tooltip}</span>}\r\n </div>\r\n </div>\r\n <button\r\n onClick={() => onChange(!checked)}\r\n className={`w-11 h-6 shrink-0 transition-colors relative focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-zinc-900 ${checked ? 'bg-[var(--accent)]' : 'bg-zinc-700'}`}\r\n style={{\r\n '--tw-ring-color': 'var(--accent)',\r\n borderRadius: 'var(--radius-full)',\r\n borderWidth: 'var(--border-width)',\r\n borderColor: 'rgba(255,255,255,0.1)'\r\n } as React.CSSProperties}\r\n >\r\n <div\r\n className={`absolute top-1/2 -translate-y-1/2 left-1 w-4 h-4 transition-transform shadow-sm ${checked ? 'translate-x-5' : 'translate-x-0'}`}\r\n style={{\r\n borderRadius: 'var(--radius-full)',\r\n backgroundColor: checked ? 'var(--accent-contrast)' : '#ffffff'\r\n }}\r\n />\r\n </button>\r\n </div>\r\n);\r\n\r\nexport const Slider = ({ label, value, min, max, step, onChange, formatValue, icon }: any) => (\r\n <div\r\n className=\"py-2.5 px-3 hover:bg-white/5 group transition-colors\"\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex justify-between items-center mb-2\">\r\n <div className=\"flex items-center gap-3\">\r\n {icon && <span className=\"text-zinc-500 group-hover:text-zinc-400 transition-colors flex items-center justify-center w-4 h-4\"><RenderContent content={icon} /></span>}\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">{label}</span>\r\n </div>\r\n <span\r\n className=\"text-[10px] font-mono font-medium text-zinc-300 bg-white/10 px-1.5 py-0.5 tabular-nums\"\r\n style={{ borderRadius: 'var(--radius-sm)' }}\r\n >{formatValue ? formatValue(value) : value}</span>\r\n </div>\r\n <div className=\"relative h-4 flex items-center px-1\">\r\n <input\r\n type=\"range\"\r\n min={min} max={max} step={step}\r\n value={value}\r\n onChange={(e) => onChange(parseFloat(e.target.value))}\r\n className=\"w-full h-1.5 appearance-none cursor-pointer focus:outline-none focus:ring-2 strata-range-input\"\r\n style={{\r\n borderRadius: 'var(--radius-full)',\r\n background: `linear-gradient(to right, var(--accent) 0%, var(--accent) ${(value - min) / (max - min) * 100}%, #3f3f46 ${(value - min) / (max - min) * 100}%, #3f3f46 100%)`,\r\n '--tw-ring-color': 'var(--accent)'\r\n } as React.CSSProperties}\r\n />\r\n <style>{`\r\n .strata-range-input::-webkit-slider-thumb {\r\n -webkit-appearance: none;\r\n height: 14px;\r\n width: 14px;\r\n background: #ffffff;\r\n cursor: pointer;\r\n box-shadow: 0 1px 3px rgba(0,0,0,0.5);\r\n transition: transform 0.1s;\r\n border-radius: var(--radius-full);\r\n border: var(--border-width) solid rgba(0,0,0,0.1);\r\n }\r\n .strata-range-input::-webkit-slider-thumb:hover {\r\n transform: scale(1.1);\r\n }\r\n /* Pixel theme specific overrides are handled by global css */\r\n `}</style>\r\n </div>\r\n </div>\r\n);\r\n\r\nexport const Select = ({ label, value, options, onChange, icon }: any) => (\r\n <div\r\n className=\"py-2.5 px-3 hover:bg-white/5 group transition-colors\"\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex items-center gap-3 mb-2\">\r\n {icon && <span className=\"text-zinc-500 group-hover:text-zinc-400 transition-colors flex items-center justify-center w-4 h-4\"><RenderContent content={icon} /></span>}\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">{label}</span>\r\n </div>\r\n <div className=\"relative\">\r\n <select\r\n value={value}\r\n onChange={(e) => onChange(e.target.value)}\r\n className=\"w-full bg-zinc-800 border-[length:var(--border-width)] border-white/10 px-3 py-2 text-sm text-zinc-200 focus:outline-none focus:ring-2 appearance-none hover:bg-zinc-700 transition-colors cursor-pointer\"\r\n style={{ '--tw-ring-color': 'var(--accent)', borderRadius: 'var(--radius)' } as React.CSSProperties}\r\n >\r\n {options.map((opt: any) => (\r\n <option key={opt.value} value={opt.value}>{opt.label}</option>\r\n ))}\r\n </select>\r\n <div className=\"absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-zinc-400\">\r\n <svg width=\"10\" height=\"6\" viewBox=\"0 0 10 6\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M1 1L5 5L9 1\" stroke=\"currentColor\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" /></svg>\r\n </div>\r\n </div>\r\n </div>\r\n);\r\n\r\nexport const SettingsGroup = ({ title, children }: any) => (\r\n <div className=\"py-2\">\r\n {title && <h4 className=\"px-3 text-[10px] font-bold text-[var(--accent)] uppercase tracking-wider mb-1 mt-2\">{title}</h4>}\r\n <div className=\"space-y-0.5\">\r\n {children}\r\n </div>\r\n </div>\r\n);\r\n","import React, { useRef, useLayoutEffect, useState, useEffect } from \"react\";\r\nimport { ArrowLeftIcon, CheckIcon } from \"../Icons\";\r\nimport { SettingItem } from \"../../core/StrataCore\";\r\nimport { Toggle, Slider, SettingsGroup } from \"./SettingsPrimitives\";\r\n\r\nexport const Menu = ({\r\n children,\r\n onClose,\r\n align = \"right\",\r\n maxHeight,\r\n className,\r\n}: {\r\n children?: React.ReactNode;\r\n onClose: () => void;\r\n align?: \"right\" | \"center\";\r\n maxHeight?: number;\r\n className?: string;\r\n}) => {\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const contentRef = useRef<HTMLDivElement>(null);\r\n const [height, setHeight] = useState<number | \"auto\">(\"auto\");\r\n\r\n const positionClasses =\r\n align === \"center\"\r\n ? \"left-1/2 -translate-x-1/2 origin-bottom\"\r\n : \"right-0 origin-bottom-right\";\r\n\r\n // Smooth height animation logic\r\n useLayoutEffect(() => {\r\n if (!contentRef.current) return;\r\n\r\n const updateHeight = () => {\r\n if (contentRef.current) {\r\n setHeight(contentRef.current.offsetHeight);\r\n }\r\n };\r\n\r\n const observer = new ResizeObserver(updateHeight);\r\n observer.observe(contentRef.current);\r\n\r\n // Initial measure\r\n updateHeight();\r\n\r\n return () => observer.disconnect();\r\n }, []);\r\n\r\n // Constrain dynamic height by maxHeight prop if provided\r\n const calculatedStyle = {\r\n height: height === \"auto\" ? \"auto\" : `${height + 14}px`, // + padding\r\n maxHeight: maxHeight ? `${maxHeight}px` : undefined,\r\n };\r\n\r\n return (\r\n <div\r\n ref={containerRef}\r\n className={`absolute bottom-full mb-4 ${positionClasses} bg-[var(--bg-panel)] backdrop-blur-xl border-[length:var(--border-width)] border-white/10 shadow-2xl overflow-hidden w-[300px] max-w-[calc(100vw-32px)] text-sm z-50 ring-1 ring-white/5 font-[family-name:var(--font-main)] flex flex-col p-1.5 transition-[height,opacity,transform] duration-300 ease-out ${className}`}\r\n style={{ ...calculatedStyle, borderRadius: \"var(--radius-lg)\" }}\r\n onClick={(e) => e.stopPropagation()}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n >\r\n <div\r\n className=\"overflow-y-auto hide-scrollbar flex-1\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <div ref={contentRef}>{children}</div>\r\n </div>\r\n </div>\r\n );\r\n};\r\n\r\n// Helper for rendering string/node safely\r\nconst RenderContent = ({\r\n content,\r\n className,\r\n}: {\r\n content: string | React.ReactNode;\r\n className?: string;\r\n}) => {\r\n if (typeof content === \"string\") {\r\n // If it looks like HTML, use dangerous. Otherwise regular text.\r\n if (content.trim().startsWith(\"<\"))\r\n return (\r\n <span\r\n className={className}\r\n dangerouslySetInnerHTML={{ __html: content }}\r\n />\r\n );\r\n return <span className={className}>{content}</span>;\r\n }\r\n return <span className={className}>{content}</span>;\r\n};\r\n\r\nexport const MenuItem = ({\r\n label,\r\n value,\r\n active,\r\n onClick,\r\n hasSubmenu,\r\n icon,\r\n rightIcon,\r\n}: any) => (\r\n <button\r\n onClick={onClick}\r\n className=\"w-full flex items-center justify-between px-3 py-2.5 hover:bg-white/10 transition-colors text-left text-zinc-200 active:bg-white/5 focus:outline-none focus:bg-white/10 group overflow-hidden my-0.5\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <div className=\"flex items-center gap-3 overflow-hidden\">\r\n {icon && (\r\n <span className=\"text-zinc-400 shrink-0 group-hover:text-zinc-300 transition-colors flex items-center justify-center w-4 h-4\">\r\n <RenderContent content={icon} />\r\n </span>\r\n )}\r\n <span\r\n className={`font-medium truncate text-sm flex items-center ${active ? \"text-[var(--accent)]\" : \"\"}`}\r\n title={typeof label === \"string\" ? label : undefined}\r\n >\r\n <RenderContent content={label} />\r\n </span>\r\n </div>\r\n <div className=\"flex items-center gap-2 text-zinc-400 shrink-0\">\r\n {value && (\r\n <span\r\n className=\"text-xs font-medium truncate max-w-[60px]\"\r\n title={value}\r\n >\r\n <RenderContent content={value} />\r\n </span>\r\n )}\r\n {rightIcon}\r\n {active && (\r\n <CheckIcon className=\"w-4 h-4 text-[var(--accent)] shrink-0\" />\r\n )}\r\n {hasSubmenu && (\r\n <span className=\"text-xs group-hover:translate-x-0.5 transition-transform text-zinc-500 shrink-0\">\r\n ›\r\n </span>\r\n )}\r\n </div>\r\n </button>\r\n);\r\n\r\nexport const MenuHeader = ({\r\n label,\r\n onBack,\r\n rightAction,\r\n}: {\r\n label: string | React.ReactNode;\r\n onBack: () => void;\r\n rightAction?: React.ReactNode;\r\n}) => (\r\n <div\r\n className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <button\r\n className=\"flex items-center gap-2 hover:text-white transition-colors focus:outline-none\"\r\n onClick={onBack}\r\n >\r\n <ArrowLeftIcon className=\"w-3 h-3\" />\r\n <span>\r\n <RenderContent content={label} />\r\n </span>\r\n </button>\r\n {rightAction}\r\n </div>\r\n);\r\n\r\nexport const MenuDivider = () => (\r\n <div className=\"h-px bg-white/5 mx-2 my-1\"></div>\r\n);\r\n\r\n// --- Recursive Menu Explorer ---\r\n\r\nexport const MenuExplorer = ({\r\n items,\r\n onClose,\r\n title,\r\n maxHeight,\r\n className,\r\n}: {\r\n items: SettingItem[];\r\n onClose: () => void;\r\n title?: string;\r\n maxHeight?: number;\r\n className?: string;\r\n}) => {\r\n const [history, setHistory] = useState<SettingItem[]>([]);\r\n\r\n // Current view context\r\n const currentItem = history.length > 0 ? history[history.length - 1] : null;\r\n const currentList = currentItem ? currentItem.children || [] : items;\r\n const currentTitle = currentItem ? currentItem.html : title || \"Menu\";\r\n\r\n const goBack = () => {\r\n setHistory((prev) => prev.slice(0, -1));\r\n };\r\n\r\n const navigateTo = (item: SettingItem) => {\r\n if (item.children) {\r\n setHistory((prev) => [...prev, item]);\r\n }\r\n };\r\n\r\n return (\r\n <Menu onClose={onClose} maxHeight={maxHeight} className={className}>\r\n <div className=\"animate-in fade-in slide-in-from-right-4 duration-200\">\r\n {/* Header (Only if deep or title exists and is root) */}\r\n {history.length > 0 ? (\r\n <MenuHeader label={currentTitle || \"Menu\"} onBack={goBack} />\r\n ) : (\r\n title && (\r\n <div\r\n className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <span>{title}</span>\r\n </div>\r\n )\r\n )}\r\n\r\n <div className=\"pb-1\">\r\n {currentList.map((item, i) => {\r\n // Case 0: Separator\r\n if (item.separator) {\r\n return <MenuDivider key={i} />;\r\n }\r\n\r\n // Case 0.5: Label\r\n if (item.isLabel) {\r\n return (\r\n <div\r\n key={i}\r\n className=\"px-3 py-1.5 text-[10px] font-bold text-zinc-500 uppercase tracking-wider select-none\"\r\n >\r\n <RenderContent content={item.html || \"\"} />\r\n </div>\r\n );\r\n }\r\n\r\n // Case 1: Range (Slider)\r\n if (item.range) {\r\n return (\r\n <div key={i} className=\"px-1\">\r\n <Slider\r\n label={item.html}\r\n icon={item.icon}\r\n value={item.value ?? item.min ?? 0}\r\n min={item.min ?? 0}\r\n max={item.max ?? 100}\r\n step={item.step ?? 1}\r\n onChange={(val: number) =>\r\n item.onRange && item.onRange(val)\r\n }\r\n formatValue={item.formatValue}\r\n />\r\n </div>\r\n );\r\n }\r\n\r\n // Case 2: Toggle Switch\r\n if (item.switch !== undefined) {\r\n return (\r\n <div key={i} className=\"px-1\">\r\n <Toggle\r\n label={item.html}\r\n icon={item.icon}\r\n checked={item.switch}\r\n tooltip={item.tooltip}\r\n onChange={(val: boolean) =>\r\n item.onSwitch && item.onSwitch(item, val)\r\n }\r\n />\r\n </div>\r\n );\r\n }\r\n\r\n // Case 3: Navigation (Children) or Action\r\n return (\r\n <React.Fragment key={i}>\r\n <MenuItem\r\n label={item.html}\r\n icon={item.icon}\r\n value={item.currentLabel || item.value}\r\n active={item.active}\r\n hasSubmenu={!!item.children}\r\n onClick={() => {\r\n if (item.children) {\r\n navigateTo(item);\r\n } else if (item.onClick) {\r\n item.onClick(item);\r\n if (!item.switch && !item.range) {\r\n // Close on standard actions\r\n onClose();\r\n }\r\n } else if (item.click) {\r\n item.click(item);\r\n onClose();\r\n }\r\n }}\r\n />\r\n </React.Fragment>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </Menu>\r\n );\r\n};\r\n","import React, { useState, useRef, useMemo } from \"react\";\r\nimport { SubtitleSettings, SubtitleTrackState } from \"../../core/StrataCore\";\r\nimport { Menu, MenuItem, MenuHeader } from \"./Menu\";\r\nimport { SettingsGroup, Toggle, Slider, Select } from \"./SettingsPrimitives\";\r\nimport {\r\n UploadIcon,\r\n CustomizeIcon,\r\n ResetIcon,\r\n ClockIcon,\r\n MinusIcon,\r\n PlusIcon,\r\n MoveVerticalIcon,\r\n TypeIcon,\r\n PaletteIcon,\r\n BoldIcon,\r\n CaseUpperIcon,\r\n EyeIcon,\r\n BlurIcon,\r\n SearchIcon,\r\n LoaderIcon,\r\n FileCheckIcon,\r\n FileWarningIcon,\r\n} from \"../Icons\";\r\n\r\nexport const SubtitleMenu = ({\r\n tracks,\r\n current,\r\n onSelect,\r\n onUpload,\r\n onClose,\r\n settings,\r\n onSettingsChange,\r\n onReset,\r\n offset,\r\n onOffsetChange,\r\n maxHeight,\r\n animationClass,\r\n}: {\r\n tracks: SubtitleTrackState[];\r\n current: number;\r\n onSelect: (index: number) => void;\r\n onUpload: (file: File) => void;\r\n onClose: () => void;\r\n settings: SubtitleSettings;\r\n onSettingsChange: (settings: Partial<SubtitleSettings>) => void;\r\n onReset: () => void;\r\n offset: number;\r\n onOffsetChange: (val: number) => void;\r\n maxHeight: number;\r\n animationClass: string;\r\n}) => {\r\n const [view, setView] = useState<\"main\" | \"customize\">(\"main\");\r\n const [search, setSearch] = useState(\"\");\r\n const fileInputRef = useRef<HTMLInputElement>(null);\r\n\r\n const filteredTracks = useMemo(() => {\r\n if (!search) return tracks;\r\n return tracks.filter(\r\n (t) =>\r\n t.label.toLowerCase().includes(search.toLowerCase()) ||\r\n (t.srcLang && t.srcLang.toLowerCase().includes(search.toLowerCase())),\r\n );\r\n }, [tracks, search]);\r\n\r\n return (\r\n <Menu\r\n onClose={onClose}\r\n align=\"right\"\r\n maxHeight={maxHeight}\r\n className={animationClass}\r\n >\r\n {view === \"main\" && (\r\n <div className=\"animate-in slide-in-from-left-4 fade-in duration-200 flex flex-col h-full\">\r\n <div\r\n className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md shrink-0\"\r\n style={{ borderRadius: \"var(--radius)\" }}\r\n >\r\n <span>Subtitles</span>\r\n </div>\r\n\r\n <div className=\"px-1.5 pb-2 shrink-0\">\r\n <MenuItem\r\n label=\"Upload Subtitle\"\r\n icon={<UploadIcon className=\"w-4 h-4\" />}\r\n onClick={() => fileInputRef.current?.click()}\r\n />\r\n <input\r\n type=\"file\"\r\n accept=\".vtt,.srt\"\r\n ref={fileInputRef}\r\n className=\"hidden\"\r\n onChange={(e) => {\r\n if (e.target.files?.[0]) onUpload(e.target.files[0]);\r\n }}\r\n />\r\n <MenuItem\r\n label=\"Customize\"\r\n icon={<CustomizeIcon className=\"w-4 h-4\" />}\r\n onClick={() => setView(\"customize\")}\r\n hasSubmenu\r\n />\r\n <div className=\"h-px bg-white/5 mx-2 my-1\"></div>\r\n <MenuItem\r\n label=\"Off\"\r\n active={current === -1}\r\n onClick={() => {\r\n onSelect(-1);\r\n onClose();\r\n }}\r\n />\r\n\r\n <div className=\"relative mt-2\">\r\n <input\r\n type=\"text\"\r\n placeholder=\"Search subtitles...\"\r\n value={search}\r\n onChange={(e) => setSearch(e.target.value)}\r\n className=\"w-full bg-zinc-800/50 border border-white/10 rounded-md py-1.5 pl-8 pr-3 text-xs text-zinc-200 focus:outline-none focus:border-white/20 transition-colors\"\r\n />\r\n <SearchIcon className=\"w-3.5 h-3.5 text-zinc-500 absolute left-2.5 top-1/2 -translate-y-1/2 pointer-events-none\" />\r\n </div>\r\n </div>\r\n\r\n <div className=\"overflow-y-auto hide-scrollbar flex-1\">\r\n {filteredTracks.map((track) => {\r\n let rightIcon = null;\r\n if (track.status === \"loading\") {\r\n rightIcon = (\r\n <LoaderIcon className=\"w-3.5 h-3.5 animate-spin text-[var(--accent)]\" />\r\n );\r\n } else if (track.status === \"error\") {\r\n rightIcon = (\r\n <FileWarningIcon className=\"w-3.5 h-3.5 text-red-500\" />\r\n );\r\n } else if (track.status === \"success\") {\r\n rightIcon = (\r\n <FileCheckIcon className=\"w-3.5 h-3.5 text-emerald-500\" />\r\n );\r\n }\r\n\r\n return (\r\n <MenuItem\r\n key={track.index}\r\n label={track.label}\r\n value={track.srcLang}\r\n active={current === track.index}\r\n rightIcon={rightIcon}\r\n onClick={() => {\r\n onSelect(track.index);\r\n onClose();\r\n }}\r\n />\r\n );\r\n })}\r\n {filteredTracks.length === 0 && search && (\r\n <div className=\"px-4 py-3 text-center text-xs text-zinc-500\">\r\n No results found\r\n </div>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n\r\n {view === \"customize\" && (\r\n <div className=\"animate-in slide-in-from-right-4 fade-in duration-200\">\r\n <MenuHeader\r\n label=\"Customize\"\r\n onBack={() => setView(\"main\")}\r\n rightAction={\r\n <button\r\n onClick={onReset}\r\n className=\"p-1.5 text-zinc-400 hover:text-white transition-colors rounded-md hover:bg-white/10\"\r\n title=\"Reset All\"\r\n >\r\n <ResetIcon className=\"w-4 h-4\" />\r\n </button>\r\n }\r\n />\r\n\r\n <div className=\"pb-1\">\r\n <SettingsGroup>\r\n <Toggle\r\n label=\"Native Video Subtitle\"\r\n checked={settings.useNative}\r\n onChange={(val: boolean) =>\r\n onSettingsChange({ useNative: val })\r\n }\r\n />\r\n </SettingsGroup>\r\n\r\n {!settings.useNative && (\r\n <>\r\n <SettingsGroup title=\"Sync & Position\">\r\n <div className=\"py-2.5 px-3 rounded-lg hover:bg-white/5 group transition-colors\">\r\n <div className=\"flex justify-between items-center mb-2\">\r\n <div className=\"flex items-center gap-3\">\r\n <ClockIcon className=\"w-4 h-4 text-zinc-500 group-hover:text-zinc-400 transition-colors\" />\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">\r\n Sync Offset\r\n </span>\r\n </div>\r\n </div>\r\n <div className=\"flex items-center gap-2\">\r\n <button\r\n onClick={() =>\r\n onOffsetChange(Math.round((offset - 0.1) * 10) / 10)\r\n }\r\n className=\"w-8 h-8 flex items-center justify-center bg-zinc-800 rounded-lg hover:bg-zinc-700 text-zinc-300 transition-colors active:scale-95\"\r\n >\r\n <MinusIcon className=\"w-4 h-4\" />\r\n </button>\r\n <div className=\"flex-1 bg-zinc-900 border border-white/5 rounded-lg h-8 flex items-center justify-center text-xs font-mono font-medium text-[var(--accent)]\">\r\n {offset > 0 ? \"+\" : \"\"}\r\n {offset?.toFixed(1) || \"0.0\"}s\r\n </div>\r\n <button\r\n onClick={() =>\r\n onOffsetChange(Math.round((offset + 0.1) * 10) / 10)\r\n }\r\n className=\"w-8 h-8 flex items-center justify-center bg-zinc-800 rounded-lg hover:bg-zinc-700 text-zinc-300 transition-colors active:scale-95\"\r\n >\r\n <PlusIcon className=\"w-4 h-4\" />\r\n </button>\r\n </div>\r\n </div>\r\n\r\n <Slider\r\n label=\"Vertical Position\"\r\n icon={<MoveVerticalIcon className=\"w-4 h-4\" />}\r\n value={settings.verticalOffset}\r\n min={0}\r\n max={200}\r\n step={5}\r\n onChange={(val: number) =>\r\n onSettingsChange({ verticalOffset: val })\r\n }\r\n formatValue={(v: number) => `${v}px`}\r\n />\r\n </SettingsGroup>\r\n\r\n <SettingsGroup title=\"Appearance\">\r\n <Slider\r\n label=\"Text Size\"\r\n icon={<TypeIcon className=\"w-4 h-4\" />}\r\n value={settings.textSize}\r\n min={50}\r\n max={200}\r\n step={10}\r\n onChange={(val: number) =>\r\n onSettingsChange({ textSize: val })\r\n }\r\n formatValue={(v: number) => `${v}%`}\r\n />\r\n\r\n <div className=\"py-2.5 px-3 rounded-lg hover:bg-white/5 group transition-colors\">\r\n <div className=\"flex items-center gap-3 mb-2\">\r\n <PaletteIcon className=\"w-4 h-4 text-zinc-500 group-hover:text-zinc-400 transition-colors\" />\r\n <span className=\"text-xs font-bold text-zinc-400 uppercase tracking-wider group-hover:text-zinc-300 transition-colors\">\r\n Text Color\r\n </span>\r\n </div>\r\n <div className=\"flex items-center justify-between gap-2 p-1 bg-zinc-800/50 rounded-lg\">\r\n {[\r\n \"#ffffff\",\r\n \"#ffff00\",\r\n \"#00ffff\",\r\n \"#ff00ff\",\r\n \"#ff0000\",\r\n \"#00ff00\",\r\n ].map((c) => (\r\n <button\r\n key={c}\r\n onClick={() => onSettingsChange({ textColor: c })}\r\n className={`w-6 h-6 rounded-full border border-white/10 transition-transform hover:scale-110 ${settings.textColor === c ? \"ring-2 scale-110\" : \"\"}`}\r\n style={\r\n {\r\n backgroundColor: c,\r\n \"--tw-ring-color\": \"var(--accent)\",\r\n } as any\r\n }\r\n />\r\n ))}\r\n <div className=\"w-px h-6 bg-white/10 mx-1\"></div>\r\n <div className=\"relative w-6 h-6 rounded-full overflow-hidden ring-1 ring-white/20 cursor-pointer\">\r\n <input\r\n type=\"color\"\r\n value={settings.textColor}\r\n onChange={(e) =>\r\n onSettingsChange({ textColor: e.target.value })\r\n }\r\n className=\"absolute inset-[-4px] w-[150%] h-[150%] cursor-pointer p-0 border-0\"\r\n />\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <Select\r\n label=\"Text Style\"\r\n value={settings.textStyle}\r\n options={[\r\n { label: \"None\", value: \"none\" },\r\n { label: \"Outline\", value: \"outline\" },\r\n { label: \"Raised\", value: \"raised\" },\r\n { label: \"Depressed\", value: \"depressed\" },\r\n { label: \"Drop Shadow\", value: \"shadow\" },\r\n ]}\r\n onChange={(val: string) =>\r\n onSettingsChange({\r\n textStyle: val as SubtitleSettings[\"textStyle\"],\r\n })\r\n }\r\n />\r\n\r\n <div className=\"grid grid-cols-2 gap-2 mt-1 px-1\">\r\n <Toggle\r\n label=\"Bold\"\r\n icon={<BoldIcon className=\"w-4 h-4\" />}\r\n checked={settings.isBold}\r\n onChange={(v: boolean) => onSettingsChange({ isBold: v })}\r\n />\r\n <Toggle\r\n label=\"Fix Caps\"\r\n icon={<CaseUpperIcon className=\"w-4 h-4\" />}\r\n checked={settings.fixCapitalization}\r\n onChange={(v: boolean) =>\r\n onSettingsChange({ fixCapitalization: v })\r\n }\r\n />\r\n </div>\r\n </SettingsGroup>\r\n\r\n <SettingsGroup title=\"Background\">\r\n <Slider\r\n label=\"Opacity\"\r\n icon={<EyeIcon className=\"w-4 h-4\" />}\r\n value={settings.backgroundOpacity}\r\n min={0}\r\n max={100}\r\n step={5}\r\n onChange={(val: number) =>\r\n onSettingsChange({ backgroundOpacity: val })\r\n }\r\n formatValue={(v: number) => `${v}%`}\r\n />\r\n\r\n <Toggle\r\n label=\"Blur Background\"\r\n icon={<BlurIcon className=\"w-4 h-4\" />}\r\n checked={settings.backgroundBlur}\r\n onChange={(v: boolean) =>\r\n onSettingsChange({ backgroundBlur: v })\r\n }\r\n />\r\n\r\n {settings.backgroundBlur && (\r\n <Slider\r\n label=\"Blur Intensity\"\r\n value={settings.backgroundBlurAmount}\r\n min={0}\r\n max={20}\r\n step={1}\r\n onChange={(val: number) =>\r\n onSettingsChange({ backgroundBlurAmount: val })\r\n }\r\n formatValue={(v: number) => `${v}px`}\r\n />\r\n )}\r\n </SettingsGroup>\r\n </>\r\n )}\r\n </div>\r\n </div>\r\n )}\r\n </Menu>\r\n );\r\n};\r\n","\r\nimport React, { useRef, useEffect, useState, useLayoutEffect } from 'react';\r\nimport { ContextMenuItem } from '../../core/StrataCore';\r\nimport { CheckIcon } from '../Icons';\r\n\r\ninterface ContextMenuProps {\r\n x: number;\r\n y: number;\r\n items: ContextMenuItem[];\r\n onClose: () => void;\r\n containerWidth: number;\r\n containerHeight: number;\r\n}\r\n\r\nconst RenderContent = ({ content }: { content: string | React.ReactNode }) => {\r\n if (typeof content === 'string') {\r\n if (content.trim().startsWith('<')) return <span dangerouslySetInnerHTML={{ __html: content }} />;\r\n return <span>{content}</span>;\r\n }\r\n return <>{content}</>;\r\n};\r\n\r\nexport const ContextMenu = ({ x, y, items, onClose, containerWidth, containerHeight }: ContextMenuProps) => {\r\n const menuRef = useRef<HTMLDivElement>(null);\r\n const [layout, setLayout] = useState<{ top: number, left: number, maxHeight?: number, opacity: number }>({\r\n top: y,\r\n left: x,\r\n opacity: 0\r\n });\r\n\r\n useLayoutEffect(() => {\r\n if (!menuRef.current) return;\r\n\r\n const rect = menuRef.current.getBoundingClientRect();\r\n const width = rect.width;\r\n // Since we render all items initially, height is accurate\r\n const height = rect.height;\r\n\r\n let newLeft = x;\r\n let newTop = y;\r\n\r\n // Horizontal Logic: Flip left if overflowing right\r\n if (x + width > containerWidth - 10) {\r\n newLeft = x - width;\r\n }\r\n // Clamp left edge\r\n if (newLeft < 10) newLeft = 10;\r\n if (newLeft + width > containerWidth) newLeft = Math.max(10, containerWidth - width - 10);\r\n\r\n // Vertical Logic: Flip up if overflowing bottom\r\n if (y + height > containerHeight - 10) {\r\n newTop = y - height;\r\n }\r\n\r\n let availableHeight = containerHeight - 20;\r\n\r\n // Clamp top edge\r\n if (newTop < 10) newTop = 10;\r\n\r\n // If after flipping/clamping it still overflows bottom, we must shift up or limit height\r\n if (newTop + height > containerHeight - 10) {\r\n newTop = Math.max(10, containerHeight - height - 10);\r\n // If even at top it overflows, height is capped by container\r\n }\r\n\r\n setLayout({\r\n top: newTop,\r\n left: newLeft,\r\n maxHeight: availableHeight,\r\n opacity: 1\r\n });\r\n\r\n }, [x, y, items, containerWidth, containerHeight]);\r\n\r\n useEffect(() => {\r\n const handleClickOutside = (event: MouseEvent) => {\r\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\r\n onClose();\r\n }\r\n };\r\n document.addEventListener('mousedown', handleClickOutside);\r\n return () => document.removeEventListener('mousedown', handleClickOutside);\r\n }, [onClose]);\r\n\r\n return (\r\n <div\r\n ref={menuRef}\r\n className=\"absolute z-50 min-w-[200px] bg-[var(--bg-panel)] backdrop-blur-xl border-[length:var(--border-width)] border-white/10 shadow-2xl p-1.5 font-[family-name:var(--font-main)] overflow-y-auto hide-scrollbar flex flex-col\"\r\n style={{\r\n top: layout.top,\r\n left: layout.left,\r\n maxHeight: layout.maxHeight,\r\n opacity: layout.opacity,\r\n borderRadius: 'var(--radius-lg)'\r\n }}\r\n onClick={(e) => e.stopPropagation()}\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n >\r\n {items.map((item, index) => {\r\n // Separator Logic: 0 height with top border for a crisp line\r\n if (item.separator) {\r\n return <div key={index} className=\"h-0 border-t border-white/10 mx-2 my-1.5\" />;\r\n }\r\n\r\n // Label Logic\r\n if (item.isLabel) {\r\n return (\r\n <div key={index} className=\"px-3 py-1.5 text-[10px] font-bold text-zinc-500 uppercase tracking-wider select-none\">\r\n <RenderContent content={item.html || ''} />\r\n </div>\r\n );\r\n }\r\n\r\n // Standard Interactive Item\r\n return (\r\n <React.Fragment key={index}>\r\n <button\r\n onClick={() => {\r\n if (!item.disabled) {\r\n if (item.click) item.click(onClose);\r\n else if (item.onClick) item.onClick(onClose);\r\n }\r\n }}\r\n disabled={item.disabled}\r\n className={`w-full text-left px-3 py-2.5 flex items-center justify-between hover:bg-white/10 focus:bg-white/10 focus:outline-none transition-colors text-sm text-zinc-200 disabled:opacity-50 disabled:cursor-not-allowed group my-0.5`}\r\n style={{ borderRadius: 'var(--radius)' }}\r\n >\r\n <div className=\"flex items-center gap-3 overflow-hidden\">\r\n {item.icon && <span className=\"text-zinc-400 w-4 h-4 flex items-center justify-center shrink-0 group-hover:text-zinc-300 transition-colors\"><RenderContent content={item.icon} /></span>}\r\n <span className={`flex items-center font-medium truncate ${item.checked ? 'text-[var(--accent)]' : ''}`}><RenderContent content={item.html || ''} /></span>\r\n </div>\r\n {item.checked && <CheckIcon className=\"w-4 h-4 text-[var(--accent)] shrink-0 ml-2\" />}\r\n </button>\r\n {/* Legacy support for showBorder, though item.separator is preferred now */}\r\n {item.showBorder && <div className=\"h-0 border-t border-white/10 mx-2 my-1\" />}\r\n </React.Fragment>\r\n );\r\n })}\r\n </div>\r\n );\r\n};\r\n","\r\nimport React, { useEffect, useState } from 'react';\r\nimport { StrataCore } from '../../core/StrataCore';\r\nimport { CloseIcon } from '../Icons';\r\n\r\nexport const VideoInfo = ({ player, onClose }: { player: StrataCore, onClose: () => void }) => {\r\n const [stats, setStats] = useState<Record<string, string | number>>({});\r\n\r\n useEffect(() => {\r\n const update = () => {\r\n if (!player.video) return;\r\n const v = player.video;\r\n const q = (v as any).getVideoPlaybackQuality ? (v as any).getVideoPlaybackQuality() : null;\r\n\r\n setStats({\r\n 'Player Size': `${v.offsetWidth} x ${v.offsetHeight}`,\r\n 'Video Resolution': `${v.videoWidth} x ${v.videoHeight}`,\r\n 'Current Time': `${v.currentTime.toFixed(3)}s`,\r\n 'Duration': `${v.duration.toFixed(3)}s`,\r\n 'Volume': `${Math.round(v.volume * 100)}%`,\r\n 'Dropped Frames': q ? q.droppedVideoFrames : 'N/A',\r\n 'Buffer': v.buffered.length > 0 ? `${(v.buffered.end(v.buffered.length - 1) - v.currentTime).toFixed(2)}s` : '0s',\r\n 'Engine': player.store.get().sources[player.store.get().currentSourceIndex]?.type || 'native',\r\n 'URL': v.currentSrc\r\n });\r\n };\r\n update();\r\n const timer = setInterval(update, 1000);\r\n return () => clearInterval(timer);\r\n }, [player]);\r\n\r\n return (\r\n <div className=\"absolute inset-0 z-[60] flex items-center justify-center bg-black/60 backdrop-blur-sm p-4 animate-in fade-in duration-200\">\r\n <div\r\n className=\"bg-[var(--bg-panel)] border border-white/10 rounded-xl w-full max-w-md shadow-2xl relative font-mono text-xs text-zinc-300 flex flex-col\"\r\n style={{ borderRadius: 'var(--radius)', maxHeight: '90%' }}\r\n >\r\n <div className=\"p-5 pb-0 flex-shrink-0 relative\">\r\n <button\r\n onClick={(e) => { e.stopPropagation(); onClose(); }}\r\n className=\"absolute top-3 right-3 p-1.5 text-zinc-400 hover:text-white hover:bg-white/10 rounded-full transition-colors\"\r\n >\r\n <CloseIcon className=\"w-4 h-4\" />\r\n </button>\r\n <h3 className=\"text-sm font-bold text-white mb-4 uppercase tracking-wider border-b border-white/10 pb-2\">Video Statistics</h3>\r\n </div>\r\n\r\n <div className=\"overflow-y-auto hide-scrollbar p-5 pt-0 space-y-2.5 flex-1 min-h-0\">\r\n {Object.entries(stats).map(([k, v]) => (\r\n <div key={k} className=\"flex flex-col sm:flex-row sm:justify-between sm:items-center gap-1\">\r\n <span className=\"text-zinc-500 font-bold shrink-0\">{k}</span>\r\n <span className=\"text-zinc-200 truncate select-all font-medium bg-white/5 px-1.5 py-0.5 rounded break-all text-right\" title={String(v)}>{String(v)}</span>\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n}\r\n","\r\nimport React, { useEffect, useRef, useState, useSyncExternalStore, useCallback, useMemo, useLayoutEffect } from 'react';\r\nimport { createPortal } from 'react-dom';\r\nimport { StrataCore, PlayerState, TextTrackConfig, SubtitleSettings, PlayerTheme, StrataConfig, getResolvedState, DEFAULT_STATE, IPlugin, PlayerSource, ControlItem, ContextMenuItem, SettingItem, VideoFit } from '../core/StrataCore';\r\nimport { formatTime, parseVTT, ThumbnailCue } from '../utils/playerUtils';\r\nimport { useTransition } from './hooks/useTransition';\r\nimport { NotificationContainer } from './components/NotificationContainer';\r\nimport { SubtitleOverlay } from './components/SubtitleOverlay';\r\nimport { Menu, MenuItem, MenuHeader, MenuDivider, MenuExplorer } from './components/Menu';\r\nimport { SubtitleMenu } from './components/SubtitleMenu';\r\nimport { ContextMenu } from './components/ContextMenu';\r\nimport { VideoInfo } from './components/VideoInfo';\r\nimport { SettingsGroup, Toggle, Slider, Select } from './components/SettingsPrimitives';\r\nimport {\r\n PlayIcon, PauseIcon, VolumeHighIcon, VolumeLowIcon, VolumeMuteIcon,\r\n MaximizeIcon, MinimizeIcon, SettingsIcon, PipIcon,\r\n SubtitleIcon, DownloadIcon, Replay10Icon, Forward10Icon,\r\n LoaderIcon, CastIcon, UsersIcon, PaletteIcon, CheckIcon,\r\n CustomizeIcon, CameraIcon, LockIcon, UnlockIcon, WebFullscreenIcon,\r\n FastForwardIcon, RatioIcon, ExpandIcon, InfoIcon,\r\n ServerIcon, LayersIcon, CropIcon, SpeakerIcon, FlipIcon, GaugeIcon, MusicIcon, WifiIcon, AlertCircleIcon, QualityIcon, VideoFlipIcon, FileCheckIcon, SunIcon, LayoutTemplateIcon\r\n} from './Icons';\r\n\r\ndeclare module 'react' {\r\n namespace JSX {\r\n interface IntrinsicElements {\r\n 'google-cast-launcher': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement>;\r\n }\r\n }\r\n}\r\n\r\n// Helper to determine best contrast color (black or white) for a given hex background\r\nfunction getContrastColor(hex: string) {\r\n if (!hex) return '#ffffff';\r\n hex = hex.replace('#', '');\r\n if (hex.length === 3) {\r\n hex = hex.split('').map(char => char + char).join('');\r\n }\r\n const r = parseInt(hex.substring(0, 2), 16);\r\n const g = parseInt(hex.substring(2, 4), 16);\r\n const b = parseInt(hex.substring(4, 6), 16);\r\n const yiq = ((r * 299) + (g * 587) + (b * 114)) / 1000;\r\n return (yiq >= 128) ? '#000000' : '#ffffff';\r\n}\r\n\r\n// --- Main Player Component ---\r\n\r\ninterface StrataPlayerProps extends StrataConfig {\r\n src?: string; // Optional if sources are provided\r\n type?: string; // Optional: Explicitly define type for the src (e.g. 'hls', 'dash')\r\n sources?: PlayerSource[]; // Array of sources\r\n poster?: string;\r\n thumbnails?: string; // URL to VTT thumbnails\r\n textTracks?: TextTrackConfig[];\r\n plugins?: IPlugin[]; // Allow injecting plugins from outside\r\n autoPlay?: boolean; // Added prop\r\n onGetInstance?: (core: StrataCore) => void; // Expose instance\r\n}\r\n\r\nconst THEME_COLORS = [\r\n { label: 'Strata', value: '#6366f1' },\r\n { label: 'Emerald', value: '#10b981' },\r\n { label: 'Rose', value: '#f43f5e' },\r\n { label: 'Amber', value: '#f59e0b' },\r\n { label: 'Sky', value: '#0ea5e9' },\r\n { label: 'Violet', value: '#8b5cf6' },\r\n];\r\n\r\nconst THEMES: { label: string, value: PlayerTheme, color: string }[] = [\r\n { label: 'Default', value: 'default', color: '#6366f1' },\r\n { label: 'Pixel', value: 'pixel', color: '#ef4444' },\r\n { label: 'Game', value: 'game', color: '#eab308' },\r\n { label: 'Hacker', value: 'hacker', color: '#22c55e' },\r\n];\r\n\r\n// Helper to render HTML strings safely or pass nodes through\r\nconst HtmlOrNode = ({ content, className, style }: { content: string | React.ReactNode, className?: string, style?: React.CSSProperties }) => {\r\n if (typeof content === 'string') {\r\n if (content.trim().startsWith('<')) {\r\n return <div className={className} style={style} dangerouslySetInnerHTML={{ __html: content }} />;\r\n }\r\n return <div className={className} style={style}>{content}</div>;\r\n }\r\n return <div className={className} style={style}>{content}</div>;\r\n};\r\n\r\nexport const StrataPlayer = (props: StrataPlayerProps) => {\r\n const { src, type, sources, poster, autoPlay, thumbnails, textTracks, plugins, onGetInstance, ...config } = props;\r\n\r\n // Default configs for optionals\r\n const useScreenshot = config.screenshot ?? false;\r\n const usePip = config.pip ?? true;\r\n const useSetting = config.setting ?? true;\r\n const useFullscreen = config.fullscreen ?? true;\r\n const useFullscreenWeb = config.fullscreenWeb ?? false;\r\n const useLock = config.lock ?? false;\r\n const useFastForward = config.fastForward ?? true;\r\n const useFlip = config.flip ?? true;\r\n const useAspectRatio = config.aspectRatio ?? true;\r\n const useHotKey = config.hotKey ?? true;\r\n const isBackdrop = config.backdrop ?? true;\r\n const useGestureSeek = config.gestureSeek ?? false;\r\n const useCenterControls = config.centerControls ?? true;\r\n const fetchTimeout = config.fetchTimeout ?? 30000;\r\n\r\n // Default AutoOrientation to true\r\n const useAutoOrientation = config.autoOrientation ?? true;\r\n\r\n const containerRef = useRef<HTMLDivElement>(null);\r\n const [player, setPlayer] = useState<StrataCore | null>(null);\r\n const [hasPlayed, setHasPlayed] = useState(false);\r\n const [playerHeight, setPlayerHeight] = useState(0);\r\n const [playerWidth, setPlayerWidth] = useState(0);\r\n const [isMobile, setIsMobile] = useState(false);\r\n\r\n // Resolve initial state based on props + defaults + localStorage BEFORE mounting\r\n const initialState = useMemo(() => getResolvedState(config), []);\r\n\r\n const state = useSyncExternalStore<PlayerState>(\r\n useCallback((cb) => player ? player.store.subscribe(cb) : () => { }, [player]),\r\n () => player ? player.store.get() : initialState,\r\n () => initialState\r\n );\r\n\r\n const accentContrast = useMemo(() => getContrastColor(state.themeColor), [state.themeColor]);\r\n\r\n const [settingsOpen, setSettingsOpen] = useState(false);\r\n const [subtitleMenuOpen, setSubtitleMenuOpen] = useState(false);\r\n // Active menu in Settings. Supports built-ins + dynamic 'custom-{index}' for user settings\r\n const [activeMenu, setActiveMenu] = useState<string>('main');\r\n\r\n // State for Custom Control Popovers (track ID of open control)\r\n const [activeControlId, setActiveControlId] = useState<string | null>(null);\r\n // Ref to track last active control for exit animations\r\n const lastActiveControlId = useRef<string | null>(null);\r\n if (activeControlId) lastActiveControlId.current = activeControlId;\r\n\r\n // Context Menu State\r\n const [contextMenu, setContextMenu] = useState<{ x: number, y: number, visible: boolean }>({ x: 0, y: 0, visible: false });\r\n const [showVideoInfo, setShowVideoInfo] = useState(false);\r\n\r\n // Transition States - Increased to 300ms to match CSS transition-duration\r\n const settingsTransition = useTransition(settingsOpen, 300);\r\n const subtitleTransition = useTransition(subtitleMenuOpen, 300);\r\n const controlTransition = useTransition(!!activeControlId, 300);\r\n\r\n // Helper to close all menus\r\n const closeAllMenus = useCallback(() => {\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n setSettingsOpen(false);\r\n setSubtitleMenuOpen(false);\r\n setActiveControlId(null);\r\n setContextMenu(prev => ({ ...prev, visible: false }));\r\n }\r\n }, [settingsOpen, subtitleMenuOpen, activeControlId, contextMenu.visible]);\r\n\r\n // Global listener to close popovers on outside click (e.g. layers, empty control bar space)\r\n useEffect(() => {\r\n const handleGlobalClick = (e: MouseEvent | TouchEvent) => {\r\n // Since Menu components stop propagation, any click reaching document is \"outside\"\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n closeAllMenus();\r\n }\r\n };\r\n\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n document.addEventListener('click', handleGlobalClick);\r\n document.addEventListener('touchstart', handleGlobalClick);\r\n }\r\n \r\n return () => {\r\n document.removeEventListener('click', handleGlobalClick);\r\n document.removeEventListener('touchstart', handleGlobalClick);\r\n };\r\n }, [settingsOpen, subtitleMenuOpen, activeControlId, contextMenu.visible, closeAllMenus]);\r\n\r\n // Seek & Scrubbing State\r\n const [isScrubbing, setIsScrubbing] = useState(false);\r\n const [scrubbingTime, setScrubbingTime] = useState(0);\r\n const [isVolumeScrubbing, setIsVolumeScrubbing] = useState(false);\r\n const [isVolumeHovered, setIsVolumeHovered] = useState(false);\r\n const [isVolumeLocked, setIsVolumeLocked] = useState(false); // For mobile/touch\r\n \r\n // Brightness Gesture State\r\n const [isBrightnessAdjusting, setIsBrightnessAdjusting] = useState(false);\r\n\r\n const [thumbnailCues, setThumbnailCues] = useState<ThumbnailCue[]>([]);\r\n const [hoverTime, setHoverTime] = useState<number | null>(null);\r\n const [hoverPos, setHoverPos] = useState<number>(0);\r\n const [currentThumbnail, setCurrentThumbnail] = useState<ThumbnailCue | null>(null);\r\n const [seekAnimation, setSeekAnimation] = useState<{ type: 'forward' | 'rewind', id: number } | null>(null);\r\n const [skipTrigger, setSkipTrigger] = useState<'forward' | 'rewind' | null>(null);\r\n\r\n // Fast Forward State\r\n const [isFastForwarding, setIsFastForwarding] = useState(false);\r\n const fastForwardTimerRef = useRef<any>(null);\r\n const originalRateRef = useRef<number>(1);\r\n\r\n // Gesture Refs\r\n const touchStartX = useRef<number | null>(null);\r\n const touchStartY = useRef<number | null>(null);\r\n const touchStartTime = useRef<number>(0);\r\n const touchStartVolume = useRef<number>(0);\r\n const touchStartBrightness = useRef<number>(0);\r\n const gestureModeRef = useRef<'seek' | 'volume' | 'brightness' | null>(null);\r\n const isDraggingRef = useRef(false);\r\n\r\n const clickTimeoutRef = useRef<any>(null);\r\n const controlsTimeoutRef = useRef<any>(null);\r\n const progressBarRef = useRef<HTMLDivElement>(null);\r\n const volumeBarRef = useRef<HTMLDivElement>(null);\r\n const animationCleanupRef = useRef<any>(null);\r\n\r\n // Force re-attach player to container when WebFullscreen toggles (Portal)\r\n useLayoutEffect(() => {\r\n if (player && containerRef.current) {\r\n player.attach(containerRef.current);\r\n }\r\n }, [player, state.isWebFullscreen]);\r\n\r\n // Separate ResizeObserver to ensure it tracks the correct DOM node through portal transitions\r\n useLayoutEffect(() => {\r\n if (!containerRef.current) return;\r\n\r\n const updateDims = () => {\r\n if (containerRef.current) {\r\n setPlayerHeight(containerRef.current.clientHeight);\r\n setPlayerWidth(containerRef.current.clientWidth);\r\n }\r\n };\r\n\r\n // Initialize size immediately\r\n updateDims();\r\n\r\n const observer = new ResizeObserver((entries) => {\r\n for (const entry of entries) {\r\n setPlayerHeight(entry.contentRect.height);\r\n setPlayerWidth(entry.contentRect.width);\r\n }\r\n });\r\n observer.observe(containerRef.current);\r\n\r\n return () => {\r\n observer.disconnect();\r\n };\r\n }, [state.isWebFullscreen]); // Re-bind when portal state changes\r\n\r\n useEffect(() => {\r\n setIsMobile('ontouchstart' in window || navigator.maxTouchPoints > 0);\r\n\r\n if (!containerRef.current) return;\r\n // Pass poster into core config so metadata can use it\r\n const core = new StrataCore({ ...config, poster });\r\n\r\n // Register plugins\r\n if (plugins && plugins.length > 0) {\r\n plugins.forEach(p => core.use(p));\r\n }\r\n\r\n core.attach(containerRef.current);\r\n setPlayer(core);\r\n if (onGetInstance) onGetInstance(core);\r\n\r\n // Core Init complete\r\n\r\n return () => {\r\n core.destroy();\r\n setPlayer(null);\r\n };\r\n }, []); // Only runs once on mount to setup Core\r\n\r\n // Reactive Prop Updates\r\n useEffect(() => {\r\n if (!player) return;\r\n const updates: any = {};\r\n if (config.theme !== undefined && config.theme !== state.theme) updates.theme = config.theme;\r\n if (config.themeColor !== undefined && config.themeColor !== state.themeColor) updates.themeColor = config.themeColor;\r\n if (config.iconSize !== undefined && config.iconSize !== state.iconSize) updates.iconSize = config.iconSize;\r\n if (config.brightness !== undefined && Math.abs(config.brightness - state.brightness) > 0.05) player.setBrightness(config.brightness);\r\n \r\n // Update Video Fit if prop changes\r\n if (config.videoFit !== undefined && config.videoFit !== state.videoFit) player.setVideoFit(config.videoFit);\r\n\r\n if (Object.keys(updates).length > 0) {\r\n player.setAppearance(updates);\r\n }\r\n\r\n if (config.volume !== undefined && Math.abs(config.volume - state.volume) > 0.01) player.setVolume(config.volume);\r\n if (config.muted !== undefined && config.muted !== state.isMuted) {\r\n if (config.muted) player.video.muted = true;\r\n else { player.video.muted = false; }\r\n }\r\n }, [player, config.theme, config.themeColor, config.iconSize, config.volume, config.muted, config.brightness, config.videoFit]);\r\n\r\n useEffect(() => {\r\n if (!player) return;\r\n const tracks = textTracks || [];\r\n if (sources && sources.length > 0) {\r\n setHasPlayed(false);\r\n player.setSources(sources, tracks);\r\n } else if (src) {\r\n setHasPlayed(false);\r\n player.setSources([{ url: src, type: type || 'auto' }], tracks);\r\n }\r\n }, [src, type, sources, textTracks, player]);\r\n\r\n useEffect(() => {\r\n if (player && autoPlay) {\r\n player.play().catch(() => {\r\n // Autoplay blocked handling\r\n player.pause(); \r\n // Explicitly sync state because video.pause() might not trigger event if already paused/failed\r\n player.store.setState({ isPlaying: false, isBuffering: false });\r\n player.notify({ type: 'warning', message: 'Autoplay blocked by browser. Click play to start.', duration: 5000 });\r\n });\r\n }\r\n }, [player, autoPlay]);\r\n\r\n useEffect(() => {\r\n if (state.isPlaying && !hasPlayed) setHasPlayed(true);\r\n }, [state.isPlaying, hasPlayed]);\r\n\r\n useEffect(() => {\r\n if (thumbnails && player) {\r\n parseVTT(thumbnails, player.notify.bind(player), fetchTimeout).then(setCues => setThumbnailCues(setCues));\r\n } else setThumbnailCues([]);\r\n }, [thumbnails, player, fetchTimeout]);\r\n\r\n // Safety cleanup for seek animation if onAnimationEnd fails\r\n useEffect(() => {\r\n if (seekAnimation) {\r\n if (animationCleanupRef.current) clearTimeout(animationCleanupRef.current);\r\n animationCleanupRef.current = setTimeout(() => {\r\n setSeekAnimation(null);\r\n }, 600); // slightly longer than 500ms animation\r\n }\r\n return () => {\r\n if (animationCleanupRef.current) clearTimeout(animationCleanupRef.current);\r\n };\r\n }, [seekAnimation]);\r\n\r\n useEffect(() => {\r\n const handleKeyDown = (e: KeyboardEvent) => {\r\n if (!player || !useHotKey) return;\r\n if (document.activeElement?.tagName === 'INPUT') return;\r\n const key = e.key.toLowerCase();\r\n switch (key) {\r\n case ' ': case 'k': e.preventDefault(); player.togglePlay(); break;\r\n case 'arrowright': e.preventDefault(); player.skip(5); break;\r\n case 'arrowleft': e.preventDefault(); player.skip(-5); break;\r\n case 'arrowup': e.preventDefault(); player.setVolume(player.video.volume + 0.1); break;\r\n case 'arrowdown': e.preventDefault(); player.setVolume(player.video.volume - 0.1); break;\r\n case 'f': e.preventDefault(); player.toggleFullscreen(); break;\r\n case 'm': e.preventDefault(); player.toggleMute(); break;\r\n case 'escape':\r\n // Check store directly to avoid stale state in closure\r\n if (player.store.get().isWebFullscreen) {\r\n e.preventDefault();\r\n player.toggleWebFullscreen();\r\n }\r\n break;\r\n }\r\n };\r\n window.addEventListener('keydown', handleKeyDown);\r\n return () => window.removeEventListener('keydown', handleKeyDown);\r\n }, [player, useHotKey]);\r\n\r\n const handleMouseMove = () => {\r\n if (!player) return;\r\n // Even if locked, we want to wake up controls so the lock button becomes visible\r\n player.setControlsVisible(true);\r\n if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) return;\r\n controlsTimeoutRef.current = setTimeout(() => {\r\n if (!state.isPlaying || settingsOpen || subtitleMenuOpen || activeControlId) return;\r\n player.setControlsVisible(false);\r\n }, 2500);\r\n };\r\n\r\n useEffect(() => {\r\n if (!player) return;\r\n if (!settingsOpen && !subtitleMenuOpen && !activeControlId && state.isPlaying) handleMouseMove();\r\n else if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n player.setControlsVisible(true);\r\n if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);\r\n }\r\n }, [settingsOpen, subtitleMenuOpen, activeControlId, state.isPlaying, player]);\r\n\r\n // --- Fast Forward Logic ---\r\n const startFastForward = useCallback(() => {\r\n if (!useFastForward || !player || !state.isPlaying || state.isLocked) return;\r\n\r\n // Prevent gestures if menus are open\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n return;\r\n }\r\n\r\n originalRateRef.current = player.video.playbackRate;\r\n fastForwardTimerRef.current = setTimeout(() => {\r\n player.video.playbackRate = 2;\r\n setIsFastForwarding(true);\r\n }, 500); // 500ms delay for long press\r\n }, [useFastForward, player, state.isPlaying, state.isLocked, settingsOpen, subtitleMenuOpen, activeControlId]);\r\n\r\n const stopFastForward = useCallback(() => {\r\n if (fastForwardTimerRef.current) clearTimeout(fastForwardTimerRef.current);\r\n if (isFastForwarding && player) {\r\n player.video.playbackRate = originalRateRef.current; // Restore original rate\r\n setIsFastForwarding(false);\r\n }\r\n }, [isFastForwarding, player]);\r\n\r\n // --- Gesture Logic (Seek, Volume, Brightness) ---\r\n const handleTouchStart = (e: React.TouchEvent) => {\r\n startFastForward();\r\n\r\n // Prevent gestures if menus are open\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n return;\r\n }\r\n\r\n if (state.isLocked) return;\r\n\r\n touchStartX.current = e.touches[0].clientX;\r\n touchStartY.current = e.touches[0].clientY;\r\n \r\n touchStartTime.current = state.currentTime;\r\n touchStartVolume.current = state.volume;\r\n touchStartBrightness.current = state.brightness;\r\n \r\n isDraggingRef.current = false;\r\n gestureModeRef.current = null;\r\n };\r\n\r\n const handleTouchMove = (e: React.TouchEvent) => {\r\n if (state.isLocked || !player) return;\r\n if (touchStartX.current === null || touchStartY.current === null) return;\r\n\r\n const clientX = e.touches[0].clientX;\r\n const clientY = e.touches[0].clientY;\r\n const deltaX = clientX - touchStartX.current;\r\n const deltaY = clientY - touchStartY.current; // Moving down is positive\r\n\r\n // Determine Gesture Mode if not yet set\r\n if (!gestureModeRef.current) {\r\n // Threshold\r\n if (Math.abs(deltaX) > 10 || Math.abs(deltaY) > 10) {\r\n isDraggingRef.current = true;\r\n // Stop any pending fast forward\r\n stopFastForward();\r\n\r\n // Determine direction\r\n if (Math.abs(deltaX) > Math.abs(deltaY)) {\r\n // Horizontal -> Seek (if enabled)\r\n if (useGestureSeek) {\r\n gestureModeRef.current = 'seek';\r\n setIsScrubbing(true);\r\n }\r\n } else {\r\n // Vertical\r\n // Left half = Brightness, Right half = Volume\r\n const halfScreen = containerRef.current ? containerRef.current.clientWidth / 2 : window.innerWidth / 2;\r\n if (touchStartX.current < halfScreen) {\r\n gestureModeRef.current = 'brightness';\r\n setIsBrightnessAdjusting(true);\r\n } else {\r\n gestureModeRef.current = 'volume';\r\n setIsVolumeLocked(true); // Re-use volume lock state to show overlay\r\n }\r\n }\r\n }\r\n }\r\n\r\n // Execute Gesture Logic\r\n if (gestureModeRef.current === 'seek' && containerRef.current && state.duration) {\r\n const rect = containerRef.current.getBoundingClientRect();\r\n const deltaRatio = deltaX / rect.width;\r\n const newTime = Math.max(0, Math.min(state.duration, touchStartTime.current + (deltaRatio * state.duration)));\r\n setScrubbingTime(newTime);\r\n }\r\n else if (gestureModeRef.current === 'volume') {\r\n // Drag Up (negative deltaY) -> Increase volume\r\n // Drag Down (positive deltaY) -> Decrease volume\r\n // Sensitivity: Full height = 100% volume change\r\n const sensitivity = 1.5; \r\n const deltaPct = -(deltaY / (containerRef.current?.clientHeight || 300)) * sensitivity;\r\n player.setVolume(Math.max(0, Math.min(1, touchStartVolume.current + deltaPct)));\r\n }\r\n else if (gestureModeRef.current === 'brightness') {\r\n // Drag Up -> Increase Brightness\r\n // Max brightness usually 1.5 or 2.0 (150-200%). Let's cap at 2.0 (200%)\r\n const sensitivity = 1.5;\r\n const deltaPct = -(deltaY / (containerRef.current?.clientHeight || 300)) * sensitivity;\r\n player.setBrightness(Math.max(0, Math.min(2, touchStartBrightness.current + deltaPct)));\r\n }\r\n };\r\n\r\n const handleTouchEnd = (e: React.TouchEvent) => {\r\n stopFastForward();\r\n\r\n if (gestureModeRef.current === 'seek') {\r\n player?.seek(scrubbingTime);\r\n setIsScrubbing(false);\r\n } else if (gestureModeRef.current === 'volume') {\r\n setIsVolumeLocked(false);\r\n } else if (gestureModeRef.current === 'brightness') {\r\n setIsBrightnessAdjusting(false);\r\n }\r\n\r\n isDraggingRef.current = false;\r\n gestureModeRef.current = null;\r\n touchStartX.current = null;\r\n touchStartY.current = null;\r\n };\r\n\r\n const calculateTimeFromEvent = (e: React.MouseEvent | React.TouchEvent | MouseEvent | TouchEvent) => {\r\n if (!progressBarRef.current || !state.duration) return 0;\r\n const rect = progressBarRef.current.getBoundingClientRect();\r\n const clientX = 'touches' in e ? (e as TouchEvent).touches[0].clientX : (e as MouseEvent).clientX;\r\n const pct = Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\r\n return pct * state.duration;\r\n };\r\n\r\n const handleSeekStart = (e: React.MouseEvent | React.TouchEvent) => {\r\n e.stopPropagation();\r\n if (state.isLocked) return;\r\n\r\n // Ensure menus close when interacting with progress bar\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n }\r\n\r\n setIsScrubbing(true);\r\n setScrubbingTime(calculateTimeFromEvent(e));\r\n const handleMove = (moveEvent: MouseEvent | TouchEvent) => setScrubbingTime(calculateTimeFromEvent(moveEvent));\r\n const handleUp = (upEvent: MouseEvent | TouchEvent) => {\r\n player?.seek(calculateTimeFromEvent(upEvent));\r\n setIsScrubbing(false);\r\n document.removeEventListener('mousemove', handleMove); document.removeEventListener('touchmove', handleMove);\r\n document.removeEventListener('mouseup', handleUp); document.removeEventListener('touchend', handleUp);\r\n };\r\n document.addEventListener('mousemove', handleMove); document.addEventListener('touchmove', handleMove);\r\n document.addEventListener('mouseup', handleUp); document.addEventListener('touchend', handleUp);\r\n };\r\n\r\n const calculateVolumeFromEvent = (e: React.MouseEvent | React.TouchEvent | MouseEvent | TouchEvent) => {\r\n if (!volumeBarRef.current) return 0;\r\n const rect = volumeBarRef.current.getBoundingClientRect();\r\n const clientX = 'touches' in e ? (e as TouchEvent).touches[0].clientX : (e as MouseEvent).clientX;\r\n return Math.max(0, Math.min(1, (clientX - rect.left) / rect.width));\r\n };\r\n\r\n const handleVolumeStart = (e: React.MouseEvent | React.TouchEvent) => {\r\n e.stopPropagation();\r\n if (!player || state.isLocked) return;\r\n setIsVolumeScrubbing(true);\r\n player.setVolume(calculateVolumeFromEvent(e));\r\n const handleMove = (moveEvent: MouseEvent | TouchEvent) => player.setVolume(calculateVolumeFromEvent(moveEvent));\r\n const handleUp = () => {\r\n setIsVolumeScrubbing(false);\r\n document.removeEventListener('mousemove', handleMove); document.removeEventListener('touchmove', handleMove);\r\n document.removeEventListener('mouseup', handleUp); document.removeEventListener('touchend', handleUp);\r\n };\r\n document.addEventListener('mousemove', handleMove); document.addEventListener('touchmove', handleMove);\r\n document.addEventListener('mouseup', handleUp); document.addEventListener('touchend', handleUp);\r\n };\r\n\r\n const handleProgressMove = (e: React.MouseEvent<HTMLDivElement>) => {\r\n if (!state.duration || state.isLive) return;\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n const percent = (e.clientX - rect.left) / rect.width;\r\n const time = percent * state.duration;\r\n setHoverPos(percent * 100);\r\n setHoverTime(time);\r\n if (thumbnailCues.length > 0) setCurrentThumbnail(thumbnailCues.find(c => time >= c.start && time < c.end) || null);\r\n };\r\n\r\n const triggerSkip = (direction: 'forward' | 'rewind') => {\r\n if (!player || state.isLocked) return;\r\n player.skip(direction === 'forward' ? 10 : -10);\r\n setSkipTrigger(direction);\r\n setTimeout(() => setSkipTrigger(null), 300);\r\n };\r\n\r\n const handleContainerClick = (e: React.MouseEvent<HTMLDivElement>) => {\r\n if (!player) return;\r\n\r\n // If we just finished a drag gesture, ignore the click\r\n if (isDraggingRef.current) {\r\n isDraggingRef.current = false;\r\n return;\r\n }\r\n\r\n // Priority 1: Close menus on outside click.\r\n // If a menu is open, clicking the container should ONLY close the menu, NOT toggle play/pause.\r\n if (settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible) {\r\n closeAllMenus();\r\n return;\r\n }\r\n\r\n if (isVolumeLocked) setIsVolumeLocked(false);\r\n if (isBrightnessAdjusting) setIsBrightnessAdjusting(false);\r\n\r\n // Wake up controls so lock button is visible if locked\r\n player.setControlsVisible(true);\r\n if (controlsTimeoutRef.current) clearTimeout(controlsTimeoutRef.current);\r\n controlsTimeoutRef.current = setTimeout(() => {\r\n if (!state.isPlaying || settingsOpen || subtitleMenuOpen || activeControlId) return;\r\n player.setControlsVisible(false);\r\n }, 2500);\r\n\r\n // If locked, do nothing else (prevent play/pause, seek, double tap)\r\n if (state.isLocked) return;\r\n\r\n // Priority 2: Toggle Play/Pause or handle gestures\r\n const rect = e.currentTarget.getBoundingClientRect();\r\n const x = e.clientX - rect.left;\r\n const width = rect.width;\r\n const now = Date.now();\r\n\r\n if (clickTimeoutRef.current) {\r\n clearTimeout(clickTimeoutRef.current);\r\n clickTimeoutRef.current = null;\r\n // Double Click Logic\r\n if (x < width * 0.35) { triggerSkip('rewind'); setSeekAnimation({ type: 'rewind', id: now }); }\r\n else if (x > width * 0.65) { triggerSkip('forward'); setSeekAnimation({ type: 'forward', id: now }); }\r\n else player.toggleFullscreen();\r\n } else {\r\n // Single Click Logic (Delayed to wait for potential double click)\r\n clickTimeoutRef.current = setTimeout(() => {\r\n player.togglePlay();\r\n clickTimeoutRef.current = null;\r\n }, 250);\r\n }\r\n };\r\n\r\n const handleContextMenu = (e: React.MouseEvent) => {\r\n e.preventDefault();\r\n e.stopPropagation(); // Prevent container click from firing\r\n if (state.isLocked) return;\r\n\r\n // Close other menus first\r\n closeAllMenus();\r\n\r\n const rect = containerRef.current?.getBoundingClientRect();\r\n if (!rect) return;\r\n\r\n // Small timeout to allow state updates (closeAllMenus) to propagate\r\n // before opening the new context menu\r\n requestAnimationFrame(() => {\r\n setContextMenu({\r\n visible: true,\r\n x: e.clientX - rect.left,\r\n y: e.clientY - rect.top\r\n });\r\n });\r\n };\r\n\r\n const handleVolumeIconClick = (e: React.MouseEvent | React.TouchEvent) => {\r\n e.stopPropagation();\r\n closeAllMenus(); // Close context menu if open\r\n\r\n if (isVolumeLocked) {\r\n setIsVolumeLocked(false);\r\n return;\r\n }\r\n\r\n if (isMobile) {\r\n setIsVolumeLocked(true);\r\n } else {\r\n // Desktop default behavior: Mute toggle\r\n player?.toggleMute();\r\n }\r\n };\r\n\r\n const VolIcon = state.isMuted || state.volume === 0 ? VolumeMuteIcon : state.volume < 0.5 ? VolumeLowIcon : VolumeHighIcon;\r\n\r\n const menuMaxHeight = Math.max(100, playerHeight - 120);\r\n\r\n const getIconClass = () => {\r\n switch (state.iconSize) {\r\n case 'small': return 'w-4 h-4';\r\n case 'large': return 'w-6 h-6';\r\n default: return 'w-5 h-5';\r\n }\r\n }\r\n const getButtonClass = () => {\r\n switch (state.iconSize) {\r\n case 'small': return 'p-2 min-w-[32px] min-h-[32px]';\r\n case 'large': return 'p-3 min-w-[44px] min-h-[44px]'; // Larger touch targets\r\n default: return 'p-2.5 min-w-[36px] min-h-[36px]';\r\n }\r\n }\r\n const iconClass = getIconClass();\r\n const btnClass = getButtonClass();\r\n\r\n const getCenterSizes = () => {\r\n switch (state.iconSize) {\r\n case 'small':\r\n return {\r\n playBtn: 'w-14 h-14',\r\n playIcon: 'w-6 h-6',\r\n skipBtn: 'w-10 h-10',\r\n skipIcon: 'w-5 h-5'\r\n };\r\n case 'large':\r\n return {\r\n playBtn: 'w-24 h-24',\r\n playIcon: 'w-12 h-12',\r\n skipBtn: 'w-16 h-16',\r\n skipIcon: 'w-8 h-8'\r\n };\r\n default: // medium\r\n return {\r\n playBtn: 'w-20 h-20',\r\n playIcon: 'w-9 h-9',\r\n skipBtn: 'w-12 h-12',\r\n skipIcon: 'w-6 h-6'\r\n };\r\n }\r\n }\r\n const center = getCenterSizes();\r\n\r\n // Bottom Controls Visibility: Show if paused, or actively showing controls, or menus open. \r\n // HIDDEN IF LOCKED.\r\n // Use state.controlsVisible from Core to sync with external listeners (like ArtPlayer consumers)\r\n const isControlsVisible = !state.isLocked && (state.controlsVisible || !state.isPlaying || settingsOpen || subtitleMenuOpen || activeControlId || contextMenu.visible);\r\n const isVolumeVisible = isVolumeHovered || isVolumeScrubbing || isVolumeLocked;\r\n\r\n const backdropClass = isBackdrop ? 'backdrop-blur-xl bg-black/80' : 'bg-black/95';\r\n\r\n // --- Dynamic Controls Rendering ---\r\n const controls: ControlItem[] = useMemo(() => {\r\n const items: ControlItem[] = [\r\n { id: 'play', position: 'left', index: 10, isBuiltIn: true },\r\n { id: 'volume', position: 'left', index: 20, isBuiltIn: true },\r\n { id: 'time', position: 'left', index: 30, isBuiltIn: true },\r\n { id: 'subtitle', position: 'right', index: 80, isBuiltIn: true },\r\n { id: 'screenshot', position: 'right', index: 85, isBuiltIn: true },\r\n { id: 'pip', position: 'right', index: 90, isBuiltIn: true },\r\n { id: 'download', position: 'right', index: 95, isBuiltIn: true },\r\n { id: 'settings', position: 'right', index: 100, isBuiltIn: true },\r\n { id: 'fullscreenWeb', position: 'right', index: 110, isBuiltIn: true },\r\n { id: 'fullscreen', position: 'right', index: 120, isBuiltIn: true },\r\n ];\r\n\r\n if (config.controls) {\r\n // Merge user controls\r\n config.controls.forEach(c => {\r\n const existing = items.find(i => i.id === c.id);\r\n if (existing) {\r\n Object.assign(existing, c); // Override\r\n } else {\r\n items.push(c);\r\n }\r\n });\r\n }\r\n\r\n // Detect HLS source for Download Menu Options\r\n const currentSource = state.sources[state.currentSourceIndex] || { url: src || '', type: type || 'auto' };\r\n const isHls = currentSource.type === 'hls' || currentSource.url.includes('.m3u8');\r\n\r\n // Apply Download Menu logic if HLS\r\n const downloadControl = items.find(i => i.id === 'download');\r\n if (downloadControl) {\r\n if (isHls) {\r\n downloadControl.children = [\r\n { html: 'Download Format', isLabel: true },\r\n { \r\n html: 'MPEG-TS', \r\n value: 'Original Stream', \r\n icon: <FileCheckIcon className=\"w-3.5 h-3.5\" />,\r\n onClick: () => player?.download({ format: 'ts' }) \r\n },\r\n { \r\n html: 'MP4', \r\n value: 'Converted', \r\n icon: <CustomizeIcon className=\"w-3.5 h-3.5\" />,\r\n onClick: () => player?.download({ format: 'mp4' }) \r\n }\r\n ];\r\n downloadControl.onClick = undefined; // Ensure toggle logic works by removing click handler\r\n } else {\r\n downloadControl.children = undefined;\r\n downloadControl.onClick = (p) => p.download();\r\n }\r\n }\r\n\r\n // Filter based on config toggles\r\n return items.filter(c => {\r\n if (c.id === 'screenshot' && !useScreenshot) return false;\r\n if (c.id === 'pip' && !usePip) return false;\r\n if (c.id === 'settings' && !useSetting) return false;\r\n if (c.id === 'fullscreen' && !useFullscreen) return false;\r\n if (c.id === 'fullscreenWeb' && !useFullscreenWeb) return false;\r\n return true;\r\n }).sort((a, b) => a.index - b.index);\r\n }, [config.controls, useScreenshot, usePip, useSetting, useFullscreen, useFullscreenWeb, state.currentSourceIndex, state.sources, src, type]);\r\n\r\n const renderControl = (item: ControlItem) => {\r\n if (!item.isBuiltIn) {\r\n // Render custom user control\r\n const controlId = item.id || `ctrl-${item.index}`;\r\n const isMenuOpen = activeControlId === controlId;\r\n\r\n // Allow rendering if it's the active one OR if it was the last active one during the unmount phase\r\n const shouldRenderMenu = isMenuOpen || (controlTransition.isMounted && lastActiveControlId.current === controlId);\r\n\r\n return (\r\n <div key={item.index} className=\"relative\">\r\n <button\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n if (item.children) {\r\n // Toggle logic: If click same button, toggle off. If click diff button, close old, open new.\r\n const wasOpen = isMenuOpen;\r\n closeAllMenus();\r\n if (!wasOpen) setActiveControlId(controlId);\r\n } else {\r\n closeAllMenus(); // Close context menu\r\n if (item.click) item.click(player!);\r\n else if (item.onClick) item.onClick(player!);\r\n }\r\n }}\r\n className={`strata-control-btn transition-colors focus:outline-none flex items-center justify-center ${btnClass} ${isMenuOpen ? 'text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'} ${item.className || ''}`}\r\n style={{ borderRadius: 'var(--radius)', ...item.style }}\r\n title={item.tooltip}\r\n >\r\n <HtmlOrNode content={item.html || ''} />\r\n </button>\r\n {/* Use MenuExplorer for nested controls */}\r\n {item.children && shouldRenderMenu && (\r\n <MenuExplorer\r\n items={item.children}\r\n onClose={closeAllMenus}\r\n maxHeight={menuMaxHeight}\r\n className={`strata-backdrop ${backdropClass} ${controlTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}\r\n />\r\n )}\r\n </div>\r\n );\r\n }\r\n\r\n // Built-ins\r\n switch (item.id) {\r\n case 'play':\r\n return (\r\n <button key=\"play\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.togglePlay(); }} className={`strata-control-btn text-zinc-300 hover:text-white transition-colors hover:bg-white/10 focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}>\r\n {state.isPlaying ? <PauseIcon className={`${iconClass} fill-current`} /> : <PlayIcon className={`${iconClass} fill-current`} />}\r\n </button>\r\n );\r\n case 'volume':\r\n return (\r\n <div key=\"volume\" className=\"flex items-center gap-2 group/vol relative\"\r\n onMouseEnter={() => { if (window.matchMedia('(hover: hover)').matches) setIsVolumeHovered(true); }}\r\n onMouseLeave={() => { if (window.matchMedia('(hover: hover)').matches) setIsVolumeHovered(false); }}\r\n >\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={handleVolumeIconClick} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}>\r\n <VolIcon className={iconClass} />\r\n </button>\r\n <div className={`relative h-8 flex items-center transition-all duration-300 ease-out overflow-hidden ${isVolumeVisible ? 'w-28 opacity-100 ml-1' : 'w-0 opacity-0'}`}>\r\n <div ref={volumeBarRef} className=\"relative w-full h-full flex items-center cursor-pointer px-2\" onMouseDown={handleVolumeStart} onTouchStart={handleVolumeStart}>\r\n <div className=\"w-full h-1 bg-white/20 overflow-hidden\" style={{ borderRadius: 'var(--radius-full)' }}>\r\n <div className=\"h-full bg-white\" style={{ width: `${(state.isMuted ? 0 : state.volume) * 100}%`, borderRadius: 'var(--radius-full)' }}></div>\r\n </div>\r\n <div className=\"absolute h-3 w-3 bg-white shadow-md top-1/2 -translate-y-1/2 pointer-events-none\" style={{ left: `calc(${(state.isMuted ? 0 : state.volume) * 100}% * 0.85 + 4px)`, borderRadius: 'var(--radius-full)' }} />\r\n </div>\r\n </div>\r\n {isVolumeVisible && <div className=\"strata-tooltip absolute bottom-full mb-2 px-1.5 py-0.5 rounded text-[10px] font-bold font-mono shadow-lg pointer-events-none whitespace-nowrap z-50 transform -translate-x-1/2\" style={{ left: `calc(52px + ${(state.isMuted ? 0 : state.volume) * 80}px)` }}>{state.isMuted ? '0%' : `${Math.round(state.volume * 100)}%`}</div>}\r\n </div>\r\n );\r\n case 'time':\r\n return config.isLive ? (\r\n <div key=\"live\" className=\"flex items-center gap-2 px-2 py-0.5 rounded-md border border-white/10\" style={{ backgroundColor: `${state.themeColor}1a`, borderColor: `${state.themeColor}33` }}>\r\n <div className=\"w-2 h-2 rounded-full animate-pulse\" style={{ backgroundColor: state.themeColor }} />\r\n <span className=\"text-[10px] font-bold tracking-wider\" style={{ color: state.themeColor }}>LIVE</span>\r\n </div>\r\n ) : (\r\n <div key=\"time\" className=\"text-xs font-medium text-zinc-400 font-mono select-none hidden sm:block tabular-nums\">{formatTime(isScrubbing ? scrubbingTime : state.currentTime)} <span className=\"text-zinc-600\">/</span> {formatTime(state.duration)}</div>\r\n );\r\n case 'subtitle':\r\n return (\r\n <div key=\"subtitle\" className=\"relative\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); const wasOpen = subtitleMenuOpen; closeAllMenus(); if (!wasOpen) setSubtitleMenuOpen(true); }} className={`strata-control-btn transition-colors focus:outline-none ${btnClass} ${subtitleMenuOpen ? 'text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'}`} style={{ borderRadius: 'var(--radius)' }}><SubtitleIcon className={iconClass} /></button>\r\n {subtitleTransition.isMounted && (\r\n <SubtitleMenu\r\n tracks={state.subtitleTracks} current={state.currentSubtitle} onSelect={(idx: number) => player?.setSubtitle(idx)}\r\n onUpload={(file: File) => player?.addTextTrack(file, file.name)} onClose={closeAllMenus}\r\n settings={state.subtitleSettings} onSettingsChange={(s: Partial<SubtitleSettings>) => player?.updateSubtitleSettings(s)}\r\n onReset={() => player?.resetSubtitleSettings()} offset={state.subtitleOffset} onOffsetChange={(val: number) => player?.setSubtitleOffset(val)}\r\n maxHeight={menuMaxHeight} animationClass={`strata-backdrop ${backdropClass} ${subtitleTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}\r\n />\r\n )}\r\n </div>\r\n );\r\n case 'screenshot': return <button key=\"ss\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.screenshot(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 transition-colors hidden sm:block focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }} title=\"Screenshot\"><CameraIcon className={iconClass} /></button>;\r\n case 'pip': return <button key=\"pip\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.togglePip(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 transition-colors hidden sm:block focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}><PipIcon className={iconClass} /></button>;\r\n \r\n // Modified Download Handler with Menu Support via Built-in Extension\r\n case 'download': \r\n if (item.children) {\r\n const isMenuOpen = activeControlId === 'download-menu';\r\n const shouldRenderMenu = isMenuOpen || (controlTransition.isMounted && lastActiveControlId.current === 'download-menu');\r\n return (\r\n <div key=\"dl\" className=\"relative\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { \r\n e.stopPropagation(); \r\n const wasOpen = isMenuOpen;\r\n closeAllMenus(); \r\n if (!wasOpen) setActiveControlId('download-menu');\r\n }} className={`strata-control-btn transition-colors hidden sm:block focus:outline-none ${btnClass} ${isMenuOpen ? 'text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'}`} style={{ borderRadius: 'var(--radius)' }}><DownloadIcon className={iconClass} /></button>\r\n \r\n {shouldRenderMenu && (\r\n <MenuExplorer\r\n items={item.children}\r\n onClose={closeAllMenus}\r\n maxHeight={menuMaxHeight}\r\n className={`strata-backdrop ${backdropClass} ${controlTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}\r\n />\r\n )}\r\n </div>\r\n );\r\n }\r\n return <button key=\"dl\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.download(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 transition-colors hidden sm:block focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}><DownloadIcon className={iconClass} /></button>;\r\n \r\n case 'fullscreen': return <button key=\"fs\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.toggleFullscreen(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 rounded-lg transition-transform focus:outline-none ${btnClass}`} style={{ borderRadius: 'var(--radius)' }}>{(state.isFullscreen || state.isWebFullscreen) ? <MinimizeIcon className={iconClass} /> : <MaximizeIcon className={iconClass} />}</button>;\r\n case 'fullscreenWeb': return <button key=\"fsw\" onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player?.toggleWebFullscreen(); }} className={`strata-control-btn text-zinc-300 hover:text-white hover:bg-white/10 hidden sm:block focus:outline-none ${btnClass} ${state.isWebFullscreen ? 'text-[var(--accent)]' : ''}`} style={{ borderRadius: 'var(--radius)' }} title=\"Web Fullscreen\"><WebFullscreenIcon className={iconClass} /></button>;\r\n case 'settings':\r\n return (\r\n <div key=\"settings\" className=\"relative\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); const wasOpen = settingsOpen; closeAllMenus(); if (!wasOpen) { setSettingsOpen(true); setActiveMenu('main'); } }} className={`strata-control-btn transition-all duration-300 focus:outline-none ${btnClass} ${settingsOpen ? 'rotate-90 text-[var(--accent)] bg-white/10' : 'text-zinc-300 hover:text-white hover:bg-white/10'}`} style={{ borderRadius: 'var(--radius)' }}><SettingsIcon className={iconClass} /></button>\r\n {settingsTransition.isMounted && (<Menu onClose={closeAllMenus} align=\"right\" maxHeight={menuMaxHeight} className={`strata-backdrop ${backdropClass} ${settingsTransition.isVisible ? 'opacity-100 translate-y-0 scale-100 animate-in fade-in zoom-in-95 duration-300' : 'opacity-0 translate-y-2 scale-95 duration-300'}`}><div className=\"w-full\">\r\n {activeMenu === 'main' && (\r\n <div className=\"animate-in slide-in-from-left-4 fade-in duration-200\">\r\n <div className=\"px-3 py-2 mb-1 border-b border-white/5 font-bold text-zinc-400 uppercase text-[11px] tracking-wider flex justify-between items-center bg-white/5 sticky top-0 z-10 backdrop-blur-md\" style={{ borderRadius: 'var(--radius)' }}><span>Settings</span></div>\r\n\r\n {/* Source - Top Priority */}\r\n {state.sources.length > 1 && (\r\n <>\r\n <MenuItem label=\"Source\" icon={<ServerIcon className=\"w-4 h-4\" />} value={state.sources[state.currentSourceIndex]?.name || `Source ${state.currentSourceIndex + 1}`} onClick={() => setActiveMenu('sources')} hasSubmenu />\r\n <MenuDivider />\r\n </>\r\n )}\r\n\r\n {/* Playback Configuration */}\r\n <MenuItem label=\"Quality\" icon={<QualityIcon className=\"w-4 h-4\" />} value={state.currentQuality === -1 ? 'Auto' : `${state.qualityLevels[state.currentQuality]?.height}p`} onClick={() => setActiveMenu('quality')} hasSubmenu />\r\n <MenuItem label=\"Speed\" icon={<GaugeIcon className=\"w-4 h-4\" />} value={`${state.playbackRate}x`} onClick={() => setActiveMenu('speed')} hasSubmenu />\r\n <MenuItem label=\"Audio\" icon={<MusicIcon className=\"w-4 h-4\" />} value={state.audioTracks[state.currentAudioTrack]?.label || 'Default'} onClick={() => setActiveMenu('audio')} hasSubmenu />\r\n\r\n <MenuDivider />\r\n\r\n {/* Visual Adjustments */}\r\n <MenuItem label=\"Video Fit\" icon={<LayoutTemplateIcon className=\"w-4 h-4\" />} value={state.videoFit === 'none' ? 'Default' : state.videoFit.charAt(0).toUpperCase() + state.videoFit.slice(1)} onClick={() => setActiveMenu('videofit')} hasSubmenu />\r\n {useAspectRatio && <MenuItem label=\"Aspect Ratio\" icon={<CropIcon className=\"w-4 h-4\" />} value={state.aspectRatio} onClick={() => setActiveMenu('ratio')} hasSubmenu />}\r\n {useFlip && <MenuItem label=\"Flip\" icon={<VideoFlipIcon className=\"w-4 h-4\" />} value={state.flipState.horizontal ? 'H' : state.flipState.vertical ? 'V' : 'Normal'} onClick={() => setActiveMenu('flip')} hasSubmenu />}\r\n \r\n {/* Audio Tools */}\r\n <MenuItem label=\"Audio Boost\" icon={<SpeakerIcon className=\"w-4 h-4\" />} value={state.audioGain > 1 ? `${state.audioGain}x` : 'Off'} onClick={() => setActiveMenu('boost')} hasSubmenu />\r\n\r\n <MenuDivider />\r\n\r\n {/* Network & Social */}\r\n <MenuItem label=\"Watch Party\" icon={<UsersIcon className=\"w-4 h-4\" />} onClick={() => setActiveMenu('party')} hasSubmenu />\r\n <MenuItem label=\"Cast to Device\" icon={<CastIcon className=\"w-4 h-4\" />} onClick={() => { player?.requestCast(); closeAllMenus(); }} />\r\n\r\n {/* Custom User Settings (Nested Support Added Here) */}\r\n {config.settings && config.settings.length > 0 && <MenuDivider />}\r\n {config.settings?.map((s, i) => (\r\n s.switch !== undefined ? (\r\n <div key={`cust-${i}`} className=\"px-1\">\r\n <Toggle\r\n label={s.html}\r\n icon={s.icon}\r\n checked={s.switch}\r\n tooltip={s.tooltip}\r\n onChange={(val: boolean) => { if (s.onSwitch) s.onSwitch(s, val); }}\r\n />\r\n </div>\r\n ) : (\r\n <MenuItem\r\n key={`cust-${i}`}\r\n label={s.html}\r\n icon={s.icon}\r\n value={s.currentLabel || s.value}\r\n hasSubmenu={!!s.children}\r\n onClick={() => {\r\n if (s.children) {\r\n setActiveMenu(`custom-${i}`);\r\n } else {\r\n if (s.click) s.click(s);\r\n else if (s.onClick) s.onClick(s);\r\n closeAllMenus();\r\n }\r\n }}\r\n />\r\n )\r\n ))}\r\n\r\n <MenuDivider />\r\n\r\n {/* Appearance - Bottom */}\r\n <MenuItem label=\"Appearance\" icon={<PaletteIcon className=\"w-4 h-4\" />} onClick={() => setActiveMenu('appearance')} hasSubmenu />\r\n </div>\r\n )}\r\n\r\n {/* Render Nested Custom Setting Menu if active */}\r\n {activeMenu.startsWith('custom-') && (() => {\r\n const idx = parseInt(activeMenu.split('-')[1]);\r\n const item = config.settings?.[idx];\r\n if (!item || !item.children) return null;\r\n return (\r\n <div className=\"animate-in slide-in-from-right-4 fade-in duration-200\">\r\n <MenuHeader label={item.html || 'Menu'} onBack={() => setActiveMenu('main')} />\r\n {item.children.map((child, k) => (\r\n <React.Fragment key={k}>\r\n {child.separator && <MenuDivider />}\r\n {child.switch !== undefined && (\r\n <div className=\"px-1\"><Toggle label={child.html} checked={child.switch} onChange={(v: boolean) => child.onSwitch && child.onSwitch(child, v)} /></div>\r\n )}\r\n {!child.separator && child.switch === undefined && (\r\n <MenuItem\r\n label={child.html}\r\n icon={child.icon}\r\n value={child.value}\r\n active={child.active}\r\n onClick={() => {\r\n if (child.onClick) child.onClick(child);\r\n else if (child.click) child.click(child);\r\n closeAllMenus();\r\n }}\r\n />\r\n )}\r\n </React.Fragment>\r\n ))}\r\n </div>\r\n );\r\n })()}\r\n\r\n {['speed', 'quality', 'audio', 'boost', 'party', 'appearance', 'sources', 'flip', 'ratio', 'videofit'].includes(activeMenu) && (\r\n <div className=\"animate-in slide-in-from-right-4 fade-in duration-200\">\r\n {activeMenu === 'sources' && (\r\n <>\r\n <MenuHeader label=\"Select Source\" onBack={() => setActiveMenu('main')} />\r\n {state.sources.map((src, i) => {\r\n const status = state.sourceStatuses[i];\r\n const statusIcon = status === 'success'\r\n ? <WifiIcon className=\"w-3.5 h-3.5 text-emerald-500\" />\r\n : status === 'error'\r\n ? <AlertCircleIcon className=\"w-3.5 h-3.5 text-red-500\" />\r\n : null;\r\n return (\r\n <MenuItem\r\n key={i}\r\n label={src.name || `Source ${i + 1}`}\r\n value={src.type}\r\n active={state.currentSourceIndex === i}\r\n rightIcon={statusIcon}\r\n onClick={() => player?.switchSource(i)}\r\n />\r\n );\r\n })}\r\n </>\r\n )}\r\n {activeMenu === 'speed' && (<><MenuHeader label=\"Speed\" onBack={() => setActiveMenu('main')} />{[0.5, 1, 1.5, 2].map(rate => (<MenuItem key={rate} label={`${rate}x`} active={state.playbackRate === rate} onClick={() => player!.video.playbackRate = rate} />))}</>)}\r\n {activeMenu === 'quality' && (<><MenuHeader label=\"Quality\" onBack={() => setActiveMenu('main')} /><MenuItem label=\"Auto\" active={state.currentQuality === -1} onClick={() => player?.setQuality(-1)} />{state.qualityLevels.map((lvl) => (<MenuItem key={lvl.index} label={`${lvl.height}p`} value={`${Math.round(lvl.bitrate / 1000)}k`} active={state.currentQuality === lvl.index} onClick={() => player?.setQuality(lvl.index)} />))}</>)}\r\n {activeMenu === 'audio' && (<><MenuHeader label=\"Audio Track\" onBack={() => setActiveMenu('main')} />{state.audioTracks.length === 0 && <div className=\"px-4 py-3 text-zinc-500 text-xs text-center\">No tracks available</div>}{state.audioTracks.map((track) => (<MenuItem key={track.index} label={track.label} value={track.language} active={state.currentAudioTrack === track.index} onClick={() => player?.setAudioTrack(track.index)} />))}</>)}\r\n {activeMenu === 'boost' && (<><MenuHeader label=\"Audio Boost\" onBack={() => setActiveMenu('main')} />{[1, 1.5, 2, 3].map(gain => (<MenuItem key={gain} label={gain === 1 ? 'Off' : `${gain}x`} active={state.audioGain === gain} onClick={() => player?.setAudioGain(gain)} />))}</>)}\r\n {activeMenu === 'flip' && (\r\n <>\r\n <MenuHeader label=\"Video Flip\" onBack={() => setActiveMenu('main')} />\r\n <div className=\"p-2 space-y-1\">\r\n <Toggle label=\"Horizontal Flip\" checked={state.flipState.horizontal} onChange={() => player?.setFlip('horizontal')} />\r\n <Toggle label=\"Vertical Flip\" checked={state.flipState.vertical} onChange={() => player?.setFlip('vertical')} />\r\n </div>\r\n </>\r\n )}\r\n {activeMenu === 'ratio' && (\r\n <>\r\n <MenuHeader label=\"Aspect Ratio\" onBack={() => setActiveMenu('main')} />\r\n <div className=\"max-h-[250px] overflow-y-auto hide-scrollbar\">\r\n {['default', '16:9', '4:3', '21:9', '18:9', '1:1', '9:16'].map(r => (\r\n <MenuItem key={r} label={r === 'default' ? 'Default' : r.replace(':', ' : ')} active={state.aspectRatio === r} onClick={() => player?.setAspectRatio(r)} />\r\n ))}\r\n </div>\r\n </>\r\n )}\r\n {activeMenu === 'videofit' && (\r\n <>\r\n <MenuHeader label=\"Video Fit\" onBack={() => setActiveMenu('main')} />\r\n <MenuItem label=\"Contain (Default)\" value=\"Fit\" active={state.videoFit === 'contain'} onClick={() => player?.setVideoFit('contain')} />\r\n <MenuItem label=\"Cover\" value=\"Zoom\" active={state.videoFit === 'cover'} onClick={() => player?.setVideoFit('cover')} />\r\n <MenuItem label=\"Fill\" value=\"Stretch\" active={state.videoFit === 'fill'} onClick={() => player?.setVideoFit('fill')} />\r\n <MenuItem label=\"None\" value=\"Original\" active={state.videoFit === 'none'} onClick={() => player?.setVideoFit('none')} />\r\n </>\r\n )}\r\n {activeMenu === 'party' && (<><MenuHeader label=\"Watch Party\" onBack={() => setActiveMenu('main')} /><div className=\"p-4 space-y-3\"><p className=\"text-xs text-zinc-400 leading-relaxed\">Create a synchronized room on WatchParty.me to watch together.</p><a href={`https://www.watchparty.me/create?video=${encodeURIComponent(state.sources[state.currentSourceIndex]?.url || src || '')}`} target=\"_blank\" rel=\"noopener noreferrer\" className=\"flex items-center justify-center w-full py-2.5 bg-[var(--accent)] hover:opacity-90 text-white font-medium transition-opacity text-xs\" style={{ borderRadius: 'var(--radius)' }}>Create Room</a></div></>)}\r\n {activeMenu === 'appearance' && (\r\n <>\r\n <MenuHeader label=\"Appearance\" onBack={() => setActiveMenu('main')} />\r\n <div className=\"pb-1\">\r\n <div className=\"px-1 pt-1\">\r\n <Slider \r\n label=\"Brightness\"\r\n icon={<SunIcon className=\"w-4 h-4\" />}\r\n value={state.brightness}\r\n min={0} max={2} step={0.1}\r\n onChange={(val: number) => player?.setBrightness(val)}\r\n formatValue={(v: number) => `${Math.round(v * 100)}%`}\r\n />\r\n </div>\r\n\r\n <SettingsGroup title=\"Theme\">\r\n <div className=\"grid grid-cols-2 gap-2 px-3\">\r\n {THEMES.map(theme => (\r\n <button key={theme.value} onClick={() => player?.setAppearance({ theme: theme.value, themeColor: theme.color })} className={`py-2 text-xs font-bold uppercase tracking-wide transition-colors border-[length:var(--border-width)] border-white/10 ${state.theme === theme.value ? 'bg-[var(--accent)] text-white' : 'bg-white/5 text-zinc-400 hover:text-white'}`} style={{ borderRadius: 'var(--radius)' }}>{theme.label}</button>\r\n ))}\r\n </div>\r\n </SettingsGroup>\r\n <SettingsGroup title=\"Icon Size\">\r\n <div className=\"grid grid-cols-3 gap-1 px-3\">\r\n {(['small', 'medium', 'large'] as const).map(s => (\r\n <button key={s} onClick={() => player?.setAppearance({ iconSize: s })} className={`py-1.5 text-xs font-medium transition-colors ${state.iconSize === s ? 'bg-white text-black' : 'bg-white/5 text-zinc-400 hover:text-zinc-200'}`} style={{ borderRadius: 'var(--radius)' }}>{s.charAt(0).toUpperCase() + s.slice(1)}</button>\r\n ))}\r\n </div>\r\n </SettingsGroup>\r\n <SettingsGroup title=\"Theme Color\">\r\n <div className=\"grid grid-cols-6 gap-2 px-3\">\r\n {THEME_COLORS.map(c => (\r\n <button key={c.value} title={c.label} onClick={() => player?.setAppearance({ themeColor: c.value })} className={`w-6 h-6 transition-transform hover:scale-110 ${state.themeColor === c.value ? 'ring-2 ring-white scale-110' : 'ring-1 ring-white/10'}`} style={{ backgroundColor: c.value, borderRadius: 'var(--radius-full)' }}>{state.themeColor === c.value && <CheckIcon className=\"w-3 h-3 text-white mx-auto stroke-[3]\" />}</button>\r\n ))}\r\n </div>\r\n <div className=\"px-3 pt-4\">\r\n <div className=\"flex items-center gap-3 bg-white/5 p-2 hover:bg-white/10 transition-colors group\" style={{ borderRadius: 'var(--radius)' }}>\r\n <div className=\"relative w-6 h-6 overflow-hidden ring-1 ring-white/20\" style={{ borderRadius: 'var(--radius-full)' }}>\r\n <input type=\"color\" value={state.themeColor} onChange={(e) => player?.setAppearance({ themeColor: e.target.value })} className=\"absolute inset-[-4px] w-[150%] h-[150%] cursor-pointer p-0 border-0\" />\r\n </div>\r\n <span className=\"text-xs text-zinc-400 font-medium group-hover:text-zinc-200\">Custom Color</span>\r\n <span className=\"text-[10px] font-mono text-zinc-500 ml-auto uppercase\">{state.themeColor}</span>\r\n </div>\r\n </div>\r\n </SettingsGroup>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n )}\r\n </div></Menu>)}\r\n </div>\r\n );\r\n default: return null;\r\n }\r\n };\r\n\r\n // --- Dynamic Context Menu ---\r\n const contextMenuItems: ContextMenuItem[] = useMemo(() => {\r\n const items: ContextMenuItem[] = [\r\n // Loop (Playback Group)\r\n { html: 'Playback', isLabel: true },\r\n {\r\n html: 'Loop',\r\n checked: state.isLooping,\r\n onClick: () => player?.toggleLoop()\r\n },\r\n { separator: true },\r\n\r\n // Flip (Transform Group)\r\n { html: 'Transform', isLabel: true },\r\n { html: 'Flip Horizontal', onClick: () => player?.setFlip('horizontal') },\r\n { html: 'Flip Vertical', onClick: () => player?.setFlip('vertical') },\r\n { separator: true },\r\n\r\n // Aspect Ratio Group\r\n { html: 'Aspect Ratio', isLabel: true },\r\n { html: 'Default', checked: state.aspectRatio === 'default', onClick: () => player?.setAspectRatio('default') },\r\n { html: '16:9', checked: state.aspectRatio === '16:9', onClick: () => player?.setAspectRatio('16:9') },\r\n { html: '21:9', checked: state.aspectRatio === '21:9', onClick: () => player?.setAspectRatio('21:9') },\r\n { separator: true },\r\n \r\n // Video Fit Group\r\n { html: 'Video Fit', isLabel: true },\r\n { html: 'Contain', checked: state.videoFit === 'contain', onClick: () => player?.setVideoFit('contain') },\r\n { html: 'Cover', checked: state.videoFit === 'cover', onClick: () => player?.setVideoFit('cover') },\r\n { separator: true },\r\n\r\n // Stats\r\n {\r\n html: 'Video Info',\r\n icon: <InfoIcon className=\"w-3.5 h-3.5\" />,\r\n onClick: () => setShowVideoInfo(true)\r\n },\r\n { separator: true }\r\n ];\r\n\r\n if (config.contextmenu) {\r\n items.push(...config.contextmenu);\r\n }\r\n\r\n // Branding\r\n items.push({\r\n html: <span className=\"text-zinc-500 text-xs font-semibold tracking-wide\">StrataPlayer</span>,\r\n disabled: true\r\n });\r\n\r\n // Always append Close at the very end\r\n items.push({\r\n html: 'Close',\r\n onClick: (close) => close(), // Wrapper handles close\r\n icon: <div className=\"text-red-400\"><svg width=\"12\" height=\"12\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"3\" strokeLinecap=\"round\" strokeLinejoin=\"round\"><path d=\"M18 6 6 18\" /><path d=\"m6 6 12 12\" /></svg></div>\r\n });\r\n\r\n return items;\r\n }, [config.contextmenu, state.aspectRatio, state.isLooping, state.videoFit, player]);\r\n\r\n const isWebFs = state.isWebFullscreen;\r\n\r\n const playerContent = (\r\n <div\r\n id={config.id}\r\n ref={containerRef}\r\n className={`group bg-black overflow-hidden select-none font-[family-name:var(--font-main)] outline-none text-zinc-100 strata-player-reset flex items-center justify-center ${isWebFs ? 'fixed inset-0 z-[2147483647] w-screen h-screen rounded-none' : 'relative w-full h-full rounded-[var(--radius-player)]'} ${config.container || ''}`}\r\n // touch-action: manipulation improves tap response\r\n style={{ touchAction: 'manipulation', '--accent': state.themeColor, '--accent-contrast': accentContrast } as React.CSSProperties}\r\n onMouseMove={handleMouseMove}\r\n onMouseLeave={() => { if (state.isPlaying && !settingsOpen && !subtitleMenuOpen && !activeControlId && player) player.setControlsVisible(false); }}\r\n\r\n // Mouse Events\r\n onMouseDown={startFastForward}\r\n onMouseUp={stopFastForward}\r\n\r\n // Touch Events (Unified Gesture Logic)\r\n onTouchStart={handleTouchStart}\r\n onTouchMove={handleTouchMove}\r\n onTouchEnd={handleTouchEnd}\r\n\r\n onContextMenu={handleContextMenu}\r\n tabIndex={0}\r\n role=\"region\"\r\n aria-label=\"Video Player\"\r\n data-theme={state.theme}\r\n >\r\n {/* Same styles block as before */}\r\n <style>{`\r\n [data-theme=\"default\"] {\r\n --radius: 0.75rem;\r\n --radius-lg: 0.75rem;\r\n --radius-sm: 0.375rem;\r\n --radius-full: 9999px;\r\n --radius-player: 0.25rem;\r\n --font-main: \"Inter\", sans-serif;\r\n --border-width: 0px;\r\n --bg-panel: rgba(9, 9, 11, 0.95);\r\n --tooltip-bg: #ffffff;\r\n --tooltip-text: #000000;\r\n --tooltip-border: 0px solid transparent;\r\n }\r\n [data-theme=\"pixel\"] {\r\n --radius: 0px;\r\n --radius-lg: 0px;\r\n --radius-sm: 0px;\r\n --radius-full: 0px;\r\n --radius-player: 0px;\r\n --font-main: \"Press Start 2P\", cursive;\r\n --border-width: 2px;\r\n --bg-panel: #000000;\r\n --tooltip-bg: #000000;\r\n --tooltip-text: #ffffff;\r\n --tooltip-border: 2px solid #ffffff;\r\n image-rendering: pixelated;\r\n }\r\n [data-theme=\"game\"] {\r\n --radius: 4px;\r\n --radius-lg: 6px;\r\n --radius-sm: 2px;\r\n --radius-full: 4px;\r\n --radius-player: 4px;\r\n --font-main: \"Cinzel\", serif;\r\n --border-width: 1px;\r\n --bg-panel: #0a0a0a;\r\n --tooltip-bg: #1a1a1a;\r\n --tooltip-text: #ffffff;\r\n --tooltip-border: 1px solid var(--accent);\r\n }\r\n [data-theme=\"hacker\"] {\r\n --radius: 0px;\r\n --radius-lg: 0px;\r\n --radius-sm: 0px;\r\n --radius-full: 0px;\r\n --radius-player: 0px;\r\n --font-main: \"JetBrains Mono\", monospace;\r\n --border-width: 1px;\r\n --bg-panel: #000000;\r\n --tooltip-bg: #000000;\r\n --tooltip-text: var(--accent);\r\n --tooltip-border: 1px solid var(--accent);\r\n text-shadow: 0 0 5px var(--accent);\r\n }\r\n \r\n [data-theme=\"pixel\"] .strata-control-btn {\r\n border: 2px solid white;\r\n background: black;\r\n }\r\n [data-theme=\"pixel\"] .strata-control-btn:hover {\r\n background: white;\r\n color: black;\r\n }\r\n [data-theme=\"pixel\"] .strata-range-input::-webkit-slider-thumb {\r\n border-radius: 0 !important;\r\n height: 16px !important;\r\n width: 16px !important;\r\n box-shadow: none !important;\r\n }\r\n \r\n [data-theme=\"hacker\"] .strata-scanlines {\r\n background: linear-gradient(\r\n to bottom,\r\n rgba(255,255,255,0),\r\n rgba(255,255,255,0) 50%,\r\n rgba(0,0,0,0.2) 50%,\r\n rgba(0,0,0,0.2)\r\n );\r\n background-size: 100% 4px;\r\n position: absolute;\r\n inset: 0;\r\n pointer-events: none;\r\n z-index: 40;\r\n }\r\n\r\n .strata-tooltip {\r\n background-color: var(--tooltip-bg);\r\n color: var(--tooltip-text);\r\n border: var(--tooltip-border);\r\n border-radius: var(--radius-sm);\r\n font-family: var(--font-main);\r\n }\r\n \r\n /* Override Backdrop for specific themes if needed */\r\n [data-theme=\"pixel\"] .strata-backdrop { backdrop-filter: none; background: #000; }\r\n [data-theme=\"hacker\"] .strata-backdrop { backdrop-filter: none; background: #000; }\r\n `}</style>\r\n\r\n {state.theme === 'hacker' && <div className=\"strata-scanlines\" />}\r\n\r\n {!player && <div className=\"absolute inset-0 flex items-center justify-center bg-zinc-950 z-50\"><LoaderIcon className=\"w-10 h-10 text-[var(--accent)] animate-spin\" /></div>}\r\n\r\n {player && (\r\n <>\r\n {/* Custom Layers */}\r\n {config.layers?.map((layer, idx) => (\r\n <div\r\n key={idx}\r\n className={`absolute inset-0 pointer-events-none z-10 ${layer.className || ''}`}\r\n style={layer.style}\r\n >\r\n <HtmlOrNode content={layer.html || ''} className=\"w-full h-full\" />\r\n </div>\r\n ))}\r\n\r\n <NotificationContainer notifications={state.notifications} />\r\n <SubtitleOverlay cues={state.activeCues} settings={state.subtitleSettings} />\r\n\r\n {/* Main Interaction Layer (z-[1]) - Sits ABOVE video (which is appended at z-0/auto) to capture clicks */}\r\n <div \r\n className=\"absolute inset-0 z-[1] cursor-pointer\" \r\n onClick={handleContainerClick} \r\n aria-hidden=\"true\" \r\n role=\"button\"\r\n tabIndex={-1}\r\n />\r\n\r\n {poster && !hasPlayed && (\r\n <div\r\n className=\"absolute inset-0 bg-cover bg-center z-[5] pointer-events-none strata-poster\"\r\n style={{ backgroundImage: `url(${poster})` }}\r\n />\r\n )}\r\n\r\n {/* Context Menu */}\r\n {contextMenu.visible && (\r\n <ContextMenu\r\n x={contextMenu.x}\r\n y={contextMenu.y}\r\n items={contextMenuItems}\r\n onClose={closeAllMenus}\r\n containerWidth={playerWidth}\r\n containerHeight={playerHeight}\r\n />\r\n )}\r\n\r\n {/* Video Info Modal */}\r\n {showVideoInfo && player && (\r\n <VideoInfo player={player} onClose={() => setShowVideoInfo(false)} />\r\n )}\r\n\r\n {/* Fast Forward Overlay */}\r\n {isFastForwarding && (\r\n <div className=\"absolute top-8 left-1/2 -translate-x-1/2 bg-black/50 backdrop-blur-md px-4 py-2 rounded-full flex items-center gap-2 z-40 animate-in fade-in zoom-in duration-200 pointer-events-none\">\r\n <FastForwardIcon className=\"w-4 h-4 text-[var(--accent)] fill-current\" />\r\n <span className=\"text-xs font-bold tracking-wider\">2x Speed</span>\r\n </div>\r\n )}\r\n \r\n {/* Volume Overlay (Gestures) */}\r\n {isVolumeLocked && (\r\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-black/60 backdrop-blur-md p-6 rounded-2xl flex flex-col items-center gap-4 z-40 animate-in fade-in zoom-in duration-200 pointer-events-none\">\r\n {state.isMuted || state.volume === 0 ? <VolumeMuteIcon className=\"w-10 h-10 text-white/80\" /> : <VolumeHighIcon className=\"w-10 h-10 text-white/80\" />}\r\n <div className=\"w-32 h-1.5 bg-white/20 rounded-full overflow-hidden\">\r\n <div className=\"h-full bg-[var(--accent)]\" style={{ width: `${state.isMuted ? 0 : state.volume * 100}%` }} />\r\n </div>\r\n <span className=\"text-xl font-bold font-mono\">{Math.round(state.volume * 100)}%</span>\r\n </div>\r\n )}\r\n \r\n {/* Brightness Overlay (Gestures) */}\r\n {isBrightnessAdjusting && (\r\n <div className=\"absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 bg-black/60 backdrop-blur-md p-6 rounded-2xl flex flex-col items-center gap-4 z-40 animate-in fade-in zoom-in duration-200 pointer-events-none\">\r\n <SunIcon className=\"w-10 h-10 text-white/80\" />\r\n <div className=\"w-32 h-1.5 bg-white/20 rounded-full overflow-hidden\">\r\n <div className=\"h-full bg-[var(--accent)]\" style={{ width: `${Math.min(100, state.brightness * 100)}%` }} />\r\n </div>\r\n <span className=\"text-xl font-bold font-mono\">{Math.round(state.brightness * 100)}%</span>\r\n </div>\r\n )}\r\n\r\n {/* Mobile Lock Button */}\r\n {useLock && isMobile && state.controlsVisible && (\r\n <button\r\n onMouseDown={(e) => e.stopPropagation()}\r\n onTouchStart={(e) => e.stopPropagation()}\r\n onClick={(e) => { e.stopPropagation(); player.toggleLock(); }}\r\n className={`absolute left-4 md:left-6 bottom-24 md:bottom-28 z-50 p-3 rounded-full bg-black/50 backdrop-blur-md border border-white/10 text-white transition-all active:scale-95 ${state.isLocked ? 'text-[var(--accent)] bg-white/10' : 'hover:bg-white/10'}`}\r\n >\r\n {state.isLocked ? <LockIcon className=\"w-5 h-5\" /> : <UnlockIcon className=\"w-5 h-5\" />}\r\n </button>\r\n )}\r\n\r\n {seekAnimation && (\r\n <div\r\n key={seekAnimation.id}\r\n className={`absolute top-0 bottom-0 flex items-center justify-center w-[35%] z-20 bg-white/5 backdrop-blur-[1px] animate-out fade-out duration-500 fill-mode-forwards pointer-events-none ${seekAnimation.type === 'rewind' ? 'left-0 rounded-r-[4rem]' : 'right-0 rounded-l-[4rem]'}`}\r\n onAnimationEnd={() => setSeekAnimation(null)}\r\n >\r\n <div className=\"flex flex-col items-center text-white drop-shadow-lg\">\r\n {seekAnimation.type === 'rewind' ? <Replay10Icon className=\"w-12 h-12 animate-pulse\" /> : <Forward10Icon className=\"w-12 h-12 animate-pulse\" />}\r\n <span className=\"font-bold text-sm mt-2 font-mono\">{seekAnimation.type === 'rewind' ? '-10s' : '+10s'}</span>\r\n </div>\r\n </div>\r\n )}\r\n {state.isBuffering && <div className=\"absolute inset-0 flex items-center justify-center z-20 pointer-events-none\"><LoaderIcon className=\"w-12 h-12 text-[var(--accent)] animate-spin drop-shadow-lg\" /></div>}\r\n {state.error && <div className=\"absolute inset-0 flex items-center justify-center z-30 bg-black/90 backdrop-blur-md animate-in fade-in\"><div className=\"flex flex-col items-center gap-4 text-red-500 p-8 max-w-md text-center\"><span className=\"text-5xl mb-2\">⚠️</span><h3 className=\"text-xl font-bold text-white\">Playback Error</h3><p className=\"text-zinc-400 text-sm\">{state.error}</p><button onClick={() => player.load(player.store.get().sources[player.store.get().currentSourceIndex] || { url: src || '', type: type || 'auto' }, textTracks)} className=\"px-6 py-2 bg-[var(--accent)] text-white font-medium rounded-full hover:opacity-90 transition-opacity mt-4 shadow-lg\">Try Again</button></div></div>}\r\n\r\n {/* Center Controls - Hidden if locked or configured off */}\r\n {useCenterControls && !state.isLocked && (((!state.isPlaying && !state.isBuffering && !state.error) || state.controlsVisible) && !state.isBuffering) ? (\r\n <div\r\n className={`absolute inset-0 flex items-center justify-center z-10 transition-opacity duration-300 pointer-events-none ${state.controlsVisible || !state.isPlaying ? 'opacity-100' : 'opacity-0'}`}\r\n >\r\n <div className=\"flex items-center gap-8 md:gap-16 pointer-events-auto\">\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); triggerSkip('rewind'); }} className={`group flex items-center justify-center rounded-full bg-black/40 hover:bg-black/60 border border-white/10 transition-all duration-300 active:scale-125 active:opacity-80 text-white/90 focus:outline-none backdrop-blur-sm ${center.skipBtn}`}><Replay10Icon className={center.skipIcon} /></button>\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); player.togglePlay(); }} className={`group relative flex items-center justify-center rounded-full bg-white/10 hover:bg-[var(--accent)] border border-white/10 shadow-2xl transition-all duration-300 active:scale-90 active:opacity-80 focus:outline-none backdrop-blur-md ${center.playBtn}`}>{state.isPlaying ? <PauseIcon className={`${center.playIcon} text-white fill-current`} /> : <PlayIcon className={`${center.playIcon} text-white ml-1 fill-current`} />}</button>\r\n <button onMouseDown={(e) => e.stopPropagation()} onTouchStart={(e) => e.stopPropagation()} onClick={(e) => { e.stopPropagation(); closeAllMenus(); triggerSkip('forward'); }} className={`group flex items-center justify-center rounded-full bg-black/40 hover:bg-black/60 border border-white/10 transition-all duration-300 active:scale-125 active:opacity-80 text-white/90 focus:outline-none backdrop-blur-sm ${center.skipBtn}`}><Forward10Icon className={center.skipIcon} /></button>\r\n </div>\r\n </div>\r\n ) : null}\r\n\r\n {/* Bottom Control Bar - Hidden if locked */}\r\n <div\r\n className={`absolute inset-x-0 bottom-0 z-30 transition-all duration-300 px-4 md:px-6 py-4 bg-gradient-to-t from-black/90 via-black/50 to-transparent ${isControlsVisible ? 'opacity-100 translate-y-0' : 'opacity-0 translate-y-4 pointer-events-none'}`}\r\n onClick={(e) => {\r\n if (settingsOpen || subtitleMenuOpen || activeControlId) {\r\n closeAllMenus();\r\n }\r\n // Stop prop to prevent play toggle, but allow menu closing logic above to run first\r\n if (e.target === e.currentTarget) {\r\n setIsVolumeLocked(false);\r\n }\r\n e.stopPropagation();\r\n }}\r\n >\r\n {/* Progress Bar (Hidden in Live Mode) */}\r\n {!config.isLive && (\r\n <div\r\n ref={progressBarRef}\r\n className=\"relative w-full h-3 group/slider mb-3 cursor-pointer touch-none flex items-center\"\r\n onMouseMove={handleProgressMove}\r\n onMouseLeave={() => { setHoverTime(null); setCurrentThumbnail(null); }}\r\n onMouseDown={handleSeekStart}\r\n onTouchStart={handleSeekStart}\r\n >\r\n {/* Highlights */}\r\n {config.highlight?.map((h, i) => (\r\n <div key={i} className=\"absolute top-1/2 -translate-y-1/2 w-1.5 h-1.5 bg-yellow-400 rounded-full z-10 pointer-events-none\" style={{ left: `${(h.time / state.duration) * 100}%` }} title={h.text} />\r\n ))}\r\n\r\n {hoverTime !== null && (<div className=\"absolute bottom-full mb-1.5 flex flex-col items-center transform -translate-x-1/2 z-40 pointer-events-none transition-opacity duration-150\" style={{ left: `clamp(70px, ${hoverPos}%, calc(100% - 70px))` }}>{currentThumbnail && (<div className=\"bg-black/90 border border-white/10 shadow-2xl overflow-hidden backdrop-blur-sm\" style={{ width: `${currentThumbnail.w * 0.5}px`, height: `${currentThumbnail.h * 0.5}px`, borderRadius: 'var(--radius)' }}><div style={{ backgroundImage: `url(\"${currentThumbnail.url}\")`, width: `${currentThumbnail.w}px`, height: `${currentThumbnail.h}px`, backgroundPosition: `-${currentThumbnail.x}px -${currentThumbnail.y}px`, backgroundRepeat: 'no-repeat', transform: 'scale(0.5)', transformOrigin: 'top left' }} /></div>)}<div className=\"strata-tooltip px-2 py-0.5 text-[11px] font-bold font-mono shadow-lg tabular-nums mt-1\">{formatTime(hoverTime)}</div></div>)}\r\n\r\n {/* Track */}\r\n <div className=\"w-full h-1 bg-white/20 overflow-hidden relative backdrop-blur-sm border-[length:var(--border-width)] border-white/10\" style={{ borderRadius: 'var(--radius-full)' }}>\r\n {state.duration > 0 && state.buffered.map((range, i) => (<div key={i} className=\"absolute top-0 bottom-0 bg-white/20\" style={{ left: `${(range.start / state.duration) * 100}%`, width: `${((range.end - range.start) / state.duration) * 100}%` }} />))}\r\n <div className=\"absolute left-0 top-0 bottom-0 bg-[var(--accent)]\" style={{ width: `${((isScrubbing ? scrubbingTime : state.currentTime) / state.duration) * 100}%` }} />\r\n </div>\r\n\r\n {/* Thumb */}\r\n <div\r\n className=\"absolute top-1/2 -translate-y-1/2 -translate-x-1/2 w-3.5 h-3.5 bg-white shadow-md scale-0 group-hover/slider:scale-100 transition-transform duration-100 z-10\"\r\n style={{\r\n left: `${((isScrubbing ? scrubbingTime : state.currentTime) / state.duration) * 100}%`,\r\n borderRadius: 'var(--radius-full)'\r\n }}\r\n />\r\n </div>\r\n )}\r\n\r\n <div className=\"flex items-center justify-between pointer-events-auto\">\r\n <div className=\"flex items-center gap-3\">\r\n {controls.filter(c => c.position === 'left' || c.position === 'center').map(renderControl)}\r\n </div>\r\n\r\n <div className=\"flex items-center gap-1\">\r\n {controls.filter(c => c.position === 'right').map(renderControl)}\r\n </div>\r\n </div>\r\n </div>\r\n </>\r\n )}\r\n </div>\r\n );\r\n \r\n if (state.isWebFullscreen && typeof document !== 'undefined') {\r\n return createPortal(playerContent, document.body);\r\n }\r\n \r\n return playerContent;\r\n};\r\n","\r\nimport './index.css';\r\nimport React from 'react';\r\nimport { createRoot } from 'react-dom/client';\r\nimport { StrataPlayer } from './ui/StrataPlayer';\r\nimport {\r\n StrataCore,\r\n PlayerState,\r\n PlayerSource,\r\n StrataConfig,\r\n TextTrackConfig,\r\n IPlugin,\r\n SubtitleSettings,\r\n PlayerTheme,\r\n Highlight,\r\n LayerConfig,\r\n ContextMenuItem,\r\n ControlItem,\r\n SettingItem,\r\n Notification\r\n} from './core/StrataCore';\r\n\r\n// Export React Component\r\nexport { StrataPlayer };\r\n\r\n// Export Core & Plugins for advanced usage\r\nexport { StrataCore };\r\nexport type {\r\n PlayerState,\r\n PlayerSource,\r\n StrataConfig,\r\n TextTrackConfig,\r\n IPlugin,\r\n SubtitleSettings,\r\n PlayerTheme,\r\n Highlight,\r\n LayerConfig,\r\n ContextMenuItem,\r\n ControlItem,\r\n SettingItem,\r\n Notification\r\n};\r\n\r\n// Export Vanilla JS / Framework Agnostic Mounting Helper\r\nexport interface StrataPlayerInstance {\r\n unmount: () => void;\r\n update: (props: any) => void;\r\n}\r\n\r\nexport const mountStrataPlayer = (container: HTMLElement, props: any): StrataPlayerInstance => {\r\n const root = createRoot(container);\r\n\r\n // Initial Render\r\n root.render(React.createElement(StrataPlayer, props));\r\n\r\n return {\r\n unmount: () => {\r\n root.unmount();\r\n },\r\n update: (newProps: any) => {\r\n // Merge props or replace depending on needs, here we merge with original + new\r\n root.render(React.createElement(StrataPlayer, { ...props, ...newProps }));\r\n }\r\n };\r\n};\r\n"],"names":["EventBus","__publicField","event","callback","_a","subscribers","cb","data","NanoStore","initialState","partial","prevState","update","listener","AudioEngine","video","e","value","formatTime","seconds","h","m","s","fetchVttWithRetry","url","retries","timeout","i","controller","id","res","r","parseVTT","notify","lines","cues","start","end","baseUrl","parseTime","t","parts","line","times","urlPart","hash","x","y","w","coords","injectLibraryResources","pre1","pre2","link","script","DEFAULT_SUBTITLE_SETTINGS","STORAGE_KEY","DEFAULT_STATE","getResolvedState","config","saved","raw","mergedSubtitleSettings","resolvedVideoFit","StrataCore","videoElement","isFs","lockType","state","settings","val","status","idx","prev","ms","details","total","title","_b","artwork","duration","position","playbackRate","message","isFatal","customMessage","error","delay","time","onCanPlay","finalMsg","buffered","index","newTracks","signal","effectiveTimeout","localController","fetchSignal","content","text","vtt","totalSeconds","d","container","entries","entry","plugin","sources","tracks","wasPlaying","source","isRetry","srcObj","initialSubtitleTracks","type","oldTracks","defaultTrackIndex","label","newIndex","newTrack","file","reader","blob","src","lang","isDefault","track","vol","safeVol","gain","visible","err","isWebFs","newState","canvas","ctx","direction","current","scaleX","scaleY","ratio","fit","safe","aspectRatio","videoFit","targetRatio","rect","containerRatio","finalW","finalH","initializeCastApi","isAvailable","castSession","mediaInfo","request","activeTrack","c","targetTrack","blobUrl","domTracks","newSettings","target","offset","currentOffset","delta","cue","options","notifId","response","contentLength","loaded","chunks","startTime","progressSamples","lastUpdate","done","now","percent","etaSuffix","rate","oldest","newest","timeDiff","bytesDiff","elapsed","etaMs","a","_c","format","bestBandwidth","bestUrl","bandwidthMatch","bandwidth","nextLine","segments","extension","mime","fileHandle","writable","memoryBlobs","isTsContent","segmentSamples","progress","countDiff","msPerSegment","avgTime","buffer","finalBlob","finalExt","n","newNotification","existing","p","useTransition","isActive","isMounted","setIsMounted","useState","isVisible","setIsVisible","useEffect","timer","Icon","className","children","fill","strokeWidth","viewBox","jsx","PlayIcon","PauseIcon","jsxs","VolumeHighIcon","VolumeLowIcon","VolumeMuteIcon","MaximizeIcon","MinimizeIcon","SettingsIcon","CheckIcon","PipIcon","SubtitleIcon","DownloadIcon","UploadIcon","ArrowLeftIcon","LoaderIcon","CastIcon","UsersIcon","ClockIcon","MinusIcon","PlusIcon","CustomizeIcon","TypeIcon","PaletteIcon","EyeIcon","MoveVerticalIcon","ResetIcon","BoldIcon","CaseUpperIcon","BlurIcon","CameraIcon","LockIcon","UnlockIcon","WebFullscreenIcon","FastForwardIcon","CloseIcon","InfoIcon","ServerIcon","CropIcon","SpeakerIcon","GaugeIcon","MusicIcon","WifiIcon","AlertCircleIcon","QualityIcon","VideoFlipIcon","SearchIcon","FileCheckIcon","FileWarningIcon","SunIcon","LayoutTemplateIcon","Replay10Icon","Forward10Icon","NotificationContainer","notifications","isProgress","SubtitleOverlay","getTextShadow","RenderContent","Toggle","checked","onChange","icon","tooltip","Slider","min","max","step","formatValue","Select","opt","SettingsGroup","Menu","onClose","align","maxHeight","containerRef","useRef","contentRef","height","setHeight","positionClasses","useLayoutEffect","updateHeight","observer","calculatedStyle","MenuItem","active","onClick","hasSubmenu","rightIcon","MenuHeader","onBack","rightAction","MenuDivider","MenuExplorer","items","history","setHistory","currentItem","currentList","currentTitle","goBack","navigateTo","item","React","SubtitleMenu","onSelect","onUpload","onSettingsChange","onReset","onOffsetChange","animationClass","view","setView","search","setSearch","fileInputRef","filteredTracks","useMemo","Fragment","v","ContextMenu","containerWidth","containerHeight","menuRef","layout","setLayout","width","newLeft","newTop","availableHeight","handleClickOutside","VideoInfo","player","stats","setStats","q","k","getContrastColor","hex","char","g","b","THEME_COLORS","THEMES","HtmlOrNode","style","StrataPlayer","props","poster","autoPlay","thumbnails","textTracks","plugins","onGetInstance","useScreenshot","usePip","useSetting","useFullscreen","useFullscreenWeb","useLock","useFastForward","useFlip","useAspectRatio","useHotKey","isBackdrop","useGestureSeek","useCenterControls","fetchTimeout","setPlayer","hasPlayed","setHasPlayed","playerHeight","setPlayerHeight","playerWidth","setPlayerWidth","isMobile","setIsMobile","useSyncExternalStore","useCallback","accentContrast","settingsOpen","setSettingsOpen","subtitleMenuOpen","setSubtitleMenuOpen","activeMenu","setActiveMenu","activeControlId","setActiveControlId","lastActiveControlId","contextMenu","setContextMenu","showVideoInfo","setShowVideoInfo","settingsTransition","subtitleTransition","controlTransition","closeAllMenus","handleGlobalClick","isScrubbing","setIsScrubbing","scrubbingTime","setScrubbingTime","isVolumeScrubbing","setIsVolumeScrubbing","isVolumeHovered","setIsVolumeHovered","isVolumeLocked","setIsVolumeLocked","isBrightnessAdjusting","setIsBrightnessAdjusting","thumbnailCues","setThumbnailCues","hoverTime","setHoverTime","hoverPos","setHoverPos","currentThumbnail","setCurrentThumbnail","seekAnimation","setSeekAnimation","skipTrigger","setSkipTrigger","isFastForwarding","setIsFastForwarding","fastForwardTimerRef","originalRateRef","touchStartX","touchStartY","touchStartTime","touchStartVolume","touchStartBrightness","gestureModeRef","isDraggingRef","clickTimeoutRef","controlsTimeoutRef","progressBarRef","volumeBarRef","animationCleanupRef","core","updates","setCues","handleKeyDown","handleMouseMove","startFastForward","stopFastForward","handleTouchStart","handleTouchMove","clientX","clientY","deltaX","deltaY","halfScreen","deltaRatio","newTime","deltaPct","handleTouchEnd","calculateTimeFromEvent","handleSeekStart","handleMove","moveEvent","handleUp","upEvent","calculateVolumeFromEvent","handleVolumeStart","handleProgressMove","triggerSkip","handleContainerClick","handleContextMenu","handleVolumeIconClick","VolIcon","menuMaxHeight","getIconClass","getButtonClass","iconClass","btnClass","center","isControlsVisible","isVolumeVisible","backdropClass","controls","currentSource","isHls","downloadControl","renderControl","controlId","isMenuOpen","shouldRenderMenu","wasOpen","_d","child","statusIcon","lvl","_e","theme","contextMenuItems","close","playerContent","layer","range","createPortal","mountStrataPlayer","root","createRoot","newProps"],"mappings":"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"}
|