@obipascal/player 1.0.5 → 1.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -240,6 +240,7 @@ function VideoPlayer({ videoUrl }: VideoPlayerProps) {
240
240
 
241
241
  const s3config: S3Config = {
242
242
  cloudFrontDomains: [url.hostname],
243
+ withCredentials: true, // Enable cookies for CloudFront signed cookies
243
244
  signUrl: async (resourceUrl: string) => {
244
245
  try {
245
246
  const { data } = await refetch({
@@ -336,6 +337,7 @@ async function initializePlayer() {
336
337
  container: "#player",
337
338
  s3Config: {
338
339
  cloudFrontDomains: ["media.yourdomain.com"], // Your CloudFront domain
340
+ withCredentials: true, // Enable cookies for all HLS requests (required for CloudFront signed cookies)
339
341
  signUrl: async (url) => {
340
342
  // This function is called when player needs to access a video
341
343
  // Call your backend to refresh/set cookies if needed
@@ -734,9 +736,19 @@ interface WontumPlayerConfig {
734
736
  poster?: string // Poster image URL
735
737
  preload?: "none" | "metadata" | "auto" // Preload strategy
736
738
  theme?: PlayerTheme // Custom theme
737
- s3Config?: S3Config // S3 configuration
739
+ s3Config?: S3Config // S3/CloudFront configuration
738
740
  analytics?: AnalyticsConfig // Analytics configuration
739
741
  hlsConfig?: Partial<any> // HLS.js config override
742
+ subtitles?: SubtitleTrack[] // Subtitle tracks
743
+ stickyControls?: boolean // Keep controls always visible
744
+ }
745
+
746
+ interface S3Config {
747
+ signUrl?: (url: string) => Promise<string> // Sign URL and set cookies
748
+ cloudFrontDomains?: string[] // CloudFront domains (e.g., ['media.example.com'])
749
+ withCredentials?: boolean // Enable cookies for HLS requests (default: false, required for CloudFront signed cookies)
750
+ region?: string // S3 region
751
+ endpoint?: string // Custom S3 endpoint
740
752
  }
741
753
  ```
742
754
 
@@ -758,11 +770,17 @@ player.setPlaybackRate(rate: number): void // 0.5, 1, 1.5, 2, etc.
758
770
 
759
771
  // Quality control
760
772
  player.setQuality(qualityIndex: number): void
773
+ player.getQualities(): QualityLevel[]
761
774
 
762
775
  // Fullscreen
763
776
  player.enterFullscreen(): void
764
777
  player.exitFullscreen(): void
765
778
 
779
+ // Picture-in-Picture
780
+ player.enterPictureInPicture(): Promise<void>
781
+ player.exitPictureInPicture(): Promise<void>
782
+ player.togglePictureInPicture(): Promise<void>
783
+
766
784
  // State
767
785
  player.getState(): PlayerState
768
786
 
@@ -792,6 +810,8 @@ type PlayerEventType =
792
810
  | "error"
793
811
  | "qualitychange"
794
812
  | "fullscreenchange"
813
+ | "pictureinpictureenter"
814
+ | "pictureinpictureexit"
795
815
  ```
796
816
 
797
817
  ### React Components
@@ -994,6 +1014,15 @@ player.on("qualitychange", (event) => {
994
1014
  console.log("Quality changed to:", event.data.quality)
995
1015
  })
996
1016
 
1017
+ // Picture-in-Picture events
1018
+ player.on("pictureinpictureenter", () => {
1019
+ console.log("Entered Picture-in-Picture mode")
1020
+ })
1021
+
1022
+ player.on("pictureinpictureexit", () => {
1023
+ console.log("Exited Picture-in-Picture mode")
1024
+ })
1025
+
997
1026
  // Buffer events
998
1027
  player.on("waiting", () => console.log("Buffering..."))
999
1028
  player.on("canplay", () => console.log("Ready to play"))
@@ -1065,10 +1094,46 @@ player.setQuality(2) // Set to quality index 2
1065
1094
  player.enterFullscreen()
1066
1095
  player.exitFullscreen()
1067
1096
 
1097
+ // Picture-in-Picture
1098
+ await player.enterPictureInPicture()
1099
+ await player.exitPictureInPicture()
1100
+ await player.togglePictureInPicture()
1101
+
1068
1102
  // Cleanup
1069
1103
  player.destroy() // Remove player and clean up resources
1070
1104
  ```
1071
1105
 
1106
+ ### Picture-in-Picture Mode
1107
+
1108
+ Enable floating video that stays on top while users work in other apps:
1109
+
1110
+ ```typescript
1111
+ const player = new WontumPlayer({
1112
+ src: "https://example.com/video.m3u8",
1113
+ container: "#player",
1114
+ })
1115
+
1116
+ // Enter PiP mode
1117
+ await player.enterPictureInPicture()
1118
+
1119
+ // Listen for PiP events
1120
+ player.on("pictureinpictureenter", () => {
1121
+ console.log("Video is now floating!")
1122
+ })
1123
+
1124
+ player.on("pictureinpictureexit", () => {
1125
+ console.log("Back to normal mode")
1126
+ })
1127
+
1128
+ // Custom button to toggle PiP
1129
+ const pipButton = document.getElementById("pip-btn")
1130
+ pipButton.addEventListener("click", async () => {
1131
+ await player.togglePictureInPicture()
1132
+ })
1133
+ ```
1134
+
1135
+ **Note:** Picture-in-Picture is supported in most modern browsers. The player includes a built-in PiP button in the controls.
1136
+
1072
1137
  ## 📋 Complete API Reference
1073
1138
 
1074
1139
  For detailed API documentation including all methods, events, types, and configuration options, see **[API-REFERENCE.md](./API-REFERENCE.md)**.
@@ -1083,6 +1148,7 @@ For detailed API documentation including all methods, events, types, and configu
1083
1148
  - **Quality:** `setQuality(index)`, `getQualities()`
1084
1149
  - **Playback Rate:** `setPlaybackRate(rate)`
1085
1150
  - **Fullscreen:** `enterFullscreen()`, `exitFullscreen()`
1151
+ - **Picture-in-Picture:** `enterPictureInPicture()`, `exitPictureInPicture()`, `togglePictureInPicture()`
1086
1152
  - **State:** `getState()`, `getCurrentTime()`, `getDuration()`
1087
1153
  - **Lifecycle:** `destroy()`
1088
1154
 
@@ -1129,9 +1195,9 @@ Contributions are welcome! Please follow these steps:
1129
1195
 
1130
1196
  ## 💬 Support
1131
1197
 
1132
- - **Issues:** [GitHub Issues](https://github.com/yourorg/wontum-player/issues)
1133
- - **Discussions:** [GitHub Discussions](https://github.com/yourorg/wontum-player/discussions)
1134
- - **Email:** support@wontum.com
1198
+ - **Issues:** [GitHub Issues](https://github.com/obipascal/wontum-player/issues)
1199
+ - **Discussions:** [GitHub Discussions](https://github.com/obipascal/wontum-player/discussions)
1200
+ - **Email:** pascalobi83@gmail.com
1135
1201
 
1136
1202
  ## 🙏 Acknowledgments
1137
1203
 
@@ -36,6 +36,9 @@ export declare class WontumPlayer {
36
36
  getQualities(): QualityLevel[];
37
37
  enterFullscreen(): void;
38
38
  exitFullscreen(): void;
39
+ enterPictureInPicture(): Promise<void>;
40
+ exitPictureInPicture(): Promise<void>;
41
+ togglePictureInPicture(): Promise<void>;
39
42
  getState(): PlayerState;
40
43
  getVideoElement(): HTMLVideoElement;
41
44
  /**
@@ -45,6 +45,8 @@ export interface S3Config {
45
45
  getPresignedUrl?: (key: string) => Promise<string>;
46
46
  /** CloudFront domain patterns to match (e.g., ['media.domain.com']) */
47
47
  cloudFrontDomains?: string[];
48
+ /** Enable credentials (cookies) for HLS requests - required for CloudFront signed cookies */
49
+ withCredentials?: boolean;
48
50
  /** S3 bucket region */
49
51
  region?: string;
50
52
  /** Custom S3 endpoint */
@@ -82,7 +84,7 @@ export interface PlayerState {
82
84
  /**
83
85
  * Player events (compatible with Mux Player and HTML5 MediaElement events)
84
86
  */
85
- export type PlayerEventType = "play" | "pause" | "playing" | "ended" | "timeupdate" | "volumechange" | "ratechange" | "seeked" | "seeking" | "waiting" | "loadstart" | "loadeddata" | "loadedmetadata" | "canplay" | "canplaythrough" | "durationchange" | "progress" | "error" | "abort" | "emptied" | "stalled" | "suspend" | "qualitychange" | "fullscreenchange" | "resize";
87
+ export type PlayerEventType = "play" | "pause" | "playing" | "ended" | "timeupdate" | "volumechange" | "ratechange" | "seeked" | "seeking" | "waiting" | "loadstart" | "loadeddata" | "loadedmetadata" | "canplay" | "canplaythrough" | "durationchange" | "progress" | "error" | "abort" | "emptied" | "stalled" | "suspend" | "qualitychange" | "fullscreenchange" | "pictureinpictureenter" | "pictureinpictureexit" | "resize";
86
88
  export interface PlayerEvent {
87
89
  type: PlayerEventType;
88
90
  data?: any;
@@ -13,12 +13,15 @@ export declare class UIController {
13
13
  private skipBackwardButton;
14
14
  private skipForwardButton;
15
15
  private volumeButton;
16
+ private volumeContainer;
16
17
  private fullscreenButton;
18
+ private pipButton;
17
19
  private settingsButton;
18
20
  private volumeSlider;
19
21
  private progressInput;
20
22
  private hideControlsTimeout;
21
23
  private stickyControls;
24
+ private isVolumeSliderActive;
22
25
  constructor(container: HTMLElement, player: WontumPlayer);
23
26
  private injectStyles;
24
27
  private createProgressBar;
@@ -38,6 +41,7 @@ export declare class UIController {
38
41
  private getVolumeIcon;
39
42
  private getMutedIcon;
40
43
  private getFullscreenIcon;
44
+ private getPipIcon;
41
45
  private getSkipBackwardIcon;
42
46
  private getSkipForwardIcon;
43
47
  private getSettingsIcon;
@@ -1,13 +1,13 @@
1
- "use strict";var V=Object.defineProperty;var W=(l,t,e)=>t in l?V(l,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):l[t]=e;var o=(l,t,e)=>W(l,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("hls.js"),I=require("react/jsx-runtime"),h=require("react");function _(l){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(l){for(const e in l)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(l,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>l[e]})}}return t.default=l,Object.freeze(t)}const B=_(h);class P{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",a=e.controlsBackground||"linear-gradient(to top, rgba(0,0,0,0.8), transparent)",r=e.buttonHoverBg||"rgba(255, 255, 255, 0.1)",c=e.progressHeight||"6px",u=e.borderRadius||"4px",g=document.createElement("style");g.id=t,g.textContent=`
1
+ "use strict";var j=Object.defineProperty;var W=(l,t,e)=>t in l?j(l,t,{enumerable:!0,configurable:!0,writable:!0,value:e}):l[t]=e;var r=(l,t,e)=>W(l,typeof t!="symbol"?t+"":t,e);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const m=require("hls.js"),M=require("react/jsx-runtime"),h=require("react");function _(l){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(l){for(const e in l)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(l,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>l[e]})}}return t.default=l,Object.freeze(t)}const R=_(h);class B{constructor(t){r(this,"config");r(this,"sessionId");r(this,"events",[]);r(this,"sessionStartTime");r(this,"playbackStartTime",null);r(this,"totalPlayTime",0);r(this,"totalBufferTime",0);r(this,"bufferStartTime",null);r(this,"rebufferCount",0);r(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 s;if(!((s=this.config)!=null&&s.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 A{constructor(t,e){r(this,"container");r(this,"player");r(this,"controlsContainer");r(this,"progressContainer");r(this,"progressBar");r(this,"playButton");r(this,"skipBackwardButton");r(this,"skipForwardButton");r(this,"volumeButton");r(this,"volumeContainer");r(this,"fullscreenButton");r(this,"pipButton");r(this,"settingsButton");r(this,"volumeSlider");r(this,"progressInput");r(this,"hideControlsTimeout",null);r(this,"stickyControls",!1);r(this,"isVolumeSliderActive",!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.volumeContainer=this.controlsContainer.querySelector(".wontum-volume-container"),this.fullscreenButton=this.controlsContainer.querySelector(".wontum-fullscreen-btn"),this.pipButton=this.controlsContainer.querySelector(".wontum-pip-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",s=e.accentColor||"#2563eb",i=e.fontFamily||"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif",a=e.controlsBackground||"linear-gradient(to top, rgba(0,0,0,0.8), transparent)",o=e.buttonHoverBg||"rgba(255, 255, 255, 0.1)",c=e.progressHeight||"6px",u=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: ${s};
5
+ font-family: ${i};
6
6
  overflow: hidden;
7
7
  --primary-color: ${n};
8
- --accent-color: ${i};
8
+ --accent-color: ${s};
9
9
  --controls-bg: ${a};
10
- --button-hover: ${r};
10
+ --button-hover: ${o};
11
11
  --progress-height: ${c};
12
12
  --border-radius: ${u};
13
13
  }
@@ -100,18 +100,20 @@
100
100
  .wontum-progress-container {
101
101
  position: absolute;
102
102
  bottom: 58px;
103
- left: 0;
104
- right: 0;
103
+ left: 50%;
104
+ transform: translateX(-50%);
105
+ width: 70%;
106
+ max-width: 600px;
105
107
  height: 5px;
106
108
  cursor: pointer;
107
109
  z-index: 12;
108
- padding: 0 20px;
110
+ padding: 0;
109
111
  transition: height 0.2s ease, opacity 0.3s ease, transform 0.3s ease;
110
112
  }
111
113
 
112
114
  .wontum-progress-container.hidden {
113
115
  opacity: 0;
114
- transform: translateY(100%);
116
+ transform: translateX(-50%) translateY(100%);
115
117
  pointer-events: none;
116
118
  }
117
119
 
@@ -197,6 +199,7 @@
197
199
  position: relative;
198
200
  display: flex;
199
201
  align-items: center;
202
+ gap: 0;
200
203
  }
201
204
 
202
205
  .wontum-volume-slider-wrapper {
@@ -208,18 +211,31 @@
208
211
  backdrop-filter: blur(10px);
209
212
  padding: 12px 8px;
210
213
  border-radius: 6px;
211
- margin-bottom: 8px;
214
+ margin-bottom: 5px;
212
215
  opacity: 0;
213
216
  pointer-events: none;
214
217
  transition: opacity 0.2s ease;
215
218
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
219
+ z-index: 20;
216
220
  }
217
221
 
218
- .wontum-volume-container:hover .wontum-volume-slider-wrapper {
222
+ .wontum-volume-container:hover .wontum-volume-slider-wrapper,
223
+ .wontum-volume-slider-wrapper:hover {
219
224
  opacity: 1;
220
225
  pointer-events: all;
221
226
  }
222
227
 
228
+ /* Add a bridge area between button and slider to prevent gap */
229
+ .wontum-volume-container::before {
230
+ content: '';
231
+ position: absolute;
232
+ bottom: 100%;
233
+ left: 0;
234
+ right: 0;
235
+ height: 10px;
236
+ background: transparent;
237
+ }
238
+
223
239
  .wontum-volume-slider {
224
240
  -webkit-appearance: slider-vertical;
225
241
  appearance: slider-vertical;
@@ -534,6 +550,10 @@
534
550
  </div>
535
551
  </div>
536
552
 
553
+ <button class="wontum-btn wontum-pip-btn" aria-label="Picture-in-Picture">
554
+ ${this.getPipIcon()}
555
+ </button>
556
+
537
557
  <button class="wontum-btn wontum-fullscreen-btn" aria-label="Fullscreen">
538
558
  ${this.getFullscreenIcon()}
539
559
  </button>
@@ -542,28 +562,28 @@
542
562
  <div class="wontum-loading" style="display: none;">
543
563
  <div class="wontum-spinner"></div>
544
564
  </div>
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),a=this.player.getState(),r=s/100*a.duration;this.player.seek(r)}),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,a=s.getAttribute("data-tab");t.forEach(u=>u.classList.remove("active")),s.classList.add("active"),this.controlsContainer.querySelectorAll(".wontum-tab-panel").forEach(u=>u.classList.remove("active"));const c=this.controlsContainer.querySelector(`[data-panel="${a}"]`);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=`
565
+ `,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 s=n.target,i=parseFloat(s.value),a=this.player.getState(),o=i/100*a.duration;this.player.seek(o)}),this.volumeSlider.addEventListener("input",n=>{const s=n.target,i=parseFloat(s.value)/100;this.player.setVolume(i)}),this.volumeButton.addEventListener("click",()=>{this.player.getState().muted?this.player.unmute():this.player.mute()}),this.volumeContainer.addEventListener("mouseenter",()=>{this.isVolumeSliderActive=!0}),this.volumeContainer.addEventListener("mouseleave",()=>{this.isVolumeSliderActive=!1}),this.volumeSlider.addEventListener("input",()=>{this.isVolumeSliderActive=!0,this.resetHideControlsTimeout()}),this.volumeSlider.addEventListener("change",()=>{setTimeout(()=>{this.isVolumeSliderActive=!1},500)}),this.fullscreenButton.addEventListener("click",()=>{this.player.getState().fullscreen?this.player.exitFullscreen():this.player.enterFullscreen()}),this.pipButton.addEventListener("click",async()=>{try{await this.player.togglePictureInPicture()}catch(n){console.error("PiP error:",n)}}),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",s=>{const i=s.currentTarget,a=i.getAttribute("data-tab");t.forEach(u=>u.classList.remove("active")),i.classList.add("active"),this.controlsContainer.querySelectorAll(".wontum-tab-panel").forEach(u=>u.classList.remove("active"));const c=this.controlsContainer.querySelector(`[data-panel="${a}"]`);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 i=e/n.duration*100;this.progressBar.style.width=`${i}%`,this.progressInput.value=i.toString()}const s=this.controlsContainer.querySelector(".wontum-current-time");s.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(s=>s.mode==="showing");t.innerHTML=`
546
566
  <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}`}
567
+ ${e.map((s,i)=>`
568
+ <div class="wontum-subtitle-option ${i===n?"active":""}" data-track="${i}">
569
+ ${s.label||s.language||`Track ${i+1}`}
550
570
  </div>
551
571
  `).join("")}
552
- `,t.querySelectorAll(".wontum-subtitle-option").forEach(i=>{i.addEventListener("click",s=>{const a=s.target,r=parseInt(a.dataset.track||"-1");r===-1?this.player.disableSubtitles():this.player.enableSubtitles(r),t.querySelectorAll(".wontum-subtitle-option").forEach(c=>c.classList.remove("active")),a.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"}
572
+ `,t.querySelectorAll(".wontum-subtitle-option").forEach(s=>{s.addEventListener("click",i=>{const a=i.target,o=parseInt(a.dataset.track||"-1");o===-1?this.player.disableSubtitles():this.player.enableSubtitles(o),t.querySelectorAll(".wontum-subtitle-option").forEach(c=>c.classList.remove("active")),a.classList.add("active")})})}updateSpeedMenu(){const t=this.controlsContainer.querySelector(".wontum-speed-menu"),n=this.player.getState().playbackRate||1,s=[.25,.5,.75,1,1.25,1.5,1.75,2];t.innerHTML=s.map(i=>`
573
+ <div class="wontum-speed-option ${n===i?"active":""}" data-speed="${i}">
574
+ ${i===1?"Normal":i+"x"}
555
575
  </div>
556
- `).join(""),t.querySelectorAll(".wontum-speed-option").forEach(s=>{s.addEventListener("click",a=>{const r=a.target,c=parseFloat(r.dataset.speed||"1");this.player.setPlaybackRate(c),t.querySelectorAll(".wontum-speed-option").forEach(u=>u.classList.remove("active")),r.classList.add("active")})})}updateSettingsMenu(){const t=this.controlsContainer.querySelector(".wontum-settings-menu");t.innerHTML=`
576
+ `).join(""),t.querySelectorAll(".wontum-speed-option").forEach(i=>{i.addEventListener("click",a=>{const o=a.target,c=parseFloat(o.dataset.speed||"1");this.player.setPlaybackRate(c),t.querySelectorAll(".wontum-speed-option").forEach(u=>u.classList.remove("active")),o.classList.add("active")})})}updateSettingsMenu(){const t=this.controlsContainer.querySelector(".wontum-settings-menu");t.innerHTML=`
557
577
  <div class="wontum-settings-option" data-setting="sticky-controls">
558
578
  <span>Sticky Controls</span>
559
579
  <div class="wontum-toggle-switch ${this.stickyControls?"active":""}"></div>
560
580
  </div>
561
581
  `;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=`
562
582
  <div class="wontum-quality-option active" data-quality="-1">Auto</div>
563
- ${n.map((i,s)=>`
564
- <div class="wontum-quality-option" data-quality="${s}">${i.name}</div>
583
+ ${n.map((s,i)=>`
584
+ <div class="wontum-quality-option" data-quality="${i}">${s.name}</div>
565
585
  `).join("")}
566
- `,e.querySelectorAll(".wontum-quality-option").forEach(i=>{i.addEventListener("click",s=>{const a=s.target,r=parseInt(a.dataset.quality||"-1");this.player.setQuality(r),e.querySelectorAll(".wontum-quality-option").forEach(c=>c.classList.remove("active")),a.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">
586
+ `,e.querySelectorAll(".wontum-quality-option").forEach(s=>{s.addEventListener("click",i=>{const a=i.target,o=parseInt(a.dataset.quality||"-1");this.player.setQuality(o),e.querySelectorAll(".wontum-quality-option").forEach(c=>c.classList.remove("active")),a.classList.add("active")})})}showControls(){this.controlsContainer.classList.remove("hidden"),this.progressContainer.classList.remove("hidden")}hideControls(){if(this.stickyControls||this.isVolumeSliderActive)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>'}getPipIcon(){return'<svg viewBox="0 0 24 24"><path d="M19 7h-8v6h8V7zm2-4H3c-1.1 0-2 .9-2 2v14c0 1.1.9 1.98 2 1.98h18c1.1 0 2-.88 2-1.98V5c0-1.1-.9-2-2-2zm0 16.01H3V4.98h18v14.03z"/></svg>'}getSkipBackwardIcon(){return`<svg viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
567
587
  <circle cx="30" cy="30" r="28" stroke="white" stroke-width="2"/>
568
588
  <!-- Circular arrow backward -->
569
589
  <path d="M30 12 A18 18 0 1 0 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
@@ -575,4 +595,4 @@
575
595
  <path d="M30 12 A18 18 0 1 1 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
576
596
  <path d="M35 12 L30 12 L30 17" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
577
597
  <text x="30" y="35" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="white" text-anchor="middle">10</text>
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,e=0){var s,a;if(this.signedUrls.has(t))return t;if((s=this.config)!=null&&s.signUrl)try{const r=await this.config.signUrl(t);return this.signedUrls.add(t),r}catch(r){const c=(r==null?void 0:r.name)==="AbortError"||((a=r==null?void 0:r.message)==null?void 0:a.includes("aborted"));if(c&&e<2)return console.warn(`Sign URL aborted, retrying (${e+1}/2)...`),await new Promise(u=>setTimeout(u,300)),this.signCloudFrontUrl(t,e+1);throw console.error("Failed to sign CloudFront URL:",r),c?new Error("Failed to sign CloudFront URL: Request was aborted. If using Apollo Client or other GraphQL clients, consider moving the query outside component lifecycle or using useQuery with skip option."):new Error(`Failed to sign CloudFront URL: ${(r==null?void 0:r.message)||"Unknown error"}`)}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 P(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 a;const s=(a=this.hls)==null?void 0:a.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 N=l=>{const{src:t,autoplay:e,muted:n,controls:i=!0,poster:s,preload:a,theme:r,s3Config:c,analytics:u,hlsConfig:g,subtitles:U,stickyControls:D,onReady:f,onPlay:k,onPause:E,onEnded:x,onTimeUpdate:S,onVolumeChange:C,onError:L,onLoadedMetadata:T,onQualityChange:q,style:z,className:H,width:v="100%",height:y="500px"}=l,w=h.useRef(null),M=h.useRef(null);return h.useEffect(()=>{if(!w.current)return;const j={src:t,container:w.current,autoplay:e,muted:n,controls:i,poster:s,preload:a,theme:r,s3Config:c,analytics:u,hlsConfig:g,subtitles:U,stickyControls:D},d=new b(j);return M.current=d,k&&d.on("play",k),E&&d.on("pause",E),x&&d.on("ended",x),L&&d.on("error",p=>{var R;return L((R=p.data)==null?void 0:R.error)}),T&&d.on("loadedmetadata",T),q&&d.on("qualitychange",p=>q(p.data.level)),S&&d.on("timeupdate",p=>S(p.data.currentTime)),C&&d.on("volumechange",p=>C(p.data.volume,p.data.muted)),f&&f(d),()=>{d.destroy(),M.current=null}},[t]),I.jsx("div",{ref:w,className:H,style:{width:typeof v=="number"?`${v}px`:v,height:typeof y=="number"?`${y}px`:y,...z}})},Q=l=>{const[t,e]=h.useState(null),[n,i]=h.useState(null),s=h.useRef(null);return h.useEffect(()=>{if(!s.current)return;const a=new b({...l,container:s.current});e(a);const r=()=>{i(a.getState())};return a.on("play",r),a.on("pause",r),a.on("timeupdate",r),a.on("volumechange",r),a.on("loadedmetadata",r),()=>{a.destroy()}},[l.src]),{containerRef:s,player:t,state:n}},A=B.createContext({player:null,state:null}),O=l=>{const{player:t,children:e}=l,[n,i]=h.useState(t.getState());return h.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(A.Provider,{value:{player:t,state:n},children:e})},Y=()=>{const l=B.useContext(A);if(!l.player)throw new Error("useWontumPlayerContext must be used within WontumPlayerProvider");return l};exports.Analytics=P;exports.S3Handler=F;exports.UIController=$;exports.WontumPlayer=b;exports.WontumPlayerProvider=O;exports.WontumPlayerReact=N;exports.useWontumPlayer=Q;exports.useWontumPlayerContext=Y;
598
+ </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){r(this,"config");r(this,"urlCache",new Map);r(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(s=>n.hostname.includes(s))}catch{return!1}}isS3Url(t){return t.includes(".s3.")||t.includes("s3.amazonaws.com")||t.startsWith("s3://")}async signCloudFrontUrl(t,e=0){var i,a;if(this.signedUrls.has(t))return t;if((i=this.config)!=null&&i.signUrl)try{const o=await this.config.signUrl(t);return this.signedUrls.add(t),o}catch(o){const c=(o==null?void 0:o.name)==="AbortError"||((a=o==null?void 0:o.message)==null?void 0:a.includes("aborted"));if(c&&e<2)return console.warn(`Sign URL aborted, retrying (${e+1}/2)...`),await new Promise(u=>setTimeout(u,300)),this.signCloudFrontUrl(t,e+1);throw console.error("Failed to sign CloudFront URL:",o),c?new Error("Failed to sign CloudFront URL: Request was aborted. If using Apollo Client or other GraphQL clients, consider moving the query outside component lifecycle or using useQuery with skip option."):new Error(`Failed to sign CloudFront URL: ${(o==null?void 0:o.message)||"Unknown error"}`)}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 s;const e=this.extractS3Key(t),n=this.urlCache.get(e);if(n&&n.expiresAt>Date.now())return n.url;if((s=this.config)!=null&&s.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,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],s=e.slice(1).join("/");return{bucket:n,key:s}}clearCache(){this.urlCache.clear(),this.signedUrls.clear()}}class b{constructor(t){r(this,"container");r(this,"videoElement");r(this,"hls",null);r(this,"config");r(this,"eventListeners",new Map);r(this,"analytics");r(this,"s3Handler");r(this,"uiController");r(this,"qualities",[]);r(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 B(t.analytics),this.s3Handler=new F(t.s3Config),this.videoElement=this.createVideoElement(),this.container.appendChild(this.videoElement),this.uiController=new A(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.crossOrigin="use-credentials",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){var e;try{const n=await this.s3Handler.processUrl(t);if(m.isSupported()){const s=((e=this.config.s3Config)==null?void 0:e.withCredentials)??!1,i={...this.config.hlsConfig,xhrSetup:(a,o)=>{var c;s&&(a.withCredentials=!0),(c=this.config.hlsConfig)!=null&&c.xhrSetup&&this.config.hlsConfig.xhrSetup(a,o)}};this.hls=new m(i),this.hls.loadSource(n),this.hls.attachMedia(this.videoElement),this.hls.on(m.Events.MANIFEST_PARSED,(a,o)=>{const c=this.extractQualities(o.levels);this.qualities=c}),this.hls.on(m.Events.LEVEL_SWITCHED,(a,o)=>{var u;const c=(u=this.hls)==null?void 0:u.levels[o.level];c&&(this.state.quality=`${c.height}p`,this.emit("qualitychange",{quality:this.state.quality}))}),this.hls.on(m.Events.ERROR,(a,o)=>{o.fatal&&this.handleHlsError(o)})}else if(this.videoElement.canPlayType("application/vnd.apple.mpegurl"))this.videoElement.src=n;else throw new Error("HLS is not supported in this browser")}catch(n){console.error("Failed to load video source:",n),this.emit("error",{error:n})}}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}))}async enterPictureInPicture(){if(document.pictureInPictureEnabled&&!this.videoElement.disablePictureInPicture)try{await this.videoElement.requestPictureInPicture(),this.emit("pictureinpictureenter",{})}catch(t){throw console.error("Failed to enter Picture-in-Picture:",t),t}}async exitPictureInPicture(){if(document.pictureInPictureElement)try{await document.exitPictureInPicture(),this.emit("pictureinpictureexit",{})}catch(t){throw console.error("Failed to exit Picture-in-Picture:",t),t}}async togglePictureInPicture(){document.pictureInPictureElement?await this.exitPictureInPicture():await this.enterPictureInPicture()}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 s;const n={type:t,data:e,timestamp:Date.now()};(s=this.eventListeners.get(t))==null||s.forEach(i=>{i(n)})}destroy(){this.hls&&(this.hls.destroy(),this.hls=null),this.uiController.destroy(),this.videoElement.remove(),this.eventListeners.clear(),this.analytics.destroy()}}const N=l=>{const{src:t,autoplay:e,muted:n,controls:s=!0,poster:i,preload:a,theme:o,s3Config:c,analytics:u,hlsConfig:g,subtitles:z,stickyControls:U,onReady:f,onPlay:k,onPause:E,onEnded:x,onTimeUpdate:S,onVolumeChange:C,onError:L,onLoadedMetadata:T,onQualityChange:P,style:H,className:D,width:v="100%",height:y="500px"}=l,w=h.useRef(null),q=h.useRef(null);return h.useEffect(()=>{if(!w.current)return;const V={src:t,container:w.current,autoplay:e,muted:n,controls:s,poster:i,preload:a,theme:o,s3Config:c,analytics:u,hlsConfig:g,subtitles:z,stickyControls:U},d=new b(V);return q.current=d,k&&d.on("play",k),E&&d.on("pause",E),x&&d.on("ended",x),L&&d.on("error",p=>{var I;return L((I=p.data)==null?void 0:I.error)}),T&&d.on("loadedmetadata",T),P&&d.on("qualitychange",p=>P(p.data.level)),S&&d.on("timeupdate",p=>S(p.data.currentTime)),C&&d.on("volumechange",p=>C(p.data.volume,p.data.muted)),f&&f(d),()=>{d.destroy(),q.current=null}},[t]),M.jsx("div",{ref:w,className:D,style:{width:typeof v=="number"?`${v}px`:v,height:typeof y=="number"?`${y}px`:y,...H}})},O=l=>{const[t,e]=h.useState(null),[n,s]=h.useState(null),i=h.useRef(null);return h.useEffect(()=>{if(!i.current)return;const a=new b({...l,container:i.current});e(a);const o=()=>{s(a.getState())};return a.on("play",o),a.on("pause",o),a.on("timeupdate",o),a.on("volumechange",o),a.on("loadedmetadata",o),()=>{a.destroy()}},[l.src]),{containerRef:i,player:t,state:n}},$=R.createContext({player:null,state:null}),Q=l=>{const{player:t,children:e}=l,[n,s]=h.useState(t.getState());return h.useEffect(()=>{const i=()=>{s(t.getState())};return t.on("play",i),t.on("pause",i),t.on("timeupdate",i),t.on("volumechange",i),t.on("loadedmetadata",i),()=>{}},[t]),M.jsx($.Provider,{value:{player:t,state:n},children:e})},Y=()=>{const l=R.useContext($);if(!l.player)throw new Error("useWontumPlayerContext must be used within WontumPlayerProvider");return l};exports.Analytics=B;exports.S3Handler=F;exports.UIController=A;exports.WontumPlayer=b;exports.WontumPlayerProvider=Q;exports.WontumPlayerReact=N;exports.useWontumPlayer=O;exports.useWontumPlayerContext=Y;