@videojs/react 0.1.0-preview.8 → 10.0.0-alpha.3
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 +1 -1
- package/dist/default/_virtual/_rolldown/runtime.js +18 -0
- package/dist/default/index.js +22 -0
- package/dist/default/media/audio.js +22 -0
- package/dist/default/media/audio.js.map +1 -0
- package/dist/default/media/background-video/index.js +28 -0
- package/dist/default/media/background-video/index.js.map +1 -0
- package/dist/default/media/hls-video/index.js +25 -0
- package/dist/default/media/hls-video/index.js.map +1 -0
- package/dist/default/media/video.js +22 -0
- package/dist/default/media/video.js.map +1 -0
- package/dist/default/player/context.js +55 -0
- package/dist/default/player/context.js.map +1 -0
- package/dist/default/player/create-player.js +38 -0
- package/dist/default/player/create-player.js.map +1 -0
- package/dist/default/presets/audio/index.js +5 -0
- package/dist/default/presets/audio/minimal-skin.css +3 -0
- package/dist/default/presets/audio/minimal-skin.js +11 -0
- package/dist/default/presets/audio/minimal-skin.js.map +1 -0
- package/dist/default/presets/audio/skin.css +3 -0
- package/dist/default/presets/audio/skin.js +11 -0
- package/dist/default/presets/audio/skin.js.map +1 -0
- package/dist/default/presets/background/index.js +4 -0
- package/dist/default/presets/background/skin.css +3 -0
- package/dist/default/presets/background/skin.js +11 -0
- package/dist/default/presets/background/skin.js.map +1 -0
- package/dist/default/presets/video/index.js +7 -0
- package/dist/default/presets/video/minimal-skin.css +637 -0
- package/dist/default/presets/video/minimal-skin.js +234 -0
- package/dist/default/presets/video/minimal-skin.js.map +1 -0
- package/dist/default/presets/video/minimal-skin.tailwind.js +231 -0
- package/dist/default/presets/video/minimal-skin.tailwind.js.map +1 -0
- package/dist/default/presets/video/skin.css +638 -0
- package/dist/default/presets/video/skin.js +223 -0
- package/dist/default/presets/video/skin.js.map +1 -0
- package/dist/default/presets/video/skin.tailwind.js +222 -0
- package/dist/default/presets/video/skin.tailwind.js.map +1 -0
- package/dist/default/ui/buffering-indicator/buffering-indicator.js +50 -0
- package/dist/default/ui/buffering-indicator/buffering-indicator.js.map +1 -0
- package/dist/default/ui/buffering-indicator/index.js +3 -0
- package/dist/default/ui/captions-button/captions-button.js +51 -0
- package/dist/default/ui/captions-button/captions-button.js.map +1 -0
- package/dist/default/ui/captions-button/index.js +3 -0
- package/dist/default/ui/controls/controls-group.js +27 -0
- package/dist/default/ui/controls/controls-group.js.map +1 -0
- package/dist/default/ui/controls/controls-root.js +31 -0
- package/dist/default/ui/controls/controls-root.js.map +1 -0
- package/dist/default/ui/controls/index.js +3 -0
- package/dist/default/ui/controls/index.parts.js +13 -0
- package/dist/default/ui/controls/index.parts.js.map +1 -0
- package/dist/default/ui/error-dialog/error-dialog.js +54 -0
- package/dist/default/ui/error-dialog/error-dialog.js.map +1 -0
- package/dist/default/ui/error-dialog/index.js +3 -0
- package/dist/default/ui/fullscreen-button/fullscreen-button.js +44 -0
- package/dist/default/ui/fullscreen-button/fullscreen-button.js.map +1 -0
- package/dist/default/ui/fullscreen-button/index.js +3 -0
- package/dist/default/ui/hooks/use-button.js +44 -0
- package/dist/default/ui/hooks/use-button.js.map +1 -0
- package/dist/default/ui/mute-button/index.js +3 -0
- package/dist/default/ui/mute-button/mute-button.js +47 -0
- package/dist/default/ui/mute-button/mute-button.js.map +1 -0
- package/dist/default/ui/pip-button/index.js +3 -0
- package/dist/default/ui/pip-button/pip-button.js +44 -0
- package/dist/default/ui/pip-button/pip-button.js.map +1 -0
- package/dist/default/ui/play-button/index.js +3 -0
- package/dist/default/ui/play-button/play-button.js +60 -0
- package/dist/default/ui/play-button/play-button.js.map +1 -0
- package/dist/default/ui/poster/index.js +3 -0
- package/dist/default/ui/poster/poster.js +43 -0
- package/dist/default/ui/poster/poster.js.map +1 -0
- package/dist/default/ui/seek-button/index.js +3 -0
- package/dist/default/ui/seek-button/seek-button.js +62 -0
- package/dist/default/ui/seek-button/seek-button.js.map +1 -0
- package/dist/default/ui/time/index.js +3 -0
- package/dist/default/ui/time/index.parts.js +15 -0
- package/dist/default/ui/time/index.parts.js.map +1 -0
- package/dist/default/ui/time/time-group.js +34 -0
- package/dist/default/ui/time/time-group.js.map +1 -0
- package/dist/default/ui/time/time-separator.js +34 -0
- package/dist/default/ui/time/time-separator.js.map +1 -0
- package/dist/default/ui/time/time-value.js +54 -0
- package/dist/default/ui/time/time-value.js.map +1 -0
- package/dist/default/utils/attach-media-element.js +12 -0
- package/dist/default/utils/attach-media-element.js.map +1 -0
- package/dist/default/utils/media-props.js +11 -0
- package/dist/default/utils/media-props.js.map +1 -0
- package/dist/default/utils/merge-props.js +85 -0
- package/dist/default/utils/merge-props.js.map +1 -0
- package/dist/default/utils/use-composed-refs.js +57 -0
- package/dist/default/utils/use-composed-refs.js.map +1 -0
- package/dist/default/utils/use-render.js +71 -0
- package/dist/default/utils/use-render.js.map +1 -0
- package/dist/dev/_virtual/_rolldown/runtime.js +18 -0
- package/dist/dev/index.d.ts +23 -0
- package/dist/dev/index.js +22 -0
- package/dist/dev/media/audio.d.ts +12 -0
- package/dist/dev/media/audio.d.ts.map +1 -0
- package/dist/dev/media/audio.js +22 -0
- package/dist/dev/media/audio.js.map +1 -0
- package/dist/dev/media/background-video/index.d.ts +12 -0
- package/dist/dev/media/background-video/index.d.ts.map +1 -0
- package/dist/dev/media/background-video/index.js +28 -0
- package/dist/dev/media/background-video/index.js.map +1 -0
- package/dist/dev/media/hls-video/index.d.ts +11 -0
- package/dist/dev/media/hls-video/index.d.ts.map +1 -0
- package/dist/dev/media/hls-video/index.js +25 -0
- package/dist/dev/media/hls-video/index.js.map +1 -0
- package/dist/dev/media/video.d.ts +12 -0
- package/dist/dev/media/video.d.ts.map +1 -0
- package/dist/dev/media/video.js +22 -0
- package/dist/dev/media/video.js.map +1 -0
- package/dist/dev/player/context.d.ts +40 -0
- package/dist/dev/player/context.d.ts.map +1 -0
- package/dist/dev/player/context.js +55 -0
- package/dist/dev/player/context.js.map +1 -0
- package/dist/dev/player/create-player.d.ts +47 -0
- package/dist/dev/player/create-player.d.ts.map +1 -0
- package/dist/dev/player/create-player.js +39 -0
- package/dist/dev/player/create-player.js.map +1 -0
- package/dist/dev/presets/audio/index.d.ts +4 -0
- package/dist/dev/presets/audio/index.js +5 -0
- package/dist/dev/presets/audio/minimal-skin.css +3 -0
- package/dist/dev/presets/audio/minimal-skin.d.ts +9 -0
- package/dist/dev/presets/audio/minimal-skin.d.ts.map +1 -0
- package/dist/dev/presets/audio/minimal-skin.js +11 -0
- package/dist/dev/presets/audio/minimal-skin.js.map +1 -0
- package/dist/dev/presets/audio/skin.css +3 -0
- package/dist/dev/presets/audio/skin.d.ts +9 -0
- package/dist/dev/presets/audio/skin.d.ts.map +1 -0
- package/dist/dev/presets/audio/skin.js +11 -0
- package/dist/dev/presets/audio/skin.js.map +1 -0
- package/dist/dev/presets/background/index.d.ts +3 -0
- package/dist/dev/presets/background/index.js +4 -0
- package/dist/dev/presets/background/skin.css +3 -0
- package/dist/dev/presets/background/skin.d.ts +9 -0
- package/dist/dev/presets/background/skin.d.ts.map +1 -0
- package/dist/dev/presets/background/skin.js +11 -0
- package/dist/dev/presets/background/skin.js.map +1 -0
- package/dist/dev/presets/types.d.ts +10 -0
- package/dist/dev/presets/types.d.ts.map +1 -0
- package/dist/dev/presets/video/index.d.ts +6 -0
- package/dist/dev/presets/video/index.js +7 -0
- package/dist/dev/presets/video/minimal-skin.css +637 -0
- package/dist/dev/presets/video/minimal-skin.d.ts +9 -0
- package/dist/dev/presets/video/minimal-skin.d.ts.map +1 -0
- package/dist/dev/presets/video/minimal-skin.js +234 -0
- package/dist/dev/presets/video/minimal-skin.js.map +1 -0
- package/dist/dev/presets/video/minimal-skin.tailwind.d.ts +8 -0
- package/dist/dev/presets/video/minimal-skin.tailwind.d.ts.map +1 -0
- package/dist/dev/presets/video/minimal-skin.tailwind.js +231 -0
- package/dist/dev/presets/video/minimal-skin.tailwind.js.map +1 -0
- package/dist/dev/presets/video/skin.css +638 -0
- package/dist/dev/presets/video/skin.d.ts +9 -0
- package/dist/dev/presets/video/skin.d.ts.map +1 -0
- package/dist/dev/presets/video/skin.js +223 -0
- package/dist/dev/presets/video/skin.js.map +1 -0
- package/dist/dev/presets/video/skin.tailwind.d.ts +8 -0
- package/dist/dev/presets/video/skin.tailwind.d.ts.map +1 -0
- package/dist/dev/presets/video/skin.tailwind.js +222 -0
- package/dist/dev/presets/video/skin.tailwind.js.map +1 -0
- package/dist/dev/ui/buffering-indicator/buffering-indicator.d.ts +32 -0
- package/dist/dev/ui/buffering-indicator/buffering-indicator.d.ts.map +1 -0
- package/dist/dev/ui/buffering-indicator/buffering-indicator.js +53 -0
- package/dist/dev/ui/buffering-indicator/buffering-indicator.js.map +1 -0
- package/dist/dev/ui/buffering-indicator/index.d.ts +2 -0
- package/dist/dev/ui/buffering-indicator/index.js +3 -0
- package/dist/dev/ui/captions-button/captions-button.d.ts +36 -0
- package/dist/dev/ui/captions-button/captions-button.d.ts.map +1 -0
- package/dist/dev/ui/captions-button/captions-button.js +51 -0
- package/dist/dev/ui/captions-button/captions-button.js.map +1 -0
- package/dist/dev/ui/captions-button/index.d.ts +2 -0
- package/dist/dev/ui/captions-button/index.js +3 -0
- package/dist/dev/ui/controls/controls-group.d.ts +17 -0
- package/dist/dev/ui/controls/controls-group.d.ts.map +1 -0
- package/dist/dev/ui/controls/controls-group.js +27 -0
- package/dist/dev/ui/controls/controls-group.js.map +1 -0
- package/dist/dev/ui/controls/controls-root.d.ts +18 -0
- package/dist/dev/ui/controls/controls-root.d.ts.map +1 -0
- package/dist/dev/ui/controls/controls-root.js +34 -0
- package/dist/dev/ui/controls/controls-root.js.map +1 -0
- package/dist/dev/ui/controls/index.d.ts +2 -0
- package/dist/dev/ui/controls/index.js +3 -0
- package/dist/dev/ui/controls/index.parts.d.ts +10 -0
- package/dist/dev/ui/controls/index.parts.d.ts.map +1 -0
- package/dist/dev/ui/controls/index.parts.js +13 -0
- package/dist/dev/ui/controls/index.parts.js.map +1 -0
- package/dist/dev/ui/error-dialog/error-dialog.d.ts +35 -0
- package/dist/dev/ui/error-dialog/error-dialog.d.ts.map +1 -0
- package/dist/dev/ui/error-dialog/error-dialog.js +54 -0
- package/dist/dev/ui/error-dialog/error-dialog.js.map +1 -0
- package/dist/dev/ui/error-dialog/index.d.ts +2 -0
- package/dist/dev/ui/error-dialog/index.js +3 -0
- package/dist/dev/ui/fullscreen-button/fullscreen-button.d.ts +14 -0
- package/dist/dev/ui/fullscreen-button/fullscreen-button.d.ts.map +1 -0
- package/dist/dev/ui/fullscreen-button/fullscreen-button.js +47 -0
- package/dist/dev/ui/fullscreen-button/fullscreen-button.js.map +1 -0
- package/dist/dev/ui/fullscreen-button/index.d.ts +2 -0
- package/dist/dev/ui/fullscreen-button/index.js +3 -0
- package/dist/dev/ui/hooks/use-button.d.ts +40 -0
- package/dist/dev/ui/hooks/use-button.d.ts.map +1 -0
- package/dist/dev/ui/hooks/use-button.js +46 -0
- package/dist/dev/ui/hooks/use-button.js.map +1 -0
- package/dist/dev/ui/mute-button/index.d.ts +2 -0
- package/dist/dev/ui/mute-button/index.js +3 -0
- package/dist/dev/ui/mute-button/mute-button.d.ts +17 -0
- package/dist/dev/ui/mute-button/mute-button.d.ts.map +1 -0
- package/dist/dev/ui/mute-button/mute-button.js +50 -0
- package/dist/dev/ui/mute-button/mute-button.js.map +1 -0
- package/dist/dev/ui/pip-button/index.d.ts +2 -0
- package/dist/dev/ui/pip-button/index.js +3 -0
- package/dist/dev/ui/pip-button/pip-button.d.ts +14 -0
- package/dist/dev/ui/pip-button/pip-button.d.ts.map +1 -0
- package/dist/dev/ui/pip-button/pip-button.js +47 -0
- package/dist/dev/ui/pip-button/pip-button.js.map +1 -0
- package/dist/dev/ui/play-button/index.d.ts +2 -0
- package/dist/dev/ui/play-button/index.js +3 -0
- package/dist/dev/ui/play-button/play-button.d.ts +30 -0
- package/dist/dev/ui/play-button/play-button.d.ts.map +1 -0
- package/dist/dev/ui/play-button/play-button.js +63 -0
- package/dist/dev/ui/play-button/play-button.js.map +1 -0
- package/dist/dev/ui/poster/index.d.ts +2 -0
- package/dist/dev/ui/poster/index.js +3 -0
- package/dist/dev/ui/poster/poster.d.ts +28 -0
- package/dist/dev/ui/poster/poster.d.ts.map +1 -0
- package/dist/dev/ui/poster/poster.js +46 -0
- package/dist/dev/ui/poster/poster.js.map +1 -0
- package/dist/dev/ui/seek-button/index.d.ts +2 -0
- package/dist/dev/ui/seek-button/index.js +3 -0
- package/dist/dev/ui/seek-button/seek-button.d.ts +31 -0
- package/dist/dev/ui/seek-button/seek-button.d.ts.map +1 -0
- package/dist/dev/ui/seek-button/seek-button.js +65 -0
- package/dist/dev/ui/seek-button/seek-button.js.map +1 -0
- package/dist/dev/ui/time/index.d.ts +2 -0
- package/dist/dev/ui/time/index.js +3 -0
- package/dist/dev/ui/time/index.parts.d.ts +11 -0
- package/dist/dev/ui/time/index.parts.d.ts.map +1 -0
- package/dist/dev/ui/time/index.parts.js +15 -0
- package/dist/dev/ui/time/index.parts.js.map +1 -0
- package/dist/dev/ui/time/time-group.d.ts +29 -0
- package/dist/dev/ui/time/time-group.d.ts.map +1 -0
- package/dist/dev/ui/time/time-group.js +34 -0
- package/dist/dev/ui/time/time-group.js.map +1 -0
- package/dist/dev/ui/time/time-separator.d.ts +26 -0
- package/dist/dev/ui/time/time-separator.d.ts.map +1 -0
- package/dist/dev/ui/time/time-separator.js +34 -0
- package/dist/dev/ui/time/time-separator.js.map +1 -0
- package/dist/dev/ui/time/time-value.d.ts +24 -0
- package/dist/dev/ui/time/time-value.d.ts.map +1 -0
- package/dist/dev/ui/time/time-value.js +57 -0
- package/dist/dev/ui/time/time-value.js.map +1 -0
- package/dist/dev/utils/attach-media-element.js +12 -0
- package/dist/dev/utils/attach-media-element.js.map +1 -0
- package/dist/dev/utils/media-props.js +11 -0
- package/dist/dev/utils/media-props.js.map +1 -0
- package/dist/dev/utils/merge-props.d.ts +26 -0
- package/dist/dev/utils/merge-props.d.ts.map +1 -0
- package/dist/dev/utils/merge-props.js +85 -0
- package/dist/dev/utils/merge-props.js.map +1 -0
- package/dist/dev/utils/types.d.ts +27 -0
- package/dist/dev/utils/types.d.ts.map +1 -0
- package/dist/dev/utils/use-composed-refs.js +57 -0
- package/dist/dev/utils/use-composed-refs.js.map +1 -0
- package/dist/dev/utils/use-render.d.ts +45 -0
- package/dist/dev/utils/use-render.d.ts.map +1 -0
- package/dist/dev/utils/use-render.js +71 -0
- package/dist/dev/utils/use-render.js.map +1 -0
- package/package.json +58 -53
- package/dist/FrostedSkin-t8edr5LV.d.ts +0 -13
- package/dist/FrostedSkin-t8edr5LV.d.ts.map +0 -1
- package/dist/MinimalSkin-DzHkJgW-.d.ts +0 -13
- package/dist/MinimalSkin-DzHkJgW-.d.ts.map +0 -1
- package/dist/VolumeSlider-DmlupkvF.js +0 -1042
- package/dist/VolumeSlider-DmlupkvF.js.map +0 -1
- package/dist/frosted-0lXuIgHt.js +0 -156
- package/dist/frosted-0lXuIgHt.js.map +0 -1
- package/dist/icons-BqfV81R8.js +0 -316
- package/dist/icons-BqfV81R8.js.map +0 -1
- package/dist/icons.d.ts +0 -71
- package/dist/icons.d.ts.map +0 -1
- package/dist/icons.js +0 -3
- package/dist/index-CM70WSkA.d.ts +0 -36
- package/dist/index-CM70WSkA.d.ts.map +0 -1
- package/dist/index.d.ts +0 -312
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -89
- package/dist/index.js.map +0 -1
- package/dist/minimal-B-R9aRNe.js +0 -162
- package/dist/minimal-B-R9aRNe.js.map +0 -1
- package/dist/skins/frosted.css +0 -4
- package/dist/skins/frosted.d.ts +0 -2
- package/dist/skins/frosted.js +0 -9
- package/dist/skins/minimal.css +0 -4
- package/dist/skins/minimal.d.ts +0 -2
- package/dist/skins/minimal.js +0 -9
- package/dist/store-hGO5HE2A.js +0 -124
- package/dist/store-hGO5HE2A.js.map +0 -1
- package/dist/store.d.ts +0 -2
- package/dist/store.js +0 -6
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { Container } from "../../player/context.js";
|
|
2
|
+
import { BufferingIndicator } from "../../ui/buffering-indicator/buffering-indicator.js";
|
|
3
|
+
import { ControlsRoot } from "../../ui/controls/controls-root.js";
|
|
4
|
+
import { FullscreenButton } from "../../ui/fullscreen-button/fullscreen-button.js";
|
|
5
|
+
import { MuteButton } from "../../ui/mute-button/mute-button.js";
|
|
6
|
+
import { PiPButton } from "../../ui/pip-button/pip-button.js";
|
|
7
|
+
import { PlayButton } from "../../ui/play-button/play-button.js";
|
|
8
|
+
import { SeekButton } from "../../ui/seek-button/seek-button.js";
|
|
9
|
+
import { Group } from "../../ui/time/time-group.js";
|
|
10
|
+
import { Value } from "../../ui/time/time-value.js";
|
|
11
|
+
import { CaptionsButton } from "../../ui/captions-button/captions-button.js";
|
|
12
|
+
import { ErrorDialog } from "../../ui/error-dialog/error-dialog.js";
|
|
13
|
+
import { forwardRef } from "react";
|
|
14
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
import { cn } from "@videojs/utils/style";
|
|
16
|
+
import { CaptionsOffIcon, CaptionsOnIcon, FullscreenEnterIcon, FullscreenExitIcon, PauseIcon, PipIcon, PlayIcon, RestartIcon, SeekIcon, SpinnerIcon, VolumeHighIcon, VolumeLowIcon, VolumeOffIcon } from "@videojs/icons/react";
|
|
17
|
+
|
|
18
|
+
//#region src/presets/video/skin.tsx
|
|
19
|
+
const SEEK_TIME = 10;
|
|
20
|
+
const Button = forwardRef(function Button({ className, ...props }, ref) {
|
|
21
|
+
return /* @__PURE__ */ jsx("button", {
|
|
22
|
+
ref,
|
|
23
|
+
type: "button",
|
|
24
|
+
className: cn("media-button", className),
|
|
25
|
+
...props
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
function PlayButtonIcon({ state, className, ...rest }) {
|
|
29
|
+
const { ended, paused } = state;
|
|
30
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
31
|
+
/* @__PURE__ */ jsx(RestartIcon, {
|
|
32
|
+
...rest,
|
|
33
|
+
className: cn(className, { "media-icon--hidden": !ended })
|
|
34
|
+
}),
|
|
35
|
+
/* @__PURE__ */ jsx(PlayIcon, {
|
|
36
|
+
...rest,
|
|
37
|
+
className: cn(className, { "media-icon--hidden": ended || !paused })
|
|
38
|
+
}),
|
|
39
|
+
/* @__PURE__ */ jsx(PauseIcon, {
|
|
40
|
+
...rest,
|
|
41
|
+
className: cn(className, { "media-icon--hidden": paused })
|
|
42
|
+
})
|
|
43
|
+
] });
|
|
44
|
+
}
|
|
45
|
+
function MuteButtonIcon({ state, className, ...rest }) {
|
|
46
|
+
const { muted, volumeLevel } = state;
|
|
47
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
48
|
+
/* @__PURE__ */ jsx(VolumeOffIcon, {
|
|
49
|
+
...rest,
|
|
50
|
+
className: cn(className, { "media-icon--hidden": !muted })
|
|
51
|
+
}),
|
|
52
|
+
/* @__PURE__ */ jsx(VolumeLowIcon, {
|
|
53
|
+
...rest,
|
|
54
|
+
className: cn(className, { "media-icon--hidden": muted || volumeLevel !== "low" })
|
|
55
|
+
}),
|
|
56
|
+
/* @__PURE__ */ jsx(VolumeHighIcon, {
|
|
57
|
+
...rest,
|
|
58
|
+
className: cn(className, { "media-icon--hidden": muted || volumeLevel === "low" })
|
|
59
|
+
})
|
|
60
|
+
] });
|
|
61
|
+
}
|
|
62
|
+
function CaptionsButtonIcon({ state, className, ...rest }) {
|
|
63
|
+
const { active } = state;
|
|
64
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(CaptionsOffIcon, {
|
|
65
|
+
...rest,
|
|
66
|
+
className: cn(className, { "media-icon--hidden": active })
|
|
67
|
+
}), /* @__PURE__ */ jsx(CaptionsOnIcon, {
|
|
68
|
+
...rest,
|
|
69
|
+
className: cn(className, { "media-icon--hidden": !active })
|
|
70
|
+
})] });
|
|
71
|
+
}
|
|
72
|
+
function FullscreenButtonIcon({ state, className, ...rest }) {
|
|
73
|
+
const { fullscreen } = state;
|
|
74
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(FullscreenExitIcon, {
|
|
75
|
+
...rest,
|
|
76
|
+
className: cn(className, { "media-icon--hidden": !fullscreen })
|
|
77
|
+
}), /* @__PURE__ */ jsx(FullscreenEnterIcon, {
|
|
78
|
+
...rest,
|
|
79
|
+
className: cn(className, { "media-icon--hidden": fullscreen })
|
|
80
|
+
})] });
|
|
81
|
+
}
|
|
82
|
+
function VideoSkin(props) {
|
|
83
|
+
const { children, className, ...rest } = props;
|
|
84
|
+
return /* @__PURE__ */ jsxs(Container, {
|
|
85
|
+
className: cn("media-default-skin", className),
|
|
86
|
+
...rest,
|
|
87
|
+
children: [
|
|
88
|
+
children,
|
|
89
|
+
/* @__PURE__ */ jsx(BufferingIndicator, { render: (props, state) => state.visible ? /* @__PURE__ */ jsx("div", {
|
|
90
|
+
...props,
|
|
91
|
+
className: "media-buffering-indicator",
|
|
92
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
93
|
+
className: "media-surface",
|
|
94
|
+
children: /* @__PURE__ */ jsx(SpinnerIcon, { className: "media-icon" })
|
|
95
|
+
})
|
|
96
|
+
}) : null }),
|
|
97
|
+
/* @__PURE__ */ jsx(ErrorDialog, {
|
|
98
|
+
"aria-labelledby": "media-error-title",
|
|
99
|
+
"aria-describedby": "media-error-description",
|
|
100
|
+
render: (props, { onDismiss }) => /* @__PURE__ */ jsx("div", {
|
|
101
|
+
...props,
|
|
102
|
+
className: "media-error",
|
|
103
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
104
|
+
className: "media-error__dialog media-surface",
|
|
105
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
106
|
+
className: "media-error__content",
|
|
107
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
108
|
+
id: "media-error-title",
|
|
109
|
+
className: "media-error__title",
|
|
110
|
+
children: "Something went wrong."
|
|
111
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
112
|
+
id: "media-error-description",
|
|
113
|
+
className: "media-error__description",
|
|
114
|
+
children: "An error occurred while trying to play the video. Please try again."
|
|
115
|
+
})]
|
|
116
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
117
|
+
className: "media-error__actions",
|
|
118
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
119
|
+
onClick: onDismiss,
|
|
120
|
+
children: "OK"
|
|
121
|
+
})
|
|
122
|
+
})]
|
|
123
|
+
})
|
|
124
|
+
})
|
|
125
|
+
}),
|
|
126
|
+
/* @__PURE__ */ jsxs(ControlsRoot, {
|
|
127
|
+
className: "media-surface media-controls",
|
|
128
|
+
children: [
|
|
129
|
+
/* @__PURE__ */ jsx(PlayButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
130
|
+
...props,
|
|
131
|
+
className: "media-button--icon",
|
|
132
|
+
children: /* @__PURE__ */ jsx(PlayButtonIcon, {
|
|
133
|
+
state,
|
|
134
|
+
className: "media-icon"
|
|
135
|
+
})
|
|
136
|
+
}) }),
|
|
137
|
+
/* @__PURE__ */ jsx(SeekButton, {
|
|
138
|
+
seconds: -SEEK_TIME,
|
|
139
|
+
render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
140
|
+
...props,
|
|
141
|
+
className: "media-button--icon media-button--seek",
|
|
142
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
143
|
+
className: "media-icon__container",
|
|
144
|
+
children: [/* @__PURE__ */ jsx(SeekIcon, { className: "media-icon media-icon--seek media-icon--flipped" }), /* @__PURE__ */ jsx("span", {
|
|
145
|
+
className: "media-icon__label",
|
|
146
|
+
children: SEEK_TIME
|
|
147
|
+
})]
|
|
148
|
+
})
|
|
149
|
+
})
|
|
150
|
+
}),
|
|
151
|
+
/* @__PURE__ */ jsx(SeekButton, {
|
|
152
|
+
seconds: SEEK_TIME,
|
|
153
|
+
render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
154
|
+
...props,
|
|
155
|
+
className: "media-button--icon media-button--seek",
|
|
156
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
157
|
+
className: "media-icon__container",
|
|
158
|
+
children: [/* @__PURE__ */ jsx(SeekIcon, { className: "media-icon media-icon--seek" }), /* @__PURE__ */ jsx("span", {
|
|
159
|
+
className: "media-icon__label",
|
|
160
|
+
children: SEEK_TIME
|
|
161
|
+
})]
|
|
162
|
+
})
|
|
163
|
+
})
|
|
164
|
+
}),
|
|
165
|
+
/* @__PURE__ */ jsxs(Group, {
|
|
166
|
+
className: "media-time",
|
|
167
|
+
children: [
|
|
168
|
+
/* @__PURE__ */ jsx(Value, {
|
|
169
|
+
type: "current",
|
|
170
|
+
className: "media-time__value"
|
|
171
|
+
}),
|
|
172
|
+
/* @__PURE__ */ jsx("div", {
|
|
173
|
+
className: "media-slider",
|
|
174
|
+
style: {
|
|
175
|
+
height: "4px",
|
|
176
|
+
background: "oklab(1 0 0 / 0.2)"
|
|
177
|
+
}
|
|
178
|
+
}),
|
|
179
|
+
/* @__PURE__ */ jsx(Value, {
|
|
180
|
+
type: "duration",
|
|
181
|
+
className: "media-time__value"
|
|
182
|
+
})
|
|
183
|
+
]
|
|
184
|
+
}),
|
|
185
|
+
/* @__PURE__ */ jsx(MuteButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
186
|
+
...props,
|
|
187
|
+
className: "media-button--icon",
|
|
188
|
+
children: /* @__PURE__ */ jsx(MuteButtonIcon, {
|
|
189
|
+
state,
|
|
190
|
+
className: "media-icon"
|
|
191
|
+
})
|
|
192
|
+
}) }),
|
|
193
|
+
/* @__PURE__ */ jsx(CaptionsButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
194
|
+
...props,
|
|
195
|
+
className: "media-button--icon",
|
|
196
|
+
children: /* @__PURE__ */ jsx(CaptionsButtonIcon, {
|
|
197
|
+
state,
|
|
198
|
+
className: "media-icon"
|
|
199
|
+
})
|
|
200
|
+
}) }),
|
|
201
|
+
/* @__PURE__ */ jsx(PiPButton, { render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
202
|
+
...props,
|
|
203
|
+
className: "media-button--icon",
|
|
204
|
+
children: /* @__PURE__ */ jsx(PipIcon, { className: "media-icon" })
|
|
205
|
+
}) }),
|
|
206
|
+
/* @__PURE__ */ jsx(FullscreenButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
207
|
+
...props,
|
|
208
|
+
className: "media-button--icon",
|
|
209
|
+
children: /* @__PURE__ */ jsx(FullscreenButtonIcon, {
|
|
210
|
+
state,
|
|
211
|
+
className: "media-icon"
|
|
212
|
+
})
|
|
213
|
+
}) })
|
|
214
|
+
]
|
|
215
|
+
}),
|
|
216
|
+
/* @__PURE__ */ jsx("div", { className: "media-overlay" })
|
|
217
|
+
]
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
//#endregion
|
|
222
|
+
export { VideoSkin };
|
|
223
|
+
//# sourceMappingURL=skin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skin.js","names":["Controls.Root","Time.Group","Time.Value"],"sources":["../../../../src/presets/video/skin.tsx"],"sourcesContent":["import type { FullscreenButtonState, MuteButtonState, PlayButtonState } from '@videojs/core';\nimport {\n CaptionsOffIcon,\n CaptionsOnIcon,\n FullscreenEnterIcon,\n FullscreenExitIcon,\n PauseIcon,\n PipIcon,\n PlayIcon,\n RestartIcon,\n SeekIcon,\n SpinnerIcon,\n VolumeHighIcon,\n VolumeLowIcon,\n VolumeOffIcon,\n} from '@videojs/icons/react';\nimport { cn } from '@videojs/utils/style';\nimport { type ComponentProps, forwardRef, type ReactNode } from 'react';\nimport { Container } from '@/player/context';\nimport { BufferingIndicator } from '@/ui/buffering-indicator';\nimport { CaptionsButton, type CaptionsButtonState } from '@/ui/captions-button';\nimport { Controls } from '@/ui/controls';\nimport { ErrorDialog } from '@/ui/error-dialog';\nimport { FullscreenButton } from '@/ui/fullscreen-button';\nimport { MuteButton } from '@/ui/mute-button';\nimport { PiPButton } from '@/ui/pip-button';\nimport { PlayButton } from '@/ui/play-button';\nimport { SeekButton } from '@/ui/seek-button';\nimport { Time } from '@/ui/time';\nimport type { BaseSkinProps } from '../types';\n\nconst SEEK_TIME = 10;\n\nexport type VideoSkinProps = BaseSkinProps;\n\nconst Button = forwardRef<HTMLButtonElement, ComponentProps<'button'>>(function Button({ className, ...props }, ref) {\n return <button ref={ref} type=\"button\" className={cn('media-button', className)} {...props} />;\n});\n\nfunction PlayButtonIcon({ state, className, ...rest }: { state: PlayButtonState } & ComponentProps<'svg'>) {\n const { ended, paused } = state;\n return (\n <>\n <RestartIcon {...rest} className={cn(className, { 'media-icon--hidden': !ended })} />\n <PlayIcon {...rest} className={cn(className, { 'media-icon--hidden': ended || !paused })} />\n <PauseIcon {...rest} className={cn(className, { 'media-icon--hidden': paused })} />\n </>\n );\n}\n\nfunction MuteButtonIcon({ state, className, ...rest }: { state: MuteButtonState } & ComponentProps<'svg'>) {\n const { muted, volumeLevel } = state;\n return (\n <>\n <VolumeOffIcon {...rest} className={cn(className, { 'media-icon--hidden': !muted })} />\n <VolumeLowIcon {...rest} className={cn(className, { 'media-icon--hidden': muted || volumeLevel !== 'low' })} />\n <VolumeHighIcon {...rest} className={cn(className, { 'media-icon--hidden': muted || volumeLevel === 'low' })} />\n </>\n );\n}\n\nfunction CaptionsButtonIcon({ state, className, ...rest }: { state: CaptionsButtonState } & ComponentProps<'svg'>) {\n const { active } = state;\n return (\n <>\n <CaptionsOffIcon {...rest} className={cn(className, { 'media-icon--hidden': active })} />\n <CaptionsOnIcon {...rest} className={cn(className, { 'media-icon--hidden': !active })} />\n </>\n );\n}\n\nfunction FullscreenButtonIcon({ state, className, ...rest }: { state: FullscreenButtonState } & ComponentProps<'svg'>) {\n const { fullscreen } = state;\n return (\n <>\n <FullscreenExitIcon {...rest} className={cn(className, { 'media-icon--hidden': !fullscreen })} />\n <FullscreenEnterIcon {...rest} className={cn(className, { 'media-icon--hidden': fullscreen })} />\n </>\n );\n}\n\nexport function VideoSkin(props: VideoSkinProps): ReactNode {\n const { children, className, ...rest } = props;\n\n return (\n <Container className={cn('media-default-skin', className)} {...rest}>\n {children}\n\n <BufferingIndicator\n render={(props, state) =>\n state.visible ? (\n <div {...props} className=\"media-buffering-indicator\">\n <div className=\"media-surface\">\n <SpinnerIcon className=\"media-icon\" />\n </div>\n </div>\n ) : null\n }\n />\n\n <ErrorDialog\n aria-labelledby=\"media-error-title\"\n aria-describedby=\"media-error-description\"\n render={(props, { onDismiss }) => (\n <div {...props} className=\"media-error\">\n <div className=\"media-error__dialog media-surface\">\n <div className=\"media-error__content\">\n <p id=\"media-error-title\" className=\"media-error__title\">\n Something went wrong.\n </p>\n <p id=\"media-error-description\" className=\"media-error__description\">\n An error occurred while trying to play the video. Please try again.\n </p>\n </div>\n <div className=\"media-error__actions\">\n <Button onClick={onDismiss}>OK</Button>\n </div>\n </div>\n </div>\n )}\n />\n\n <Controls.Root className=\"media-surface media-controls\">\n <PlayButton\n render={(props, state) => (\n <Button {...props} className=\"media-button--icon\">\n <PlayButtonIcon state={state} className=\"media-icon\" />\n </Button>\n )}\n />\n\n <SeekButton\n seconds={-SEEK_TIME}\n render={(props) => (\n <Button {...props} className=\"media-button--icon media-button--seek\">\n <span className=\"media-icon__container\">\n <SeekIcon className=\"media-icon media-icon--seek media-icon--flipped\" />\n <span className=\"media-icon__label\">{SEEK_TIME}</span>\n </span>\n </Button>\n )}\n />\n\n <SeekButton\n seconds={SEEK_TIME}\n render={(props) => (\n <Button {...props} className=\"media-button--icon media-button--seek\">\n <span className=\"media-icon__container\">\n <SeekIcon className=\"media-icon media-icon--seek\" />\n <span className=\"media-icon__label\">{SEEK_TIME}</span>\n </span>\n </Button>\n )}\n />\n\n <Time.Group className=\"media-time\">\n <Time.Value type=\"current\" className=\"media-time__value\" />\n {/* Temporary spacer */}\n <div className=\"media-slider\" style={{ height: '4px', background: 'oklab(1 0 0 / 0.2)' }} />\n <Time.Value type=\"duration\" className=\"media-time__value\" />\n </Time.Group>\n\n <MuteButton\n render={(props, state) => (\n <Button {...props} className=\"media-button--icon\">\n <MuteButtonIcon state={state} className=\"media-icon\" />\n </Button>\n )}\n />\n\n <CaptionsButton\n render={(props, state) => (\n <Button {...props} className=\"media-button--icon\">\n <CaptionsButtonIcon state={state} className=\"media-icon\" />\n </Button>\n )}\n />\n\n <PiPButton\n render={(props) => (\n <Button {...props} className=\"media-button--icon\">\n <PipIcon className=\"media-icon\" />\n </Button>\n )}\n />\n\n <FullscreenButton\n render={(props, state) => (\n <Button {...props} className=\"media-button--icon\">\n <FullscreenButtonIcon state={state} className=\"media-icon\" />\n </Button>\n )}\n />\n </Controls.Root>\n\n {/* <div className=\"media-captions\">\n <div className=\"media-captions__container\">\n <span className=\"media-captions__text\">An example cue</span>\n <span className=\"media-captions__text\">\n <p>Another example cue with HTML</p>\n </span>\n </div>\n </div> */}\n\n <div className=\"media-overlay\" />\n </Container>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import { Container } from "../../player/context.js";
|
|
2
|
+
import { BufferingIndicator } from "../../ui/buffering-indicator/buffering-indicator.js";
|
|
3
|
+
import { ControlsRoot } from "../../ui/controls/controls-root.js";
|
|
4
|
+
import { FullscreenButton } from "../../ui/fullscreen-button/fullscreen-button.js";
|
|
5
|
+
import { MuteButton } from "../../ui/mute-button/mute-button.js";
|
|
6
|
+
import { PiPButton } from "../../ui/pip-button/pip-button.js";
|
|
7
|
+
import { PlayButton } from "../../ui/play-button/play-button.js";
|
|
8
|
+
import { SeekButton } from "../../ui/seek-button/seek-button.js";
|
|
9
|
+
import { Group } from "../../ui/time/time-group.js";
|
|
10
|
+
import { Value } from "../../ui/time/time-value.js";
|
|
11
|
+
import { CaptionsButton } from "../../ui/captions-button/captions-button.js";
|
|
12
|
+
import { ErrorDialog } from "../../ui/error-dialog/error-dialog.js";
|
|
13
|
+
import { forwardRef } from "react";
|
|
14
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
import { cn } from "@videojs/utils/style";
|
|
16
|
+
import { CaptionsOffIcon, CaptionsOnIcon, FullscreenEnterIcon, FullscreenExitIcon, PauseIcon, PipIcon, PlayIcon, RestartIcon, SeekIcon, SpinnerIcon, VolumeHighIcon, VolumeLowIcon, VolumeOffIcon } from "@videojs/icons/react";
|
|
17
|
+
|
|
18
|
+
//#region src/presets/video/skin.tailwind.tsx
|
|
19
|
+
const SEEK_TIME = 10;
|
|
20
|
+
const surface = cn("bg-white/10", "backdrop-blur-3xl backdrop-brightness-90 backdrop-saturate-150", "ring ring-white/5 ring-inset shadow-sm shadow-black/15", "after:absolute after:inset-0 after:ring after:rounded-[inherit] after:ring-black/15 after:pointer-events-none after:z-10", "[@media(prefers-reduced-transparency:reduce)]:bg-black/70 [@media(prefers-reduced-transparency:reduce)]:ring-black [@media(prefers-reduced-transparency:reduce)]:after:ring-white/20", "contrast-more:bg-black/90 contrast-more:ring-black contrast-more:after:ring-white/20");
|
|
21
|
+
const icon = cn("[grid-area:1/1] size-4.5 shrink-0", "drop-shadow-[0_1px_0_var(--tw-drop-shadow-color)] drop-shadow-black/25", "transition-discrete transition-[display,opacity] duration-150 ease-out");
|
|
22
|
+
const iconHidden = "hidden opacity-0";
|
|
23
|
+
const Button = forwardRef(function Button({ className, variant, ...props }, ref) {
|
|
24
|
+
return /* @__PURE__ */ jsx("button", {
|
|
25
|
+
ref,
|
|
26
|
+
type: "button",
|
|
27
|
+
className: cn("shrink-0 border-none cursor-pointer select-none", "outline-2 outline-transparent -outline-offset-2", "transition-[background-color,color,outline-offset] duration-150 ease-out", "disabled:cursor-not-allowed disabled:opacity-50 disabled:grayscale", variant === "icon" ? cn("grid p-2 bg-transparent rounded-full", "text-white/90", "text-shadow-2xs text-shadow-black/25", "hover:bg-white/10 hover:text-white hover:no-underline", "focus-visible:bg-white/10 focus-visible:text-white", "focus-visible:outline-blue-500 focus-visible:outline-offset-2", "aria-expanded:bg-white/10 aria-expanded:text-white") : cn("flex items-center justify-center py-2 px-4 bg-white rounded-full", "text-black font-medium", "focus-visible:outline-blue-500 focus-visible:outline-offset-2"), className),
|
|
28
|
+
...props
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
function PlayButtonIcon({ state, className, ...rest }) {
|
|
32
|
+
const { ended, paused } = state;
|
|
33
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
34
|
+
/* @__PURE__ */ jsx(RestartIcon, {
|
|
35
|
+
...rest,
|
|
36
|
+
className: cn(className, { [iconHidden]: !ended })
|
|
37
|
+
}),
|
|
38
|
+
/* @__PURE__ */ jsx(PlayIcon, {
|
|
39
|
+
...rest,
|
|
40
|
+
className: cn(className, { [iconHidden]: ended || !paused })
|
|
41
|
+
}),
|
|
42
|
+
/* @__PURE__ */ jsx(PauseIcon, {
|
|
43
|
+
...rest,
|
|
44
|
+
className: cn(className, { [iconHidden]: paused })
|
|
45
|
+
})
|
|
46
|
+
] });
|
|
47
|
+
}
|
|
48
|
+
function MuteButtonIcon({ state, className, ...rest }) {
|
|
49
|
+
const { muted, volumeLevel } = state;
|
|
50
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
51
|
+
/* @__PURE__ */ jsx(VolumeOffIcon, {
|
|
52
|
+
...rest,
|
|
53
|
+
className: cn(className, { [iconHidden]: !muted })
|
|
54
|
+
}),
|
|
55
|
+
/* @__PURE__ */ jsx(VolumeLowIcon, {
|
|
56
|
+
...rest,
|
|
57
|
+
className: cn(className, { [iconHidden]: muted || volumeLevel !== "low" })
|
|
58
|
+
}),
|
|
59
|
+
/* @__PURE__ */ jsx(VolumeHighIcon, {
|
|
60
|
+
...rest,
|
|
61
|
+
className: cn(className, { [iconHidden]: muted || volumeLevel === "low" })
|
|
62
|
+
})
|
|
63
|
+
] });
|
|
64
|
+
}
|
|
65
|
+
function CaptionsButtonIcon({ state, className, ...rest }) {
|
|
66
|
+
const { active } = state;
|
|
67
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(CaptionsOffIcon, {
|
|
68
|
+
...rest,
|
|
69
|
+
className: cn(className, { [iconHidden]: active })
|
|
70
|
+
}), /* @__PURE__ */ jsx(CaptionsOnIcon, {
|
|
71
|
+
...rest,
|
|
72
|
+
className: cn(className, { [iconHidden]: !active })
|
|
73
|
+
})] });
|
|
74
|
+
}
|
|
75
|
+
function FullscreenButtonIcon({ state, className, ...rest }) {
|
|
76
|
+
const { fullscreen } = state;
|
|
77
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(FullscreenExitIcon, {
|
|
78
|
+
...rest,
|
|
79
|
+
className: cn(className, { [iconHidden]: !fullscreen })
|
|
80
|
+
}), /* @__PURE__ */ jsx(FullscreenEnterIcon, {
|
|
81
|
+
...rest,
|
|
82
|
+
className: cn(className, { [iconHidden]: fullscreen })
|
|
83
|
+
})] });
|
|
84
|
+
}
|
|
85
|
+
function VideoSkinTailwind(props) {
|
|
86
|
+
const { children, className, ...rest } = props;
|
|
87
|
+
return /* @__PURE__ */ jsxs(Container, {
|
|
88
|
+
className: cn("relative isolate overflow-clip @container/media-root", "rounded-[var(--media-border-radius,2rem)] bg-black", "font-[Inter_Variable,Inter,ui-sans-serif,system-ui,sans-serif] text-[0.8125rem] leading-normal subpixel-antialiased", "**:box-border **:m-0", "[&_button]:font-[inherit]", "motion-safe:[interpolate-size:allow-keywords]", "before:absolute before:pointer-events-none before:rounded-[inherit] before:z-10", "before:inset-px before:ring-1 before:ring-inset before:ring-white/15", "after:absolute after:pointer-events-none after:rounded-[inherit] after:z-10", "after:inset-0 after:ring-1 after:ring-inset after:ring-black/10", "[&>video]:block [&>video]:w-full [&>video]:h-full", "[&>img]:absolute [&>img]:inset-0 [&>img]:w-full [&>img]:h-full", "[&>img]:object-cover [&>img]:pointer-events-none", "[&>img]:transition-opacity [&>img]:duration-[250ms]", "[&>img:not([data-visible])]:opacity-0", "[&:fullscreen]:rounded-none", className),
|
|
89
|
+
...rest,
|
|
90
|
+
children: [
|
|
91
|
+
children,
|
|
92
|
+
/* @__PURE__ */ jsx(BufferingIndicator, { render: (props, state) => state.visible ? /* @__PURE__ */ jsx("div", {
|
|
93
|
+
...props,
|
|
94
|
+
className: "absolute inset-0 flex items-center justify-center pointer-events-none z-10 text-white",
|
|
95
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
96
|
+
className: cn("p-1 rounded-full", surface),
|
|
97
|
+
children: /* @__PURE__ */ jsx(SpinnerIcon, { className: icon })
|
|
98
|
+
})
|
|
99
|
+
}) : null }),
|
|
100
|
+
/* @__PURE__ */ jsx(ErrorDialog, {
|
|
101
|
+
"aria-labelledby": "media-error-title",
|
|
102
|
+
"aria-describedby": "media-error-description",
|
|
103
|
+
render: (props, { onDismiss }) => /* @__PURE__ */ jsx("div", {
|
|
104
|
+
...props,
|
|
105
|
+
className: "peer/error group/error absolute inset-0 z-20 items-center justify-center pointer-events-none hidden data-[visible]:flex",
|
|
106
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
107
|
+
className: cn("hidden flex-col gap-3 max-w-72 p-3 rounded-[1.75rem] text-white text-sm pointer-events-auto", "group-data-[visible]/error:flex", "transition-[display,opacity,scale,transform] duration-500 delay-100 transition-discrete", "starting:opacity-0 starting:scale-50", "ease-[linear(0,0.034_1.5%,0.763_9.7%,1.066_13.9%,1.198_19.9%,1.184_21.8%,0.963_37.5%,0.997_50.9%,1)]", surface),
|
|
108
|
+
children: [/* @__PURE__ */ jsxs("div", {
|
|
109
|
+
className: "flex flex-col gap-2 px-2 pt-2 pb-1.5",
|
|
110
|
+
children: [/* @__PURE__ */ jsx("p", {
|
|
111
|
+
id: "media-error-title",
|
|
112
|
+
className: "font-semibold leading-tight",
|
|
113
|
+
children: "Something went wrong."
|
|
114
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
115
|
+
id: "media-error-description",
|
|
116
|
+
className: "opacity-70",
|
|
117
|
+
children: "An error occurred while trying to play the video. Please try again."
|
|
118
|
+
})]
|
|
119
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
120
|
+
className: "flex gap-2 *:flex-1",
|
|
121
|
+
children: /* @__PURE__ */ jsx(Button, {
|
|
122
|
+
onClick: onDismiss,
|
|
123
|
+
children: "OK"
|
|
124
|
+
})
|
|
125
|
+
})]
|
|
126
|
+
})
|
|
127
|
+
})
|
|
128
|
+
}),
|
|
129
|
+
/* @__PURE__ */ jsxs(ControlsRoot, {
|
|
130
|
+
className: cn("peer/controls", surface, "absolute @container/media-controls bottom-3 inset-x-3", "p-[0.175rem] flex items-center gap-[0.075rem]", "text-white rounded-full z-10", "will-change-[scale,transform,filter,opacity]", "transition-[scale,transform,filter,opacity] ease-out", "delay-0 duration-100 origin-bottom", "not-data-[visible]:pointer-events-none not-data-[visible]:blur-[8px]", "not-data-[visible]:scale-90 not-data-[visible]:opacity-0", "not-data-[visible]:delay-500 not-data-[visible]:duration-300", "motion-reduce:not-data-[visible]:duration-100", "motion-reduce:not-data-[visible]:blur-none", "motion-reduce:not-data-[visible]:scale-100", "@2xl/media-root:p-1 @2xl/media-root:gap-0.5"),
|
|
131
|
+
children: [
|
|
132
|
+
/* @__PURE__ */ jsx(PlayButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
133
|
+
variant: "icon",
|
|
134
|
+
...props,
|
|
135
|
+
children: /* @__PURE__ */ jsx(PlayButtonIcon, {
|
|
136
|
+
state,
|
|
137
|
+
className: icon
|
|
138
|
+
})
|
|
139
|
+
}) }),
|
|
140
|
+
/* @__PURE__ */ jsx(SeekButton, {
|
|
141
|
+
seconds: -SEEK_TIME,
|
|
142
|
+
render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
143
|
+
variant: "icon",
|
|
144
|
+
...props,
|
|
145
|
+
className: "@max-md/media-controls:hidden",
|
|
146
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
147
|
+
className: "relative",
|
|
148
|
+
children: [/* @__PURE__ */ jsx(SeekIcon, { className: cn(icon, "[scale:-1_1]") }), /* @__PURE__ */ jsx("span", {
|
|
149
|
+
className: "absolute left-0 -bottom-0.75 text-[0.75em] font-[480] tabular-nums",
|
|
150
|
+
children: SEEK_TIME
|
|
151
|
+
})]
|
|
152
|
+
})
|
|
153
|
+
})
|
|
154
|
+
}),
|
|
155
|
+
/* @__PURE__ */ jsx(SeekButton, {
|
|
156
|
+
seconds: SEEK_TIME,
|
|
157
|
+
render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
158
|
+
variant: "icon",
|
|
159
|
+
...props,
|
|
160
|
+
className: "@max-md/media-controls:hidden",
|
|
161
|
+
children: /* @__PURE__ */ jsxs("span", {
|
|
162
|
+
className: "relative",
|
|
163
|
+
children: [/* @__PURE__ */ jsx(SeekIcon, { className: icon }), /* @__PURE__ */ jsx("span", {
|
|
164
|
+
className: "absolute right-0 -bottom-0.75 text-[0.75em] font-[480] tabular-nums",
|
|
165
|
+
children: SEEK_TIME
|
|
166
|
+
})]
|
|
167
|
+
})
|
|
168
|
+
})
|
|
169
|
+
}),
|
|
170
|
+
/* @__PURE__ */ jsxs(Group, {
|
|
171
|
+
className: "@container/media-time flex items-center flex-1 gap-3 px-2",
|
|
172
|
+
children: [
|
|
173
|
+
/* @__PURE__ */ jsx(Value, {
|
|
174
|
+
type: "current",
|
|
175
|
+
className: "hidden @2xs/media-time:block text-shadow-2xs text-shadow-black/25 tabular-nums"
|
|
176
|
+
}),
|
|
177
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 h-1 rounded-full bg-white/20" }),
|
|
178
|
+
/* @__PURE__ */ jsx(Value, {
|
|
179
|
+
type: "duration",
|
|
180
|
+
className: "text-shadow-2xs text-shadow-black/25 tabular-nums"
|
|
181
|
+
})
|
|
182
|
+
]
|
|
183
|
+
}),
|
|
184
|
+
/* @__PURE__ */ jsx(CaptionsButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
185
|
+
variant: "icon",
|
|
186
|
+
...props,
|
|
187
|
+
children: /* @__PURE__ */ jsx(CaptionsButtonIcon, {
|
|
188
|
+
state,
|
|
189
|
+
className: icon
|
|
190
|
+
})
|
|
191
|
+
}) }),
|
|
192
|
+
/* @__PURE__ */ jsx(MuteButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
193
|
+
variant: "icon",
|
|
194
|
+
...props,
|
|
195
|
+
children: /* @__PURE__ */ jsx(MuteButtonIcon, {
|
|
196
|
+
state,
|
|
197
|
+
className: icon
|
|
198
|
+
})
|
|
199
|
+
}) }),
|
|
200
|
+
/* @__PURE__ */ jsx(PiPButton, { render: (props) => /* @__PURE__ */ jsx(Button, {
|
|
201
|
+
variant: "icon",
|
|
202
|
+
...props,
|
|
203
|
+
children: /* @__PURE__ */ jsx(PipIcon, { className: icon })
|
|
204
|
+
}) }),
|
|
205
|
+
/* @__PURE__ */ jsx(FullscreenButton, { render: (props, state) => /* @__PURE__ */ jsx(Button, {
|
|
206
|
+
variant: "icon",
|
|
207
|
+
...props,
|
|
208
|
+
children: /* @__PURE__ */ jsx(FullscreenButtonIcon, {
|
|
209
|
+
state,
|
|
210
|
+
className: icon
|
|
211
|
+
})
|
|
212
|
+
}) })
|
|
213
|
+
]
|
|
214
|
+
}),
|
|
215
|
+
/* @__PURE__ */ jsx("div", { className: cn("absolute inset-0 flex flex-col items-start", "pointer-events-none rounded-[inherit]", "opacity-0", "bg-gradient-to-t from-black/50 via-black/30 to-transparent", "backdrop-blur-[0px] backdrop-saturate-120 backdrop-brightness-90", "transition-[opacity,backdrop-filter] ease-out", "duration-300 delay-500", "peer-data-[visible]/controls:opacity-100", "peer-data-[visible]/controls:duration-150", "peer-data-[visible]/controls:delay-0", "peer-data-[visible]/error:opacity-100", "peer-data-[visible]/error:duration-150", "peer-data-[visible]/error:delay-0", "peer-data-[visible]/error:backdrop-blur-[8px]", "motion-reduce:duration-100") })
|
|
216
|
+
]
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
//#endregion
|
|
221
|
+
export { VideoSkinTailwind };
|
|
222
|
+
//# sourceMappingURL=skin.tailwind.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skin.tailwind.js","names":["Controls.Root","Time.Group","Time.Value"],"sources":["../../../../src/presets/video/skin.tailwind.tsx"],"sourcesContent":["import type { FullscreenButtonState, MuteButtonState, PlayButtonState } from '@videojs/core';\nimport {\n CaptionsOffIcon,\n CaptionsOnIcon,\n FullscreenEnterIcon,\n FullscreenExitIcon,\n PauseIcon,\n PipIcon,\n PlayIcon,\n RestartIcon,\n SeekIcon,\n SpinnerIcon,\n VolumeHighIcon,\n VolumeLowIcon,\n VolumeOffIcon,\n} from '@videojs/icons/react';\nimport { cn } from '@videojs/utils/style';\nimport { type ComponentProps, forwardRef, type ReactNode } from 'react';\nimport { Container } from '@/player/context';\nimport { BufferingIndicator } from '@/ui/buffering-indicator';\nimport { CaptionsButton, type CaptionsButtonState } from '@/ui/captions-button';\nimport { Controls } from '@/ui/controls';\nimport { ErrorDialog } from '@/ui/error-dialog';\nimport { FullscreenButton } from '@/ui/fullscreen-button';\nimport { MuteButton } from '@/ui/mute-button';\nimport { PiPButton } from '@/ui/pip-button';\nimport { PlayButton } from '@/ui/play-button';\nimport { SeekButton } from '@/ui/seek-button';\nimport { Time } from '@/ui/time';\nimport type { VideoSkinProps } from './skin';\n\nconst SEEK_TIME = 10;\n\n/* ------------------------------------ Reused fragments ------------------------------------- */\n\nconst surface = cn(\n 'bg-white/10',\n 'backdrop-blur-3xl backdrop-brightness-90 backdrop-saturate-150',\n // Border and shadow\n 'ring ring-white/5 ring-inset shadow-sm shadow-black/15',\n // Border to enhance contrast on lighter videos\n 'after:absolute after:inset-0 after:ring after:rounded-[inherit] after:ring-black/15 after:pointer-events-none after:z-10',\n // Reduced transparency for users with preference\n '[@media(prefers-reduced-transparency:reduce)]:bg-black/70 [@media(prefers-reduced-transparency:reduce)]:ring-black [@media(prefers-reduced-transparency:reduce)]:after:ring-white/20',\n // High contrast mode\n 'contrast-more:bg-black/90 contrast-more:ring-black contrast-more:after:ring-white/20'\n);\n\nconst icon = cn(\n '[grid-area:1/1] size-4.5 shrink-0',\n 'drop-shadow-[0_1px_0_var(--tw-drop-shadow-color)] drop-shadow-black/25',\n 'transition-discrete transition-[display,opacity] duration-150 ease-out'\n);\n\nconst iconHidden = 'hidden opacity-0';\n\n/* --------------------------------------- Components ---------------------------------------- */\n\nconst Button = forwardRef<HTMLButtonElement, ComponentProps<'button'> & { variant?: 'icon' }>(function Button(\n { className, variant, ...props },\n ref\n) {\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cn(\n // Shared\n 'shrink-0 border-none cursor-pointer select-none',\n 'outline-2 outline-transparent -outline-offset-2',\n 'transition-[background-color,color,outline-offset] duration-150 ease-out',\n 'disabled:cursor-not-allowed disabled:opacity-50 disabled:grayscale',\n // Variant\n variant === 'icon'\n ? cn(\n 'grid p-2 bg-transparent rounded-full',\n 'text-white/90',\n 'text-shadow-2xs text-shadow-black/25',\n 'hover:bg-white/10 hover:text-white hover:no-underline',\n 'focus-visible:bg-white/10 focus-visible:text-white',\n 'focus-visible:outline-blue-500 focus-visible:outline-offset-2',\n 'aria-expanded:bg-white/10 aria-expanded:text-white'\n )\n : cn(\n 'flex items-center justify-center py-2 px-4 bg-white rounded-full',\n 'text-black font-medium',\n 'focus-visible:outline-blue-500 focus-visible:outline-offset-2'\n ),\n className\n )}\n {...props}\n />\n );\n});\n\nfunction PlayButtonIcon({ state, className, ...rest }: { state: PlayButtonState } & ComponentProps<'svg'>) {\n const { ended, paused } = state;\n return (\n <>\n <RestartIcon {...rest} className={cn(className, { [iconHidden]: !ended })} />\n <PlayIcon {...rest} className={cn(className, { [iconHidden]: ended || !paused })} />\n <PauseIcon {...rest} className={cn(className, { [iconHidden]: paused })} />\n </>\n );\n}\n\nfunction MuteButtonIcon({ state, className, ...rest }: { state: MuteButtonState } & ComponentProps<'svg'>) {\n const { muted, volumeLevel } = state;\n return (\n <>\n <VolumeOffIcon {...rest} className={cn(className, { [iconHidden]: !muted })} />\n <VolumeLowIcon {...rest} className={cn(className, { [iconHidden]: muted || volumeLevel !== 'low' })} />\n <VolumeHighIcon {...rest} className={cn(className, { [iconHidden]: muted || volumeLevel === 'low' })} />\n </>\n );\n}\n\nfunction CaptionsButtonIcon({ state, className, ...rest }: { state: CaptionsButtonState } & ComponentProps<'svg'>) {\n const { active } = state;\n return (\n <>\n <CaptionsOffIcon {...rest} className={cn(className, { [iconHidden]: active })} />\n <CaptionsOnIcon {...rest} className={cn(className, { [iconHidden]: !active })} />\n </>\n );\n}\n\nfunction FullscreenButtonIcon({ state, className, ...rest }: { state: FullscreenButtonState } & ComponentProps<'svg'>) {\n const { fullscreen } = state;\n return (\n <>\n <FullscreenExitIcon {...rest} className={cn(className, { [iconHidden]: !fullscreen })} />\n <FullscreenEnterIcon {...rest} className={cn(className, { [iconHidden]: fullscreen })} />\n </>\n );\n}\n\n/* ------------------------------------------ Skin ------------------------------------------- */\n\nexport function VideoSkinTailwind(props: VideoSkinProps): ReactNode {\n const { children, className, ...rest } = props;\n\n return (\n <Container\n className={cn(\n // Layout & containment\n 'relative isolate overflow-clip @container/media-root',\n // Appearance\n 'rounded-[var(--media-border-radius,2rem)] bg-black',\n 'font-[Inter_Variable,Inter,ui-sans-serif,system-ui,sans-serif] text-[0.8125rem] leading-normal subpixel-antialiased',\n // Resets\n '**:box-border **:m-0',\n '[&_button]:font-[inherit]',\n 'motion-safe:[interpolate-size:allow-keywords]',\n // Inner highlight ring (::before)\n 'before:absolute before:pointer-events-none before:rounded-[inherit] before:z-10',\n 'before:inset-px before:ring-1 before:ring-inset before:ring-white/15',\n // Outer border ring (::after)\n 'after:absolute after:pointer-events-none after:rounded-[inherit] after:z-10',\n 'after:inset-0 after:ring-1 after:ring-inset after:ring-black/10',\n // Video element\n '[&>video]:block [&>video]:w-full [&>video]:h-full',\n // Poster image\n '[&>img]:absolute [&>img]:inset-0 [&>img]:w-full [&>img]:h-full',\n '[&>img]:object-cover [&>img]:pointer-events-none',\n '[&>img]:transition-opacity [&>img]:duration-[250ms]',\n '[&>img:not([data-visible])]:opacity-0',\n // Fullscreen\n '[&:fullscreen]:rounded-none',\n className\n )}\n {...rest}\n >\n {children}\n\n <BufferingIndicator\n render={(props, state) =>\n state.visible ? (\n <div\n {...props}\n className=\"absolute inset-0 flex items-center justify-center pointer-events-none z-10 text-white\"\n >\n <div className={cn('p-1 rounded-full', surface)}>\n <SpinnerIcon className={icon} />\n </div>\n </div>\n ) : null\n }\n />\n\n <ErrorDialog\n aria-labelledby=\"media-error-title\"\n aria-describedby=\"media-error-description\"\n render={(props, { onDismiss }) => (\n <div\n {...props}\n className=\"peer/error group/error absolute inset-0 z-20 items-center justify-center pointer-events-none hidden data-[visible]:flex\"\n >\n <div\n className={cn(\n 'hidden flex-col gap-3 max-w-72 p-3 rounded-[1.75rem] text-white text-sm pointer-events-auto',\n 'group-data-[visible]/error:flex',\n 'transition-[display,opacity,scale,transform] duration-500 delay-100 transition-discrete',\n 'starting:opacity-0 starting:scale-50',\n 'ease-[linear(0,0.034_1.5%,0.763_9.7%,1.066_13.9%,1.198_19.9%,1.184_21.8%,0.963_37.5%,0.997_50.9%,1)]',\n surface\n )}\n >\n <div className=\"flex flex-col gap-2 px-2 pt-2 pb-1.5\">\n <p id=\"media-error-title\" className=\"font-semibold leading-tight\">\n Something went wrong.\n </p>\n <p id=\"media-error-description\" className=\"opacity-70\">\n An error occurred while trying to play the video. Please try again.\n </p>\n </div>\n <div className=\"flex gap-2 *:flex-1\">\n <Button onClick={onDismiss}>OK</Button>\n </div>\n </div>\n </div>\n )}\n />\n\n <Controls.Root\n className={cn(\n // Peer marker for overlay/captions\n 'peer/controls',\n // Surface\n surface,\n // Layout\n 'absolute @container/media-controls bottom-3 inset-x-3',\n 'p-[0.175rem] flex items-center gap-[0.075rem]',\n 'text-white rounded-full z-10',\n // Transitions\n 'will-change-[scale,transform,filter,opacity]',\n 'transition-[scale,transform,filter,opacity] ease-out',\n 'delay-0 duration-100 origin-bottom',\n // Hidden state\n 'not-data-[visible]:pointer-events-none not-data-[visible]:blur-[8px]',\n 'not-data-[visible]:scale-90 not-data-[visible]:opacity-0',\n 'not-data-[visible]:delay-500 not-data-[visible]:duration-300',\n // Reduced motion + hidden\n 'motion-reduce:not-data-[visible]:duration-100',\n 'motion-reduce:not-data-[visible]:blur-none',\n 'motion-reduce:not-data-[visible]:scale-100',\n // Wider container\n '@2xl/media-root:p-1 @2xl/media-root:gap-0.5'\n )}\n >\n <PlayButton\n render={(props, state) => (\n <Button variant=\"icon\" {...props}>\n <PlayButtonIcon state={state} className={icon} />\n </Button>\n )}\n />\n\n <SeekButton\n seconds={-SEEK_TIME}\n render={(props) => (\n <Button variant=\"icon\" {...props} className=\"@max-md/media-controls:hidden\">\n <span className=\"relative\">\n <SeekIcon className={cn(icon, '[scale:-1_1]')} />\n <span className=\"absolute left-0 -bottom-0.75 text-[0.75em] font-[480] tabular-nums\">{SEEK_TIME}</span>\n </span>\n </Button>\n )}\n />\n\n <SeekButton\n seconds={SEEK_TIME}\n render={(props) => (\n <Button variant=\"icon\" {...props} className=\"@max-md/media-controls:hidden\">\n <span className=\"relative\">\n <SeekIcon className={icon} />\n <span className=\"absolute right-0 -bottom-0.75 text-[0.75em] font-[480] tabular-nums\">{SEEK_TIME}</span>\n </span>\n </Button>\n )}\n />\n\n <Time.Group className=\"@container/media-time flex items-center flex-1 gap-3 px-2\">\n <Time.Value\n type=\"current\"\n className=\"hidden @2xs/media-time:block text-shadow-2xs text-shadow-black/25 tabular-nums\"\n />\n {/* Temporary spacer */}\n <div className=\"flex-1 h-1 rounded-full bg-white/20\" />\n <Time.Value type=\"duration\" className=\"text-shadow-2xs text-shadow-black/25 tabular-nums\" />\n </Time.Group>\n\n <CaptionsButton\n render={(props, state) => (\n <Button variant=\"icon\" {...props}>\n <CaptionsButtonIcon state={state} className={icon} />\n </Button>\n )}\n />\n\n <MuteButton\n render={(props, state) => (\n <Button variant=\"icon\" {...props}>\n <MuteButtonIcon state={state} className={icon} />\n </Button>\n )}\n />\n\n <PiPButton\n render={(props) => (\n <Button variant=\"icon\" {...props}>\n <PipIcon className={icon} />\n </Button>\n )}\n />\n\n <FullscreenButton\n render={(props, state) => (\n <Button variant=\"icon\" {...props}>\n <FullscreenButtonIcon state={state} className={icon} />\n </Button>\n )}\n />\n </Controls.Root>\n\n {/* <div\n className={cn(\n 'absolute z-20 pointer-events-none text-balance text-base',\n 'inset-x-4 bottom-6',\n 'transition-transform duration-150 ease-out delay-600',\n 'motion-reduce:duration-50',\n // Responsive font sizes\n '@xs/media-root:text-2xl',\n '@3xl/media-root:text-3xl',\n '@7xl/media-root:text-4xl',\n // Shift up when controls visible\n 'peer-data-[visible]/controls:-translate-y-12 peer-data-[visible]/controls:delay-25',\n )}\n >\n <div className=\"max-w-[42ch] mx-auto text-center flex flex-col items-center\">\n <span className={cn(\n 'block py-0.5 px-2 text-white text-center whitespace-pre-wrap leading-1.2',\n '[text-shadow:0_0_1px_oklab(0_0_0_/_0.7),0_0_8px_oklab(0_0_0_/_0.7)]',\n 'contrast-more:[text-shadow:none] contrast-more:[box-decoration-break:clone] contrast-more:bg-black/70',\n '*:inline',\n )}>\n An example cue\n </span>\n </div>\n </div> */}\n\n <div\n className={cn(\n // Layout\n 'absolute inset-0 flex flex-col items-start',\n 'pointer-events-none rounded-[inherit]',\n // Default: hidden\n 'opacity-0',\n 'bg-gradient-to-t from-black/50 via-black/30 to-transparent',\n 'backdrop-blur-[0px] backdrop-saturate-120 backdrop-brightness-90',\n // Transitions\n 'transition-[opacity,backdrop-filter] ease-out',\n 'duration-300 delay-500',\n // Shown when controls visible\n 'peer-data-[visible]/controls:opacity-100',\n 'peer-data-[visible]/controls:duration-150',\n 'peer-data-[visible]/controls:delay-0',\n // Shown when error visible (+ blur)\n 'peer-data-[visible]/error:opacity-100',\n 'peer-data-[visible]/error:duration-150',\n 'peer-data-[visible]/error:delay-0',\n 'peer-data-[visible]/error:backdrop-blur-[8px]',\n // Reduced motion\n 'motion-reduce:duration-100'\n )}\n />\n </Container>\n );\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { usePlayer } from "../../player/context.js";
|
|
4
|
+
import { renderElement } from "../../utils/use-render.js";
|
|
5
|
+
import { selectPlayback } from "@videojs/core/dom";
|
|
6
|
+
import { forwardRef, useState, useSyncExternalStore } from "react";
|
|
7
|
+
import { BufferingIndicatorCore, BufferingIndicatorDataAttrs } from "@videojs/core";
|
|
8
|
+
|
|
9
|
+
//#region src/ui/buffering-indicator/buffering-indicator.tsx
|
|
10
|
+
/**
|
|
11
|
+
* Displays a buffering indicator when media is waiting for data.
|
|
12
|
+
*
|
|
13
|
+
* Visibility is delayed (default 500ms) to avoid flashing on quick buffers.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <BufferingIndicator />
|
|
18
|
+
*
|
|
19
|
+
* <BufferingIndicator delay={1000} />
|
|
20
|
+
*
|
|
21
|
+
* <BufferingIndicator
|
|
22
|
+
* render={(props, state) => (
|
|
23
|
+
* <div {...props}>{state.visible && <Spinner />}</div>
|
|
24
|
+
* )}
|
|
25
|
+
* />
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
const BufferingIndicator = forwardRef(function BufferingIndicator(componentProps, forwardedRef) {
|
|
29
|
+
const { render, className, style, delay, ...elementProps } = componentProps;
|
|
30
|
+
const playback = usePlayer(selectPlayback);
|
|
31
|
+
const [core] = useState(() => new BufferingIndicatorCore());
|
|
32
|
+
core.setProps({ delay });
|
|
33
|
+
if (playback) core.update(playback);
|
|
34
|
+
const state = useSyncExternalStore((cb) => core.state.subscribe(cb), () => core.state.current, () => core.state.current);
|
|
35
|
+
if (!playback) return null;
|
|
36
|
+
return renderElement("div", {
|
|
37
|
+
render,
|
|
38
|
+
className,
|
|
39
|
+
style
|
|
40
|
+
}, {
|
|
41
|
+
state,
|
|
42
|
+
stateAttrMap: BufferingIndicatorDataAttrs,
|
|
43
|
+
ref: [forwardedRef],
|
|
44
|
+
props: [elementProps]
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
//#endregion
|
|
49
|
+
export { BufferingIndicator };
|
|
50
|
+
//# sourceMappingURL=buffering-indicator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"buffering-indicator.js","names":[],"sources":["../../../../src/ui/buffering-indicator/buffering-indicator.tsx"],"sourcesContent":["'use client';\n\nimport { BufferingIndicatorCore, BufferingIndicatorDataAttrs } from '@videojs/core';\nimport { logMissingFeature, selectPlayback } from '@videojs/core/dom';\nimport type { ForwardedRef } from 'react';\nimport { forwardRef, useState, useSyncExternalStore } from 'react';\n\nimport { usePlayer } from '../../player/context';\nimport type { UIComponentProps } from '../../utils/types';\nimport { renderElement } from '../../utils/use-render';\n\nexport interface BufferingIndicatorProps\n extends UIComponentProps<'div', BufferingIndicatorCore.State>,\n BufferingIndicatorCore.Props {}\n\n/**\n * Displays a buffering indicator when media is waiting for data.\n *\n * Visibility is delayed (default 500ms) to avoid flashing on quick buffers.\n *\n * @example\n * ```tsx\n * <BufferingIndicator />\n *\n * <BufferingIndicator delay={1000} />\n *\n * <BufferingIndicator\n * render={(props, state) => (\n * <div {...props}>{state.visible && <Spinner />}</div>\n * )}\n * />\n * ```\n */\nexport const BufferingIndicator = forwardRef(function BufferingIndicator(\n componentProps: BufferingIndicatorProps,\n forwardedRef: ForwardedRef<HTMLDivElement>\n) {\n const { render, className, style, delay, ...elementProps } = componentProps;\n\n const playback = usePlayer(selectPlayback);\n\n const [core] = useState(() => new BufferingIndicatorCore());\n core.setProps({ delay });\n\n if (playback) core.update(playback);\n\n const state = useSyncExternalStore(\n (cb) => core.state.subscribe(cb),\n () => core.state.current,\n () => core.state.current\n );\n\n if (!playback) {\n if (__DEV__) logMissingFeature('BufferingIndicator', 'playback');\n return null;\n }\n\n return renderElement(\n 'div',\n { render, className, style },\n {\n state,\n stateAttrMap: BufferingIndicatorDataAttrs,\n ref: [forwardedRef],\n props: [elementProps],\n }\n );\n});\n\nexport namespace BufferingIndicator {\n export type Props = BufferingIndicatorProps;\n export type State = BufferingIndicatorCore.State;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AAiCA,MAAa,qBAAqB,WAAW,SAAS,mBACpD,gBACA,cACA;CACA,MAAM,EAAE,QAAQ,WAAW,OAAO,OAAO,GAAG,iBAAiB;CAE7D,MAAM,WAAW,UAAU,eAAe;CAE1C,MAAM,CAAC,QAAQ,eAAe,IAAI,wBAAwB,CAAC;AAC3D,MAAK,SAAS,EAAE,OAAO,CAAC;AAExB,KAAI,SAAU,MAAK,OAAO,SAAS;CAEnC,MAAM,QAAQ,sBACX,OAAO,KAAK,MAAM,UAAU,GAAG,QAC1B,KAAK,MAAM,eACX,KAAK,MAAM,QAClB;AAED,KAAI,CAAC,SAEH,QAAO;AAGT,QAAO,cACL,OACA;EAAE;EAAQ;EAAW;EAAO,EAC5B;EACE;EACA,cAAc;EACd,KAAK,CAAC,aAAa;EACnB,OAAO,CAAC,aAAa;EACtB,CACF;EACD"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { renderElement } from "../../utils/use-render.js";
|
|
4
|
+
import { useButton } from "../hooks/use-button.js";
|
|
5
|
+
import { forwardRef, useState } from "react";
|
|
6
|
+
|
|
7
|
+
//#region src/ui/captions-button/captions-button.tsx
|
|
8
|
+
const CaptionButtonDataAttrs = { active: "data-active" };
|
|
9
|
+
/**
|
|
10
|
+
* A button that toggles captions.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```tsx
|
|
14
|
+
* <CaptionsButton />
|
|
15
|
+
*
|
|
16
|
+
* <CaptionsButton
|
|
17
|
+
* render={(props, state) => (
|
|
18
|
+
* <button {...props}>
|
|
19
|
+
* {state.active ? <CaptionsOnIcon /> : <CaptionsOffIcon />}
|
|
20
|
+
* </button>
|
|
21
|
+
* )}
|
|
22
|
+
* />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
const CaptionsButton = forwardRef(function CaptionsButton(componentProps, forwardedRef) {
|
|
26
|
+
const { render, className, style, label, disabled, ...elementProps } = componentProps;
|
|
27
|
+
const [isActive, setIsActive] = useState(false);
|
|
28
|
+
const { getButtonProps, buttonRef } = useButton({
|
|
29
|
+
displayName: "CaptionsButton",
|
|
30
|
+
onActivate: () => setIsActive((active) => !active),
|
|
31
|
+
isDisabled: () => disabled ?? false
|
|
32
|
+
});
|
|
33
|
+
return renderElement("button", {
|
|
34
|
+
render,
|
|
35
|
+
className,
|
|
36
|
+
style
|
|
37
|
+
}, {
|
|
38
|
+
state: { active: isActive },
|
|
39
|
+
stateAttrMap: CaptionButtonDataAttrs,
|
|
40
|
+
ref: [forwardedRef, buttonRef],
|
|
41
|
+
props: [
|
|
42
|
+
elementProps,
|
|
43
|
+
getButtonProps(),
|
|
44
|
+
{ "aria-pressed": isActive }
|
|
45
|
+
]
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
export { CaptionsButton };
|
|
51
|
+
//# sourceMappingURL=captions-button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"captions-button.js","names":[],"sources":["../../../../src/ui/captions-button/captions-button.tsx"],"sourcesContent":["'use client';\n\nimport type { StateAttrMap } from '@videojs/core';\nimport type { ForwardedRef } from 'react';\nimport { forwardRef, useState } from 'react';\n\nimport type { UIComponentProps } from '../../utils/types';\nimport { renderElement } from '../../utils/use-render';\nimport { useButton } from '../hooks/use-button';\n\n// FIXME: Replace with state/props from core.\nexport type CaptionsButtonState = {\n active: boolean;\n};\ntype CaptionButtonCoreProps = {\n /** Custom label for the button. */\n label?: string | ((state: CaptionsButtonState) => string) | undefined;\n /** Whether the button is disabled. */\n disabled?: boolean | undefined;\n};\nconst CaptionButtonDataAttrs = {\n /** Present when the captions are active. */\n active: 'data-active',\n} as const satisfies StateAttrMap<CaptionsButtonState>;\n\nexport interface CaptionsButtonProps extends UIComponentProps<'button', CaptionsButtonState>, CaptionButtonCoreProps {}\n\n/**\n * A button that toggles captions.\n *\n * @example\n * ```tsx\n * <CaptionsButton />\n *\n * <CaptionsButton\n * render={(props, state) => (\n * <button {...props}>\n * {state.active ? <CaptionsOnIcon /> : <CaptionsOffIcon />}\n * </button>\n * )}\n * />\n * ```\n */\nexport const CaptionsButton = forwardRef(function CaptionsButton(\n componentProps: CaptionsButtonProps,\n forwardedRef: ForwardedRef<HTMLButtonElement>\n) {\n const { render, className, style, label, disabled, ...elementProps } = componentProps;\n\n // FIXME: Replace with actual captions state\n const [isActive, setIsActive] = useState(false);\n\n const { getButtonProps, buttonRef } = useButton({\n displayName: 'CaptionsButton',\n onActivate: () => setIsActive((active) => !active), // FIXME: Replace with actual toggle logic\n isDisabled: () => disabled ?? false,\n });\n\n return renderElement(\n 'button',\n { render, className, style },\n {\n state: { active: isActive }, // FIXME: Replace with actual toggle logic\n stateAttrMap: CaptionButtonDataAttrs,\n ref: [forwardedRef, buttonRef],\n props: [elementProps, getButtonProps(), { 'aria-pressed': isActive }],\n }\n );\n});\n\nexport namespace CaptionsButton {\n export type Props = CaptionsButtonProps;\n export type State = CaptionsButtonState;\n}\n"],"mappings":";;;;;;;AAoBA,MAAM,yBAAyB,EAE7B,QAAQ,eACT;;;;;;;;;;;;;;;;;AAoBD,MAAa,iBAAiB,WAAW,SAAS,eAChD,gBACA,cACA;CACA,MAAM,EAAE,QAAQ,WAAW,OAAO,OAAO,UAAU,GAAG,iBAAiB;CAGvE,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM;CAE/C,MAAM,EAAE,gBAAgB,cAAc,UAAU;EAC9C,aAAa;EACb,kBAAkB,aAAa,WAAW,CAAC,OAAO;EAClD,kBAAkB,YAAY;EAC/B,CAAC;AAEF,QAAO,cACL,UACA;EAAE;EAAQ;EAAW;EAAO,EAC5B;EACE,OAAO,EAAE,QAAQ,UAAU;EAC3B,cAAc;EACd,KAAK,CAAC,cAAc,UAAU;EAC9B,OAAO;GAAC;GAAc,gBAAgB;GAAE,EAAE,gBAAgB,UAAU;GAAC;EACtE,CACF;EACD"}
|