@obipascal/player 1.0.2 → 1.0.4

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.
@@ -1,4 +1,4 @@
1
- import { WontumPlayerConfig, PlayerState, PlayerEvent, PlayerEventType } from './types';
1
+ import { WontumPlayerConfig, PlayerState, PlayerEvent, PlayerEventType, QualityLevel } from './types';
2
2
  import { Analytics } from './analytics';
3
3
 
4
4
  /**
@@ -13,6 +13,7 @@ export declare class WontumPlayer {
13
13
  analytics: Analytics;
14
14
  private s3Handler;
15
15
  private uiController;
16
+ private qualities;
16
17
  private state;
17
18
  constructor(config: WontumPlayerConfig);
18
19
  private addSubtitleTracks;
@@ -32,6 +33,7 @@ export declare class WontumPlayer {
32
33
  unmute(): void;
33
34
  setPlaybackRate(rate: number): void;
34
35
  setQuality(qualityIndex: number): void;
36
+ getQualities(): QualityLevel[];
35
37
  enterFullscreen(): void;
36
38
  exitFullscreen(): void;
37
39
  getState(): PlayerState;
@@ -1,7 +1,6 @@
1
- import { default as React } from 'react';
2
1
  import { WontumPlayer } from './player';
3
2
  import { WontumPlayerConfig, PlayerState } from './types';
4
-
3
+ import * as React from "react";
5
4
  export interface WontumPlayerReactProps extends Omit<WontumPlayerConfig, "container"> {
6
5
  /** Callback when player is ready */
7
6
  onReady?: (player: WontumPlayer) => void;
@@ -12,6 +11,8 @@ export interface WontumPlayerReactProps extends Omit<WontumPlayerConfig, "contai
12
11
  onTimeUpdate?: (currentTime: number) => void;
13
12
  onVolumeChange?: (volume: number, muted: boolean) => void;
14
13
  onError?: (error: any) => void;
14
+ onLoadedMetadata?: () => void;
15
+ onQualityChange?: (level: number) => void;
15
16
  /** Container style */
16
17
  style?: React.CSSProperties;
17
18
  /** Container className */
