@frameset/plex-player 1.0.6 → 2.0.1

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.
@@ -0,0 +1,438 @@
1
+ import React$1 from 'react';
2
+
3
+ interface VideoSource {
4
+ src: string;
5
+ type?: string;
6
+ quality?: string;
7
+ label?: string;
8
+ }
9
+ interface TextTrack {
10
+ src: string;
11
+ kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';
12
+ srclang: string;
13
+ label: string;
14
+ default?: boolean;
15
+ }
16
+ interface VastConfig {
17
+ url: string;
18
+ skipDelay?: number;
19
+ position?: 'preroll' | 'midroll' | 'postroll';
20
+ midrollTime?: number;
21
+ }
22
+ interface PlexVideoPlayerProps {
23
+ /** Video source URL or array of sources */
24
+ src: string | VideoSource[];
25
+ /** Poster image URL */
26
+ poster?: string;
27
+ /** Enable autoplay */
28
+ autoPlay?: boolean;
29
+ /** Mute video on load */
30
+ muted?: boolean;
31
+ /** Loop video playback */
32
+ loop?: boolean;
33
+ /** Preload behavior */
34
+ preload?: 'none' | 'metadata' | 'auto';
35
+ /** Player width */
36
+ width?: number | string;
37
+ /** Player height */
38
+ height?: number | string;
39
+ /** Enable controls */
40
+ controls?: boolean;
41
+ /** Enable Picture-in-Picture */
42
+ pip?: boolean;
43
+ /** Enable fullscreen */
44
+ fullscreen?: boolean;
45
+ /** Enable playback speed control */
46
+ playbackSpeed?: boolean;
47
+ /** Available playback speeds */
48
+ playbackSpeeds?: number[];
49
+ /** Enable volume control */
50
+ volume?: boolean;
51
+ /** Initial volume (0-1) */
52
+ initialVolume?: number;
53
+ /** Enable progress bar */
54
+ progressBar?: boolean;
55
+ /** Enable time display */
56
+ timeDisplay?: boolean;
57
+ /** Enable quality selector */
58
+ qualitySelector?: boolean;
59
+ /** Text tracks (subtitles) */
60
+ textTracks?: TextTrack[];
61
+ /** VAST ads configuration */
62
+ vast?: VastConfig | VastConfig[];
63
+ /** Enable keyboard shortcuts */
64
+ keyboard?: boolean;
65
+ /** Hotkey mappings */
66
+ hotkeys?: HotkeyConfig;
67
+ /** Custom CSS class */
68
+ className?: string;
69
+ /** Inline styles */
70
+ style?: React.CSSProperties;
71
+ /** Accent color for controls */
72
+ accentColor?: string;
73
+ /** Control bar color theme */
74
+ theme?: 'dark' | 'light' | 'auto';
75
+ /** Timeout for hiding controls (ms) */
76
+ controlsTimeout?: number;
77
+ /** Enable double-click to fullscreen */
78
+ doubleClickFullscreen?: boolean;
79
+ /** Enable click to play/pause */
80
+ clickToPlay?: boolean;
81
+ /** Thumbnail preview on progress bar */
82
+ thumbnailPreview?: {
83
+ enabled: boolean;
84
+ sprites?: string;
85
+ interval?: number;
86
+ width?: number;
87
+ height?: number;
88
+ };
89
+ onPlay?: () => void;
90
+ onPause?: () => void;
91
+ onEnded?: () => void;
92
+ onTimeUpdate?: (time: number) => void;
93
+ onProgress?: (buffered: number) => void;
94
+ onVolumeChange?: (volume: number, muted: boolean) => void;
95
+ onSeeking?: (time: number) => void;
96
+ onSeeked?: (time: number) => void;
97
+ onRateChange?: (rate: number) => void;
98
+ onQualityChange?: (quality: string) => void;
99
+ onFullscreenChange?: (isFullscreen: boolean) => void;
100
+ onPipChange?: (isPip: boolean) => void;
101
+ onError?: (error: MediaError | null) => void;
102
+ onReady?: () => void;
103
+ onAdStart?: (ad: VastAdInfo) => void;
104
+ onAdEnd?: () => void;
105
+ onAdSkip?: () => void;
106
+ onAdError?: (error: Error) => void;
107
+ }
108
+ interface HotkeyConfig {
109
+ play?: string;
110
+ mute?: string;
111
+ fullscreen?: string;
112
+ pip?: string;
113
+ seekForward?: string;
114
+ seekBackward?: string;
115
+ volumeUp?: string;
116
+ volumeDown?: string;
117
+ }
118
+ interface VastAdInfo {
119
+ id: string;
120
+ title: string;
121
+ duration: number;
122
+ skipOffset?: number;
123
+ clickThrough?: string;
124
+ }
125
+ interface PlexVideoPlayerRef {
126
+ play: () => Promise<void>;
127
+ pause: () => void;
128
+ stop: () => void;
129
+ seek: (time: number) => void;
130
+ setVolume: (volume: number) => void;
131
+ mute: () => void;
132
+ unmute: () => void;
133
+ toggleMute: () => void;
134
+ enterFullscreen: () => Promise<void>;
135
+ exitFullscreen: () => Promise<void>;
136
+ toggleFullscreen: () => Promise<void>;
137
+ enterPip: () => Promise<void>;
138
+ exitPip: () => Promise<void>;
139
+ togglePip: () => Promise<void>;
140
+ setPlaybackRate: (rate: number) => void;
141
+ setQuality: (quality: string) => void;
142
+ getCurrentTime: () => number;
143
+ getDuration: () => number;
144
+ getVolume: () => number;
145
+ isMuted: () => boolean;
146
+ isPlaying: () => boolean;
147
+ isFullscreen: () => boolean;
148
+ isPip: () => boolean;
149
+ getVideoElement: () => HTMLVideoElement | null;
150
+ }
151
+ interface PlayerState {
152
+ isPlaying: boolean;
153
+ isPaused: boolean;
154
+ isEnded: boolean;
155
+ isBuffering: boolean;
156
+ isSeeking: boolean;
157
+ isFullscreen: boolean;
158
+ isPip: boolean;
159
+ isMuted: boolean;
160
+ isAdPlaying: boolean;
161
+ volume: number;
162
+ currentTime: number;
163
+ duration: number;
164
+ buffered: number;
165
+ playbackRate: number;
166
+ currentQuality: string | null;
167
+ error: MediaError | null;
168
+ }
169
+ interface UsePlayerOptions {
170
+ autoPlay?: boolean;
171
+ muted?: boolean;
172
+ loop?: boolean;
173
+ volume?: number;
174
+ playbackRate?: number;
175
+ }
176
+ interface UsePlayerReturn {
177
+ state: PlayerState;
178
+ videoRef: React.RefObject<HTMLVideoElement>;
179
+ containerRef: React.RefObject<HTMLDivElement>;
180
+ play: () => Promise<void>;
181
+ pause: () => void;
182
+ togglePlay: () => void;
183
+ seek: (time: number) => void;
184
+ setVolume: (volume: number) => void;
185
+ toggleMute: () => void;
186
+ setPlaybackRate: (rate: number) => void;
187
+ enterFullscreen: () => Promise<void>;
188
+ exitFullscreen: () => Promise<void>;
189
+ toggleFullscreen: () => Promise<void>;
190
+ enterPip: () => Promise<void>;
191
+ exitPip: () => Promise<void>;
192
+ togglePip: () => Promise<void>;
193
+ }
194
+
195
+ declare const PlexVideoPlayer: React$1.ForwardRefExoticComponent<PlexVideoPlayerProps & React$1.RefAttributes<PlexVideoPlayerRef>>;
196
+
197
+ interface ProgressBarProps {
198
+ currentTime: number;
199
+ duration: number;
200
+ buffered: number;
201
+ onSeek: (time: number) => void;
202
+ thumbnailPreview?: {
203
+ enabled: boolean;
204
+ sprites?: string;
205
+ interval?: number;
206
+ width?: number;
207
+ height?: number;
208
+ };
209
+ disabled?: boolean;
210
+ }
211
+ declare const ProgressBar: React$1.FC<ProgressBarProps>;
212
+
213
+ interface VolumeControlProps {
214
+ volume: number;
215
+ muted: boolean;
216
+ onVolumeChange: (volume: number) => void;
217
+ onToggleMute: () => void;
218
+ }
219
+ declare const VolumeControl: React$1.FC<VolumeControlProps>;
220
+
221
+ interface SettingsMenuProps {
222
+ playbackRate: number;
223
+ playbackSpeeds: number[];
224
+ onPlaybackRateChange: (rate: number) => void;
225
+ qualityEnabled: boolean;
226
+ sources?: VideoSource[];
227
+ currentQuality?: string;
228
+ onQualityChange?: (quality: string) => void;
229
+ captionsEnabled?: boolean;
230
+ textTracks?: TextTrack[];
231
+ currentTrack?: string;
232
+ onTrackChange?: (track: string | null) => void;
233
+ }
234
+ declare const SettingsMenu: React$1.FC<SettingsMenuProps>;
235
+
236
+ interface AdOverlayProps {
237
+ ad: VastAdInfo;
238
+ timeRemaining: number;
239
+ canSkip: boolean;
240
+ onSkip: () => void;
241
+ onClick: () => void;
242
+ }
243
+ declare const AdOverlay: React$1.FC<AdOverlayProps>;
244
+
245
+ interface ErrorDisplayProps {
246
+ error: MediaError | null;
247
+ onRetry: () => void;
248
+ }
249
+ declare const ErrorDisplay: React$1.FC<ErrorDisplayProps>;
250
+
251
+ interface LoaderProps {
252
+ visible: boolean;
253
+ }
254
+ declare const Loader: React$1.FC<LoaderProps>;
255
+
256
+ interface IconProps {
257
+ className?: string;
258
+ size?: number;
259
+ }
260
+ declare const PlayIcon: React$1.FC<IconProps>;
261
+ declare const PauseIcon: React$1.FC<IconProps>;
262
+ declare const VolumeHighIcon: React$1.FC<IconProps>;
263
+ declare const VolumeMediumIcon: React$1.FC<IconProps>;
264
+ declare const VolumeLowIcon: React$1.FC<IconProps>;
265
+ declare const VolumeMuteIcon: React$1.FC<IconProps>;
266
+ declare const FullscreenIcon: React$1.FC<IconProps>;
267
+ declare const FullscreenExitIcon: React$1.FC<IconProps>;
268
+ declare const PipIcon: React$1.FC<IconProps>;
269
+ declare const PipExitIcon: React$1.FC<IconProps>;
270
+ declare const SettingsIcon: React$1.FC<IconProps>;
271
+ declare const CaptionsIcon: React$1.FC<IconProps>;
272
+ declare const SpeedIcon: React$1.FC<IconProps>;
273
+ declare const QualityIcon: React$1.FC<IconProps>;
274
+ declare const ForwardIcon: React$1.FC<IconProps>;
275
+ declare const RewindIcon: React$1.FC<IconProps>;
276
+ declare const SkipNextIcon: React$1.FC<IconProps>;
277
+ declare const SkipPrevIcon: React$1.FC<IconProps>;
278
+ declare const ErrorIcon: React$1.FC<IconProps>;
279
+ declare const ExternalLinkIcon: React$1.FC<IconProps>;
280
+ declare const CheckIcon: React$1.FC<IconProps>;
281
+
282
+ declare const usePlayer: (options?: UsePlayerOptions) => UsePlayerReturn;
283
+
284
+ interface UseKeyboardOptions {
285
+ enabled: boolean;
286
+ hotkeys?: HotkeyConfig;
287
+ onPlay: () => void;
288
+ onMute: () => void;
289
+ onFullscreen: () => void;
290
+ onPip: () => void;
291
+ onSeek: (delta: number) => void;
292
+ onVolume: (delta: number) => void;
293
+ containerRef: React.RefObject<HTMLDivElement>;
294
+ }
295
+ declare const useKeyboard: ({ enabled, hotkeys, onPlay, onMute, onFullscreen, onPip, onSeek, onVolume, containerRef, }: UseKeyboardOptions) => void;
296
+
297
+ interface UseVastOptions {
298
+ vastConfig?: VastConfig | VastConfig[];
299
+ videoRef: React.RefObject<HTMLVideoElement>;
300
+ onAdStart?: (ad: VastAdInfo) => void;
301
+ onAdEnd?: () => void;
302
+ onAdSkip?: () => void;
303
+ onAdError?: (error: Error) => void;
304
+ }
305
+ interface UseVastReturn {
306
+ isAdPlaying: boolean;
307
+ currentAd: VastAdInfo | null;
308
+ adTimeRemaining: number;
309
+ canSkip: boolean;
310
+ skipAd: () => void;
311
+ handleAdClick: () => void;
312
+ checkForAd: (currentTime: number, duration: number) => void;
313
+ }
314
+ declare const useVast: ({ vastConfig, videoRef, onAdStart, onAdEnd, onAdSkip, onAdError, }: UseVastOptions) => UseVastReturn;
315
+
316
+ /**
317
+ * Format time in seconds to MM:SS or HH:MM:SS format
318
+ */
319
+ declare const formatTime: (seconds: number) => string;
320
+ /**
321
+ * Parse time string to seconds
322
+ */
323
+ declare const parseTime: (time: string) => number;
324
+ /**
325
+ * Calculate percentage
326
+ */
327
+ declare const percentage: (value: number, total: number) => number;
328
+ /**
329
+ * Clamp a value between min and max
330
+ */
331
+ declare const clamp: (value: number, min: number, max: number) => number;
332
+ /**
333
+ * Throttle function execution
334
+ */
335
+ declare const throttle: <T extends (...args: unknown[]) => unknown>(func: T, limit: number) => ((...args: Parameters<T>) => void);
336
+ /**
337
+ * Debounce function execution
338
+ */
339
+ declare const debounce: <T extends (...args: unknown[]) => unknown>(func: T, wait: number) => ((...args: Parameters<T>) => void);
340
+ /**
341
+ * Check if fullscreen is supported
342
+ */
343
+ declare const isFullscreenSupported: () => boolean;
344
+ /**
345
+ * Check if Picture-in-Picture is supported
346
+ */
347
+ declare const isPipSupported: () => boolean;
348
+ /**
349
+ * Get current fullscreen element
350
+ */
351
+ declare const getFullscreenElement: () => Element | null;
352
+ /**
353
+ * Request fullscreen on element
354
+ */
355
+ declare const requestFullscreen: (element: HTMLElement) => Promise<void>;
356
+ /**
357
+ * Exit fullscreen
358
+ */
359
+ declare const exitFullscreen: () => Promise<void>;
360
+ /**
361
+ * Detect video type from URL
362
+ */
363
+ declare const detectVideoType: (url: string) => string;
364
+ /**
365
+ * Check if HLS is natively supported
366
+ */
367
+ declare const isHlsNativelySupported: () => boolean;
368
+ /**
369
+ * Generate unique ID
370
+ */
371
+ declare const generateId: () => string;
372
+ /**
373
+ * Check if device is mobile
374
+ */
375
+ declare const isMobile: () => boolean;
376
+ /**
377
+ * Check if device is touch-enabled
378
+ */
379
+ declare const isTouchDevice: () => boolean;
380
+ /**
381
+ * Parse buffered time ranges
382
+ */
383
+ declare const getBufferedEnd: (video: HTMLVideoElement) => number;
384
+ /**
385
+ * Check browser support for specific video format
386
+ */
387
+ declare const canPlayType: (type: string) => boolean;
388
+
389
+ interface VastMediaFile {
390
+ url: string;
391
+ type: string;
392
+ width: number;
393
+ height: number;
394
+ bitrate?: number;
395
+ }
396
+ interface VastAd {
397
+ id: string;
398
+ title: string;
399
+ description?: string;
400
+ duration: number;
401
+ skipOffset?: number;
402
+ clickThrough?: string;
403
+ clickTracking?: string[];
404
+ impressionUrls: string[];
405
+ mediaFiles: VastMediaFile[];
406
+ trackingEvents: Record<string, string[]>;
407
+ }
408
+ interface VastResponse {
409
+ ads: VastAd[];
410
+ error?: string;
411
+ }
412
+ /**
413
+ * Parse VAST XML response
414
+ */
415
+ declare const parseVastXml: (xmlString: string) => VastResponse;
416
+ /**
417
+ * Fetch and parse VAST ad
418
+ */
419
+ declare const fetchVastAd: (config: VastConfig) => Promise<VastAd | null>;
420
+ /**
421
+ * Select best media file based on device capabilities
422
+ */
423
+ declare const selectBestMediaFile: (mediaFiles: VastMediaFile[]) => VastMediaFile | null;
424
+ /**
425
+ * Fire tracking pixel
426
+ */
427
+ declare const fireTrackingPixel: (url: string) => void;
428
+ /**
429
+ * Fire multiple tracking pixels
430
+ */
431
+ declare const fireTrackingPixels: (urls: string[]) => void;
432
+ /**
433
+ * Convert VAST ad to player-friendly format
434
+ */
435
+ declare const convertToAdInfo: (ad: VastAd) => VastAdInfo;
436
+
437
+ export { AdOverlay, CaptionsIcon, CheckIcon, ErrorDisplay, ErrorIcon, ExternalLinkIcon, ForwardIcon, FullscreenExitIcon, FullscreenIcon, Loader, PauseIcon, PipExitIcon, PipIcon, PlayIcon, PlexVideoPlayer, ProgressBar, QualityIcon, RewindIcon, SettingsIcon, SettingsMenu, SkipNextIcon, SkipPrevIcon, SpeedIcon, VolumeControl, VolumeHighIcon, VolumeLowIcon, VolumeMediumIcon, VolumeMuteIcon, canPlayType, clamp, convertToAdInfo, debounce, PlexVideoPlayer as default, detectVideoType, exitFullscreen, fetchVastAd, fireTrackingPixel, fireTrackingPixels, formatTime, generateId, getBufferedEnd, getFullscreenElement, isFullscreenSupported, isHlsNativelySupported, isMobile, isPipSupported, isTouchDevice, parseTime, parseVastXml, percentage, requestFullscreen, selectBestMediaFile, throttle, useKeyboard, usePlayer, useVast };
438
+ export type { HotkeyConfig, PlayerState, PlexVideoPlayerProps, PlexVideoPlayerRef, TextTrack, UsePlayerOptions, UsePlayerReturn, VastAdInfo, VastConfig, VideoSource };
@@ -0,0 +1,2 @@
1
+ import{jsxs as e,jsx as t,Fragment as n}from"react/jsx-runtime";import{useRef as r,useState as i,useCallback as l,useEffect as a,forwardRef as c,useMemo as s,useImperativeHandle as o}from"react";const u=e=>{if(!isFinite(e)||isNaN(e))return"0:00";const t=Math.floor(e/3600),n=Math.floor(e%3600/60),r=Math.floor(e%60);return t>0?`${t}:${n.toString().padStart(2,"0")}:${r.toString().padStart(2,"0")}`:`${n}:${r.toString().padStart(2,"0")}`},d=e=>{const t=e.split(":").map(Number);return 3===t.length?3600*t[0]+60*t[1]+t[2]:2===t.length?60*t[0]+t[1]:t[0]||0},p=(e,t)=>0===t?0:Math.min(100,Math.max(0,e/t*100)),m=(e,t,n)=>Math.min(n,Math.max(t,e)),h=(e,t)=>{let n=!1;return(...r)=>{n||(e(...r),n=!0,setTimeout(()=>n=!1,t))}},v=(e,t)=>{let n=null;return(...r)=>{n&&clearTimeout(n),n=setTimeout(()=>e(...r),t)}},g=()=>!!(document.fullscreenEnabled||document.webkitFullscreenEnabled||document.mozFullScreenEnabled||document.msFullscreenEnabled),y=()=>"pictureInPictureEnabled"in document&&document.pictureInPictureEnabled,w=()=>document.fullscreenElement||document.webkitFullscreenElement||document.mozFullScreenElement||document.msFullscreenElement||null,f=async e=>{e.requestFullscreen?await e.requestFullscreen():e.webkitRequestFullscreen?await e.webkitRequestFullscreen():e.mozRequestFullScreen?await e.mozRequestFullScreen():e.msRequestFullscreen&&await e.msRequestFullscreen()},b=async()=>{document.exitFullscreen?await document.exitFullscreen():document.webkitExitFullscreen?await document.webkitExitFullscreen():document.mozCancelFullScreen?await document.mozCancelFullScreen():document.msExitFullscreen&&await document.msExitFullscreen()},k=e=>{const t=e.split("?")[0].split(".").pop()?.toLowerCase();return{mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",ogv:"video/ogg",m3u8:"application/x-mpegURL",mpd:"application/dash+xml",mov:"video/quicktime",avi:"video/x-msvideo",mkv:"video/x-matroska"}[t||""]||"video/mp4"},x=()=>""!==document.createElement("video").canPlayType("application/vnd.apple.mpegurl"),E=()=>`plex-${Math.random().toString(36).substring(2,11)}`,_=()=>/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),N=()=>"ontouchstart"in window||navigator.maxTouchPoints>0,z=e=>{if(0===e.buffered.length)return 0;const t=e.currentTime;for(let n=0;n<e.buffered.length;n++)if(e.buffered.start(n)<=t&&e.buffered.end(n)>=t)return e.buffered.end(n);return e.buffered.end(e.buffered.length-1)},P=e=>{const t=document.createElement("video").canPlayType(e);return"probably"===t||"maybe"===t},C=({currentTime:n,duration:c,buffered:s,onSeek:o,thumbnailPreview:d,disabled:h=!1})=>{const v=r(null),[g,y]=i(!1),[w,f]=i(null),[b,k]=i(0),x=p(n,c),E=p(s,c),_=l(e=>{if(!v.current)return 0;const t=v.current.getBoundingClientRect();return m((e-t.left)/t.width,0,1)*c},[c]),N=l(e=>{if(!v.current)return;const t=v.current.getBoundingClientRect(),n="clientX"in e?e.clientX:0,r=m(n-t.left,0,t.width),i=_(n);k(r),f(i),g&&o(i)},[g,_,o]),z=l(e=>{if(h)return;e.preventDefault(),y(!0);const t=_(e.clientX);o(t)},[h,_,o]),P=l(()=>{y(!1)},[]),C=l(e=>{const t=_(e.clientX);f(t)},[_]),T=l(()=>{f(null)},[]);a(()=>{if(g){const e=e=>N(e);return window.addEventListener("mousemove",e),window.addEventListener("mouseup",P),()=>{window.removeEventListener("mousemove",e),window.removeEventListener("mouseup",P)}}},[g,N,P]);const L=l(e=>{if(h)return;e.preventDefault();const t=e.touches[0],n=_(t.clientX);y(!0),o(n)},[h,_,o]),S=l(e=>{if(!g)return;const t=e.touches[0],n=_(t.clientX);o(n)},[g,_,o]),A=l(()=>{y(!1)},[]);return e("div",{ref:v,className:"plex-video-player__progress-container",onMouseDown:z,onMouseEnter:C,onMouseLeave:T,onMouseMove:e=>N(e.nativeEvent),onTouchStart:L,onTouchMove:S,onTouchEnd:A,role:"slider","aria-label":"Video progress","aria-valuemin":0,"aria-valuemax":c,"aria-valuenow":n,"aria-valuetext":u(n),tabIndex:0,children:[e("div",{className:"plex-video-player__progress",children:[t("div",{className:"plex-video-player__progress-buffered",style:{width:`${E}%`}}),t("div",{className:"plex-video-player__progress-played",style:{width:`${x}%`}}),t("div",{className:"plex-video-player__progress-handle",style:{left:`${x}%`}})]}),d?.enabled&&null!==w&&e("div",{className:"plex-video-player__thumbnail-preview",style:{left:`${b}px`,width:d.width||160,height:d.height||90},children:[d.sprites&&t("div",{style:{width:"100%",height:"100%",backgroundImage:`url(${d.sprites})`,backgroundPosition:M(w,c,d.interval||10,d.width||160,d.height||90),backgroundSize:"cover"}}),t("div",{className:"plex-video-player__thumbnail-time",children:u(w)})]}),null!==w&&!d?.enabled&&t("div",{className:"plex-video-player__thumbnail-preview",style:{left:`${b}px`,width:"auto",height:"auto",padding:"4px 8px"},children:t("span",{style:{color:"white",fontSize:"12px"},children:u(w)})})]})},M=(e,t,n,r,i)=>{const l=Math.floor(e/n);return`-${l%10*r}px -${Math.floor(l/10)*i}px`},T=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M8 5v14l11-7z"})}),L=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M6 19h4V5H6v14zm8-14v14h4V5h-4z"})}),S=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z"})}),A=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M18.5 12c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM5 9v6h4l5 5V4L9 9H5z"})}),F=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M7 9v6h4l5 5V4l-5 5H7z"})}),V=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z"})}),q=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"})}),R=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M5 16h3v3h2v-5H5v2zm3-8H5v2h5V5H8v3zm6 11h2v-3h3v-2h-5v5zm2-11V5h-2v5h5V8h-3z"})}),B=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h18v14z"})}),H=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M21 3H3c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H3V5h18v14zM5 7h8v6H5z"})}),I=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M19.14 12.94c.04-.31.06-.63.06-.94 0-.31-.02-.63-.06-.94l2.03-1.58c.18-.14.23-.41.12-.61l-1.92-3.32c-.12-.22-.37-.29-.59-.22l-2.39.96c-.5-.38-1.03-.7-1.62-.94l-.36-2.54c-.04-.24-.24-.41-.48-.41h-3.84c-.24 0-.43.17-.47.41l-.36 2.54c-.59.24-1.13.57-1.62.94l-2.39-.96c-.22-.08-.47 0-.59.22L2.74 8.87c-.12.21-.08.47.12.61l2.03 1.58c-.04.31-.06.63-.06.94s.02.63.06.94l-2.03 1.58c-.18.14-.23.41-.12.61l1.92 3.32c.12.22.37.29.59.22l2.39-.96c.5.38 1.03.7 1.62.94l.36 2.54c.05.24.24.41.48.41h3.84c.24 0 .44-.17.47-.41l.36-2.54c.59-.24 1.13-.56 1.62-.94l2.39.96c.22.08.47 0 .59-.22l1.92-3.32c.12-.22.07-.47-.12-.61l-2.01-1.58zM12 15.6c-1.98 0-3.6-1.62-3.6-3.6s1.62-3.6 3.6-3.6 3.6 1.62 3.6 3.6-1.62 3.6-3.6 3.6z"})}),D=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M19 4H5c-1.11 0-2 .9-2 2v12c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm-8 7H9.5v-.5h-2v3h2V13H11v1c0 .55-.45 1-1 1H7c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1zm7 0h-1.5v-.5h-2v3h2V13H18v1c0 .55-.45 1-1 1h-3c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v1z"})}),$=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44zm-9.79 6.84a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z"})}),O=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm0 16H5V5h14v14zM7.5 13h2v2H7.5zm4.5 0h2v2h-2zm4.5 0h2v2h-2zM7.5 9h2v2H7.5zm4.5 0h2v2h-2zm4.5 0h2v2h-2z"})}),Q=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M4 18l8.5-6L4 6v12zm9-12v12l8.5-6L13 6z"})}),U=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M11 18V6l-8.5 6 8.5 6zm.5-6l8.5 6V6l-8.5 6z"})}),X=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M6 18l8.5-6L6 6v12zM16 6v12h2V6h-2z"})}),j=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M6 6h2v12H6zm3.5 6l8.5 6V6z"})}),K=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm1 15h-2v-2h2v2zm0-4h-2V7h2v6z"})}),G=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z"})}),J=({className:e,size:n=24})=>t("svg",{className:e,width:n,height:n,viewBox:"0 0 24 24",fill:"currentColor",xmlns:"http://www.w3.org/2000/svg",children:t("path",{d:"M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"})}),W=({volume:n,muted:r,onVolumeChange:i,onToggleMute:a})=>{const c=l(e=>{const t=parseFloat(e.target.value);i(t)},[i]);return e("div",{className:"plex-video-player__volume-container",children:[t("button",{className:"plex-video-player__btn",onClick:a,"aria-label":r?"Unmute":"Mute",title:r?"Unmute (M)":"Mute (M)",type:"button",children:t(r||0===n?V:n<.33?F:n<.66?A:S,{})}),t("div",{className:"plex-video-player__volume-slider-container",children:t("input",{type:"range",className:"plex-video-player__volume-slider",min:0,max:1,step:.01,value:r?0:n,onChange:c,"aria-label":"Volume",style:{background:`linear-gradient(to right, var(--plex-primary) 0%, var(--plex-primary) ${100*(r?0:n)}%, var(--plex-progress-bg) ${100*(r?0:n)}%, var(--plex-progress-bg) 100%)`}})})]})},Y=({playbackRate:c,playbackSpeeds:s,onPlaybackRateChange:o,qualityEnabled:u,sources:d,currentQuality:p,onQualityChange:m,captionsEnabled:h,textTracks:v,currentTrack:g,onTrackChange:y})=>{const[w,f]=i(!1),[b,k]=i("main"),x=r(null);a(()=>{const e=e=>{x.current&&!x.current.contains(e.target)&&(f(!1),k("main"))};if(w)return document.addEventListener("mousedown",e),()=>document.removeEventListener("mousedown",e)},[w]);const E=l(()=>{f(e=>!e),k("main")},[]),_=l(e=>{o(e),k("main")},[o]),N=l(e=>{m?.(e),k("main")},[m]),z=l(e=>{y?.(e),k("main")},[y]);return e("div",{className:"plex-video-player__settings-container",ref:x,children:[t("button",{className:"plex-video-player__btn",onClick:E,"aria-label":"Settings","aria-expanded":w,title:"Settings",type:"button",children:t(I,{})}),w&&e("div",{className:"plex-video-player__settings-menu "+(w?"plex-video-player__settings-menu--open":""),children:["main"===b&&e(n,{children:[t("div",{className:"plex-video-player__settings-title",children:"Settings"}),e("button",{className:"plex-video-player__settings-item",onClick:()=>k("speed"),type:"button",children:[t("span",{children:"Playback Speed"}),t("span",{children:1===c?"Normal":`${c}x`})]}),u&&d&&d.length>1&&e("button",{className:"plex-video-player__settings-item",onClick:()=>k("quality"),type:"button",children:[t("span",{children:"Quality"}),t("span",{children:p||"Auto"})]}),h&&v&&v.length>0&&e("button",{className:"plex-video-player__settings-item",onClick:()=>k("captions"),type:"button",children:[t("span",{children:"Captions"}),t("span",{children:g||"Off"})]})]}),"speed"===b&&e(n,{children:[t("button",{className:"plex-video-player__settings-title",onClick:()=>k("main"),style:{cursor:"pointer",border:"none",background:"transparent",width:"100%",textAlign:"left"},type:"button",children:"← Playback Speed"}),t("div",{className:"plex-video-player__speed-menu",children:s.map(e=>t("button",{className:"plex-video-player__speed-btn "+(c===e?"plex-video-player__speed-btn--active":""),onClick:()=>_(e),type:"button",children:1===e?"Normal":`${e}x`},e))})]}),"quality"===b&&e(n,{children:[t("button",{className:"plex-video-player__settings-title",onClick:()=>k("main"),style:{cursor:"pointer",border:"none",background:"transparent",width:"100%",textAlign:"left"},type:"button",children:"← Quality"}),t("div",{className:"plex-video-player__quality-menu",children:d?.map(n=>e("button",{className:"plex-video-player__settings-item "+(p===n.quality?"plex-video-player__settings-item--active":""),onClick:()=>N(n.quality||n.src),type:"button",children:[t("span",{children:n.label||n.quality||"Unknown"}),p===n.quality&&t(J,{size:16})]},n.quality||n.src))})]}),"captions"===b&&e(n,{children:[t("button",{className:"plex-video-player__settings-title",onClick:()=>k("main"),style:{cursor:"pointer",border:"none",background:"transparent",width:"100%",textAlign:"left"},type:"button",children:"← Captions"}),e("div",{className:"plex-video-player__quality-menu",children:[e("button",{className:"plex-video-player__settings-item "+(g?"":"plex-video-player__settings-item--active"),onClick:()=>z(null),type:"button",children:[t("span",{children:"Off"}),!g&&t(J,{size:16})]}),v?.map(n=>e("button",{className:"plex-video-player__settings-item "+(g===n.srclang?"plex-video-player__settings-item--active":""),onClick:()=>z(n.srclang),type:"button",children:[t("span",{children:n.label}),g===n.srclang&&t(J,{size:16})]},n.srclang))]})]})]})]})},Z=({ad:n,timeRemaining:r,canSkip:i,onSkip:l,onClick:a})=>{const c=i?"Skip Ad":`Skip in ${Math.ceil(r)}s`;return e("div",{className:"plex-video-player__ad-overlay",onClick:a,children:[e("div",{className:"plex-video-player__ad-info",children:[t("span",{className:"plex-video-player__ad-badge",children:"Ad"}),e("span",{children:[u(r)," remaining"]})]}),n.clickThrough&&e("button",{className:"plex-video-player__ad-learn-more",onClick:e=>{e.stopPropagation(),a()},type:"button",children:[t(G,{size:16}),"Learn More"]}),t("button",{className:"plex-video-player__ad-skip",onClick:e=>{e.stopPropagation(),i&&l()},disabled:!i,type:"button",children:c})]})},ee={1:"The video playback was aborted.",2:"A network error occurred while loading the video.",3:"The video format is not supported or cannot be decoded.",4:"The video source is not supported."},te=({error:n,onRetry:r})=>{const i=n?.code||0,l=ee[i]||"An unknown error occurred.";return e("div",{className:"plex-video-player__error",children:[t(K,{className:"plex-video-player__error-icon",size:60}),t("div",{className:"plex-video-player__error-message",children:l}),i>0&&e("div",{className:"plex-video-player__error-code",children:["Error Code: ",i]}),t("button",{className:"plex-video-player__error-retry",onClick:r,type:"button",children:"Try Again"})]})},ne=({visible:e})=>e?t("div",{className:"plex-video-player__loader",children:t("div",{className:"plex-video-player__loader-spinner"})}):null,re={play:"Space",mute:"m",fullscreen:"f",pip:"p",seekForward:"ArrowRight",seekBackward:"ArrowLeft",volumeUp:"ArrowUp",volumeDown:"ArrowDown"},ie=({enabled:e,hotkeys:t={},onPlay:n,onMute:r,onFullscreen:i,onPip:c,onSeek:s,onVolume:o,containerRef:u})=>{const d={...re,...t},p=l(t=>{if(!e)return;const l=t.target;if("INPUT"===l.tagName||"TEXTAREA"===l.tagName||l.isContentEditable)return;const a=u.current;if(!a||!a.contains(document.activeElement))return;switch(t.key){case d.play:case" ":t.preventDefault(),n();break;case d.mute:case"M":t.preventDefault(),r();break;case d.fullscreen:case"F":t.preventDefault(),i();break;case d.pip:case"P":t.preventDefault(),c();break;case d.seekForward:t.preventDefault(),s(t.shiftKey?30:10);break;case d.seekBackward:t.preventDefault(),s(t.shiftKey?-30:-10);break;case d.volumeUp:t.preventDefault(),o(.1);break;case d.volumeDown:t.preventDefault(),o(-.1);break;case"0":case"1":case"2":case"3":case"4":case"5":case"6":case"7":case"8":case"9":t.preventDefault(),s(-1/0)}},[e,d,n,r,i,c,s,o,u]);a(()=>{if(e)return document.addEventListener("keydown",p),()=>{document.removeEventListener("keydown",p)}},[e,p])},le=e=>{const t=(new DOMParser).parseFromString(e,"text/xml");if(t.querySelector("parsererror"))return{ads:[],error:"Failed to parse VAST XML"};const n=[];return t.querySelectorAll("Ad").forEach(e=>{const t=e.querySelector("InLine");if(!t)return;const r=e.getAttribute("id")||"",i=t.querySelector("AdTitle")?.textContent||"",l=t.querySelector("Description")?.textContent||void 0,a=t.querySelectorAll("Creative");let c,s,o=0;const u=[],d=[],p={};a.forEach(e=>{const t=e.querySelector("Linear");if(!t)return;const n=t.querySelector("Duration")?.textContent;n&&(o=ae(n));const r=t.getAttribute("skipoffset");r&&(c=ae(r));t.querySelectorAll("MediaFile").forEach(e=>{const t=e.textContent?.trim();t&&d.push({url:t,type:e.getAttribute("type")||"video/mp4",width:parseInt(e.getAttribute("width")||"0",10),height:parseInt(e.getAttribute("height")||"0",10),bitrate:parseInt(e.getAttribute("bitrate")||"0",10)||void 0})});const i=t.querySelector("VideoClicks");i&&(s=i.querySelector("ClickThrough")?.textContent?.trim(),i.querySelectorAll("ClickTracking").forEach(e=>{const t=e.textContent?.trim();t&&u.push(t)}));t.querySelectorAll("TrackingEvents Tracking").forEach(e=>{const t=e.getAttribute("event"),n=e.textContent?.trim();t&&n&&(p[t]||(p[t]=[]),p[t].push(n))})});const m=[];t.querySelectorAll("Impression").forEach(e=>{const t=e.textContent?.trim();t&&m.push(t)}),d.length>0&&n.push({id:r,title:i,description:l,duration:o,skipOffset:c,clickThrough:s,clickTracking:u,impressionUrls:m,mediaFiles:d,trackingEvents:p})}),{ads:n}},ae=e=>{if(e.includes("%"))return-1;const t=e.split(":");if(3!==t.length)return 0;return 3600*parseInt(t[0],10)+60*parseInt(t[1],10)+parseFloat(t[2])},ce=async e=>{try{const t=await fetch(e.url,{method:"GET",headers:{Accept:"application/xml"}});if(!t.ok)return null;const n=await t.text(),r=le(n);if(r.error||0===r.ads.length)return null;const i=r.ads[0];return void 0!==e.skipDelay&&void 0===i.skipOffset&&(i.skipOffset=e.skipDelay),i}catch(e){return null}},se=e=>{if(0===e.length)return null;const t=document.createElement("video"),n=e.filter(e=>""!==t.canPlayType(e.type));if(0===n.length)return null;n.sort((e,t)=>{const n=e.width*e.height,r=t.width*t.height;return n!==r?r-n:(t.bitrate||0)-(e.bitrate||0)});return/Android|iPhone|iPad|iPod/i.test(navigator.userAgent)&&n.length>1?n[n.length-1]:n[0]},oe=e=>{(new Image).src=e},ue=e=>{e.forEach(oe)},de=e=>({id:e.id,title:e.title,duration:e.duration,skipOffset:e.skipOffset,clickThrough:e.clickThrough}),pe=({vastConfig:e,videoRef:t,onAdStart:n,onAdEnd:c,onAdSkip:s,onAdError:o})=>{const[u,d]=i(!1),[p,m]=i(null),[h,v]=i(0),[g,y]=i(!1),w=r(null),f=r(""),b=r(0),k=r(new Set),x=r(null),E=Array.isArray(e)?e:e?[e]:[],_=l(async e=>{const r=t.current;if(r&&!u)try{const t=await ce(e);if(!t)return void o?.(new Error("Failed to fetch VAST ad"));const i=se(t.mediaFiles);if(!i)return void o?.(new Error("No compatible media file found"));f.current=r.currentSrc,b.current=r.currentTime,ue(t.impressionUrls),w.current=t,m(de(t)),d(!0),v(t.duration),y(void 0===t.skipOffset||0===t.skipOffset),r.src=i.url,r.currentTime=0,await r.play(),t.trackingEvents.start&&ue(t.trackingEvents.start),n?.(de(t)),x.current=window.setInterval(()=>{const e=Math.max(0,t.duration-r.currentTime);v(e),t.skipOffset&&r.currentTime>=t.skipOffset&&y(!0);const n=r.currentTime/t.duration*100;n>=25&&t.trackingEvents.firstQuartile&&ue(t.trackingEvents.firstQuartile),n>=50&&t.trackingEvents.midpoint&&ue(t.trackingEvents.midpoint),n>=75&&t.trackingEvents.thirdQuartile&&ue(t.trackingEvents.thirdQuartile)},250);const l=()=>{t.trackingEvents.complete&&ue(t.trackingEvents.complete),N()};r.addEventListener("ended",l,{once:!0})}catch(e){o?.(e instanceof Error?e:new Error("Ad playback failed")),N()}},[t,u,n,o]),N=l(()=>{const e=t.current;e&&(x.current&&(clearInterval(x.current),x.current=null),f.current&&(e.src=f.current,e.currentTime=b.current,e.play().catch(()=>{})),d(!1),m(null),v(0),y(!1),w.current=null,c?.())},[t,c]),z=l(()=>{if(!g||!w.current)return;const e=w.current;e.trackingEvents.skip&&ue(e.trackingEvents.skip),s?.(),N()},[g,N,s]),P=l(()=>{if(!w.current)return;const e=w.current;e.clickThrough&&window.open(e.clickThrough,"_blank"),e.clickTracking&&ue(e.clickTracking)},[]),C=l((e,t)=>{u||0===E.length||E.forEach(n=>{const r=n.position||"preroll",i=`${r}-${n.midrollTime||0}`;if(k.current.has(i))return;let l=!1;switch(r){case"preroll":l=0===e;break;case"midroll":n.midrollTime&&e>=n.midrollTime&&(l=!0);break;case"postroll":l=e>=t-.5}l&&(k.current.add(i),_(n))})},[E,u,_]);return a(()=>()=>{x.current&&clearInterval(x.current)},[]),{isAdPlaying:u,currentAd:p,adTimeRemaining:h,canSkip:g,skipAd:z,handleAdClick:P,checkForAd:C}},me=c((n,c)=>{const{src:d,poster:p,autoPlay:m=!1,muted:v=!1,loop:g=!1,controls:y=!0,width:w="100%",className:f="",style:b={},pip:k=!0,fullscreen:x=!0,playbackSpeed:E=!0,playbackSpeeds:_=[.25,.5,.75,1,1.25,1.5,1.75,2],volume:N=!0,initialVolume:z=1,progressBar:P=!0,timeDisplay:M=!0,qualitySelector:S=!0,textTracks:A=[],vast:F,keyboard:V=!0,hotkeys:H,accentColor:I="#e50914",controlsTimeout:D=3e3,doubleClickFullscreen:$=!0,clickToPlay:O=!0,preload:Q="metadata",onPlay:U,onPause:X,onEnded:j,onTimeUpdate:K,onProgress:G,onVolumeChange:J,onFullscreenChange:ee,onPipChange:re,onQualityChange:le,onError:ae,onAdStart:ce,onAdEnd:se,onAdSkip:oe,onAdError:ue,onReady:de}=n,me=r(null),he=r(null),ve=r(null),ge=r(0),[ye,we]=i(!1),[fe,be]=i(0),[ke,xe]=i(0),[Ee,_e]=i(0),[Ne,ze]=i(v?0:z),[Pe,Ce]=i(v),[Me,Te]=i(!1),[Le,Se]=i(!1),[Ae,Fe]=i(!0),[Ve,qe]=i(null),[Re,Be]=i(!0),[He,Ie]=i(1),[De,$e]=i("auto"),[Oe,Qe]=i(null),Ue=s(()=>"string"==typeof d?[{src:d,type:"video/mp4"}]:d,[d]),{currentAd:Xe,isAdPlaying:je,adTimeRemaining:Ke,canSkip:Ge,skipAd:Je,handleAdClick:We,checkForAd:Ye}=pe({vastConfig:F,videoRef:me,onAdStart:ce,onAdEnd:se,onAdSkip:oe,onAdError:ue}),Ze=l(async()=>{const e=me.current;if(e)try{await e.play()}catch(e){}},[]),et=l(()=>{const e=me.current;e&&e.pause()},[]),tt=l(()=>{const e=me.current;e&&(e.pause(),e.currentTime=0)},[]),nt=l(()=>{const e=me.current;e&&(e.paused?Ze():et())},[Ze,et]),rt=l(e=>{const t=me.current;t&&(t.currentTime=Math.max(0,Math.min(e,t.duration||0)))},[]),it=l(e=>{const t=me.current;if(!t)return;const n=Math.max(0,Math.min(1,e));t.volume=n,t.muted=0===n,ze(n),Ce(0===n)},[]),lt=l(()=>{const e=me.current;e&&(e.muted=!0,Ce(!0))},[]),at=l(()=>{const e=me.current;e&&(e.muted=!1,0===e.volume&&(e.volume=.5,ze(.5)),Ce(!1))},[]),ct=l(()=>{const e=me.current;e&&(e.muted?at():lt())},[lt,at]),st=l(async()=>{const e=he.current;if(e)try{await e.requestFullscreen(),Te(!0)}catch(e){}},[]),ot=l(async()=>{try{document.fullscreenElement&&(await document.exitFullscreen(),Te(!1))}catch(e){}},[]),ut=l(async()=>{document.fullscreenElement?await ot():await st()},[st,ot]),dt=l(async()=>{const e=me.current;if(e&&document.pictureInPictureEnabled)try{await e.requestPictureInPicture(),Se(!0)}catch(e){}},[]),pt=l(async()=>{try{document.pictureInPictureElement&&(await document.exitPictureInPicture(),Se(!1))}catch(e){}},[]),mt=l(async()=>{document.pictureInPictureElement?await pt():await dt()},[dt,pt]),ht=l(e=>{const t=me.current;t&&(t.playbackRate=e,Ie(e))},[]),vt=l(e=>{const t=Ue.find(t=>t.label===e||t.quality===e);if(t&&me.current){const n=me.current,r=!n.paused,i=n.currentTime;n.src=t.src,n.currentTime=i,r&&n.play(),$e(e),le?.(e)}},[Ue,le]),gt=l(e=>{const t=me.current;if(t){for(let n=0;n<t.textTracks.length;n++){const r=t.textTracks[n];r.mode=r.label===e?"showing":"hidden"}Qe(e)}},[]),yt=l(()=>{ye&&Be(!1)},[ye]),wt=l(()=>{Be(!0),ve.current&&clearTimeout(ve.current),ye&&(ve.current=setTimeout(yt,D))},[ye,D,yt]),ft=s(()=>h(wt,200),[wt]),bt=l(()=>{if(!O)return;const e=Date.now();$&&e-ge.current<300?ut():nt(),ge.current=e},[O,$,nt,ut]);a(()=>{const e=me.current;if(!e)return;const t=()=>{we(!0),U?.()},n=()=>{we(!1),X?.()},r=()=>{we(!1),j?.()},i=()=>{be(e.currentTime),K?.(e.currentTime),Ye(e.currentTime,e.duration)},l=()=>{xe(e.duration)},a=()=>{if(e.buffered.length>0){const t=e.buffered.end(e.buffered.length-1)/e.duration*100;_e(t),G?.(t)}},c=()=>{ze(e.volume),Ce(e.muted),J?.(e.volume,e.muted)},s=()=>{xe(e.duration),Fe(!1),de?.()},o=()=>{Fe(!0)},u=()=>{Fe(!1)},d=()=>{Fe(!1)},p=()=>{qe(e.error),Fe(!1),ae?.(e.error)};return e.addEventListener("play",t),e.addEventListener("pause",n),e.addEventListener("ended",r),e.addEventListener("timeupdate",i),e.addEventListener("durationchange",l),e.addEventListener("progress",a),e.addEventListener("volumechange",c),e.addEventListener("loadedmetadata",s),e.addEventListener("waiting",o),e.addEventListener("playing",u),e.addEventListener("canplay",d),e.addEventListener("error",p),()=>{e.removeEventListener("play",t),e.removeEventListener("pause",n),e.removeEventListener("ended",r),e.removeEventListener("timeupdate",i),e.removeEventListener("durationchange",l),e.removeEventListener("progress",a),e.removeEventListener("volumechange",c),e.removeEventListener("loadedmetadata",s),e.removeEventListener("waiting",o),e.removeEventListener("playing",u),e.removeEventListener("canplay",d),e.removeEventListener("error",p)}},[U,X,j,K,G,J,de,ae,Ye]),a(()=>{const e=()=>{const e=!!document.fullscreenElement;Te(e),ee?.(e)};return document.addEventListener("fullscreenchange",e),()=>{document.removeEventListener("fullscreenchange",e)}},[ee]),a(()=>{const e=me.current;if(!e)return;const t=()=>{Se(!0),re?.(!0)},n=()=>{Se(!1),re?.(!1)};return e.addEventListener("enterpictureinpicture",t),e.addEventListener("leavepictureinpicture",n),()=>{e.removeEventListener("enterpictureinpicture",t),e.removeEventListener("leavepictureinpicture",n)}},[re]),ie({enabled:V,containerRef:he,hotkeys:H,onPlay:nt,onMute:ct,onFullscreen:ut,onPip:mt,onSeek:e=>rt(fe+e),onVolume:e=>it(Ne+e)}),a(()=>()=>{ve.current&&clearTimeout(ve.current)},[]);const kt=l(()=>{qe(null),me.current?.load()},[]);o(c,()=>({play:Ze,pause:et,stop:tt,seek:rt,setVolume:it,mute:lt,unmute:at,toggleMute:ct,enterFullscreen:st,exitFullscreen:ot,toggleFullscreen:ut,enterPip:dt,exitPip:pt,togglePip:mt,setPlaybackRate:ht,setQuality:vt,getCurrentTime:()=>me.current?.currentTime||0,getDuration:()=>me.current?.duration||0,getVolume:()=>me.current?.volume||0,isMuted:()=>me.current?.muted??!0,isPlaying:()=>!me.current?.paused,isFullscreen:()=>Me,isPip:()=>Le,getVideoElement:()=>me.current}),[Ze,et,tt,rt,it,lt,at,ct,st,ot,ut,dt,pt,mt,ht,vt,Me,Le]);const xt=Ue[0]?.src||"";return e("div",{ref:he,className:`plex-video-player ${Me?"plex-video-player--fullscreen":""} ${f}`,style:{...{"--plex-accent-color":I},width:w,...b},onMouseMove:ft,onMouseLeave:()=>ye&&Be(!1),tabIndex:0,children:[e("video",{ref:me,className:"plex-video-player__video",src:xt,poster:p,autoPlay:m,muted:v,loop:g,preload:Q,playsInline:!0,onClick:bt,children:[Ue.slice(1).map((e,n)=>t("source",{src:e.src,type:e.type},n)),A.map((e,n)=>t("track",{kind:e.kind,src:e.src,srcLang:e.srclang,label:e.label,default:e.default},n))]}),t(ne,{visible:Ae&&!Ve}),Ve&&t(te,{error:Ve,onRetry:kt}),je&&Xe&&t(Z,{ad:Xe,timeRemaining:Ke,canSkip:Ge,onSkip:Je,onClick:We}),y&&!je&&e("div",{className:"plex-video-player__controls "+(Re?"plex-video-player__controls--visible":""),children:[P&&t(C,{currentTime:fe,duration:ke,buffered:Ee,onSeek:rt}),e("div",{className:"plex-video-player__controls-bottom",children:[e("div",{className:"plex-video-player__controls-left",children:[t("button",{className:"plex-video-player__btn",onClick:nt,"aria-label":ye?"Pause":"Play",type:"button",children:t(ye?L:T,{})}),N&&t(W,{volume:Ne,muted:Pe,onVolumeChange:it,onToggleMute:ct}),M&&e("div",{className:"plex-video-player__time",children:[t("span",{children:u(fe)}),t("span",{children:" / "}),t("span",{children:u(ke)})]})]}),e("div",{className:"plex-video-player__controls-right",children:[E&&t(Y,{playbackRate:He,playbackSpeeds:_,onPlaybackRateChange:ht,qualityEnabled:S&&Ue.length>1,sources:Ue,currentQuality:De,onQualityChange:vt,captionsEnabled:A.length>0,textTracks:A,currentTrack:Oe??void 0,onTrackChange:gt}),k&&document.pictureInPictureEnabled&&t("button",{className:"plex-video-player__btn",onClick:mt,"aria-label":Le?"Exit Picture in Picture":"Picture in Picture",type:"button",children:t(B,{})}),x&&t("button",{className:"plex-video-player__btn",onClick:ut,"aria-label":Me?"Exit Fullscreen":"Fullscreen",type:"button",children:t(Me?R:q,{})})]})]})]}),!ye&&!Ae&&!Ve&&!je&&t("button",{className:"plex-video-player__big-play",onClick:nt,"aria-label":"Play",type:"button",children:t(T,{})})]})});me.displayName="PlexVideoPlayer";const he={isPlaying:!1,isPaused:!0,isEnded:!1,isBuffering:!1,isSeeking:!1,isFullscreen:!1,isPip:!1,isMuted:!1,isAdPlaying:!1,volume:1,currentTime:0,duration:0,buffered:0,playbackRate:1,currentQuality:null,error:null},ve=(e={})=>{const{autoPlay:t=!1,muted:n=!1,loop:c=!1,volume:s=1,playbackRate:o=1}=e,u=r(null),d=r(null),[p,m]=i({...he,volume:s,isMuted:n,playbackRate:o}),h=l(e=>{m(t=>({...t,...e}))},[]),v=l(async()=>{const e=u.current;if(e)try{await e.play(),h({isPlaying:!0,isPaused:!1,isEnded:!1})}catch(e){}},[h]),g=l(()=>{const e=u.current;e&&(e.pause(),h({isPlaying:!1,isPaused:!0}))},[h]),k=l(()=>{p.isPlaying?g():v()},[p.isPlaying,v,g]),x=l(e=>{const t=u.current;if(!t)return;const n=Math.max(0,Math.min(e,t.duration||0));t.currentTime=n,h({currentTime:n})},[h]),E=l(e=>{const t=u.current;if(!t)return;const n=Math.max(0,Math.min(1,e));t.volume=n,t.muted=0===n,h({volume:n,isMuted:0===n})},[h]),_=l(()=>{const e=u.current;e&&(e.muted=!e.muted,h({isMuted:e.muted}))},[h]),N=l(e=>{const t=u.current;t&&(t.playbackRate=e,h({playbackRate:e}))},[h]),P=l(async()=>{const e=d.current;if(e)try{await f(e),h({isFullscreen:!0})}catch(e){}},[h]),C=l(async()=>{try{await b(),h({isFullscreen:!1})}catch(e){}},[h]),M=l(async()=>{p.isFullscreen?await C():await P()},[p.isFullscreen,P,C]),T=l(async()=>{const e=u.current;if(e&&y())try{await e.requestPictureInPicture(),h({isPip:!0})}catch(e){}},[h]),L=l(async()=>{if(document.pictureInPictureElement)try{await document.exitPictureInPicture(),h({isPip:!1})}catch(e){}},[h]),S=l(async()=>{p.isPip?await L():await T()},[p.isPip,T,L]);return a(()=>{const e=u.current;if(!e)return;e.muted=n,e.volume=s,e.playbackRate=o,e.loop=c;const r={loadedmetadata:()=>{h({duration:e.duration})},timeupdate:()=>{h({currentTime:e.currentTime,buffered:z(e)})},play:()=>{h({isPlaying:!0,isPaused:!1,isEnded:!1})},pause:()=>{h({isPlaying:!1,isPaused:!0})},ended:()=>{h({isPlaying:!1,isPaused:!0,isEnded:!0})},waiting:()=>{h({isBuffering:!0})},canplay:()=>{h({isBuffering:!1})},seeking:()=>{h({isSeeking:!0})},seeked:()=>{h({isSeeking:!1})},volumechange:()=>{h({volume:e.volume,isMuted:e.muted})},ratechange:()=>{h({playbackRate:e.playbackRate})},error:()=>{h({error:e.error})},enterpictureinpicture:()=>{h({isPip:!0})},leavepictureinpicture:()=>{h({isPip:!1})}};return Object.entries(r).forEach(([t,n])=>{e.addEventListener(t,n)}),t&&v(),()=>{Object.entries(r).forEach(([t,n])=>{e.removeEventListener(t,n)})}},[t,n,c,s,o,v,h]),a(()=>{const e=()=>{const e=!!w();h({isFullscreen:e})};return document.addEventListener("fullscreenchange",e),document.addEventListener("webkitfullscreenchange",e),document.addEventListener("mozfullscreenchange",e),document.addEventListener("MSFullscreenChange",e),()=>{document.removeEventListener("fullscreenchange",e),document.removeEventListener("webkitfullscreenchange",e),document.removeEventListener("mozfullscreenchange",e),document.removeEventListener("MSFullscreenChange",e)}},[h]),{state:p,videoRef:u,containerRef:d,play:v,pause:g,togglePlay:k,seek:x,setVolume:E,toggleMute:_,setPlaybackRate:N,enterFullscreen:P,exitFullscreen:C,toggleFullscreen:M,enterPip:T,exitPip:L,togglePip:S}};export{Z as AdOverlay,D as CaptionsIcon,J as CheckIcon,te as ErrorDisplay,K as ErrorIcon,G as ExternalLinkIcon,Q as ForwardIcon,R as FullscreenExitIcon,q as FullscreenIcon,ne as Loader,L as PauseIcon,H as PipExitIcon,B as PipIcon,T as PlayIcon,me as PlexVideoPlayer,C as ProgressBar,O as QualityIcon,U as RewindIcon,I as SettingsIcon,Y as SettingsMenu,X as SkipNextIcon,j as SkipPrevIcon,$ as SpeedIcon,W as VolumeControl,S as VolumeHighIcon,F as VolumeLowIcon,A as VolumeMediumIcon,V as VolumeMuteIcon,P as canPlayType,m as clamp,de as convertToAdInfo,v as debounce,me as default,k as detectVideoType,b as exitFullscreen,ce as fetchVastAd,oe as fireTrackingPixel,ue as fireTrackingPixels,u as formatTime,E as generateId,z as getBufferedEnd,w as getFullscreenElement,g as isFullscreenSupported,x as isHlsNativelySupported,_ as isMobile,y as isPipSupported,N as isTouchDevice,d as parseTime,le as parseVastXml,p as percentage,f as requestFullscreen,se as selectBestMediaFile,h as throttle,ie as useKeyboard,ve as usePlayer,pe as useVast};
2
+ //# sourceMappingURL=index.esm.js.map