@factorialco/f0-react 4.67.0 → 4.68.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1418 @@
1
+ import { u as W, t as je, v as Ge, m as $, x as Xe, y as Ze, z as qe, A as Ye, B as Je, E as Qe, G as et, H as tt, J as nt, K as rt, L as at, M as ye, N as ot, O as Ce, l as st, Q as it, R as ct, U as lt, w as dt, r as ut } from "./F0CanvasPanel-BStowVw4.js";
2
+ import { jsxs as R, jsx as l } from "react/jsx-runtime";
3
+ import { forwardRef as re, useId as ft, useState as x, useRef as O, useEffect as _, useMemo as J, useCallback as M } from "react";
4
+ import { d as H, f as de } from "./tooltip-Cik7KBQT.js";
5
+ import { F as mt, a as pt, b as Pe, c as ht, d as gt } from "./VolumeMuted-XL3dwOL-.js";
6
+ function Se(e) {
7
+ return Array.isArray(e);
8
+ }
9
+ function ee(e, t) {
10
+ return e === void 0 ? void 0 : Se(e) ? e.length === 0 ? void 0 : ((t ? e.find((n) => n.locale === t) : void 0) ?? e[0]).value : e;
11
+ }
12
+ function ae(...e) {
13
+ const t = /* @__PURE__ */ new Map();
14
+ for (const a of e)
15
+ if (Se(a))
16
+ for (const n of a) {
17
+ const o = t.get(n.locale);
18
+ o ? !o.label && n.label && (o.label = n.label) : t.set(n.locale, {
19
+ locale: n.locale,
20
+ label: n.label
21
+ });
22
+ }
23
+ return Array.from(t.values());
24
+ }
25
+ function Le(e, t) {
26
+ if (e.label) return e.label;
27
+ try {
28
+ const a = t ?? e.locale, o = new Intl.DisplayNames([a], { type: "language" }).of(e.locale) ?? e.locale;
29
+ return o.charAt(0).toLocaleUpperCase(a) + o.slice(1);
30
+ } catch {
31
+ return e.locale;
32
+ }
33
+ }
34
+ function Z(e, t) {
35
+ if (e.length === 0) return;
36
+ const a = e.map((r) => r.locale), n = (r) => r.split("-")[0], o = (r) => a.find((u) => u === r) ?? a.find((u) => n(u) === n(r));
37
+ if (t) {
38
+ const r = o(t);
39
+ if (r) return r;
40
+ }
41
+ const i = typeof navigator < "u" ? navigator.language : void 0;
42
+ if (i) {
43
+ const r = o(i);
44
+ if (r) return r;
45
+ }
46
+ return a[0];
47
+ }
48
+ const Re = [0.5, 0.75, 1, 1.25, 1.5], oe = 1, le = 0.25, Q = 5, te = 0.1, q = 12, vt = 1, bt = 250, yt = [25, 50, 75], Lt = 300 * 1e3, wt = 10, kt = 0.03;
49
+ function ne(e) {
50
+ if (!Number.isFinite(e) || e < 0) return "0:00";
51
+ const t = Math.floor(e / 60), a = Math.floor(e % 60);
52
+ return `${t}:${a.toString().padStart(2, "0")}`;
53
+ }
54
+ function se(e) {
55
+ return `${e}x`;
56
+ }
57
+ function xt(e) {
58
+ return Re.includes(e);
59
+ }
60
+ const De = {
61
+ x: 12,
62
+ y: 15,
63
+ textAnchor: "middle",
64
+ fontSize: 8,
65
+ fontWeight: 700,
66
+ fontFamily: "inherit",
67
+ letterSpacing: -0.4
68
+ }, ue = re(({ animate: e, ...t }, a) => /* @__PURE__ */ R(
69
+ "svg",
70
+ {
71
+ xmlns: "http://www.w3.org/2000/svg",
72
+ viewBox: "0 0 24 24",
73
+ fill: "none",
74
+ ref: a,
75
+ ...t,
76
+ "aria-hidden": "true",
77
+ children: [
78
+ /* @__PURE__ */ l(
79
+ "rect",
80
+ {
81
+ x: 3.5,
82
+ y: 6.5,
83
+ width: 17,
84
+ height: 11,
85
+ rx: 2.5,
86
+ stroke: "currentColor",
87
+ vectorEffect: "non-scaling-stroke"
88
+ }
89
+ ),
90
+ /* @__PURE__ */ l("text", { ...De, fill: "currentColor", children: "AD" })
91
+ ]
92
+ }
93
+ ));
94
+ ue.displayName = "AudioDescriptionLineIcon";
95
+ const Te = re(({ animate: e, ...t }, a) => {
96
+ const n = `ad-mask-${ft().replace(/:/g, "")}`;
97
+ return /* @__PURE__ */ R(
98
+ "svg",
99
+ {
100
+ xmlns: "http://www.w3.org/2000/svg",
101
+ viewBox: "0 0 24 24",
102
+ fill: "none",
103
+ ref: a,
104
+ ...t,
105
+ "aria-hidden": "true",
106
+ children: [
107
+ /* @__PURE__ */ R("mask", { id: n, maskUnits: "userSpaceOnUse", children: [
108
+ /* @__PURE__ */ l("rect", { x: 3, y: 6, width: 18, height: 12, rx: 3, fill: "white" }),
109
+ /* @__PURE__ */ l("text", { ...De, fill: "black", children: "AD" })
110
+ ] }),
111
+ /* @__PURE__ */ l(
112
+ "rect",
113
+ {
114
+ x: 3,
115
+ y: 6,
116
+ width: 18,
117
+ height: 12,
118
+ rx: 3,
119
+ fill: "currentColor",
120
+ mask: `url(#${n})`
121
+ }
122
+ )
123
+ ]
124
+ }
125
+ );
126
+ });
127
+ Te.displayName = "AudioDescriptionFilledIcon";
128
+ const fe = re(
129
+ ({ animate: e, ...t }, a) => /* @__PURE__ */ R(
130
+ "svg",
131
+ {
132
+ xmlns: "http://www.w3.org/2000/svg",
133
+ fill: "none",
134
+ viewBox: "0 0 24 24",
135
+ ref: a,
136
+ ...t,
137
+ children: [
138
+ /* @__PURE__ */ l(
139
+ "rect",
140
+ {
141
+ x: 3.5,
142
+ y: 6.5,
143
+ width: 17,
144
+ height: 11,
145
+ rx: 2.5,
146
+ stroke: "currentColor",
147
+ vectorEffect: "non-scaling-stroke"
148
+ }
149
+ ),
150
+ /* @__PURE__ */ l(
151
+ "path",
152
+ {
153
+ stroke: "currentColor",
154
+ strokeLinecap: "round",
155
+ d: "M7 10.75h8",
156
+ vectorEffect: "non-scaling-stroke"
157
+ }
158
+ ),
159
+ /* @__PURE__ */ l(
160
+ "path",
161
+ {
162
+ stroke: "currentColor",
163
+ strokeLinecap: "round",
164
+ d: "M7 13.75h4.5",
165
+ vectorEffect: "non-scaling-stroke"
166
+ }
167
+ )
168
+ ]
169
+ }
170
+ )
171
+ );
172
+ fe.displayName = "CaptionsLineIcon";
173
+ const Me = re(
174
+ ({ animate: e, ...t }, a) => /* @__PURE__ */ l(
175
+ "svg",
176
+ {
177
+ xmlns: "http://www.w3.org/2000/svg",
178
+ fill: "none",
179
+ viewBox: "0 0 24 24",
180
+ ref: a,
181
+ ...t,
182
+ children: /* @__PURE__ */ l(
183
+ "path",
184
+ {
185
+ fill: "currentColor",
186
+ fillRule: "evenodd",
187
+ clipRule: "evenodd",
188
+ d: "M6 6h12a3 3 0 0 1 3 3v6a3 3 0 0 1-3 3H6a3 3 0 0 1-3-3V9a3 3 0 0 1 3-3Zm1.25 4.5a.75.75 0 0 0 0 1.5h7.5a.75.75 0 0 0 0-1.5h-7.5Zm0 3a.75.75 0 0 0 0 1.5h4a.75.75 0 0 0 0-1.5h-4Z",
189
+ vectorEffect: "non-scaling-stroke"
190
+ }
191
+ )
192
+ }
193
+ )
194
+ );
195
+ Me.displayName = "CaptionsFilledIcon";
196
+ function Et({
197
+ value: e,
198
+ onChange: t,
199
+ containerRef: a
200
+ }) {
201
+ const { t: n } = W(), [o, i] = x(!1), r = (u) => {
202
+ const d = Array.from(
203
+ u.currentTarget.querySelectorAll(
204
+ '[role="menuitemradio"]'
205
+ )
206
+ );
207
+ if (d.length === 0) return;
208
+ const m = d.indexOf(document.activeElement);
209
+ let g;
210
+ switch (u.key) {
211
+ case "ArrowDown":
212
+ g = m < 0 ? 0 : (m + 1) % d.length;
213
+ break;
214
+ case "ArrowUp":
215
+ g = m <= 0 ? d.length - 1 : m - 1;
216
+ break;
217
+ case "Home":
218
+ g = 0;
219
+ break;
220
+ case "End":
221
+ g = d.length - 1;
222
+ break;
223
+ default:
224
+ return;
225
+ }
226
+ u.preventDefault(), d[g]?.focus();
227
+ };
228
+ return /* @__PURE__ */ R(je, { open: o, onOpenChange: i, children: [
229
+ /* @__PURE__ */ l(Ge, { asChild: !0, children: /* @__PURE__ */ l(
230
+ $,
231
+ {
232
+ variant: "ghost",
233
+ size: "sm",
234
+ label: se(e),
235
+ "aria-label": n("videoPlayer.playbackSpeed", {
236
+ rate: se(e)
237
+ })
238
+ }
239
+ ) }),
240
+ /* @__PURE__ */ l(
241
+ Xe,
242
+ {
243
+ container: a.current,
244
+ side: "top",
245
+ align: "end",
246
+ sideOffset: 8,
247
+ className: H(
248
+ "flex w-auto min-w-[7rem] flex-col gap-0.5 rounded-md border",
249
+ "border-solid border-f1-border-secondary bg-f1-background p-1 shadow-md"
250
+ ),
251
+ role: "menu",
252
+ "aria-label": n("videoPlayer.playbackSpeedLabel"),
253
+ onKeyDown: r,
254
+ children: Re.map((u) => {
255
+ const d = u === e;
256
+ return /* @__PURE__ */ R(
257
+ "button",
258
+ {
259
+ type: "button",
260
+ role: "menuitemradio",
261
+ "aria-checked": d,
262
+ className: H(
263
+ "relative flex items-center rounded-xs py-1.5 pl-8 pr-3",
264
+ "cursor-pointer border-none bg-transparent text-left text-sm font-medium tabular-nums",
265
+ "text-f1-foreground transition-colors hover:bg-f1-background-secondary",
266
+ "focus-visible:bg-f1-background-secondary focus-visible:outline-none",
267
+ "[&_svg]:h-3.5 [&_svg]:w-3.5"
268
+ ),
269
+ onClick: () => {
270
+ t(u), i(!1);
271
+ },
272
+ children: [
273
+ d && /* @__PURE__ */ l("span", { className: "absolute left-2.5 inline-flex items-center", children: /* @__PURE__ */ l(Ze, {}) }),
274
+ se(u)
275
+ ]
276
+ },
277
+ u
278
+ );
279
+ })
280
+ }
281
+ )
282
+ ] });
283
+ }
284
+ const ie = "off", we = "py-2 pr-4 text-base font-medium", Ct = "gap-2 py-2 pl-3 pr-2 text-base font-medium", Ae = "max-h-[var(--radix-dropdown-menu-content-available-height)] min-w-[13rem] overflow-y-auto p-1";
285
+ function ce({
286
+ icon: e,
287
+ label: t,
288
+ container: a,
289
+ options: n,
290
+ value: o,
291
+ onLanguageChange: i,
292
+ on: r,
293
+ onOff: u,
294
+ offLabel: d
295
+ }) {
296
+ const m = u !== void 0, g = n.find((c) => c.locale === o), y = m && !r ? d : g ? Le(g) : d;
297
+ return /* @__PURE__ */ R(Qe, { children: [
298
+ /* @__PURE__ */ R(et, { className: Ct, children: [
299
+ /* @__PURE__ */ l(tt, { icon: e }),
300
+ /* @__PURE__ */ l("span", { className: "flex-1", children: t }),
301
+ /* @__PURE__ */ l("span", { className: "text-f1-foreground-secondary", children: y })
302
+ ] }),
303
+ /* @__PURE__ */ l(nt, { container: a ?? void 0, children: /* @__PURE__ */ l(rt, { className: Ae, children: /* @__PURE__ */ R(
304
+ at,
305
+ {
306
+ value: m ? r ? o : ie : o,
307
+ onValueChange: (c) => m && c === ie ? u() : i(c),
308
+ children: [
309
+ n.map((c) => /* @__PURE__ */ l(
310
+ ye,
311
+ {
312
+ value: c.locale,
313
+ className: we,
314
+ children: Le(c)
315
+ },
316
+ c.locale
317
+ )),
318
+ m && /* @__PURE__ */ l(ye, { value: ie, className: we, children: d })
319
+ ]
320
+ }
321
+ ) }) })
322
+ ] });
323
+ }
324
+ function Pt({
325
+ containerRef: e,
326
+ audioLanguages: t,
327
+ audioLanguage: a,
328
+ onAudioLanguageChange: n,
329
+ captionLanguages: o,
330
+ captionLanguage: i,
331
+ captionsOn: r,
332
+ onCaptionLanguageChange: u,
333
+ onCaptionsOff: d,
334
+ audioDescriptionLanguages: m,
335
+ audioDescriptionLanguage: g,
336
+ audioDescriptionOn: y,
337
+ onAudioDescriptionLanguageChange: c,
338
+ onAudioDescriptionOff: f
339
+ }) {
340
+ const { t: h } = W(), b = e.current, E = h("videoPlayer.off");
341
+ return /* @__PURE__ */ R(qe, { children: [
342
+ /* @__PURE__ */ l(Ye, { asChild: !0, children: /* @__PURE__ */ l(
343
+ $,
344
+ {
345
+ variant: "ghost",
346
+ size: "sm",
347
+ hideLabel: !0,
348
+ icon: mt,
349
+ label: h("videoPlayer.settings")
350
+ }
351
+ ) }),
352
+ /* @__PURE__ */ R(
353
+ Je,
354
+ {
355
+ container: b,
356
+ side: "top",
357
+ align: "end",
358
+ className: Ae,
359
+ children: [
360
+ t.length > 1 && /* @__PURE__ */ l(
361
+ ce,
362
+ {
363
+ icon: pt,
364
+ label: h("videoPlayer.audio"),
365
+ container: b,
366
+ options: t,
367
+ value: a,
368
+ onLanguageChange: n,
369
+ offLabel: E
370
+ }
371
+ ),
372
+ o.length > 1 && /* @__PURE__ */ l(
373
+ ce,
374
+ {
375
+ icon: fe,
376
+ label: h("videoPlayer.subtitles"),
377
+ container: b,
378
+ options: o,
379
+ value: i,
380
+ on: r,
381
+ onLanguageChange: u,
382
+ onOff: d,
383
+ offLabel: E
384
+ }
385
+ ),
386
+ m.length > 1 && /* @__PURE__ */ l(
387
+ ce,
388
+ {
389
+ icon: ue,
390
+ label: h("videoPlayer.audioDescription"),
391
+ container: b,
392
+ options: m,
393
+ value: g,
394
+ on: y,
395
+ onLanguageChange: c,
396
+ onOff: f,
397
+ offLabel: E
398
+ }
399
+ )
400
+ ]
401
+ }
402
+ )
403
+ ] });
404
+ }
405
+ function St(e) {
406
+ return e.audioLanguages > 1 || e.captionLanguages > 1 || e.audioDescriptionLanguages > 1;
407
+ }
408
+ function Rt({
409
+ currentTime: e,
410
+ duration: t,
411
+ markerTime: a,
412
+ blockSeekPastMarker: n = !1,
413
+ onSeek: o
414
+ }) {
415
+ const { t: i } = W(), r = O(null), [u, d] = x(!1), [m, g] = x(null), y = t > 0 ? Math.min(1, e / t) : 0, c = a !== void 0 && t > 0 ? Math.min(1, a / t) : 0, f = a !== void 0 && t > 0 && a > 0 && a < t - le && e < a - le, h = (v) => {
416
+ const S = r.current;
417
+ if (!S) return 0;
418
+ const I = S.getBoundingClientRect();
419
+ return Math.max(0, Math.min(1, (v - I.left) / I.width));
420
+ }, b = (v) => {
421
+ t && o(h(v) * t);
422
+ }, E = (v) => {
423
+ t && (v.preventDefault(), v.currentTarget.setPointerCapture(v.pointerId), d(!0), b(v.clientX));
424
+ }, A = (v) => {
425
+ t && (g(h(v.clientX)), u && b(v.clientX));
426
+ }, k = (v) => {
427
+ u && (d(!1), v.currentTarget.hasPointerCapture(v.pointerId) && v.currentTarget.releasePointerCapture(v.pointerId));
428
+ }, L = m !== null && n && a !== void 0 && m > c, T = (v) => {
429
+ if (!t) return;
430
+ let S = null;
431
+ switch (v.key) {
432
+ case "ArrowLeft":
433
+ S = Math.max(0, e - Q);
434
+ break;
435
+ case "ArrowRight":
436
+ S = Math.min(t, e + Q);
437
+ break;
438
+ case "Home":
439
+ S = 0;
440
+ break;
441
+ case "End":
442
+ S = t;
443
+ break;
444
+ default:
445
+ return;
446
+ }
447
+ v.preventDefault(), v.stopPropagation(), o(S);
448
+ };
449
+ return /* @__PURE__ */ R(
450
+ "div",
451
+ {
452
+ ref: r,
453
+ className: H(
454
+ "relative flex h-4 flex-1 items-center rounded-sm",
455
+ "cursor-pointer touch-none",
456
+ de()
457
+ ),
458
+ role: "slider",
459
+ tabIndex: 0,
460
+ "aria-label": i("videoPlayer.seekLabel"),
461
+ "aria-valuemin": 0,
462
+ "aria-valuemax": t || 0,
463
+ "aria-valuenow": e,
464
+ "aria-valuetext": i("videoPlayer.timeProgress", {
465
+ current: ne(e),
466
+ total: ne(t)
467
+ }),
468
+ onPointerDown: E,
469
+ onPointerMove: A,
470
+ onPointerUp: k,
471
+ onPointerCancel: k,
472
+ onLostPointerCapture: () => d(!1),
473
+ onPointerLeave: () => g(null),
474
+ onKeyDown: T,
475
+ children: [
476
+ /* @__PURE__ */ l("div", { className: "absolute inset-x-0 h-1 rounded-sm bg-f1-foreground/30" }),
477
+ /* @__PURE__ */ l(
478
+ "div",
479
+ {
480
+ className: "pointer-events-none absolute left-0 h-1 rounded-sm bg-f1-foreground",
481
+ style: { width: `${y * 100}%` }
482
+ }
483
+ ),
484
+ f && /* @__PURE__ */ l(
485
+ "div",
486
+ {
487
+ className: "pointer-events-none absolute z-[1] h-2.5 w-0.5 -translate-x-px bg-f1-foreground/95",
488
+ style: { left: `${c * 100}%` },
489
+ "aria-hidden": "true"
490
+ }
491
+ ),
492
+ /* @__PURE__ */ l(
493
+ "div",
494
+ {
495
+ className: "pointer-events-none absolute z-[2] h-3 w-3 -translate-x-1/2 rounded-full bg-f1-foreground shadow-[0_0_4px_rgba(0,0,0,0.4)]",
496
+ style: { left: `${y * 100}%` }
497
+ }
498
+ ),
499
+ L && /* @__PURE__ */ l("div", { className: "absolute inset-0 cursor-not-allowed" })
500
+ ]
501
+ }
502
+ );
503
+ }
504
+ function Dt(e, t) {
505
+ return t || e === 0 ? Pe : e <= 0.5 ? ht : gt;
506
+ }
507
+ function Tt({
508
+ volume: e,
509
+ isMuted: t,
510
+ onToggleMute: a,
511
+ onVolumeChange: n,
512
+ silent: o = !1
513
+ }) {
514
+ const { t: i } = W(), r = t || e === 0;
515
+ return o ? /* @__PURE__ */ l(
516
+ $,
517
+ {
518
+ variant: "ghost",
519
+ size: "sm",
520
+ hideLabel: !0,
521
+ disabled: !0,
522
+ icon: Pe,
523
+ label: i("videoPlayer.noAudio")
524
+ }
525
+ ) : /* @__PURE__ */ R("div", { className: "flex items-center gap-1", children: [
526
+ /* @__PURE__ */ l(
527
+ $,
528
+ {
529
+ variant: "ghost",
530
+ size: "sm",
531
+ hideLabel: !0,
532
+ icon: Dt(e, r),
533
+ label: i(r ? "videoPlayer.unmute" : "videoPlayer.mute"),
534
+ onClick: a
535
+ }
536
+ ),
537
+ /* @__PURE__ */ l(Mt, { value: r ? 0 : e, onChange: n })
538
+ ] });
539
+ }
540
+ function Mt({ value: e, onChange: t }) {
541
+ const { t: a } = W(), n = O(null), [o, i] = x(!1), r = Math.max(0, Math.min(1, e)), u = (c) => {
542
+ const f = n.current;
543
+ if (!f) return 0;
544
+ const h = f.getBoundingClientRect(), b = h.width - q;
545
+ return b <= 0 ? 0 : Math.max(
546
+ 0,
547
+ Math.min(1, (c - h.left - q / 2) / b)
548
+ );
549
+ }, d = (c) => {
550
+ c.preventDefault(), c.currentTarget.setPointerCapture(c.pointerId), i(!0), t(u(c.clientX));
551
+ }, m = (c) => {
552
+ o && t(u(c.clientX));
553
+ }, g = (c) => {
554
+ o && (i(!1), c.currentTarget.hasPointerCapture(c.pointerId) && c.currentTarget.releasePointerCapture(c.pointerId));
555
+ }, y = (c) => {
556
+ let f = null;
557
+ switch (c.key) {
558
+ case "ArrowRight":
559
+ case "ArrowUp":
560
+ f = Math.min(1, r + te);
561
+ break;
562
+ case "ArrowLeft":
563
+ case "ArrowDown":
564
+ f = Math.max(0, r - te);
565
+ break;
566
+ case "Home":
567
+ f = 0;
568
+ break;
569
+ case "End":
570
+ f = 1;
571
+ break;
572
+ default:
573
+ return;
574
+ }
575
+ c.preventDefault(), c.stopPropagation(), t(f);
576
+ };
577
+ return /* @__PURE__ */ R(
578
+ "div",
579
+ {
580
+ ref: n,
581
+ className: H(
582
+ "relative flex h-4 w-[60px] items-center rounded-sm",
583
+ "cursor-pointer touch-none",
584
+ de()
585
+ ),
586
+ role: "slider",
587
+ tabIndex: 0,
588
+ "aria-label": a("videoPlayer.volume"),
589
+ "aria-valuemin": 0,
590
+ "aria-valuemax": 1,
591
+ "aria-valuenow": Number(r.toFixed(2)),
592
+ "aria-valuetext": `${Math.round(r * 100)}%`,
593
+ onPointerDown: d,
594
+ onPointerMove: m,
595
+ onPointerUp: g,
596
+ onPointerCancel: g,
597
+ onLostPointerCapture: () => i(!1),
598
+ onKeyDown: y,
599
+ children: [
600
+ /* @__PURE__ */ l("div", { className: "absolute inset-x-0 h-1 rounded-sm bg-f1-foreground/30" }),
601
+ /* @__PURE__ */ l(
602
+ "div",
603
+ {
604
+ className: "pointer-events-none absolute left-0 h-1 rounded-sm bg-f1-foreground",
605
+ style: {
606
+ width: `calc(${q}px + (100% - ${q}px) * ${r})`
607
+ }
608
+ }
609
+ ),
610
+ /* @__PURE__ */ l(
611
+ "div",
612
+ {
613
+ className: "pointer-events-none absolute h-3 w-3 -translate-x-1/2 rounded-full bg-f1-foreground shadow-[0_0_4px_rgba(0,0,0,0.4)]",
614
+ style: {
615
+ left: `calc(${q / 2}px + (100% - ${q}px) * ${r})`
616
+ }
617
+ }
618
+ )
619
+ ]
620
+ }
621
+ );
622
+ }
623
+ function At({
624
+ isPlaying: e,
625
+ currentTime: t,
626
+ duration: a,
627
+ volume: n,
628
+ isMuted: o,
629
+ playbackRate: i,
630
+ isFullscreen: r,
631
+ markerTime: u,
632
+ blockSeekPastMarker: d,
633
+ containerRef: m,
634
+ captionsAvailable: g,
635
+ captionsOn: y,
636
+ audioDescriptionAvailable: c,
637
+ audioDescriptionOn: f,
638
+ silent: h,
639
+ persist: b,
640
+ audioLanguages: E,
641
+ audioLanguage: A,
642
+ onAudioLanguageChange: k,
643
+ captionLanguages: L,
644
+ captionLanguage: T,
645
+ onCaptionLanguageChange: v,
646
+ onCaptionsOff: S,
647
+ audioDescriptionLanguages: I,
648
+ audioDescriptionLanguage: C,
649
+ onAudioDescriptionLanguageChange: s,
650
+ onAudioDescriptionOff: P,
651
+ onTogglePlay: D,
652
+ onToggleMute: B,
653
+ onVolumeChange: j,
654
+ onPlaybackRateChange: K,
655
+ onToggleFullscreen: G,
656
+ onToggleCaptions: F,
657
+ onToggleAudioDescription: V,
658
+ onSeek: Y,
659
+ download: X
660
+ }) {
661
+ const { t: p } = W(), N = g && L.length <= 1, z = c && I.length <= 1, U = St({
662
+ audioLanguages: E.length,
663
+ captionLanguages: L.length,
664
+ audioDescriptionLanguages: I.length
665
+ });
666
+ return /* @__PURE__ */ R(
667
+ "div",
668
+ {
669
+ className: H(
670
+ // `dark` scopes the on-video controls to white; the playback-speed menu
671
+ // portals to the player root (outside this scope) so it follows the
672
+ // app's real theme — light by default, dark when the app is in dark mode.
673
+ "dark absolute inset-x-0 bottom-0 z-[2] flex select-none items-center gap-2",
674
+ // Plain dark gradient scrim (like the original trainings player). f0's
675
+ // Tailwind palette has no `black`, so the stops use arbitrary hex+alpha.
676
+ // `rounded-b-[inherit]` keeps the bottom corners on the player's radius.
677
+ "rounded-b-[inherit] bg-gradient-to-t from-[#000000f2] via-[#000000b3] to-transparent px-3 py-3",
678
+ // Shadow so the white controls stay legible over light *and* dark frames.
679
+ "[text-shadow:0_1px_2px_rgba(0,0,0,0.55)] [&_svg]:drop-shadow-[0_1px_2px_rgba(0,0,0,0.55)]",
680
+ "transition-opacity duration-200 motion-reduce:transition-none",
681
+ // Always visible while paused (a paused video should look controllable,
682
+ // not like a still image) or when `persist` is set; otherwise they
683
+ // auto-hide during playback and reveal on hover or keyboard focus.
684
+ !e || b ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100"
685
+ ),
686
+ children: [
687
+ /* @__PURE__ */ l(
688
+ $,
689
+ {
690
+ variant: "ghost",
691
+ size: "sm",
692
+ hideLabel: !0,
693
+ icon: e ? ot : Ce,
694
+ label: p(e ? "videoPlayer.pause" : "videoPlayer.play"),
695
+ onClick: D
696
+ }
697
+ ),
698
+ /* @__PURE__ */ l(
699
+ Rt,
700
+ {
701
+ currentTime: t,
702
+ duration: a,
703
+ markerTime: u,
704
+ blockSeekPastMarker: d,
705
+ onSeek: Y
706
+ }
707
+ ),
708
+ /* @__PURE__ */ R("span", { className: "min-w-[80px] whitespace-nowrap text-center text-base font-medium tabular-nums text-f1-foreground", children: [
709
+ ne(t),
710
+ " / ",
711
+ ne(a)
712
+ ] }),
713
+ /* @__PURE__ */ l(
714
+ Tt,
715
+ {
716
+ volume: n,
717
+ isMuted: o,
718
+ onToggleMute: B,
719
+ onVolumeChange: j,
720
+ silent: h
721
+ }
722
+ ),
723
+ /* @__PURE__ */ l(
724
+ Et,
725
+ {
726
+ value: i,
727
+ onChange: K,
728
+ containerRef: m
729
+ }
730
+ ),
731
+ N && // Filled glyph when captions are on, line glyph when off; `aria-pressed`
732
+ // conveys the state to assistive tech (the label stays stable).
733
+ /* @__PURE__ */ l(
734
+ $,
735
+ {
736
+ variant: "ghost",
737
+ size: "sm",
738
+ hideLabel: !0,
739
+ icon: y ? Me : fe,
740
+ label: p("videoPlayer.captions"),
741
+ "aria-pressed": y,
742
+ onClick: F
743
+ }
744
+ ),
745
+ z && // Filled "AD" badge when on, line badge when off — the same on/off
746
+ // language as captions, legible over video. `hideLabel` gives the
747
+ // captions-style tooltip from the label; `aria-pressed` conveys state.
748
+ /* @__PURE__ */ l(
749
+ $,
750
+ {
751
+ variant: "ghost",
752
+ size: "sm",
753
+ hideLabel: !0,
754
+ icon: f ? Te : ue,
755
+ label: p("videoPlayer.audioDescription"),
756
+ "aria-pressed": f,
757
+ onClick: V
758
+ }
759
+ ),
760
+ U && /* @__PURE__ */ l(
761
+ Pt,
762
+ {
763
+ containerRef: m,
764
+ audioLanguages: E,
765
+ audioLanguage: A,
766
+ onAudioLanguageChange: k,
767
+ captionLanguages: L,
768
+ captionLanguage: T,
769
+ captionsOn: y,
770
+ onCaptionLanguageChange: v,
771
+ onCaptionsOff: S,
772
+ audioDescriptionLanguages: I,
773
+ audioDescriptionLanguage: C,
774
+ audioDescriptionOn: f,
775
+ onAudioDescriptionLanguageChange: s,
776
+ onAudioDescriptionOff: P
777
+ }
778
+ ),
779
+ X && /* @__PURE__ */ l(
780
+ $,
781
+ {
782
+ variant: "ghost",
783
+ size: "sm",
784
+ hideLabel: !0,
785
+ icon: st,
786
+ label: X.label,
787
+ onClick: X.onClick
788
+ }
789
+ ),
790
+ /* @__PURE__ */ l(
791
+ $,
792
+ {
793
+ variant: "ghost",
794
+ size: "sm",
795
+ hideLabel: !0,
796
+ icon: r ? it : ct,
797
+ label: p(r ? "videoPlayer.exitFullscreen" : "videoPlayer.enterFullscreen"),
798
+ onClick: G
799
+ }
800
+ )
801
+ ]
802
+ }
803
+ );
804
+ }
805
+ const ke = (e) => e.trimStart().startsWith("WEBVTT");
806
+ function Ie(e) {
807
+ const t = e !== void 0 && ke(e), [a, n] = x();
808
+ return _(() => {
809
+ if (e === void 0 || !ke(e)) {
810
+ n(void 0);
811
+ return;
812
+ }
813
+ const o = URL.createObjectURL(new Blob([e], { type: "text/vtt" }));
814
+ return n(o), () => URL.revokeObjectURL(o);
815
+ }, [e]), {
816
+ trackSrc: e === void 0 ? void 0 : t ? a : e,
817
+ needsCrossOrigin: e !== void 0 && !t
818
+ };
819
+ }
820
+ const xe = "descriptions";
821
+ function It(e, { enabled: t, describedSrc: a, descriptions: n }) {
822
+ const o = a !== void 0, { trackSrc: i, needsCrossOrigin: r } = Ie(n), [u, d] = x(!1), m = o || n !== void 0 || u, [g, y] = x(), c = O(!1);
823
+ return _(() => {
824
+ if (!e) return;
825
+ const f = e.textTracks, h = typeof window < "u" && "speechSynthesis" in window, b = t && !o && h, E = () => {
826
+ c.current && (c.current = !1, e.play().catch(() => {
827
+ }));
828
+ }, A = (C) => {
829
+ window.speechSynthesis.cancel();
830
+ const s = new SpeechSynthesisUtterance(C);
831
+ s.onend = E, s.onerror = E, window.speechSynthesis.speak(s);
832
+ }, k = /* @__PURE__ */ new WeakSet(), L = [], T = (C) => {
833
+ if (C.kind !== xe || (C.mode = "hidden", k.has(C)) || typeof C.addEventListener != "function") return;
834
+ k.add(C);
835
+ const s = () => {
836
+ const D = C.activeCues?.[0]?.text || void 0;
837
+ y(D), b && D && (e.paused || (e.pause(), c.current = !0), A(D));
838
+ };
839
+ C.addEventListener("cuechange", s), L.push(() => C.removeEventListener("cuechange", s));
840
+ }, v = () => {
841
+ let C = !1;
842
+ for (let s = 0; s < f.length; s++) {
843
+ const P = f[s];
844
+ P.kind === xe && (n === void 0 && (C = !0), T(P));
845
+ }
846
+ d(C);
847
+ };
848
+ v();
849
+ const S = typeof f.addEventListener == "function", I = () => v();
850
+ return S && (f.addEventListener("addtrack", I), f.addEventListener("removetrack", I)), () => {
851
+ S && (f.removeEventListener("addtrack", I), f.removeEventListener("removetrack", I)), L.forEach((C) => C()), h && window.speechSynthesis.cancel(), E();
852
+ };
853
+ }, [e, t, o, n, i]), J(
854
+ () => ({ trackSrc: i, needsCrossOrigin: r, available: m, activeCue: g }),
855
+ [i, r, m, g]
856
+ );
857
+ }
858
+ function Nt({
859
+ targetRef: e
860
+ }) {
861
+ const [t, a] = x(!1);
862
+ _(() => {
863
+ const o = () => {
864
+ a(document.fullscreenElement === e.current);
865
+ };
866
+ return document.addEventListener("fullscreenchange", o), () => {
867
+ document.removeEventListener("fullscreenchange", o);
868
+ };
869
+ }, [e]);
870
+ const n = M(async () => {
871
+ const o = e.current;
872
+ if (o)
873
+ try {
874
+ document.fullscreenElement ? await document.exitFullscreen() : await o.requestFullscreen();
875
+ } catch {
876
+ }
877
+ }, [e]);
878
+ return { isFullscreen: t, toggleFullscreen: n };
879
+ }
880
+ function _t({
881
+ videoRef: e,
882
+ seek: t,
883
+ togglePlay: a,
884
+ toggleMute: n,
885
+ toggleFullscreen: o,
886
+ setVolume: i
887
+ }) {
888
+ return M(
889
+ (r) => {
890
+ const u = r.target;
891
+ if (u instanceof HTMLElement && (u.closest(
892
+ 'button, a, input, textarea, select, [role="button"], [contenteditable="true"]'
893
+ ) || u.closest('[role="menu"], [role^="menuitem"]') || u.getAttribute("role") === "slider"))
894
+ return;
895
+ const d = e.current;
896
+ if (!d) return;
897
+ switch (r.key.length === 1 ? r.key.toLowerCase() : r.key) {
898
+ case " ":
899
+ r.preventDefault(), a();
900
+ return;
901
+ case "ArrowLeft":
902
+ r.preventDefault(), t(Math.max(0, d.currentTime - Q));
903
+ return;
904
+ case "ArrowRight": {
905
+ r.preventDefault();
906
+ const g = d.duration || d.currentTime + Q;
907
+ t(Math.min(g, d.currentTime + Q));
908
+ return;
909
+ }
910
+ case "ArrowUp":
911
+ r.preventDefault(), i(Math.min(1, d.volume + te));
912
+ return;
913
+ case "ArrowDown":
914
+ r.preventDefault(), i(Math.max(0, d.volume - te));
915
+ return;
916
+ case "m":
917
+ r.preventDefault(), n();
918
+ return;
919
+ case "f":
920
+ r.preventDefault(), o();
921
+ return;
922
+ default:
923
+ return;
924
+ }
925
+ },
926
+ [e, t, a, n, o, i]
927
+ );
928
+ }
929
+ function Ft({
930
+ video: e,
931
+ enabled: t,
932
+ resetKey: a
933
+ }) {
934
+ const n = O(0), o = O(0), i = O(t);
935
+ i.current = t;
936
+ const [r, u] = x(0);
937
+ _(() => {
938
+ n.current = 0, o.current = 0, u(0);
939
+ }, [a]), _(() => {
940
+ if (!e) return;
941
+ const m = () => {
942
+ i.current && e.currentTime > n.current + le && (e.currentTime = n.current);
943
+ }, g = () => {
944
+ u((h) => {
945
+ const b = n.current;
946
+ return b - h >= 1 ? b : h;
947
+ });
948
+ }, y = () => {
949
+ u((h) => Math.max(h, n.current));
950
+ }, c = () => {
951
+ const h = e.currentTime - o.current;
952
+ h >= 0 && h < vt && e.currentTime > n.current && (n.current = e.currentTime, g()), m(), o.current = e.currentTime;
953
+ }, f = () => {
954
+ m(), y();
955
+ };
956
+ return e.addEventListener("timeupdate", c), e.addEventListener("seeking", f), e.addEventListener("seeked", f), e.addEventListener("pause", y), e.addEventListener("ended", y), () => {
957
+ e.removeEventListener("timeupdate", c), e.removeEventListener("seeking", f), e.removeEventListener("seeked", f), e.removeEventListener("pause", y), e.removeEventListener("ended", y);
958
+ };
959
+ }, [e]);
960
+ const d = M((m) => i.current ? Math.min(m, n.current) : m, []);
961
+ return { maxWatchedTime: r, clampSeek: d };
962
+ }
963
+ const Ee = /* @__PURE__ */ new Set([
964
+ "captions",
965
+ "subtitles"
966
+ ]), Ot = 2, Ut = 3;
967
+ function Vt(e, t) {
968
+ const { trackSrc: a, needsCrossOrigin: n } = Ie(t), [o, i] = x(!1), [r, u] = x(!1), [d, m] = x(!1), y = r || t !== void 0 && !d;
969
+ return _(() => {
970
+ m(!1), u(!1);
971
+ }, [a]), _(() => {
972
+ if (!e) return;
973
+ const c = e.textTracks, f = e.querySelector(
974
+ 'track[kind="captions"]'
975
+ ), h = () => {
976
+ let k = !1;
977
+ for (let L = 0; L < c.length; L++) {
978
+ const T = c[L];
979
+ Ee.has(T.kind) && (T.mode = o ? "showing" : "hidden", T.cues && T.cues.length > 0 && (k = !0));
980
+ }
981
+ if (u(k), f) {
982
+ if (f.readyState === Ut)
983
+ m(!0);
984
+ else if (f.readyState === Ot) {
985
+ const L = f.track?.cues;
986
+ m(!L || L.length === 0);
987
+ }
988
+ }
989
+ };
990
+ h();
991
+ const b = [];
992
+ if (f) {
993
+ const k = () => h(), L = () => m(!0);
994
+ f.addEventListener("load", k), f.addEventListener("error", L), b.push(() => {
995
+ f.removeEventListener("load", k), f.removeEventListener("error", L);
996
+ });
997
+ }
998
+ for (let k = 0; k < c.length; k++) {
999
+ const L = c[k];
1000
+ if (!Ee.has(L.kind) || typeof L.addEventListener != "function") continue;
1001
+ const T = () => h();
1002
+ L.addEventListener("cuechange", T), b.push(() => L.removeEventListener("cuechange", T));
1003
+ }
1004
+ const E = typeof c.addEventListener == "function", A = () => h();
1005
+ return E && (c.addEventListener("addtrack", A), c.addEventListener("removetrack", A)), e.addEventListener("loadedmetadata", h), () => {
1006
+ b.forEach((k) => k()), E && (c.removeEventListener("addtrack", A), c.removeEventListener("removetrack", A)), e.removeEventListener("loadedmetadata", h);
1007
+ };
1008
+ }, [e, t, o, a]), J(
1009
+ () => ({
1010
+ trackSrc: a,
1011
+ needsCrossOrigin: n,
1012
+ available: y,
1013
+ showing: o,
1014
+ toggle: () => i((c) => !c)
1015
+ }),
1016
+ [a, n, y, o]
1017
+ );
1018
+ }
1019
+ function $t(e) {
1020
+ const t = Math.min(
1021
+ wt,
1022
+ e * kt
1023
+ );
1024
+ return e - t;
1025
+ }
1026
+ function Kt({
1027
+ video: e,
1028
+ onComplete: t,
1029
+ resetKey: a
1030
+ }) {
1031
+ const n = O(t);
1032
+ n.current = t;
1033
+ const o = O(!1), i = !!t;
1034
+ _(() => {
1035
+ o.current = !1;
1036
+ }, [a]), _(() => {
1037
+ if (!e || !i) return;
1038
+ const r = () => {
1039
+ o.current || !e.duration || e.currentTime >= $t(e.duration) && (o.current = !0, n.current?.(e));
1040
+ };
1041
+ return e.addEventListener("timeupdate", r), e.addEventListener("ended", r), () => {
1042
+ e.removeEventListener("timeupdate", r), e.removeEventListener("ended", r);
1043
+ };
1044
+ }, [e, i]);
1045
+ }
1046
+ function zt({
1047
+ video: e,
1048
+ onMilestone: t,
1049
+ resetKey: a
1050
+ }) {
1051
+ const n = O(t);
1052
+ n.current = t;
1053
+ const o = O(/* @__PURE__ */ new Set()), i = !!t;
1054
+ _(() => {
1055
+ o.current.clear();
1056
+ }, [a]), _(() => {
1057
+ if (!e || !i) return;
1058
+ const r = () => {
1059
+ if (!e.duration) return;
1060
+ const u = Math.round(e.currentTime / e.duration * 100);
1061
+ for (const d of yt)
1062
+ o.current.has(d) || u >= d && (o.current.add(d), n.current?.(d, e));
1063
+ };
1064
+ return e.addEventListener("timeupdate", r), () => {
1065
+ e.removeEventListener("timeupdate", r);
1066
+ };
1067
+ }, [e, i]);
1068
+ }
1069
+ function Bt(e) {
1070
+ const t = O(null), [a, n] = x(
1071
+ null
1072
+ ), o = O(0), i = M((s) => {
1073
+ t.current = s, n(s);
1074
+ }, []), [r, u] = x(!1), [d, m] = x(!1), [g, y] = x(0), [c, f] = x(0), [h, b] = x(1), [E, A] = x(!1), [k, L] = x(
1075
+ oe
1076
+ );
1077
+ _(() => {
1078
+ o.current = 0, t.current && (t.current.playbackRate = oe), u(!1), m(!1), y(0), f(0), L(oe);
1079
+ }, [e]), _(() => {
1080
+ const s = a;
1081
+ if (!s) return;
1082
+ const P = () => m(!0), D = () => m(!1), B = () => m(!1), j = () => {
1083
+ b(s.volume), A(s.muted);
1084
+ }, K = () => f(s.duration || 0), G = () => {
1085
+ xt(s.playbackRate) && L(s.playbackRate);
1086
+ }, F = () => {
1087
+ const V = performance.now();
1088
+ V - o.current >= bt && (o.current = V, y(s.currentTime));
1089
+ };
1090
+ return s.addEventListener("play", P), s.addEventListener("pause", D), s.addEventListener("ended", B), s.addEventListener("volumechange", j), s.addEventListener("loadedmetadata", K), s.addEventListener("ratechange", G), s.addEventListener("timeupdate", F), s.readyState >= 1 && s.duration && f(s.duration), () => {
1091
+ s.removeEventListener("play", P), s.removeEventListener("pause", D), s.removeEventListener("ended", B), s.removeEventListener("volumechange", j), s.removeEventListener("loadedmetadata", K), s.removeEventListener("ratechange", G), s.removeEventListener("timeupdate", F);
1092
+ };
1093
+ }, [a]);
1094
+ const T = M(() => {
1095
+ const s = t.current;
1096
+ s && (s.paused || s.ended ? s.play().catch(() => {
1097
+ }) : s.pause());
1098
+ }, []), v = M(() => {
1099
+ const s = t.current;
1100
+ s && (s.muted = !s.muted);
1101
+ }, []), S = M((s) => {
1102
+ const P = t.current;
1103
+ if (!P) return;
1104
+ const D = Math.max(0, Math.min(1, s));
1105
+ P.volume = D, P.muted = D === 0;
1106
+ }, []), I = M((s) => {
1107
+ const P = t.current;
1108
+ P && (P.playbackRate = s);
1109
+ }, []), C = M((s) => {
1110
+ const P = t.current;
1111
+ if (!P) return;
1112
+ const D = Math.max(0, Math.min(s, P.duration || s));
1113
+ P.currentTime = D, y(D);
1114
+ }, []);
1115
+ return {
1116
+ videoRef: t,
1117
+ videoElement: a,
1118
+ setVideoNode: i,
1119
+ videoLoaded: r,
1120
+ isPlaying: d,
1121
+ currentTime: g,
1122
+ duration: c,
1123
+ volume: h,
1124
+ isMuted: E,
1125
+ playbackRate: k,
1126
+ setVideoLoaded: u,
1127
+ togglePlay: T,
1128
+ toggleMute: v,
1129
+ setVolume: S,
1130
+ setPlaybackRate: I,
1131
+ seekTo: C
1132
+ };
1133
+ }
1134
+ function Ht({
1135
+ video: e,
1136
+ onTrackAction: t
1137
+ }) {
1138
+ const a = O(t);
1139
+ a.current = t;
1140
+ const n = !!t;
1141
+ _(() => {
1142
+ if (!e || !n) return;
1143
+ let o = null;
1144
+ const i = () => {
1145
+ o && (clearInterval(o), o = null);
1146
+ }, r = () => {
1147
+ a.current?.(), i(), o = setInterval(() => {
1148
+ a.current?.();
1149
+ }, Lt);
1150
+ }, u = () => {
1151
+ a.current?.(), i();
1152
+ }, d = () => i();
1153
+ return e.addEventListener("play", r), e.addEventListener("pause", u), e.addEventListener("ended", d), () => {
1154
+ i(), e.removeEventListener("play", r), e.removeEventListener("pause", u), e.removeEventListener("ended", d);
1155
+ };
1156
+ }, [e, n]);
1157
+ }
1158
+ function Wt({
1159
+ src: e,
1160
+ poster: t,
1161
+ ariaLabel: a,
1162
+ silent: n = !1,
1163
+ persistControls: o = !1,
1164
+ content: i,
1165
+ defaultLanguage: r,
1166
+ autoPlay: u = !1,
1167
+ autoFocus: d = !1,
1168
+ download: m,
1169
+ restrictForwardSeek: g = !1,
1170
+ onTrackAction: y,
1171
+ onMilestone: c,
1172
+ onComplete: f,
1173
+ ...h
1174
+ }) {
1175
+ const { t: b } = W(), E = O(null), A = J(() => ae(e), [e]), [k, L] = x(
1176
+ () => Z(A, r)
1177
+ ), T = A.some((w) => w.locale === k) ? k : Z(A, r), v = ee(e, T) ?? "", S = J(
1178
+ () => ae(i?.captions),
1179
+ [i?.captions]
1180
+ ), [I, C] = x(
1181
+ () => Z(S, r)
1182
+ ), s = S.some(
1183
+ (w) => w.locale === I
1184
+ ) ? I : Z(S, r), P = ee(i?.captions, s), D = J(
1185
+ () => ae(i?.descriptions, i?.describedSrc),
1186
+ [i?.descriptions, i?.describedSrc]
1187
+ ), [B, j] = x(
1188
+ () => Z(D, r)
1189
+ ), K = D.some(
1190
+ (w) => w.locale === B
1191
+ ) ? B : Z(D, r), G = ee(
1192
+ i?.descriptions,
1193
+ K
1194
+ ), F = ee(
1195
+ i?.describedSrc,
1196
+ K
1197
+ ), [V, Y] = x(!1), X = V && F ? F : v, p = Bt(X), N = Vt(p.videoElement, P), z = It(p.videoElement, {
1198
+ enabled: V,
1199
+ describedSrc: F,
1200
+ descriptions: G
1201
+ }), U = M(() => {
1202
+ const w = p.videoRef.current;
1203
+ if (!w) return;
1204
+ const He = w.currentTime, We = !w.paused, be = () => {
1205
+ w.currentTime = He, We && w.play().catch(() => {
1206
+ }), w.removeEventListener("loadedmetadata", be);
1207
+ };
1208
+ w.addEventListener("loadedmetadata", be);
1209
+ }, [p.videoRef]), Ne = M(
1210
+ (w) => {
1211
+ U(), L(w);
1212
+ },
1213
+ [U]
1214
+ ), _e = M(() => {
1215
+ F && U(), Y((w) => !w);
1216
+ }, [F, U]), Fe = M(
1217
+ (w) => {
1218
+ C(w), N.showing || N.toggle();
1219
+ },
1220
+ [N]
1221
+ ), Oe = M(() => {
1222
+ N.showing && N.toggle();
1223
+ }, [N]), Ue = M(
1224
+ (w) => {
1225
+ F && U(), j(w), Y(!0);
1226
+ },
1227
+ [F, U]
1228
+ ), Ve = M(() => {
1229
+ F && U(), Y(!1);
1230
+ }, [F, U]);
1231
+ Ht({ video: p.videoElement, onTrackAction: y }), zt({
1232
+ video: p.videoElement,
1233
+ onMilestone: c,
1234
+ resetKey: v
1235
+ }), Kt({
1236
+ video: p.videoElement,
1237
+ onComplete: f,
1238
+ resetKey: v
1239
+ });
1240
+ const { maxWatchedTime: $e, clampSeek: me } = Ft({
1241
+ video: p.videoElement,
1242
+ enabled: g,
1243
+ resetKey: v
1244
+ }), pe = M(
1245
+ (w) => p.seekTo(me(w)),
1246
+ [p, me]
1247
+ ), { isFullscreen: Ke, toggleFullscreen: he } = Nt({
1248
+ targetRef: E
1249
+ }), ge = M(() => {
1250
+ }, []), ve = !!(V && F);
1251
+ _(() => {
1252
+ const w = p.videoRef.current;
1253
+ n && w && (w.muted = !ve);
1254
+ }, [n, ve, p.videoElement, p.videoRef]);
1255
+ const ze = _t({
1256
+ videoRef: p.videoRef,
1257
+ seek: pe,
1258
+ togglePlay: p.togglePlay,
1259
+ toggleMute: n ? ge : p.toggleMute,
1260
+ toggleFullscreen: he,
1261
+ setVolume: n ? ge : p.setVolume
1262
+ });
1263
+ _(() => {
1264
+ d && E.current?.focus({ preventScroll: !0 });
1265
+ }, [d]);
1266
+ const Be = (w) => w.preventDefault();
1267
+ return /* @__PURE__ */ R(
1268
+ "div",
1269
+ {
1270
+ ref: E,
1271
+ className: H(
1272
+ "group relative h-full w-full overflow-hidden rounded-[inherit]",
1273
+ "[&:fullscreen]:h-screen [&:fullscreen]:w-screen [&:fullscreen]:rounded-none [&:fullscreen]:bg-[#000]",
1274
+ de()
1275
+ ),
1276
+ role: "region",
1277
+ "aria-label": a ?? b("videoPlayer.regionLabel"),
1278
+ tabIndex: 0,
1279
+ onKeyDown: ze,
1280
+ "data-video-captions": n ? "no-audio" : N.available ? "available" : "missing",
1281
+ ...h,
1282
+ children: [
1283
+ /* @__PURE__ */ R(
1284
+ "video",
1285
+ {
1286
+ ref: p.setVideoNode,
1287
+ autoPlay: u,
1288
+ playsInline: !0,
1289
+ disablePictureInPicture: !0,
1290
+ disableRemotePlayback: !0,
1291
+ draggable: !1,
1292
+ onContextMenu: Be,
1293
+ onClick: p.togglePlay,
1294
+ src: X,
1295
+ poster: t,
1296
+ crossOrigin: N.needsCrossOrigin || z.needsCrossOrigin ? "anonymous" : void 0,
1297
+ onLoadedData: () => p.setVideoLoaded(!0),
1298
+ className: H(
1299
+ "block h-full w-full cursor-pointer rounded-[inherit] object-contain transition-opacity duration-300",
1300
+ // Lift native captions clear of the bottom controls bar (~3.5rem
1301
+ // tall) so they never sit behind it. WebKit/Blink honour this
1302
+ // pseudo-element; other engines keep the default bottom placement.
1303
+ "[&::-webkit-media-text-track-container]:![transform:translateY(-3.5rem)]"
1304
+ ),
1305
+ style: { opacity: p.videoLoaded || t ? 1 : 0 },
1306
+ children: [
1307
+ N.trackSrc && /* @__PURE__ */ l(
1308
+ "track",
1309
+ {
1310
+ kind: "captions",
1311
+ src: N.trackSrc,
1312
+ label: b("videoPlayer.captions"),
1313
+ default: !1
1314
+ }
1315
+ ),
1316
+ z.trackSrc && /* @__PURE__ */ l(
1317
+ "track",
1318
+ {
1319
+ kind: "descriptions",
1320
+ src: z.trackSrc,
1321
+ label: b("videoPlayer.audioDescription"),
1322
+ default: !1
1323
+ }
1324
+ )
1325
+ ]
1326
+ }
1327
+ ),
1328
+ !p.isPlaying && /* @__PURE__ */ l(
1329
+ "div",
1330
+ {
1331
+ "aria-hidden": !0,
1332
+ "data-video-play-overlay": !0,
1333
+ className: "pointer-events-none absolute inset-0 z-[1] flex items-center justify-center",
1334
+ children: /* @__PURE__ */ l(
1335
+ "button",
1336
+ {
1337
+ type: "button",
1338
+ tabIndex: -1,
1339
+ onClick: p.togglePlay,
1340
+ className: "dark pointer-events-auto flex size-14 items-center justify-center rounded-full bg-[#000000b3] pl-0.5 text-f1-foreground shadow-[0_2px_8px_rgba(0,0,0,0.45)] transition-transform duration-150 hover:scale-105 motion-reduce:transition-none [&_svg]:size-7",
1341
+ children: /* @__PURE__ */ l(lt, { icon: Ce, size: "lg" })
1342
+ }
1343
+ )
1344
+ }
1345
+ ),
1346
+ N.showing && z.activeCue && /* @__PURE__ */ l(
1347
+ "div",
1348
+ {
1349
+ "aria-hidden": !0,
1350
+ className: "dark pointer-events-none absolute inset-x-0 top-0 z-[2] flex justify-center p-3",
1351
+ children: /* @__PURE__ */ R("p", { className: "max-w-[90%] rounded-md bg-[#000000b3] px-2 py-1 text-center text-base italic text-f1-foreground [text-shadow:0_1px_2px_rgba(0,0,0,0.55)]", children: [
1352
+ /* @__PURE__ */ R("span", { className: "pr-1 font-medium not-italic opacity-70", children: [
1353
+ "[",
1354
+ b("videoPlayer.audioDescription"),
1355
+ "]"
1356
+ ] }),
1357
+ z.activeCue
1358
+ ] })
1359
+ }
1360
+ ),
1361
+ /* @__PURE__ */ l("span", { className: "sr-only", "aria-live": "polite", children: p.isPlaying ? b("videoPlayer.playing") : b("videoPlayer.paused") }),
1362
+ p.videoLoaded && /* @__PURE__ */ l(
1363
+ At,
1364
+ {
1365
+ isPlaying: p.isPlaying,
1366
+ currentTime: p.currentTime,
1367
+ duration: p.duration,
1368
+ volume: p.volume,
1369
+ isMuted: p.isMuted,
1370
+ playbackRate: p.playbackRate,
1371
+ isFullscreen: Ke,
1372
+ markerTime: g ? $e : void 0,
1373
+ blockSeekPastMarker: g,
1374
+ containerRef: E,
1375
+ captionsAvailable: N.available,
1376
+ captionsOn: N.showing,
1377
+ audioDescriptionAvailable: z.available,
1378
+ audioDescriptionOn: V,
1379
+ silent: n,
1380
+ persist: o,
1381
+ audioLanguages: A,
1382
+ audioLanguage: T,
1383
+ onAudioLanguageChange: Ne,
1384
+ captionLanguages: S,
1385
+ captionLanguage: s,
1386
+ onCaptionLanguageChange: Fe,
1387
+ onCaptionsOff: Oe,
1388
+ audioDescriptionLanguages: D,
1389
+ audioDescriptionLanguage: K,
1390
+ onAudioDescriptionLanguageChange: Ue,
1391
+ onAudioDescriptionOff: Ve,
1392
+ onTogglePlay: p.togglePlay,
1393
+ onToggleMute: p.toggleMute,
1394
+ onVolumeChange: p.setVolume,
1395
+ onPlaybackRateChange: p.setPlaybackRate,
1396
+ onToggleFullscreen: () => {
1397
+ he();
1398
+ },
1399
+ onToggleCaptions: N.toggle,
1400
+ onToggleAudioDescription: _e,
1401
+ onSeek: pe,
1402
+ download: m
1403
+ }
1404
+ )
1405
+ ]
1406
+ }
1407
+ );
1408
+ }
1409
+ const Yt = dt(
1410
+ ut("F0VideoPlayer", Wt)
1411
+ );
1412
+ export {
1413
+ Yt as F,
1414
+ ae as c,
1415
+ Z as d,
1416
+ Le as l,
1417
+ ee as r
1418
+ };