@@ -14,9 +14,6 @@ export declare class UIController {
14
14
  private skipForwardButton;
15
15
  private volumeButton;
16
16
  private fullscreenButton;
17
- private qualityButton;
18
- private subtitleButton;
19
- private speedButton;
20
17
  private settingsButton;
21
18
  private volumeSlider;
22
19
  private progressInput;
@@ -41,11 +38,8 @@ export declare class UIController {
41
38
  private getVolumeIcon;
42
39
  private getMutedIcon;
43
40
  private getFullscreenIcon;
44
- private getQualityIcon;
45
41
  private getSkipBackwardIcon;
46
42
  private getSkipForwardIcon;
47
- private getSubtitleIcon;
48
- private getSpeedIcon;
49
43
  private getSettingsIcon;
50
44
  destroy(): void;
51
45
  }
@@ -1,15 +1,15 @@
1
- "use strict";var at=Object.defineProperty;var lt=(c,t,e)=>t in c?at(c,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):c[t]=e;var o=(c,t,e)=>lt(c,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const k=require("hls.js"),v=require("react");class tt{constructor(t){o(this,"config");o(this,"sessionId");o(this,"events",[]);o(this,"sessionStartTime");o(this,"playbackStartTime",null);o(this,"totalPlayTime",0);o(this,"totalBufferTime",0);o(this,"bufferStartTime",null);o(this,"rebufferCount",0);o(this,"seekCount",0);var e;this.config=t,this.sessionId=(t==null?void 0:t.sessionId)||this.generateSessionId(),this.sessionStartTime=Date.now(),(e=this.config)!=null&&e.enabled&&this.trackEvent("session_start",this.getSessionData())}trackEvent(t,e={}){var r;if(!((r=this.config)!=null&&r.enabled))return;const s={eventType:t,timestamp:Date.now(),sessionId:this.sessionId,videoId:this.config.videoId,userId:this.config.userId,data:{...e,...this.getQoEMetrics()}};this.events.push(s),this.updateMetrics(t,e),this.config.endpoint&&this.sendEvent(s),process.env.NODE_ENV==="development"&&console.log("[Analytics]",t,s.data)}updateMetrics(t,e){switch(t){case"play":this.playbackStartTime=Date.now();break;case"pause":case"ended":this.playbackStartTime&&(this.totalPlayTime+=Date.now()-this.playbackStartTime,this.playbackStartTime=null);break;case"buffering_start":this.bufferStartTime=Date.now(),this.rebufferCount++;break;case"buffering_end":this.bufferStartTime&&(this.totalBufferTime+=Date.now()-this.bufferStartTime,this.bufferStartTime=null);break;case"seeked":this.seekCount++;break}}getQoEMetrics(){const t=Date.now()-this.sessionStartTime,e=this.totalPlayTime>0?this.totalBufferTime/this.totalPlayTime:0;return{sessionDuration:t,totalPlayTime:this.totalPlayTime,totalBufferTime:this.totalBufferTime,bufferingRatio:Math.round(e*1e3)/1e3,rebufferCount:this.rebufferCount,seekCount:this.seekCount}}getSessionData(){return{userAgent:navigator.userAgent,platform:navigator.platform,language:navigator.language,screenResolution:`${screen.width}x${screen.height}`,viewport:`${window.innerWidth}x${window.innerHeight}`,connection:this.getConnectionInfo()}}getConnectionInfo(){const t=navigator,e=t.connection||t.mozConnection||t.webkitConnection;return e?{effectiveType:e.effectiveType,downlink:e.downlink,rtt:e.rtt,saveData:e.saveData}:null}async sendEvent(t){var e;if((e=this.config)!=null&&e.endpoint)try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(s){console.error("Failed to send analytics event:",s)}}generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}getEvents(){return[...this.events]}getMetrics(){return{sessionId:this.sessionId,...this.getQoEMetrics(),eventCount:this.events.length}}destroy(){var t;(t=this.config)!=null&&t.enabled&&this.trackEvent("session_end",this.getSessionData()),this.events=[]}}class et{constructor(t,e){o(this,"container");o(this,"player");o(this,"controlsContainer");o(this,"progressContainer");o(this,"progressBar");o(this,"playButton");o(this,"skipBackwardButton");o(this,"skipForwardButton");o(this,"volumeButton");o(this,"fullscreenButton");o(this,"qualityButton");o(this,"subtitleButton");o(this,"speedButton");o(this,"settingsButton");o(this,"volumeSlider");o(this,"progressInput");o(this,"hideControlsTimeout",null);o(this,"stickyControls",!1);this.container=t,this.player=e,this.injectStyles(),this.createProgressBar(),this.controlsContainer=this.createControls(),this.container.appendChild(this.controlsContainer),this.playButton=this.controlsContainer.querySelector(".wontum-play-btn"),this.skipBackwardButton=this.controlsContainer.querySelector(".wontum-skip-backward-btn"),this.skipForwardButton=this.controlsContainer.querySelector(".wontum-skip-forward-btn"),this.volumeButton=this.controlsContainer.querySelector(".wontum-volume-btn"),this.fullscreenButton=this.controlsContainer.querySelector(".wontum-fullscreen-btn"),this.qualityButton=this.controlsContainer.querySelector(".wontum-quality-btn"),this.subtitleButton=this.controlsContainer.querySelector(".wontum-subtitle-btn"),this.speedButton=this.controlsContainer.querySelector(".wontum-speed-btn"),this.settingsButton=this.controlsContainer.querySelector(".wontum-settings-btn"),this.volumeSlider=this.controlsContainer.querySelector(".wontum-volume-slider"),this.progressInput=this.container.querySelector(".wontum-progress-input"),this.progressBar=this.container.querySelector(".wontum-progress-filled"),this.stickyControls=this.player.config.stickyControls||!1,this.stickyControls&&this.controlsContainer.classList.add("sticky"),this.setupEventListeners(),this.setupPlayerEventListeners()}injectStyles(){const t="wontum-player-styles";if(document.getElementById(t))return;const e=this.player.config.theme||{},s=e.primaryColor||"#3b82f6",r=e.accentColor||"#2563eb",i=e.fontFamily||"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",l=e.controlsBackground||"linear-gradient(to top, rgba(0,0,0,0.8), transparent)",u=e.buttonHoverBg||"rgba(255, 255, 255, 0.1)",g=e.progressHeight||"6px",b=e.borderRadius||"4px",f=document.createElement("style");f.id=t,f.textContent=`
1
+ "use strict";var V=Object.defineProperty;var W=(a,t,e)=>t in a?V(a,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):a[t]=e;var o=(a,t,e)=>W(a,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("hls.js"),I=require("react/jsx-runtime"),d=require("react");function N(a){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(a){for(const e in a)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(a,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>a[e]})}}return t.default=a,Object.freeze(t)}const P=N(d);class R{constructor(t){o(this,"config");o(this,"sessionId");o(this,"events",[]);o(this,"sessionStartTime");o(this,"playbackStartTime",null);o(this,"totalPlayTime",0);o(this,"totalBufferTime",0);o(this,"bufferStartTime",null);o(this,"rebufferCount",0);o(this,"seekCount",0);var e;this.config=t,this.sessionId=(t==null?void 0:t.sessionId)||this.generateSessionId(),this.sessionStartTime=Date.now(),(e=this.config)!=null&&e.enabled&&this.trackEvent("session_start",this.getSessionData())}trackEvent(t,e={}){var i;if(!((i=this.config)!=null&&i.enabled))return;const n={eventType:t,timestamp:Date.now(),sessionId:this.sessionId,videoId:this.config.videoId,userId:this.config.userId,data:{...e,...this.getQoEMetrics()}};this.events.push(n),this.updateMetrics(t,e),this.config.endpoint&&this.sendEvent(n),process.env.NODE_ENV==="development"&&console.log("[Analytics]",t,n.data)}updateMetrics(t,e){switch(t){case"play":this.playbackStartTime=Date.now();break;case"pause":case"ended":this.playbackStartTime&&(this.totalPlayTime+=Date.now()-this.playbackStartTime,this.playbackStartTime=null);break;case"buffering_start":this.bufferStartTime=Date.now(),this.rebufferCount++;break;case"buffering_end":this.bufferStartTime&&(this.totalBufferTime+=Date.now()-this.bufferStartTime,this.bufferStartTime=null);break;case"seeked":this.seekCount++;break}}getQoEMetrics(){const t=Date.now()-this.sessionStartTime,e=this.totalPlayTime>0?this.totalBufferTime/this.totalPlayTime:0;return{sessionDuration:t,totalPlayTime:this.totalPlayTime,totalBufferTime:this.totalBufferTime,bufferingRatio:Math.round(e*1e3)/1e3,rebufferCount:this.rebufferCount,seekCount:this.seekCount}}getSessionData(){return{userAgent:navigator.userAgent,platform:navigator.platform,language:navigator.language,screenResolution:`${screen.width}x${screen.height}`,viewport:`${window.innerWidth}x${window.innerHeight}`,connection:this.getConnectionInfo()}}getConnectionInfo(){const t=navigator,e=t.connection||t.mozConnection||t.webkitConnection;return e?{effectiveType:e.effectiveType,downlink:e.downlink,rtt:e.rtt,saveData:e.saveData}:null}async sendEvent(t){var e;if((e=this.config)!=null&&e.endpoint)try{await fetch(this.config.endpoint,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)})}catch(n){console.error("Failed to send analytics event:",n)}}generateSessionId(){return`session_${Date.now()}_${Math.random().toString(36).substr(2,9)}`}getEvents(){return[...this.events]}getMetrics(){return{sessionId:this.sessionId,...this.getQoEMetrics(),eventCount:this.events.length}}destroy(){var t;(t=this.config)!=null&&t.enabled&&this.trackEvent("session_end",this.getSessionData()),this.events=[]}}class ${constructor(t,e){o(this,"container");o(this,"player");o(this,"controlsContainer");o(this,"progressContainer");o(this,"progressBar");o(this,"playButton");o(this,"skipBackwardButton");o(this,"skipForwardButton");o(this,"volumeButton");o(this,"fullscreenButton");o(this,"settingsButton");o(this,"volumeSlider");o(this,"progressInput");o(this,"hideControlsTimeout",null);o(this,"stickyControls",!1);this.container=t,this.player=e,this.injectStyles(),this.createProgressBar(),this.controlsContainer=this.createControls(),this.container.appendChild(this.controlsContainer),this.playButton=this.controlsContainer.querySelector(".wontum-play-btn"),this.skipBackwardButton=this.controlsContainer.querySelector(".wontum-skip-backward-btn"),this.skipForwardButton=this.controlsContainer.querySelector(".wontum-skip-forward-btn"),this.volumeButton=this.controlsContainer.querySelector(".wontum-volume-btn"),this.fullscreenButton=this.controlsContainer.querySelector(".wontum-fullscreen-btn"),this.settingsButton=this.controlsContainer.querySelector(".wontum-settings-btn"),this.volumeSlider=this.controlsContainer.querySelector(".wontum-volume-slider"),this.progressInput=this.container.querySelector(".wontum-progress-input"),this.progressBar=this.container.querySelector(".wontum-progress-filled"),this.stickyControls=this.player.config.stickyControls||!1,this.stickyControls&&this.controlsContainer.classList.add("sticky"),this.setupEventListeners(),this.setupPlayerEventListeners()}injectStyles(){const t="wontum-player-styles";if(document.getElementById(t))return;const e=this.player.config.theme||{},n=e.primaryColor||"#3b82f6",i=e.accentColor||"#2563eb",s=e.fontFamily||"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",r=e.controlsBackground||"linear-gradient(to top, rgba(0,0,0,0.8), transparent)",l=e.buttonHoverBg||"rgba(255, 255, 255, 0.1)",c=e.progressHeight||"6px",h=e.borderRadius||"4px",g=document.createElement("style");g.id=t,g.textContent=`
2
2
  .wontum-player-container {
3
3
  position: relative;
4
4
  background: #000;
5
- font-family: ${i};
5
+ font-family: ${s};
6
6
  overflow: hidden;
7
- --primary-color: ${s};
8
- --accent-color: ${r};
9
- --controls-bg: ${l};
10
- --button-hover: ${u};
11
- --progress-height: ${g};
12
- --border-radius: ${b};
7
+ --primary-color: ${n};
8
+ --accent-color: ${i};
9
+ --controls-bg: ${r};
10
+ --button-hover: ${l};
11
+ --progress-height: ${c};
12
+ --border-radius: ${h};
13
13
  }
14
14
 
15
15
  .wontum-player-video {
@@ -278,21 +278,7 @@
278
278
  }
279
279
 
280
280
  .wontum-quality-menu {
281
- position: absolute;
282
- bottom: 100%;
283
- right: 0;
284
- background: rgba(20, 20, 20, 0.95);
285
- backdrop-filter: blur(10px);
286
- border-radius: 6px;
287
281
  padding: 6px 0;
288
- margin-bottom: 8px;
289
- display: none;
290
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
291
- min-width: 120px;
292
- }
293
-
294
- .wontum-quality-menu.active {
295
- display: block;
296
282
  }
297
283
 
298
284
  .wontum-quality-option {
@@ -315,21 +301,7 @@
315
301
  }
316
302
 
317
303
  .wontum-speed-menu {
318
- position: absolute;
319
- bottom: 100%;
320
- right: 0;
321
- background: rgba(20, 20, 20, 0.95);
322
- backdrop-filter: blur(10px);
323
- border-radius: 6px;
324
304
  padding: 6px 0;
325
- margin-bottom: 8px;
326
- display: none;
327
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
328
- min-width: 120px;
329
- }
330
-
331
- .wontum-speed-menu.active {
332
- display: block;
333
305
  }
334
306
 
335
307
  .wontum-speed-option {
@@ -351,24 +323,73 @@
351
323
  background: rgba(255, 255, 255, 0.05);
352
324
  }
353
325
 
354
- .wontum-settings-menu {
326
+ .wontum-settings-panel {
355
327
  position: absolute;
356
328
  bottom: 100%;
357
329
  right: 0;
358
330
  background: rgba(20, 20, 20, 0.95);
359
331
  backdrop-filter: blur(10px);
360
- border-radius: 6px;
361
- padding: 6px 0;
332
+ border-radius: 8px;
362
333
  margin-bottom: 8px;
363
- min-width: 200px;
334
+ min-width: 320px;
364
335
  display: none;
365
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
336
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
337
+ overflow: hidden;
338
+ }
339
+
340
+ .wontum-settings-panel.active {
341
+ display: flex;
342
+ flex-direction: column;
343
+ }
344
+
345
+ .wontum-settings-tabs {
346
+ display: flex;
347
+ background: rgba(0, 0, 0, 0.3);
348
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
349
+ }
350
+
351
+ .wontum-tab {
352
+ flex: 1;
353
+ padding: 10px 12px;
354
+ background: none;
355
+ border: none;
356
+ color: rgba(255, 255, 255, 0.7);
357
+ font-size: 12px;
358
+ cursor: pointer;
359
+ transition: all 0.2s ease;
360
+ border-bottom: 2px solid transparent;
361
+ font-family: inherit;
362
+ }
363
+
364
+ .wontum-tab:hover {
365
+ background: rgba(255, 255, 255, 0.05);
366
+ color: rgba(255, 255, 255, 0.9);
367
+ }
368
+
369
+ .wontum-tab.active {
370
+ color: var(--primary-color);
371
+ border-bottom-color: var(--primary-color);
372
+ background: rgba(59, 130, 246, 0.1);
373
+ }
374
+
375
+ .wontum-settings-content {
376
+ min-height: 120px;
377
+ max-height: 300px;
378
+ overflow-y: auto;
366
379
  }
367
380
 
368
- .wontum-settings-menu.active {
381
+ .wontum-tab-panel {
382
+ display: none;
383
+ }
384
+
385
+ .wontum-tab-panel.active {
369
386
  display: block;
370
387
  }
371
388
 
389
+ .wontum-settings-menu {
390
+ padding: 6px 0;
391
+ }
392
+
372
393
  .wontum-settings-option {
373
394
  padding: 12px 16px;
374
395
  cursor: pointer;
@@ -416,21 +437,7 @@
416
437
  }
417
438
 
418
439
  .wontum-subtitle-menu {
419
- position: absolute;
420
- bottom: 100%;
421
- right: 0;
422
- background: rgba(20, 20, 20, 0.95);
423
- backdrop-filter: blur(10px);
424
- border-radius: 6px;
425
440
  padding: 6px 0;
426
- margin-bottom: 8px;
427
- display: none;
428
- min-width: 150px;
429
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
430
- }
431
-
432
- .wontum-subtitle-menu.active {
433
- display: block;
434
441
  }
435
442
 
436
443
  .wontum-subtitle-option {
@@ -463,7 +470,7 @@
463
470
  transform: translateY(0) !important;
464
471
  pointer-events: all !important;
465
472
  }
466
- `,document.head.appendChild(f),this.container.classList.add("wontum-player-container")}createProgressBar(){const t=document.createElement("div");t.className="wontum-progress-container",t.innerHTML=`
473
+ `,document.head.appendChild(g),this.container.classList.add("wontum-player-container")}createProgressBar(){const t=document.createElement("div");t.className="wontum-progress-container",t.innerHTML=`
467
474
  <div class="wontum-progress-track"></div>
468
475
  <div class="wontum-progress-filled"></div>
469
476
  <input type="range" class="wontum-progress-input" min="0" max="100" value="0" step="0.1">
@@ -499,32 +506,32 @@
499
506
 
500
507
  <div class="wontum-spacer"></div>
501
508
 
502
- <div class="wontum-subtitle-container" style="position: relative;">
503
- <button class="wontum-btn wontum-subtitle-btn" aria-label="Subtitles">
504
- ${this.getSubtitleIcon()}
505
- </button>
506
- <div class="wontum-subtitle-menu"></div>
507
- </div>
508
-
509
- <div class="wontum-speed-container" style="position: relative;">
510
- <button class="wontum-btn wontum-speed-btn" aria-label="Playback Speed">
511
- ${this.getSpeedIcon()}
512
- </button>
513
- <div class="wontum-speed-menu"></div>
514
- </div>
515
-
516
- <div class="wontum-quality-container" style="position: relative;">
517
- <button class="wontum-btn wontum-quality-btn" aria-label="Quality">
518
- ${this.getQualityIcon()}
519
- </button>
520
- <div class="wontum-quality-menu"></div>
521
- </div>
522
-
523
509
  <div class="wontum-settings-container" style="position: relative;">
524
510
  <button class="wontum-btn wontum-settings-btn" aria-label="Settings">
525
511
  ${this.getSettingsIcon()}
526
512
  </button>
527
- <div class="wontum-settings-menu"></div>
513
+ <div class="wontum-settings-panel">
514
+ <div class="wontum-settings-tabs">
515
+ <button class="wontum-tab active" data-tab="general">General</button>
516
+ <button class="wontum-tab" data-tab="quality">Quality</button>
517
+ <button class="wontum-tab" data-tab="speed">Speed</button>
518
+ <button class="wontum-tab" data-tab="subtitles">Subtitles</button>
519
+ </div>
520
+ <div class="wontum-settings-content">
521
+ <div class="wontum-tab-panel active" data-panel="general">
522
+ <div class="wontum-settings-menu"></div>
523
+ </div>
524
+ <div class="wontum-tab-panel" data-panel="quality">
525
+ <div class="wontum-quality-menu"></div>
526
+ </div>
527
+ <div class="wontum-tab-panel" data-panel="speed">
528
+ <div class="wontum-speed-menu"></div>
529
+ </div>
530
+ <div class="wontum-tab-panel" data-panel="subtitles">
531
+ <div class="wontum-subtitle-menu"></div>
532
+ </div>
533
+ </div>
534
+ </div>
528
535
  </div>
529
536
 
530
537
  <button class="wontum-btn wontum-fullscreen-btn" aria-label="Fullscreen">
@@ -535,28 +542,28 @@
535
542
  <div class="wontum-loading" style="display: none;">
536
543
  <div class="wontum-spinner"></div>
537
544
  </div>
538
- `,t}setupEventListeners(){this.playButton.addEventListener("click",()=>{this.player.getState().playing?this.player.pause():this.player.play()}),this.skipBackwardButton.addEventListener("click",()=>{this.player.skipBackward(10)}),this.skipForwardButton.addEventListener("click",()=>{this.player.skipForward(10)}),this.progressInput.addEventListener("input",e=>{const s=e.target,r=parseFloat(s.value),i=this.player.getState(),l=r/100*i.duration;this.player.seek(l)}),this.volumeSlider.addEventListener("input",e=>{const s=e.target,r=parseFloat(s.value)/100;this.player.setVolume(r)}),this.volumeButton.addEventListener("click",()=>{this.player.getState().muted?this.player.unmute():this.player.mute()}),this.fullscreenButton.addEventListener("click",()=>{this.player.getState().fullscreen?this.player.exitFullscreen():this.player.enterFullscreen()}),this.qualityButton.addEventListener("click",()=>{var s,r,i;this.controlsContainer.querySelector(".wontum-quality-menu").classList.toggle("active"),(s=this.controlsContainer.querySelector(".wontum-settings-menu"))==null||s.classList.remove("active"),(r=this.controlsContainer.querySelector(".wontum-subtitle-menu"))==null||r.classList.remove("active"),(i=this.controlsContainer.querySelector(".wontum-speed-menu"))==null||i.classList.remove("active")}),this.subtitleButton.addEventListener("click",()=>{var s,r,i;this.controlsContainer.querySelector(".wontum-subtitle-menu").classList.toggle("active"),(s=this.controlsContainer.querySelector(".wontum-settings-menu"))==null||s.classList.remove("active"),(r=this.controlsContainer.querySelector(".wontum-quality-menu"))==null||r.classList.remove("active"),(i=this.controlsContainer.querySelector(".wontum-speed-menu"))==null||i.classList.remove("active"),this.updateSubtitleMenu()}),this.speedButton.addEventListener("click",()=>{var s,r,i;this.controlsContainer.querySelector(".wontum-speed-menu").classList.toggle("active"),(s=this.controlsContainer.querySelector(".wontum-settings-menu"))==null||s.classList.remove("active"),(r=this.controlsContainer.querySelector(".wontum-quality-menu"))==null||r.classList.remove("active"),(i=this.controlsContainer.querySelector(".wontum-subtitle-menu"))==null||i.classList.remove("active"),this.updateSpeedMenu()}),this.settingsButton.addEventListener("click",()=>{var s,r,i;this.controlsContainer.querySelector(".wontum-settings-menu").classList.toggle("active"),(s=this.controlsContainer.querySelector(".wontum-quality-menu"))==null||s.classList.remove("active"),(r=this.controlsContainer.querySelector(".wontum-subtitle-menu"))==null||r.classList.remove("active"),(i=this.controlsContainer.querySelector(".wontum-speed-menu"))==null||i.classList.remove("active"),this.updateSettingsMenu()}),this.player.getVideoElement().addEventListener("click",()=>{this.player.getState().playing?this.player.pause():this.player.play()}),this.container.addEventListener("mousemove",()=>{this.showControls(),this.resetHideControlsTimeout()}),this.container.addEventListener("mouseleave",()=>{this.hideControls()})}setupPlayerEventListeners(){this.player.on("play",()=>{this.playButton.innerHTML=this.getPauseIcon()}),this.player.on("pause",()=>{this.playButton.innerHTML=this.getPlayIcon()}),this.player.on("timeupdate",t=>{const{currentTime:e}=t.data,s=this.player.getState();if(s.duration>0){const i=e/s.duration*100;this.progressBar.style.width=`${i}%`,this.progressInput.value=i.toString()}const r=this.controlsContainer.querySelector(".wontum-current-time");r.textContent=this.formatTime(e)}),this.player.on("loadedmetadata",t=>{const{duration:e}=t.data,s=this.controlsContainer.querySelector(".wontum-duration");s.textContent=this.formatTime(e),t.data.qualities&&this.updateQualityMenu(t.data.qualities)}),this.player.on("volumechange",t=>{const{volume:e,muted:s}=t.data;this.volumeSlider.value=(e*100).toString(),this.volumeButton.innerHTML=s?this.getMutedIcon():this.getVolumeIcon()}),this.player.on("waiting",()=>{const t=this.controlsContainer.querySelector(".wontum-loading");t.style.display="block"}),this.player.on("canplay",()=>{const t=this.controlsContainer.querySelector(".wontum-loading");t.style.display="none"})}updateSubtitleMenu(){const t=this.controlsContainer.querySelector(".wontum-subtitle-menu"),e=this.player.getSubtitleTracks();if(e.length===0){t.innerHTML='<div class="wontum-subtitle-option">No subtitles available</div>';return}const s=e.findIndex(r=>r.mode==="showing");t.innerHTML=`
539
- <div class="wontum-subtitle-option ${s===-1?"active":""}" data-track="-1">Off</div>
540
- ${e.map((r,i)=>`
541
- <div class="wontum-subtitle-option ${i===s?"active":""}" data-track="${i}">
542
- ${r.label||r.language||`Track ${i+1}`}
545
+ `,t}setupEventListeners(){this.playButton.addEventListener("click",()=>{this.player.getState().playing?this.player.pause():this.player.play()}),this.skipBackwardButton.addEventListener("click",()=>{this.player.skipBackward(10)}),this.skipForwardButton.addEventListener("click",()=>{this.player.skipForward(10)}),this.progressInput.addEventListener("input",n=>{const i=n.target,s=parseFloat(i.value),r=this.player.getState(),l=s/100*r.duration;this.player.seek(l)}),this.volumeSlider.addEventListener("input",n=>{const i=n.target,s=parseFloat(i.value)/100;this.player.setVolume(s)}),this.volumeButton.addEventListener("click",()=>{this.player.getState().muted?this.player.unmute():this.player.mute()}),this.fullscreenButton.addEventListener("click",()=>{this.player.getState().fullscreen?this.player.exitFullscreen():this.player.enterFullscreen()}),this.settingsButton.addEventListener("click",()=>{const n=this.controlsContainer.querySelector(".wontum-settings-panel");n.classList.toggle("active"),n.classList.contains("active")&&(this.updateSettingsMenu(),this.updateQualityMenu(),this.updateSpeedMenu(),this.updateSubtitleMenu())});const t=this.controlsContainer.querySelectorAll(".wontum-tab");t.forEach(n=>{n.addEventListener("click",i=>{const s=i.currentTarget,r=s.getAttribute("data-tab");t.forEach(h=>h.classList.remove("active")),s.classList.add("active"),this.controlsContainer.querySelectorAll(".wontum-tab-panel").forEach(h=>h.classList.remove("active"));const c=this.controlsContainer.querySelector(`[data-panel="${r}"]`);c==null||c.classList.add("active")})}),this.player.getVideoElement().addEventListener("click",()=>{this.player.getState().playing?this.player.pause():this.player.play()}),this.container.addEventListener("mousemove",()=>{this.showControls(),this.resetHideControlsTimeout()}),this.container.addEventListener("mouseleave",()=>{this.hideControls()})}setupPlayerEventListeners(){this.player.on("play",()=>{this.playButton.innerHTML=this.getPauseIcon()}),this.player.on("pause",()=>{this.playButton.innerHTML=this.getPlayIcon()}),this.player.on("timeupdate",t=>{const{currentTime:e}=t.data,n=this.player.getState();if(n.duration>0){const s=e/n.duration*100;this.progressBar.style.width=`${s}%`,this.progressInput.value=s.toString()}const i=this.controlsContainer.querySelector(".wontum-current-time");i.textContent=this.formatTime(e)}),this.player.on("loadedmetadata",t=>{const{duration:e}=t.data,n=this.controlsContainer.querySelector(".wontum-duration");n.textContent=this.formatTime(e),t.data.qualities&&this.updateQualityMenu(t.data.qualities)}),this.player.on("volumechange",t=>{const{volume:e,muted:n}=t.data;this.volumeSlider.value=(e*100).toString(),this.volumeButton.innerHTML=n?this.getMutedIcon():this.getVolumeIcon()}),this.player.on("waiting",()=>{const t=this.controlsContainer.querySelector(".wontum-loading");t.style.display="block"}),this.player.on("canplay",()=>{const t=this.controlsContainer.querySelector(".wontum-loading");t.style.display="none"})}updateSubtitleMenu(){const t=this.controlsContainer.querySelector(".wontum-subtitle-menu"),e=this.player.getSubtitleTracks();if(e.length===0){t.innerHTML='<div class="wontum-subtitle-option">No subtitles available</div>';return}const n=e.findIndex(i=>i.mode==="showing");t.innerHTML=`
546
+ <div class="wontum-subtitle-option ${n===-1?"active":""}" data-track="-1">Off</div>
547
+ ${e.map((i,s)=>`
548
+ <div class="wontum-subtitle-option ${s===n?"active":""}" data-track="${s}">
549
+ ${i.label||i.language||`Track ${s+1}`}
543
550
  </div>
544
551
  `).join("")}
545
- `,t.querySelectorAll(".wontum-subtitle-option").forEach(r=>{r.addEventListener("click",i=>{const l=i.target,u=parseInt(l.dataset.track||"-1");u===-1?this.player.disableSubtitles():this.player.enableSubtitles(u),t.querySelectorAll(".wontum-subtitle-option").forEach(g=>g.classList.remove("active")),l.classList.add("active"),t.classList.remove("active")})})}updateSpeedMenu(){const t=this.controlsContainer.querySelector(".wontum-speed-menu"),s=this.player.getState().playbackRate||1,r=[.25,.5,.75,1,1.25,1.5,1.75,2];t.innerHTML=r.map(i=>`
546
- <div class="wontum-speed-option ${s===i?"active":""}" data-speed="${i}">
547
- ${i===1?"Normal":i+"x"}
552
+ `,t.querySelectorAll(".wontum-subtitle-option").forEach(i=>{i.addEventListener("click",s=>{const r=s.target,l=parseInt(r.dataset.track||"-1");l===-1?this.player.disableSubtitles():this.player.enableSubtitles(l),t.querySelectorAll(".wontum-subtitle-option").forEach(c=>c.classList.remove("active")),r.classList.add("active")})})}updateSpeedMenu(){const t=this.controlsContainer.querySelector(".wontum-speed-menu"),n=this.player.getState().playbackRate||1,i=[.25,.5,.75,1,1.25,1.5,1.75,2];t.innerHTML=i.map(s=>`
553
+ <div class="wontum-speed-option ${n===s?"active":""}" data-speed="${s}">
554
+ ${s===1?"Normal":s+"x"}
548
555
  </div>
549
- `).join(""),t.querySelectorAll(".wontum-speed-option").forEach(i=>{i.addEventListener("click",l=>{const u=l.target,g=parseFloat(u.dataset.speed||"1");this.player.setPlaybackRate(g),t.querySelectorAll(".wontum-speed-option").forEach(b=>b.classList.remove("active")),u.classList.add("active"),t.classList.remove("active")})})}updateSettingsMenu(){const t=this.controlsContainer.querySelector(".wontum-settings-menu");t.innerHTML=`
556
+ `).join(""),t.querySelectorAll(".wontum-speed-option").forEach(s=>{s.addEventListener("click",r=>{const l=r.target,c=parseFloat(l.dataset.speed||"1");this.player.setPlaybackRate(c),t.querySelectorAll(".wontum-speed-option").forEach(h=>h.classList.remove("active")),l.classList.add("active")})})}updateSettingsMenu(){const t=this.controlsContainer.querySelector(".wontum-settings-menu");t.innerHTML=`
550
557
  <div class="wontum-settings-option" data-setting="sticky-controls">
551
558
  <span>Sticky Controls</span>
552
559
  <div class="wontum-toggle-switch ${this.stickyControls?"active":""}"></div>
553
560
  </div>
554
- `;const e=t.querySelector('[data-setting="sticky-controls"]');e.addEventListener("click",()=>{this.stickyControls=!this.stickyControls,e.querySelector(".wontum-toggle-switch").classList.toggle("active"),this.stickyControls?(this.controlsContainer.classList.add("sticky"),this.progressContainer.classList.add("sticky")):(this.controlsContainer.classList.remove("sticky"),this.progressContainer.classList.remove("sticky"))})}updateQualityMenu(t){const e=this.controlsContainer.querySelector(".wontum-quality-menu");e.innerHTML=`
561
+ `;const e=t.querySelector('[data-setting="sticky-controls"]');e.addEventListener("click",()=>{this.stickyControls=!this.stickyControls,e.querySelector(".wontum-toggle-switch").classList.toggle("active"),this.stickyControls?(this.controlsContainer.classList.add("sticky"),this.progressContainer.classList.add("sticky")):(this.controlsContainer.classList.remove("sticky"),this.progressContainer.classList.remove("sticky"))})}updateQualityMenu(t){const e=this.controlsContainer.querySelector(".wontum-quality-menu"),n=t||this.player.getQualities();if(!n||n.length===0){e.innerHTML='<div class="wontum-quality-option">No qualities available</div>';return}e.innerHTML=`
555
562
  <div class="wontum-quality-option active" data-quality="-1">Auto</div>
556
- ${t.map((s,r)=>`
557
- <div class="wontum-quality-option" data-quality="${r}">${s.name}</div>
563
+ ${n.map((i,s)=>`
564
+ <div class="wontum-quality-option" data-quality="${s}">${i.name}</div>
558
565
  `).join("")}
559
- `,e.querySelectorAll(".wontum-quality-option").forEach(s=>{s.addEventListener("click",r=>{const i=r.target,l=parseInt(i.dataset.quality||"-1");this.player.setQuality(l),e.querySelectorAll(".wontum-quality-option").forEach(u=>u.classList.remove("active")),i.classList.add("active"),e.classList.remove("active")})})}showControls(){this.controlsContainer.classList.remove("hidden"),this.progressContainer.classList.remove("hidden")}hideControls(){if(this.stickyControls)return;this.player.getState().playing&&(this.controlsContainer.classList.add("hidden"),this.progressContainer.classList.add("hidden"))}resetHideControlsTimeout(){this.stickyControls||(this.hideControlsTimeout&&clearTimeout(this.hideControlsTimeout),this.hideControlsTimeout=window.setTimeout(()=>{this.hideControls()},1e4))}formatTime(t){if(isNaN(t))return"0:00";const e=Math.floor(t/60),s=Math.floor(t%60);return`${e}:${s.toString().padStart(2,"0")}`}getPlayIcon(){return'<svg viewBox="0 0 24 24"><path fill="white" d="M8 5v14l11-7z"/></svg>'}getPauseIcon(){return'<svg viewBox="0 0 24 24"><path fill="white" d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/></svg>'}getVolumeIcon(){return'<svg viewBox="0 0 24 24"><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.02z"/></svg>'}getMutedIcon(){return'<svg viewBox="0 0 24 24"><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"/></svg>'}getFullscreenIcon(){return'<svg viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>'}getQualityIcon(){return'<svg viewBox="0 0 24 24"><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-2zm-8 12H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/></svg>'}getSkipBackwardIcon(){return`<svg viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
566
+ `,e.querySelectorAll(".wontum-quality-option").forEach(i=>{i.addEventListener("click",s=>{const r=s.target,l=parseInt(r.dataset.quality||"-1");this.player.setQuality(l),e.querySelectorAll(".wontum-quality-option").forEach(c=>c.classList.remove("active")),r.classList.add("active")})})}showControls(){this.controlsContainer.classList.remove("hidden"),this.progressContainer.classList.remove("hidden")}hideControls(){if(this.stickyControls)return;this.player.getState().playing&&(this.controlsContainer.classList.add("hidden"),this.progressContainer.classList.add("hidden"))}resetHideControlsTimeout(){this.stickyControls||(this.hideControlsTimeout&&clearTimeout(this.hideControlsTimeout),this.hideControlsTimeout=window.setTimeout(()=>{this.hideControls()},1e4))}formatTime(t){if(isNaN(t))return"0:00";const e=Math.floor(t/60),n=Math.floor(t%60);return`${e}:${n.toString().padStart(2,"0")}`}getPlayIcon(){return'<svg viewBox="0 0 24 24"><path fill="white" d="M8 5v14l11-7z"/></svg>'}getPauseIcon(){return'<svg viewBox="0 0 24 24"><path fill="white" d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/></svg>'}getVolumeIcon(){return'<svg viewBox="0 0 24 24"><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.02z"/></svg>'}getMutedIcon(){return'<svg viewBox="0 0 24 24"><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"/></svg>'}getFullscreenIcon(){return'<svg viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>'}getSkipBackwardIcon(){return`<svg viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
560
567
  <circle cx="30" cy="30" r="28" stroke="white" stroke-width="2"/>
561
568
  <!-- Circular arrow backward -->
562
569
  <path d="M30 12 A18 18 0 1 0 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
@@ -568,25 +575,4 @@
568
575
  <path d="M30 12 A18 18 0 1 1 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
569
576
  <path d="M35 12 L30 12 L30 17" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
570
577
  <text x="30" y="35" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="white" text-anchor="middle">10</text>
571
- </svg>`}getSubtitleIcon(){return'<svg viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM4 12h4v2H4v-2zm10 6H4v-2h10v2zm6 0h-4v-2h4v2zm0-4H10v-2h10v2z"/></svg>'}getSpeedIcon(){return'<svg viewBox="0 0 24 24"><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"/></svg>'}getSettingsIcon(){return'<svg viewBox="0 0 24 24"><path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.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-.05.3-.09.63-.09.94s.02.64.07.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"/></svg>'}destroy(){this.hideControlsTimeout&&clearTimeout(this.hideControlsTimeout),this.controlsContainer.remove()}}class nt{constructor(t){o(this,"config");o(this,"urlCache",new Map);o(this,"signedUrls",new Set);this.config=t}async processUrl(t){return this.isCloudFrontUrl(t)?this.signCloudFrontUrl(t):this.isS3Url(t)?this.getPresignedUrl(t):t}isCloudFrontUrl(t){var e;if(!((e=this.config)!=null&&e.cloudFrontDomains)||this.config.cloudFrontDomains.length===0)return!1;try{const s=new URL(t);return this.config.cloudFrontDomains.some(r=>s.hostname.includes(r))}catch{return!1}}isS3Url(t){return t.includes(".s3.")||t.includes("s3.amazonaws.com")||t.startsWith("s3://")}async signCloudFrontUrl(t){var e;if(this.signedUrls.has(t))return t;if((e=this.config)!=null&&e.signUrl)try{const s=await this.config.signUrl(t);return this.signedUrls.add(t),s}catch(s){throw console.error("Failed to sign CloudFront URL:",s),new Error("Failed to sign CloudFront URL")}return console.warn("No signUrl function provided. CloudFront cookies may not be set."),t}extractS3Key(t){if(t.startsWith("s3://"))return t.replace("s3://","").split("/").slice(1).join("/");const e=t.match(/s3[.-]([^.]+)\.amazonaws\.com\/(.+)/);if(e)return e[2];const s=t.match(/([^.]+)\.s3\.amazonaws\.com\/(.+)/);return s?s[2]:t}async getPresignedUrl(t){var r;const e=this.extractS3Key(t),s=this.urlCache.get(e);if(s&&s.expiresAt>Date.now())return s.url;if((r=this.config)!=null&&r.getPresignedUrl)try{const i=await this.config.getPresignedUrl(e);return this.urlCache.set(e,{url:i,expiresAt:Date.now()+50*60*1e3}),i}catch(i){throw console.error("Failed to generate presigned URL:",i),new Error("Failed to generate presigned URL for S3 object")}return console.warn("No getPresignedUrl function provided. Using direct S3 URL (requires public bucket)"),t}static constructS3Url(t,e,s="us-east-1"){return`https://${t}.s3.${s}.amazonaws.com/${e}`}static parseS3Uri(t){if(!t.startsWith("s3://"))return null;const e=t.replace("s3://","").split("/"),s=e[0],r=e.slice(1).join("/");return{bucket:s,key:r}}clearCache(){this.urlCache.clear(),this.signedUrls.clear()}}class V{constructor(t){o(this,"container");o(this,"videoElement");o(this,"hls",null);o(this,"config");o(this,"eventListeners",new Map);o(this,"analytics");o(this,"s3Handler");o(this,"uiController");o(this,"state",{playing:!1,paused:!0,ended:!1,buffering:!1,currentTime:0,duration:0,volume:1,muted:!1,playbackRate:1,quality:"auto",availableQualities:[],fullscreen:!1});if(this.config=t,this.container=typeof t.container=="string"?document.querySelector(t.container):t.container,!this.container)throw new Error("Container element not found");this.analytics=new tt(t.analytics),this.s3Handler=new nt(t.s3Config),this.videoElement=this.createVideoElement(),this.container.appendChild(this.videoElement),this.uiController=new et(this.container,this),this.setupVideoListeners(),this.loadSource(t.src),t.autoplay&&(this.videoElement.autoplay=!0),t.muted&&this.mute(),t.poster&&(this.videoElement.poster=t.poster),t.preload&&(this.videoElement.preload=t.preload),t.subtitles&&this.addSubtitleTracks(t.subtitles)}addSubtitleTracks(t){t.forEach(e=>{const s=document.createElement("track");s.kind="subtitles",s.label=e.label,s.src=e.src,s.srclang=e.srclang,e.default&&(s.default=!0),this.videoElement.appendChild(s)})}createVideoElement(){const t=document.createElement("video");return t.className="wontum-player-video",t.style.width="100%",t.style.height="100%",t.playsInline=!0,t}setupVideoListeners(){this.videoElement.addEventListener("play",()=>{this.state.playing=!0,this.state.paused=!1,this.emit("play"),this.analytics.trackEvent("play",this.getAnalyticsData())}),this.videoElement.addEventListener("pause",()=>{this.state.playing=!1,this.state.paused=!0,this.emit("pause"),this.analytics.trackEvent("pause",this.getAnalyticsData())}),this.videoElement.addEventListener("ended",()=>{this.state.ended=!0,this.state.playing=!1,this.emit("ended"),this.analytics.trackEvent("ended",this.getAnalyticsData())}),this.videoElement.addEventListener("timeupdate",()=>{this.state.currentTime=this.videoElement.currentTime,this.emit("timeupdate",{currentTime:this.state.currentTime})}),this.videoElement.addEventListener("loadedmetadata",()=>{this.state.duration=this.videoElement.duration,this.emit("loadedmetadata",{duration:this.state.duration}),this.analytics.trackEvent("loadedmetadata",this.getAnalyticsData())}),this.videoElement.addEventListener("volumechange",()=>{this.state.volume=this.videoElement.volume,this.state.muted=this.videoElement.muted,this.emit("volumechange",{volume:this.state.volume,muted:this.state.muted})}),this.videoElement.addEventListener("ratechange",()=>{this.state.playbackRate=this.videoElement.playbackRate,this.emit("ratechange",{playbackRate:this.state.playbackRate})}),this.videoElement.addEventListener("waiting",()=>{this.state.buffering=!0,this.emit("waiting"),this.analytics.trackEvent("buffering_start",this.getAnalyticsData())}),this.videoElement.addEventListener("canplay",()=>{this.state.buffering=!1,this.emit("canplay"),this.analytics.trackEvent("buffering_end",this.getAnalyticsData())}),this.videoElement.addEventListener("seeking",()=>{this.emit("seeking")}),this.videoElement.addEventListener("seeked",()=>{this.emit("seeked",{currentTime:this.state.currentTime}),this.analytics.trackEvent("seeked",this.getAnalyticsData())}),this.videoElement.addEventListener("error",t=>{const e=this.videoElement.error;this.emit("error",{error:e}),this.analytics.trackEvent("error",{...this.getAnalyticsData(),error:e==null?void 0:e.message})}),this.videoElement.addEventListener("loadstart",()=>{this.emit("loadstart")}),this.videoElement.addEventListener("loadeddata",()=>{this.emit("loadeddata")}),this.videoElement.addEventListener("canplaythrough",()=>{this.emit("canplaythrough")}),this.videoElement.addEventListener("playing",()=>{this.state.playing=!0,this.state.buffering=!1,this.emit("playing")}),this.videoElement.addEventListener("durationchange",()=>{this.state.duration=this.videoElement.duration,this.emit("durationchange",{duration:this.state.duration})}),this.videoElement.addEventListener("progress",()=>{this.emit("progress",{buffered:this.videoElement.buffered})}),this.videoElement.addEventListener("stalled",()=>{this.emit("stalled")}),this.videoElement.addEventListener("suspend",()=>{this.emit("suspend")}),this.videoElement.addEventListener("abort",()=>{this.emit("abort")}),this.videoElement.addEventListener("emptied",()=>{this.emit("emptied")}),this.videoElement.addEventListener("resize",()=>{this.emit("resize",{videoWidth:this.videoElement.videoWidth,videoHeight:this.videoElement.videoHeight})})}async loadSource(t){try{const e=await this.s3Handler.processUrl(t);if(k.isSupported())this.hls=new k(this.config.hlsConfig),this.hls.loadSource(e),this.hls.attachMedia(this.videoElement),this.hls.on(k.Events.MANIFEST_PARSED,(s,r)=>{const i=this.extractQualities(r.levels);this.state.availableQualities=i.map(l=>l.name),this.emit("loadedmetadata",{qualities:i})}),this.hls.on(k.Events.LEVEL_SWITCHED,(s,r)=>{var l;const i=(l=this.hls)==null?void 0:l.levels[r.level];i&&(this.state.quality=`${i.height}p`,this.emit("qualitychange",{quality:this.state.quality}))}),this.hls.on(k.Events.ERROR,(s,r)=>{r.fatal&&this.handleHlsError(r)});else if(this.videoElement.canPlayType("application/vnd.apple.mpegurl"))this.videoElement.src=e;else throw new Error("HLS is not supported in this browser")}catch(e){console.error("Failed to load video source:",e),this.emit("error",{error:e})}}extractQualities(t){return t.map(e=>({height:e.height,width:e.width,bitrate:e.bitrate,name:`${e.height}p`}))}handleHlsError(t){var e,s;switch(t.type){case k.ErrorTypes.NETWORK_ERROR:console.error("Network error occurred"),(e=this.hls)==null||e.startLoad();break;case k.ErrorTypes.MEDIA_ERROR:console.error("Media error occurred"),(s=this.hls)==null||s.recoverMediaError();break;default:console.error("Fatal error occurred:",t),this.destroy();break}}getAnalyticsData(){return{currentTime:this.state.currentTime,duration:this.state.duration,quality:this.state.quality,playbackRate:this.state.playbackRate,volume:this.state.volume,muted:this.state.muted}}play(){return this.videoElement.play()}pause(){this.videoElement.pause()}seek(t){this.videoElement.currentTime=t}skipForward(t=10){const e=Math.min(this.state.currentTime+t,this.state.duration);this.seek(e)}skipBackward(t=10){const e=Math.max(this.state.currentTime-t,0);this.seek(e)}setVolume(t){this.videoElement.volume=Math.max(0,Math.min(1,t))}mute(){this.videoElement.muted=!0}unmute(){this.videoElement.muted=!1}setPlaybackRate(t){this.videoElement.playbackRate=t}setQuality(t){this.hls&&(this.hls.currentLevel=t)}enterFullscreen(){this.container.requestFullscreen&&(this.container.requestFullscreen(),this.state.fullscreen=!0,this.emit("fullscreenchange",{fullscreen:!0}))}exitFullscreen(){document.exitFullscreen&&(document.exitFullscreen(),this.state.fullscreen=!1,this.emit("fullscreenchange",{fullscreen:!1}))}getState(){return{...this.state}}getVideoElement(){return this.videoElement}enableSubtitles(t){const e=this.videoElement.textTracks;for(let s=0;s<e.length;s++)e[s].mode=s===t?"showing":"hidden"}disableSubtitles(){const t=this.videoElement.textTracks;for(let e=0;e<t.length;e++)t[e].mode="hidden"}toggleSubtitles(){const t=this.videoElement.textTracks;return Array.from(t).some(s=>s.mode==="showing")?(this.disableSubtitles(),!1):t.length>0?(this.enableSubtitles(0),!0):!1}getSubtitleTracks(){return Array.from(this.videoElement.textTracks)}areSubtitlesEnabled(){const t=this.videoElement.textTracks;return Array.from(t).some(e=>e.mode==="showing")}on(t,e){this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e)}off(t,e){var s;(s=this.eventListeners.get(t))==null||s.delete(e)}emit(t,e){var r;const s={type:t,data:e,timestamp:Date.now()};(r=this.eventListeners.get(t))==null||r.forEach(i=>{i(s)})}destroy(){this.hls&&(this.hls.destroy(),this.hls=null),this.uiController.destroy(),this.videoElement.remove(),this.eventListeners.clear(),this.analytics.destroy()}}var N={exports:{}},P={};/**
572
- * @license React
573
- * react-jsx-runtime.production.js
574
- *
575
- * Copyright (c) Meta Platforms, Inc. and affiliates.
576
- *
577
- * This source code is licensed under the MIT license found in the
578
- * LICENSE file in the root directory of this source tree.
579
- */var Z;function ct(){if(Z)return P;Z=1;var c=Symbol.for("react.transitional.element"),t=Symbol.for("react.fragment");function e(s,r,i){var l=null;if(i!==void 0&&(l=""+i),r.key!==void 0&&(l=""+r.key),"key"in r){i={};for(var u in r)u!=="key"&&(i[u]=r[u])}else i=r;return r=i.ref,{$$typeof:c,type:s,key:l,ref:r!==void 0?r:null,props:i}}return P.Fragment=t,P.jsx=e,P.jsxs=e,P}var A={};/**
580
- * @license React
581
- * react-jsx-runtime.development.js
582
- *
583
- * Copyright (c) Meta Platforms, Inc. and affiliates.
584
- *
585
- * This source code is licensed under the MIT license found in the
586
- * LICENSE file in the root directory of this source tree.
587
- */var K;function ut(){return K||(K=1,process.env.NODE_ENV!=="production"&&function(){function c(n){if(n==null)return null;if(typeof n=="function")return n.$$typeof===B?null:n.displayName||n.name||null;if(typeof n=="string")return n;switch(n){case E:return"Fragment";case F:return"Profiler";case I:return"StrictMode";case q:return"Suspense";case _:return"SuspenseList";case y:return"Activity"}if(typeof n=="object")switch(typeof n.tag=="number"&&console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."),n.$$typeof){case M:return"Portal";case L:return n.displayName||"Context";case O:return(n._context.displayName||"Context")+".Consumer";case R:var a=n.render;return n=n.displayName,n||(n=a.displayName||a.name||"",n=n!==""?"ForwardRef("+n+")":"ForwardRef"),n;case j:return a=n.displayName||null,a!==null?a:c(n.type)||"Memo";case p:a=n._payload,n=n._init;try{return c(n(a))}catch{}}return null}function t(n){return""+n}function e(n){try{t(n);var a=!1}catch{a=!0}if(a){a=console;var d=a.error,h=typeof Symbol=="function"&&Symbol.toStringTag&&n[Symbol.toStringTag]||n.constructor.name||"Object";return d.call(a,"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",h),t(n)}}function s(n){if(n===E)return"<>";if(typeof n=="object"&&n!==null&&n.$$typeof===p)return"<...>";try{var a=c(n);return a?"<"+a+">":"<...>"}catch{return"<...>"}}function r(){var n=z.A;return n===null?null:n.getOwner()}function i(){return Error("react-stack-top-frame")}function l(n){if(W.call(n,"key")){var a=Object.getOwnPropertyDescriptor(n,"key").get;if(a&&a.isReactWarning)return!1}return n.key!==void 0}function u(n,a){function d(){Y||(Y=!0,console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",a))}d.isReactWarning=!0,Object.defineProperty(n,"key",{get:d,configurable:!0})}function g(){var n=c(this.type);return Q[n]||(Q[n]=!0,console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")),n=this.props.ref,n!==void 0?n:null}function b(n,a,d,h,$,D){var m=d.ref;return n={$$typeof:T,type:n,key:a,props:d,_owner:h},(m!==void 0?m:null)!==null?Object.defineProperty(n,"ref",{enumerable:!1,get:g}):Object.defineProperty(n,"ref",{enumerable:!1,value:null}),n._store={},Object.defineProperty(n._store,"validated",{configurable:!1,enumerable:!1,writable:!0,value:0}),Object.defineProperty(n,"_debugInfo",{configurable:!1,enumerable:!1,writable:!0,value:null}),Object.defineProperty(n,"_debugStack",{configurable:!1,enumerable:!1,writable:!0,value:$}),Object.defineProperty(n,"_debugTask",{configurable:!1,enumerable:!1,writable:!0,value:D}),Object.freeze&&(Object.freeze(n.props),Object.freeze(n)),n}function f(n,a,d,h,$,D){var m=a.children;if(m!==void 0)if(h)if(it(m)){for(h=0;h<m.length;h++)S(m[h]);Object.freeze&&Object.freeze(m)}else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");else S(m);if(W.call(a,"key")){m=c(n);var x=Object.keys(a).filter(function(ot){return ot!=="key"});h=0<x.length?"{key: someKey, "+x.join(": ..., ")+": ...}":"{key: someKey}",G[m+h]||(x=0<x.length?"{"+x.join(": ..., ")+": ...}":"{}",console.error(`A props object containing a "key" prop is being spread into JSX:
588
- let props = %s;
589
- <%s {...props} />
590
- React keys must be passed directly to JSX without using spread:
591
- let props = %s;
592
- <%s key={someKey} {...props} />`,h,m,x,m),G[m+h]=!0)}if(m=null,d!==void 0&&(e(d),m=""+d),l(a)&&(e(a.key),m=""+a.key),"key"in a){d={};for(var U in a)U!=="key"&&(d[U]=a[U])}else d=a;return m&&u(d,typeof n=="function"?n.displayName||n.name||"Unknown":n),b(n,m,d,r(),$,D)}function S(n){C(n)?n._store&&(n._store.validated=1):typeof n=="object"&&n!==null&&n.$$typeof===p&&(n._payload.status==="fulfilled"?C(n._payload.value)&&n._payload.value._store&&(n._payload.value._store.validated=1):n._store&&(n._store.validated=1))}function C(n){return typeof n=="object"&&n!==null&&n.$$typeof===T}var w=v,T=Symbol.for("react.transitional.element"),M=Symbol.for("react.portal"),E=Symbol.for("react.fragment"),I=Symbol.for("react.strict_mode"),F=Symbol.for("react.profiler"),O=Symbol.for("react.consumer"),L=Symbol.for("react.context"),R=Symbol.for("react.forward_ref"),q=Symbol.for("react.suspense"),_=Symbol.for("react.suspense_list"),j=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),y=Symbol.for("react.activity"),B=Symbol.for("react.client.reference"),z=w.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,W=Object.prototype.hasOwnProperty,it=Array.isArray,H=console.createTask?console.createTask:function(){return null};w={react_stack_bottom_frame:function(n){return n()}};var Y,Q={},J=w.react_stack_bottom_frame.bind(w,i)(),X=H(s(i)),G={};A.Fragment=E,A.jsx=function(n,a,d){var h=1e4>z.recentlyCreatedOwnerStacks++;return f(n,a,d,!1,h?Error("react-stack-top-frame"):J,h?H(s(n)):X)},A.jsxs=function(n,a,d){var h=1e4>z.recentlyCreatedOwnerStacks++;return f(n,a,d,!0,h?Error("react-stack-top-frame"):J,h?H(s(n)):X)}}()),A}process.env.NODE_ENV==="production"?N.exports=ct():N.exports=ut();var st=N.exports;const dt=c=>{const{src:t,autoplay:e,muted:s,controls:r=!0,poster:i,preload:l,theme:u,s3Config:g,analytics:b,hlsConfig:f,onReady:S,onPlay:C,onPause:w,onEnded:T,onTimeUpdate:M,onVolumeChange:E,onError:I,style:F,className:O,width:L="100%",height:R="500px"}=c,q=v.useRef(null),_=v.useRef(null);return v.useEffect(()=>{if(!q.current)return;const j={src:t,container:q.current,autoplay:e,muted:s,controls:r,poster:i,preload:l,theme:u,s3Config:g,analytics:b,hlsConfig:f},p=new V(j);return _.current=p,C&&p.on("play",C),w&&p.on("pause",w),T&&p.on("ended",T),I&&p.on("error",y=>{var B;return I((B=y.data)==null?void 0:B.error)}),M&&p.on("timeupdate",y=>M(y.data.currentTime)),E&&p.on("volumechange",y=>E(y.data.volume,y.data.muted)),S&&S(p),()=>{p.destroy(),_.current=null}},[t]),v.useEffect(()=>{_.current},[e,s,r]),st.jsx("div",{ref:q,className:O,style:{width:typeof L=="number"?`${L}px`:L,height:typeof R=="number"?`${R}px`:R,...F}})},ht=c=>{const[t,e]=v.useState(null),[s,r]=v.useState(null),i=v.useRef(null);return v.useEffect(()=>{if(!i.current)return;const l=new V({...c,container:i.current});e(l);const u=()=>{r(l.getState())};return l.on("play",u),l.on("pause",u),l.on("timeupdate",u),l.on("volumechange",u),l.on("loadedmetadata",u),()=>{l.destroy()}},[c.src]),{containerRef:i,player:t,state:s}},rt=v.createContext({player:null,state:null}),mt=c=>{const{player:t,children:e}=c,[s,r]=v.useState(t.getState());return v.useEffect(()=>{const i=()=>{r(t.getState())};return t.on("play",i),t.on("pause",i),t.on("timeupdate",i),t.on("volumechange",i),t.on("loadedmetadata",i),()=>{}},[t]),st.jsx(rt.Provider,{value:{player:t,state:s},children:e})},pt=()=>{const c=v.useContext(rt);if(!c.player)throw new Error("useWontumPlayerContext must be used within WontumPlayerProvider");return c};exports.Analytics=tt;exports.S3Handler=nt;exports.UIController=et;exports.WontumPlayer=V;exports.WontumPlayerProvider=mt;exports.WontumPlayerReact=dt;exports.useWontumPlayer=ht;exports.useWontumPlayerContext=pt;
578
+ </svg>`}getSettingsIcon(){return'<svg viewBox="0 0 24 24"><path d="M19.14 12.94c.04-.3.06-.61.06-.94 0-.32-.02-.64-.07-.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-.05.3-.09.63-.09.94s.02.64.07.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"/></svg>'}destroy(){this.hideControlsTimeout&&clearTimeout(this.hideControlsTimeout),this.controlsContainer.remove()}}class F{constructor(t){o(this,"config");o(this,"urlCache",new Map);o(this,"signedUrls",new Set);this.config=t}async processUrl(t){return this.isCloudFrontUrl(t)?this.signCloudFrontUrl(t):this.isS3Url(t)?this.getPresignedUrl(t):t}isCloudFrontUrl(t){var e;if(!((e=this.config)!=null&&e.cloudFrontDomains)||this.config.cloudFrontDomains.length===0)return!1;try{const n=new URL(t);return this.config.cloudFrontDomains.some(i=>n.hostname.includes(i))}catch{return!1}}isS3Url(t){return t.includes(".s3.")||t.includes("s3.amazonaws.com")||t.startsWith("s3://")}async signCloudFrontUrl(t){var e;if(this.signedUrls.has(t))return t;if((e=this.config)!=null&&e.signUrl)try{const n=await this.config.signUrl(t);return this.signedUrls.add(t),n}catch(n){throw console.error("Failed to sign CloudFront URL:",n),new Error("Failed to sign CloudFront URL")}return console.warn("No signUrl function provided. CloudFront cookies may not be set."),t}extractS3Key(t){if(t.startsWith("s3://"))return t.replace("s3://","").split("/").slice(1).join("/");const e=t.match(/s3[.-]([^.]+)\.amazonaws\.com\/(.+)/);if(e)return e[2];const n=t.match(/([^.]+)\.s3\.amazonaws\.com\/(.+)/);return n?n[2]:t}async getPresignedUrl(t){var i;const e=this.extractS3Key(t),n=this.urlCache.get(e);if(n&&n.expiresAt>Date.now())return n.url;if((i=this.config)!=null&&i.getPresignedUrl)try{const s=await this.config.getPresignedUrl(e);return this.urlCache.set(e,{url:s,expiresAt:Date.now()+50*60*1e3}),s}catch(s){throw console.error("Failed to generate presigned URL:",s),new Error("Failed to generate presigned URL for S3 object")}return console.warn("No getPresignedUrl function provided. Using direct S3 URL (requires public bucket)"),t}static constructS3Url(t,e,n="us-east-1"){return`https://${t}.s3.${n}.amazonaws.com/${e}`}static parseS3Uri(t){if(!t.startsWith("s3://"))return null;const e=t.replace("s3://","").split("/"),n=e[0],i=e.slice(1).join("/");return{bucket:n,key:i}}clearCache(){this.urlCache.clear(),this.signedUrls.clear()}}class b{constructor(t){o(this,"container");o(this,"videoElement");o(this,"hls",null);o(this,"config");o(this,"eventListeners",new Map);o(this,"analytics");o(this,"s3Handler");o(this,"uiController");o(this,"qualities",[]);o(this,"state",{playing:!1,paused:!0,ended:!1,buffering:!1,currentTime:0,duration:0,volume:1,muted:!1,playbackRate:1,quality:"auto",availableQualities:[],fullscreen:!1});if(this.config=t,this.container=typeof t.container=="string"?document.querySelector(t.container):t.container,!this.container)throw new Error("Container element not found");this.analytics=new R(t.analytics),this.s3Handler=new F(t.s3Config),this.videoElement=this.createVideoElement(),this.container.appendChild(this.videoElement),this.uiController=new $(this.container,this),this.setupVideoListeners(),this.loadSource(t.src),t.autoplay&&(this.videoElement.autoplay=!0),t.muted&&this.mute(),t.poster&&(this.videoElement.poster=t.poster),t.preload&&(this.videoElement.preload=t.preload),t.subtitles&&this.addSubtitleTracks(t.subtitles)}addSubtitleTracks(t){t.forEach(e=>{const n=document.createElement("track");n.kind="subtitles",n.label=e.label,n.src=e.src,n.srclang=e.srclang,e.default&&(n.default=!0),this.videoElement.appendChild(n)})}createVideoElement(){const t=document.createElement("video");return t.className="wontum-player-video",t.style.width="100%",t.style.height="100%",t.playsInline=!0,t}setupVideoListeners(){this.videoElement.addEventListener("play",()=>{this.state.playing=!0,this.state.paused=!1,this.emit("play"),this.analytics.trackEvent("play",this.getAnalyticsData())}),this.videoElement.addEventListener("pause",()=>{this.state.playing=!1,this.state.paused=!0,this.emit("pause"),this.analytics.trackEvent("pause",this.getAnalyticsData())}),this.videoElement.addEventListener("ended",()=>{this.state.ended=!0,this.state.playing=!1,this.emit("ended"),this.analytics.trackEvent("ended",this.getAnalyticsData())}),this.videoElement.addEventListener("timeupdate",()=>{this.state.currentTime=this.videoElement.currentTime,this.emit("timeupdate",{currentTime:this.state.currentTime})}),this.videoElement.addEventListener("loadedmetadata",()=>{this.state.duration=this.videoElement.duration,this.emit("loadedmetadata",{duration:this.state.duration}),this.analytics.trackEvent("loadedmetadata",this.getAnalyticsData())}),this.videoElement.addEventListener("volumechange",()=>{this.state.volume=this.videoElement.volume,this.state.muted=this.videoElement.muted,this.emit("volumechange",{volume:this.state.volume,muted:this.state.muted})}),this.videoElement.addEventListener("ratechange",()=>{this.state.playbackRate=this.videoElement.playbackRate,this.emit("ratechange",{playbackRate:this.state.playbackRate})}),this.videoElement.addEventListener("waiting",()=>{this.state.buffering=!0,this.emit("waiting"),this.analytics.trackEvent("buffering_start",this.getAnalyticsData())}),this.videoElement.addEventListener("canplay",()=>{this.state.buffering=!1,this.emit("canplay"),this.analytics.trackEvent("buffering_end",this.getAnalyticsData())}),this.videoElement.addEventListener("seeking",()=>{this.emit("seeking")}),this.videoElement.addEventListener("seeked",()=>{this.emit("seeked",{currentTime:this.state.currentTime}),this.analytics.trackEvent("seeked",this.getAnalyticsData())}),this.videoElement.addEventListener("error",t=>{const e=this.videoElement.error;this.emit("error",{error:e}),this.analytics.trackEvent("error",{...this.getAnalyticsData(),error:e==null?void 0:e.message})}),this.videoElement.addEventListener("loadstart",()=>{this.emit("loadstart")}),this.videoElement.addEventListener("loadeddata",()=>{this.emit("loadeddata")}),this.videoElement.addEventListener("canplaythrough",()=>{this.emit("canplaythrough")}),this.videoElement.addEventListener("playing",()=>{this.state.playing=!0,this.state.buffering=!1,this.emit("playing")}),this.videoElement.addEventListener("durationchange",()=>{this.state.duration=this.videoElement.duration,this.emit("durationchange",{duration:this.state.duration})}),this.videoElement.addEventListener("progress",()=>{this.emit("progress",{buffered:this.videoElement.buffered})}),this.videoElement.addEventListener("stalled",()=>{this.emit("stalled")}),this.videoElement.addEventListener("suspend",()=>{this.emit("suspend")}),this.videoElement.addEventListener("abort",()=>{this.emit("abort")}),this.videoElement.addEventListener("emptied",()=>{this.emit("emptied")}),this.videoElement.addEventListener("resize",()=>{this.emit("resize",{videoWidth:this.videoElement.videoWidth,videoHeight:this.videoElement.videoHeight})})}async loadSource(t){try{const e=await this.s3Handler.processUrl(t);if(m.isSupported())this.hls=new m(this.config.hlsConfig),this.hls.loadSource(e),this.hls.attachMedia(this.videoElement),this.hls.on(m.Events.MANIFEST_PARSED,(n,i)=>{const s=this.extractQualities(i.levels);this.qualities=s}),this.hls.on(m.Events.LEVEL_SWITCHED,(n,i)=>{var r;const s=(r=this.hls)==null?void 0:r.levels[i.level];s&&(this.state.quality=`${s.height}p`,this.emit("qualitychange",{quality:this.state.quality}))}),this.hls.on(m.Events.ERROR,(n,i)=>{i.fatal&&this.handleHlsError(i)});else if(this.videoElement.canPlayType("application/vnd.apple.mpegurl"))this.videoElement.src=e;else throw new Error("HLS is not supported in this browser")}catch(e){console.error("Failed to load video source:",e),this.emit("error",{error:e})}}extractQualities(t){return t.map(e=>({height:e.height,width:e.width,bitrate:e.bitrate,name:`${e.height}p`}))}handleHlsError(t){var e,n;switch(t.type){case m.ErrorTypes.NETWORK_ERROR:console.error("Network error occurred"),(e=this.hls)==null||e.startLoad();break;case m.ErrorTypes.MEDIA_ERROR:console.error("Media error occurred"),(n=this.hls)==null||n.recoverMediaError();break;default:console.error("Fatal error occurred:",t),this.destroy();break}}getAnalyticsData(){return{currentTime:this.state.currentTime,duration:this.state.duration,quality:this.state.quality,playbackRate:this.state.playbackRate,volume:this.state.volume,muted:this.state.muted}}play(){return this.videoElement.play()}pause(){this.videoElement.pause()}seek(t){this.videoElement.currentTime=t}skipForward(t=10){const e=Math.min(this.state.currentTime+t,this.state.duration);this.seek(e)}skipBackward(t=10){const e=Math.max(this.state.currentTime-t,0);this.seek(e)}setVolume(t){this.videoElement.volume=Math.max(0,Math.min(1,t))}mute(){this.videoElement.muted=!0}unmute(){this.videoElement.muted=!1}setPlaybackRate(t){this.videoElement.playbackRate=t}setQuality(t){this.hls&&(this.hls.currentLevel=t)}getQualities(){return this.qualities}enterFullscreen(){this.container.requestFullscreen&&(this.container.requestFullscreen(),this.state.fullscreen=!0,this.emit("fullscreenchange",{fullscreen:!0}))}exitFullscreen(){document.exitFullscreen&&(document.exitFullscreen(),this.state.fullscreen=!1,this.emit("fullscreenchange",{fullscreen:!1}))}getState(){return{...this.state}}getVideoElement(){return this.videoElement}enableSubtitles(t){const e=this.videoElement.textTracks;for(let n=0;n<e.length;n++)e[n].mode=n===t?"showing":"hidden"}disableSubtitles(){const t=this.videoElement.textTracks;for(let e=0;e<t.length;e++)t[e].mode="hidden"}toggleSubtitles(){const t=this.videoElement.textTracks;return Array.from(t).some(n=>n.mode==="showing")?(this.disableSubtitles(),!1):t.length>0?(this.enableSubtitles(0),!0):!1}getSubtitleTracks(){return Array.from(this.videoElement.textTracks)}areSubtitlesEnabled(){const t=this.videoElement.textTracks;return Array.from(t).some(e=>e.mode==="showing")}on(t,e){this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e)}off(t,e){var n;(n=this.eventListeners.get(t))==null||n.delete(e)}emit(t,e){var i;const n={type:t,data:e,timestamp:Date.now()};(i=this.eventListeners.get(t))==null||i.forEach(s=>{s(n)})}destroy(){this.hls&&(this.hls.destroy(),this.hls=null),this.uiController.destroy(),this.videoElement.remove(),this.eventListeners.clear(),this.analytics.destroy()}}const O=a=>{const{src:t,autoplay:e,muted:n,controls:i=!0,poster:s,preload:r,theme:l,s3Config:c,analytics:h,hlsConfig:g,subtitles:A,stickyControls:H,onReady:f,onPlay:k,onPause:E,onEnded:x,onTimeUpdate:S,onVolumeChange:C,onError:L,onLoadedMetadata:T,onQualityChange:q,style:U,className:D,width:v="100%",height:y="500px"}=a,w=d.useRef(null),M=d.useRef(null);return d.useEffect(()=>{if(!w.current)return;const j={src:t,container:w.current,autoplay:e,muted:n,controls:i,poster:s,preload:r,theme:l,s3Config:c,analytics:h,hlsConfig:g,subtitles:A,stickyControls:H},u=new b(j);return M.current=u,k&&u.on("play",k),E&&u.on("pause",E),x&&u.on("ended",x),L&&u.on("error",p=>{var B;return L((B=p.data)==null?void 0:B.error)}),T&&u.on("loadedmetadata",T),q&&u.on("qualitychange",p=>q(p.data.level)),S&&u.on("timeupdate",p=>S(p.data.currentTime)),C&&u.on("volumechange",p=>C(p.data.volume,p.data.muted)),f&&f(u),()=>{u.destroy(),M.current=null}},[t]),I.jsx("div",{ref:w,className:D,style:{width:typeof v=="number"?`${v}px`:v,height:typeof y=="number"?`${y}px`:y,...U}})},_=a=>{const[t,e]=d.useState(null),[n,i]=d.useState(null),s=d.useRef(null);return d.useEffect(()=>{if(!s.current)return;const r=new b({...a,container:s.current});e(r);const l=()=>{i(r.getState())};return r.on("play",l),r.on("pause",l),r.on("timeupdate",l),r.on("volumechange",l),r.on("loadedmetadata",l),()=>{r.destroy()}},[a.src]),{containerRef:s,player:t,state:n}},z=P.createContext({player:null,state:null}),Q=a=>{const{player:t,children:e}=a,[n,i]=d.useState(t.getState());return d.useEffect(()=>{const s=()=>{i(t.getState())};return t.on("play",s),t.on("pause",s),t.on("timeupdate",s),t.on("volumechange",s),t.on("loadedmetadata",s),()=>{}},[t]),I.jsx(z.Provider,{value:{player:t,state:n},children:e})},Y=()=>{const a=P.useContext(z);if(!a.player)throw new Error("useWontumPlayerContext must be used within WontumPlayerProvider");return a};exports.Analytics=R;exports.S3Handler=F;exports.UIController=$;exports.WontumPlayer=b;exports.WontumPlayerProvider=Q;exports.WontumPlayerReact=O;exports.useWontumPlayer=_;exports.useWontumPlayerContext=Y;