@banou/media-player 0.8.17 → 0.8.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +208 -156
- package/dist/react/components/icons.d.ts +9 -0
- package/dist/utils/colors.d.ts +0 -2
- package/package.json +1 -1
- package/src/lib/react/components/burn-in-hint.tsx +1 -1
- package/src/lib/react/components/control-bar.tsx +13 -20
- package/src/lib/react/components/icons.tsx +16 -0
- package/src/lib/react/components/tooltip-display.tsx +116 -26
- package/src/lib/utils/colors.ts +0 -2
package/dist/index.js
CHANGED
|
@@ -67,17 +67,17 @@ var re = {
|
|
|
67
67
|
1e3,
|
|
68
68
|
3e3,
|
|
69
69
|
1e4
|
|
70
|
-
], ue = 6e4, de = 500,
|
|
70
|
+
], ue = 6e4, de = 500, fe = (e) => e instanceof Error ? e.message : String(e), pe = (e) => {
|
|
71
71
|
let t = [], n = e?.cause;
|
|
72
72
|
for (let e = 0; n != null && e < 8; e++) {
|
|
73
73
|
if (typeof MediaError < "u" && n instanceof MediaError) {
|
|
74
74
|
t.push(`MediaError code ${n.code}${n.message ? `: ${n.message}` : ""}`);
|
|
75
75
|
break;
|
|
76
76
|
}
|
|
77
|
-
t.push(
|
|
77
|
+
t.push(fe(n)), n = n?.cause;
|
|
78
78
|
}
|
|
79
79
|
return t.length ? t.join("\n") : void 0;
|
|
80
|
-
},
|
|
80
|
+
}, me = (e, t, r) => {
|
|
81
81
|
let a = R(), { read: o, size: s, publicPath: c = "", libavWorkerUrl: l = "", jassubWorkerUrl: f = "", jassubWasmUrl: h = "", jassubLegacyWasmUrl: g, defaultFontUrl: _, bufferSize: v, autoplay: y = !1, seekPrepareBudgetMs: b = de } = r ?? {}, [x, S] = m(void 0), [C, w] = m(0), T = p({
|
|
82
82
|
count: 0,
|
|
83
83
|
at: 0
|
|
@@ -137,7 +137,7 @@ var re = {
|
|
|
137
137
|
ready: !1
|
|
138
138
|
});
|
|
139
139
|
let u = (t, n) => {
|
|
140
|
-
let r = Date.now(), i =
|
|
140
|
+
let r = Date.now(), i = fe(t), o = pe(t), s = a.playbackErrors, c = s[s.length - 1];
|
|
141
141
|
if (c && c.message === i && c.detail === o && c.recovered === n) {
|
|
142
142
|
let e = {
|
|
143
143
|
...c,
|
|
@@ -246,13 +246,13 @@ var re = {
|
|
|
246
246
|
y,
|
|
247
247
|
C
|
|
248
248
|
]);
|
|
249
|
-
},
|
|
249
|
+
}, he = 5e3, ge = 6e4, _e = ({ publicPath: e, workerUrl: t, length: n, read: i, downloadedRanges: a }) => {
|
|
250
250
|
let [o, s] = m([]), c = p(null), l = p(i);
|
|
251
251
|
l.current = i;
|
|
252
252
|
let u = f(() => a?.map(({ startByteOffset: e, endByteOffset: t }) => [e, t]), [a?.map(({ startByteOffset: e, endByteOffset: t }) => `${e}-${t}`).join(",")]), h = p(u);
|
|
253
253
|
return h.current = u, d(() => {
|
|
254
254
|
if (!n || !i || !e || !t) return;
|
|
255
|
-
let a = !1, o = null, u, d =
|
|
255
|
+
let a = !1, o = null, u, d = he, f = () => {
|
|
256
256
|
r({
|
|
257
257
|
publicPath: e,
|
|
258
258
|
workerUrl: t,
|
|
@@ -268,7 +268,7 @@ var re = {
|
|
|
268
268
|
}
|
|
269
269
|
o = e, c.current = e, e.update(h.current);
|
|
270
270
|
}, () => {
|
|
271
|
-
a || (u = setTimeout(f, d), d = Math.min(d * 2,
|
|
271
|
+
a || (u = setTimeout(f, d), d = Math.min(d * 2, ge));
|
|
272
272
|
});
|
|
273
273
|
};
|
|
274
274
|
return f(), () => {
|
|
@@ -281,7 +281,7 @@ var re = {
|
|
|
281
281
|
]), d(() => {
|
|
282
282
|
c.current?.update(u);
|
|
283
283
|
}, [u]), o;
|
|
284
|
-
},
|
|
284
|
+
}, z = (e, n) => {
|
|
285
285
|
let r = p(null), [i, o] = m(!1), [s] = m(() => t());
|
|
286
286
|
d(() => {
|
|
287
287
|
if (!e || !n || !s) return;
|
|
@@ -309,7 +309,7 @@ var re = {
|
|
|
309
309
|
mode: s,
|
|
310
310
|
burnedIn: i
|
|
311
311
|
};
|
|
312
|
-
},
|
|
312
|
+
}, B = {
|
|
313
313
|
headings: {
|
|
314
314
|
large: "\n font-weight: 600;\n font-size: calc(2.8 * var(--mp-unit));\n line-height: calc(3.4 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(3.4 * var(--mp-unit));\n line-height: calc(4.1 * var(--mp-unit));\n }\n ",
|
|
315
315
|
medium: "\n font-weight: 600;\n font-size: calc(2.4 * var(--mp-unit));\n line-height: calc(2.9 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(2.8 * var(--mp-unit));\n line-height: calc(3.4 * var(--mp-unit));\n }\n ",
|
|
@@ -336,14 +336,14 @@ var re = {
|
|
|
336
336
|
medium: "\n font-weight: 500;\n font-size: calc(0.8 * var(--mp-unit));\n line-height: calc(1.1 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(1 * var(--mp-unit));\n line-height: calc(1.4 * var(--mp-unit));\n }\n ",
|
|
337
337
|
regular: "\n font-weight: 400;\n font-size: calc(0.8 * var(--mp-unit));\n line-height: calc(1.1 * var(--mp-unit));\n @media (min-width: 960px) {\n font-size: calc(1 * var(--mp-unit));\n line-height: calc(1.4 * var(--mp-unit));\n }\n "
|
|
338
338
|
}
|
|
339
|
-
},
|
|
339
|
+
}, ve = h`
|
|
340
340
|
top: unset !important;
|
|
341
341
|
left: unset !important;
|
|
342
342
|
width: 100%;
|
|
343
343
|
height: 100%;
|
|
344
344
|
margin: auto;
|
|
345
345
|
pointer-events: none;
|
|
346
|
-
`,
|
|
346
|
+
`, ye = h`
|
|
347
347
|
position: absolute;
|
|
348
348
|
top: 0;
|
|
349
349
|
left: 0;
|
|
@@ -351,7 +351,7 @@ var re = {
|
|
|
351
351
|
padding: calc(1.2 * var(--mp-unit)) calc(1.6 * var(--mp-unit));
|
|
352
352
|
/* clears a notch once the player is fullscreen; resolves to zero everywhere else */
|
|
353
353
|
padding-top: calc(calc(1.2 * var(--mp-unit)) + env(safe-area-inset-top, 0px));
|
|
354
|
-
${
|
|
354
|
+
${B.headings.small}
|
|
355
355
|
color: white;
|
|
356
356
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
357
357
|
z-index: 2;
|
|
@@ -372,7 +372,7 @@ var re = {
|
|
|
372
372
|
|
|
373
373
|
background: linear-gradient(180deg, rgba(0,0,0,0.4) 0%, rgba(0,0,0,0.3) 30%, rgba(0,0,0,0.2) 60%, rgba(0,0,0,0.1) 80%, transparent 100%);
|
|
374
374
|
transition: opacity 0.1s cubic-bezier(.4,0,1,1);
|
|
375
|
-
`,
|
|
375
|
+
`, be = h`
|
|
376
376
|
position: absolute;
|
|
377
377
|
inset: 0;
|
|
378
378
|
z-index: 2;
|
|
@@ -392,53 +392,75 @@ var re = {
|
|
|
392
392
|
to { transform: rotate(360deg); }
|
|
393
393
|
`} 0.8s linear infinite;
|
|
394
394
|
}
|
|
395
|
-
`,
|
|
395
|
+
`, xe = h`
|
|
396
396
|
position: absolute;
|
|
397
397
|
inset: auto 0 20%;
|
|
398
398
|
z-index: 3;
|
|
399
399
|
padding: 0 calc(2 * var(--mp-unit));
|
|
400
400
|
text-align: center;
|
|
401
401
|
color: #fff;
|
|
402
|
-
${
|
|
402
|
+
${B.bLarge.regular}
|
|
403
403
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
404
404
|
pointer-events: none;
|
|
405
|
-
`,
|
|
405
|
+
`, Se = (e) => e instanceof Error ? e.message : typeof e == "string" ? e : "Playback failed", Ce = ({ onCanvasRef: e }) => {
|
|
406
406
|
let t = R((e) => e.title), n = R((e) => e.hideUI), r = R((e) => e.playbackError), i = R((e) => e.ready), a = R((e) => e.size), o = R((e) => e.waiting);
|
|
407
407
|
return /* @__PURE__ */ w(S, { children: [
|
|
408
408
|
t ? /* @__PURE__ */ C("div", {
|
|
409
409
|
className: "title",
|
|
410
|
-
css:
|
|
410
|
+
css: ye,
|
|
411
411
|
style: { ...n ? {
|
|
412
412
|
opacity: "0",
|
|
413
413
|
pointerEvents: "none"
|
|
414
414
|
} : {} },
|
|
415
415
|
children: t
|
|
416
416
|
}) : void 0,
|
|
417
|
-
(a ? !i : o) && !r ? /* @__PURE__ */ C("div", { css:
|
|
417
|
+
(a ? !i : o) && !r ? /* @__PURE__ */ C("div", { css: be }) : void 0,
|
|
418
418
|
r ? /* @__PURE__ */ C("div", {
|
|
419
|
-
css:
|
|
420
|
-
children:
|
|
419
|
+
css: xe,
|
|
420
|
+
children: Se(r)
|
|
421
421
|
}) : void 0,
|
|
422
422
|
/* @__PURE__ */ C("canvas", {
|
|
423
423
|
ref: e,
|
|
424
|
-
css:
|
|
424
|
+
css: ve
|
|
425
425
|
})
|
|
426
426
|
] });
|
|
427
|
-
},
|
|
427
|
+
}, V = 1e-4, H = 1, U = (e) => Math.max(V, Math.min(H, e)) ** 2, W = (e) => Math.max(V, Math.min(H, e)) ** (H / 2), G = (e) => {
|
|
428
428
|
if (e === void 0) return "0:00";
|
|
429
429
|
let t = Math.floor(e / 3600), n = Math.floor(e % 3600 / 60), r = Math.floor(e % 60);
|
|
430
430
|
return t > 0 ? `${t}:${n < 10 ? "0" : ""}${n}:${r < 10 ? "0" : ""}${r}` : `${n}:${r < 10 ? "0" : ""}${r}`;
|
|
431
|
-
},
|
|
431
|
+
}, we = (e, t) => `${G(e)} / ${G(t)}`, Te = (e) => h`
|
|
432
432
|
display: flex;
|
|
433
|
-
justify-content: flex-
|
|
433
|
+
justify-content: flex-start;
|
|
434
434
|
|
|
435
|
-
|
|
435
|
+
/*
|
|
436
|
+
* Bounded here rather than at each call site.
|
|
437
|
+
*
|
|
438
|
+
* react-tooltip's own chip rule carries width: max-content, so with nothing opposing it a chip
|
|
439
|
+
* grows to the widest UNWRAPPED line of its content: a two sentence tooltip measured 1178px
|
|
440
|
+
* through this component. Both declarations are load bearing, since a bound with no wrapping only
|
|
441
|
+
* moves the overflow inside a narrow box. 26 units is the width control-bar.tsx was already
|
|
442
|
+
* imposing on its own two line tooltip by hand, so nothing in the bar changes shape.
|
|
443
|
+
*/
|
|
444
|
+
max-width: min(calc(26 * var(--mp-unit)), calc(100vw - calc(2.4 * var(--mp-unit))));
|
|
445
|
+
white-space: normal;
|
|
446
|
+
overflow-wrap: anywhere;
|
|
447
|
+
text-align: left;
|
|
448
|
+
|
|
449
|
+
/*
|
|
450
|
+
* The radius carries !important for the same reason the paddings below do.
|
|
451
|
+
*
|
|
452
|
+
* react-tooltip injects its stylesheet from a passive effect while emotion inserts through
|
|
453
|
+
* useInsertionEffect, which runs earlier, so react-tooltip's sheet lands in the head LAST at
|
|
454
|
+
* exactly this specificity and wins every tie. Its own radius is 3px, which is what was drawn
|
|
455
|
+
* here until this was stated.
|
|
456
|
+
*/
|
|
457
|
+
border-radius: calc(0.4 * var(--mp-unit))!important;
|
|
436
458
|
user-select: none;
|
|
437
459
|
|
|
438
460
|
z-index: 3;
|
|
439
461
|
|
|
440
462
|
* {
|
|
441
|
-
${
|
|
463
|
+
${B.bMedium.regular}
|
|
442
464
|
}
|
|
443
465
|
|
|
444
466
|
${e === "sm" && h`
|
|
@@ -450,20 +472,48 @@ var re = {
|
|
|
450
472
|
${e === "lg" && h`
|
|
451
473
|
padding: calc(1.2 * var(--mp-unit))!important;
|
|
452
474
|
`}
|
|
453
|
-
`,
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
475
|
+
`, K = {
|
|
476
|
+
x: -1,
|
|
477
|
+
y: -1,
|
|
478
|
+
anchors: 0
|
|
479
|
+
}, Ee = (e) => {
|
|
480
|
+
K.x = e.clientX, K.y = e.clientY;
|
|
481
|
+
}, De = () => (K.anchors++ === 0 && window.addEventListener("pointermove", Ee, {
|
|
482
|
+
capture: !0,
|
|
483
|
+
passive: !0
|
|
484
|
+
}), () => {
|
|
485
|
+
--K.anchors === 0 && window.removeEventListener("pointermove", Ee, { capture: !0 });
|
|
486
|
+
}), q = ({ id: e, toolTipText: t, text: n, delayShow: r = 0, closeDelay: i = 0, offset: a = 20, tooltipPlace: o = "top", disabled: s = !1, size: c = "md" }) => {
|
|
487
|
+
let l = p(null), u = p(null);
|
|
488
|
+
return d(() => {
|
|
489
|
+
let e = De(), t = () => {
|
|
490
|
+
let e = l.current;
|
|
491
|
+
if (!e) return;
|
|
492
|
+
let { left: t, right: n, top: r, bottom: i } = e.getBoundingClientRect();
|
|
493
|
+
K.x >= t && K.x < n && K.y >= r && K.y < i || u.current?.close();
|
|
494
|
+
}, n = ["fullscreenchange", "webkitfullscreenchange"];
|
|
495
|
+
for (let e of n) document.addEventListener(e, t);
|
|
496
|
+
return () => {
|
|
497
|
+
e();
|
|
498
|
+
for (let e of n) document.removeEventListener(e, t);
|
|
499
|
+
};
|
|
500
|
+
}, []), /* @__PURE__ */ w(S, { children: [/* @__PURE__ */ C("div", {
|
|
501
|
+
ref: l,
|
|
502
|
+
"data-tooltip-id": e,
|
|
503
|
+
"data-open": !0,
|
|
504
|
+
"data-tooltip-offset": a,
|
|
505
|
+
"data-tooltip-delay-show": r,
|
|
506
|
+
"data-tooltip-delay-hide": i,
|
|
507
|
+
"data-tooltip-place": o,
|
|
508
|
+
children: n
|
|
509
|
+
}), !s && /* @__PURE__ */ C(ne, {
|
|
510
|
+
ref: u,
|
|
511
|
+
css: Te(c),
|
|
512
|
+
id: e,
|
|
513
|
+
noArrow: !0,
|
|
514
|
+
children: t
|
|
515
|
+
})] });
|
|
516
|
+
}, J = ({ ref: e, onChange: t, orientation: n = "horizontal", disabled: r = !1 }) => {
|
|
467
517
|
let [i, a] = m(!1), o = p(t);
|
|
468
518
|
o.current = t;
|
|
469
519
|
let s = p(null), c = u((t, r) => {
|
|
@@ -502,7 +552,7 @@ var re = {
|
|
|
502
552
|
style: { touchAction: "none" }
|
|
503
553
|
}
|
|
504
554
|
};
|
|
505
|
-
},
|
|
555
|
+
}, Oe = h`
|
|
506
556
|
position: relative;
|
|
507
557
|
height: calc(.4 * var(--mp-unit));
|
|
508
558
|
|
|
@@ -556,7 +606,7 @@ var re = {
|
|
|
556
606
|
box-shadow: 0 0 calc(1 * var(--mp-unit)) rgba(0, 0, 0, .5);
|
|
557
607
|
|
|
558
608
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
559
|
-
${
|
|
609
|
+
${B.bMedium.bold}
|
|
560
610
|
|
|
561
611
|
position: absolute;
|
|
562
612
|
/* Anchored on its bottom edge rather than its top: now that it has a background its height
|
|
@@ -673,14 +723,14 @@ var re = {
|
|
|
673
723
|
--thumbnail-width: calc(18 * var(--mp-unit));
|
|
674
724
|
--thumbnail-half: calc(9 * var(--mp-unit));
|
|
675
725
|
}
|
|
676
|
-
`,
|
|
726
|
+
`, ke = 4, Ae = () => {
|
|
677
727
|
let e = R(), t = R((e) => e.currentTime), n = R((e) => e.requestSeek), r = R((e) => e.duration), i = R((e) => e.size), a = R((e) => e.downloadedRanges), o = R((e) => e.indexes), s = R((e) => e.thumbnails), c = R((e) => e.thumbnailAt), l = p(null), [u, h] = m(void 0), [g, _] = m(void 0), v = p(void 0), y = p(0), b = p(void 0), x = p(void 0), S = p(!1), { dragging: T, handlers: E } = J({
|
|
678
728
|
ref: l,
|
|
679
729
|
onChange: (e) => {
|
|
680
730
|
if (y.current += 1, b.current = e, x.current === void 0) x.current = e;
|
|
681
731
|
else if (!S.current) {
|
|
682
732
|
let t = l.current?.getBoundingClientRect().width ?? 0;
|
|
683
|
-
Math.abs(e - x.current) * t >
|
|
733
|
+
Math.abs(e - x.current) * t > ke && (S.current = !0);
|
|
684
734
|
}
|
|
685
735
|
h(e), v.current !== "mouse" && _(e * r);
|
|
686
736
|
}
|
|
@@ -742,7 +792,7 @@ var re = {
|
|
|
742
792
|
g
|
|
743
793
|
]);
|
|
744
794
|
return /* @__PURE__ */ w("div", {
|
|
745
|
-
css:
|
|
795
|
+
css: Oe,
|
|
746
796
|
ref: l,
|
|
747
797
|
className: T ? "progress-bar dragging" : "progress-bar",
|
|
748
798
|
onMouseMove: A,
|
|
@@ -783,7 +833,7 @@ var re = {
|
|
|
783
833
|
})
|
|
784
834
|
]
|
|
785
835
|
});
|
|
786
|
-
},
|
|
836
|
+
}, je = "data:image/svg+xml,%3csvg%20xmlns='http://www.w3.org/2000/svg'%20width='24'%20height='24'%20viewBox='0%200%2024%2024'%20fill='none'%20stroke='%23fff'%20stroke-width='2'%20stroke-linecap='round'%20stroke-linejoin='round'%20class='icon%20icon-tabler%20icons-tabler-outline%20icon-tabler-picture-in-picture'%3e%3cpath%20stroke='none'%20d='M0%200h24v24H0z'%20fill='none'%20/%3e%3cpath%20d='M11%2019h-6a2%202%200%200%201%20-2%20-2v-10a2%202%200%200%201%202%20-2h14a2%202%200%200%201%202%202v4'%20/%3e%3cpath%20d='M14%2014m0%201a1%201%200%200%201%201%20-1h5a1%201%200%200%201%201%201v3a1%201%200%200%201%20-1%201h-5a1%201%200%200%201%20-1%20-1z'%20/%3e%3c/svg%3e", Y = {
|
|
787
837
|
xmlns: "http://www.w3.org/2000/svg",
|
|
788
838
|
width: 24,
|
|
789
839
|
height: 24,
|
|
@@ -793,7 +843,7 @@ var re = {
|
|
|
793
843
|
strokeWidth: 2,
|
|
794
844
|
strokeLinecap: "round",
|
|
795
845
|
strokeLinejoin: "round"
|
|
796
|
-
},
|
|
846
|
+
}, Me = (e) => /* @__PURE__ */ w("svg", {
|
|
797
847
|
...Y,
|
|
798
848
|
...e,
|
|
799
849
|
children: [/* @__PURE__ */ C("rect", {
|
|
@@ -804,7 +854,7 @@ var re = {
|
|
|
804
854
|
rx: "2",
|
|
805
855
|
ry: "2"
|
|
806
856
|
}), /* @__PURE__ */ C("path", { d: "M7 15h4m4 0h2M7 11h2m4 0h4" })]
|
|
807
|
-
}),
|
|
857
|
+
}), Ne = (e) => /* @__PURE__ */ w("svg", {
|
|
808
858
|
...Y,
|
|
809
859
|
...e,
|
|
810
860
|
children: [
|
|
@@ -824,7 +874,7 @@ var re = {
|
|
|
824
874
|
y2: "22"
|
|
825
875
|
})
|
|
826
876
|
]
|
|
827
|
-
}),
|
|
877
|
+
}), Pe = (e) => /* @__PURE__ */ w("svg", {
|
|
828
878
|
...Y,
|
|
829
879
|
...e,
|
|
830
880
|
children: [
|
|
@@ -839,6 +889,21 @@ var re = {
|
|
|
839
889
|
}),
|
|
840
890
|
/* @__PURE__ */ C("path", { d: "M14.5 18.5h2m2 0h1" })
|
|
841
891
|
]
|
|
892
|
+
}), Fe = (e) => /* @__PURE__ */ w("svg", {
|
|
893
|
+
...Y,
|
|
894
|
+
...e,
|
|
895
|
+
children: [
|
|
896
|
+
/* @__PURE__ */ C("path", { d: "M21 11V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h5" }),
|
|
897
|
+
/* @__PURE__ */ C("rect", {
|
|
898
|
+
x: "12",
|
|
899
|
+
y: "13",
|
|
900
|
+
width: "10",
|
|
901
|
+
height: "8",
|
|
902
|
+
rx: "1",
|
|
903
|
+
ry: "1"
|
|
904
|
+
}),
|
|
905
|
+
/* @__PURE__ */ C("path", { d: "M6 9h3m2 0h2" })
|
|
906
|
+
]
|
|
842
907
|
}), X = h`
|
|
843
908
|
.popover {
|
|
844
909
|
position: absolute;
|
|
@@ -878,7 +943,7 @@ var re = {
|
|
|
878
943
|
|
|
879
944
|
border-radius: 8px;
|
|
880
945
|
background-color: rgba(28,28,28,0.95);
|
|
881
|
-
${
|
|
946
|
+
${B.bMedium.regular}
|
|
882
947
|
|
|
883
948
|
z-index: 4;
|
|
884
949
|
|
|
@@ -921,7 +986,7 @@ var re = {
|
|
|
921
986
|
|
|
922
987
|
.secondary {
|
|
923
988
|
color: #eee;
|
|
924
|
-
${
|
|
989
|
+
${B.bSmall.regular}
|
|
925
990
|
}
|
|
926
991
|
}
|
|
927
992
|
}
|
|
@@ -963,10 +1028,10 @@ var re = {
|
|
|
963
1028
|
.failed {
|
|
964
1029
|
border-bottom: 1px solid #4D4D4E;
|
|
965
1030
|
color: #f66;
|
|
966
|
-
${
|
|
1031
|
+
${B.bSmall.regular}
|
|
967
1032
|
}
|
|
968
1033
|
}
|
|
969
|
-
`,
|
|
1034
|
+
`, Ie = ({ title: e, tracks: t, selected: n, onSelect: r, onBack: i, offLabel: a, pending: o, failed: s }) => {
|
|
970
1035
|
let c = o !== void 0, l = (e, i, a) => {
|
|
971
1036
|
let s = c && o === e, l = c || t.find((t) => t.id === e)?.disabled;
|
|
972
1037
|
return /* @__PURE__ */ w("div", {
|
|
@@ -1034,7 +1099,7 @@ var re = {
|
|
|
1034
1099
|
});
|
|
1035
1100
|
}
|
|
1036
1101
|
};
|
|
1037
|
-
},
|
|
1102
|
+
}, Le = h`
|
|
1038
1103
|
/* Not a containing block, for the reason given on popoverStyle: the menu anchors to the control bar,
|
|
1039
1104
|
which is the width of the player box, so it can be clamped to it. */
|
|
1040
1105
|
position: static;
|
|
@@ -1078,7 +1143,7 @@ ${X}
|
|
|
1078
1143
|
|
|
1079
1144
|
color: #fff;
|
|
1080
1145
|
cursor: pointer;
|
|
1081
|
-
${
|
|
1146
|
+
${B.bSmall.regular}
|
|
1082
1147
|
|
|
1083
1148
|
&:hover {
|
|
1084
1149
|
background-color: rgba(255,255,255,.1);
|
|
@@ -1099,7 +1164,7 @@ ${X}
|
|
|
1099
1164
|
|
|
1100
1165
|
.when {
|
|
1101
1166
|
color: #bbb;
|
|
1102
|
-
${
|
|
1167
|
+
${B.bSmall.regular}
|
|
1103
1168
|
|
|
1104
1169
|
/* the one part of the line worth scanning for, so it is the one part at full brightness */
|
|
1105
1170
|
.count {
|
|
@@ -1118,27 +1183,27 @@ ${X}
|
|
|
1118
1183
|
color: #ddd;
|
|
1119
1184
|
overflow-wrap: anywhere;
|
|
1120
1185
|
white-space: pre-wrap;
|
|
1121
|
-
${
|
|
1186
|
+
${B.bSmall.regular}
|
|
1122
1187
|
}
|
|
1123
1188
|
}
|
|
1124
1189
|
}
|
|
1125
|
-
`,
|
|
1190
|
+
`, Re = (e) => new Date(e).toLocaleTimeString(), Q = (e) => e === void 0 || !Number.isFinite(e) ? void 0 : G(Math.max(0, e)), ze = (e) => e.reduce((e, t) => e + t.count, 0), Be = (e) => e.map((e, t) => {
|
|
1126
1191
|
let n = Q(e.atMediaTime), r = e.count > 1 ? `${new Date(e.at).toISOString()} to ${new Date(e.lastAt).toISOString()} ×${e.count}` : new Date(e.at).toISOString();
|
|
1127
1192
|
return [
|
|
1128
1193
|
`${t + 1}. ${r}${n ? ` (at ${n})` : ""}${e.recovered ? " [recovered]" : ""}`,
|
|
1129
1194
|
e.message,
|
|
1130
1195
|
e.detail
|
|
1131
1196
|
].filter(Boolean).join("\n");
|
|
1132
|
-
}).join("\n\n"),
|
|
1197
|
+
}).join("\n\n"), Ve = () => {
|
|
1133
1198
|
let e = R((e) => e.playbackErrors), { open: t, toggle: n, containerRef: r } = Z(), [i, a] = m(!1);
|
|
1134
1199
|
if (e.length === 0) return null;
|
|
1135
1200
|
let o = () => {
|
|
1136
|
-
navigator.clipboard?.writeText(
|
|
1201
|
+
navigator.clipboard?.writeText(Be(e)).then(() => {
|
|
1137
1202
|
a(!0), setTimeout(() => a(!1), 2e3);
|
|
1138
1203
|
}, (e) => console.warn("[media-player] could not copy the errors:", e));
|
|
1139
|
-
}, s = `Playback errors (${
|
|
1204
|
+
}, s = `Playback errors (${ze(e)})`;
|
|
1140
1205
|
return /* @__PURE__ */ w("div", {
|
|
1141
|
-
css:
|
|
1206
|
+
css: Le,
|
|
1142
1207
|
ref: r,
|
|
1143
1208
|
children: [/* @__PURE__ */ C(q, {
|
|
1144
1209
|
id: "errors",
|
|
@@ -1169,8 +1234,8 @@ ${X}
|
|
|
1169
1234
|
/* @__PURE__ */ w("span", {
|
|
1170
1235
|
className: "when",
|
|
1171
1236
|
children: [
|
|
1172
|
-
|
|
1173
|
-
e.count > 1 ? ` to ${
|
|
1237
|
+
Re(e.at),
|
|
1238
|
+
e.count > 1 ? ` to ${Re(e.lastAt)}` : "",
|
|
1174
1239
|
Q(e.atMediaTime) ? ` at ${Q(e.atMediaTime)}` : "",
|
|
1175
1240
|
e.recovered ? " recovered" : "",
|
|
1176
1241
|
e.count > 1 ? /* @__PURE__ */ C("span", {
|
|
@@ -1191,7 +1256,7 @@ ${X}
|
|
|
1191
1256
|
}, `${e.at}-${t}`))]
|
|
1192
1257
|
})]
|
|
1193
1258
|
});
|
|
1194
|
-
},
|
|
1259
|
+
}, He = h`
|
|
1195
1260
|
display: flex;
|
|
1196
1261
|
align-items: center;
|
|
1197
1262
|
justify-content: center;
|
|
@@ -1244,7 +1309,7 @@ width: 100%;
|
|
|
1244
1309
|
}
|
|
1245
1310
|
}
|
|
1246
1311
|
}
|
|
1247
|
-
`,
|
|
1312
|
+
`, Ue = () => {
|
|
1248
1313
|
let e = R(), t = R((e) => e.playbackRate), n = p(null), r = p(null), i = .25, a = 3 - i, o = (e, t = .05) => Math.round(e / t) * t, s = o(t || 1), c = (e) => (e - i) / a * 100, l = (e) => o(i + e * a), { handlers: u } = J({
|
|
1249
1314
|
ref: r,
|
|
1250
1315
|
onChange: (t) => e.setPlaybackRate(l(t))
|
|
@@ -1261,7 +1326,7 @@ width: 100%;
|
|
|
1261
1326
|
}, [t]);
|
|
1262
1327
|
let m = c(s);
|
|
1263
1328
|
return /* @__PURE__ */ w("div", {
|
|
1264
|
-
css:
|
|
1329
|
+
css: He,
|
|
1265
1330
|
children: [/* @__PURE__ */ w("div", { children: [s.toFixed(2), "x"] }), /* @__PURE__ */ C("div", {
|
|
1266
1331
|
className: "playback-slider",
|
|
1267
1332
|
ref: n,
|
|
@@ -1279,7 +1344,7 @@ width: 100%;
|
|
|
1279
1344
|
})
|
|
1280
1345
|
})]
|
|
1281
1346
|
});
|
|
1282
|
-
},
|
|
1347
|
+
}, We = h`
|
|
1283
1348
|
/* Deliberately NOT a containing block. The menu anchors to the control bar instead, which is exactly
|
|
1284
1349
|
as wide as the player box and can therefore be clamped to it. The outside-click check uses
|
|
1285
1350
|
\`contains\` on the ref, which is DOM containment and needs no position, and the bar's other
|
|
@@ -1338,7 +1403,7 @@ ${X}
|
|
|
1338
1403
|
}
|
|
1339
1404
|
}
|
|
1340
1405
|
|
|
1341
|
-
`,
|
|
1406
|
+
`, Ge = () => {
|
|
1342
1407
|
let e = R(), t = R((e) => e.playbackRate), n = R((e) => e.audioTracks), r = R((e) => e.selectedAudioTrack), i = R((e) => e.selectAudioTrack), [a, o] = m(0), { open: s, toggle: c, containerRef: l, pending: u, failed: d, runSelect: f } = Z({ onReset: () => o(0) }), p = (t) => {
|
|
1343
1408
|
e.setPlaybackRate(t), o(0);
|
|
1344
1409
|
}, h = (e) => {
|
|
@@ -1347,7 +1412,7 @@ ${X}
|
|
|
1347
1412
|
o(e);
|
|
1348
1413
|
};
|
|
1349
1414
|
return /* @__PURE__ */ w("div", {
|
|
1350
|
-
css:
|
|
1415
|
+
css: We,
|
|
1351
1416
|
ref: l,
|
|
1352
1417
|
children: [
|
|
1353
1418
|
/* @__PURE__ */ C(q, {
|
|
@@ -1386,7 +1451,7 @@ ${X}
|
|
|
1386
1451
|
}),
|
|
1387
1452
|
/* @__PURE__ */ C("div", {
|
|
1388
1453
|
className: "slider no-hover",
|
|
1389
|
-
children: /* @__PURE__ */ C(
|
|
1454
|
+
children: /* @__PURE__ */ C(Ue, {})
|
|
1390
1455
|
}),
|
|
1391
1456
|
/* @__PURE__ */ w("div", {
|
|
1392
1457
|
className: "options no-hover",
|
|
@@ -1411,7 +1476,7 @@ ${X}
|
|
|
1411
1476
|
})
|
|
1412
1477
|
]
|
|
1413
1478
|
}),
|
|
1414
|
-
s && a === 2 && /* @__PURE__ */ C(
|
|
1479
|
+
s && a === 2 && /* @__PURE__ */ C(Ie, {
|
|
1415
1480
|
title: "Audio",
|
|
1416
1481
|
tracks: n,
|
|
1417
1482
|
selected: r,
|
|
@@ -1422,7 +1487,7 @@ ${X}
|
|
|
1422
1487
|
})
|
|
1423
1488
|
]
|
|
1424
1489
|
});
|
|
1425
|
-
},
|
|
1490
|
+
}, Ke = h`
|
|
1426
1491
|
/* Not a containing block, for the reason given on popoverStyle: the menu anchors to the control bar,
|
|
1427
1492
|
which is the width of the player box, so it can be clamped to it. */
|
|
1428
1493
|
position: static;
|
|
@@ -1439,12 +1504,12 @@ position: static;
|
|
|
1439
1504
|
}
|
|
1440
1505
|
|
|
1441
1506
|
${X}
|
|
1442
|
-
`,
|
|
1507
|
+
`, qe = () => {
|
|
1443
1508
|
let e = R((e) => e.subtitleTracks), t = R((e) => e.selectedSubtitleTrack), n = R((e) => e.selectSubtitleTrack), r = R((e) => e.subtitleOffLabel), { open: i, toggle: a, containerRef: o, pending: s, failed: c, runSelect: l } = Z();
|
|
1444
1509
|
if (e.length === 0) return null;
|
|
1445
1510
|
let u = t !== void 0;
|
|
1446
1511
|
return /* @__PURE__ */ w("div", {
|
|
1447
|
-
css:
|
|
1512
|
+
css: Ke,
|
|
1448
1513
|
ref: o,
|
|
1449
1514
|
children: [/* @__PURE__ */ C(q, {
|
|
1450
1515
|
id: "subtitles",
|
|
@@ -1456,10 +1521,10 @@ ${X}
|
|
|
1456
1521
|
"aria-label": "Subtitles",
|
|
1457
1522
|
"aria-expanded": i,
|
|
1458
1523
|
"aria-pressed": u,
|
|
1459
|
-
children: u ? /* @__PURE__ */ C(
|
|
1524
|
+
children: u ? /* @__PURE__ */ C(Me, { className: "captions" }) : /* @__PURE__ */ C(Ne, { className: "captions-off" })
|
|
1460
1525
|
}),
|
|
1461
1526
|
toolTipText: /* @__PURE__ */ C("span", { children: "Subtitles" })
|
|
1462
|
-
}), i && /* @__PURE__ */ C(
|
|
1527
|
+
}), i && /* @__PURE__ */ C(Ie, {
|
|
1463
1528
|
title: "Subtitles",
|
|
1464
1529
|
tracks: e,
|
|
1465
1530
|
selected: t,
|
|
@@ -1469,14 +1534,13 @@ ${X}
|
|
|
1469
1534
|
failed: c
|
|
1470
1535
|
})]
|
|
1471
1536
|
});
|
|
1472
|
-
},
|
|
1537
|
+
}, Je = {
|
|
1473
1538
|
primary: "#EAEBEE",
|
|
1474
1539
|
secondary: "#D0D0D9",
|
|
1475
1540
|
hover: "rgba(255, 255, 255, 0.13)",
|
|
1476
|
-
accent: "#6EA8FE",
|
|
1477
1541
|
borderPrimary: "#384F70",
|
|
1478
1542
|
backgroundTooltip: "#222222"
|
|
1479
|
-
},
|
|
1543
|
+
}, Ye = h`
|
|
1480
1544
|
display: flex;
|
|
1481
1545
|
align-items: center;
|
|
1482
1546
|
|
|
@@ -1519,7 +1583,7 @@ ${X}
|
|
|
1519
1583
|
width: 10px;
|
|
1520
1584
|
height: 10px;
|
|
1521
1585
|
}
|
|
1522
|
-
`,
|
|
1586
|
+
`, Xe = ({ value: e, onChange: t }) => {
|
|
1523
1587
|
let n = R((e) => e.volume), r = R((e) => e.muted), i = p(null), a = p(null), { handlers: o } = J({
|
|
1524
1588
|
ref: a,
|
|
1525
1589
|
onChange: t
|
|
@@ -1534,12 +1598,12 @@ ${X}
|
|
|
1534
1598
|
e && e.removeEventListener("wheel", s);
|
|
1535
1599
|
};
|
|
1536
1600
|
}, [e]);
|
|
1537
|
-
let c = e * 100, l = f(() => Math.round(r ? 0 :
|
|
1601
|
+
let c = e * 100, l = f(() => Math.round(r ? 0 : W(n) * 100), [n, r]);
|
|
1538
1602
|
return /* @__PURE__ */ C(q, {
|
|
1539
1603
|
id: "volume-slider",
|
|
1540
1604
|
text: /* @__PURE__ */ C("div", {
|
|
1541
1605
|
ref: i,
|
|
1542
|
-
css:
|
|
1606
|
+
css: Ye,
|
|
1543
1607
|
...o,
|
|
1544
1608
|
children: /* @__PURE__ */ C("div", {
|
|
1545
1609
|
ref: a,
|
|
@@ -1558,7 +1622,7 @@ ${X}
|
|
|
1558
1622
|
children: [l, "%"]
|
|
1559
1623
|
})
|
|
1560
1624
|
});
|
|
1561
|
-
},
|
|
1625
|
+
}, Ze = h`
|
|
1562
1626
|
position: relative;
|
|
1563
1627
|
display: flex;
|
|
1564
1628
|
align-items: center;
|
|
@@ -1583,7 +1647,7 @@ ${X}
|
|
|
1583
1647
|
border-radius: 4px;
|
|
1584
1648
|
|
|
1585
1649
|
.volume-value {
|
|
1586
|
-
${
|
|
1650
|
+
${B.bMedium.regular};
|
|
1587
1651
|
color: #ffffff;
|
|
1588
1652
|
}
|
|
1589
1653
|
}
|
|
@@ -1621,10 +1685,10 @@ ${X}
|
|
|
1621
1685
|
}
|
|
1622
1686
|
}
|
|
1623
1687
|
|
|
1624
|
-
`,
|
|
1625
|
-
let t = R(), n = R((e) => e.volume), r = R((e) => e.muted), i = f(() =>
|
|
1688
|
+
`, Qe = ({ ref: e }) => {
|
|
1689
|
+
let t = R(), n = R((e) => e.volume), r = R((e) => e.muted), i = f(() => W(n), [n]);
|
|
1626
1690
|
return /* @__PURE__ */ w("div", {
|
|
1627
|
-
css:
|
|
1691
|
+
css: Ze,
|
|
1628
1692
|
children: [/* @__PURE__ */ C(q, {
|
|
1629
1693
|
id: "sound",
|
|
1630
1694
|
text: /* @__PURE__ */ C("button", {
|
|
@@ -1644,27 +1708,25 @@ ${X}
|
|
|
1644
1708
|
className: "volume-slider-container",
|
|
1645
1709
|
children: /* @__PURE__ */ C("div", {
|
|
1646
1710
|
className: "volume-slider-background",
|
|
1647
|
-
children: /* @__PURE__ */ C(
|
|
1711
|
+
children: /* @__PURE__ */ C(Xe, {
|
|
1648
1712
|
value: r ? 0 : i,
|
|
1649
1713
|
onChange: (e) => {
|
|
1650
|
-
t.setVolume(
|
|
1714
|
+
t.setVolume(U(e));
|
|
1651
1715
|
}
|
|
1652
1716
|
})
|
|
1653
1717
|
})
|
|
1654
1718
|
})]
|
|
1655
1719
|
});
|
|
1656
|
-
}, $ = .05,
|
|
1720
|
+
}, $ = .05, $e = 5, et = h`
|
|
1657
1721
|
display: flex;
|
|
1658
1722
|
flex-direction: column;
|
|
1659
1723
|
gap: calc(0.4 * var(--mp-unit));
|
|
1660
|
-
max-width: calc(26 * var(--mp-unit));
|
|
1661
|
-
white-space: normal;
|
|
1662
1724
|
|
|
1663
1725
|
.hint {
|
|
1664
1726
|
opacity: 0.72;
|
|
1665
1727
|
font-size: 0.9em;
|
|
1666
1728
|
}
|
|
1667
|
-
`,
|
|
1729
|
+
`, tt = h`
|
|
1668
1730
|
position: absolute;
|
|
1669
1731
|
bottom: 0;
|
|
1670
1732
|
width: 100%;
|
|
@@ -1722,16 +1784,6 @@ ${X}
|
|
|
1722
1784
|
}
|
|
1723
1785
|
}
|
|
1724
1786
|
|
|
1725
|
-
/**
|
|
1726
|
-
* The burn-in control's own on state.
|
|
1727
|
-
*
|
|
1728
|
-
* Not \`colors.hover\`: the pointer is on the button at the moment of the click, so an on state
|
|
1729
|
-
* drawn in the hover colour is invisible exactly when it is being looked for.
|
|
1730
|
-
*/
|
|
1731
|
-
button[aria-pressed='true'] svg {
|
|
1732
|
-
stroke: ${We.accent};
|
|
1733
|
-
}
|
|
1734
|
-
|
|
1735
1787
|
.play, .sound, .time, .errors, .subtitles, .settings, .picture-in-picture, .full-screen {
|
|
1736
1788
|
display: flex;
|
|
1737
1789
|
align-items: center;
|
|
@@ -1764,7 +1816,7 @@ ${X}
|
|
|
1764
1816
|
cursor: pointer;
|
|
1765
1817
|
|
|
1766
1818
|
:hover {
|
|
1767
|
-
background-color: ${
|
|
1819
|
+
background-color: ${Je.hover};
|
|
1768
1820
|
}
|
|
1769
1821
|
|
|
1770
1822
|
/* the hit area grows, the icon does not, keyed on the pointer because a narrow desktop
|
|
@@ -1781,7 +1833,7 @@ ${X}
|
|
|
1781
1833
|
|
|
1782
1834
|
.left {
|
|
1783
1835
|
.time {
|
|
1784
|
-
${
|
|
1836
|
+
${B.bMedium.regular}
|
|
1785
1837
|
text-shadow: 0 0 4px rgba(0, 0, 0, 1);
|
|
1786
1838
|
}
|
|
1787
1839
|
}
|
|
@@ -1802,10 +1854,10 @@ ${X}
|
|
|
1802
1854
|
}
|
|
1803
1855
|
}
|
|
1804
1856
|
}
|
|
1805
|
-
`,
|
|
1857
|
+
`, nt = () => {
|
|
1806
1858
|
let e = R(), t = R((e) => e.paused), n = R((e) => e.currentTime), r = R((e) => e.duration), i = R((e) => e.fullscreen), a = R((e) => e.hideUI), o = R((e) => e.togglePictureInPicture), s = R((e) => e.pictureInPictureMode), c = R((e) => e.burnedInSubtitles), l = R((e) => e.subtitleTracks), f = R((e) => e.requestSeek), [p, h] = m(null), g = s === "burn-in", _ = l.length > 0, v = r > 0 && n === r, y = u(({ direction: t, stepSize: n }) => {
|
|
1807
|
-
let r =
|
|
1808
|
-
e.setVolume(
|
|
1859
|
+
let r = W(e.volume), i = t === "up" ? n : -n, a = Math.max(0, Math.min(1, r + i)), o = e.muted;
|
|
1860
|
+
e.setVolume(U(a)), o && !e.muted && e.toggleMuted();
|
|
1809
1861
|
}, [e]);
|
|
1810
1862
|
d(() => {
|
|
1811
1863
|
let t = (t) => f ? f(t) : e.seek(t), n = (n) => {
|
|
@@ -1826,8 +1878,8 @@ ${X}
|
|
|
1826
1878
|
});
|
|
1827
1879
|
else if (n.key === "ArrowRight") {
|
|
1828
1880
|
if (!e.duration) return;
|
|
1829
|
-
t(Math.min(e.currentTime +
|
|
1830
|
-
} else n.key === "ArrowLeft" ? t(Math.max(e.currentTime -
|
|
1881
|
+
t(Math.min(e.currentTime + $e, e.duration));
|
|
1882
|
+
} else n.key === "ArrowLeft" ? t(Math.max(e.currentTime - $e, 0)) : i = !1;
|
|
1831
1883
|
i && n.preventDefault();
|
|
1832
1884
|
};
|
|
1833
1885
|
return window.addEventListener("keydown", n), () => window.removeEventListener("keydown", n);
|
|
@@ -1848,12 +1900,12 @@ ${X}
|
|
|
1848
1900
|
return d(() => {
|
|
1849
1901
|
if (p) return p.addEventListener("wheel", b, { passive: !1 }), () => p.removeEventListener("wheel", b);
|
|
1850
1902
|
}, [p, b]), /* @__PURE__ */ w("div", {
|
|
1851
|
-
css:
|
|
1903
|
+
css: tt,
|
|
1852
1904
|
style: { ...a ? {
|
|
1853
1905
|
opacity: "0",
|
|
1854
1906
|
pointerEvents: "none"
|
|
1855
1907
|
} : {} },
|
|
1856
|
-
children: [/* @__PURE__ */ C(
|
|
1908
|
+
children: [/* @__PURE__ */ C(Ae, {}), /* @__PURE__ */ w("div", {
|
|
1857
1909
|
className: "actions",
|
|
1858
1910
|
children: [/* @__PURE__ */ w("div", {
|
|
1859
1911
|
className: "left",
|
|
@@ -1870,18 +1922,18 @@ ${X}
|
|
|
1870
1922
|
}),
|
|
1871
1923
|
toolTipText: /* @__PURE__ */ C("span", { children: v ? "Replay (k)" : t ? "Play (k)" : "Pause (k)" })
|
|
1872
1924
|
}),
|
|
1873
|
-
/* @__PURE__ */ C(
|
|
1925
|
+
/* @__PURE__ */ C(Qe, { ref: h }),
|
|
1874
1926
|
/* @__PURE__ */ C("div", {
|
|
1875
1927
|
className: "time",
|
|
1876
|
-
children:
|
|
1928
|
+
children: we(n, r)
|
|
1877
1929
|
})
|
|
1878
1930
|
]
|
|
1879
1931
|
}), /* @__PURE__ */ w("div", {
|
|
1880
1932
|
className: "right",
|
|
1881
1933
|
children: [
|
|
1882
|
-
/* @__PURE__ */ C(Le, {}),
|
|
1883
|
-
/* @__PURE__ */ C(Ue, {}),
|
|
1884
1934
|
/* @__PURE__ */ C(Ve, {}),
|
|
1935
|
+
/* @__PURE__ */ C(qe, {}),
|
|
1936
|
+
/* @__PURE__ */ C(Ge, {}),
|
|
1885
1937
|
o ? /* @__PURE__ */ C(q, {
|
|
1886
1938
|
id: "picture-in-picture",
|
|
1887
1939
|
tooltipPlace: "top-end",
|
|
@@ -1892,13 +1944,13 @@ ${X}
|
|
|
1892
1944
|
disabled: g && !_,
|
|
1893
1945
|
"aria-label": g ? "Put the subtitles in the video" : "Picture in picture",
|
|
1894
1946
|
"aria-pressed": g ? c : void 0,
|
|
1895
|
-
children: g ?
|
|
1896
|
-
src:
|
|
1947
|
+
children: g ? C(c ? Pe : Fe, {}) : /* @__PURE__ */ C("img", {
|
|
1948
|
+
src: je,
|
|
1897
1949
|
alt: ""
|
|
1898
1950
|
})
|
|
1899
1951
|
}),
|
|
1900
1952
|
toolTipText: /* @__PURE__ */ w("span", {
|
|
1901
|
-
css:
|
|
1953
|
+
css: et,
|
|
1902
1954
|
children: [/* @__PURE__ */ C("span", {
|
|
1903
1955
|
className: "lead",
|
|
1904
1956
|
children: g ? _ ? c ? "Subtitles are in the picture" : "Put the subtitles in the picture" : "This file has no subtitles" : "Picture in picture"
|
|
@@ -1925,7 +1977,7 @@ ${X}
|
|
|
1925
1977
|
})]
|
|
1926
1978
|
})]
|
|
1927
1979
|
});
|
|
1928
|
-
},
|
|
1980
|
+
}, rt = 9e3, it = h`
|
|
1929
1981
|
position: absolute;
|
|
1930
1982
|
inset: 0;
|
|
1931
1983
|
z-index: 2;
|
|
@@ -1963,12 +2015,12 @@ ${X}
|
|
|
1963
2015
|
}
|
|
1964
2016
|
|
|
1965
2017
|
.title {
|
|
1966
|
-
${
|
|
2018
|
+
${B.bMedium.bold}
|
|
1967
2019
|
color: #fff;
|
|
1968
2020
|
}
|
|
1969
2021
|
|
|
1970
2022
|
.body {
|
|
1971
|
-
${
|
|
2023
|
+
${B.bSmall.regular}
|
|
1972
2024
|
color: rgba(255, 255, 255, 0.75);
|
|
1973
2025
|
}
|
|
1974
2026
|
|
|
@@ -1977,9 +2029,9 @@ ${X}
|
|
|
1977
2029
|
flex: none;
|
|
1978
2030
|
font-size: calc(2.6 * var(--mp-unit));
|
|
1979
2031
|
line-height: 1;
|
|
1980
|
-
color: #
|
|
2032
|
+
color: #fff;
|
|
1981
2033
|
}
|
|
1982
|
-
`,
|
|
2034
|
+
`, at = () => {
|
|
1983
2035
|
let e = R((e) => e.burnedInSubtitles), t = R((e) => e.pictureInPictureMode), [n, r] = m(!1);
|
|
1984
2036
|
return d(() => {
|
|
1985
2037
|
if (t !== "burn-in" || !e) {
|
|
@@ -1987,10 +2039,10 @@ ${X}
|
|
|
1987
2039
|
return;
|
|
1988
2040
|
}
|
|
1989
2041
|
r(!0);
|
|
1990
|
-
let n = setTimeout(() => r(!1),
|
|
2042
|
+
let n = setTimeout(() => r(!1), rt);
|
|
1991
2043
|
return () => clearTimeout(n);
|
|
1992
2044
|
}, [t, e]), t !== "burn-in" || !e ? null : /* @__PURE__ */ C("div", {
|
|
1993
|
-
css:
|
|
2045
|
+
css: it,
|
|
1994
2046
|
className: n ? "show" : "",
|
|
1995
2047
|
role: "status",
|
|
1996
2048
|
children: /* @__PURE__ */ w("div", {
|
|
@@ -2011,7 +2063,7 @@ ${X}
|
|
|
2011
2063
|
})]
|
|
2012
2064
|
})
|
|
2013
2065
|
});
|
|
2014
|
-
},
|
|
2066
|
+
}, ot = 3e3, st = h`
|
|
2015
2067
|
position: absolute;
|
|
2016
2068
|
inset: 0;
|
|
2017
2069
|
z-index: 2;
|
|
@@ -2022,7 +2074,7 @@ ${X}
|
|
|
2022
2074
|
hoverable while faded out, popping a tooltip over nothing. It cascades where pointer-events does
|
|
2023
2075
|
not, and transitioning it holds the item on screen for the length of the fade. */
|
|
2024
2076
|
transition: opacity 0.1s cubic-bezier(.4,0,1,1), visibility 0.1s;
|
|
2025
|
-
`,
|
|
2077
|
+
`, ct = h`
|
|
2026
2078
|
position: relative;
|
|
2027
2079
|
background-color: black;
|
|
2028
2080
|
display: flex;
|
|
@@ -2054,20 +2106,20 @@ ${X}
|
|
|
2054
2106
|
&.hide {
|
|
2055
2107
|
cursor: none;
|
|
2056
2108
|
}
|
|
2057
|
-
`,
|
|
2109
|
+
`, lt = (e, t = "") => s.toArray(e).flatMap((e, n) => {
|
|
2058
2110
|
let r = `${t}${l(e) && e.key != null ? e.key : n}`;
|
|
2059
|
-
return l(e) && e.type === c ?
|
|
2111
|
+
return l(e) && e.type === c ? lt(e.props.children, `${r}/`) : [{
|
|
2060
2112
|
key: r,
|
|
2061
2113
|
item: e
|
|
2062
2114
|
}];
|
|
2063
|
-
}),
|
|
2115
|
+
}), ut = ({ ref: e, onVideoRef: t, onCanvasRef: n, overlay: r, controls: i, children: a }) => {
|
|
2064
2116
|
let o = R(), s = R((e) => e.hideUI), c = R((e) => e.setHideUI), l = p(void 0), u = p("mouse");
|
|
2065
2117
|
d(() => () => clearTimeout(l.current), []);
|
|
2066
2118
|
let f = () => {
|
|
2067
|
-
c(!1), clearTimeout(l.current), l.current = setTimeout(() => c(!0),
|
|
2119
|
+
c(!1), clearTimeout(l.current), l.current = setTimeout(() => c(!0), ot);
|
|
2068
2120
|
};
|
|
2069
2121
|
return /* @__PURE__ */ w("div", {
|
|
2070
|
-
css:
|
|
2122
|
+
css: ct,
|
|
2071
2123
|
ref: e,
|
|
2072
2124
|
onPointerMove: (e) => {
|
|
2073
2125
|
u.current = e.pointerType, e.pointerType === "mouse" && f();
|
|
@@ -2083,9 +2135,9 @@ ${X}
|
|
|
2083
2135
|
},
|
|
2084
2136
|
className: s ? "hide" : "",
|
|
2085
2137
|
children: [
|
|
2086
|
-
/* @__PURE__ */ C(
|
|
2087
|
-
|
|
2088
|
-
css:
|
|
2138
|
+
/* @__PURE__ */ C(Ce, { onCanvasRef: n }),
|
|
2139
|
+
lt(r).map(({ key: e, item: t }) => /* @__PURE__ */ C("div", {
|
|
2140
|
+
css: st,
|
|
2089
2141
|
style: { ...s ? {
|
|
2090
2142
|
opacity: "0",
|
|
2091
2143
|
visibility: "hidden",
|
|
@@ -2093,8 +2145,8 @@ ${X}
|
|
|
2093
2145
|
} : {} },
|
|
2094
2146
|
children: t
|
|
2095
2147
|
}, e)),
|
|
2096
|
-
i === !1 ? null : /* @__PURE__ */ C(
|
|
2097
|
-
/* @__PURE__ */ C(
|
|
2148
|
+
i === !1 ? null : /* @__PURE__ */ C(nt, {}),
|
|
2149
|
+
/* @__PURE__ */ C(at, {}),
|
|
2098
2150
|
/* @__PURE__ */ w("div", {
|
|
2099
2151
|
className: "video",
|
|
2100
2152
|
onClick: () => {
|
|
@@ -2111,16 +2163,16 @@ ${X}
|
|
|
2111
2163
|
})
|
|
2112
2164
|
]
|
|
2113
2165
|
});
|
|
2114
|
-
},
|
|
2166
|
+
}, dt = ({ options: e, children: t }) => {
|
|
2115
2167
|
let n = "media" in e ? e : null, r = n ? null : e, { title: i } = e, { size: a, downloadedRanges: o, publicPath: s, libavWorkerUrl: c, read: l, thumbnailRead: u, thumbnailsEnabled: f } = r ?? {}, p = y(), h = v(), [g, _] = m(null), [b, x] = m(null), S = n?.media ?? g;
|
|
2116
|
-
d(() => (p?.(S), () => p?.(null)), [S, p]),
|
|
2117
|
-
let w =
|
|
2168
|
+
d(() => (p?.(S), () => p?.(null)), [S, p]), me(g, b, r);
|
|
2169
|
+
let w = _e({
|
|
2118
2170
|
publicPath: s,
|
|
2119
2171
|
workerUrl: c,
|
|
2120
2172
|
length: f === !1 ? void 0 : a,
|
|
2121
2173
|
read: u ?? l,
|
|
2122
2174
|
downloadedRanges: o
|
|
2123
|
-
}), T = n?.thumbnails?.all ?? w, { toggle: E, mode: D, burnedIn: O } =
|
|
2175
|
+
}), T = n?.thumbnails?.all ?? w, { toggle: E, mode: D, burnedIn: O } = z(g, b), k = R((e) => e.setSourceState);
|
|
2124
2176
|
d(() => {
|
|
2125
2177
|
k({
|
|
2126
2178
|
title: i,
|
|
@@ -2172,7 +2224,7 @@ ${X}
|
|
|
2172
2224
|
selectedAudioTrack: M.selectedId ?? void 0,
|
|
2173
2225
|
selectAudioTrack: (e) => M.select(String(e))
|
|
2174
2226
|
});
|
|
2175
|
-
}, [k, M]), /* @__PURE__ */ C(
|
|
2227
|
+
}, [k, M]), /* @__PURE__ */ C(ut, {
|
|
2176
2228
|
ref: h,
|
|
2177
2229
|
onVideoRef: n ? void 0 : _,
|
|
2178
2230
|
onCanvasRef: x,
|
|
@@ -2180,7 +2232,7 @@ ${X}
|
|
|
2180
2232
|
controls: e.controls,
|
|
2181
2233
|
children: t
|
|
2182
2234
|
});
|
|
2183
|
-
},
|
|
2235
|
+
}, ft = h`
|
|
2184
2236
|
/**
|
|
2185
2237
|
* The chrome's whole scale, in one place.
|
|
2186
2238
|
*
|
|
@@ -2250,17 +2302,17 @@ ${X}
|
|
|
2250
2302
|
height: 100%;
|
|
2251
2303
|
width: 100%;
|
|
2252
2304
|
overflow: hidden;
|
|
2253
|
-
`,
|
|
2254
|
-
css:
|
|
2255
|
-
children: /* @__PURE__ */ C(L.Provider, { children: /* @__PURE__ */ C(
|
|
2305
|
+
`, pt = (e) => /* @__PURE__ */ C("div", {
|
|
2306
|
+
css: ft,
|
|
2307
|
+
children: /* @__PURE__ */ C(L.Provider, { children: /* @__PURE__ */ C(dt, {
|
|
2256
2308
|
options: e,
|
|
2257
2309
|
children: e.children
|
|
2258
2310
|
}) })
|
|
2259
|
-
}),
|
|
2311
|
+
}), mt = (e) => !!e && typeof e == "object" && "at" in e, ht = (e) => !!e && typeof e == "object" && "selection" in e, gt = ({ blob: e, name: t }) => ({
|
|
2260
2312
|
length: e.size,
|
|
2261
2313
|
name: t ?? (e instanceof File ? e.name : void 0),
|
|
2262
2314
|
read: (t, n) => e.slice(t, t + n).arrayBuffer()
|
|
2263
|
-
}),
|
|
2315
|
+
}), _t = async (e, t) => {
|
|
2264
2316
|
let n = await fetch(e, {
|
|
2265
2317
|
headers: { Range: "bytes=0-1" },
|
|
2266
2318
|
credentials: t
|
|
@@ -2270,8 +2322,8 @@ ${X}
|
|
|
2270
2322
|
if (!Number.isFinite(i) || i <= 0) throw Error("The source did not report its length");
|
|
2271
2323
|
if (!r && n.status !== 206) throw Error("The source does not support range requests");
|
|
2272
2324
|
return i;
|
|
2273
|
-
},
|
|
2274
|
-
let i = t ?? await
|
|
2325
|
+
}, vt = async ({ url: e, length: t, name: n, credentials: r }) => {
|
|
2326
|
+
let i = t ?? await _t(e, r);
|
|
2275
2327
|
return {
|
|
2276
2328
|
length: i,
|
|
2277
2329
|
name: n,
|
|
@@ -2284,9 +2336,9 @@ ${X}
|
|
|
2284
2336
|
return a.arrayBuffer();
|
|
2285
2337
|
}
|
|
2286
2338
|
};
|
|
2287
|
-
},
|
|
2288
|
-
if ("blob" in e) return
|
|
2289
|
-
if ("url" in e) return
|
|
2339
|
+
}, yt = async (e) => {
|
|
2340
|
+
if ("blob" in e) return gt(e);
|
|
2341
|
+
if ("url" in e) return vt(e);
|
|
2290
2342
|
if ("read" in e) return {
|
|
2291
2343
|
length: e.length,
|
|
2292
2344
|
name: e.name,
|
|
@@ -2295,4 +2347,4 @@ ${X}
|
|
|
2295
2347
|
throw Error(`Unknown source type: ${e}`);
|
|
2296
2348
|
};
|
|
2297
2349
|
//#endregion
|
|
2298
|
-
export {
|
|
2350
|
+
export { pt as MediaPlayer, pt as default, L as Player, e as SUBTITLES_OFF, a as createPictureInPicture, o as createSubtitleRenderer, r as createThumbnailGenerator, yt as inputToRemuxerInput, ht as isDelegatedTracks, mt as isExternalThumbnails, ie as sourceFeature, i as startPlayback, z as usePictureInPicture, R as usePlayer, _e as useSeekThumbnails };
|
|
@@ -10,3 +10,12 @@ export declare const CaptionsOff: (props: SVGProps<SVGSVGElement>) => import("@e
|
|
|
10
10
|
* captions glyph either, because the button beside it already is one.
|
|
11
11
|
*/
|
|
12
12
|
export declare const SubtitlesInPicture: (props: SVGProps<SVGSVGElement>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
13
|
+
/**
|
|
14
|
+
* The same frame with the captions still on the MAIN picture: burn-in is available but off.
|
|
15
|
+
*
|
|
16
|
+
* The pair exists because that control is the one button in the bar whose glyph did not move with its
|
|
17
|
+
* state, so the state was carried by an accent colour and by nothing else. A pair, not a slash: a
|
|
18
|
+
* slashed resting state reads as unavailable, and the subtitles button beside it already draws
|
|
19
|
+
* Feather's slash for its own off state.
|
|
20
|
+
*/
|
|
21
|
+
export declare const SubtitlesOutsidePicture: (props: SVGProps<SVGSVGElement>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
package/dist/utils/colors.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -10,7 +10,7 @@ import { usePlayer } from '../player'
|
|
|
10
10
|
import { TooltipDisplay } from './tooltip-display'
|
|
11
11
|
import { ProgressBar } from './progress-bar'
|
|
12
12
|
import pictureInPicture from '../../assets/picture-in-picture.svg'
|
|
13
|
-
import { SubtitlesInPicture } from './icons'
|
|
13
|
+
import { SubtitlesInPicture, SubtitlesOutsidePicture } from './icons'
|
|
14
14
|
import ErrorsAction from './errors'
|
|
15
15
|
import SettingsAction from './settings'
|
|
16
16
|
import SubtitlesAction from './subtitles'
|
|
@@ -21,17 +21,15 @@ const VOLUME_STEP = 0.05
|
|
|
21
21
|
const SEEK_STEP = 5
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
|
-
* Two stacked lines inside a tooltip
|
|
24
|
+
* Two stacked lines inside a tooltip.
|
|
25
25
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
26
|
+
* The width to wrap against is no longer here: TooltipDisplay bounds every chip it draws, at the
|
|
27
|
+
* same 26 units this had imposed by hand, so a call site only says what its content is.
|
|
28
28
|
*/
|
|
29
29
|
const tooltipLinesStyle = css`
|
|
30
30
|
display: flex;
|
|
31
31
|
flex-direction: column;
|
|
32
32
|
gap: calc(0.4 * var(--mp-unit));
|
|
33
|
-
max-width: calc(26 * var(--mp-unit));
|
|
34
|
-
white-space: normal;
|
|
35
33
|
|
|
36
34
|
.hint {
|
|
37
35
|
opacity: 0.72;
|
|
@@ -97,16 +95,6 @@ const style = css`
|
|
|
97
95
|
}
|
|
98
96
|
}
|
|
99
97
|
|
|
100
|
-
/**
|
|
101
|
-
* The burn-in control's own on state.
|
|
102
|
-
*
|
|
103
|
-
* Not \`colors.hover\`: the pointer is on the button at the moment of the click, so an on state
|
|
104
|
-
* drawn in the hover colour is invisible exactly when it is being looked for.
|
|
105
|
-
*/
|
|
106
|
-
button[aria-pressed='true'] svg {
|
|
107
|
-
stroke: ${colors.accent};
|
|
108
|
-
}
|
|
109
|
-
|
|
110
98
|
.play, .sound, .time, .errors, .subtitles, .settings, .picture-in-picture, .full-screen {
|
|
111
99
|
display: flex;
|
|
112
100
|
align-items: center;
|
|
@@ -333,15 +321,20 @@ export const ControlBar = () => {
|
|
|
333
321
|
aria-label={burnIn ? 'Put the subtitles in the video' : 'Picture in picture'}
|
|
334
322
|
aria-pressed={burnIn ? burnedInSubtitles : undefined}
|
|
335
323
|
>
|
|
324
|
+
{/* The glyph carries the on state, which is what every other toggle in this bar
|
|
325
|
+
does. It used to be carried by an accent stroke instead, and that was the only
|
|
326
|
+
blue in the chrome. */}
|
|
336
327
|
{burnIn
|
|
337
|
-
?
|
|
328
|
+
? burnedInSubtitles
|
|
329
|
+
? <SubtitlesInPicture />
|
|
330
|
+
: <SubtitlesOutsidePicture />
|
|
338
331
|
: <img src={pictureInPicture} alt='' />}
|
|
339
332
|
</button>
|
|
340
333
|
}
|
|
341
334
|
toolTipText={
|
|
342
|
-
// The
|
|
343
|
-
//
|
|
344
|
-
//
|
|
335
|
+
// The chip is drawn in its own subtree, where the control bar's rules never
|
|
336
|
+
// reach it: a bare `small` stays inline and runs straight on from the line above
|
|
337
|
+
// it. Both lines carry their layout themselves.
|
|
345
338
|
<span css={tooltipLinesStyle}>
|
|
346
339
|
<span className='lead'>
|
|
347
340
|
{!burnIn
|
|
@@ -51,3 +51,19 @@ export const SubtitlesInPicture = (props: SVGProps<SVGSVGElement>) => (
|
|
|
51
51
|
<path d='M14.5 18.5h2m2 0h1' />
|
|
52
52
|
</svg>
|
|
53
53
|
)
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The same frame with the captions still on the MAIN picture: burn-in is available but off.
|
|
57
|
+
*
|
|
58
|
+
* The pair exists because that control is the one button in the bar whose glyph did not move with its
|
|
59
|
+
* state, so the state was carried by an accent colour and by nothing else. A pair, not a slash: a
|
|
60
|
+
* slashed resting state reads as unavailable, and the subtitles button beside it already draws
|
|
61
|
+
* Feather's slash for its own off state.
|
|
62
|
+
*/
|
|
63
|
+
export const SubtitlesOutsidePicture = (props: SVGProps<SVGSVGElement>) => (
|
|
64
|
+
<svg {...iconProps} {...props}>
|
|
65
|
+
<path d='M21 11V7a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h5' />
|
|
66
|
+
<rect x='12' y='13' width='10' height='8' rx='1' ry='1' />
|
|
67
|
+
<path d='M6 9h3m2 0h2' />
|
|
68
|
+
</svg>
|
|
69
|
+
)
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ReactNode } from 'react'
|
|
2
|
+
import type { TooltipRefProps } from 'react-tooltip'
|
|
2
3
|
|
|
4
|
+
import { useEffect, useRef } from 'react'
|
|
3
5
|
import { css } from '@emotion/react'
|
|
4
6
|
import { PlacesType, Tooltip } from 'react-tooltip'
|
|
5
7
|
|
|
@@ -13,9 +15,31 @@ export enum buttonSize {
|
|
|
13
15
|
|
|
14
16
|
const style = (size: buttonSize) => css`
|
|
15
17
|
display: flex;
|
|
16
|
-
justify-content: flex-
|
|
18
|
+
justify-content: flex-start;
|
|
17
19
|
|
|
18
|
-
|
|
20
|
+
/*
|
|
21
|
+
* Bounded here rather than at each call site.
|
|
22
|
+
*
|
|
23
|
+
* react-tooltip's own chip rule carries width: max-content, so with nothing opposing it a chip
|
|
24
|
+
* grows to the widest UNWRAPPED line of its content: a two sentence tooltip measured 1178px
|
|
25
|
+
* through this component. Both declarations are load bearing, since a bound with no wrapping only
|
|
26
|
+
* moves the overflow inside a narrow box. 26 units is the width control-bar.tsx was already
|
|
27
|
+
* imposing on its own two line tooltip by hand, so nothing in the bar changes shape.
|
|
28
|
+
*/
|
|
29
|
+
max-width: min(calc(26 * var(--mp-unit)), calc(100vw - calc(2.4 * var(--mp-unit))));
|
|
30
|
+
white-space: normal;
|
|
31
|
+
overflow-wrap: anywhere;
|
|
32
|
+
text-align: left;
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* The radius carries !important for the same reason the paddings below do.
|
|
36
|
+
*
|
|
37
|
+
* react-tooltip injects its stylesheet from a passive effect while emotion inserts through
|
|
38
|
+
* useInsertionEffect, which runs earlier, so react-tooltip's sheet lands in the head LAST at
|
|
39
|
+
* exactly this specificity and wins every tie. Its own radius is 3px, which is what was drawn
|
|
40
|
+
* here until this was stated.
|
|
41
|
+
*/
|
|
42
|
+
border-radius: calc(0.4 * var(--mp-unit))!important;
|
|
19
43
|
user-select: none;
|
|
20
44
|
|
|
21
45
|
z-index: 3;
|
|
@@ -35,6 +59,25 @@ const style = (size: buttonSize) => css`
|
|
|
35
59
|
`}
|
|
36
60
|
`
|
|
37
61
|
|
|
62
|
+
/**
|
|
63
|
+
* Where the pointer is, shared by every anchor rather than tracked once per tooltip.
|
|
64
|
+
*
|
|
65
|
+
* The chrome mounts eight of these, and each only needs to answer one question at one moment, so a
|
|
66
|
+
* single refcounted listener answers it for all of them. Installed on the first mount rather than at
|
|
67
|
+
* module scope, so importing this library still does nothing to the document.
|
|
68
|
+
*/
|
|
69
|
+
const pointer = { x: -1, y: -1, anchors: 0 }
|
|
70
|
+
const trackPointer = (event: PointerEvent) => { pointer.x = event.clientX; pointer.y = event.clientY }
|
|
71
|
+
|
|
72
|
+
const watchPointer = () => {
|
|
73
|
+
if (pointer.anchors++ === 0) {
|
|
74
|
+
window.addEventListener('pointermove', trackPointer, { capture: true, passive: true })
|
|
75
|
+
}
|
|
76
|
+
return () => {
|
|
77
|
+
if (--pointer.anchors === 0) window.removeEventListener('pointermove', trackPointer, { capture: true })
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
38
81
|
interface TooltipDisplayProps {
|
|
39
82
|
id: string
|
|
40
83
|
toolTipText: ReactNode
|
|
@@ -57,30 +100,77 @@ export const TooltipDisplay = ({
|
|
|
57
100
|
tooltipPlace = 'top',
|
|
58
101
|
disabled = false,
|
|
59
102
|
size = buttonSize.md
|
|
60
|
-
}: TooltipDisplayProps) =>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
103
|
+
}: TooltipDisplayProps) => {
|
|
104
|
+
const anchor = useRef<HTMLDivElement>(null)
|
|
105
|
+
const tooltip = useRef<TooltipRefProps>(null)
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Close on a fullscreen transition, unless the pointer really is still on the anchor.
|
|
109
|
+
*
|
|
110
|
+
* Going fullscreen relays the whole chrome out from under a pointer that never moved, and the
|
|
111
|
+
* browser recomputes the hover chain for that SILENTLY: the :hover flag flips a frame later, so
|
|
112
|
+
* the grey pill corrects itself in about 14ms, but no boundary event is dispatched at all.
|
|
113
|
+
* react-tooltip closes on mouseout and on nothing else, so it never learns the pointer left and
|
|
114
|
+
* the chip stays painted for the rest of the session. It survives arbitrary pointer movement,
|
|
115
|
+
* because the browser has already updated its own element-under-pointer, and it survives the
|
|
116
|
+
* chrome's auto-hide, coming back the moment the controls wake.
|
|
117
|
+
*
|
|
118
|
+
* Scoped to the fullscreen transition on purpose: the same layout move made by ordinary CSS does
|
|
119
|
+
* dispatch mouseout and closes the chip by itself, so no other reflow needs this and widening it
|
|
120
|
+
* would only add ways to close a tooltip that should be open.
|
|
121
|
+
*
|
|
122
|
+
* Tested against the anchor's rect rather than closed outright, because a player that already
|
|
123
|
+
* fills the window moves nothing, and the tooltip under the pointer is then legitimately open.
|
|
124
|
+
* That is the same test chrome.tsx's onMouseOut makes when relatedTarget comes back null. The rect
|
|
125
|
+
* is already the post-transition one when fullscreenchange fires, where matches(':hover') is not,
|
|
126
|
+
* which is why the pointer is tracked rather than asked for.
|
|
127
|
+
*/
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
const untrack = watchPointer()
|
|
130
|
+
const closeIfPointerLeft = () => {
|
|
131
|
+
const element = anchor.current
|
|
132
|
+
if (!element) return
|
|
133
|
+
const { left, right, top, bottom } = element.getBoundingClientRect()
|
|
134
|
+
if (pointer.x >= left && pointer.x < right && pointer.y >= top && pointer.y < bottom) return
|
|
135
|
+
tooltip.current?.close()
|
|
136
|
+
}
|
|
137
|
+
// webkit's own name as well, the way @videojs/core's fullscreen feature listens for both. Typed
|
|
138
|
+
// as string so the prefixed name checks against the DOM lib's event map.
|
|
139
|
+
const changeEvents: string[] = ['fullscreenchange', 'webkitfullscreenchange']
|
|
140
|
+
for (const type of changeEvents) document.addEventListener(type, closeIfPointerLeft)
|
|
141
|
+
return () => {
|
|
142
|
+
untrack()
|
|
143
|
+
for (const type of changeEvents) document.removeEventListener(type, closeIfPointerLeft)
|
|
82
144
|
}
|
|
83
|
-
|
|
84
|
-
|
|
145
|
+
}, [])
|
|
146
|
+
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
<div
|
|
150
|
+
ref={anchor}
|
|
151
|
+
data-tooltip-id={id}
|
|
152
|
+
data-open={true}
|
|
153
|
+
data-tooltip-offset={offset}
|
|
154
|
+
data-tooltip-delay-show={delayShow}
|
|
155
|
+
data-tooltip-delay-hide={closeDelay}
|
|
156
|
+
data-tooltip-place={tooltipPlace}
|
|
157
|
+
>
|
|
158
|
+
{text}
|
|
159
|
+
</div>
|
|
160
|
+
{
|
|
161
|
+
!disabled && (
|
|
162
|
+
<Tooltip
|
|
163
|
+
ref={tooltip}
|
|
164
|
+
css={style(size)}
|
|
165
|
+
id={id}
|
|
166
|
+
noArrow={true}
|
|
167
|
+
>
|
|
168
|
+
{toolTipText}
|
|
169
|
+
</Tooltip>
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
</>
|
|
173
|
+
)
|
|
174
|
+
}
|
|
85
175
|
|
|
86
176
|
export default TooltipDisplay
|
package/src/lib/utils/colors.ts
CHANGED
|
@@ -2,8 +2,6 @@ const colors = {
|
|
|
2
2
|
primary: '#EAEBEE',
|
|
3
3
|
secondary: '#D0D0D9',
|
|
4
4
|
hover: 'rgba(255, 255, 255, 0.13)',
|
|
5
|
-
/** A control that is ON. Distinct from `hover`, which the pointer is already painting. */
|
|
6
|
-
accent: '#6EA8FE',
|
|
7
5
|
borderPrimary: '#384F70',
|
|
8
6
|
backgroundTooltip: '#222222',
|
|
9
7
|
}
|