@obipascal/player 1.0.4 → 1.0.6

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
@@ -215,6 +215,75 @@ function ControlPanel() {
215
215
  }
216
216
  ```
217
217
 
218
+ ### Using with Apollo Client / GraphQL
219
+
220
+ If you're using Apollo Client or other GraphQL clients for URL signing, use `useQuery` instead of `useLazyQuery` to avoid abort errors:
221
+
222
+ ```tsx
223
+ import React from "react"
224
+ import { S3Config, WontumPlayerReact } from "@obipascal/player"
225
+ import { useQuery } from "@apollo/client"
226
+ import { GET_MEDIA_SIGNED_URL } from "@/graphql/queries/media.queries"
227
+
228
+ interface VideoPlayerProps {
229
+ videoUrl: string
230
+ }
231
+
232
+ function VideoPlayer({ videoUrl }: VideoPlayerProps) {
233
+ // ✅ Use useQuery with skip option instead of useLazyQuery
234
+ const { refetch } = useQuery(GET_MEDIA_SIGNED_URL, {
235
+ skip: true, // Don't run on mount
236
+ fetchPolicy: "no-cache", // Always fetch fresh signed URLs
237
+ })
238
+
239
+ const url = new URL(videoUrl)
240
+
241
+ const s3config: S3Config = {
242
+ cloudFrontDomains: [url.hostname],
243
+ signUrl: async (resourceUrl: string) => {
244
+ try {
245
+ const { data } = await refetch({
246
+ signingMediaInput: {
247
+ resourceUrl,
248
+ isPublic: false,
249
+ type: "COOKIES",
250
+ },
251
+ })
252
+
253
+ console.log("Signed URL result:", data)
254
+ // For cookie-based signing, return the original URL
255
+ // The server sets cookies in the response
256
+ return resourceUrl
257
+ } catch (error) {
258
+ console.error("Failed to sign URL:", error)
259
+ throw error
260
+ }
261
+ },
262
+ }
263
+
264
+ return (
265
+ <WontumPlayerReact
266
+ src={videoUrl}
267
+ width="100%"
268
+ height="500px"
269
+ autoplay={false}
270
+ controls
271
+ s3Config={s3config}
272
+ theme={{
273
+ primaryColor: "#3b82f6",
274
+ accentColor: "#60a5fa",
275
+ }}
276
+ />
277
+ )
278
+ }
279
+ ```
280
+
281
+ **Why `useQuery` with `skip` instead of `useLazyQuery`?**
282
+
283
+ - `useLazyQuery` creates a new AbortController on each call, which can be aborted during React lifecycle
284
+ - `useQuery` with `skip: true` and `refetch` persists across renders, avoiding abort issues
285
+ - The SDK includes retry logic for AbortErrors, but using `useQuery` prevents them entirely
286
+
218
287
  ## 🔒 CloudFront & S3 Integration
219
288
 
220
289
  This player supports **three video hosting scenarios**. Choose the one that fits your needs:
@@ -1,4 +1,4 @@
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=`
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=`
2
2
  .wontum-player-container {
3
3
  position: relative;
4
4
  background: #000;
@@ -6,10 +6,10 @@
6
6
  overflow: hidden;
7
7
  --primary-color: ${n};
8
8
  --accent-color: ${i};
9
- --controls-bg: ${r};
10
- --button-hover: ${l};
9
+ --controls-bg: ${a};
10
+ --button-hover: ${r};
11
11
  --progress-height: ${c};
12
- --border-radius: ${h};
12
+ --border-radius: ${u};
13
13
  }
14
14
 
15
15
  .wontum-player-video {
@@ -542,18 +542,18 @@
542
542
  <div class="wontum-loading" style="display: none;">
543
543
  <div class="wontum-spinner"></div>
544
544
  </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),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=`
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=`
546
546
  <div class="wontum-subtitle-option ${n===-1?"active":""}" data-track="-1">Off</div>
547
547
  ${e.map((i,s)=>`
548
548
  <div class="wontum-subtitle-option ${s===n?"active":""}" data-track="${s}">
549
549
  ${i.label||i.language||`Track ${s+1}`}
550
550
  </div>
551
551
  `).join("")}
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=>`
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
553
  <div class="wontum-speed-option ${n===s?"active":""}" data-speed="${s}">
554
554
  ${s===1?"Normal":s+"x"}
