@openrails/contentkit-ui 0.103.2 → 0.104.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -49
- package/dist/client/beacons.d.ts +3 -13
- package/dist/client/beacons.js +8 -46
- package/dist/client/beacons.js.map +1 -1
- package/dist/client/client.d.ts +3 -0
- package/dist/client/client.js +45 -43
- package/dist/client/client.js.map +1 -1
- package/dist/client/content/favorites.d.ts +2 -0
- package/dist/client/content/favorites.js.map +1 -1
- package/dist/client/content/types.d.ts +3 -0
- package/dist/client/content/types.js.map +1 -1
- package/dist/client/contents.d.ts +7 -1
- package/dist/client/contents.js +8 -0
- package/dist/client/contents.js.map +1 -1
- package/dist/client/discovery.d.ts +34 -5
- package/dist/client/discovery.js +23 -2
- package/dist/client/discovery.js.map +1 -1
- package/dist/client/engagement.d.ts +70 -0
- package/dist/client/engagement.js +191 -0
- package/dist/client/engagement.js.map +1 -0
- package/dist/client/generated/routes.d.ts +74 -35
- package/dist/client/generated/routes.js +119 -60
- package/dist/client/generated/routes.js.map +1 -1
- package/dist/client/generated/wire.d.ts +88 -85
- package/dist/client/generated/wire.js.map +1 -1
- package/dist/client/guest-reading-history.d.ts +40 -0
- package/dist/client/guest-reading-history.js +144 -0
- package/dist/client/guest-reading-history.js.map +1 -0
- package/dist/client/index.d.ts +5 -3
- package/dist/client/media/windows.d.ts +2 -0
- package/dist/client/media/windows.js +4 -1
- package/dist/client/media/windows.js.map +1 -1
- package/dist/client/stats.d.ts +4 -20
- package/dist/client/stats.js +0 -11
- package/dist/client/stats.js.map +1 -1
- package/dist/client/versions.d.ts +8 -6
- package/dist/client/versions.js +15 -10
- package/dist/client/versions.js.map +1 -1
- package/dist/client.js +24 -22
- package/dist/components/admin/bulk-drafts.d.ts +17 -0
- package/dist/components/admin/bulk-drafts.js +41 -0
- package/dist/components/admin/bulk-drafts.js.map +1 -0
- package/dist/components/admin/content-admin.d.ts +1 -1
- package/dist/components/admin/content-admin.js.map +1 -1
- package/dist/components/admin/content-manager.d.ts +11 -3
- package/dist/components/admin/content-manager.js +751 -394
- package/dist/components/admin/content-manager.js.map +1 -1
- package/dist/components/admin/group-manager.d.ts +8 -3
- package/dist/components/admin/group-manager.js +218 -146
- package/dist/components/admin/group-manager.js.map +1 -1
- package/dist/components/admin/page-notices.d.ts +16 -0
- package/dist/components/admin/page-notices.js +113 -0
- package/dist/components/admin/page-notices.js.map +1 -0
- package/dist/components/admin/page-picker.d.ts +38 -0
- package/dist/components/admin/page-picker.js +159 -0
- package/dist/components/admin/page-picker.js.map +1 -0
- package/dist/components/admin/quick-search.d.ts +14 -0
- package/dist/components/admin/quick-search.js +60 -0
- package/dist/components/admin/quick-search.js.map +1 -0
- package/dist/components/admin/reader-content-editor.js +382 -321
- package/dist/components/admin/reader-content-editor.js.map +1 -1
- package/dist/components/admin/reader-manifest.js +181 -179
- package/dist/components/admin/reader-manifest.js.map +1 -1
- package/dist/components/admin/shell.d.ts +10 -2
- package/dist/components/admin/shell.js +114 -42
- package/dist/components/admin/shell.js.map +1 -1
- package/dist/components/admin/stats-dashboard.d.ts +4 -9
- package/dist/components/admin/stats-dashboard.js +303 -207
- package/dist/components/admin/stats-dashboard.js.map +1 -1
- package/dist/components/admin/upload-queue.d.ts +14 -0
- package/dist/components/admin/upload-queue.js +115 -98
- package/dist/components/admin/upload-queue.js.map +1 -1
- package/dist/components/content/card.d.ts +31 -3
- package/dist/components/content/card.js +324 -158
- package/dist/components/content/card.js.map +1 -1
- package/dist/components/content/daily-releases.js +144 -190
- package/dist/components/content/daily-releases.js.map +1 -1
- package/dist/components/content/editor-save.js +27 -25
- package/dist/components/content/editor-save.js.map +1 -1
- package/dist/components/content/editors.js +274 -253
- package/dist/components/content/editors.js.map +1 -1
- package/dist/components/content/favorites.d.ts +6 -0
- package/dist/components/content/favorites.js +47 -0
- package/dist/components/content/favorites.js.map +1 -0
- package/dist/components/content/filter-dialog.js +19 -15
- package/dist/components/content/filter-dialog.js.map +1 -1
- package/dist/components/content/filters.d.ts +2 -0
- package/dist/components/content/filters.js +5 -1
- package/dist/components/content/filters.js.map +1 -1
- package/dist/components/content/grid.d.ts +44 -16
- package/dist/components/content/grid.js +308 -270
- package/dist/components/content/grid.js.map +1 -1
- package/dist/components/content/history.d.ts +6 -0
- package/dist/components/content/history.js +111 -0
- package/dist/components/content/history.js.map +1 -0
- package/dist/components/content/index.d.ts +6 -3
- package/dist/components/content/listing.d.ts +14 -3
- package/dist/components/content/listing.js +65 -56
- package/dist/components/content/listing.js.map +1 -1
- package/dist/components/content/offer-fields.js +6 -6
- package/dist/components/content/paged-grid.d.ts +10 -0
- package/dist/components/content/paged-grid.js +116 -0
- package/dist/components/content/paged-grid.js.map +1 -0
- package/dist/components/content/pagination.d.ts +19 -0
- package/dist/components/content/pagination.js +97 -0
- package/dist/components/content/pagination.js.map +1 -0
- package/dist/components/content/paywall.d.ts +9 -0
- package/dist/components/content/paywall.js +27 -3
- package/dist/components/content/paywall.js.map +1 -1
- package/dist/components/content/post-list.d.ts +37 -0
- package/dist/components/content/post-list.js +203 -0
- package/dist/components/content/post-list.js.map +1 -0
- package/dist/components/content/reader-settings.d.ts +2 -0
- package/dist/components/content/reader-settings.js +1 -1
- package/dist/components/content/reader-settings.js.map +1 -1
- package/dist/components/content/search.d.ts +11 -4
- package/dist/components/content/search.js +22 -11
- package/dist/components/content/search.js.map +1 -1
- package/dist/components/content/summary-tile.d.ts +14 -0
- package/dist/components/content/summary-tile.js +63 -0
- package/dist/components/content/summary-tile.js.map +1 -0
- package/dist/components/groups/banner.d.ts +6 -2
- package/dist/components/groups/banner.js +79 -61
- package/dist/components/groups/banner.js.map +1 -1
- package/dist/components/groups/directory.d.ts +12 -2
- package/dist/components/groups/directory.js +168 -105
- package/dist/components/groups/directory.js.map +1 -1
- package/dist/components/groups/editor.js +10 -10
- package/dist/components/groups/editor.js.map +1 -1
- package/dist/components/groups/entity-chips.d.ts +61 -0
- package/dist/components/groups/entity-chips.js +382 -0
- package/dist/components/groups/entity-chips.js.map +1 -0
- package/dist/components/groups/group-members.d.ts +29 -0
- package/dist/components/groups/group-members.js +474 -0
- package/dist/components/groups/group-members.js.map +1 -0
- package/dist/components/groups/header.js +53 -45
- package/dist/components/groups/header.js.map +1 -1
- package/dist/components/groups/index.d.ts +3 -1
- package/dist/components/groups/memberships.d.ts +3 -36
- package/dist/components/groups/memberships.js +105 -480
- package/dist/components/groups/memberships.js.map +1 -1
- package/dist/components/groups/scoped.d.ts +23 -0
- package/dist/components/groups/scoped.js +92 -0
- package/dist/components/groups/scoped.js.map +1 -0
- package/dist/components/media-folder-editor.d.ts +5 -0
- package/dist/components/media-folder-editor.js +419 -231
- package/dist/components/media-folder-editor.js.map +1 -1
- package/dist/components/sortable-list.d.ts +5 -1
- package/dist/components/sortable-list.js +97 -81
- package/dist/components/sortable-list.js.map +1 -1
- package/dist/components/video-mini-player.d.ts +4 -1
- package/dist/components/video-mini-player.js +77 -71
- package/dist/components/video-mini-player.js.map +1 -1
- package/dist/components/video-player.d.ts +4 -1
- package/dist/components/video-player.js +280 -276
- package/dist/components/video-player.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +41 -34
- package/dist/locales/admin/de.js +80 -47
- package/dist/locales/admin/de.js.map +1 -1
- package/dist/locales/admin/en.d.ts +74 -41
- package/dist/locales/admin/en.js +80 -47
- package/dist/locales/admin/en.js.map +1 -1
- package/dist/locales/admin/es.js +80 -47
- package/dist/locales/admin/es.js.map +1 -1
- package/dist/locales/admin/ja.js +80 -47
- package/dist/locales/admin/ja.js.map +1 -1
- package/dist/locales/admin/ko.js +80 -47
- package/dist/locales/admin/ko.js.map +1 -1
- package/dist/locales/admin/zh.js +80 -47
- package/dist/locales/admin/zh.js.map +1 -1
- package/dist/locales/de.js +1 -0
- package/dist/locales/de.js.map +1 -1
- package/dist/locales/discovery/de.js +25 -2
- package/dist/locales/discovery/de.js.map +1 -1
- package/dist/locales/discovery/en.d.ts +24 -1
- package/dist/locales/discovery/en.js +25 -2
- package/dist/locales/discovery/en.js.map +1 -1
- package/dist/locales/discovery/es.js +25 -2
- package/dist/locales/discovery/es.js.map +1 -1
- package/dist/locales/discovery/ja.js +25 -2
- package/dist/locales/discovery/ja.js.map +1 -1
- package/dist/locales/discovery/ko.js +25 -2
- package/dist/locales/discovery/ko.js.map +1 -1
- package/dist/locales/discovery/zh.js +25 -2
- package/dist/locales/discovery/zh.js.map +1 -1
- package/dist/locales/en.d.ts +119 -44
- package/dist/locales/en.js +1 -0
- package/dist/locales/en.js.map +1 -1
- package/dist/locales/es.js +1 -0
- package/dist/locales/es.js.map +1 -1
- package/dist/locales/groups/de.js +22 -4
- package/dist/locales/groups/de.js.map +1 -1
- package/dist/locales/groups/en.d.ts +20 -2
- package/dist/locales/groups/en.js +22 -4
- package/dist/locales/groups/en.js.map +1 -1
- package/dist/locales/groups/es.js +22 -4
- package/dist/locales/groups/es.js.map +1 -1
- package/dist/locales/groups/ja.js +22 -4
- package/dist/locales/groups/ja.js.map +1 -1
- package/dist/locales/groups/ko.js +22 -4
- package/dist/locales/groups/ko.js.map +1 -1
- package/dist/locales/groups/zh.js +22 -4
- package/dist/locales/groups/zh.js.map +1 -1
- package/dist/locales/ja.js +1 -0
- package/dist/locales/ja.js.map +1 -1
- package/dist/locales/ko.js +1 -0
- package/dist/locales/ko.js.map +1 -1
- package/dist/locales/zh.js +1 -0
- package/dist/locales/zh.js.map +1 -1
- package/dist/react/discovery.d.ts +36 -17
- package/dist/react/discovery.js +305 -221
- package/dist/react/discovery.js.map +1 -1
- package/dist/react/groups.d.ts +19 -3
- package/dist/react/groups.js +49 -22
- package/dist/react/groups.js.map +1 -1
- package/dist/react/index.d.ts +7 -4
- package/dist/react/page-notices.d.ts +13 -0
- package/dist/react/page-notices.js +38 -0
- package/dist/react/page-notices.js.map +1 -0
- package/dist/react/post-reads.d.ts +23 -0
- package/dist/react/post-reads.js +90 -0
- package/dist/react/post-reads.js.map +1 -0
- package/dist/react/remembered-sort.d.ts +5 -0
- package/dist/react/remembered-sort.js +29 -0
- package/dist/react/remembered-sort.js.map +1 -0
- package/dist/react/resources.d.ts +3 -1
- package/dist/react/resources.js +6 -2
- package/dist/react/resources.js.map +1 -1
- package/dist/react/stats.d.ts +3 -7
- package/dist/react/stats.js +2 -6
- package/dist/react/stats.js.map +1 -1
- package/dist/react/use-engagement.d.ts +28 -0
- package/dist/react/use-engagement.js +226 -0
- package/dist/react/use-engagement.js.map +1 -0
- package/dist/react/use-resource.d.ts +4 -3
- package/dist/react/use-resource.js +2 -1
- package/dist/react/use-resource.js.map +1 -1
- package/dist/react.js +29 -26
- package/dist/styles.css +1 -1
- package/dist/ui/dialog.d.ts +2 -1
- package/dist/ui/dialog.js +23 -20
- package/dist/ui/dialog.js.map +1 -1
- package/dist/urls/index.d.ts +1 -1
- package/dist/urls.js +2 -2
- package/dist/urls.js.map +1 -1
- package/package.json +1 -1
- package/dist/components/admin/page-review.d.ts +0 -13
- package/dist/components/admin/page-review.js +0 -225
- package/dist/components/admin/page-review.js.map +0 -1
- package/dist/react/page-review.d.ts +0 -14
- package/dist/react/page-review.js +0 -37
- package/dist/react/page-review.js.map +0 -1
|
@@ -3,9 +3,9 @@ import { publicRenditions as t } from "../client/public.js";
|
|
|
3
3
|
import { useMessages as n } from "../i18n/context.js";
|
|
4
4
|
import { ContentKitUiRoot as ee } from "../scope.js";
|
|
5
5
|
import { PLAYER_VOLUME_KEY as r, playerKeyAction as i, writeVolume as a } from "../client/player.js";
|
|
6
|
-
import { useHlsPlayer as
|
|
7
|
-
import { useActiveCues as
|
|
8
|
-
import { Captions as
|
|
6
|
+
import { useHlsPlayer as o } from "../react/gallery.js";
|
|
7
|
+
import { useActiveCues as te, useMediaState as ne, useProgressReports as re } from "../react/player.js";
|
|
8
|
+
import { Captions as ie, ControlButton as s, SeekBar as ae, Spinner as oe, clock as c } from "./player-controls.js";
|
|
9
9
|
import { SpriteFrame as l, keyAllowed as u } from "./video-player.js";
|
|
10
10
|
import { useCallback as d, useEffect as f, useRef as p, useState as m } from "react";
|
|
11
11
|
import { jsx as h, jsxs as g } from "react/jsx-runtime";
|
|
@@ -14,56 +14,62 @@ import { Cancel01Icon as se, GoBackward10SecIcon as ce, GoForward10SecIcon as le
|
|
|
14
14
|
import { HugeiconsIcon as he } from "@hugeicons/react";
|
|
15
15
|
//#region src/components/video-mini-player.tsx
|
|
16
16
|
var ge = 2500;
|
|
17
|
-
function v({ handoff: v, onExpand: _e, onClose:
|
|
18
|
-
let { t:
|
|
19
|
-
...
|
|
20
|
-
src:
|
|
17
|
+
function v({ handoff: v, onExpand: _e, onClose: ve, onProgress: ye, engagement: y, progressInterval: be = 1e4, keyboard: b = "global", label: x, position: xe = "bottom-right", crossOrigin: Se, className: Ce, style: we, appearance: Te, ...S }) {
|
|
18
|
+
let { t: C } = n(), w = `${v.base}master.m3u8`, T = o({
|
|
19
|
+
...S,
|
|
20
|
+
src: w,
|
|
21
21
|
startAt: v.time,
|
|
22
22
|
autoPlay: v.playing,
|
|
23
23
|
audioLanguage: v.audioLanguage,
|
|
24
24
|
subtitleLanguage: v.subtitleLanguage,
|
|
25
25
|
trackKey: null,
|
|
26
26
|
qualityKey: null
|
|
27
|
-
}), { status:
|
|
28
|
-
|
|
29
|
-
}, [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
}), { status: E, error: D, started: O } = T, [k, Ee] = m(null), A = T.ref, De = d((e) => {
|
|
28
|
+
A(e), Ee(e);
|
|
29
|
+
}, [A]), j = y?.video;
|
|
30
|
+
f(() => (j?.(O ? k : null), () => j?.(null)), [
|
|
31
|
+
j,
|
|
32
|
+
O,
|
|
33
|
+
k
|
|
34
|
+
]);
|
|
35
|
+
let M = ne(k), N = te(k);
|
|
36
|
+
re(k, {
|
|
37
|
+
enabled: O,
|
|
38
|
+
source: O ? w : null,
|
|
39
|
+
interval: be,
|
|
40
|
+
onProgress: ye
|
|
35
41
|
});
|
|
36
|
-
let [
|
|
42
|
+
let [Oe, P] = m(!0), F = p(void 0), I = d(() => {
|
|
37
43
|
P(!0), clearTimeout(F.current), F.current = setTimeout(() => P(!1), ge);
|
|
38
44
|
}, []), L = d(() => {
|
|
39
45
|
clearTimeout(F.current), P(!1);
|
|
40
46
|
}, []);
|
|
41
47
|
f(() => () => clearTimeout(F.current), []);
|
|
42
|
-
let [R,
|
|
48
|
+
let [R, ke] = m(!1), z = !M.paused && !M.ended, B = Oe || !z || R || !!D, V = p(!1), H = () => k?.currentTime || M.time || v.time, Ae = () => {
|
|
43
49
|
V.current || (V.current = !0, _e({
|
|
44
50
|
time: H(),
|
|
45
51
|
playing: z
|
|
46
52
|
}));
|
|
47
|
-
},
|
|
48
|
-
V.current || (V.current = !0,
|
|
53
|
+
}, je = () => {
|
|
54
|
+
V.current || (V.current = !0, k?.pause(), ve({ time: H() }));
|
|
49
55
|
}, U = () => {
|
|
50
|
-
|
|
56
|
+
k && (!O || k.paused || k.ended ? T.play() : k.pause());
|
|
51
57
|
}, W = M.duration || v.duration || 0, G = (e) => {
|
|
52
|
-
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
volume:
|
|
56
|
-
muted:
|
|
58
|
+
k && (k.currentTime = Math.min(W || e, Math.max(0, e)));
|
|
59
|
+
}, Me = S.volumeKey === void 0 ? r : S.volumeKey, K = () => {
|
|
60
|
+
k && (k.muted = !k.muted, !k.muted && k.volume === 0 && (k.volume = 1), a(Me, {
|
|
61
|
+
volume: k.volume,
|
|
62
|
+
muted: k.muted
|
|
57
63
|
}));
|
|
58
64
|
}, q = (e, t) => {
|
|
59
|
-
if (!
|
|
65
|
+
if (!k || b === "global" && !"kjlmKJLM".includes(t)) return !1;
|
|
60
66
|
switch (e.type) {
|
|
61
67
|
case "toggle":
|
|
62
68
|
U();
|
|
63
69
|
break;
|
|
64
70
|
case "seekBy":
|
|
65
|
-
if (!
|
|
66
|
-
G(
|
|
71
|
+
if (!O) return !1;
|
|
72
|
+
G(k.currentTime + e.seconds);
|
|
67
73
|
break;
|
|
68
74
|
case "mute":
|
|
69
75
|
K();
|
|
@@ -73,46 +79,46 @@ function v({ handoff: v, onExpand: _e, onClose: y, onProgress: b, progressInterv
|
|
|
73
79
|
return I(), !0;
|
|
74
80
|
}, J = p(q);
|
|
75
81
|
J.current = q;
|
|
76
|
-
let [Y,
|
|
82
|
+
let [Y, Ne] = m(null);
|
|
77
83
|
f(() => {
|
|
78
|
-
if (!
|
|
79
|
-
let e =
|
|
84
|
+
if (!b || !Y) return;
|
|
85
|
+
let e = b === "global" ? document : Y, t = (e) => {
|
|
80
86
|
let t = e;
|
|
81
87
|
if (t.defaultPrevented) return;
|
|
82
88
|
let n = i(t);
|
|
83
89
|
n && u(t.target, t.key, Y) && J.current(n, t.key) && t.preventDefault();
|
|
84
90
|
};
|
|
85
91
|
return e.addEventListener("keydown", t), () => e.removeEventListener("keydown", t);
|
|
86
|
-
}, [
|
|
87
|
-
let X = p("mouse"),
|
|
92
|
+
}, [b, Y]);
|
|
93
|
+
let X = p("mouse"), Pe = (e) => {
|
|
88
94
|
e.preventDefault(), X.current === "mouse" ? (U(), I()) : B && z ? L() : I();
|
|
89
|
-
}, Z = v.width && v.height ? v.width / v.height : M.aspect ?? 16 / 9, Q = typeof v.poster == "string" ? [] : t(v.poster),
|
|
95
|
+
}, Z = v.width && v.height ? v.width / v.height : M.aspect ?? 16 / 9, Q = typeof v.poster == "string" ? [] : t(v.poster), Fe = !D && (E === "loading" || E === "buffering"), $ = "rounded-full text-white hover:bg-white/15";
|
|
90
96
|
return /* @__PURE__ */ g(ee, {
|
|
91
|
-
ref:
|
|
92
|
-
appearance:
|
|
97
|
+
ref: Ne,
|
|
98
|
+
appearance: Te,
|
|
93
99
|
role: "region",
|
|
94
|
-
"aria-label":
|
|
100
|
+
"aria-label": x ? `${C("player.miniPlayer")}: ${x}` : C("player.miniPlayer"),
|
|
95
101
|
"data-ckui": "mini-player",
|
|
96
|
-
"data-status":
|
|
97
|
-
className: _("@container fixed bottom-4 z-50 touch-manipulation overflow-hidden rounded-md bg-black text-white shadow-lg select-none",
|
|
102
|
+
"data-status": E,
|
|
103
|
+
className: _("@container fixed bottom-4 z-50 touch-manipulation overflow-hidden rounded-md bg-black text-white shadow-lg select-none", xe === "bottom-left" ? "left-4" : "right-4", Ce),
|
|
98
104
|
style: {
|
|
99
105
|
aspectRatio: String(Z),
|
|
100
106
|
width: `min(24rem, calc(100vw - 2rem), calc(60svh * ${Z}))`,
|
|
101
|
-
...
|
|
107
|
+
...we
|
|
102
108
|
},
|
|
103
109
|
onPointerDown: (e) => X.current = e.pointerType || "mouse",
|
|
104
110
|
onPointerMove: (e) => e.pointerType === "mouse" && I(),
|
|
105
111
|
onPointerLeave: (e) => e.pointerType === "mouse" && !R && z && L(),
|
|
106
112
|
children: [
|
|
107
113
|
/* @__PURE__ */ h("video", {
|
|
108
|
-
ref:
|
|
114
|
+
ref: De,
|
|
109
115
|
className: "absolute inset-0 size-full object-contain",
|
|
110
116
|
playsInline: !0,
|
|
111
117
|
preload: "none",
|
|
112
|
-
crossOrigin:
|
|
113
|
-
"aria-label":
|
|
118
|
+
crossOrigin: Se,
|
|
119
|
+
"aria-label": x
|
|
114
120
|
}),
|
|
115
|
-
!
|
|
121
|
+
!O && (typeof v.poster == "string" ? /* @__PURE__ */ h("img", {
|
|
116
122
|
alt: "",
|
|
117
123
|
src: v.poster,
|
|
118
124
|
className: "pointer-events-none absolute inset-0 size-full object-contain"
|
|
@@ -121,16 +127,16 @@ function v({ handoff: v, onExpand: _e, onClose: y, onProgress: b, progressInterv
|
|
|
121
127
|
className: "pointer-events-none absolute inset-0 size-full object-contain"
|
|
122
128
|
}) : /* @__PURE__ */ h(l, {
|
|
123
129
|
vtt: `${v.base}sprite.vtt`,
|
|
124
|
-
loader:
|
|
130
|
+
loader: S.loader
|
|
125
131
|
})),
|
|
126
132
|
/* @__PURE__ */ h("div", {
|
|
127
133
|
"aria-hidden": !0,
|
|
128
134
|
"data-ckui": "surface",
|
|
129
135
|
className: "absolute inset-0",
|
|
130
|
-
onClick:
|
|
136
|
+
onClick: Pe
|
|
131
137
|
}),
|
|
132
|
-
/* @__PURE__ */ h(
|
|
133
|
-
cues:
|
|
138
|
+
/* @__PURE__ */ h(ie, {
|
|
139
|
+
cues: O ? N : [],
|
|
134
140
|
bottom: B ? "2.75rem" : "0.75rem"
|
|
135
141
|
}),
|
|
136
142
|
/* @__PURE__ */ g("div", {
|
|
@@ -139,16 +145,16 @@ function v({ handoff: v, onExpand: _e, onClose: y, onProgress: b, progressInterv
|
|
|
139
145
|
children: [
|
|
140
146
|
/* @__PURE__ */ g("div", {
|
|
141
147
|
className: "absolute inset-x-0 top-0 flex items-center justify-between p-1.5",
|
|
142
|
-
children: [/* @__PURE__ */ h(
|
|
143
|
-
label:
|
|
148
|
+
children: [/* @__PURE__ */ h(s, {
|
|
149
|
+
label: C("player.expand"),
|
|
144
150
|
icon: fe,
|
|
145
|
-
onClick:
|
|
151
|
+
onClick: Ae,
|
|
146
152
|
className: $,
|
|
147
153
|
"data-ckui": "mini-expand"
|
|
148
|
-
}), /* @__PURE__ */ h(
|
|
149
|
-
label:
|
|
154
|
+
}), /* @__PURE__ */ h(s, {
|
|
155
|
+
label: C("player.close"),
|
|
150
156
|
icon: se,
|
|
151
|
-
onClick:
|
|
157
|
+
onClick: je,
|
|
152
158
|
className: $,
|
|
153
159
|
"data-ckui": "mini-close"
|
|
154
160
|
})]
|
|
@@ -156,10 +162,10 @@ function v({ handoff: v, onExpand: _e, onClose: y, onProgress: b, progressInterv
|
|
|
156
162
|
/* @__PURE__ */ g("div", {
|
|
157
163
|
className: "absolute inset-0 m-auto flex h-fit w-fit items-center gap-3 @sm:gap-5",
|
|
158
164
|
children: [
|
|
159
|
-
/* @__PURE__ */ h(
|
|
160
|
-
label:
|
|
165
|
+
/* @__PURE__ */ h(s, {
|
|
166
|
+
label: C("player.seekBack", { seconds: 10 }),
|
|
161
167
|
icon: ce,
|
|
162
|
-
disabled: !
|
|
168
|
+
disabled: !O,
|
|
163
169
|
onClick: () => {
|
|
164
170
|
G(H() - 10), I();
|
|
165
171
|
},
|
|
@@ -167,24 +173,24 @@ function v({ handoff: v, onExpand: _e, onClose: y, onProgress: b, progressInterv
|
|
|
167
173
|
}),
|
|
168
174
|
/* @__PURE__ */ h("button", {
|
|
169
175
|
type: "button",
|
|
170
|
-
"aria-label":
|
|
171
|
-
title:
|
|
176
|
+
"aria-label": C(z ? "player.pause" : "player.resume"),
|
|
177
|
+
title: C(z ? "player.pause" : "player.resume"),
|
|
172
178
|
onClick: () => {
|
|
173
179
|
U(), I();
|
|
174
180
|
},
|
|
175
181
|
className: _("flex size-12 cursor-pointer items-center justify-center outline-none focus-visible:ring-2 focus-visible:ring-white/80", $),
|
|
176
182
|
"data-ckui": "mini-play",
|
|
177
|
-
children:
|
|
183
|
+
children: Fe && O ? /* @__PURE__ */ h(oe, { className: "size-7" }) : /* @__PURE__ */ h(he, {
|
|
178
184
|
icon: z ? ue : de,
|
|
179
185
|
className: "size-7 fill-current",
|
|
180
186
|
strokeWidth: 1.5,
|
|
181
187
|
"aria-hidden": !0
|
|
182
188
|
})
|
|
183
189
|
}),
|
|
184
|
-
/* @__PURE__ */ h(
|
|
185
|
-
label:
|
|
190
|
+
/* @__PURE__ */ h(s, {
|
|
191
|
+
label: C("player.seekForward", { seconds: 10 }),
|
|
186
192
|
icon: le,
|
|
187
|
-
disabled: !
|
|
193
|
+
disabled: !O,
|
|
188
194
|
onClick: () => {
|
|
189
195
|
G(H() + 10), I();
|
|
190
196
|
},
|
|
@@ -197,8 +203,8 @@ function v({ handoff: v, onExpand: _e, onClose: y, onProgress: b, progressInterv
|
|
|
197
203
|
children: [/* @__PURE__ */ h("span", {
|
|
198
204
|
className: "text-xs font-medium tabular-nums",
|
|
199
205
|
children: W > 0 ? `${c(M.time || v.time)} / ${c(W)}` : c(M.time || v.time)
|
|
200
|
-
}), /* @__PURE__ */ h(
|
|
201
|
-
label: M.muted ?
|
|
206
|
+
}), /* @__PURE__ */ h(s, {
|
|
207
|
+
label: M.muted ? C("player.unmute") : C("player.mute"),
|
|
202
208
|
icon: M.muted ? me : pe,
|
|
203
209
|
onClick: K,
|
|
204
210
|
className: _($, "size-8")
|
|
@@ -208,23 +214,23 @@ function v({ handoff: v, onExpand: _e, onClose: y, onProgress: b, progressInterv
|
|
|
208
214
|
}),
|
|
209
215
|
/* @__PURE__ */ h("div", {
|
|
210
216
|
className: "absolute inset-x-0 bottom-0 z-10",
|
|
211
|
-
children: /* @__PURE__ */ h(
|
|
217
|
+
children: /* @__PURE__ */ h(ae, {
|
|
212
218
|
thin: !0,
|
|
213
219
|
time: M.time || v.time,
|
|
214
220
|
duration: W,
|
|
215
221
|
buffered: M.buffered,
|
|
216
222
|
onSeek: G,
|
|
217
|
-
onScrub: (e) =>
|
|
223
|
+
onScrub: (e) => ke(e !== null)
|
|
218
224
|
})
|
|
219
225
|
}),
|
|
220
|
-
|
|
226
|
+
D && /* @__PURE__ */ g("div", {
|
|
221
227
|
role: "alert",
|
|
222
228
|
className: "absolute inset-0 z-20 flex flex-col items-center justify-center gap-2 bg-black/80 p-3 text-center text-xs",
|
|
223
|
-
children: [/* @__PURE__ */ h("p", { children:
|
|
229
|
+
children: [/* @__PURE__ */ h("p", { children: C(`player.errors.${D.kind}`) }), /* @__PURE__ */ h("button", {
|
|
224
230
|
type: "button",
|
|
225
|
-
onClick:
|
|
231
|
+
onClick: T.retry,
|
|
226
232
|
className: "rounded-md bg-white/15 px-2 py-1 font-medium hover:bg-white/25",
|
|
227
|
-
children:
|
|
233
|
+
children: C("player.retry")
|
|
228
234
|
})]
|
|
229
235
|
})
|
|
230
236
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"video-mini-player.js","names":[],"sources":["../../src/components/video-mini-player.tsx"],"sourcesContent":["import { Cancel01Icon, GoBackward10SecIcon, GoForward10SecIcon, SquareArrowExpand01Icon, PauseIcon, PlayIcon, VolumeHighIcon, VolumeOffIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useCallback, useEffect, useRef, useState, type CSSProperties, type MouseEvent } from \"react\";\nimport type { ContentKitUiAppearance } from \"../appearance.js\";\nimport { JUMP_SEEK, PLAYER_VOLUME_KEY, playerKeyAction, writeVolume, type PlayerAction } from \"../client/player.js\";\nimport { publicRenditions } from \"../client/public.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport { useHlsPlayer, type HlsPlayerOptions } from \"../react/gallery.js\";\nimport { useActiveCues, useMediaState, useProgressReports, type PlaybackProgress } from \"../react/player.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\nimport { Captions, ControlButton, SeekBar, Spinner, clock } from \"./player-controls.js\";\nimport { RenditionImg } from \"./rendition-img.js\";\nimport { SpriteFrame, keyAllowed, type PlayerHandoff } from \"./video-player.js\";\n\nconst CONTROLS_IDLE_MS = 2500;\n\nexport interface VideoMiniPlayerProps extends Omit<HlsPlayerOptions, \"src\" | \"startAt\" | \"autoPlay\" | \"audioLanguage\" | \"subtitleLanguage\" | \"active\"> {\n /** What VideoPlayer's onMiniPlayer handed over. */\n handoff: PlayerHandoff;\n /** Back to the full player, where this one is. */\n onExpand: (state: { time: number; playing: boolean }) => void;\n onClose: (state: { time: number }) => void;\n onProgress?: (progress: PlaybackProgress) => void;\n /** Milliseconds. Default 10000. */\n progressInterval?: number;\n /** K, J, L and M page-wide (default), every shortcut while focus is in it, or none. */\n keyboard?: \"global\" | \"focus\" | false;\n /** The video's title. */\n label?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n crossOrigin?: \"anonymous\" | \"use-credentials\";\n className?: string;\n style?: CSSProperties;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * The video docked in a corner while the viewer browses: play, ±10 s, mute,\n * a seek line, expand back to the full player and close. It starts where\n * the handoff stopped, playing if it was.\n */\nexport function VideoMiniPlayer({\n handoff,\n onExpand,\n onClose,\n onProgress,\n progressInterval = 10_000,\n keyboard = \"global\",\n label,\n position = \"bottom-right\",\n crossOrigin,\n className,\n style,\n appearance,\n ...options\n}: VideoMiniPlayerProps) {\n const { t } = useMessages();\n const src = `${handoff.base}master.m3u8`;\n const player = useHlsPlayer({\n ...options,\n src,\n startAt: handoff.time,\n autoPlay: handoff.playing,\n audioLanguage: handoff.audioLanguage,\n subtitleLanguage: handoff.subtitleLanguage,\n // The handoff carries the viewer's choices; a few hundred pixels need no manual rung.\n trackKey: null,\n qualityKey: null,\n });\n const { status, error, started } = player;\n const [video, setVideo] = useState<HTMLVideoElement | null>(null);\n const attach = player.ref;\n const videoRef = useCallback(\n (el: HTMLVideoElement | null) => {\n attach(el);\n setVideo(el);\n },\n [attach],\n );\n const media = useMediaState(video);\n const cues = useActiveCues(video);\n useProgressReports(video, { enabled: started, source: started ? src : null, interval: progressInterval, onProgress });\n\n const [poked, setPoked] = useState(true);\n const idle = useRef<ReturnType<typeof setTimeout>>(undefined);\n const poke = useCallback(() => {\n setPoked(true);\n clearTimeout(idle.current);\n idle.current = setTimeout(() => setPoked(false), CONTROLS_IDLE_MS);\n }, []);\n const hide = useCallback(() => {\n clearTimeout(idle.current);\n setPoked(false);\n }, []);\n useEffect(() => () => clearTimeout(idle.current), []);\n const [scrubbing, setScrubbing] = useState(false);\n const playing = !media.paused && !media.ended;\n const shown = poked || !playing || scrubbing || !!error;\n\n const done = useRef(false);\n const time = () => video?.currentTime || media.time || handoff.time;\n const expand = () => {\n if (done.current) return;\n done.current = true;\n onExpand({ time: time(), playing });\n };\n const close = () => {\n if (done.current) return;\n done.current = true;\n video?.pause();\n onClose({ time: time() });\n };\n const toggle = () => {\n if (!video) return;\n if (!started || video.paused || video.ended) player.play();\n else video.pause();\n };\n const dur = media.duration || handoff.duration || 0;\n const seek = (to: number) => {\n if (video) video.currentTime = Math.min(dur || to, Math.max(0, to));\n };\n const volumeKey = options.volumeKey === undefined ? PLAYER_VOLUME_KEY : options.volumeKey;\n const toggleMute = () => {\n if (!video) return;\n video.muted = !video.muted;\n if (!video.muted && video.volume === 0) video.volume = 1;\n writeVolume(volumeKey, { volume: video.volume, muted: video.muted });\n };\n\n const run = (a: PlayerAction, key: string): boolean => {\n if (!video) return false;\n // Page-wide, only K, J, L and M: Space and the arrows scroll the page.\n if (keyboard === \"global\" && !\"kjlmKJLM\".includes(key)) return false;\n switch (a.type) {\n case \"toggle\":\n toggle();\n break;\n case \"seekBy\":\n if (!started) return false;\n seek(video.currentTime + a.seconds);\n break;\n case \"mute\":\n toggleMute();\n break;\n default:\n return false;\n }\n poke();\n return true;\n };\n const runRef = useRef(run);\n runRef.current = run;\n const [root, setRoot] = useState<HTMLDivElement | null>(null);\n useEffect(() => {\n if (!keyboard || !root) return;\n const on: EventTarget = keyboard === \"global\" ? document : root;\n const down = (e: Event) => {\n const k = e as KeyboardEvent;\n if (k.defaultPrevented) return;\n const action = playerKeyAction(k);\n if (!action || !keyAllowed(k.target, k.key, root) || !runRef.current(action, k.key)) return;\n k.preventDefault();\n };\n on.addEventListener(\"keydown\", down);\n return () => on.removeEventListener(\"keydown\", down);\n }, [keyboard, root]);\n\n // Touch has no hover: a tap shows or hides the controls. A click plays and pauses.\n const pointerType = useRef(\"mouse\");\n const onSurfaceClick = (e: MouseEvent) => {\n e.preventDefault();\n if (pointerType.current === \"mouse\") {\n toggle();\n poke();\n } else if (shown && playing) hide();\n else poke();\n };\n\n const aspect = handoff.width && handoff.height ? handoff.width / handoff.height : (media.aspect ?? 16 / 9);\n const posterOutputs = typeof handoff.poster === \"string\" ? [] : publicRenditions(handoff.poster);\n const busy = !error && (status === \"loading\" || status === \"buffering\");\n const overlay = \"rounded-full text-white hover:bg-white/15\";\n return (\n <ContentKitUiRoot\n ref={setRoot}\n appearance={appearance}\n role=\"region\"\n aria-label={label ? `${t(\"player.miniPlayer\")}: ${label}` : t(\"player.miniPlayer\")}\n data-ckui=\"mini-player\"\n data-status={status}\n className={cn(\n \"@container fixed bottom-4 z-50 touch-manipulation overflow-hidden rounded-md bg-black text-white shadow-lg select-none\",\n position === \"bottom-left\" ? \"left-4\" : \"right-4\",\n className,\n )}\n style={{ aspectRatio: String(aspect), width: `min(24rem, calc(100vw - 2rem), calc(60svh * ${aspect}))`, ...style }}\n onPointerDown={(e) => (pointerType.current = e.pointerType || \"mouse\")}\n onPointerMove={(e) => e.pointerType === \"mouse\" && poke()}\n onPointerLeave={(e) => e.pointerType === \"mouse\" && !scrubbing && playing && hide()}\n >\n <video ref={videoRef} className=\"absolute inset-0 size-full object-contain\" playsInline preload=\"none\" crossOrigin={crossOrigin} aria-label={label} />\n {!started &&\n (typeof handoff.poster === \"string\" ? (\n <img alt=\"\" src={handoff.poster} className=\"pointer-events-none absolute inset-0 size-full object-contain\" />\n ) : posterOutputs.length ? (\n <RenditionImg outputs={posterOutputs} className=\"pointer-events-none absolute inset-0 size-full object-contain\" />\n ) : (\n <SpriteFrame vtt={`${handoff.base}sprite.vtt`} loader={options.loader} />\n ))}\n <div aria-hidden data-ckui=\"surface\" className=\"absolute inset-0\" onClick={onSurfaceClick} />\n <Captions cues={started ? cues : []} bottom={shown ? \"2.75rem\" : \"0.75rem\"} />\n <div\n data-ckui=\"controls\"\n className={cn(\n \"pointer-events-none absolute inset-0 bg-black/45 transition-opacity duration-200 focus-within:opacity-100 motion-reduce:transition-none\",\n shown ? \"opacity-100 [&_button]:pointer-events-auto\" : \"opacity-0\",\n )}\n >\n <div className=\"absolute inset-x-0 top-0 flex items-center justify-between p-1.5\">\n <ControlButton label={t(\"player.expand\")} icon={SquareArrowExpand01Icon} onClick={expand} className={overlay} data-ckui=\"mini-expand\" />\n <ControlButton label={t(\"player.close\")} icon={Cancel01Icon} onClick={close} className={overlay} data-ckui=\"mini-close\" />\n </div>\n <div className=\"absolute inset-0 m-auto flex h-fit w-fit items-center gap-3 @sm:gap-5\">\n <ControlButton\n label={t(\"player.seekBack\", { seconds: JUMP_SEEK })}\n icon={GoBackward10SecIcon}\n disabled={!started}\n onClick={() => {\n seek(time() - JUMP_SEEK);\n poke();\n }}\n className={cn(overlay, \"[&_svg]:size-6\")}\n />\n <button\n type=\"button\"\n aria-label={playing ? t(\"player.pause\") : t(\"player.resume\")}\n title={playing ? t(\"player.pause\") : t(\"player.resume\")}\n onClick={() => {\n toggle();\n poke();\n }}\n className={cn(\"flex size-12 cursor-pointer items-center justify-center outline-none focus-visible:ring-2 focus-visible:ring-white/80\", overlay)}\n data-ckui=\"mini-play\"\n >\n {busy && started ? <Spinner className=\"size-7\" /> : <HugeiconsIcon icon={playing ? PauseIcon : PlayIcon} className=\"size-7 fill-current\" strokeWidth={1.5} aria-hidden />}\n </button>\n <ControlButton\n label={t(\"player.seekForward\", { seconds: JUMP_SEEK })}\n icon={GoForward10SecIcon}\n disabled={!started}\n onClick={() => {\n seek(time() + JUMP_SEEK);\n poke();\n }}\n className={cn(overlay, \"[&_svg]:size-6\")}\n />\n </div>\n <div className=\"absolute inset-x-0 bottom-3 flex items-center justify-between px-2.5\">\n <span className=\"text-xs font-medium tabular-nums\">{dur > 0 ? `${clock(media.time || handoff.time)} / ${clock(dur)}` : clock(media.time || handoff.time)}</span>\n <ControlButton label={media.muted ? t(\"player.unmute\") : t(\"player.mute\")} icon={media.muted ? VolumeOffIcon : VolumeHighIcon} onClick={toggleMute} className={cn(overlay, \"size-8\")} />\n </div>\n </div>\n <div className=\"absolute inset-x-0 bottom-0 z-10\">\n <SeekBar thin time={media.time || handoff.time} duration={dur} buffered={media.buffered} onSeek={seek} onScrub={(v) => setScrubbing(v !== null)} />\n </div>\n {error && (\n <div role=\"alert\" className=\"absolute inset-0 z-20 flex flex-col items-center justify-center gap-2 bg-black/80 p-3 text-center text-xs\">\n <p>{t(`player.errors.${error.kind}`)}</p>\n <button type=\"button\" onClick={player.retry} className=\"rounded-md bg-white/15 px-2 py-1 font-medium hover:bg-white/25\">\n {t(\"player.retry\")}\n </button>\n </div>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAeA,IAAM,KAAmB;AA2BzB,SAAgB,EAAgB,EAC9B,YACA,cACA,YACA,eACA,uBAAmB,KACnB,cAAW,UACX,UACA,eAAW,gBACX,iBACA,eACA,WACA,gBACA,GAAG,KACoB;CACvB,IAAM,EAAE,SAAM,EAAY,GACpB,IAAM,GAAG,EAAQ,KAAK,cACtB,IAAS,GAAa;EAC1B,GAAG;EACH;EACA,SAAS,EAAQ;EACjB,UAAU,EAAQ;EAClB,eAAe,EAAQ;EACvB,kBAAkB,EAAQ;EAE1B,UAAU;EACV,YAAY;CACd,CAAC,GACK,EAAE,WAAQ,UAAO,eAAY,GAC7B,CAAC,GAAO,MAAY,EAAkC,IAAI,GAC1D,IAAS,EAAO,KAChB,KAAW,GACd,MAAgC;EAE/B,AADA,EAAO,CAAE,GACT,GAAS,CAAE;CACb,GACA,CAAC,CAAM,CACT,GACM,IAAQ,GAAc,CAAK,GAC3B,IAAO,GAAc,CAAK;CAChC,GAAmB,GAAO;EAAE,SAAS;EAAS,QAAQ,IAAU,IAAM;EAAM,UAAU;EAAkB;CAAW,CAAC;CAEpH,IAAM,CAAC,IAAO,KAAY,EAAS,EAAI,GACjC,IAAO,EAAsC,KAAA,CAAS,GACtD,IAAO,QAAkB;EAG7B,AAFA,EAAS,EAAI,GACb,aAAa,EAAK,OAAO,GACzB,EAAK,UAAU,iBAAiB,EAAS,EAAK,GAAG,EAAgB;CACnE,GAAG,CAAC,CAAC,GACC,IAAO,QAAkB;EAE7B,AADA,aAAa,EAAK,OAAO,GACzB,EAAS,EAAK;CAChB,GAAG,CAAC,CAAC;CACL,cAAsB,aAAa,EAAK,OAAO,GAAG,CAAC,CAAC;CACpD,IAAM,CAAC,GAAW,MAAgB,EAAS,EAAK,GAC1C,IAAU,CAAC,EAAM,UAAU,CAAC,EAAM,OAClC,IAAQ,MAAS,CAAC,KAAW,KAAa,CAAC,CAAC,GAE5C,IAAO,EAAO,EAAK,GACnB,UAAa,GAAO,eAAe,EAAM,QAAQ,EAAQ,MACzD,WAAe;EACf,EAAK,YACT,EAAK,UAAU,IACf,GAAS;GAAE,MAAM,EAAK;GAAG;EAAQ,CAAC;CACpC,GACM,WAAc;EACd,EAAK,YACT,EAAK,UAAU,IACf,GAAO,MAAM,GACb,EAAQ,EAAE,MAAM,EAAK,EAAE,CAAC;CAC1B,GACM,UAAe;EACd,MACD,CAAC,KAAW,EAAM,UAAU,EAAM,QAAO,EAAO,KAAK,IACpD,EAAM,MAAM;CACnB,GACM,IAAM,EAAM,YAAY,EAAQ,YAAY,GAC5C,KAAQ,MAAe;EAC3B,AAAI,MAAO,EAAM,cAAc,KAAK,IAAI,KAAO,GAAI,KAAK,IAAI,GAAG,CAAE,CAAC;CACpE,GACM,KAAY,EAAQ,cAAc,KAAA,IAAY,IAAoB,EAAQ,WAC1E,UAAmB;EAClB,MACL,EAAM,QAAQ,CAAC,EAAM,OACjB,CAAC,EAAM,SAAS,EAAM,WAAW,MAAG,EAAM,SAAS,IACvD,EAAY,IAAW;GAAE,QAAQ,EAAM;GAAQ,OAAO,EAAM;EAAM,CAAC;CACrE,GAEM,KAAO,GAAiB,MAAyB;EAGrD,IAFI,CAAC,KAED,MAAa,YAAY,CAAC,WAAW,SAAS,CAAG,GAAG,OAAO;EAC/D,QAAQ,EAAE,MAAV;GACE,KAAK;IACH,EAAO;IACP;GACF,KAAK;IACH,IAAI,CAAC,GAAS,OAAO;IACrB,EAAK,EAAM,cAAc,EAAE,OAAO;IAClC;GACF,KAAK;IACH,EAAW;IACX;GACF,SACE,OAAO;EACX;EAEA,OADA,EAAK,GACE;CACT,GACM,IAAS,EAAO,CAAG;CACzB,EAAO,UAAU;CACjB,IAAM,CAAC,GAAM,MAAW,EAAgC,IAAI;CAC5D,QAAgB;EACd,IAAI,CAAC,KAAY,CAAC,GAAM;EACxB,IAAM,IAAkB,MAAa,WAAW,WAAW,GACrD,KAAQ,MAAa;GACzB,IAAM,IAAI;GACV,IAAI,EAAE,kBAAkB;GACxB,IAAM,IAAS,EAAgB,CAAC;GAC5B,AAAC,KAAW,EAAW,EAAE,QAAQ,EAAE,KAAK,CAAI,KAAM,EAAO,QAAQ,GAAQ,EAAE,GAAG,KAClF,EAAE,eAAe;EACnB;EAEA,OADA,EAAG,iBAAiB,WAAW,CAAI,SACtB,EAAG,oBAAoB,WAAW,CAAI;CACrD,GAAG,CAAC,GAAU,CAAI,CAAC;CAGnB,IAAM,IAAc,EAAO,OAAO,GAC5B,MAAkB,MAAkB;EAExC,AADA,EAAE,eAAe,GACb,EAAY,YAAY,WAC1B,EAAO,GACP,EAAK,KACI,KAAS,IAAS,EAAK,IAC7B,EAAK;CACZ,GAEM,IAAS,EAAQ,SAAS,EAAQ,SAAS,EAAQ,QAAQ,EAAQ,SAAU,EAAM,UAAU,KAAK,GAClG,IAAgB,OAAO,EAAQ,UAAW,WAAW,CAAC,IAAI,EAAiB,EAAQ,MAAM,GACzF,KAAO,CAAC,MAAU,MAAW,aAAa,MAAW,cACrD,IAAU;CAChB,OACE,kBAAC,IAAD;EACE,KAAK;EACO;EACZ,MAAK;EACL,cAAY,IAAQ,GAAG,EAAE,mBAAmB,EAAE,IAAI,MAAU,EAAE,mBAAmB;EACjF,aAAU;EACV,eAAa;EACb,WAAW,EACT,0HACA,OAAa,gBAAgB,WAAW,WACxC,EACF;EACA,OAAO;GAAE,aAAa,OAAO,CAAM;GAAG,OAAO,+CAA+C,EAAO;GAAK,GAAG;EAAM;EACjH,gBAAgB,MAAO,EAAY,UAAU,EAAE,eAAe;EAC9D,gBAAgB,MAAM,EAAE,gBAAgB,WAAW,EAAK;EACxD,iBAAiB,MAAM,EAAE,gBAAgB,WAAW,CAAC,KAAa,KAAW,EAAK;EAfpF,UAAA;GAiBE,kBAAC,SAAD;IAAO,KAAK;IAAU,WAAU;IAA4C,aAAA;IAAY,SAAQ;IAAoB;IAAa,cAAY;GAAQ,CAAA;GACpJ,CAAC,MACC,OAAO,EAAQ,UAAW,WACzB,kBAAC,OAAD;IAAK,KAAI;IAAG,KAAK,EAAQ;IAAQ,WAAU;GAAiE,CAAA,IAC1G,EAAc,SAChB,kBAAC,GAAD;IAAc,SAAS;IAAe,WAAU;GAAiE,CAAA,IAEjH,kBAAC,GAAD;IAAa,KAAK,GAAG,EAAQ,KAAK;IAAa,QAAQ,EAAQ;GAAS,CAAA;GAE5E,kBAAC,OAAD;IAAK,eAAA;IAAY,aAAU;IAAU,WAAU;IAAmB,SAAS;GAAiB,CAAA;GAC5F,kBAAC,IAAD;IAAU,MAAM,IAAU,IAAO,CAAC;IAAG,QAAQ,IAAQ,YAAY;GAAY,CAAA;GAC7E,kBAAC,OAAD;IACE,aAAU;IACV,WAAW,EACT,2IACA,IAAQ,+CAA+C,WACzD;IALF,UAAA;KAOE,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,GAAD;OAAe,OAAO,EAAE,eAAe;OAAG,MAAM;OAAyB,SAAS;OAAQ,WAAW;OAAS,aAAU;MAAe,CAAA,GACvI,kBAAC,GAAD;OAAe,OAAO,EAAE,cAAc;OAAG,MAAM;OAAc,SAAS;OAAO,WAAW;OAAS,aAAU;MAAc,CAAA,CACtH;;KACL,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA;OACE,kBAAC,GAAD;QACE,OAAO,EAAE,mBAAmB,EAAE,SAAA,GAAmB,CAAC;QAClD,MAAM;QACN,UAAU,CAAC;QACX,eAAe;SAEb,AADA,EAAK,EAAK,IAAA,EAAa,GACvB,EAAK;QACP;QACA,WAAW,EAAG,GAAS,gBAAgB;OACxC,CAAA;OACD,kBAAC,UAAD;QACE,MAAK;QACL,cAAsB,EAAV,IAAY,iBAAoB,eAAe;QAC3D,OAAiB,EAAV,IAAY,iBAAoB,eAAe;QACtD,eAAe;SAEb,AADA,EAAO,GACP,EAAK;QACP;QACA,WAAW,EAAG,yHAAyH,CAAO;QAC9I,aAAU;QAET,UAAA,MAAQ,IAAU,kBAAC,GAAD,EAAS,WAAU,SAAU,CAAA,IAAI,kBAAC,IAAD;SAAe,MAAM,IAAU,KAAY;SAAU,WAAU;SAAsB,aAAa;SAAK,eAAA;QAAa,CAAA;OAClK,CAAA;OACR,kBAAC,GAAD;QACE,OAAO,EAAE,sBAAsB,EAAE,SAAA,GAAmB,CAAC;QACrD,MAAM;QACN,UAAU,CAAC;QACX,eAAe;SAEb,AADA,EAAK,EAAK,IAAA,EAAa,GACvB,EAAK;QACP;QACA,WAAW,EAAG,GAAS,gBAAgB;OACxC,CAAA;MACE;;KACL,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,QAAD;OAAM,WAAU;OAAoC,UAAA,IAAM,IAAI,GAAG,EAAM,EAAM,QAAQ,EAAQ,IAAI,EAAE,KAAK,EAAM,CAAG,MAAM,EAAM,EAAM,QAAQ,EAAQ,IAAI;MAAQ,CAAA,GAC/J,kBAAC,GAAD;OAAe,OAAO,EAAM,QAAQ,EAAE,eAAe,IAAI,EAAE,aAAa;OAAG,MAAM,EAAM,QAAQ,KAAgB;OAAgB,SAAS;OAAY,WAAW,EAAG,GAAS,QAAQ;MAAI,CAAA,CACpL;;IACF;;GACL,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAAC,IAAD;KAAS,MAAA;KAAK,MAAM,EAAM,QAAQ,EAAQ;KAAM,UAAU;KAAK,UAAU,EAAM;KAAU,QAAQ;KAAM,UAAU,MAAM,GAAa,MAAM,IAAI;IAAI,CAAA;GAC/I,CAAA;GACJ,KACC,kBAAC,OAAD;IAAK,MAAK;IAAQ,WAAU;IAA5B,UAAA,CACE,kBAAC,KAAD,EAAA,UAAI,EAAE,iBAAiB,EAAM,MAAM,EAAK,CAAA,GACxC,kBAAC,UAAD;KAAQ,MAAK;KAAS,SAAS,EAAO;KAAO,WAAU;KACpD,UAAA,EAAE,cAAc;IACX,CAAA,CACL;;EAES;;AAEtB"}
|
|
1
|
+
{"version":3,"file":"video-mini-player.js","names":[],"sources":["../../src/components/video-mini-player.tsx"],"sourcesContent":["import { Cancel01Icon, GoBackward10SecIcon, GoForward10SecIcon, SquareArrowExpand01Icon, PauseIcon, PlayIcon, VolumeHighIcon, VolumeOffIcon } from \"@hugeicons/core-free-icons\";\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport { cn } from \"cn\";\nimport { useCallback, useEffect, useRef, useState, type CSSProperties, type MouseEvent } from \"react\";\nimport type { ContentKitUiAppearance } from \"../appearance.js\";\nimport { JUMP_SEEK, PLAYER_VOLUME_KEY, playerKeyAction, writeVolume, type PlayerAction } from \"../client/player.js\";\nimport { publicRenditions } from \"../client/public.js\";\nimport { useMessages } from \"../i18n/context.js\";\nimport { useHlsPlayer, type HlsPlayerOptions } from \"../react/gallery.js\";\nimport type { ReadingEngagement } from \"../react/use-engagement.js\";\nimport { useActiveCues, useMediaState, useProgressReports, type PlaybackProgress } from \"../react/player.js\";\nimport { ContentKitUiRoot } from \"../scope.js\";\nimport { Captions, ControlButton, SeekBar, Spinner, clock } from \"./player-controls.js\";\nimport { RenditionImg } from \"./rendition-img.js\";\nimport { SpriteFrame, keyAllowed, type PlayerHandoff } from \"./video-player.js\";\n\nconst CONTROLS_IDLE_MS = 2500;\n\nexport interface VideoMiniPlayerProps extends Omit<HlsPlayerOptions, \"src\" | \"startAt\" | \"autoPlay\" | \"audioLanguage\" | \"subtitleLanguage\" | \"active\"> {\n /** What VideoPlayer's onMiniPlayer handed over. */\n handoff: PlayerHandoff;\n /** Back to the full player, where this one is. */\n onExpand: (state: { time: number; playing: boolean }) => void;\n onClose: (state: { time: number }) => void;\n onProgress?: (progress: PlaybackProgress) => void;\n /** Continue actual visible playback measurements after the full player handoff. */\n engagement?: Pick<ReadingEngagement, \"video\">;\n /** Milliseconds. Default 10000. */\n progressInterval?: number;\n /** K, J, L and M page-wide (default), every shortcut while focus is in it, or none. */\n keyboard?: \"global\" | \"focus\" | false;\n /** The video's title. */\n label?: string;\n position?: \"bottom-right\" | \"bottom-left\";\n crossOrigin?: \"anonymous\" | \"use-credentials\";\n className?: string;\n style?: CSSProperties;\n appearance?: ContentKitUiAppearance;\n}\n\n/**\n * The video docked in a corner while the viewer browses: play, ±10 s, mute,\n * a seek line, expand back to the full player and close. It starts where\n * the handoff stopped, playing if it was.\n */\nexport function VideoMiniPlayer({\n handoff,\n onExpand,\n onClose,\n onProgress,\n engagement,\n progressInterval = 10_000,\n keyboard = \"global\",\n label,\n position = \"bottom-right\",\n crossOrigin,\n className,\n style,\n appearance,\n ...options\n}: VideoMiniPlayerProps) {\n const { t } = useMessages();\n const src = `${handoff.base}master.m3u8`;\n const player = useHlsPlayer({\n ...options,\n src,\n startAt: handoff.time,\n autoPlay: handoff.playing,\n audioLanguage: handoff.audioLanguage,\n subtitleLanguage: handoff.subtitleLanguage,\n // The handoff carries the viewer's choices; a few hundred pixels need no manual rung.\n trackKey: null,\n qualityKey: null,\n });\n const { status, error, started } = player;\n const [video, setVideo] = useState<HTMLVideoElement | null>(null);\n const attach = player.ref;\n const videoRef = useCallback(\n (el: HTMLVideoElement | null) => {\n attach(el);\n setVideo(el);\n },\n [attach],\n );\n const bindEngagement = engagement?.video;\n useEffect(() => {\n bindEngagement?.(started ? video : null);\n return () => bindEngagement?.(null);\n }, [bindEngagement, started, video]);\n const media = useMediaState(video);\n const cues = useActiveCues(video);\n useProgressReports(video, { enabled: started, source: started ? src : null, interval: progressInterval, onProgress });\n\n const [poked, setPoked] = useState(true);\n const idle = useRef<ReturnType<typeof setTimeout>>(undefined);\n const poke = useCallback(() => {\n setPoked(true);\n clearTimeout(idle.current);\n idle.current = setTimeout(() => setPoked(false), CONTROLS_IDLE_MS);\n }, []);\n const hide = useCallback(() => {\n clearTimeout(idle.current);\n setPoked(false);\n }, []);\n useEffect(() => () => clearTimeout(idle.current), []);\n const [scrubbing, setScrubbing] = useState(false);\n const playing = !media.paused && !media.ended;\n const shown = poked || !playing || scrubbing || !!error;\n\n const done = useRef(false);\n const time = () => video?.currentTime || media.time || handoff.time;\n const expand = () => {\n if (done.current) return;\n done.current = true;\n onExpand({ time: time(), playing });\n };\n const close = () => {\n if (done.current) return;\n done.current = true;\n video?.pause();\n onClose({ time: time() });\n };\n const toggle = () => {\n if (!video) return;\n if (!started || video.paused || video.ended) player.play();\n else video.pause();\n };\n const dur = media.duration || handoff.duration || 0;\n const seek = (to: number) => {\n if (video) video.currentTime = Math.min(dur || to, Math.max(0, to));\n };\n const volumeKey = options.volumeKey === undefined ? PLAYER_VOLUME_KEY : options.volumeKey;\n const toggleMute = () => {\n if (!video) return;\n video.muted = !video.muted;\n if (!video.muted && video.volume === 0) video.volume = 1;\n writeVolume(volumeKey, { volume: video.volume, muted: video.muted });\n };\n\n const run = (a: PlayerAction, key: string): boolean => {\n if (!video) return false;\n // Page-wide, only K, J, L and M: Space and the arrows scroll the page.\n if (keyboard === \"global\" && !\"kjlmKJLM\".includes(key)) return false;\n switch (a.type) {\n case \"toggle\":\n toggle();\n break;\n case \"seekBy\":\n if (!started) return false;\n seek(video.currentTime + a.seconds);\n break;\n case \"mute\":\n toggleMute();\n break;\n default:\n return false;\n }\n poke();\n return true;\n };\n const runRef = useRef(run);\n runRef.current = run;\n const [root, setRoot] = useState<HTMLDivElement | null>(null);\n useEffect(() => {\n if (!keyboard || !root) return;\n const on: EventTarget = keyboard === \"global\" ? document : root;\n const down = (e: Event) => {\n const k = e as KeyboardEvent;\n if (k.defaultPrevented) return;\n const action = playerKeyAction(k);\n if (!action || !keyAllowed(k.target, k.key, root) || !runRef.current(action, k.key)) return;\n k.preventDefault();\n };\n on.addEventListener(\"keydown\", down);\n return () => on.removeEventListener(\"keydown\", down);\n }, [keyboard, root]);\n\n // Touch has no hover: a tap shows or hides the controls. A click plays and pauses.\n const pointerType = useRef(\"mouse\");\n const onSurfaceClick = (e: MouseEvent) => {\n e.preventDefault();\n if (pointerType.current === \"mouse\") {\n toggle();\n poke();\n } else if (shown && playing) hide();\n else poke();\n };\n\n const aspect = handoff.width && handoff.height ? handoff.width / handoff.height : (media.aspect ?? 16 / 9);\n const posterOutputs = typeof handoff.poster === \"string\" ? [] : publicRenditions(handoff.poster);\n const busy = !error && (status === \"loading\" || status === \"buffering\");\n const overlay = \"rounded-full text-white hover:bg-white/15\";\n return (\n <ContentKitUiRoot\n ref={setRoot}\n appearance={appearance}\n role=\"region\"\n aria-label={label ? `${t(\"player.miniPlayer\")}: ${label}` : t(\"player.miniPlayer\")}\n data-ckui=\"mini-player\"\n data-status={status}\n className={cn(\n \"@container fixed bottom-4 z-50 touch-manipulation overflow-hidden rounded-md bg-black text-white shadow-lg select-none\",\n position === \"bottom-left\" ? \"left-4\" : \"right-4\",\n className,\n )}\n style={{ aspectRatio: String(aspect), width: `min(24rem, calc(100vw - 2rem), calc(60svh * ${aspect}))`, ...style }}\n onPointerDown={(e) => (pointerType.current = e.pointerType || \"mouse\")}\n onPointerMove={(e) => e.pointerType === \"mouse\" && poke()}\n onPointerLeave={(e) => e.pointerType === \"mouse\" && !scrubbing && playing && hide()}\n >\n <video ref={videoRef} className=\"absolute inset-0 size-full object-contain\" playsInline preload=\"none\" crossOrigin={crossOrigin} aria-label={label} />\n {!started &&\n (typeof handoff.poster === \"string\" ? (\n <img alt=\"\" src={handoff.poster} className=\"pointer-events-none absolute inset-0 size-full object-contain\" />\n ) : posterOutputs.length ? (\n <RenditionImg outputs={posterOutputs} className=\"pointer-events-none absolute inset-0 size-full object-contain\" />\n ) : (\n <SpriteFrame vtt={`${handoff.base}sprite.vtt`} loader={options.loader} />\n ))}\n <div aria-hidden data-ckui=\"surface\" className=\"absolute inset-0\" onClick={onSurfaceClick} />\n <Captions cues={started ? cues : []} bottom={shown ? \"2.75rem\" : \"0.75rem\"} />\n <div\n data-ckui=\"controls\"\n className={cn(\n \"pointer-events-none absolute inset-0 bg-black/45 transition-opacity duration-200 focus-within:opacity-100 motion-reduce:transition-none\",\n shown ? \"opacity-100 [&_button]:pointer-events-auto\" : \"opacity-0\",\n )}\n >\n <div className=\"absolute inset-x-0 top-0 flex items-center justify-between p-1.5\">\n <ControlButton label={t(\"player.expand\")} icon={SquareArrowExpand01Icon} onClick={expand} className={overlay} data-ckui=\"mini-expand\" />\n <ControlButton label={t(\"player.close\")} icon={Cancel01Icon} onClick={close} className={overlay} data-ckui=\"mini-close\" />\n </div>\n <div className=\"absolute inset-0 m-auto flex h-fit w-fit items-center gap-3 @sm:gap-5\">\n <ControlButton\n label={t(\"player.seekBack\", { seconds: JUMP_SEEK })}\n icon={GoBackward10SecIcon}\n disabled={!started}\n onClick={() => {\n seek(time() - JUMP_SEEK);\n poke();\n }}\n className={cn(overlay, \"[&_svg]:size-6\")}\n />\n <button\n type=\"button\"\n aria-label={playing ? t(\"player.pause\") : t(\"player.resume\")}\n title={playing ? t(\"player.pause\") : t(\"player.resume\")}\n onClick={() => {\n toggle();\n poke();\n }}\n className={cn(\"flex size-12 cursor-pointer items-center justify-center outline-none focus-visible:ring-2 focus-visible:ring-white/80\", overlay)}\n data-ckui=\"mini-play\"\n >\n {busy && started ? <Spinner className=\"size-7\" /> : <HugeiconsIcon icon={playing ? PauseIcon : PlayIcon} className=\"size-7 fill-current\" strokeWidth={1.5} aria-hidden />}\n </button>\n <ControlButton\n label={t(\"player.seekForward\", { seconds: JUMP_SEEK })}\n icon={GoForward10SecIcon}\n disabled={!started}\n onClick={() => {\n seek(time() + JUMP_SEEK);\n poke();\n }}\n className={cn(overlay, \"[&_svg]:size-6\")}\n />\n </div>\n <div className=\"absolute inset-x-0 bottom-3 flex items-center justify-between px-2.5\">\n <span className=\"text-xs font-medium tabular-nums\">{dur > 0 ? `${clock(media.time || handoff.time)} / ${clock(dur)}` : clock(media.time || handoff.time)}</span>\n <ControlButton label={media.muted ? t(\"player.unmute\") : t(\"player.mute\")} icon={media.muted ? VolumeOffIcon : VolumeHighIcon} onClick={toggleMute} className={cn(overlay, \"size-8\")} />\n </div>\n </div>\n <div className=\"absolute inset-x-0 bottom-0 z-10\">\n <SeekBar thin time={media.time || handoff.time} duration={dur} buffered={media.buffered} onSeek={seek} onScrub={(v) => setScrubbing(v !== null)} />\n </div>\n {error && (\n <div role=\"alert\" className=\"absolute inset-0 z-20 flex flex-col items-center justify-center gap-2 bg-black/80 p-3 text-center text-xs\">\n <p>{t(`player.errors.${error.kind}`)}</p>\n <button type=\"button\" onClick={player.retry} className=\"rounded-md bg-white/15 px-2 py-1 font-medium hover:bg-white/25\">\n {t(\"player.retry\")}\n </button>\n </div>\n )}\n </ContentKitUiRoot>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;AAgBA,IAAM,KAAmB;AA6BzB,SAAgB,EAAgB,EAC9B,YACA,cACA,aACA,gBACA,eACA,uBAAmB,KACnB,cAAW,UACX,UACA,eAAW,gBACX,iBACA,eACA,WACA,gBACA,GAAG,KACoB;CACvB,IAAM,EAAE,SAAM,EAAY,GACpB,IAAM,GAAG,EAAQ,KAAK,cACtB,IAAS,EAAa;EAC1B,GAAG;EACH;EACA,SAAS,EAAQ;EACjB,UAAU,EAAQ;EAClB,eAAe,EAAQ;EACvB,kBAAkB,EAAQ;EAE1B,UAAU;EACV,YAAY;CACd,CAAC,GACK,EAAE,WAAQ,UAAO,eAAY,GAC7B,CAAC,GAAO,MAAY,EAAkC,IAAI,GAC1D,IAAS,EAAO,KAChB,KAAW,GACd,MAAgC;EAE/B,AADA,EAAO,CAAE,GACT,GAAS,CAAE;CACb,GACA,CAAC,CAAM,CACT,GACM,IAAiB,GAAY;CACnC,SACE,IAAiB,IAAU,IAAQ,IAAI,SAC1B,IAAiB,IAAI,IACjC;EAAC;EAAgB;EAAS;CAAK,CAAC;CACnC,IAAM,IAAQ,GAAc,CAAK,GAC3B,IAAO,GAAc,CAAK;CAChC,GAAmB,GAAO;EAAE,SAAS;EAAS,QAAQ,IAAU,IAAM;EAAM,UAAU;EAAkB;CAAW,CAAC;CAEpH,IAAM,CAAC,IAAO,KAAY,EAAS,EAAI,GACjC,IAAO,EAAsC,KAAA,CAAS,GACtD,IAAO,QAAkB;EAG7B,AAFA,EAAS,EAAI,GACb,aAAa,EAAK,OAAO,GACzB,EAAK,UAAU,iBAAiB,EAAS,EAAK,GAAG,EAAgB;CACnE,GAAG,CAAC,CAAC,GACC,IAAO,QAAkB;EAE7B,AADA,aAAa,EAAK,OAAO,GACzB,EAAS,EAAK;CAChB,GAAG,CAAC,CAAC;CACL,cAAsB,aAAa,EAAK,OAAO,GAAG,CAAC,CAAC;CACpD,IAAM,CAAC,GAAW,MAAgB,EAAS,EAAK,GAC1C,IAAU,CAAC,EAAM,UAAU,CAAC,EAAM,OAClC,IAAQ,MAAS,CAAC,KAAW,KAAa,CAAC,CAAC,GAE5C,IAAO,EAAO,EAAK,GACnB,UAAa,GAAO,eAAe,EAAM,QAAQ,EAAQ,MACzD,WAAe;EACf,EAAK,YACT,EAAK,UAAU,IACf,GAAS;GAAE,MAAM,EAAK;GAAG;EAAQ,CAAC;CACpC,GACM,WAAc;EACd,EAAK,YACT,EAAK,UAAU,IACf,GAAO,MAAM,GACb,GAAQ,EAAE,MAAM,EAAK,EAAE,CAAC;CAC1B,GACM,UAAe;EACd,MACD,CAAC,KAAW,EAAM,UAAU,EAAM,QAAO,EAAO,KAAK,IACpD,EAAM,MAAM;CACnB,GACM,IAAM,EAAM,YAAY,EAAQ,YAAY,GAC5C,KAAQ,MAAe;EAC3B,AAAI,MAAO,EAAM,cAAc,KAAK,IAAI,KAAO,GAAI,KAAK,IAAI,GAAG,CAAE,CAAC;CACpE,GACM,KAAY,EAAQ,cAAc,KAAA,IAAY,IAAoB,EAAQ,WAC1E,UAAmB;EAClB,MACL,EAAM,QAAQ,CAAC,EAAM,OACjB,CAAC,EAAM,SAAS,EAAM,WAAW,MAAG,EAAM,SAAS,IACvD,EAAY,IAAW;GAAE,QAAQ,EAAM;GAAQ,OAAO,EAAM;EAAM,CAAC;CACrE,GAEM,KAAO,GAAiB,MAAyB;EAGrD,IAFI,CAAC,KAED,MAAa,YAAY,CAAC,WAAW,SAAS,CAAG,GAAG,OAAO;EAC/D,QAAQ,EAAE,MAAV;GACE,KAAK;IACH,EAAO;IACP;GACF,KAAK;IACH,IAAI,CAAC,GAAS,OAAO;IACrB,EAAK,EAAM,cAAc,EAAE,OAAO;IAClC;GACF,KAAK;IACH,EAAW;IACX;GACF,SACE,OAAO;EACX;EAEA,OADA,EAAK,GACE;CACT,GACM,IAAS,EAAO,CAAG;CACzB,EAAO,UAAU;CACjB,IAAM,CAAC,GAAM,MAAW,EAAgC,IAAI;CAC5D,QAAgB;EACd,IAAI,CAAC,KAAY,CAAC,GAAM;EACxB,IAAM,IAAkB,MAAa,WAAW,WAAW,GACrD,KAAQ,MAAa;GACzB,IAAM,IAAI;GACV,IAAI,EAAE,kBAAkB;GACxB,IAAM,IAAS,EAAgB,CAAC;GAC5B,AAAC,KAAW,EAAW,EAAE,QAAQ,EAAE,KAAK,CAAI,KAAM,EAAO,QAAQ,GAAQ,EAAE,GAAG,KAClF,EAAE,eAAe;EACnB;EAEA,OADA,EAAG,iBAAiB,WAAW,CAAI,SACtB,EAAG,oBAAoB,WAAW,CAAI;CACrD,GAAG,CAAC,GAAU,CAAI,CAAC;CAGnB,IAAM,IAAc,EAAO,OAAO,GAC5B,MAAkB,MAAkB;EAExC,AADA,EAAE,eAAe,GACb,EAAY,YAAY,WAC1B,EAAO,GACP,EAAK,KACI,KAAS,IAAS,EAAK,IAC7B,EAAK;CACZ,GAEM,IAAS,EAAQ,SAAS,EAAQ,SAAS,EAAQ,QAAQ,EAAQ,SAAU,EAAM,UAAU,KAAK,GAClG,IAAgB,OAAO,EAAQ,UAAW,WAAW,CAAC,IAAI,EAAiB,EAAQ,MAAM,GACzF,KAAO,CAAC,MAAU,MAAW,aAAa,MAAW,cACrD,IAAU;CAChB,OACE,kBAAC,IAAD;EACE,KAAK;EACO;EACZ,MAAK;EACL,cAAY,IAAQ,GAAG,EAAE,mBAAmB,EAAE,IAAI,MAAU,EAAE,mBAAmB;EACjF,aAAU;EACV,eAAa;EACb,WAAW,EACT,0HACA,OAAa,gBAAgB,WAAW,WACxC,EACF;EACA,OAAO;GAAE,aAAa,OAAO,CAAM;GAAG,OAAO,+CAA+C,EAAO;GAAK,GAAG;EAAM;EACjH,gBAAgB,MAAO,EAAY,UAAU,EAAE,eAAe;EAC9D,gBAAgB,MAAM,EAAE,gBAAgB,WAAW,EAAK;EACxD,iBAAiB,MAAM,EAAE,gBAAgB,WAAW,CAAC,KAAa,KAAW,EAAK;EAfpF,UAAA;GAiBE,kBAAC,SAAD;IAAO,KAAK;IAAU,WAAU;IAA4C,aAAA;IAAY,SAAQ;IAAoB;IAAa,cAAY;GAAQ,CAAA;GACpJ,CAAC,MACC,OAAO,EAAQ,UAAW,WACzB,kBAAC,OAAD;IAAK,KAAI;IAAG,KAAK,EAAQ;IAAQ,WAAU;GAAiE,CAAA,IAC1G,EAAc,SAChB,kBAAC,GAAD;IAAc,SAAS;IAAe,WAAU;GAAiE,CAAA,IAEjH,kBAAC,GAAD;IAAa,KAAK,GAAG,EAAQ,KAAK;IAAa,QAAQ,EAAQ;GAAS,CAAA;GAE5E,kBAAC,OAAD;IAAK,eAAA;IAAY,aAAU;IAAU,WAAU;IAAmB,SAAS;GAAiB,CAAA;GAC5F,kBAAC,IAAD;IAAU,MAAM,IAAU,IAAO,CAAC;IAAG,QAAQ,IAAQ,YAAY;GAAY,CAAA;GAC7E,kBAAC,OAAD;IACE,aAAU;IACV,WAAW,EACT,2IACA,IAAQ,+CAA+C,WACzD;IALF,UAAA;KAOE,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,GAAD;OAAe,OAAO,EAAE,eAAe;OAAG,MAAM;OAAyB,SAAS;OAAQ,WAAW;OAAS,aAAU;MAAe,CAAA,GACvI,kBAAC,GAAD;OAAe,OAAO,EAAE,cAAc;OAAG,MAAM;OAAc,SAAS;OAAO,WAAW;OAAS,aAAU;MAAc,CAAA,CACtH;;KACL,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA;OACE,kBAAC,GAAD;QACE,OAAO,EAAE,mBAAmB,EAAE,SAAA,GAAmB,CAAC;QAClD,MAAM;QACN,UAAU,CAAC;QACX,eAAe;SAEb,AADA,EAAK,EAAK,IAAA,EAAa,GACvB,EAAK;QACP;QACA,WAAW,EAAG,GAAS,gBAAgB;OACxC,CAAA;OACD,kBAAC,UAAD;QACE,MAAK;QACL,cAAsB,EAAV,IAAY,iBAAoB,eAAe;QAC3D,OAAiB,EAAV,IAAY,iBAAoB,eAAe;QACtD,eAAe;SAEb,AADA,EAAO,GACP,EAAK;QACP;QACA,WAAW,EAAG,yHAAyH,CAAO;QAC9I,aAAU;QAET,UAAA,MAAQ,IAAU,kBAAC,IAAD,EAAS,WAAU,SAAU,CAAA,IAAI,kBAAC,IAAD;SAAe,MAAM,IAAU,KAAY;SAAU,WAAU;SAAsB,aAAa;SAAK,eAAA;QAAa,CAAA;OAClK,CAAA;OACR,kBAAC,GAAD;QACE,OAAO,EAAE,sBAAsB,EAAE,SAAA,GAAmB,CAAC;QACrD,MAAM;QACN,UAAU,CAAC;QACX,eAAe;SAEb,AADA,EAAK,EAAK,IAAA,EAAa,GACvB,EAAK;QACP;QACA,WAAW,EAAG,GAAS,gBAAgB;OACxC,CAAA;MACE;;KACL,kBAAC,OAAD;MAAK,WAAU;MAAf,UAAA,CACE,kBAAC,QAAD;OAAM,WAAU;OAAoC,UAAA,IAAM,IAAI,GAAG,EAAM,EAAM,QAAQ,EAAQ,IAAI,EAAE,KAAK,EAAM,CAAG,MAAM,EAAM,EAAM,QAAQ,EAAQ,IAAI;MAAQ,CAAA,GAC/J,kBAAC,GAAD;OAAe,OAAO,EAAM,QAAQ,EAAE,eAAe,IAAI,EAAE,aAAa;OAAG,MAAM,EAAM,QAAQ,KAAgB;OAAgB,SAAS;OAAY,WAAW,EAAG,GAAS,QAAQ;MAAI,CAAA,CACpL;;IACF;;GACL,kBAAC,OAAD;IAAK,WAAU;IACb,UAAA,kBAAC,IAAD;KAAS,MAAA;KAAK,MAAM,EAAM,QAAQ,EAAQ;KAAM,UAAU;KAAK,UAAU,EAAM;KAAU,QAAQ;KAAM,UAAU,MAAM,GAAa,MAAM,IAAI;IAAI,CAAA;GAC/I,CAAA;GACJ,KACC,kBAAC,OAAD;IAAK,MAAK;IAAQ,WAAU;IAA5B,UAAA,CACE,kBAAC,KAAD,EAAA,UAAI,EAAE,iBAAiB,EAAM,MAAM,EAAK,CAAA,GACxC,kBAAC,UAAD;KAAQ,MAAK;KAAS,SAAS,EAAO;KAAO,WAAU;KACpD,UAAA,EAAE,cAAc;IACX,CAAA,CACL;;EAES;;AAEtB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { CSSProperties, ReactNode } from 'react';
|
|
2
2
|
import { ContentKitUiAppearance } from '../appearance.js';
|
|
3
3
|
import { PlaybackError } from '../client/playback.js';
|
|
4
|
+
import { ReadingEngagement } from '../react/use-engagement.js';
|
|
4
5
|
import { PlayerTrack } from '../client/player.js';
|
|
5
6
|
import { HlsPlayerOptions } from '../react/gallery.js';
|
|
6
7
|
import { PlaybackProgress } from '../react/player.js';
|
|
@@ -107,6 +108,8 @@ export interface VideoPlayerProps extends Omit<HlsPlayerOptions, "src"> {
|
|
|
107
108
|
keyboard?: "focus" | "global" | false;
|
|
108
109
|
/** Resume points and watch time: every `progressInterval` of playback, and on pause, seek, end, page hide and unload. */
|
|
109
110
|
onProgress?: (progress: PlaybackProgress) => void;
|
|
111
|
+
/** Measure real playback only, excluding inline previews and the poster. */
|
|
112
|
+
engagement?: Pick<ReadingEngagement, "video">;
|
|
110
113
|
/** Milliseconds. Default 10000. */
|
|
111
114
|
progressInterval?: number;
|
|
112
115
|
onEvent?: (event: PlayerEvent) => void;
|
|
@@ -140,7 +143,7 @@ export declare function keyAllowed(target: EventTarget | null, key: string, root
|
|
|
140
143
|
* touch gestures, resume and progress reports, and a specific error with
|
|
141
144
|
* Retry and a support code.
|
|
142
145
|
*/
|
|
143
|
-
export declare function VideoPlayer({ base, poster, width, height, duration, pending, progress, failed, layout, maxHeight, inlinePreview, previewStart, keyboard, onProgress, progressInterval, onEvent, theater, onTheaterChange, onMiniPlayer, renderDownloads, menuItems, crossOrigin, label, className, style, appearance, startAt, ...options }: VideoPlayerProps): import('react').JSX.Element;
|
|
146
|
+
export declare function VideoPlayer({ base, poster, width, height, duration, pending, progress, failed, layout, maxHeight, inlinePreview, previewStart, keyboard, onProgress, engagement, progressInterval, onEvent, theater, onTheaterChange, onMiniPlayer, renderDownloads, menuItems, crossOrigin, label, className, style, appearance, startAt, ...options }: VideoPlayerProps): import('react').JSX.Element;
|
|
144
147
|
/** A preview's start: the given second, else 10% in, kept a second before the end. */
|
|
145
148
|
export declare function previewStartAt(start: number | undefined, duration: number | undefined): number;
|
|
146
149
|
/** "2160p 4K", "1080p HD", "720p": a rung by its short side. */
|