@liqvid/controls 1.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +9 -0
- package/README.md +3 -0
- package/dist/esm/ColorSchemeToggle.js +24 -0
- package/dist/esm/FullScreen.js +32 -0
- package/dist/esm/MuteButton.js +37 -0
- package/dist/esm/PlayPause.js +39 -0
- package/dist/esm/ScrubberBar.js +194 -0
- package/dist/esm/ThumbnailBox.js +31 -0
- package/dist/esm/TimeDisplay.js +19 -0
- package/dist/esm/VolumeSlider.js +65 -0
- package/dist/esm/fake-fullscreen.js +33 -0
- package/dist/esm/index.js +7 -0
- package/dist/esm/polyfills.js +53 -0
- package/dist/esm/utils.js +31 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/types/ColorSchemeToggle.d.ts +8 -0
- package/dist/types/FullScreen.d.ts +10 -0
- package/dist/types/MuteButton.d.ts +24 -0
- package/dist/types/PlayPause.d.ts +9 -0
- package/dist/types/ScrubberBar.d.ts +23 -0
- package/dist/types/ThumbnailBox.d.ts +42 -0
- package/dist/types/TimeDisplay.d.ts +1 -0
- package/dist/types/VolumeSlider.d.ts +25 -0
- package/dist/types/fake-fullscreen.d.ts +4 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/polyfills.d.ts +5 -0
- package/dist/types/utils.d.ts +4 -0
- package/package.json +51 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Yuri Sulyma
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useColorScheme } from "@liqvid/color-scheme/react";
|
|
3
|
+
import { useKeymap } from "@liqvid/keymap/react";
|
|
4
|
+
import { onClickReact } from "@liqvid/utils";
|
|
5
|
+
import classNames from "classnames";
|
|
6
|
+
import { useEffect, useMemo } from "react";
|
|
7
|
+
import { bind, convertShortcuts, unbind } from "./utils";
|
|
8
|
+
export function ColorSchemeToggle({ className, render, shortcuts, }) {
|
|
9
|
+
const { colorScheme, toggleColorScheme } = useColorScheme();
|
|
10
|
+
const keymap = useKeymap();
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
// keyboard shortcut
|
|
13
|
+
bind(keymap, shortcuts, toggleColorScheme);
|
|
14
|
+
return () => {
|
|
15
|
+
unbind(keymap, shortcuts, toggleColorScheme);
|
|
16
|
+
};
|
|
17
|
+
}, [keymap, shortcuts, toggleColorScheme]);
|
|
18
|
+
const events = useMemo(() => onClickReact(toggleColorScheme), [toggleColorScheme]);
|
|
19
|
+
return render({ colorScheme }, {
|
|
20
|
+
"aria-keyshortcuts": convertShortcuts(shortcuts),
|
|
21
|
+
className: classNames("lv-controls-color-scheme lv-controls-button", className),
|
|
22
|
+
...events,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKeymap } from "@liqvid/keymap/react";
|
|
3
|
+
import { onClickReact, useForceUpdate } from "@liqvid/utils";
|
|
4
|
+
import classNames from "classnames";
|
|
5
|
+
import { useEffect } from "react";
|
|
6
|
+
import { exitFullScreen, isFullScreen, onFullScreenChange, requestFullScreen, } from "./fake-fullscreen";
|
|
7
|
+
import { convertShortcuts } from "./utils";
|
|
8
|
+
const toggleFullScreen = () => isFullScreen() ? exitFullScreen() : requestFullScreen();
|
|
9
|
+
const events = onClickReact(toggleFullScreen);
|
|
10
|
+
/** Fullscreen control */
|
|
11
|
+
export function FullScreen({ className, render, shortcuts, }) {
|
|
12
|
+
const keymap = useKeymap();
|
|
13
|
+
const forceUpdate = useForceUpdate();
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
// listener
|
|
16
|
+
onFullScreenChange(forceUpdate);
|
|
17
|
+
// keyboard shortcut
|
|
18
|
+
for (const seq of shortcuts ?? []) {
|
|
19
|
+
keymap.bind(seq, toggleFullScreen);
|
|
20
|
+
}
|
|
21
|
+
return () => {
|
|
22
|
+
for (const seq of shortcuts ?? []) {
|
|
23
|
+
keymap.unbind(seq, toggleFullScreen);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}, [forceUpdate, keymap, shortcuts]);
|
|
27
|
+
return render({ isFullScreen: isFullScreen() ?? false }, {
|
|
28
|
+
"aria-keyshortcuts": convertShortcuts(shortcuts),
|
|
29
|
+
className: classNames("lv-controls-fullscreen lv-controls-button", className),
|
|
30
|
+
...events,
|
|
31
|
+
});
|
|
32
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKeymap } from "@liqvid/keymap/react";
|
|
3
|
+
import { usePlayback, usePlaybackEvent } from "@liqvid/playback/react";
|
|
4
|
+
import { onClickReact, useForceUpdate } from "@liqvid/utils";
|
|
5
|
+
import classNames from "classnames";
|
|
6
|
+
import { useCallback, useEffect, useMemo } from "react";
|
|
7
|
+
import { bind, convertShortcuts, unbind } from "./utils";
|
|
8
|
+
/** Mute/unmute button */
|
|
9
|
+
export function Mute({ className, render, shortcuts }) {
|
|
10
|
+
const keymap = useKeymap();
|
|
11
|
+
const playback = usePlayback();
|
|
12
|
+
const forceUpdate = useForceUpdate();
|
|
13
|
+
// keyboard controls
|
|
14
|
+
const toggleMute = useCallback(() => {
|
|
15
|
+
playback.muted = !playback.muted;
|
|
16
|
+
}, [playback]);
|
|
17
|
+
usePlaybackEvent("volumechange", forceUpdate);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
// keyboard shortcuts
|
|
20
|
+
bind(keymap, shortcuts, toggleMute);
|
|
21
|
+
return () => {
|
|
22
|
+
// keyboard shortcuts
|
|
23
|
+
unbind(keymap, shortcuts, toggleMute);
|
|
24
|
+
};
|
|
25
|
+
}, [keymap, shortcuts, toggleMute]);
|
|
26
|
+
const events = useMemo(() => onClickReact(toggleMute), [toggleMute]);
|
|
27
|
+
if (render) {
|
|
28
|
+
return render({
|
|
29
|
+
muted: playback.muted,
|
|
30
|
+
volume: playback.volume,
|
|
31
|
+
}, {
|
|
32
|
+
"aria-keyshortcuts": convertShortcuts(shortcuts),
|
|
33
|
+
className: classNames("lv-controls-mute lv-controls-button", className),
|
|
34
|
+
...events,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKeymap } from "@liqvid/keymap/react";
|
|
3
|
+
import { usePlayback, usePlaybackEvent } from "@liqvid/playback/react";
|
|
4
|
+
import { onClickReact, useForceUpdate } from "@liqvid/utils";
|
|
5
|
+
import classNames from "classnames";
|
|
6
|
+
import { useCallback, useEffect, useMemo } from "react";
|
|
7
|
+
import { convertShortcuts } from "./utils";
|
|
8
|
+
/** Control for playing/pausing */
|
|
9
|
+
export function PlayPause({ className, render, shortcuts, }) {
|
|
10
|
+
const keymap = useKeymap();
|
|
11
|
+
const playback = usePlayback();
|
|
12
|
+
const forceUpdate = useForceUpdate();
|
|
13
|
+
usePlaybackEvent("pause", forceUpdate);
|
|
14
|
+
usePlaybackEvent("play", forceUpdate);
|
|
15
|
+
usePlaybackEvent("seeked", forceUpdate);
|
|
16
|
+
usePlaybackEvent("seeking", forceUpdate);
|
|
17
|
+
usePlaybackEvent("stop", forceUpdate);
|
|
18
|
+
// keyboard controls
|
|
19
|
+
const toggle = useCallback(() => playback[playback.paused ? "play" : "pause"](), [playback]);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
// keyboard shortcut
|
|
22
|
+
for (const seq of shortcuts ?? []) {
|
|
23
|
+
keymap.bind(seq, toggle);
|
|
24
|
+
}
|
|
25
|
+
return () => {
|
|
26
|
+
// unbind keyboard controls
|
|
27
|
+
for (const seq of shortcuts ?? []) {
|
|
28
|
+
keymap.unbind(seq, toggle);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
}, [keymap, shortcuts, toggle]);
|
|
32
|
+
// event handler
|
|
33
|
+
const events = useMemo(() => onClickReact(toggle), [toggle]);
|
|
34
|
+
return render({ paused: playback.paused, seeking: playback.seeking }, {
|
|
35
|
+
"aria-keyshortcuts": convertShortcuts(shortcuts),
|
|
36
|
+
className: classNames("lv-controls-playpause lv-controls-button", className),
|
|
37
|
+
...events,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { Duration } from "@liqvid/duration";
|
|
4
|
+
import { useKeymap } from "@liqvid/keymap/react";
|
|
5
|
+
import { usePlayback, usePlaybackEvent } from "@liqvid/playback/react";
|
|
6
|
+
import { anyHover, between, clamp, onDrag } from "@liqvid/utils";
|
|
7
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
8
|
+
import { ThumbnailBox } from "./ThumbnailBox";
|
|
9
|
+
export function ScrubberBar({ shortcuts, thumbs, ...props }) {
|
|
10
|
+
const playback = usePlayback();
|
|
11
|
+
const [progress, setProgress] = useState({
|
|
12
|
+
scrubber: playback.currentTime / playback.duration,
|
|
13
|
+
thumb: playback.currentTime / playback.duration,
|
|
14
|
+
});
|
|
15
|
+
const [showThumb, setShowThumb] = useState(false);
|
|
16
|
+
// refs
|
|
17
|
+
const scrubberBar = useRef(null);
|
|
18
|
+
/* Event handlers */
|
|
19
|
+
usePlaybackEvent("seek", useCallback(() => {
|
|
20
|
+
if (playback.seeking)
|
|
21
|
+
return;
|
|
22
|
+
const progress = playback.currentTime / playback.duration;
|
|
23
|
+
setProgress({ scrubber: progress, thumb: progress });
|
|
24
|
+
}, [playback]));
|
|
25
|
+
usePlaybackEvent("seeked", useCallback(() => {
|
|
26
|
+
const progress = playback.currentTime / playback.duration;
|
|
27
|
+
setProgress((prev) => ({ scrubber: progress, thumb: prev.thumb }));
|
|
28
|
+
}, [playback]));
|
|
29
|
+
usePlaybackEvent("timeupdate", useCallback(() => {
|
|
30
|
+
const progress = playback.currentTime / playback.duration;
|
|
31
|
+
setProgress((prev) => ({ scrubber: progress, thumb: prev.thumb }));
|
|
32
|
+
}, [playback]));
|
|
33
|
+
useRelativeShortcuts(shortcuts?.relative);
|
|
34
|
+
usePercentageShortcuts(shortcuts?.percentage);
|
|
35
|
+
// event handlers
|
|
36
|
+
const divEvents = useMemo(() => {
|
|
37
|
+
if (!anyHover)
|
|
38
|
+
return {};
|
|
39
|
+
const listener = onDrag(
|
|
40
|
+
// move
|
|
41
|
+
(_e, { x }) => {
|
|
42
|
+
if (!scrubberBar.current)
|
|
43
|
+
return;
|
|
44
|
+
const rect = scrubberBar.current.getBoundingClientRect(), progress = clamp(0, (x - rect.left) / rect.width, 1);
|
|
45
|
+
setProgress({ scrubber: progress, thumb: progress });
|
|
46
|
+
playback.currentTime = progress * playback.duration;
|
|
47
|
+
},
|
|
48
|
+
// down
|
|
49
|
+
(_e, { x }) => {
|
|
50
|
+
if (!scrubberBar.current)
|
|
51
|
+
return;
|
|
52
|
+
playback.seeking = true;
|
|
53
|
+
const rect = scrubberBar.current.getBoundingClientRect(), progress = clamp(0, (x - rect.left) / rect.width, 1);
|
|
54
|
+
setProgress({ scrubber: progress, thumb: progress });
|
|
55
|
+
playback.currentTime = progress * playback.duration;
|
|
56
|
+
},
|
|
57
|
+
// up
|
|
58
|
+
() => {
|
|
59
|
+
playback.seeking = false;
|
|
60
|
+
});
|
|
61
|
+
return {
|
|
62
|
+
onMouseDown: (e) => listener(e.nativeEvent),
|
|
63
|
+
};
|
|
64
|
+
}, [playback]);
|
|
65
|
+
// events to attach on the wrapper
|
|
66
|
+
const wrapEvents = useMemo(() => {
|
|
67
|
+
const props = {};
|
|
68
|
+
if (anyHover) {
|
|
69
|
+
Object.assign(props, {
|
|
70
|
+
onMouseMove: (e) => {
|
|
71
|
+
if (!scrubberBar.current)
|
|
72
|
+
return;
|
|
73
|
+
const rect = scrubberBar.current.getBoundingClientRect(), progress = clamp(0, (e.clientX - rect.left) / rect.width, 1);
|
|
74
|
+
setProgress((prev) => ({ scrubber: prev.scrubber, thumb: progress }));
|
|
75
|
+
},
|
|
76
|
+
onMouseOut: () => setShowThumb(false),
|
|
77
|
+
// show thumb preview on hover
|
|
78
|
+
onMouseOver: () => setShowThumb(true),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
const listener = onDrag(
|
|
82
|
+
// move
|
|
83
|
+
(_e, { x }) => {
|
|
84
|
+
if (!scrubberBar.current)
|
|
85
|
+
return;
|
|
86
|
+
const rect = scrubberBar.current.getBoundingClientRect(), progress = clamp(0, (x - rect.left) / rect.width, 1);
|
|
87
|
+
setProgress({ scrubber: progress, thumb: progress });
|
|
88
|
+
},
|
|
89
|
+
// start
|
|
90
|
+
(e) => {
|
|
91
|
+
e.preventDefault();
|
|
92
|
+
e.stopPropagation();
|
|
93
|
+
playback.seeking = true;
|
|
94
|
+
setShowThumb(true);
|
|
95
|
+
},
|
|
96
|
+
// end
|
|
97
|
+
(e, { x }) => {
|
|
98
|
+
e.preventDefault();
|
|
99
|
+
if (!scrubberBar.current)
|
|
100
|
+
return;
|
|
101
|
+
const rect = scrubberBar.current.getBoundingClientRect(), progress = clamp(0, (x - rect.left) / rect.width, 1);
|
|
102
|
+
setShowThumb(false);
|
|
103
|
+
playback.seeking = false;
|
|
104
|
+
playback.currentTime = progress * playback.duration;
|
|
105
|
+
});
|
|
106
|
+
props.onTouchStart = listener;
|
|
107
|
+
return props;
|
|
108
|
+
}, [playback]);
|
|
109
|
+
// events to be attached to the scrubber
|
|
110
|
+
const scrubberEvents = useMemo(() => {
|
|
111
|
+
// if (anyHover) return {};
|
|
112
|
+
const listener = onDrag(
|
|
113
|
+
// move
|
|
114
|
+
(_e, { x }) => {
|
|
115
|
+
if (!scrubberBar.current)
|
|
116
|
+
return;
|
|
117
|
+
const rect = scrubberBar.current.getBoundingClientRect(), progress = clamp(0, (x - rect.left) / rect.width, 1);
|
|
118
|
+
setProgress({ scrubber: progress, thumb: progress });
|
|
119
|
+
},
|
|
120
|
+
// start
|
|
121
|
+
(e) => {
|
|
122
|
+
e.preventDefault();
|
|
123
|
+
e.stopPropagation();
|
|
124
|
+
playback.seeking = true;
|
|
125
|
+
setShowThumb(true);
|
|
126
|
+
},
|
|
127
|
+
// end
|
|
128
|
+
(e, { x }) => {
|
|
129
|
+
e.preventDefault();
|
|
130
|
+
if (!scrubberBar.current)
|
|
131
|
+
return;
|
|
132
|
+
const rect = scrubberBar.current.getBoundingClientRect(), progress = clamp(0, (x - rect.left) / rect.width, 1);
|
|
133
|
+
setShowThumb(false);
|
|
134
|
+
playback.seeking = false;
|
|
135
|
+
playback.currentTime = progress * playback.duration;
|
|
136
|
+
});
|
|
137
|
+
return {
|
|
138
|
+
onTouchStart: listener,
|
|
139
|
+
};
|
|
140
|
+
}, [playback]);
|
|
141
|
+
// TODO: optimize this
|
|
142
|
+
const activeHighlight = thumbs?.highlights?.find((h) => between(Duration.from(h.time).inSeconds() / playback.duration, progress.thumb, Duration.from(h.time).inSeconds() / playback.duration + 0.01));
|
|
143
|
+
return (_jsxs("div", { className: "lv-controls-scrub", ref: scrubberBar, ...divEvents, ...props, children: [thumbs && (_jsx(ThumbnailBox, { ...thumbs, progress: progress.thumb, show: showThumb, title: activeHighlight?.title })), _jsxs("div", { className: "lv-controls-scrub-wrap", ...wrapEvents, children: [_jsxs("svg", { className: "lv-controls-scrub-progress", preserveAspectRatio: "none", viewBox: "0 0 100 10", children: [_jsx("rect", { className: "lv-progress-elapsed", height: "10", width: progress.scrubber * 100, x: "0", y: "0" }), _jsx("rect", { className: "lv-progress-remaining", height: "10", width: (1 - progress.scrubber) * 100, x: progress.scrubber * 100, y: "0" }), thumbs?.highlights?.map(({ time }) => {
|
|
144
|
+
const $time = Duration.from(time);
|
|
145
|
+
return (_jsx("rect", { className: ["lv-thumb-highlight"]
|
|
146
|
+
.concat($time.inSeconds() <= playback.currentTime ? "past" : [])
|
|
147
|
+
.join(" "), height: "10", width: "1", x: ($time.inSeconds() / playback.duration) * 100, y: "0" }, $time.inSeconds()));
|
|
148
|
+
})] }), _jsx("svg", { className: "lv-scrubber", style: { left: `calc(${progress.scrubber * 100}% - 6px)` }, viewBox: "0 0 100 100", ...scrubberEvents, children: _jsx("circle", { cx: "50", cy: "50", r: "50", stroke: "none" }) })] })] }));
|
|
149
|
+
}
|
|
150
|
+
function useRelativeShortcuts(shortcuts) {
|
|
151
|
+
const keymap = useKeymap();
|
|
152
|
+
const playback = usePlayback();
|
|
153
|
+
const configs = useMemo(() => shortcuts?.map(({ key, delta }) => {
|
|
154
|
+
delta = Duration.from(delta);
|
|
155
|
+
const callback = () => {
|
|
156
|
+
playback.currentTime$ = playback.currentTime$.plus(delta);
|
|
157
|
+
};
|
|
158
|
+
return [key, callback];
|
|
159
|
+
}) ?? [], [playback, shortcuts]);
|
|
160
|
+
useEffect(() => {
|
|
161
|
+
// bind
|
|
162
|
+
for (const [key, callback] of configs) {
|
|
163
|
+
keymap.bind(key, callback);
|
|
164
|
+
}
|
|
165
|
+
// unbind
|
|
166
|
+
return () => {
|
|
167
|
+
for (const [key, callback] of configs) {
|
|
168
|
+
keymap.unbind(key, callback);
|
|
169
|
+
}
|
|
170
|
+
};
|
|
171
|
+
}, [configs, keymap]);
|
|
172
|
+
}
|
|
173
|
+
function usePercentageShortcuts(shortcuts) {
|
|
174
|
+
const keymap = useKeymap();
|
|
175
|
+
const playback = usePlayback();
|
|
176
|
+
const configs = useMemo(() => shortcuts?.map(({ key, multiplier }) => {
|
|
177
|
+
const callback = () => {
|
|
178
|
+
playback.currentTime = playback.duration * multiplier;
|
|
179
|
+
};
|
|
180
|
+
return [key, callback];
|
|
181
|
+
}) ?? [], [playback, shortcuts]);
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
// bind
|
|
184
|
+
for (const [key, callback] of configs) {
|
|
185
|
+
keymap.bind(key, callback);
|
|
186
|
+
}
|
|
187
|
+
// unbind
|
|
188
|
+
return () => {
|
|
189
|
+
for (const [key, callback] of configs) {
|
|
190
|
+
keymap.unbind(key, callback);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
}, [configs, keymap]);
|
|
194
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { usePlayback } from "@liqvid/playback/react";
|
|
3
|
+
import { formatTime } from "@liqvid/utils";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
export function ThumbnailBox({ cols = 5, rows = 5, frequency = 4, path, progress, show, title, height = 100, width = 160, }) {
|
|
6
|
+
const { duration } = usePlayback();
|
|
7
|
+
const count = cols * rows;
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
// preload thumbs (once more important loading has taken place)
|
|
10
|
+
const maxSlide = Math.floor(duration / frequency), maxSheet = Math.floor(maxSlide / count);
|
|
11
|
+
for (let sheetNum = 0; sheetNum <= maxSheet; ++sheetNum) {
|
|
12
|
+
const img = new Image();
|
|
13
|
+
img.src = path.replace("%s", sheetNum.toString());
|
|
14
|
+
}
|
|
15
|
+
}, [count, frequency, path, duration]);
|
|
16
|
+
const time = progress * duration;
|
|
17
|
+
const markerNum = Math.floor(time / frequency);
|
|
18
|
+
const sheetNum = Math.floor(markerNum / count);
|
|
19
|
+
const markerNumOnSheet = markerNum % count;
|
|
20
|
+
const row = Math.floor(markerNumOnSheet / rows);
|
|
21
|
+
const col = markerNumOnSheet % rows;
|
|
22
|
+
const sheetName = path.replace("%s", sheetNum.toString());
|
|
23
|
+
return (_jsxs("div", { className: "lv-controls-thumbnail", style: {
|
|
24
|
+
display: show ? "block" : "none",
|
|
25
|
+
left: `${progress * 100}%`,
|
|
26
|
+
}, children: [title && _jsx("span", { className: "lv-thumbnail-title", children: title }), _jsxs("div", { className: "lv-thumbnail-box", children: [_jsx("img", { alt: "", src: sheetName, style: {
|
|
27
|
+
left: `-${col * width}px`,
|
|
28
|
+
maxWidth: "unset",
|
|
29
|
+
top: `-${row * height}px`,
|
|
30
|
+
} }), _jsx("span", { className: "lv-thumbnail-time", children: formatTime(time * 1000) })] })] }));
|
|
31
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { usePlayback, usePlaybackEvent, useTime } from "@liqvid/playback/react";
|
|
4
|
+
import { formatTime, useForceUpdate } from "@liqvid/utils";
|
|
5
|
+
import { useRef } from "react";
|
|
6
|
+
export function TimeDisplay() {
|
|
7
|
+
const playback = usePlayback();
|
|
8
|
+
const forceUpdate = useForceUpdate();
|
|
9
|
+
usePlaybackEvent("durationchange", forceUpdate);
|
|
10
|
+
usePlaybackEvent("seek", forceUpdate);
|
|
11
|
+
useTime(() => {
|
|
12
|
+
const timeElt = timeRef.current;
|
|
13
|
+
if (!timeElt)
|
|
14
|
+
return;
|
|
15
|
+
timeElt.innerText = formatTime(playback.currentTime$);
|
|
16
|
+
});
|
|
17
|
+
const timeRef = useRef(null);
|
|
18
|
+
return (_jsxs("span", { className: "lv-controls-time", children: [_jsx("time", { className: "lv-current-time", ref: timeRef, children: formatTime(playback.currentTime$) }), _jsx("span", { className: "lv-time-separator", children: "/" }), _jsx("time", { className: "lv-total-time", children: formatTime(playback.duration$) })] }));
|
|
19
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useKeymap } from "@liqvid/keymap/react";
|
|
3
|
+
import { usePlayback, usePlaybackEvent } from "@liqvid/playback/react";
|
|
4
|
+
import { useForceUpdate } from "@liqvid/utils";
|
|
5
|
+
import classNames from "classnames";
|
|
6
|
+
import { useCallback, useEffect } from "react";
|
|
7
|
+
const VOLUME_MAX = 100;
|
|
8
|
+
/** Volume control */
|
|
9
|
+
export function VolumeSlider({ className, render, shortcuts, }) {
|
|
10
|
+
const keymap = useKeymap();
|
|
11
|
+
const playback = usePlayback();
|
|
12
|
+
const forceUpdate = useForceUpdate();
|
|
13
|
+
usePlaybackEvent("volumechange", forceUpdate);
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
// keyboard shortcuts
|
|
16
|
+
const shortcutCallbacks = (shortcuts ?? []).map((s) => {
|
|
17
|
+
if ("delta" in s) {
|
|
18
|
+
return {
|
|
19
|
+
callback: () => {
|
|
20
|
+
playback.muted = false;
|
|
21
|
+
playback.volume += s.delta / VOLUME_MAX;
|
|
22
|
+
},
|
|
23
|
+
seq: s.seq,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
return {
|
|
28
|
+
callback: () => {
|
|
29
|
+
playback.muted = false;
|
|
30
|
+
playback.volume = s.value;
|
|
31
|
+
},
|
|
32
|
+
seq: s.seq,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
for (const { seq, callback } of shortcutCallbacks) {
|
|
37
|
+
keymap.bind(seq, callback);
|
|
38
|
+
}
|
|
39
|
+
return () => {
|
|
40
|
+
// keyboard shortcuts
|
|
41
|
+
for (const { seq: key, callback } of shortcutCallbacks) {
|
|
42
|
+
keymap.unbind(key, callback);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}, [forceUpdate, keymap, playback]);
|
|
46
|
+
// input
|
|
47
|
+
const onChange = useCallback((e) => {
|
|
48
|
+
playback.muted = false;
|
|
49
|
+
playback.volume = parseFloat(e.target.value) / VOLUME_MAX;
|
|
50
|
+
}, [playback]);
|
|
51
|
+
if (render) {
|
|
52
|
+
return render({
|
|
53
|
+
muted: playback.muted,
|
|
54
|
+
volume: playback.volume,
|
|
55
|
+
}, {
|
|
56
|
+
// "aria-keyshortcuts": convertShortcuts(shortcuts),
|
|
57
|
+
className: classNames("lv-controls-volume-slider", className),
|
|
58
|
+
max: VOLUME_MAX,
|
|
59
|
+
min: 0,
|
|
60
|
+
onChange,
|
|
61
|
+
type: "range",
|
|
62
|
+
value: playback.muted ? 0 : playback.volume * VOLUME_MAX,
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { exitFullScreen as $exitFullScreen, isFullScreen as $isFullScreen, onFullScreenChange as $onFullScreenChange, requestFullScreen as $requestFullScreen, fullscreenEnabled, } from "./polyfills";
|
|
2
|
+
let __isFullScreen = false;
|
|
3
|
+
const __callbacks = [];
|
|
4
|
+
export const requestFullScreen = fullscreenEnabled
|
|
5
|
+
? $requestFullScreen
|
|
6
|
+
: () => {
|
|
7
|
+
window.parent.postMessage({ type: "fake-fullscreen", value: true }, window.parent.origin);
|
|
8
|
+
if (!__isFullScreen) {
|
|
9
|
+
__isFullScreen = true;
|
|
10
|
+
for (const _ of __callbacks)
|
|
11
|
+
_();
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
export const exitFullScreen = fullscreenEnabled
|
|
15
|
+
? $exitFullScreen
|
|
16
|
+
: () => {
|
|
17
|
+
window.parent.postMessage({ type: "fake-fullscreen", value: false }, window.parent.origin);
|
|
18
|
+
if (__isFullScreen) {
|
|
19
|
+
__isFullScreen = false;
|
|
20
|
+
for (const _ of __callbacks)
|
|
21
|
+
_();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
export const isFullScreen = fullscreenEnabled
|
|
25
|
+
? $isFullScreen
|
|
26
|
+
: () => {
|
|
27
|
+
return __isFullScreen;
|
|
28
|
+
};
|
|
29
|
+
export const onFullScreenChange = fullscreenEnabled
|
|
30
|
+
? $onFullScreenChange
|
|
31
|
+
: (callback) => {
|
|
32
|
+
__callbacks.push(callback);
|
|
33
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { ColorSchemeToggle } from "./ColorSchemeToggle";
|
|
2
|
+
export { FullScreen } from "./FullScreen";
|
|
3
|
+
export { Mute } from "./MuteButton";
|
|
4
|
+
export { PlayPause } from "./PlayPause";
|
|
5
|
+
export { ScrubberBar, } from "./ScrubberBar";
|
|
6
|
+
export { TimeDisplay } from "./TimeDisplay";
|
|
7
|
+
export { VolumeSlider, } from "./VolumeSlider";
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { isClient } from "@liqvid/ssr";
|
|
2
|
+
const id = (_) => _;
|
|
3
|
+
export const fullscreenEnabled = isClient
|
|
4
|
+
? [
|
|
5
|
+
"fullscreenEnabled",
|
|
6
|
+
"webkitFullscreenEnabled",
|
|
7
|
+
"mozFullScreenEnabled",
|
|
8
|
+
"msFullscreenEnabled",
|
|
9
|
+
]
|
|
10
|
+
// biome-ignore lint/suspicious/noExplicitAny: vendor-specific
|
|
11
|
+
.map((_) => document[_])
|
|
12
|
+
.concat(false)
|
|
13
|
+
.find((_) => _ !== undefined)
|
|
14
|
+
: false;
|
|
15
|
+
export const requestFullScreen = isClient
|
|
16
|
+
? [
|
|
17
|
+
"requestFullscreen",
|
|
18
|
+
"webkitRequestFullscreen",
|
|
19
|
+
"mozRequestFullScreen",
|
|
20
|
+
"msRequestFullscreen",
|
|
21
|
+
]
|
|
22
|
+
// biome-ignore lint/suspicious/noExplicitAny: vendor-specific
|
|
23
|
+
.map((_) => document.body[_])
|
|
24
|
+
.concat(() => { })
|
|
25
|
+
.find(id)
|
|
26
|
+
.bind(document.body)
|
|
27
|
+
: async () => { };
|
|
28
|
+
export const exitFullScreen = isClient
|
|
29
|
+
? [
|
|
30
|
+
"exitFullscreen",
|
|
31
|
+
"webkitExitFullscreen",
|
|
32
|
+
"mozCancelFullScreen",
|
|
33
|
+
"msExitFullscreen",
|
|
34
|
+
]
|
|
35
|
+
// biome-ignore lint/suspicious/noExplicitAny: vendor-specific
|
|
36
|
+
.map((_) => document[_])
|
|
37
|
+
.concat(async () => { })
|
|
38
|
+
.find(id)
|
|
39
|
+
.bind(document)
|
|
40
|
+
: async () => { };
|
|
41
|
+
export const isFullScreen = () => ["fullscreen", "webkitIsFullScreen", "mozFullScreen"]
|
|
42
|
+
// biome-ignore lint/suspicious/noExplicitAny: vendor-specific
|
|
43
|
+
.map((_) => document[_])
|
|
44
|
+
.find((_) => _ !== undefined);
|
|
45
|
+
export function onFullScreenChange(callback) {
|
|
46
|
+
for (const event of [
|
|
47
|
+
"fullscreenchange",
|
|
48
|
+
"webkitfullscreenchange",
|
|
49
|
+
"mozfullscreenchange",
|
|
50
|
+
"MSFullscreenChange",
|
|
51
|
+
])
|
|
52
|
+
document.addEventListener(event, callback);
|
|
53
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export function bind(keymap, seqs, callback) {
|
|
2
|
+
if (!seqs)
|
|
3
|
+
return;
|
|
4
|
+
if (typeof seqs === "string") {
|
|
5
|
+
keymap.bind(seqs, callback);
|
|
6
|
+
}
|
|
7
|
+
else {
|
|
8
|
+
for (const s of seqs) {
|
|
9
|
+
keymap.bind(s, callback);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function unbind(keymap, seqs, callback) {
|
|
14
|
+
if (!seqs)
|
|
15
|
+
return;
|
|
16
|
+
if (typeof seqs === "string") {
|
|
17
|
+
keymap.bind(seqs, callback);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
for (const s of seqs) {
|
|
21
|
+
keymap.bind(s, callback);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function convertShortcuts(keys) {
|
|
26
|
+
if (typeof keys === "string")
|
|
27
|
+
return keys;
|
|
28
|
+
if (typeof keys === "undefined")
|
|
29
|
+
return undefined;
|
|
30
|
+
return keys.join(" ");
|
|
31
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"fileNames":["../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.iterable.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.core.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.collection.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.generator.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.iterable.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.promise.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.proxy.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.reflect.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.array.include.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2016.intl.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.date.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.object.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.string.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.intl.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.intl.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.promise.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2018.regexp.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.array.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.object.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.string.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.symbol.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2019.intl.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.bigint.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.date.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.promise.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.string.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.intl.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2020.number.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.promise.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.string.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.weakref.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2021.intl.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.array.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.error.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.intl.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.object.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.string.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es2022.regexp.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.d.ts","../../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","../../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/global.d.ts","../../../node_modules/.pnpm/csstype@3.2.3/node_modules/csstype/index.d.ts","../../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/index.d.ts","../../../node_modules/.pnpm/@types+react@19.2.14/node_modules/@types/react/jsx-runtime.d.ts","../../hydration/dist/types/types.d.ts","../../hydration/dist/types/hydrateelement.d.ts","../../hydration/dist/types/hydrateonclient.d.ts","../../hydration/dist/types/hydratevariants.d.ts","../../hydration/dist/types/persistence.d.ts","../../hydration/dist/types/sneakyscript.d.ts","../../hydration/dist/types/index.d.ts","../../color-scheme/dist/types/react.d.ts","../../keymap/dist/types/index.d.mts","../../keymap/dist/types/react.d.ts","../../duration/dist/types/index.d.mts","../../../node_modules/.pnpm/bezier-easing@2.1.0/node_modules/bezier-easing/src/index.d.ts","../../utils/dist/types/replay-data.d.ts","../../utils/dist/types/animation.d.ts","../../utils/dist/types/collections.d.ts","../../utils/dist/types/interaction.d.ts","../../utils/dist/types/math.d.ts","../../utils/dist/types/misc.d.ts","../../utils/dist/types/react.d.ts","../../utils/dist/types/svg.d.ts","../../utils/dist/types/time.d.ts","../../utils/dist/types/types.d.ts","../../utils/dist/types/index.d.ts","../../../node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.d.ts","../src/utils.ts","../src/colorschemetoggle.tsx","../../ssr/dist/types/index.d.mts","../src/polyfills.ts","../src/fake-fullscreen.ts","../src/fullscreen.tsx","../../event-emitter/dist/types/types.d.mts","../../event-emitter/dist/types/index.d.mts","../../playback/dist/types/synthetic-playback.d.mts","../../playback/dist/types/playback.d.mts","../../playback/dist/types/react.d.ts","../src/mutebutton.tsx","../src/playpause.tsx","../src/thumbnailbox.tsx","../src/scrubberbar.tsx","../src/timedisplay.tsx","../src/volumeslider.tsx","../src/index.ts","../../../node_modules/.pnpm/@types+react-dom@19.2.3_@types+react@19.2.14/node_modules/@types/react-dom/index.d.ts"],"fileIdsList":[[62],[60,61],[63,70],[62,63,71,73,86,87,88],[63,91],[62,63,73,86,87,88,92],[63,89,93,99,100,101,102,103,104],[62,63,73,86,87,88,98],[63,90],[62,63,73,74,86,98,101],[62,63,74,86,98],[62,63,86,98],[63,72],[62,63,73,86,87,98],[94],[95],[63,64],[64,65,66,67,68,69],[64],[63],[62,63,72],[74,96],[62,63,74,96,97],[74,75,76],[76,77,78,79,80,81,82,83,84,85],[79],[74]],"fileInfos":[{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"2e80ee7a49e8ac312cc11b77f1475804bee36b3b2bc896bead8b6e1266befb43","affectsGlobalScope":true,"impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"fb0f136d372979348d59b3f5020b4cdb81b5504192b1cacff5d1fbba29378aa1","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"a680117f487a4d2f30ea46f1b4b7f58bef1480456e18ba53ee85c2746eeca012","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"8cdf8847677ac7d20486e54dd3fcf09eda95812ac8ace44b4418da1bbbab6eb8","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"7e29f41b158de217f94cb9676bf9cbd0cd9b5a46e1985141ed36e075c52bf6ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac51dd7d31333793807a6abaa5ae168512b6131bd41d9c5b98477fc3b7800f9f","impliedFormat":1},{"version":"dc0a7f107690ee5cd8afc8dbf05c4df78085471ce16bdd9881642ec738bc81fe","impliedFormat":1},{"version":"42c169fb8c2d42f4f668c624a9a11e719d5d07dacbebb63cbcf7ef365b0a75b3","impliedFormat":1},"0eff7e8c827a6b4d69d8d70da4fb83f24f1a0b2b600556c7929dc9925095f3ba","3bacb44aeb3ebd20957d1dc2ef689ee8007157144b9cb1cbdaf2a3531d44c66b","cee0ce9ca1e0bc522c0144c26f1a65eb20b901b2761804bcc26c4713cc83f841","4c5a1176bb2807ba5c543bbd5ca2722ed22bdf27022c51f3a7c9ee872f1cc730","b4f2d9d6adc44b6b5186a439721d7679eb3bee520aacd746b3116675883cd831","8125f98748dd4bbd4ce71d509ecea3474a3cad8f3d1352e29c2a6a5b8b399738","10240982d1ac7dc0590c971472849d48a954f31fa5884afcc2eed3e11cdcd28e","b8b662c06dc5c6f1a8e4455776542ed35bcbd220dd5c66439854d21f46e74dfa",{"version":"0427b580231f52ef097919ba61fcfe5e37f5fa5523ed4fd6d4864bde4dd8470c","impliedFormat":99},"de635f3aa40a27cca6d425276d463213f07bdaf54873a776f4a03b5fdecee1ce",{"version":"6f2dfeeb74d340004f68f576add21aac0668ae1da4c4e9ba3193541f3e865867","impliedFormat":99},{"version":"5e221d7876afbd3b808798515c5dd53d49e8aa4fe4c6095bc6760b30acff4b37","impliedFormat":1},"3ec9f283a3eb75a2fb4a89467a97ae6d13d3cd7589dadb5e1e5b59a875e6f6c9","cfbb4e78e9b657a14c100a97f6f8d9997a208fe30695895ab384f3fc0246492e","06f5a3f26c2c2dddab05df1375db0a6353efa4bcd818d53e0bbde7b94024d732",{"version":"8005021af1514f4193c860c4b7eeb2f01f660c443c2f7180f2c93aed44af3b16","affectsGlobalScope":true},"2b0dafed8302e979ebbee421ac05e790ee5621457a264cb1b8e76ef3afd72f3b","7f8b57b8dd275f27fc63e58f9f0d608054060cd7f2d57a3bc53653c39f6326e3","4ea806290d11878e3ee168b836612c19bc630c4f0782b1d1582b05b90d771ff8","69eaf11c5a8479bc92d32da085bfb9cba8ca6884366b4941369a4d24a27992c6","eca06e9eb6ebd0a81decc4d04aa1d0df7a2e6cb4588c3059269321c9e0fecc09","239f3c704fc87252b5dd00f70e35bc57af83a33e20a3ad71d14c3d2d99c3b4a4","3db60448ebc41502a9869dd39a4a6a3682ca9b5fcb8297399676fea8c88b7678",{"version":"1dfdec0ec9c299625d20c5cb8f96e2a801c81d91669c6245f520e8734a92fb3d","impliedFormat":1},{"version":"b131ef9faad176b6c142cc6fe1500558f1afb70bce4f2ba2c0df60d76f4ee536","signature":"5cbe0951bd491345f6ef3e9b38dbc0b62c6a8bd553e8ed9c7f523a848ecd72cb"},{"version":"d972ca7887d35ee6efd3781ac892fece1a9c3846f7163aeadbddff8616ecf763","signature":"38b01c0690caaaf23d9959db3fbcabca5313bd83eaaa7cfe3f076fa142e0286f"},{"version":"3954f113df61328c6af4bc83c9e50ab16ddac2ee9793210608e79e40da190061","impliedFormat":99},{"version":"80baa4231e6c2d35c254d82f3fdff692dc6c88f3e4f1b97b05b42a1c29020f5d","signature":"ccd62f94aa21c99e133a749d6e87e3d1695b48a7e91e7503b9fa1549f60b767a"},{"version":"765d7581ac15e7a7aa31b7c00c55291d6ba74b188591cc382e49af47390fc2b6","signature":"94870bb11f04ff117af0715c59d24a38ccfe1f10a3a4992f9c0f8d01443c5213"},{"version":"5e789963d8dca646eae96af4669e88b61ed3acac924bc1ec62b443fff9c3645c","signature":"acf27d2f62d5d325bbe4da5a5068204fb94ae542607529ee896e6b2df6d989d0"},{"version":"be831a6a1a2b57943dff1d23aa3b335b3b1621adc35807d8e3de0a0a9e96d0c9","impliedFormat":99},{"version":"5ce65fa2203ccb5304b06fadecfc53b41325ca5069f285a80f980acc476031f5","impliedFormat":99},{"version":"a6e7dd43e08acdccbc1d7578edeb2ce08b3bca87de26782bbc66192731f9cb83","impliedFormat":99},{"version":"5d4aad5c5865c0358f488e447a0874080b0ef6094f8b313abfb4ef09de83dce5","affectsGlobalScope":true,"impliedFormat":99},"33e8acec13777aeccf10a56d2b39f2ebc46b924dde7989365fc51b7c8b390778",{"version":"0c0efef6a8299f087e4cc90636068fc36e60802856cc375b191835efff149ddf","signature":"cdf78dfee97282d3c40412a02f815e2203b8a9d548e714f78c9dac071047fc46"},{"version":"b37bf0ccebe05b1a40f816313e6a5ef84a2cb1b91a8a336b5f79b6ebdba7c430","signature":"e5609d862c97cf859e4c70ae0aeb7f82e610b8db023847cd759c8c818897e7a1"},{"version":"9dc2c42fbe64f8d3a07136707b3414912d7ca253a890514f9ae66f6c1a2b4a73","signature":"ea2cc5eb65c508b48ab52485c5c0466ea0830841cc383cd0fbb24130e30ca85e"},{"version":"4efd8eacc2e28cffcbeffdd9952f4fd0c5b5b56ec98d1a39b4a3359544fc22af","signature":"c2e4312739fbeba0ad0252ed639e3e789bb6cd2982fb560ccc0b9b6546782455"},{"version":"468abb1fdf97ce4c62cb805c358b9c164d5d23324e58368501ecd75d292099fe","signature":"f455e9d1d6106b6330464b46f3e15ff86781fc09812999abc100462b5f858d72"},{"version":"93a4e22f8716f1b77a04c1f523ada1194c4baf6bd068054afdb37c187200d06f","signature":"7cc475b8c880bd32f223e0ade4ba75b1785880740211469dc38c21e59d696bf9"},{"version":"9ed6420e92e7bd2796786b4a1d0ca16da7c695453addf04cc02847a1888f8a50","signature":"8967ac0df21fd15975f3e4f0446e518d29d2c767c21ae55d916f46b6cff1d5d4"},{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1}],"root":[88,89,[91,93],[99,105]],"options":{"alwaysStrict":true,"composite":true,"declaration":true,"declarationDir":"./types","esModuleInterop":true,"jsx":4,"module":99,"noImplicitAny":true,"noImplicitOverride":true,"noUncheckedIndexedAccess":false,"outDir":"./esm","removeComments":false,"rewriteRelativeImportExtensions":true,"rootDir":"../src","skipLibCheck":true,"strict":true,"target":9,"verbatimModuleSyntax":true},"referencedMap":[[106,1],[62,2],[63,1],[71,3],[89,4],[92,5],[93,6],[105,7],[99,8],[100,8],[91,9],[102,10],[101,11],[103,12],[88,13],[104,14],[95,15],[94,16],[65,17],[66,17],[67,17],[70,18],[68,19],[69,20],[73,21],[97,22],[98,23],[96,16],[77,24],[86,25],[82,26],[84,27]],"semanticDiagnosticsPerFile":[[102,[{"start":4607,"length":18,"code":2322,"category":1,"messageText":{"messageText":"Type '(e: MouseEvent | TouchEvent) => void' is not assignable to type 'TouchEventHandler<HTMLDivElement>'.","category":1,"code":2322,"next":[{"messageText":"Types of parameters 'e' and 'event' are incompatible.","category":1,"code":2328,"next":[{"messageText":"Type 'TouchEvent<HTMLDivElement>' is not assignable to type 'MouseEvent | TouchEvent'.","category":1,"code":2322,"next":[{"messageText":"Type 'TouchEvent<HTMLDivElement>' is missing the following properties from type 'TouchEvent': which, initUIEvent, cancelBubble, composed, and 9 more.","category":1,"code":2740,"canonicalHead":{"code":2322,"messageText":"Type 'TouchEvent<HTMLDivElement>' is not assignable to type 'TouchEvent'."}}]}]}]}},{"start":7736,"length":3,"code":2322,"category":1,"messageText":{"messageText":"Type '{ children: Element; onTouchStart: (e: MouseEvent | TouchEvent) => void; className: string; style: { left: string; }; viewBox: string; }' is not assignable to type 'SVGProps<SVGSVGElement>'.","category":1,"code":2322,"next":[{"messageText":"Types of property 'onTouchStart' are incompatible.","category":1,"code":2326,"next":[{"messageText":"Type '(e: MouseEvent | TouchEvent) => void' is not assignable to type 'TouchEventHandler<SVGSVGElement>'.","category":1,"code":2322,"next":[{"messageText":"Types of parameters 'e' and 'event' are incompatible.","category":1,"code":2328,"next":[{"messageText":"Type 'TouchEvent<SVGSVGElement>' is not assignable to type 'MouseEvent | TouchEvent'.","category":1,"code":2322,"next":[{"messageText":"Type 'TouchEvent<SVGSVGElement>' is missing the following properties from type 'TouchEvent': which, initUIEvent, cancelBubble, composed, and 9 more.","category":1,"code":2740,"canonicalHead":{"code":2322,"messageText":"Type 'TouchEvent<SVGSVGElement>' is not assignable to type 'TouchEvent'."}}]}]}],"canonicalHead":{"code":2322,"messageText":"Type '{ children: Element; onTouchStart: (e: MouseEvent | TouchEvent) => void; className: string; style: { left: string; }; viewBox: string; }' is not assignable to type 'SVGProps<SVGSVGElement>'."}}]}]}}]]],"latestChangedDtsFile":"./types/index.d.ts","version":"5.9.3"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ColorScheme } from "@liqvid/color-scheme/react";
|
|
2
|
+
export declare function ColorSchemeToggle({ className, render, shortcuts, }: {
|
|
3
|
+
className?: string;
|
|
4
|
+
render: (state: {
|
|
5
|
+
colorScheme: ColorScheme;
|
|
6
|
+
}, props: React.ButtonHTMLAttributes<HTMLButtonElement>) => React.ReactNode;
|
|
7
|
+
shortcuts?: string | string[];
|
|
8
|
+
}): import("react").ReactNode;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface FullScreenControlProps {
|
|
2
|
+
className?: string;
|
|
3
|
+
render: (state: {
|
|
4
|
+
isFullScreen: boolean;
|
|
5
|
+
}, props: React.ButtonHTMLAttributes<HTMLButtonElement>) => React.ReactNode;
|
|
6
|
+
shortcuts?: string | string[];
|
|
7
|
+
}
|
|
8
|
+
/** Fullscreen control */
|
|
9
|
+
export declare function FullScreen({ className, render, shortcuts, }: FullScreenControlProps): import("react").ReactNode;
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
interface MutePropsBase {
|
|
2
|
+
className?: string;
|
|
3
|
+
shortcuts?: string[] | string;
|
|
4
|
+
}
|
|
5
|
+
interface MutesPropsCustomRender {
|
|
6
|
+
render: (state: {
|
|
7
|
+
muted: boolean;
|
|
8
|
+
volume: number;
|
|
9
|
+
}, props: React.HTMLAttributes<HTMLButtonElement>) => React.ReactNode;
|
|
10
|
+
variants?: undefined;
|
|
11
|
+
}
|
|
12
|
+
interface MutePropsVariants {
|
|
13
|
+
render?: undefined;
|
|
14
|
+
variants: {
|
|
15
|
+
muted?: true;
|
|
16
|
+
gte?: number;
|
|
17
|
+
lt?: number;
|
|
18
|
+
props: React.ButtonHTMLAttributes<HTMLButtonElement>;
|
|
19
|
+
}[];
|
|
20
|
+
}
|
|
21
|
+
export type MuteProps = MutePropsBase & (MutesPropsCustomRender | MutePropsVariants);
|
|
22
|
+
/** Mute/unmute button */
|
|
23
|
+
export declare function Mute({ className, render, shortcuts }: MuteProps): import("react").ReactNode;
|
|
24
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** Control for playing/pausing */
|
|
2
|
+
export declare function PlayPause({ className, render, shortcuts, }: {
|
|
3
|
+
className?: string;
|
|
4
|
+
render: (state: {
|
|
5
|
+
paused: boolean;
|
|
6
|
+
seeking: boolean;
|
|
7
|
+
}, props: React.ButtonHTMLAttributes<HTMLButtonElement>) => React.ReactNode;
|
|
8
|
+
shortcuts?: string[];
|
|
9
|
+
}): import("react").ReactNode;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type DurationLike } from "@liqvid/duration";
|
|
2
|
+
import { type ThumbData } from "./ThumbnailBox";
|
|
3
|
+
export type { ThumbData };
|
|
4
|
+
export interface RelativeSeekShortcut {
|
|
5
|
+
delta: DurationLike;
|
|
6
|
+
key: string;
|
|
7
|
+
}
|
|
8
|
+
export interface PercentageSeekShortcut {
|
|
9
|
+
key: string;
|
|
10
|
+
/**
|
|
11
|
+
* @min 0
|
|
12
|
+
* @max 1
|
|
13
|
+
*/
|
|
14
|
+
multiplier: number;
|
|
15
|
+
}
|
|
16
|
+
export interface ScrubberBarProps {
|
|
17
|
+
shortcuts?: {
|
|
18
|
+
relative?: RelativeSeekShortcut[];
|
|
19
|
+
percentage?: PercentageSeekShortcut[];
|
|
20
|
+
};
|
|
21
|
+
thumbs?: ThumbData;
|
|
22
|
+
}
|
|
23
|
+
export declare function ScrubberBar({ shortcuts, thumbs, ...props }: ScrubberBarProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { DurationLike } from "@liqvid/duration";
|
|
2
|
+
export interface ThumbData {
|
|
3
|
+
/**
|
|
4
|
+
* Number of columns per thumbnail sheet.
|
|
5
|
+
* @default 5
|
|
6
|
+
*/
|
|
7
|
+
cols?: number;
|
|
8
|
+
/**
|
|
9
|
+
* Number of rows per thumbnail sheet.
|
|
10
|
+
* @default 5
|
|
11
|
+
*/
|
|
12
|
+
rows?: number;
|
|
13
|
+
/**
|
|
14
|
+
* Width of individual thumbnails.
|
|
15
|
+
* @default 160
|
|
16
|
+
*/
|
|
17
|
+
width?: number;
|
|
18
|
+
/**
|
|
19
|
+
* Height of individual thumbnails.
|
|
20
|
+
* @default 100
|
|
21
|
+
*/
|
|
22
|
+
height?: number;
|
|
23
|
+
/**
|
|
24
|
+
* How many seconds between thumbnails.
|
|
25
|
+
* @default 4
|
|
26
|
+
*/
|
|
27
|
+
frequency?: number;
|
|
28
|
+
/** URL pattern for thumbnails. Must include "%s". */
|
|
29
|
+
path: string;
|
|
30
|
+
/** Points of interest in the video to highlight. */
|
|
31
|
+
highlights?: VideoHighlight[];
|
|
32
|
+
}
|
|
33
|
+
export interface ThumbnailBoxProps extends Omit<ThumbData, "highlights"> {
|
|
34
|
+
progress: number;
|
|
35
|
+
show: boolean;
|
|
36
|
+
title?: string;
|
|
37
|
+
}
|
|
38
|
+
export interface VideoHighlight {
|
|
39
|
+
time: DurationLike;
|
|
40
|
+
title: string;
|
|
41
|
+
}
|
|
42
|
+
export declare function ThumbnailBox({ cols, rows, frequency, path, progress, show, title, height, width, }: ThumbnailBoxProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function TimeDisplay(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export interface AdjustVolumeShortcut {
|
|
2
|
+
/** Keyboard sequence */
|
|
3
|
+
seq: string;
|
|
4
|
+
/**
|
|
5
|
+
* A value of 5 will increase the volume by 5%; a value of -10 will decrease the volume by 10%.
|
|
6
|
+
*/
|
|
7
|
+
delta: number;
|
|
8
|
+
}
|
|
9
|
+
export interface SetVolumeShortcut {
|
|
10
|
+
/** Keyboard sequence */
|
|
11
|
+
seq: string;
|
|
12
|
+
/** Value between 0 and 100 to set the volume to. */
|
|
13
|
+
value: number;
|
|
14
|
+
}
|
|
15
|
+
export type VolumeShortcut = AdjustVolumeShortcut | SetVolumeShortcut;
|
|
16
|
+
export interface VolumeSliderProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
17
|
+
className?: string;
|
|
18
|
+
render: (state: {
|
|
19
|
+
muted: boolean;
|
|
20
|
+
volume: number;
|
|
21
|
+
}, props: React.InputHTMLAttributes<HTMLInputElement>) => React.ReactNode;
|
|
22
|
+
shortcuts?: VolumeShortcut[];
|
|
23
|
+
}
|
|
24
|
+
/** Volume control */
|
|
25
|
+
export declare function VolumeSlider({ className, render, shortcuts, }: VolumeSliderProps): import("react").ReactNode;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { ColorSchemeToggle } from "./ColorSchemeToggle";
|
|
2
|
+
export { FullScreen } from "./FullScreen";
|
|
3
|
+
export { Mute, type MuteProps } from "./MuteButton";
|
|
4
|
+
export { PlayPause } from "./PlayPause";
|
|
5
|
+
export { type PercentageSeekShortcut, type RelativeSeekShortcut, ScrubberBar, type ScrubberBarProps, } from "./ScrubberBar";
|
|
6
|
+
export type { ThumbData, VideoHighlight } from "./ThumbnailBox";
|
|
7
|
+
export { TimeDisplay } from "./TimeDisplay";
|
|
8
|
+
export { type VolumeShortcut, VolumeSlider, type VolumeSliderProps, } from "./VolumeSlider";
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const fullscreenEnabled: boolean;
|
|
2
|
+
export declare const requestFullScreen: () => Promise<void>;
|
|
3
|
+
export declare const exitFullScreen: () => Promise<void>;
|
|
4
|
+
export declare const isFullScreen: () => boolean | undefined;
|
|
5
|
+
export declare function onFullScreenChange(callback: EventListener): void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Keymap } from "@liqvid/keymap";
|
|
2
|
+
export declare function bind(keymap: Keymap, seqs: string | string[] | undefined, callback: () => void): void;
|
|
3
|
+
export declare function unbind(keymap: Keymap, seqs: string | string[] | undefined, callback: () => void): void;
|
|
4
|
+
export declare function convertShortcuts(keys: string | string[] | undefined): string | undefined;
|
package/package.json
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@liqvid/controls",
|
|
3
|
+
"version": "1.0.0-alpha.0",
|
|
4
|
+
"description": "Controls for Liqvid",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": {
|
|
7
|
+
"import": "./dist/esm/index.js",
|
|
8
|
+
"types": "./dist/types/index.d.ts"
|
|
9
|
+
}
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist/*"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/liqvidjs/liqvid.git"
|
|
17
|
+
},
|
|
18
|
+
"author": "Yuri Sulyma <yuri@liqvidjs.org>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"bugs": {
|
|
21
|
+
"url": "https://github.com/liqvidjs/liqvid/issues"
|
|
22
|
+
},
|
|
23
|
+
"homepage": "https://github.com/liqvidjs/liqvid/tree/main/packages/controls#readme",
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"classnames": "^2.5.1",
|
|
26
|
+
"@liqvid/player": "^1.0.0-alpha.0",
|
|
27
|
+
"@liqvid/utils": "^2.0.0-alpha.0",
|
|
28
|
+
"@liqvid/ssr": "^0.0.2",
|
|
29
|
+
"@liqvid/keymap": "^2.0.0-alpha.0",
|
|
30
|
+
"@liqvid/color-scheme": "^1.0.0-alpha.0",
|
|
31
|
+
"@liqvid/playback": "^2.0.0-alpha.0",
|
|
32
|
+
"@liqvid/duration": "^1.3.0"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@biomejs/biome": "2.4.4",
|
|
36
|
+
"@types/react": "^19",
|
|
37
|
+
"typescript": "^5.9"
|
|
38
|
+
},
|
|
39
|
+
"peerDependencies": {
|
|
40
|
+
"react": ">=18"
|
|
41
|
+
},
|
|
42
|
+
"type": "module",
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "pnpm build:clean && mkdir dist && pnpm build:js && pnpm build:postclean",
|
|
45
|
+
"build:clean": "rm -rf dist",
|
|
46
|
+
"build:js": "tsc",
|
|
47
|
+
"build:postclean": "rm dist/tsconfig.tsbuildinfo",
|
|
48
|
+
"lint": "biome check --fix",
|
|
49
|
+
"watch": "tsc --watch"
|
|
50
|
+
}
|
|
51
|
+
}
|