555
555
  </div>
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=`
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=`
557
557
  <div class="wontum-settings-option" data-setting="sticky-controls">
558
558
  <span>Sticky Controls</span>
559
559
  <div class="wontum-toggle-switch ${this.stickyControls?"active":""}"></div>
@@ -563,7 +563,7 @@
563
563
  ${n.map((i,s)=>`
564
564
  <div class="wontum-quality-option" data-quality="${s}">${i.name}</div>
565
565
  `).join("")}
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">
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">
567
567
  <circle cx="30" cy="30" r="28" stroke="white" stroke-width="2"/>
568
568
  <!-- Circular arrow backward -->
569
569
  <path d="M30 12 A18 18 0 1 0 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
@@ -575,4 +575,4 @@
575
575
  <path d="M30 12 A18 18 0 1 1 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
576
576
  <path d="M35 12 L30 12 L30 17" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
577
577
  <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){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;
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.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){try{const e=await this.s3Handler.processUrl(t);if(m.isSupported()){const n={...this.config.hlsConfig,xhrSetup:(i,s)=>{var a;i.withCredentials=!0,(a=this.config.hlsConfig)!=null&&a.xhrSetup&&this.config.hlsConfig.xhrSetup(i,s)}};this.hls=new m(n),this.hls.loadSource(e),this.hls.attachMedia(this.videoElement),this.hls.on(m.Events.MANIFEST_PARSED,(i,s)=>{const a=this.extractQualities(s.levels);this.qualities=a}),this.hls.on(m.Events.LEVEL_SWITCHED,(i,s)=>{var r;const a=(r=this.hls)==null?void 0:r.levels[s.level];a&&(this.state.quality=`${a.height}p`,this.emit("qualitychange",{quality:this.state.quality}))}),this.hls.on(m.Events.ERROR,(i,s)=>{s.fatal&&this.handleHlsError(s)})}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}})},O=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}),Q=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=Q;exports.WontumPlayerReact=N;exports.useWontumPlayer=O;exports.useWontumPlayerContext=Y;
@@ -2,10 +2,10 @@ var V = Object.defineProperty;
2
2
  var N = (l, t, e) => t in l ? V(l, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : l[t] = e;
3
3
  var o = (l, t, e) => N(l, typeof t != "symbol" ? t + "" : t, e);
4
4
  import p from "hls.js";
5
- import { jsx as $ } from "react/jsx-runtime";
6
- import * as F from "react";
5
+ import { jsx as B } from "react/jsx-runtime";
6
+ import * as $ from "react";
7
7
  import { useRef as w, useEffect as f, useState as b } from "react";
8
- class j {
8
+ class _ {
9
9
  constructor(t) {
10
10
  o(this, "config");
11
11
  o(this, "sessionId");
@@ -119,7 +119,7 @@ class j {
119
119
  (t = this.config) != null && t.enabled && this.trackEvent("session_end", this.getSessionData()), this.events = [];
120
120
  }
121
121
  }
122
- class W {
122
+ class Q {
123
123
  constructor(t, e) {
124
124
  o(this, "container");
125
125
  o(this, "player");
@@ -143,7 +143,7 @@ class W {
143
143
  injectStyles() {
144
144
  const t = "wontum-player-styles";
145
145
  if (document.getElementById(t)) return;
146
- 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)", a = e.buttonHoverBg || "rgba(255, 255, 255, 0.1)", c = e.progressHeight || "6px", d = e.borderRadius || "4px", m = document.createElement("style");
146
+ 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", m = document.createElement("style");
147
147
  m.id = t, m.textContent = `
148
148
  .wontum-player-container {
149
149
  position: relative;
@@ -152,10 +152,10 @@ class W {
152
152
  overflow: hidden;
153
153
  --primary-color: ${n};
154
154
  --accent-color: ${i};
155
- --controls-bg: ${r};
156
- --button-hover: ${a};
155
+ --controls-bg: ${a};
156
+ --button-hover: ${r};
157
157
  --progress-height: ${c};
158
- --border-radius: ${d};
158
+ --border-radius: ${u};
159
159
  }
160
160
 
161
161
  .wontum-player-video {
@@ -706,8 +706,8 @@ class W {
706
706
  }), this.skipForwardButton.addEventListener("click", () => {
707
707
  this.player.skipForward(10);
708
708
  }), this.progressInput.addEventListener("input", (n) => {
709
- const i = n.target, s = parseFloat(i.value), r = this.player.getState(), a = s / 100 * r.duration;
710
- this.player.seek(a);
709
+ const i = n.target, s = parseFloat(i.value), a = this.player.getState(), r = s / 100 * a.duration;
710
+ this.player.seek(r);
711
711
  }), this.volumeSlider.addEventListener("input", (n) => {
712
712
  const i = n.target, s = parseFloat(i.value) / 100;
713
713
  this.player.setVolume(s);
@@ -722,9 +722,9 @@ class W {
722
722
  const t = this.controlsContainer.querySelectorAll(".wontum-tab");
723
723
  t.forEach((n) => {
724
724
  n.addEventListener("click", (i) => {
725
- const s = i.currentTarget, r = s.getAttribute("data-tab");
726
- t.forEach((d) => d.classList.remove("active")), s.classList.add("active"), this.controlsContainer.querySelectorAll(".wontum-tab-panel").forEach((d) => d.classList.remove("active"));
727
- const c = this.controlsContainer.querySelector(`[data-panel="${r}"]`);
725
+ const s = i.currentTarget, a = s.getAttribute("data-tab");
726
+ t.forEach((u) => u.classList.remove("active")), s.classList.add("active"), this.controlsContainer.querySelectorAll(".wontum-tab-panel").forEach((u) => u.classList.remove("active"));
727
+ const c = this.controlsContainer.querySelector(`[data-panel="${a}"]`);
728
728
  c == null || c.classList.add("active");
729
729
  });
730
730
  }), this.player.getVideoElement().addEventListener("click", () => {
@@ -780,8 +780,8 @@ class W {
780
780
  ).join("")}
781
781
  `, t.querySelectorAll(".wontum-subtitle-option").forEach((i) => {
782
782
  i.addEventListener("click", (s) => {
783
- const r = s.target, a = parseInt(r.dataset.track || "-1");
784
- a === -1 ? this.player.disableSubtitles() : this.player.enableSubtitles(a), t.querySelectorAll(".wontum-subtitle-option").forEach((c) => c.classList.remove("active")), r.classList.add("active");
783
+ const a = s.target, r = parseInt(a.dataset.track || "-1");
784
+ r === -1 ? this.player.disableSubtitles() : this.player.enableSubtitles(r), t.querySelectorAll(".wontum-subtitle-option").forEach((c) => c.classList.remove("active")), a.classList.add("active");
785
785
  });
786
786
  });
787
787
  }
@@ -794,9 +794,9 @@ class W {
794
794
  </div>
795
795
  `
796
796
  ).join(""), t.querySelectorAll(".wontum-speed-option").forEach((s) => {
797
- s.addEventListener("click", (r) => {
798
- const a = r.target, c = parseFloat(a.dataset.speed || "1");
799
- this.player.setPlaybackRate(c), t.querySelectorAll(".wontum-speed-option").forEach((d) => d.classList.remove("active")), a.classList.add("active");
797
+ s.addEventListener("click", (a) => {
798
+ const r = a.target, c = parseFloat(r.dataset.speed || "1");
799
+ this.player.setPlaybackRate(c), t.querySelectorAll(".wontum-speed-option").forEach((u) => u.classList.remove("active")), r.classList.add("active");
800
800
  });
801
801
  });
802
802
  }
@@ -828,8 +828,8 @@ class W {
828
828
  ).join("")}
829
829
  `, e.querySelectorAll(".wontum-quality-option").forEach((i) => {
830
830
  i.addEventListener("click", (s) => {
831
- const r = s.target, a = parseInt(r.dataset.quality || "-1");
832
- this.player.setQuality(a), e.querySelectorAll(".wontum-quality-option").forEach((c) => c.classList.remove("active")), r.classList.add("active");
831
+ const a = s.target, r = parseInt(a.dataset.quality || "-1");
832
+ this.player.setQuality(r), e.querySelectorAll(".wontum-quality-option").forEach((c) => c.classList.remove("active")), a.classList.add("active");
833
833
  });
834
834
  });
835
835
  }
@@ -891,7 +891,7 @@ class W {
891
891
  this.hideControlsTimeout && clearTimeout(this.hideControlsTimeout), this.controlsContainer.remove();
892
892
  }
893
893
  }
894
- class Q {
894
+ class j {
895
895
  constructor(t) {
896
896
  o(this, "config");
897
897
  o(this, "urlCache", /* @__PURE__ */ new Map());
@@ -928,16 +928,21 @@ class Q {
928
928
  * Sign CloudFront URL by calling the signing endpoint
929
929
  * The endpoint should set signed cookies and return the URL
930
930
  */
931
- async signCloudFrontUrl(t) {
932
- var e;
931
+ async signCloudFrontUrl(t, e = 0) {
932
+ var s, a;
933
933
  if (this.signedUrls.has(t))
934
934
  return t;
935
- if ((e = this.config) != null && e.signUrl)
935
+ if ((s = this.config) != null && s.signUrl)
936
936
  try {
937
- const n = await this.config.signUrl(t);
938
- return this.signedUrls.add(t), n;
939
- } catch (n) {
940
- throw console.error("Failed to sign CloudFront URL:", n), new Error("Failed to sign CloudFront URL");
937
+ const r = await this.config.signUrl(t);
938
+ return this.signedUrls.add(t), r;
939
+ } catch (r) {
940
+ const c = (r == null ? void 0 : r.name) === "AbortError" || ((a = r == null ? void 0 : r.message) == null ? void 0 : a.includes("aborted"));
941
+ if (c && e < 2)
942
+ return console.warn(`Sign URL aborted, retrying (${e + 1}/2)...`), await new Promise((u) => setTimeout(u, 300)), this.signCloudFrontUrl(t, e + 1);
943
+ throw console.error("Failed to sign CloudFront URL:", r), c ? new Error(
944
+ "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."
945
+ ) : new Error(`Failed to sign CloudFront URL: ${(r == null ? void 0 : r.message) || "Unknown error"}`);
941
946
  }
942
947
  return console.warn("No signUrl function provided. CloudFront cookies may not be set."), t;
943
948
  }
@@ -995,7 +1000,7 @@ class Q {
995
1000
  this.urlCache.clear(), this.signedUrls.clear();
996
1001
  }
997
1002
  }
998
- class R {
1003
+ class F {
999
1004
  constructor(t) {
1000
1005
  o(this, "container");
1001
1006
  o(this, "videoElement");
@@ -1022,7 +1027,7 @@ class R {
1022
1027
  });
1023
1028
  if (this.config = t, this.container = typeof t.container == "string" ? document.querySelector(t.container) : t.container, !this.container)
1024
1029
  throw new Error("Container element not found");
1025
- this.analytics = new j(t.analytics), this.s3Handler = new Q(t.s3Config), this.videoElement = this.createVideoElement(), this.container.appendChild(this.videoElement), this.uiController = new W(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);
1030
+ this.analytics = new _(t.analytics), this.s3Handler = new j(t.s3Config), this.videoElement = this.createVideoElement(), this.container.appendChild(this.videoElement), this.uiController = new Q(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);
1026
1031
  }
1027
1032
  addSubtitleTracks(t) {
1028
1033
  t.forEach((e) => {
@@ -1032,7 +1037,7 @@ class R {
1032
1037
  }
1033
1038
  createVideoElement() {
1034
1039
  const t = document.createElement("video");
1035
- return t.className = "wontum-player-video", t.style.width = "100%", t.style.height = "100%", t.playsInline = !0, t;
1040
+ return t.className = "wontum-player-video", t.style.width = "100%", t.style.height = "100%", t.playsInline = !0, t.crossOrigin = "use-credentials", t;
1036
1041
  }
1037
1042
  setupVideoListeners() {
1038
1043
  this.videoElement.addEventListener("play", () => {
@@ -1090,18 +1095,25 @@ class R {
1090
1095
  async loadSource(t) {
1091
1096
  try {
1092
1097
  const e = await this.s3Handler.processUrl(t);
1093
- if (p.isSupported())
1094
- this.hls = new p(this.config.hlsConfig), this.hls.loadSource(e), this.hls.attachMedia(this.videoElement), this.hls.on(p.Events.MANIFEST_PARSED, (n, i) => {
1095
- const s = this.extractQualities(i.levels);
1096
- this.qualities = s;
1097
- }), this.hls.on(p.Events.LEVEL_SWITCHED, (n, i) => {
1098
+ if (p.isSupported()) {
1099
+ const n = {
1100
+ ...this.config.hlsConfig,
1101
+ xhrSetup: (i, s) => {
1102
+ var a;
1103
+ i.withCredentials = !0, (a = this.config.hlsConfig) != null && a.xhrSetup && this.config.hlsConfig.xhrSetup(i, s);
1104
+ }
1105
+ };
1106
+ this.hls = new p(n), this.hls.loadSource(e), this.hls.attachMedia(this.videoElement), this.hls.on(p.Events.MANIFEST_PARSED, (i, s) => {
1107
+ const a = this.extractQualities(s.levels);
1108
+ this.qualities = a;
1109
+ }), this.hls.on(p.Events.LEVEL_SWITCHED, (i, s) => {
1098
1110
  var r;
1099
- const s = (r = this.hls) == null ? void 0 : r.levels[i.level];
1100
- s && (this.state.quality = `${s.height}p`, this.emit("qualitychange", { quality: this.state.quality }));
1101
- }), this.hls.on(p.Events.ERROR, (n, i) => {
1102
- i.fatal && this.handleHlsError(i);
1111
+ const a = (r = this.hls) == null ? void 0 : r.levels[s.level];
1112
+ a && (this.state.quality = `${a.height}p`, this.emit("qualitychange", { quality: this.state.quality }));
1113
+ }), this.hls.on(p.Events.ERROR, (i, s) => {
1114
+ s.fatal && this.handleHlsError(s);
1103
1115
  });
1104
- else if (this.videoElement.canPlayType("application/vnd.apple.mpegurl"))
1116
+ } else if (this.videoElement.canPlayType("application/vnd.apple.mpegurl"))
1105
1117
  this.videoElement.src = e;
1106
1118
  else
1107
1119
  throw new Error("HLS is not supported in this browser");
@@ -1247,20 +1259,20 @@ class R {
1247
1259
  this.hls && (this.hls.destroy(), this.hls = null), this.uiController.destroy(), this.videoElement.remove(), this.eventListeners.clear(), this.analytics.destroy();
1248
1260
  }
1249
1261
  }
1250
- const X = (l) => {
1262
+ const K = (l) => {
1251
1263
  const {
1252
1264
  src: t,
1253
1265
  autoplay: e,
1254
1266
  muted: n,
1255
1267
  controls: i = !0,
1256
1268
  poster: s,
1257
- preload: r,
1258
- theme: a,
1269
+ preload: a,
1270
+ theme: r,
1259
1271
  s3Config: c,
1260
- analytics: d,
1272
+ analytics: u,
1261
1273
  hlsConfig: m,
1262
- subtitles: z,
1263
- stickyControls: A,
1274
+ subtitles: P,
1275
+ stickyControls: U,
1264
1276
  onReady: k,
1265
1277
  onPlay: E,
1266
1278
  onPause: x,
@@ -1270,43 +1282,43 @@ const X = (l) => {
1270
1282
  onError: T,
1271
1283
  onLoadedMetadata: q,
1272
1284
  onQualityChange: M,
1273
- style: H,
1274
- className: U,
1285
+ style: z,
1286
+ className: D,
1275
1287
  width: g = "100%",
1276
1288
  height: v = "500px"
1277
- } = l, y = w(null), B = w(null);
1289
+ } = l, y = w(null), R = w(null);
1278
1290
  return f(() => {
1279
1291
  if (!y.current) return;
1280
- const D = {
1292
+ const H = {
1281
1293
  src: t,
1282
1294
  container: y.current,
1283
1295
  autoplay: e,
1284
1296
  muted: n,
1285
1297
  controls: i,
1286
1298
  poster: s,
1287
- preload: r,
1288
- theme: a,
1299
+ preload: a,
1300
+ theme: r,
1289
1301
  s3Config: c,
1290
- analytics: d,
1302
+ analytics: u,
1291
1303
  hlsConfig: m,
1292
- subtitles: z,
1293
- stickyControls: A
1294
- }, u = new R(D);
1295
- return B.current = u, E && u.on("play", E), x && u.on("pause", x), S && u.on("ended", S), T && u.on("error", (h) => {
1304
+ subtitles: P,
1305
+ stickyControls: U
1306
+ }, d = new F(H);
1307
+ return R.current = d, E && d.on("play", E), x && d.on("pause", x), S && d.on("ended", S), T && d.on("error", (h) => {
1296
1308
  var I;
1297
1309
  return T((I = h.data) == null ? void 0 : I.error);
1298
- }), q && u.on("loadedmetadata", q), M && u.on("qualitychange", (h) => M(h.data.level)), C && u.on("timeupdate", (h) => C(h.data.currentTime)), L && u.on("volumechange", (h) => L(h.data.volume, h.data.muted)), k && k(u), () => {
1299
- u.destroy(), B.current = null;
1310
+ }), q && d.on("loadedmetadata", q), M && d.on("qualitychange", (h) => M(h.data.level)), C && d.on("timeupdate", (h) => C(h.data.currentTime)), L && d.on("volumechange", (h) => L(h.data.volume, h.data.muted)), k && k(d), () => {
1311
+ d.destroy(), R.current = null;
1300
1312
  };
1301
- }, [t]), /* @__PURE__ */ $(
1313
+ }, [t]), /* @__PURE__ */ B(
1302
1314
  "div",
1303
1315
  {
1304
1316
  ref: y,
1305
- className: U,
1317
+ className: D,
1306
1318
  style: {
1307
1319
  width: typeof g == "number" ? `${g}px` : g,
1308
1320
  height: typeof v == "number" ? `${v}px` : v,
1309
- ...H
1321
+ ...z
1310
1322
  }
1311
1323
  }
1312
1324
  );
@@ -1314,23 +1326,23 @@ const X = (l) => {
1314
1326
  const [t, e] = b(null), [n, i] = b(null), s = w(null);
1315
1327
  return f(() => {
1316
1328
  if (!s.current) return;
1317
- const r = new R({
1329
+ const a = new F({
1318
1330
  ...l,
1319
1331
  container: s.current
1320
1332
  });
1321
- e(r);
1322
- const a = () => {
1323
- i(r.getState());
1333
+ e(a);
1334
+ const r = () => {
1335
+ i(a.getState());
1324
1336
  };
1325
- return r.on("play", a), r.on("pause", a), r.on("timeupdate", a), r.on("volumechange", a), r.on("loadedmetadata", a), () => {
1326
- r.destroy();
1337
+ return a.on("play", r), a.on("pause", r), a.on("timeupdate", r), a.on("volumechange", r), a.on("loadedmetadata", r), () => {
1338
+ a.destroy();
1327
1339
  };
1328
1340
  }, [l.src]), {
1329
1341
  containerRef: s,
1330
1342
  player: t,
1331
1343
  state: n
1332
1344
  };
1333
- }, P = F.createContext({
1345
+ }, A = $.createContext({
1334
1346
  player: null,
1335
1347
  state: null
1336
1348
  }), J = (l) => {
@@ -1341,20 +1353,20 @@ const X = (l) => {
1341
1353
  };
1342
1354
  return t.on("play", s), t.on("pause", s), t.on("timeupdate", s), t.on("volumechange", s), t.on("loadedmetadata", s), () => {
1343
1355
  };
1344
- }, [t]), /* @__PURE__ */ $(P.Provider, { value: { player: t, state: n }, children: e });
1356
+ }, [t]), /* @__PURE__ */ B(A.Provider, { value: { player: t, state: n }, children: e });
1345
1357
  }, Z = () => {
1346
- const l = F.useContext(P);
1358
+ const l = $.useContext(A);
1347
1359
  if (!l.player)
1348
1360
  throw new Error("useWontumPlayerContext must be used within WontumPlayerProvider");
1349
1361
  return l;
1350
1362
  };
1351
1363
  export {
1352
- j as Analytics,
1353
- Q as S3Handler,
1354
- W as UIController,
1355
- R as WontumPlayer,
1364
+ _ as Analytics,
1365
+ j as S3Handler,
1366
+ Q as UIController,
1367
+ F as WontumPlayer,
1356
1368
  J as WontumPlayerProvider,
1357
- X as WontumPlayerReact,
1369
+ K as WontumPlayerReact,
1358
1370
  G as useWontumPlayer,
1359
1371
  Z as useWontumPlayerContext
1360
1372
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obipascal/player",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "A modern HLS video player SDK for educational platforms with S3 integration",
5
5
  "main": "dist/wontum-player.cjs.js",
6
6
  "module": "dist/wontum-player.esm.js",