@obipascal/player 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1626 @@
1
+ var at = Object.defineProperty;
2
+ var lt = (c, t, e) => t in c ? at(c, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : c[t] = e;
3
+ var o = (c, t, e) => lt(c, typeof t != "symbol" ? t + "" : t, e);
4
+ import w from "hls.js";
5
+ import Y, { useRef as U, useEffect as $, useState as V } from "react";
6
+ class ct {
7
+ constructor(t) {
8
+ o(this, "config");
9
+ o(this, "sessionId");
10
+ o(this, "events", []);
11
+ o(this, "sessionStartTime");
12
+ o(this, "playbackStartTime", null);
13
+ o(this, "totalPlayTime", 0);
14
+ o(this, "totalBufferTime", 0);
15
+ o(this, "bufferStartTime", null);
16
+ o(this, "rebufferCount", 0);
17
+ o(this, "seekCount", 0);
18
+ var e;
19
+ 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());
20
+ }
21
+ trackEvent(t, e = {}) {
22
+ var r;
23
+ if (!((r = this.config) != null && r.enabled)) return;
24
+ const s = {
25
+ eventType: t,
26
+ timestamp: Date.now(),
27
+ sessionId: this.sessionId,
28
+ videoId: this.config.videoId,
29
+ userId: this.config.userId,
30
+ data: {
31
+ ...e,
32
+ ...this.getQoEMetrics()
33
+ }
34
+ };
35
+ this.events.push(s), this.updateMetrics(t, e), this.config.endpoint && this.sendEvent(s), process.env.NODE_ENV === "development" && console.log("[Analytics]", t, s.data);
36
+ }
37
+ updateMetrics(t, e) {
38
+ switch (t) {
39
+ case "play":
40
+ this.playbackStartTime = Date.now();
41
+ break;
42
+ case "pause":
43
+ case "ended":
44
+ this.playbackStartTime && (this.totalPlayTime += Date.now() - this.playbackStartTime, this.playbackStartTime = null);
45
+ break;
46
+ case "buffering_start":
47
+ this.bufferStartTime = Date.now(), this.rebufferCount++;
48
+ break;
49
+ case "buffering_end":
50
+ this.bufferStartTime && (this.totalBufferTime += Date.now() - this.bufferStartTime, this.bufferStartTime = null);
51
+ break;
52
+ case "seeked":
53
+ this.seekCount++;
54
+ break;
55
+ }
56
+ }
57
+ getQoEMetrics() {
58
+ const t = Date.now() - this.sessionStartTime, e = this.totalPlayTime > 0 ? this.totalBufferTime / this.totalPlayTime : 0;
59
+ return {
60
+ sessionDuration: t,
61
+ totalPlayTime: this.totalPlayTime,
62
+ totalBufferTime: this.totalBufferTime,
63
+ bufferingRatio: Math.round(e * 1e3) / 1e3,
64
+ rebufferCount: this.rebufferCount,
65
+ seekCount: this.seekCount
66
+ };
67
+ }
68
+ getSessionData() {
69
+ return {
70
+ userAgent: navigator.userAgent,
71
+ platform: navigator.platform,
72
+ language: navigator.language,
73
+ screenResolution: `${screen.width}x${screen.height}`,
74
+ viewport: `${window.innerWidth}x${window.innerHeight}`,
75
+ connection: this.getConnectionInfo()
76
+ };
77
+ }
78
+ getConnectionInfo() {
79
+ const t = navigator, e = t.connection || t.mozConnection || t.webkitConnection;
80
+ return e ? {
81
+ effectiveType: e.effectiveType,
82
+ downlink: e.downlink,
83
+ rtt: e.rtt,
84
+ saveData: e.saveData
85
+ } : null;
86
+ }
87
+ async sendEvent(t) {
88
+ var e;
89
+ if ((e = this.config) != null && e.endpoint)
90
+ try {
91
+ await fetch(this.config.endpoint, {
92
+ method: "POST",
93
+ headers: {
94
+ "Content-Type": "application/json"
95
+ },
96
+ body: JSON.stringify(t)
97
+ });
98
+ } catch (s) {
99
+ console.error("Failed to send analytics event:", s);
100
+ }
101
+ }
102
+ generateSessionId() {
103
+ return `session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
104
+ }
105
+ getEvents() {
106
+ return [...this.events];
107
+ }
108
+ getMetrics() {
109
+ return {
110
+ sessionId: this.sessionId,
111
+ ...this.getQoEMetrics(),
112
+ eventCount: this.events.length
113
+ };
114
+ }
115
+ destroy() {
116
+ var t;
117
+ (t = this.config) != null && t.enabled && this.trackEvent("session_end", this.getSessionData()), this.events = [];
118
+ }
119
+ }
120
+ class ut {
121
+ constructor(t, e) {
122
+ o(this, "container");
123
+ o(this, "player");
124
+ o(this, "controlsContainer");
125
+ o(this, "progressContainer");
126
+ o(this, "progressBar");
127
+ o(this, "playButton");
128
+ o(this, "skipBackwardButton");
129
+ o(this, "skipForwardButton");
130
+ o(this, "volumeButton");
131
+ o(this, "fullscreenButton");
132
+ o(this, "qualityButton");
133
+ o(this, "subtitleButton");
134
+ o(this, "speedButton");
135
+ o(this, "settingsButton");
136
+ // private timeDisplay: HTMLElement
137
+ o(this, "volumeSlider");
138
+ o(this, "progressInput");
139
+ // private controlsVisible = true
140
+ o(this, "hideControlsTimeout", null);
141
+ o(this, "stickyControls", !1);
142
+ this.container = t, this.player = e, this.injectStyles(), this.createProgressBar(), this.controlsContainer = this.createControls(), this.container.appendChild(this.controlsContainer), this.playButton = this.controlsContainer.querySelector(".wontum-play-btn"), this.skipBackwardButton = this.controlsContainer.querySelector(".wontum-skip-backward-btn"), this.skipForwardButton = this.controlsContainer.querySelector(".wontum-skip-forward-btn"), this.volumeButton = this.controlsContainer.querySelector(".wontum-volume-btn"), this.fullscreenButton = this.controlsContainer.querySelector(".wontum-fullscreen-btn"), this.qualityButton = this.controlsContainer.querySelector(".wontum-quality-btn"), this.subtitleButton = this.controlsContainer.querySelector(".wontum-subtitle-btn"), this.speedButton = this.controlsContainer.querySelector(".wontum-speed-btn"), this.settingsButton = this.controlsContainer.querySelector(".wontum-settings-btn"), this.volumeSlider = this.controlsContainer.querySelector(".wontum-volume-slider"), this.progressInput = this.container.querySelector(".wontum-progress-input"), this.progressBar = this.container.querySelector(".wontum-progress-filled"), this.stickyControls = this.player.config.stickyControls || !1, this.stickyControls && this.controlsContainer.classList.add("sticky"), this.setupEventListeners(), this.setupPlayerEventListeners();
143
+ }
144
+ injectStyles() {
145
+ const t = "wontum-player-styles";
146
+ if (document.getElementById(t)) return;
147
+ const e = this.player.config.theme || {}, s = e.primaryColor || "#3b82f6", r = e.accentColor || "#2563eb", i = e.fontFamily || "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif", l = e.controlsBackground || "linear-gradient(to top, rgba(0,0,0,0.8), transparent)", u = e.buttonHoverBg || "rgba(255, 255, 255, 0.1)", v = e.progressHeight || "6px", y = e.borderRadius || "4px", g = document.createElement("style");
148
+ g.id = t, g.textContent = `
149
+ .wontum-player-container {
150
+ position: relative;
151
+ background: #000;
152
+ font-family: ${i};
153
+ overflow: hidden;
154
+ --primary-color: ${s};
155
+ --accent-color: ${r};
156
+ --controls-bg: ${l};
157
+ --button-hover: ${u};
158
+ --progress-height: ${v};
159
+ --border-radius: ${y};
160
+ }
161
+
162
+ .wontum-player-video {
163
+ display: block;
164
+ width: 100%;
165
+ height: 100%;
166
+ }
167
+
168
+ .wontum-controls {
169
+ position: absolute;
170
+ bottom: 0;
171
+ left: 0;
172
+ right: 0;
173
+ background: linear-gradient(to top, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.6) 50%, transparent 100%);
174
+ padding: 15px 20px 12px;
175
+ transition: opacity 0.3s ease, transform 0.3s ease;
176
+ z-index: 10;
177
+ }
178
+
179
+ .wontum-controls.hidden {
180
+ opacity: 0;
181
+ transform: translateY(100%);
182
+ pointer-events: none;
183
+ }
184
+
185
+ .wontum-center-controls {
186
+ position: absolute;
187
+ bottom: 80px;
188
+ left: 50%;
189
+ transform: translateX(-50%);
190
+ display: flex;
191
+ align-items: center;
192
+ gap: 120px;
193
+ z-index: 15;
194
+ opacity: 0;
195
+ transition: opacity 0.3s ease;
196
+ }
197
+
198
+ .wontum-player-container:hover .wontum-center-controls {
199
+ opacity: 1;
200
+ }
201
+
202
+ .wontum-center-btn {
203
+ background: rgba(0, 0, 0, 0.75);
204
+ border: none;
205
+ color: white;
206
+ cursor: pointer;
207
+ padding: 0;
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ border-radius: 50%;
212
+ transition: all 0.2s ease;
213
+ backdrop-filter: blur(10px);
214
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
215
+ }
216
+
217
+ .wontum-center-btn:hover {
218
+ background: rgba(255, 255, 255, 0.25);
219
+ transform: scale(1.08);
220
+ box-shadow: 0 6px 16px rgba(0, 0, 0, 0.5);
221
+ }
222
+
223
+ .wontum-center-btn:active {
224
+ transform: scale(0.95);
225
+ }
226
+
227
+ .wontum-center-btn.play {
228
+ width: 80px;
229
+ height: 80px;
230
+ }
231
+
232
+ .wontum-center-btn.play svg {
233
+ width: 40px;
234
+ height: 40px;
235
+ }
236
+
237
+ .wontum-center-btn.skip {
238
+ width: 70px;
239
+ height: 70px;
240
+ }
241
+
242
+ .wontum-center-btn.skip svg {
243
+ width: 70px;
244
+ height: 70px;
245
+ }
246
+
247
+ .wontum-progress-container {
248
+ position: absolute;
249
+ bottom: 58px;
250
+ left: 0;
251
+ right: 0;
252
+ height: 5px;
253
+ cursor: pointer;
254
+ z-index: 12;
255
+ padding: 0 20px;
256
+ transition: height 0.2s ease, opacity 0.3s ease, transform 0.3s ease;
257
+ }
258
+
259
+ .wontum-progress-container.hidden {
260
+ opacity: 0;
261
+ transform: translateY(100%);
262
+ pointer-events: none;
263
+ }
264
+
265
+ .wontum-progress-container:hover {
266
+ height: 7px;
267
+ }
268
+
269
+ .wontum-progress-track {
270
+ position: absolute;
271
+ width: 100%;
272
+ height: 100%;
273
+ background: rgba(255, 255, 255, 0.25);
274
+ border-radius: 3px;
275
+ }
276
+
277
+ .wontum-progress-filled {
278
+ position: absolute;
279
+ height: 100%;
280
+ background: var(--primary-color);
281
+ border-radius: 3px;
282
+ width: 0%;
283
+ transition: width 0.1s linear;
284
+ box-shadow: 0 0 8px rgba(255, 255, 255, 0.3);
285
+ }
286
+
287
+ .wontum-progress-input {
288
+ position: absolute;
289
+ width: 100%;
290
+ height: 100%;
291
+ opacity: 0;
292
+ cursor: pointer;
293
+ margin: 0;
294
+ }
295
+
296
+ .wontum-controls-row {
297
+ display: flex;
298
+ align-items: center;
299
+ gap: 12px;
300
+ color: white;
301
+ height: 36px;
302
+ }
303
+
304
+ .wontum-btn {
305
+ background: none;
306
+ border: none;
307
+ color: white;
308
+ cursor: pointer;
309
+ padding: 6px;
310
+ display: flex;
311
+ align-items: center;
312
+ justify-content: center;
313
+ border-radius: 4px;
314
+ transition: all 0.2s ease;
315
+ opacity: 0.9;
316
+ }
317
+
318
+ .wontum-btn:hover {
319
+ background: rgba(255, 255, 255, 0.15);
320
+ opacity: 1;
321
+ transform: scale(1.05);
322
+ }
323
+
324
+ .wontum-btn:active {
325
+ transform: scale(0.95);
326
+ }
327
+
328
+ .wontum-btn svg {
329
+ width: 24px;
330
+ height: 24px;
331
+ fill: currentColor;
332
+ }
333
+
334
+ .wontum-time-display {
335
+ font-size: 13px;
336
+ font-variant-numeric: tabular-nums;
337
+ font-weight: 500;
338
+ min-width: 100px;
339
+ opacity: 0.95;
340
+ letter-spacing: 0.3px;
341
+ }
342
+
343
+ .wontum-volume-container {
344
+ position: relative;
345
+ display: flex;
346
+ align-items: center;
347
+ }
348
+
349
+ .wontum-volume-slider-wrapper {
350
+ position: absolute;
351
+ bottom: 100%;
352
+ left: 50%;
353
+ transform: translateX(-50%);
354
+ background: rgba(20, 20, 20, 0.95);
355
+ backdrop-filter: blur(10px);
356
+ padding: 12px 8px;
357
+ border-radius: 6px;
358
+ margin-bottom: 8px;
359
+ opacity: 0;
360
+ pointer-events: none;
361
+ transition: opacity 0.2s ease;
362
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
363
+ }
364
+
365
+ .wontum-volume-container:hover .wontum-volume-slider-wrapper {
366
+ opacity: 1;
367
+ pointer-events: all;
368
+ }
369
+
370
+ .wontum-volume-slider {
371
+ -webkit-appearance: slider-vertical;
372
+ appearance: slider-vertical;
373
+ width: 4px;
374
+ height: 80px;
375
+ background: rgba(255, 255, 255, 0.3);
376
+ border-radius: 2px;
377
+ outline: none;
378
+ writing-mode: bt-lr;
379
+ cursor: pointer;
380
+ }
381
+
382
+ .wontum-volume-slider::-webkit-slider-thumb {
383
+ -webkit-appearance: none;
384
+ appearance: none;
385
+ width: 12px;
386
+ height: 12px;
387
+ background: var(--primary-color);
388
+ border-radius: 50%;
389
+ cursor: pointer;
390
+ }
391
+
392
+ .wontum-volume-slider::-moz-range-thumb {
393
+ width: 12px;
394
+ height: 12px;
395
+ background: var(--primary-color);
396
+ border-radius: 50%;
397
+ cursor: pointer;
398
+ border: none;
399
+ }
400
+
401
+ .wontum-spacer {
402
+ flex: 1;
403
+ }
404
+
405
+ .wontum-loading {
406
+ position: absolute;
407
+ top: 50%;
408
+ left: 50%;
409
+ transform: translate(-50%, -50%);
410
+ z-index: 5;
411
+ }
412
+
413
+ .wontum-spinner {
414
+ border: 4px solid rgba(255, 255, 255, 0.3);
415
+ border-top: 4px solid white;
416
+ border-radius: 50%;
417
+ width: 50px;
418
+ height: 50px;
419
+ animation: wontum-spin 1s linear infinite;
420
+ }
421
+
422
+ @keyframes wontum-spin {
423
+ 0% { transform: rotate(0deg); }
424
+ 100% { transform: rotate(360deg); }
425
+ }
426
+
427
+ .wontum-quality-menu {
428
+ position: absolute;
429
+ bottom: 100%;
430
+ right: 0;
431
+ background: rgba(20, 20, 20, 0.95);
432
+ backdrop-filter: blur(10px);
433
+ border-radius: 6px;
434
+ padding: 6px 0;
435
+ margin-bottom: 8px;
436
+ display: none;
437
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
438
+ min-width: 120px;
439
+ }
440
+
441
+ .wontum-quality-menu.active {
442
+ display: block;
443
+ }
444
+
445
+ .wontum-quality-option {
446
+ padding: 10px 16px;
447
+ cursor: pointer;
448
+ white-space: nowrap;
449
+ color: rgba(255, 255, 255, 0.9);
450
+ font-size: 13px;
451
+ transition: all 0.15s ease;
452
+ }
453
+
454
+ .wontum-quality-option:hover {
455
+ background: rgba(255, 255, 255, 0.12);
456
+ color: white;
457
+ }
458
+
459
+ .wontum-quality-option.active {
460
+ color: var(--primary-color);
461
+ background: rgba(255, 255, 255, 0.05);
462
+ }
463
+
464
+ .wontum-speed-menu {
465
+ position: absolute;
466
+ bottom: 100%;
467
+ right: 0;
468
+ background: rgba(20, 20, 20, 0.95);
469
+ backdrop-filter: blur(10px);
470
+ border-radius: 6px;
471
+ padding: 6px 0;
472
+ margin-bottom: 8px;
473
+ display: none;
474
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
475
+ min-width: 120px;
476
+ }
477
+
478
+ .wontum-speed-menu.active {
479
+ display: block;
480
+ }
481
+
482
+ .wontum-speed-option {
483
+ padding: 10px 16px;
484
+ cursor: pointer;
485
+ white-space: nowrap;
486
+ color: rgba(255, 255, 255, 0.9);
487
+ font-size: 13px;
488
+ transition: all 0.15s ease;
489
+ }
490
+
491
+ .wontum-speed-option:hover {
492
+ background: rgba(255, 255, 255, 0.12);
493
+ color: white;
494
+ }
495
+
496
+ .wontum-speed-option.active {
497
+ color: var(--primary-color);
498
+ background: rgba(255, 255, 255, 0.05);
499
+ }
500
+
501
+ .wontum-settings-menu {
502
+ position: absolute;
503
+ bottom: 100%;
504
+ right: 0;
505
+ background: rgba(20, 20, 20, 0.95);
506
+ backdrop-filter: blur(10px);
507
+ border-radius: 6px;
508
+ padding: 6px 0;
509
+ margin-bottom: 8px;
510
+ min-width: 200px;
511
+ display: none;
512
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
513
+ }
514
+
515
+ .wontum-settings-menu.active {
516
+ display: block;
517
+ }
518
+
519
+ .wontum-settings-option {
520
+ padding: 12px 16px;
521
+ cursor: pointer;
522
+ white-space: nowrap;
523
+ color: rgba(255, 255, 255, 0.9);
524
+ font-size: 13px;
525
+ display: flex;
526
+ align-items: center;
527
+ justify-content: space-between;
528
+ transition: all 0.15s ease;
529
+ }
530
+
531
+ .wontum-settings-option:hover {
532
+ background: rgba(255, 255, 255, 0.12);
533
+ color: white;
534
+ }
535
+
536
+ .wontum-toggle-switch {
537
+ width: 40px;
538
+ height: 20px;
539
+ background: rgba(255, 255, 255, 0.3);
540
+ border-radius: 10px;
541
+ position: relative;
542
+ transition: background 0.3s;
543
+ }
544
+
545
+ .wontum-toggle-switch.active {
546
+ background: var(--primary-color);
547
+ }
548
+
549
+ .wontum-toggle-switch::after {
550
+ content: '';
551
+ position: absolute;
552
+ width: 16px;
553
+ height: 16px;
554
+ background: white;
555
+ border-radius: 50%;
556
+ top: 2px;
557
+ left: 2px;
558
+ transition: left 0.3s;
559
+ }
560
+
561
+ .wontum-toggle-switch.active::after {
562
+ left: 22px;
563
+ }
564
+
565
+ .wontum-subtitle-menu {
566
+ position: absolute;
567
+ bottom: 100%;
568
+ right: 0;
569
+ background: rgba(20, 20, 20, 0.95);
570
+ backdrop-filter: blur(10px);
571
+ border-radius: 6px;
572
+ padding: 6px 0;
573
+ margin-bottom: 8px;
574
+ display: none;
575
+ min-width: 150px;
576
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
577
+ }
578
+
579
+ .wontum-subtitle-menu.active {
580
+ display: block;
581
+ }
582
+
583
+ .wontum-subtitle-option {
584
+ padding: 10px 16px;
585
+ cursor: pointer;
586
+ white-space: nowrap;
587
+ color: rgba(255, 255, 255, 0.9);
588
+ font-size: 13px;
589
+ transition: all 0.15s ease;
590
+ }
591
+
592
+ .wontum-subtitle-option:hover {
593
+ background: rgba(255, 255, 255, 0.12);
594
+ color: white;
595
+ }
596
+
597
+ .wontum-subtitle-option.active {
598
+ color: var(--primary-color);
599
+ background: rgba(255, 255, 255, 0.05);
600
+ }
601
+
602
+ .wontum-controls.sticky {
603
+ opacity: 1 !important;
604
+ transform: translateY(0) !important;
605
+ pointer-events: all !important;
606
+ }
607
+
608
+ .wontum-progress-container.sticky {
609
+ opacity: 1 !important;
610
+ transform: translateY(0) !important;
611
+ pointer-events: all !important;
612
+ }
613
+ `, document.head.appendChild(g), this.container.classList.add("wontum-player-container");
614
+ }
615
+ createProgressBar() {
616
+ const t = document.createElement("div");
617
+ t.className = "wontum-progress-container", t.innerHTML = `
618
+ <div class="wontum-progress-track"></div>
619
+ <div class="wontum-progress-filled"></div>
620
+ <input type="range" class="wontum-progress-input" min="0" max="100" value="0" step="0.1">
621
+ `, this.container.appendChild(t), this.progressContainer = t;
622
+ }
623
+ createControls() {
624
+ const t = document.createElement("div");
625
+ return t.className = "wontum-controls", t.innerHTML = `
626
+ <div class="wontum-center-controls">
627
+ <button class="wontum-center-btn skip wontum-skip-backward-btn" aria-label="Skip backward 10s">
628
+ ${this.getSkipBackwardIcon()}
629
+ </button>
630
+
631
+ <button class="wontum-center-btn play wontum-play-btn" aria-label="Play">
632
+ ${this.getPlayIcon()}
633
+ </button>
634
+
635
+ <button class="wontum-center-btn skip wontum-skip-forward-btn" aria-label="Skip forward 10s">
636
+ ${this.getSkipForwardIcon()}
637
+ </button>
638
+ </div>
639
+
640
+ <div class="wontum-controls-row">
641
+
642
+ <div class="wontum-volume-container">
643
+ <button class="wontum-btn wontum-volume-btn" aria-label="Mute">
644
+ ${this.getVolumeIcon()}
645
+ </button>
646
+ <div class="wontum-volume-slider-wrapper">
647
+ <input type="range" class="wontum-volume-slider" min="0" max="100" value="100" step="1" orient="vertical">
648
+ </div>
649
+ </div>
650
+
651
+ <div class="wontum-time-display">
652
+ <span class="wontum-current-time">0:00</span> / <span class="wontum-duration">0:00</span>
653
+ </div>
654
+
655
+ <div class="wontum-spacer"></div>
656
+
657
+ <div class="wontum-subtitle-container" style="position: relative;">
658
+ <button class="wontum-btn wontum-subtitle-btn" aria-label="Subtitles">
659
+ ${this.getSubtitleIcon()}
660
+ </button>
661
+ <div class="wontum-subtitle-menu"></div>
662
+ </div>
663
+
664
+ <div class="wontum-speed-container" style="position: relative;">
665
+ <button class="wontum-btn wontum-speed-btn" aria-label="Playback Speed">
666
+ ${this.getSpeedIcon()}
667
+ </button>
668
+ <div class="wontum-speed-menu"></div>
669
+ </div>
670
+
671
+ <div class="wontum-quality-container" style="position: relative;">
672
+ <button class="wontum-btn wontum-quality-btn" aria-label="Quality">
673
+ ${this.getQualityIcon()}
674
+ </button>
675
+ <div class="wontum-quality-menu"></div>
676
+ </div>
677
+
678
+ <div class="wontum-settings-container" style="position: relative;">
679
+ <button class="wontum-btn wontum-settings-btn" aria-label="Settings">
680
+ ${this.getSettingsIcon()}
681
+ </button>
682
+ <div class="wontum-settings-menu"></div>
683
+ </div>
684
+
685
+ <button class="wontum-btn wontum-fullscreen-btn" aria-label="Fullscreen">
686
+ ${this.getFullscreenIcon()}
687
+ </button>
688
+ </div>
689
+
690
+ <div class="wontum-loading" style="display: none;">
691
+ <div class="wontum-spinner"></div>
692
+ </div>
693
+ `, t;
694
+ }
695
+ setupEventListeners() {
696
+ this.playButton.addEventListener("click", () => {
697
+ this.player.getState().playing ? this.player.pause() : this.player.play();
698
+ }), this.skipBackwardButton.addEventListener("click", () => {
699
+ this.player.skipBackward(10);
700
+ }), this.skipForwardButton.addEventListener("click", () => {
701
+ this.player.skipForward(10);
702
+ }), this.progressInput.addEventListener("input", (e) => {
703
+ const s = e.target, r = parseFloat(s.value), i = this.player.getState(), l = r / 100 * i.duration;
704
+ this.player.seek(l);
705
+ }), this.volumeSlider.addEventListener("input", (e) => {
706
+ const s = e.target, r = parseFloat(s.value) / 100;
707
+ this.player.setVolume(r);
708
+ }), this.volumeButton.addEventListener("click", () => {
709
+ this.player.getState().muted ? this.player.unmute() : this.player.mute();
710
+ }), this.fullscreenButton.addEventListener("click", () => {
711
+ this.player.getState().fullscreen ? this.player.exitFullscreen() : this.player.enterFullscreen();
712
+ }), this.qualityButton.addEventListener("click", () => {
713
+ var s, r, i;
714
+ this.controlsContainer.querySelector(".wontum-quality-menu").classList.toggle("active"), (s = this.controlsContainer.querySelector(".wontum-settings-menu")) == null || s.classList.remove("active"), (r = this.controlsContainer.querySelector(".wontum-subtitle-menu")) == null || r.classList.remove("active"), (i = this.controlsContainer.querySelector(".wontum-speed-menu")) == null || i.classList.remove("active");
715
+ }), this.subtitleButton.addEventListener("click", () => {
716
+ var s, r, i;
717
+ this.controlsContainer.querySelector(".wontum-subtitle-menu").classList.toggle("active"), (s = this.controlsContainer.querySelector(".wontum-settings-menu")) == null || s.classList.remove("active"), (r = this.controlsContainer.querySelector(".wontum-quality-menu")) == null || r.classList.remove("active"), (i = this.controlsContainer.querySelector(".wontum-speed-menu")) == null || i.classList.remove("active"), this.updateSubtitleMenu();
718
+ }), this.speedButton.addEventListener("click", () => {
719
+ var s, r, i;
720
+ this.controlsContainer.querySelector(".wontum-speed-menu").classList.toggle("active"), (s = this.controlsContainer.querySelector(".wontum-settings-menu")) == null || s.classList.remove("active"), (r = this.controlsContainer.querySelector(".wontum-quality-menu")) == null || r.classList.remove("active"), (i = this.controlsContainer.querySelector(".wontum-subtitle-menu")) == null || i.classList.remove("active"), this.updateSpeedMenu();
721
+ }), this.settingsButton.addEventListener("click", () => {
722
+ var s, r, i;
723
+ this.controlsContainer.querySelector(".wontum-settings-menu").classList.toggle("active"), (s = this.controlsContainer.querySelector(".wontum-quality-menu")) == null || s.classList.remove("active"), (r = this.controlsContainer.querySelector(".wontum-subtitle-menu")) == null || r.classList.remove("active"), (i = this.controlsContainer.querySelector(".wontum-speed-menu")) == null || i.classList.remove("active"), this.updateSettingsMenu();
724
+ }), this.player.getVideoElement().addEventListener("click", () => {
725
+ this.player.getState().playing ? this.player.pause() : this.player.play();
726
+ }), this.container.addEventListener("mousemove", () => {
727
+ this.showControls(), this.resetHideControlsTimeout();
728
+ }), this.container.addEventListener("mouseleave", () => {
729
+ this.hideControls();
730
+ });
731
+ }
732
+ setupPlayerEventListeners() {
733
+ this.player.on("play", () => {
734
+ this.playButton.innerHTML = this.getPauseIcon();
735
+ }), this.player.on("pause", () => {
736
+ this.playButton.innerHTML = this.getPlayIcon();
737
+ }), this.player.on("timeupdate", (t) => {
738
+ const { currentTime: e } = t.data, s = this.player.getState();
739
+ if (s.duration > 0) {
740
+ const i = e / s.duration * 100;
741
+ this.progressBar.style.width = `${i}%`, this.progressInput.value = i.toString();
742
+ }
743
+ const r = this.controlsContainer.querySelector(".wontum-current-time");
744
+ r.textContent = this.formatTime(e);
745
+ }), this.player.on("loadedmetadata", (t) => {
746
+ const { duration: e } = t.data, s = this.controlsContainer.querySelector(".wontum-duration");
747
+ s.textContent = this.formatTime(e), t.data.qualities && this.updateQualityMenu(t.data.qualities);
748
+ }), this.player.on("volumechange", (t) => {
749
+ const { volume: e, muted: s } = t.data;
750
+ this.volumeSlider.value = (e * 100).toString(), this.volumeButton.innerHTML = s ? this.getMutedIcon() : this.getVolumeIcon();
751
+ }), this.player.on("waiting", () => {
752
+ const t = this.controlsContainer.querySelector(".wontum-loading");
753
+ t.style.display = "block";
754
+ }), this.player.on("canplay", () => {
755
+ const t = this.controlsContainer.querySelector(".wontum-loading");
756
+ t.style.display = "none";
757
+ });
758
+ }
759
+ updateSubtitleMenu() {
760
+ const t = this.controlsContainer.querySelector(".wontum-subtitle-menu"), e = this.player.getSubtitleTracks();
761
+ if (e.length === 0) {
762
+ t.innerHTML = '<div class="wontum-subtitle-option">No subtitles available</div>';
763
+ return;
764
+ }
765
+ const s = e.findIndex((r) => r.mode === "showing");
766
+ t.innerHTML = `
767
+ <div class="wontum-subtitle-option ${s === -1 ? "active" : ""}" data-track="-1">Off</div>
768
+ ${e.map(
769
+ (r, i) => `
770
+ <div class="wontum-subtitle-option ${i === s ? "active" : ""}" data-track="${i}">
771
+ ${r.label || r.language || `Track ${i + 1}`}
772
+ </div>
773
+ `
774
+ ).join("")}
775
+ `, t.querySelectorAll(".wontum-subtitle-option").forEach((r) => {
776
+ r.addEventListener("click", (i) => {
777
+ const l = i.target, u = parseInt(l.dataset.track || "-1");
778
+ u === -1 ? this.player.disableSubtitles() : this.player.enableSubtitles(u), t.querySelectorAll(".wontum-subtitle-option").forEach((v) => v.classList.remove("active")), l.classList.add("active"), t.classList.remove("active");
779
+ });
780
+ });
781
+ }
782
+ updateSpeedMenu() {
783
+ const t = this.controlsContainer.querySelector(".wontum-speed-menu"), s = this.player.getState().playbackRate || 1, r = [0.25, 0.5, 0.75, 1, 1.25, 1.5, 1.75, 2];
784
+ t.innerHTML = r.map(
785
+ (i) => `
786
+ <div class="wontum-speed-option ${s === i ? "active" : ""}" data-speed="${i}">
787
+ ${i === 1 ? "Normal" : i + "x"}
788
+ </div>
789
+ `
790
+ ).join(""), t.querySelectorAll(".wontum-speed-option").forEach((i) => {
791
+ i.addEventListener("click", (l) => {
792
+ const u = l.target, v = parseFloat(u.dataset.speed || "1");
793
+ this.player.setPlaybackRate(v), t.querySelectorAll(".wontum-speed-option").forEach((y) => y.classList.remove("active")), u.classList.add("active"), t.classList.remove("active");
794
+ });
795
+ });
796
+ }
797
+ updateSettingsMenu() {
798
+ const t = this.controlsContainer.querySelector(".wontum-settings-menu");
799
+ t.innerHTML = `
800
+ <div class="wontum-settings-option" data-setting="sticky-controls">
801
+ <span>Sticky Controls</span>
802
+ <div class="wontum-toggle-switch ${this.stickyControls ? "active" : ""}"></div>
803
+ </div>
804
+ `;
805
+ const e = t.querySelector('[data-setting="sticky-controls"]');
806
+ e.addEventListener("click", () => {
807
+ 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"));
808
+ });
809
+ }
810
+ updateQualityMenu(t) {
811
+ const e = this.controlsContainer.querySelector(".wontum-quality-menu");
812
+ e.innerHTML = `
813
+ <div class="wontum-quality-option active" data-quality="-1">Auto</div>
814
+ ${t.map(
815
+ (s, r) => `
816
+ <div class="wontum-quality-option" data-quality="${r}">${s.name}</div>
817
+ `
818
+ ).join("")}
819
+ `, e.querySelectorAll(".wontum-quality-option").forEach((s) => {
820
+ s.addEventListener("click", (r) => {
821
+ const i = r.target, l = parseInt(i.dataset.quality || "-1");
822
+ this.player.setQuality(l), e.querySelectorAll(".wontum-quality-option").forEach((u) => u.classList.remove("active")), i.classList.add("active"), e.classList.remove("active");
823
+ });
824
+ });
825
+ }
826
+ showControls() {
827
+ this.controlsContainer.classList.remove("hidden"), this.progressContainer.classList.remove("hidden");
828
+ }
829
+ hideControls() {
830
+ if (this.stickyControls) return;
831
+ this.player.getState().playing && (this.controlsContainer.classList.add("hidden"), this.progressContainer.classList.add("hidden"));
832
+ }
833
+ resetHideControlsTimeout() {
834
+ this.stickyControls || (this.hideControlsTimeout && clearTimeout(this.hideControlsTimeout), this.hideControlsTimeout = window.setTimeout(() => {
835
+ this.hideControls();
836
+ }, 1e4));
837
+ }
838
+ formatTime(t) {
839
+ if (isNaN(t)) return "0:00";
840
+ const e = Math.floor(t / 60), s = Math.floor(t % 60);
841
+ return `${e}:${s.toString().padStart(2, "0")}`;
842
+ }
843
+ // SVG Icons
844
+ getPlayIcon() {
845
+ return '<svg viewBox="0 0 24 24"><path fill="white" d="M8 5v14l11-7z"/></svg>';
846
+ }
847
+ getPauseIcon() {
848
+ return '<svg viewBox="0 0 24 24"><path fill="white" d="M6 4h4v16H6V4zm8 0h4v16h-4V4z"/></svg>';
849
+ }
850
+ getVolumeIcon() {
851
+ 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>';
852
+ }
853
+ getMutedIcon() {
854
+ 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>';
855
+ }
856
+ getFullscreenIcon() {
857
+ return '<svg viewBox="0 0 24 24"><path d="M7 14H5v5h5v-2H7v-3zm-2-4h2V7h3V5H5v5zm12 7h-3v2h5v-5h-2v3zM14 5v2h3v3h2V5h-5z"/></svg>';
858
+ }
859
+ getQualityIcon() {
860
+ return '<svg viewBox="0 0 24 24"><path d="M19 3H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2V5c0-1.1-.9-2-2-2zm-8 12H9.5v-2h-2v2H6V9h1.5v2.5h2V9H11v6zm7-1c0 .55-.45 1-1 1h-.75v1.5h-1.5V15H14c-.55 0-1-.45-1-1v-4c0-.55.45-1 1-1h3c.55 0 1 .45 1 1v4zm-3.5-.5h2v-3h-2v3z"/></svg>';
861
+ }
862
+ getSkipBackwardIcon() {
863
+ return `<svg viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
864
+ <circle cx="30" cy="30" r="28" stroke="white" stroke-width="2"/>
865
+ <!-- Circular arrow backward -->
866
+ <path d="M30 12 A18 18 0 1 0 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
867
+ <path d="M25 12 L30 12 L30 17" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
868
+ <text x="30" y="35" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="white" text-anchor="middle">10</text>
869
+ </svg>`;
870
+ }
871
+ getSkipForwardIcon() {
872
+ return `<svg viewBox="0 0 60 60" fill="none" xmlns="http://www.w3.org/2000/svg">
873
+ <circle cx="30" cy="30" r="28" stroke="white" stroke-width="2"/>
874
+ <!-- Circular arrow forward -->
875
+ <path d="M30 12 A18 18 0 1 1 30 48" stroke="white" stroke-width="2.5" stroke-linecap="round" fill="none"/>
876
+ <path d="M35 12 L30 12 L30 17" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
877
+ <text x="30" y="35" font-family="Arial, sans-serif" font-size="14" font-weight="bold" fill="white" text-anchor="middle">10</text>
878
+ </svg>`;
879
+ }
880
+ getSubtitleIcon() {
881
+ return '<svg viewBox="0 0 24 24"><path d="M20 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zM4 12h4v2H4v-2zm10 6H4v-2h10v2zm6 0h-4v-2h4v2zm0-4H10v-2h10v2z"/></svg>';
882
+ }
883
+ getSpeedIcon() {
884
+ return '<svg viewBox="0 0 24 24"><path d="M20.38 8.57l-1.23 1.85a8 8 0 0 1-.22 7.58H5.07A8 8 0 0 1 15.58 6.85l1.85-1.23A10 10 0 0 0 3.35 19a2 2 0 0 0 1.72 1h13.85a2 2 0 0 0 1.74-1 10 10 0 0 0-.27-10.44zm-9.79 6.84a2 2 0 0 0 2.83 0l5.66-8.49-8.49 5.66a2 2 0 0 0 0 2.83z"/></svg>';
885
+ }
886
+ getSettingsIcon() {
887
+ 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>';
888
+ }
889
+ destroy() {
890
+ this.hideControlsTimeout && clearTimeout(this.hideControlsTimeout), this.controlsContainer.remove();
891
+ }
892
+ }
893
+ class dt {
894
+ constructor(t) {
895
+ o(this, "config");
896
+ o(this, "urlCache", /* @__PURE__ */ new Map());
897
+ o(this, "signedUrls", /* @__PURE__ */ new Set());
898
+ this.config = t;
899
+ }
900
+ /**
901
+ * Process a URL - sign with CloudFront cookies or generate presigned URL for S3
902
+ */
903
+ async processUrl(t) {
904
+ return this.isCloudFrontUrl(t) ? this.signCloudFrontUrl(t) : this.isS3Url(t) ? this.getPresignedUrl(t) : t;
905
+ }
906
+ /**
907
+ * Check if URL is a CloudFront URL that needs signing
908
+ */
909
+ isCloudFrontUrl(t) {
910
+ var e;
911
+ if (!((e = this.config) != null && e.cloudFrontDomains) || this.config.cloudFrontDomains.length === 0)
912
+ return !1;
913
+ try {
914
+ const s = new URL(t);
915
+ return this.config.cloudFrontDomains.some((r) => s.hostname.includes(r));
916
+ } catch {
917
+ return !1;
918
+ }
919
+ }
920
+ /**
921
+ * Check if URL is an S3 URL
922
+ */
923
+ isS3Url(t) {
924
+ return t.includes(".s3.") || t.includes("s3.amazonaws.com") || t.startsWith("s3://");
925
+ }
926
+ /**
927
+ * Sign CloudFront URL by calling the signing endpoint
928
+ * The endpoint should set signed cookies and return the URL
929
+ */
930
+ async signCloudFrontUrl(t) {
931
+ var e;
932
+ if (this.signedUrls.has(t))
933
+ return t;
934
+ if ((e = this.config) != null && e.signUrl)
935
+ try {
936
+ const s = await this.config.signUrl(t);
937
+ return this.signedUrls.add(t), s;
938
+ } catch (s) {
939
+ throw console.error("Failed to sign CloudFront URL:", s), new Error("Failed to sign CloudFront URL");
940
+ }
941
+ return console.warn("No signUrl function provided. CloudFront cookies may not be set."), t;
942
+ }
943
+ /**
944
+ * Extract S3 key from URL
945
+ */
946
+ extractS3Key(t) {
947
+ if (t.startsWith("s3://"))
948
+ return t.replace("s3://", "").split("/").slice(1).join("/");
949
+ const e = t.match(/s3[.-]([^.]+)\.amazonaws\.com\/(.+)/);
950
+ if (e)
951
+ return e[2];
952
+ const s = t.match(/([^.]+)\.s3\.amazonaws\.com\/(.+)/);
953
+ return s ? s[2] : t;
954
+ }
955
+ /**
956
+ * Get presigned URL from cache or generate new one
957
+ */
958
+ async getPresignedUrl(t) {
959
+ var r;
960
+ const e = this.extractS3Key(t), s = this.urlCache.get(e);
961
+ if (s && s.expiresAt > Date.now())
962
+ return s.url;
963
+ if ((r = this.config) != null && r.getPresignedUrl)
964
+ try {
965
+ const i = await this.config.getPresignedUrl(e);
966
+ return this.urlCache.set(e, {
967
+ url: i,
968
+ expiresAt: Date.now() + 50 * 60 * 1e3
969
+ }), i;
970
+ } catch (i) {
971
+ throw console.error("Failed to generate presigned URL:", i), new Error("Failed to generate presigned URL for S3 object");
972
+ }
973
+ return console.warn("No getPresignedUrl function provided. Using direct S3 URL (requires public bucket)"), t;
974
+ }
975
+ /**
976
+ * Helper to construct S3 URL from bucket and key
977
+ */
978
+ static constructS3Url(t, e, s = "us-east-1") {
979
+ return `https://${t}.s3.${s}.amazonaws.com/${e}`;
980
+ }
981
+ /**
982
+ * Helper to parse S3 URI (s3://bucket/key)
983
+ */
984
+ static parseS3Uri(t) {
985
+ if (!t.startsWith("s3://"))
986
+ return null;
987
+ const e = t.replace("s3://", "").split("/"), s = e[0], r = e.slice(1).join("/");
988
+ return { bucket: s, key: r };
989
+ }
990
+ /**
991
+ * Clear URL cache and signed URLs
992
+ */
993
+ clearCache() {
994
+ this.urlCache.clear(), this.signedUrls.clear();
995
+ }
996
+ }
997
+ class nt {
998
+ constructor(t) {
999
+ o(this, "container");
1000
+ o(this, "videoElement");
1001
+ o(this, "hls", null);
1002
+ o(this, "config");
1003
+ o(this, "eventListeners", /* @__PURE__ */ new Map());
1004
+ o(this, "analytics");
1005
+ o(this, "s3Handler");
1006
+ o(this, "uiController");
1007
+ o(this, "state", {
1008
+ playing: !1,
1009
+ paused: !0,
1010
+ ended: !1,
1011
+ buffering: !1,
1012
+ currentTime: 0,
1013
+ duration: 0,
1014
+ volume: 1,
1015
+ muted: !1,
1016
+ playbackRate: 1,
1017
+ quality: "auto",
1018
+ availableQualities: [],
1019
+ fullscreen: !1
1020
+ });
1021
+ if (this.config = t, this.container = typeof t.container == "string" ? document.querySelector(t.container) : t.container, !this.container)
1022
+ throw new Error("Container element not found");
1023
+ this.analytics = new ct(t.analytics), this.s3Handler = new dt(t.s3Config), this.videoElement = this.createVideoElement(), this.container.appendChild(this.videoElement), this.uiController = new ut(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);
1024
+ }
1025
+ addSubtitleTracks(t) {
1026
+ t.forEach((e) => {
1027
+ const s = document.createElement("track");
1028
+ s.kind = "subtitles", s.label = e.label, s.src = e.src, s.srclang = e.srclang, e.default && (s.default = !0), this.videoElement.appendChild(s);
1029
+ });
1030
+ }
1031
+ createVideoElement() {
1032
+ const t = document.createElement("video");
1033
+ return t.className = "wontum-player-video", t.style.width = "100%", t.style.height = "100%", t.playsInline = !0, t;
1034
+ }
1035
+ setupVideoListeners() {
1036
+ this.videoElement.addEventListener("play", () => {
1037
+ this.state.playing = !0, this.state.paused = !1, this.emit("play"), this.analytics.trackEvent("play", this.getAnalyticsData());
1038
+ }), this.videoElement.addEventListener("pause", () => {
1039
+ this.state.playing = !1, this.state.paused = !0, this.emit("pause"), this.analytics.trackEvent("pause", this.getAnalyticsData());
1040
+ }), this.videoElement.addEventListener("ended", () => {
1041
+ this.state.ended = !0, this.state.playing = !1, this.emit("ended"), this.analytics.trackEvent("ended", this.getAnalyticsData());
1042
+ }), this.videoElement.addEventListener("timeupdate", () => {
1043
+ this.state.currentTime = this.videoElement.currentTime, this.emit("timeupdate", { currentTime: this.state.currentTime });
1044
+ }), this.videoElement.addEventListener("loadedmetadata", () => {
1045
+ this.state.duration = this.videoElement.duration, this.emit("loadedmetadata", { duration: this.state.duration }), this.analytics.trackEvent("loadedmetadata", this.getAnalyticsData());
1046
+ }), this.videoElement.addEventListener("volumechange", () => {
1047
+ this.state.volume = this.videoElement.volume, this.state.muted = this.videoElement.muted, this.emit("volumechange", { volume: this.state.volume, muted: this.state.muted });
1048
+ }), this.videoElement.addEventListener("ratechange", () => {
1049
+ this.state.playbackRate = this.videoElement.playbackRate, this.emit("ratechange", { playbackRate: this.state.playbackRate });
1050
+ }), this.videoElement.addEventListener("waiting", () => {
1051
+ this.state.buffering = !0, this.emit("waiting"), this.analytics.trackEvent("buffering_start", this.getAnalyticsData());
1052
+ }), this.videoElement.addEventListener("canplay", () => {
1053
+ this.state.buffering = !1, this.emit("canplay"), this.analytics.trackEvent("buffering_end", this.getAnalyticsData());
1054
+ }), this.videoElement.addEventListener("seeking", () => {
1055
+ this.emit("seeking");
1056
+ }), this.videoElement.addEventListener("seeked", () => {
1057
+ this.emit("seeked", { currentTime: this.state.currentTime }), this.analytics.trackEvent("seeked", this.getAnalyticsData());
1058
+ }), this.videoElement.addEventListener("error", (t) => {
1059
+ const e = this.videoElement.error;
1060
+ this.emit("error", { error: e }), this.analytics.trackEvent("error", { ...this.getAnalyticsData(), error: e == null ? void 0 : e.message });
1061
+ }), this.videoElement.addEventListener("loadstart", () => {
1062
+ this.emit("loadstart");
1063
+ }), this.videoElement.addEventListener("loadeddata", () => {
1064
+ this.emit("loadeddata");
1065
+ }), this.videoElement.addEventListener("canplaythrough", () => {
1066
+ this.emit("canplaythrough");
1067
+ }), this.videoElement.addEventListener("playing", () => {
1068
+ this.state.playing = !0, this.state.buffering = !1, this.emit("playing");
1069
+ }), this.videoElement.addEventListener("durationchange", () => {
1070
+ this.state.duration = this.videoElement.duration, this.emit("durationchange", { duration: this.state.duration });
1071
+ }), this.videoElement.addEventListener("progress", () => {
1072
+ this.emit("progress", { buffered: this.videoElement.buffered });
1073
+ }), this.videoElement.addEventListener("stalled", () => {
1074
+ this.emit("stalled");
1075
+ }), this.videoElement.addEventListener("suspend", () => {
1076
+ this.emit("suspend");
1077
+ }), this.videoElement.addEventListener("abort", () => {
1078
+ this.emit("abort");
1079
+ }), this.videoElement.addEventListener("emptied", () => {
1080
+ this.emit("emptied");
1081
+ }), this.videoElement.addEventListener("resize", () => {
1082
+ this.emit("resize", {
1083
+ videoWidth: this.videoElement.videoWidth,
1084
+ videoHeight: this.videoElement.videoHeight
1085
+ });
1086
+ });
1087
+ }
1088
+ async loadSource(t) {
1089
+ try {
1090
+ const e = await this.s3Handler.processUrl(t);
1091
+ if (w.isSupported())
1092
+ this.hls = new w(this.config.hlsConfig), this.hls.loadSource(e), this.hls.attachMedia(this.videoElement), this.hls.on(w.Events.MANIFEST_PARSED, (s, r) => {
1093
+ const i = this.extractQualities(r.levels);
1094
+ this.state.availableQualities = i.map((l) => l.name), this.emit("loadedmetadata", { qualities: i });
1095
+ }), this.hls.on(w.Events.LEVEL_SWITCHED, (s, r) => {
1096
+ var l;
1097
+ const i = (l = this.hls) == null ? void 0 : l.levels[r.level];
1098
+ i && (this.state.quality = `${i.height}p`, this.emit("qualitychange", { quality: this.state.quality }));
1099
+ }), this.hls.on(w.Events.ERROR, (s, r) => {
1100
+ r.fatal && this.handleHlsError(r);
1101
+ });
1102
+ else if (this.videoElement.canPlayType("application/vnd.apple.mpegurl"))
1103
+ this.videoElement.src = e;
1104
+ else
1105
+ throw new Error("HLS is not supported in this browser");
1106
+ } catch (e) {
1107
+ console.error("Failed to load video source:", e), this.emit("error", { error: e });
1108
+ }
1109
+ }
1110
+ extractQualities(t) {
1111
+ return t.map((e) => ({
1112
+ height: e.height,
1113
+ width: e.width,
1114
+ bitrate: e.bitrate,
1115
+ name: `${e.height}p`
1116
+ }));
1117
+ }
1118
+ handleHlsError(t) {
1119
+ var e, s;
1120
+ switch (t.type) {
1121
+ case w.ErrorTypes.NETWORK_ERROR:
1122
+ console.error("Network error occurred"), (e = this.hls) == null || e.startLoad();
1123
+ break;
1124
+ case w.ErrorTypes.MEDIA_ERROR:
1125
+ console.error("Media error occurred"), (s = this.hls) == null || s.recoverMediaError();
1126
+ break;
1127
+ default:
1128
+ console.error("Fatal error occurred:", t), this.destroy();
1129
+ break;
1130
+ }
1131
+ }
1132
+ getAnalyticsData() {
1133
+ return {
1134
+ currentTime: this.state.currentTime,
1135
+ duration: this.state.duration,
1136
+ quality: this.state.quality,
1137
+ playbackRate: this.state.playbackRate,
1138
+ volume: this.state.volume,
1139
+ muted: this.state.muted
1140
+ };
1141
+ }
1142
+ // Public API
1143
+ play() {
1144
+ return this.videoElement.play();
1145
+ }
1146
+ pause() {
1147
+ this.videoElement.pause();
1148
+ }
1149
+ seek(t) {
1150
+ this.videoElement.currentTime = t;
1151
+ }
1152
+ skipForward(t = 10) {
1153
+ const e = Math.min(this.state.currentTime + t, this.state.duration);
1154
+ this.seek(e);
1155
+ }
1156
+ skipBackward(t = 10) {
1157
+ const e = Math.max(this.state.currentTime - t, 0);
1158
+ this.seek(e);
1159
+ }
1160
+ setVolume(t) {
1161
+ this.videoElement.volume = Math.max(0, Math.min(1, t));
1162
+ }
1163
+ mute() {
1164
+ this.videoElement.muted = !0;
1165
+ }
1166
+ unmute() {
1167
+ this.videoElement.muted = !1;
1168
+ }
1169
+ setPlaybackRate(t) {
1170
+ this.videoElement.playbackRate = t;
1171
+ }
1172
+ setQuality(t) {
1173
+ this.hls && (this.hls.currentLevel = t);
1174
+ }
1175
+ enterFullscreen() {
1176
+ this.container.requestFullscreen && (this.container.requestFullscreen(), this.state.fullscreen = !0, this.emit("fullscreenchange", { fullscreen: !0 }));
1177
+ }
1178
+ exitFullscreen() {
1179
+ document.exitFullscreen && (document.exitFullscreen(), this.state.fullscreen = !1, this.emit("fullscreenchange", { fullscreen: !1 }));
1180
+ }
1181
+ getState() {
1182
+ return { ...this.state };
1183
+ }
1184
+ getVideoElement() {
1185
+ return this.videoElement;
1186
+ }
1187
+ /**
1188
+ * Enable subtitles for a specific track
1189
+ */
1190
+ enableSubtitles(t) {
1191
+ const e = this.videoElement.textTracks;
1192
+ for (let s = 0; s < e.length; s++)
1193
+ e[s].mode = s === t ? "showing" : "hidden";
1194
+ }
1195
+ /**
1196
+ * Disable all subtitles
1197
+ */
1198
+ disableSubtitles() {
1199
+ const t = this.videoElement.textTracks;
1200
+ for (let e = 0; e < t.length; e++)
1201
+ t[e].mode = "hidden";
1202
+ }
1203
+ /**
1204
+ * Toggle subtitles on/off
1205
+ */
1206
+ toggleSubtitles() {
1207
+ const t = this.videoElement.textTracks;
1208
+ return Array.from(t).some((s) => s.mode === "showing") ? (this.disableSubtitles(), !1) : t.length > 0 ? (this.enableSubtitles(0), !0) : !1;
1209
+ }
1210
+ /**
1211
+ * Get available subtitle tracks
1212
+ */
1213
+ getSubtitleTracks() {
1214
+ return Array.from(this.videoElement.textTracks);
1215
+ }
1216
+ /**
1217
+ * Check if subtitles are currently enabled
1218
+ */
1219
+ areSubtitlesEnabled() {
1220
+ const t = this.videoElement.textTracks;
1221
+ return Array.from(t).some((e) => e.mode === "showing");
1222
+ }
1223
+ on(t, e) {
1224
+ this.eventListeners.has(t) || this.eventListeners.set(t, /* @__PURE__ */ new Set()), this.eventListeners.get(t).add(e);
1225
+ }
1226
+ off(t, e) {
1227
+ var s;
1228
+ (s = this.eventListeners.get(t)) == null || s.delete(e);
1229
+ }
1230
+ emit(t, e) {
1231
+ var r;
1232
+ const s = {
1233
+ type: t,
1234
+ data: e,
1235
+ timestamp: Date.now()
1236
+ };
1237
+ (r = this.eventListeners.get(t)) == null || r.forEach((i) => {
1238
+ i(s);
1239
+ });
1240
+ }
1241
+ destroy() {
1242
+ this.hls && (this.hls.destroy(), this.hls = null), this.uiController.destroy(), this.videoElement.remove(), this.eventListeners.clear(), this.analytics.destroy();
1243
+ }
1244
+ }
1245
+ var W = { exports: {} }, q = {};
1246
+ /**
1247
+ * @license React
1248
+ * react-jsx-runtime.production.js
1249
+ *
1250
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
1251
+ *
1252
+ * This source code is licensed under the MIT license found in the
1253
+ * LICENSE file in the root directory of this source tree.
1254
+ */
1255
+ var tt;
1256
+ function ht() {
1257
+ if (tt) return q;
1258
+ tt = 1;
1259
+ var c = Symbol.for("react.transitional.element"), t = Symbol.for("react.fragment");
1260
+ function e(s, r, i) {
1261
+ var l = null;
1262
+ if (i !== void 0 && (l = "" + i), r.key !== void 0 && (l = "" + r.key), "key" in r) {
1263
+ i = {};
1264
+ for (var u in r)
1265
+ u !== "key" && (i[u] = r[u]);
1266
+ } else i = r;
1267
+ return r = i.ref, {
1268
+ $$typeof: c,
1269
+ type: s,
1270
+ key: l,
1271
+ ref: r !== void 0 ? r : null,
1272
+ props: i
1273
+ };
1274
+ }
1275
+ return q.Fragment = t, q.jsx = e, q.jsxs = e, q;
1276
+ }
1277
+ var P = {};
1278
+ /**
1279
+ * @license React
1280
+ * react-jsx-runtime.development.js
1281
+ *
1282
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
1283
+ *
1284
+ * This source code is licensed under the MIT license found in the
1285
+ * LICENSE file in the root directory of this source tree.
1286
+ */
1287
+ var et;
1288
+ function mt() {
1289
+ return et || (et = 1, process.env.NODE_ENV !== "production" && function() {
1290
+ function c(n) {
1291
+ if (n == null) return null;
1292
+ if (typeof n == "function")
1293
+ return n.$$typeof === I ? null : n.displayName || n.name || null;
1294
+ if (typeof n == "string") return n;
1295
+ switch (n) {
1296
+ case k:
1297
+ return "Fragment";
1298
+ case F:
1299
+ return "Profiler";
1300
+ case M:
1301
+ return "StrictMode";
1302
+ case R:
1303
+ return "Suspense";
1304
+ case _:
1305
+ return "SuspenseList";
1306
+ case f:
1307
+ return "Activity";
1308
+ }
1309
+ if (typeof n == "object")
1310
+ switch (typeof n.tag == "number" && console.error(
1311
+ "Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
1312
+ ), n.$$typeof) {
1313
+ case A:
1314
+ return "Portal";
1315
+ case T:
1316
+ return n.displayName || "Context";
1317
+ case z:
1318
+ return (n._context.displayName || "Context") + ".Consumer";
1319
+ case L:
1320
+ var a = n.render;
1321
+ return n = n.displayName, n || (n = a.displayName || a.name || "", n = n !== "" ? "ForwardRef(" + n + ")" : "ForwardRef"), n;
1322
+ case O:
1323
+ return a = n.displayName || null, a !== null ? a : c(n.type) || "Memo";
1324
+ case p:
1325
+ a = n._payload, n = n._init;
1326
+ try {
1327
+ return c(n(a));
1328
+ } catch {
1329
+ }
1330
+ }
1331
+ return null;
1332
+ }
1333
+ function t(n) {
1334
+ return "" + n;
1335
+ }
1336
+ function e(n) {
1337
+ try {
1338
+ t(n);
1339
+ var a = !1;
1340
+ } catch {
1341
+ a = !0;
1342
+ }
1343
+ if (a) {
1344
+ a = console;
1345
+ var d = a.error, h = typeof Symbol == "function" && Symbol.toStringTag && n[Symbol.toStringTag] || n.constructor.name || "Object";
1346
+ return d.call(
1347
+ a,
1348
+ "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
1349
+ h
1350
+ ), t(n);
1351
+ }
1352
+ }
1353
+ function s(n) {
1354
+ if (n === k) return "<>";
1355
+ if (typeof n == "object" && n !== null && n.$$typeof === p)
1356
+ return "<...>";
1357
+ try {
1358
+ var a = c(n);
1359
+ return a ? "<" + a + ">" : "<...>";
1360
+ } catch {
1361
+ return "<...>";
1362
+ }
1363
+ }
1364
+ function r() {
1365
+ var n = j.A;
1366
+ return n === null ? null : n.getOwner();
1367
+ }
1368
+ function i() {
1369
+ return Error("react-stack-top-frame");
1370
+ }
1371
+ function l(n) {
1372
+ if (Q.call(n, "key")) {
1373
+ var a = Object.getOwnPropertyDescriptor(n, "key").get;
1374
+ if (a && a.isReactWarning) return !1;
1375
+ }
1376
+ return n.key !== void 0;
1377
+ }
1378
+ function u(n, a) {
1379
+ function d() {
1380
+ J || (J = !0, console.error(
1381
+ "%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
1382
+ a
1383
+ ));
1384
+ }
1385
+ d.isReactWarning = !0, Object.defineProperty(n, "key", {
1386
+ get: d,
1387
+ configurable: !0
1388
+ });
1389
+ }
1390
+ function v() {
1391
+ var n = c(this.type);
1392
+ return X[n] || (X[n] = !0, console.error(
1393
+ "Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
1394
+ )), n = this.props.ref, n !== void 0 ? n : null;
1395
+ }
1396
+ function y(n, a, d, h, B, H) {
1397
+ var m = d.ref;
1398
+ return n = {
1399
+ $$typeof: C,
1400
+ type: n,
1401
+ key: a,
1402
+ props: d,
1403
+ _owner: h
1404
+ }, (m !== void 0 ? m : null) !== null ? Object.defineProperty(n, "ref", {
1405
+ enumerable: !1,
1406
+ get: v
1407
+ }) : Object.defineProperty(n, "ref", { enumerable: !1, value: null }), n._store = {}, Object.defineProperty(n._store, "validated", {
1408
+ configurable: !1,
1409
+ enumerable: !1,
1410
+ writable: !0,
1411
+ value: 0
1412
+ }), Object.defineProperty(n, "_debugInfo", {
1413
+ configurable: !1,
1414
+ enumerable: !1,
1415
+ writable: !0,
1416
+ value: null
1417
+ }), Object.defineProperty(n, "_debugStack", {
1418
+ configurable: !1,
1419
+ enumerable: !1,
1420
+ writable: !0,
1421
+ value: B
1422
+ }), Object.defineProperty(n, "_debugTask", {
1423
+ configurable: !1,
1424
+ enumerable: !1,
1425
+ writable: !0,
1426
+ value: H
1427
+ }), Object.freeze && (Object.freeze(n.props), Object.freeze(n)), n;
1428
+ }
1429
+ function g(n, a, d, h, B, H) {
1430
+ var m = a.children;
1431
+ if (m !== void 0)
1432
+ if (h)
1433
+ if (it(m)) {
1434
+ for (h = 0; h < m.length; h++)
1435
+ x(m[h]);
1436
+ Object.freeze && Object.freeze(m);
1437
+ } else
1438
+ console.error(
1439
+ "React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
1440
+ );
1441
+ else x(m);
1442
+ if (Q.call(a, "key")) {
1443
+ m = c(n);
1444
+ var E = Object.keys(a).filter(function(ot) {
1445
+ return ot !== "key";
1446
+ });
1447
+ h = 0 < E.length ? "{key: someKey, " + E.join(": ..., ") + ": ...}" : "{key: someKey}", K[m + h] || (E = 0 < E.length ? "{" + E.join(": ..., ") + ": ...}" : "{}", console.error(
1448
+ `A props object containing a "key" prop is being spread into JSX:
1449
+ let props = %s;
1450
+ <%s {...props} />
1451
+ React keys must be passed directly to JSX without using spread:
1452
+ let props = %s;
1453
+ <%s key={someKey} {...props} />`,
1454
+ h,
1455
+ m,
1456
+ E,
1457
+ m
1458
+ ), K[m + h] = !0);
1459
+ }
1460
+ if (m = null, d !== void 0 && (e(d), m = "" + d), l(a) && (e(a.key), m = "" + a.key), "key" in a) {
1461
+ d = {};
1462
+ for (var N in a)
1463
+ N !== "key" && (d[N] = a[N]);
1464
+ } else d = a;
1465
+ return m && u(
1466
+ d,
1467
+ typeof n == "function" ? n.displayName || n.name || "Unknown" : n
1468
+ ), y(
1469
+ n,
1470
+ m,
1471
+ d,
1472
+ r(),
1473
+ B,
1474
+ H
1475
+ );
1476
+ }
1477
+ function x(n) {
1478
+ S(n) ? n._store && (n._store.validated = 1) : typeof n == "object" && n !== null && n.$$typeof === p && (n._payload.status === "fulfilled" ? S(n._payload.value) && n._payload.value._store && (n._payload.value._store.validated = 1) : n._store && (n._store.validated = 1));
1479
+ }
1480
+ function S(n) {
1481
+ return typeof n == "object" && n !== null && n.$$typeof === C;
1482
+ }
1483
+ var b = Y, C = Symbol.for("react.transitional.element"), A = Symbol.for("react.portal"), k = Symbol.for("react.fragment"), M = Symbol.for("react.strict_mode"), F = Symbol.for("react.profiler"), z = Symbol.for("react.consumer"), T = Symbol.for("react.context"), L = Symbol.for("react.forward_ref"), R = Symbol.for("react.suspense"), _ = Symbol.for("react.suspense_list"), O = Symbol.for("react.memo"), p = Symbol.for("react.lazy"), f = Symbol.for("react.activity"), I = Symbol.for("react.client.reference"), j = b.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, Q = Object.prototype.hasOwnProperty, it = Array.isArray, D = console.createTask ? console.createTask : function() {
1484
+ return null;
1485
+ };
1486
+ b = {
1487
+ react_stack_bottom_frame: function(n) {
1488
+ return n();
1489
+ }
1490
+ };
1491
+ var J, X = {}, G = b.react_stack_bottom_frame.bind(
1492
+ b,
1493
+ i
1494
+ )(), Z = D(s(i)), K = {};
1495
+ P.Fragment = k, P.jsx = function(n, a, d) {
1496
+ var h = 1e4 > j.recentlyCreatedOwnerStacks++;
1497
+ return g(
1498
+ n,
1499
+ a,
1500
+ d,
1501
+ !1,
1502
+ h ? Error("react-stack-top-frame") : G,
1503
+ h ? D(s(n)) : Z
1504
+ );
1505
+ }, P.jsxs = function(n, a, d) {
1506
+ var h = 1e4 > j.recentlyCreatedOwnerStacks++;
1507
+ return g(
1508
+ n,
1509
+ a,
1510
+ d,
1511
+ !0,
1512
+ h ? Error("react-stack-top-frame") : G,
1513
+ h ? D(s(n)) : Z
1514
+ );
1515
+ };
1516
+ }()), P;
1517
+ }
1518
+ process.env.NODE_ENV === "production" ? W.exports = ht() : W.exports = mt();
1519
+ var st = W.exports;
1520
+ const ft = (c) => {
1521
+ const {
1522
+ src: t,
1523
+ autoplay: e,
1524
+ muted: s,
1525
+ controls: r = !0,
1526
+ poster: i,
1527
+ preload: l,
1528
+ theme: u,
1529
+ s3Config: v,
1530
+ analytics: y,
1531
+ hlsConfig: g,
1532
+ onReady: x,
1533
+ onPlay: S,
1534
+ onPause: b,
1535
+ onEnded: C,
1536
+ onTimeUpdate: A,
1537
+ onVolumeChange: k,
1538
+ onError: M,
1539
+ style: F,
1540
+ className: z,
1541
+ width: T = "100%",
1542
+ height: L = "500px"
1543
+ } = c, R = U(null), _ = U(null);
1544
+ return $(() => {
1545
+ if (!R.current) return;
1546
+ const O = {
1547
+ src: t,
1548
+ container: R.current,
1549
+ autoplay: e,
1550
+ muted: s,
1551
+ controls: r,
1552
+ poster: i,
1553
+ preload: l,
1554
+ theme: u,
1555
+ s3Config: v,
1556
+ analytics: y,
1557
+ hlsConfig: g
1558
+ }, p = new nt(O);
1559
+ return _.current = p, S && p.on("play", S), b && p.on("pause", b), C && p.on("ended", C), M && p.on("error", (f) => {
1560
+ var I;
1561
+ return M((I = f.data) == null ? void 0 : I.error);
1562
+ }), A && p.on("timeupdate", (f) => A(f.data.currentTime)), k && p.on("volumechange", (f) => k(f.data.volume, f.data.muted)), x && x(p), () => {
1563
+ p.destroy(), _.current = null;
1564
+ };
1565
+ }, [t]), $(() => {
1566
+ _.current;
1567
+ }, [e, s, r]), /* @__PURE__ */ st.jsx(
1568
+ "div",
1569
+ {
1570
+ ref: R,
1571
+ className: z,
1572
+ style: {
1573
+ width: typeof T == "number" ? `${T}px` : T,
1574
+ height: typeof L == "number" ? `${L}px` : L,
1575
+ ...F
1576
+ }
1577
+ }
1578
+ );
1579
+ }, yt = (c) => {
1580
+ const [t, e] = V(null), [s, r] = V(null), i = U(null);
1581
+ return $(() => {
1582
+ if (!i.current) return;
1583
+ const l = new nt({
1584
+ ...c,
1585
+ container: i.current
1586
+ });
1587
+ e(l);
1588
+ const u = () => {
1589
+ r(l.getState());
1590
+ };
1591
+ return l.on("play", u), l.on("pause", u), l.on("timeupdate", u), l.on("volumechange", u), l.on("loadedmetadata", u), () => {
1592
+ l.destroy();
1593
+ };
1594
+ }, [c.src]), {
1595
+ containerRef: i,
1596
+ player: t,
1597
+ state: s
1598
+ };
1599
+ }, rt = Y.createContext({
1600
+ player: null,
1601
+ state: null
1602
+ }), bt = (c) => {
1603
+ const { player: t, children: e } = c, [s, r] = V(t.getState());
1604
+ return $(() => {
1605
+ const i = () => {
1606
+ r(t.getState());
1607
+ };
1608
+ return t.on("play", i), t.on("pause", i), t.on("timeupdate", i), t.on("volumechange", i), t.on("loadedmetadata", i), () => {
1609
+ };
1610
+ }, [t]), /* @__PURE__ */ st.jsx(rt.Provider, { value: { player: t, state: s }, children: e });
1611
+ }, wt = () => {
1612
+ const c = Y.useContext(rt);
1613
+ if (!c.player)
1614
+ throw new Error("useWontumPlayerContext must be used within WontumPlayerProvider");
1615
+ return c;
1616
+ };
1617
+ export {
1618
+ ct as Analytics,
1619
+ dt as S3Handler,
1620
+ ut as UIController,
1621
+ nt as WontumPlayer,
1622
+ bt as WontumPlayerProvider,
1623
+ ft as WontumPlayerReact,
1624
+ yt as useWontumPlayer,
1625
+ wt as useWontumPlayerContext
1626
+ };