@videojs/html 10.0.1 → 10.2.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/README.md +2 -2
- package/dist/default/define/audio/compat-skin.css +86 -60
- package/dist/default/define/audio/compat-skin2.js +1 -1
- package/dist/default/define/audio/neutral-skin.css +2 -11
- package/dist/default/define/audio/neutral-skin2.js +1 -1
- package/dist/default/define/audio/scaffold-skin.css +1754 -0
- package/dist/default/define/audio/scaffold-skin.js +6 -0
- package/dist/default/define/audio/scaffold-skin2.js +4 -0
- package/dist/default/define/audio/skin.css +0 -1
- package/dist/default/define/audio/skin2.js +1 -1
- package/dist/default/define/live-audio/compat-skin.css +86 -60
- package/dist/default/define/live-audio/compat-skin2.js +1 -1
- package/dist/default/define/live-audio/neutral-skin.css +0 -1
- package/dist/default/define/live-audio/neutral-skin2.js +1 -1
- package/dist/default/define/live-audio/scaffold-skin.css +1574 -0
- package/dist/default/define/live-audio/scaffold-skin.js +6 -0
- package/dist/default/define/live-audio/scaffold-skin2.js +4 -0
- package/dist/default/define/live-audio/skin.css +0 -1
- package/dist/default/define/live-audio/skin2.js +1 -1
- package/dist/default/define/live-video/compat-skin.css +75 -31
- package/dist/default/define/live-video/compat-skin2.js +1 -1
- package/dist/default/define/live-video/neutral-skin.css +20 -9
- package/dist/default/define/live-video/neutral-skin2.js +1 -1
- package/dist/default/define/live-video/scaffold-skin.css +1975 -0
- package/dist/default/define/live-video/scaffold-skin.js +6 -0
- package/dist/default/define/live-video/scaffold-skin2.js +4 -0
- package/dist/default/define/live-video/skin.css +18 -7
- package/dist/default/define/live-video/skin2.js +1 -1
- package/dist/default/define/media/playerjs-video.js +11 -0
- package/dist/default/define/video/compat-skin.css +75 -31
- package/dist/default/define/video/compat-skin2.js +1 -1
- package/dist/default/define/video/neutral-skin.css +28 -19
- package/dist/default/define/video/neutral-skin2.js +1 -1
- package/dist/default/define/video/scaffold-skin.css +2215 -0
- package/dist/default/define/video/scaffold-skin.js +6 -0
- package/dist/default/define/video/scaffold-skin2.js +4 -0
- package/dist/default/define/video/skin.css +24 -7
- package/dist/default/define/video/skin2.js +1 -1
- package/dist/default/extensions/mux-data/extension.js +1 -1
- package/dist/default/icons/dist/element/compat/icons.js +1 -1
- package/dist/default/icons/dist/element/index.js +1 -0
- package/dist/default/icons/dist/element/scaffold/icons.js +30 -0
- package/dist/default/icons/dist/element/scaffold/index.js +8 -0
- package/dist/default/icons/dist/html/compat/play.js +1 -1
- package/dist/default/icons/dist/html/scaffold/airplay-enter.js +4 -0
- package/dist/default/icons/dist/html/scaffold/airplay-exit.js +4 -0
- package/dist/default/icons/dist/html/scaffold/captions-off.js +4 -0
- package/dist/default/icons/dist/html/scaffold/captions-on.js +4 -0
- package/dist/default/icons/dist/html/scaffold/cast-enter.js +4 -0
- package/dist/default/icons/dist/html/scaffold/cast-exit.js +4 -0
- package/dist/default/icons/dist/html/scaffold/check.js +4 -0
- package/dist/default/icons/dist/html/scaffold/chevron.js +4 -0
- package/dist/default/icons/dist/html/scaffold/fullscreen-enter.js +4 -0
- package/dist/default/icons/dist/html/scaffold/fullscreen-exit.js +4 -0
- package/dist/default/icons/dist/html/scaffold/gear.js +4 -0
- package/dist/default/icons/dist/html/scaffold/pause.js +4 -0
- package/dist/default/icons/dist/html/scaffold/pip-enter.js +4 -0
- package/dist/default/icons/dist/html/scaffold/pip-exit.js +4 -0
- package/dist/default/icons/dist/html/scaffold/play.js +4 -0
- package/dist/default/icons/dist/html/scaffold/quality.js +4 -0
- package/dist/default/icons/dist/html/scaffold/restart.js +4 -0
- package/dist/default/icons/dist/html/scaffold/seek.js +4 -0
- package/dist/default/icons/dist/html/scaffold/speech.js +4 -0
- package/dist/default/icons/dist/html/scaffold/speed.js +4 -0
- package/dist/default/icons/dist/html/scaffold/spinner.js +4 -0
- package/dist/default/icons/dist/html/scaffold/switches.js +4 -0
- package/dist/default/icons/dist/html/scaffold/volume-high.js +4 -0
- package/dist/default/icons/dist/html/scaffold/volume-low.js +4 -0
- package/dist/default/icons/dist/html/scaffold/volume-off.js +4 -0
- package/dist/default/icons/element/scaffold/index.js +1 -0
- package/dist/default/icons/scaffold/index.js +26 -0
- package/dist/default/internal/skins/compat-audio/register.js +1 -10
- package/dist/default/internal/skins/compat-audio/skin.css +86 -60
- package/dist/default/internal/skins/compat-audio/template.js +26 -48
- package/dist/default/internal/skins/compat-live-audio/register.js +1 -10
- package/dist/default/internal/skins/compat-live-audio/skin.css +86 -60
- package/dist/default/internal/skins/compat-live-audio/template.js +7 -29
- package/dist/default/internal/skins/compat-live-video/skin.css +75 -31
- package/dist/default/internal/skins/compat-live-video/template.js +20 -18
- package/dist/default/internal/skins/compat-video/skin.css +75 -31
- package/dist/default/internal/skins/compat-video/template.js +34 -32
- package/dist/default/internal/skins/default-audio/skin.css +0 -1
- package/dist/default/internal/skins/default-audio/template.js +12 -12
- package/dist/default/internal/skins/default-live-audio/skin.css +0 -1
- package/dist/default/internal/skins/default-live-audio/template.js +5 -5
- package/dist/default/internal/skins/default-live-video/skin.css +18 -7
- package/dist/default/internal/skins/default-live-video/template.js +16 -16
- package/dist/default/internal/skins/default-video/skin.css +24 -7
- package/dist/default/internal/skins/default-video/template.js +26 -26
- package/dist/default/internal/skins/neutral-audio/skin.css +2 -11
- package/dist/default/internal/skins/neutral-audio/template.js +13 -13
- package/dist/default/internal/skins/neutral-live-audio/skin.css +0 -1
- package/dist/default/internal/skins/neutral-live-audio/template.js +5 -5
- package/dist/default/internal/skins/neutral-live-video/skin.css +20 -9
- package/dist/default/internal/skins/neutral-live-video/template.js +16 -16
- package/dist/default/internal/skins/neutral-video/skin.css +28 -19
- package/dist/default/internal/skins/neutral-video/template.js +27 -27
- package/dist/default/internal/skins/scaffold-audio/register.js +63 -0
- package/dist/default/internal/skins/scaffold-audio/skin.css +1722 -0
- package/dist/default/internal/skins/scaffold-audio/template.js +197 -0
- package/dist/default/internal/skins/scaffold-live-audio/register.js +43 -0
- package/dist/default/internal/skins/scaffold-live-audio/skin.css +1542 -0
- package/dist/default/internal/skins/scaffold-live-audio/template.js +94 -0
- package/dist/default/internal/skins/scaffold-live-video/register.js +86 -0
- package/dist/default/internal/skins/scaffold-live-video/skin.css +1943 -0
- package/dist/default/internal/skins/scaffold-live-video/template.js +241 -0
- package/dist/default/internal/skins/scaffold-video/register.js +115 -0
- package/dist/default/internal/skins/scaffold-video/skin.css +2183 -0
- package/dist/default/internal/skins/scaffold-video/template.js +461 -0
- package/dist/default/media/hls-audio/adapter.js +1 -1
- package/dist/default/media/hls-background-video/adapter.js +1 -1
- package/dist/default/media/hls-video/adapter.js +1 -1
- package/dist/default/media/playerjs-video/adapter.js +25 -0
- package/dist/default/presets/audio/index.js +2 -1
- package/dist/default/presets/audio/scaffold-skin.js +19 -0
- package/dist/default/presets/background/skin.js +0 -2
- package/dist/default/presets/live-audio/index.js +2 -1
- package/dist/default/presets/live-audio/scaffold-skin.js +19 -0
- package/dist/default/presets/live-video/index.js +2 -1
- package/dist/default/presets/live-video/scaffold-skin.js +19 -0
- package/dist/default/presets/skin.js +0 -11
- package/dist/default/presets/video/index.js +2 -1
- package/dist/default/presets/video/scaffold-skin.js +19 -0
- package/dist/default/ui/slider/element.js +3 -1
- package/dist/default/ui/time-slider/element.js +45 -9
- package/dist/default/ui/volume-slider/element.js +3 -1
- package/dist/default/version.js +1 -1
- package/dist/dev/define/audio/compat-skin.css +86 -60
- package/dist/dev/define/audio/compat-skin2.js +1 -1
- package/dist/dev/define/audio/compat-skin2.js.map +1 -1
- package/dist/dev/define/audio/neutral-skin.css +2 -11
- package/dist/dev/define/audio/neutral-skin2.js +1 -1
- package/dist/dev/define/audio/neutral-skin2.js.map +1 -1
- package/dist/dev/define/audio/scaffold-skin.css +1754 -0
- package/dist/dev/define/audio/scaffold-skin.d.ts +1 -0
- package/dist/dev/define/audio/scaffold-skin.js +8 -0
- package/dist/dev/define/audio/scaffold-skin.js.map +1 -0
- package/dist/dev/define/audio/scaffold-skin2.js +6 -0
- package/dist/dev/define/audio/scaffold-skin2.js.map +1 -0
- package/dist/dev/define/audio/skin.css +0 -1
- package/dist/dev/define/audio/skin2.js +1 -1
- package/dist/dev/define/audio/skin2.js.map +1 -1
- package/dist/dev/define/global.js.map +1 -1
- package/dist/dev/define/live-audio/compat-skin.css +86 -60
- package/dist/dev/define/live-audio/compat-skin2.js +1 -1
- package/dist/dev/define/live-audio/compat-skin2.js.map +1 -1
- package/dist/dev/define/live-audio/neutral-skin.css +0 -1
- package/dist/dev/define/live-audio/neutral-skin2.js +1 -1
- package/dist/dev/define/live-audio/neutral-skin2.js.map +1 -1
- package/dist/dev/define/live-audio/scaffold-skin.css +1574 -0
- package/dist/dev/define/live-audio/scaffold-skin.d.ts +1 -0
- package/dist/dev/define/live-audio/scaffold-skin.js +8 -0
- package/dist/dev/define/live-audio/scaffold-skin.js.map +1 -0
- package/dist/dev/define/live-audio/scaffold-skin2.js +6 -0
- package/dist/dev/define/live-audio/scaffold-skin2.js.map +1 -0
- package/dist/dev/define/live-audio/skin.css +0 -1
- package/dist/dev/define/live-audio/skin2.js +1 -1
- package/dist/dev/define/live-audio/skin2.js.map +1 -1
- package/dist/dev/define/live-video/compat-skin.css +75 -31
- package/dist/dev/define/live-video/compat-skin2.js +1 -1
- package/dist/dev/define/live-video/compat-skin2.js.map +1 -1
- package/dist/dev/define/live-video/neutral-skin.css +20 -9
- package/dist/dev/define/live-video/neutral-skin2.js +1 -1
- package/dist/dev/define/live-video/neutral-skin2.js.map +1 -1
- package/dist/dev/define/live-video/scaffold-skin.css +1975 -0
- package/dist/dev/define/live-video/scaffold-skin.d.ts +1 -0
- package/dist/dev/define/live-video/scaffold-skin.js +8 -0
- package/dist/dev/define/live-video/scaffold-skin.js.map +1 -0
- package/dist/dev/define/live-video/scaffold-skin2.js +6 -0
- package/dist/dev/define/live-video/scaffold-skin2.js.map +1 -0
- package/dist/dev/define/live-video/skin.css +18 -7
- package/dist/dev/define/live-video/skin2.js +1 -1
- package/dist/dev/define/live-video/skin2.js.map +1 -1
- package/dist/dev/define/media/playerjs-video.d.ts +15 -0
- package/dist/dev/define/media/playerjs-video.js +13 -0
- package/dist/dev/define/media/playerjs-video.js.map +1 -0
- package/dist/dev/define/video/compat-skin.css +75 -31
- package/dist/dev/define/video/compat-skin2.js +1 -1
- package/dist/dev/define/video/compat-skin2.js.map +1 -1
- package/dist/dev/define/video/neutral-skin.css +28 -19
- package/dist/dev/define/video/neutral-skin2.js +1 -1
- package/dist/dev/define/video/neutral-skin2.js.map +1 -1
- package/dist/dev/define/video/scaffold-skin.css +2215 -0
- package/dist/dev/define/video/scaffold-skin.d.ts +1 -0
- package/dist/dev/define/video/scaffold-skin.js +8 -0
- package/dist/dev/define/video/scaffold-skin.js.map +1 -0
- package/dist/dev/define/video/scaffold-skin2.js +6 -0
- package/dist/dev/define/video/scaffold-skin2.js.map +1 -0
- package/dist/dev/define/video/skin.css +24 -7
- package/dist/dev/define/video/skin2.js +1 -1
- package/dist/dev/define/video/skin2.js.map +1 -1
- package/dist/dev/extensions/mux-data/extension.d.ts +1 -1
- package/dist/dev/extensions/mux-data/extension.js +1 -1
- package/dist/dev/extensions/mux-data/extension.js.map +1 -1
- package/dist/dev/icons/dist/element/compat/icons.js +1 -1
- package/dist/dev/icons/dist/element/compat/icons.js.map +1 -1
- package/dist/dev/icons/dist/element/index.js +1 -0
- package/dist/dev/icons/dist/element/index.js.map +1 -1
- package/dist/dev/icons/dist/element/scaffold/icons.js +32 -0
- package/dist/dev/icons/dist/element/scaffold/icons.js.map +1 -0
- package/dist/dev/icons/dist/element/scaffold/index.d.ts +1 -0
- package/dist/dev/icons/dist/element/scaffold/index.js +10 -0
- package/dist/dev/icons/dist/element/scaffold/index.js.map +1 -0
- package/dist/dev/icons/dist/html/compat/play.js +1 -1
- package/dist/dev/icons/dist/html/compat/play.js.map +1 -1
- package/dist/dev/icons/dist/html/scaffold/airplay-enter.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/airplay-enter.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/airplay-exit.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/airplay-exit.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/captions-off.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/captions-off.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/captions-on.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/captions-on.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/cast-enter.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/cast-enter.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/cast-exit.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/cast-exit.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/check.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/check.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/chevron.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/chevron.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/fullscreen-enter.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/fullscreen-enter.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/fullscreen-exit.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/fullscreen-exit.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/gear.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/gear.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/index.d.ts +28 -0
- package/dist/dev/icons/dist/html/scaffold/pause.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/pause.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/pip-enter.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/pip-enter.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/pip-exit.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/pip-exit.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/play.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/play.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/quality.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/quality.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/restart.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/restart.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/seek.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/seek.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/speech.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/speech.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/speed.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/speed.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/spinner.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/spinner.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/switches.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/switches.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/volume-high.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/volume-high.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/volume-low.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/volume-low.js.map +1 -0
- package/dist/dev/icons/dist/html/scaffold/volume-off.js +6 -0
- package/dist/dev/icons/dist/html/scaffold/volume-off.js.map +1 -0
- package/dist/dev/icons/element/scaffold/index.d.ts +1 -0
- package/dist/dev/icons/element/scaffold/index.js +1 -0
- package/dist/dev/icons/scaffold/index.d.ts +2 -0
- package/dist/dev/icons/scaffold/index.js +26 -0
- package/dist/dev/index.d.ts +3 -3
- package/dist/dev/internal/skins/compat-audio/register.d.ts +4 -5
- package/dist/dev/internal/skins/compat-audio/register.js +1 -10
- package/dist/dev/internal/skins/compat-audio/register.js.map +1 -1
- package/dist/dev/internal/skins/compat-audio/skin.css +86 -60
- package/dist/dev/internal/skins/compat-audio/template.js +26 -48
- package/dist/dev/internal/skins/compat-audio/template.js.map +1 -1
- package/dist/dev/internal/skins/compat-live-audio/register.d.ts +1 -2
- package/dist/dev/internal/skins/compat-live-audio/register.js +1 -10
- package/dist/dev/internal/skins/compat-live-audio/register.js.map +1 -1
- package/dist/dev/internal/skins/compat-live-audio/skin.css +86 -60
- package/dist/dev/internal/skins/compat-live-audio/template.js +7 -29
- package/dist/dev/internal/skins/compat-live-audio/template.js.map +1 -1
- package/dist/dev/internal/skins/compat-live-video/register.d.ts +3 -3
- package/dist/dev/internal/skins/compat-live-video/skin.css +75 -31
- package/dist/dev/internal/skins/compat-live-video/template.js +20 -18
- package/dist/dev/internal/skins/compat-live-video/template.js.map +1 -1
- package/dist/dev/internal/skins/compat-video/register.d.ts +6 -6
- package/dist/dev/internal/skins/compat-video/skin.css +75 -31
- package/dist/dev/internal/skins/compat-video/template.js +34 -32
- package/dist/dev/internal/skins/compat-video/template.js.map +1 -1
- package/dist/dev/internal/skins/default-audio/register.d.ts +3 -3
- package/dist/dev/internal/skins/default-audio/skin.css +0 -1
- package/dist/dev/internal/skins/default-audio/template.js +12 -12
- package/dist/dev/internal/skins/default-audio/template.js.map +1 -1
- package/dist/dev/internal/skins/default-live-audio/register.d.ts +1 -1
- package/dist/dev/internal/skins/default-live-audio/skin.css +0 -1
- package/dist/dev/internal/skins/default-live-audio/template.js +5 -5
- package/dist/dev/internal/skins/default-live-audio/template.js.map +1 -1
- package/dist/dev/internal/skins/default-live-video/register.d.ts +3 -3
- package/dist/dev/internal/skins/default-live-video/skin.css +18 -7
- package/dist/dev/internal/skins/default-live-video/template.js +16 -16
- package/dist/dev/internal/skins/default-live-video/template.js.map +1 -1
- package/dist/dev/internal/skins/default-video/register.d.ts +4 -4
- package/dist/dev/internal/skins/default-video/skin.css +24 -7
- package/dist/dev/internal/skins/default-video/template.js +26 -26
- package/dist/dev/internal/skins/default-video/template.js.map +1 -1
- package/dist/dev/internal/skins/neutral-audio/register.d.ts +5 -5
- package/dist/dev/internal/skins/neutral-audio/skin.css +2 -11
- package/dist/dev/internal/skins/neutral-audio/template.js +13 -13
- package/dist/dev/internal/skins/neutral-audio/template.js.map +1 -1
- package/dist/dev/internal/skins/neutral-live-audio/register.d.ts +1 -1
- package/dist/dev/internal/skins/neutral-live-audio/skin.css +0 -1
- package/dist/dev/internal/skins/neutral-live-audio/template.js +5 -5
- package/dist/dev/internal/skins/neutral-live-audio/template.js.map +1 -1
- package/dist/dev/internal/skins/neutral-live-video/register.d.ts +3 -3
- package/dist/dev/internal/skins/neutral-live-video/skin.css +20 -9
- package/dist/dev/internal/skins/neutral-live-video/template.js +16 -16
- package/dist/dev/internal/skins/neutral-live-video/template.js.map +1 -1
- package/dist/dev/internal/skins/neutral-video/register.d.ts +6 -6
- package/dist/dev/internal/skins/neutral-video/skin.css +28 -19
- package/dist/dev/internal/skins/neutral-video/template.js +27 -27
- package/dist/dev/internal/skins/neutral-video/template.js.map +1 -1
- package/dist/dev/internal/skins/scaffold-audio/register.d.ts +42 -0
- package/dist/dev/internal/skins/scaffold-audio/register.js +65 -0
- package/dist/dev/internal/skins/scaffold-audio/register.js.map +1 -0
- package/dist/dev/internal/skins/scaffold-audio/skin.css +1722 -0
- package/dist/dev/internal/skins/scaffold-audio/template.js +199 -0
- package/dist/dev/internal/skins/scaffold-audio/template.js.map +1 -0
- package/dist/dev/internal/skins/scaffold-live-audio/register.d.ts +26 -0
- package/dist/dev/internal/skins/scaffold-live-audio/register.js +45 -0
- package/dist/dev/internal/skins/scaffold-live-audio/register.js.map +1 -0
- package/dist/dev/internal/skins/scaffold-live-audio/skin.css +1542 -0
- package/dist/dev/internal/skins/scaffold-live-audio/template.js +96 -0
- package/dist/dev/internal/skins/scaffold-live-audio/template.js.map +1 -0
- package/dist/dev/internal/skins/scaffold-live-video/register.d.ts +45 -0
- package/dist/dev/internal/skins/scaffold-live-video/register.js +88 -0
- package/dist/dev/internal/skins/scaffold-live-video/register.js.map +1 -0
- package/dist/dev/internal/skins/scaffold-live-video/skin.css +1943 -0
- package/dist/dev/internal/skins/scaffold-live-video/template.js +243 -0
- package/dist/dev/internal/skins/scaffold-live-video/template.js.map +1 -0
- package/dist/dev/internal/skins/scaffold-video/register.d.ts +62 -0
- package/dist/dev/internal/skins/scaffold-video/register.js +117 -0
- package/dist/dev/internal/skins/scaffold-video/register.js.map +1 -0
- package/dist/dev/internal/skins/scaffold-video/skin.css +2183 -0
- package/dist/dev/internal/skins/scaffold-video/template.js +463 -0
- package/dist/dev/internal/skins/scaffold-video/template.js.map +1 -0
- package/dist/dev/media/hls-audio/adapter.d.ts +1 -1
- package/dist/dev/media/hls-audio/adapter.js +1 -1
- package/dist/dev/media/hls-audio/adapter.js.map +1 -1
- package/dist/dev/media/hls-background-video/adapter.d.ts +1 -1
- package/dist/dev/media/hls-background-video/adapter.js +1 -1
- package/dist/dev/media/hls-background-video/adapter.js.map +1 -1
- package/dist/dev/media/hls-video/adapter.d.ts +1 -1
- package/dist/dev/media/hls-video/adapter.js +1 -1
- package/dist/dev/media/hls-video/adapter.js.map +1 -1
- package/dist/dev/media/playerjs-video/adapter.d.ts +11 -0
- package/dist/dev/media/playerjs-video/adapter.js +61 -0
- package/dist/dev/media/playerjs-video/adapter.js.map +1 -0
- package/dist/dev/media/playerjs-video/index.d.ts +2 -0
- package/dist/dev/presets/audio/index.d.ts +2 -1
- package/dist/dev/presets/audio/index.js +2 -1
- package/dist/dev/presets/audio/scaffold-skin.d.ts +15 -0
- package/dist/dev/presets/audio/scaffold-skin.js +21 -0
- package/dist/dev/presets/audio/scaffold-skin.js.map +1 -0
- package/dist/dev/presets/background/skin.js +0 -2
- package/dist/dev/presets/background/skin.js.map +1 -1
- package/dist/dev/presets/live-audio/index.d.ts +2 -1
- package/dist/dev/presets/live-audio/index.js +2 -1
- package/dist/dev/presets/live-audio/scaffold-skin.d.ts +15 -0
- package/dist/dev/presets/live-audio/scaffold-skin.js +21 -0
- package/dist/dev/presets/live-audio/scaffold-skin.js.map +1 -0
- package/dist/dev/presets/live-video/index.d.ts +2 -1
- package/dist/dev/presets/live-video/index.js +2 -1
- package/dist/dev/presets/live-video/scaffold-skin.d.ts +15 -0
- package/dist/dev/presets/live-video/scaffold-skin.js +21 -0
- package/dist/dev/presets/live-video/scaffold-skin.js.map +1 -0
- package/dist/dev/presets/skin.js +0 -11
- package/dist/dev/presets/skin.js.map +1 -1
- package/dist/dev/presets/video/index.d.ts +2 -1
- package/dist/dev/presets/video/index.js +2 -1
- package/dist/dev/presets/video/scaffold-skin.d.ts +15 -0
- package/dist/dev/presets/video/scaffold-skin.js +21 -0
- package/dist/dev/presets/video/scaffold-skin.js.map +1 -0
- package/dist/dev/ui/slider/element.js +3 -1
- package/dist/dev/ui/slider/element.js.map +1 -1
- package/dist/dev/ui/time-slider/element.js +45 -9
- package/dist/dev/ui/time-slider/element.js.map +1 -1
- package/dist/dev/ui/volume-slider/element.js +3 -1
- package/dist/dev/ui/volume-slider/element.js.map +1 -1
- package/dist/dev/version.js +1 -1
- package/docs/README.md +1 -1
- package/docs/guides/browser-support.md +11 -11
- package/docs/guides/build-with-ai.md +1 -1
- package/docs/guides/build-your-own-skin.md +381 -0
- package/docs/guides/cdn.md +9 -9
- package/docs/guides/customize-skins.md +2 -1
- package/docs/guides/installation-cdn.md +4 -4
- package/docs/guides/installation-shadcn.md +3 -3
- package/docs/guides/installation-svelte.md +5 -5
- package/docs/guides/installation-vue.md +5 -5
- package/docs/guides/installation.md +5 -5
- package/docs/guides/internationalization.md +5 -5
- package/docs/guides/llms.txt +3 -2
- package/docs/guides/media-sources.md +1 -0
- package/docs/guides/migrate-from-media-chrome.md +4 -4
- package/docs/guides/migrate-from-mux-player.md +6 -6
- package/docs/guides/migrate-from-plyr.md +7 -7
- package/docs/guides/migrate-from-video-js-8.md +15 -7
- package/docs/guides/migrate-from-vidstack.md +3 -3
- package/docs/guides/migrate.md +2 -1
- package/docs/guides/presets.md +4 -4
- package/docs/guides/self-hosting.md +11 -8
- package/docs/guides/skins.md +6 -5
- package/docs/guides/v10-roadmap.md +2 -2
- package/docs/guides/why-videojs.md +3 -3
- package/docs/llms.txt +9 -3
- package/docs/reference/api/error-codes.md +1 -1
- package/docs/reference/api/llms.txt +1 -1
- package/docs/reference/api/preset-audio.md +1 -1
- package/docs/reference/api/preset-background.md +1 -1
- package/docs/reference/api/preset-live-audio.md +1 -1
- package/docs/reference/api/preset-live-video.md +1 -1
- package/docs/reference/api/preset-video.md +1 -1
- package/docs/reference/api/vjs8-legacy-init.md +2 -2
- package/docs/reference/components/audio-neutral-skin.md +1 -1
- package/docs/reference/components/audio-scaffold-skin.md +39 -0
- package/docs/reference/components/audio-skin.md +1 -1
- package/docs/reference/components/background-video-skin.md +1 -1
- package/docs/reference/components/background-video.md +1 -1
- package/docs/reference/components/cloudflare-video.md +1 -1
- package/docs/reference/components/dash-video.md +1 -1
- package/docs/reference/components/google-cast.md +1 -1
- package/docs/reference/components/hls-audio.md +2 -47
- package/docs/reference/components/hls-background-video.md +1 -1
- package/docs/reference/components/hls-video.md +7 -60
- package/docs/reference/components/hlsjs-video.md +11 -1
- package/docs/reference/components/icons.md +2 -1
- package/docs/reference/components/live-audio-neutral-skin.md +1 -1
- package/docs/reference/components/live-audio-scaffold-skin.md +41 -0
- package/docs/reference/components/live-audio-skin.md +1 -1
- package/docs/reference/components/live-video-neutral-skin.md +1 -1
- package/docs/reference/components/live-video-scaffold-skin.md +47 -0
- package/docs/reference/components/live-video-skin.md +1 -1
- package/docs/reference/components/llms.txt +6 -1
- package/docs/reference/components/mux-audio.md +1 -1
- package/docs/reference/components/mux-background-video.md +1 -1
- package/docs/reference/components/mux-data.md +4 -2
- package/docs/reference/components/mux-video.md +1 -1
- package/docs/reference/components/native-hls-video.md +1 -1
- package/docs/reference/components/playerjs-video.md +197 -0
- package/docs/reference/components/shaka-video.md +1 -1
- package/docs/reference/components/slider.md +2 -0
- package/docs/reference/components/spotify-audio.md +1 -1
- package/docs/reference/components/tiktok-video.md +1 -1
- package/docs/reference/components/time-slider.md +7 -5
- package/docs/reference/components/twitch-video.md +1 -1
- package/docs/reference/components/video-neutral-skin.md +1 -1
- package/docs/reference/components/video-scaffold-skin.md +51 -0
- package/docs/reference/components/video-skin.md +1 -1
- package/docs/reference/components/vimeo-video.md +1 -1
- package/docs/reference/components/volume-slider.md +8 -6
- package/docs/reference/components/wistia-video.md +5 -1
- package/docs/reference/components/youtube-video.md +2 -2
- package/package.json +46 -42
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element.js","names":[],"sources":["../../../../src/ui/time-slider/element.ts"],"sourcesContent":["import { TimeSliderCore, TimeSliderDataAttrs, type TimeSliderProps } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createSlider,\n getTimeSliderCSSVars,\n logMissingFeature,\n type SliderApi,\n selectBuffer,\n selectControls,\n selectPlayback,\n selectTime,\n} from '@videojs/core/dom';\nimport { type Text, translateText } from '@videojs/core/i18n';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { ContextProvider } from '@videojs/element/context';\nimport { hasTimeRange } from '@videojs/media';\nimport { applyStyles } from '@videojs/utils/dom';\nimport { formatTime } from '@videojs/utils/time';\n\nimport { i18nContext } from '../../i18n/context';\nimport { I18nController } from '../../i18n/controller';\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/controller';\nimport { sliderContext } from '../slider/context';\nimport { UIElement } from '../ui-element';\n\n/**\n * @fires drag-start - Fired when a pointer drag starts.\n * @fires drag-end - Fired when a pointer drag ends.\n */\nexport class TimeSliderElement extends UIElement {\n static readonly tagName = 'media-time-slider';\n\n static override properties = {\n label: { type: String },\n changeThrottle: { type: Number, attribute: 'change-throttle' },\n step: { type: Number },\n largeStep: { type: Number, attribute: 'large-step' },\n orientation: { type: String },\n disabled: { type: Boolean },\n thumbAlignment: { type: String, attribute: 'thumb-alignment' },\n pauseOnDrag: { type: Boolean, attribute: 'pause-on-drag' },\n } satisfies PropertyDeclarationMap<Exclude<keyof TimeSliderProps, 'value' | 'min' | 'max'>>;\n\n label: Text | string = '';\n changeThrottle = TimeSliderCore.defaultProps.changeThrottle;\n step = TimeSliderCore.defaultProps.step;\n largeStep = TimeSliderCore.defaultProps.largeStep;\n orientation = TimeSliderCore.defaultProps.orientation;\n disabled = TimeSliderCore.defaultProps.disabled;\n thumbAlignment = TimeSliderCore.defaultProps.thumbAlignment;\n pauseOnDrag = TimeSliderCore.defaultProps.pauseOnDrag;\n\n readonly #core = new TimeSliderCore();\n readonly #controlsState = new PlayerController(this, playerContext, selectControls);\n readonly #provider = new ContextProvider(this, { context: sliderContext });\n readonly #timeState = new PlayerController(this, playerContext, selectTime);\n readonly #bufferState = new PlayerController(this, playerContext, selectBuffer);\n readonly #playbackState = new PlayerController(this, playerContext, selectPlayback);\n readonly #i18n = new I18nController(this, i18nContext);\n\n #slider: SliderApi | null = null;\n #disconnect: AbortController | null = null;\n #releaseControlsLock: (() => void) | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n const signal = this.#disconnect.signal;\n\n this.#slider = createSlider({\n getElement: () => this,\n getThumbElement: () => this.querySelector<HTMLElement>('media-slider-thumb'),\n getOrientation: () => this.orientation,\n isDisabled: () => {\n const time = this.#timeState.value;\n const buffer = this.#bufferState.value;\n\n // `bufferFeature` is optional: compositions that omit it still get a working slider, with an empty buffer.\n return this.disabled || !time || !hasTimeRange({ ...time, ...(buffer ?? { buffered: [], seekable: [] }) });\n },\n getPercent: () => {\n const media = this.#timeState.value;\n if (!media) return 0;\n\n return this.#core.percentFromValue(media.currentTime);\n },\n getStepPercent: () => this.#core.getStepPercent(),\n getLargeStepPercent: () => this.#core.getLargeStepPercent(),\n onValueCommit: (percent) => {\n const media = this.#timeState.value;\n\n if (media) media.seek(this.#core.rawValueFromPercent(percent));\n },\n changeThrottle: this.changeThrottle,\n onPressStart: () => {\n this.#releaseControlsLock ??= this.#controlsState.value?.requestControlsLock() ?? null;\n },\n onPressEnd: () => this.#releaseControlsVisibilityLock(),\n onDragStart: () => {\n this.#core.startDrag(this.#playbackState.value);\n this.dispatchEvent(new CustomEvent('drag-start', { bubbles: true }));\n },\n onDragEnd: () => {\n this.#core.endDrag(this.#playbackState.value);\n this.dispatchEvent(new CustomEvent('drag-end', { bubbles: true }));\n },\n adjustPercent: (raw, thumbSize, trackSize) => this.#core.adjustPercentForAlignment(raw, thumbSize, trackSize),\n onResize: () => this.requestUpdate(),\n });\n\n applyElementProps(this, this.#slider.rootProps, { signal });\n applyStyles(this, this.#slider.rootStyle);\n this.#slider.input.subscribe(() => this.requestUpdate(), { signal });\n\n if (__DEV__ && !this.#timeState.value) {\n logMissingFeature(this.localName, this.#timeState.displayName!);\n }\n }\n\n override disconnectedCallback(): void {\n this.#releaseControlsVisibilityLock();\n this.#resumeIfDragPaused();\n super.disconnectedCallback();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#releaseControlsVisibilityLock();\n this.#resumeIfDragPaused();\n this.#slider?.destroy();\n super.destroyCallback();\n }\n\n // createSlider's destroy() does not fire onDragEnd, so a teardown mid-drag\n // would leave playback paused. Called from both disconnect and destroy paths\n // before super so the PlayerController is still attached.\n #resumeIfDragPaused(): void {\n this.#core.endDrag(this.#playbackState.value);\n }\n\n #releaseControlsVisibilityLock(): void {\n this.#releaseControlsLock?.();\n this.#releaseControlsLock = null;\n }\n\n protected override willUpdate(_changed: PropertyValues): void {\n super.willUpdate(_changed);\n this.#core.setProps({\n label: this.label,\n changeThrottle: this.changeThrottle,\n step: this.step,\n largeStep: this.largeStep,\n orientation: this.orientation,\n disabled: this.disabled,\n thumbAlignment: this.thumbAlignment,\n pauseOnDrag: this.pauseOnDrag,\n });\n this.#core.setFormatLocale(this.#i18n.locale);\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n\n if (!this.#slider) return;\n\n const time = this.#timeState.value;\n const buffer = this.#bufferState.value;\n\n if (!time) return;\n\n this.#core.setInput(this.#slider.input.current);\n const media = { ...time, ...(buffer ?? { buffered: [], seekable: [] }) };\n\n this.#core.setMedia(media);\n const state = this.#core.getState();\n\n const cssVars = getTimeSliderCSSVars(this.#slider.adjustForAlignment(state));\n const thumbAttrs = this.#core.getAttrs(state);\n\n applyStyles(this, cssVars);\n\n // Domain-specific data attributes on root (includes data-seeking).\n applyStateDataAttrs(this, state, TimeSliderDataAttrs);\n\n // Provide context to child elements with base slider data attrs.\n this.#provider.setValue({\n state,\n stateAttrMap: TimeSliderDataAttrs,\n pointerValue: this.#core.rawValueFromPercent(state.pointerPercent),\n thumbAttrs: {\n ...thumbAttrs,\n 'aria-label': translateText(thumbAttrs['aria-label'], this.#i18n.value),\n 'aria-valuetext': translateText(\n thumbAttrs['aria-valuetext'],\n this.#i18n.value,\n this.#core.getValueTextParams(state)\n ),\n },\n thumbProps: this.#slider.thumbProps,\n formatValue: (value) => formatTime(value, state.duration, { locale: this.#i18n.locale }),\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AA+BA,IAAa,oBAAb,cAAuC,UAAU;;;EAcxB,KAAA,QAAA;EACN,KAAA,iBAAA,eAAe,aAAa;EACtC,KAAA,OAAA,eAAe,aAAa;EACvB,KAAA,YAAA,eAAe,aAAa;EAC1B,KAAA,cAAA,eAAe,aAAa;EAC/B,KAAA,WAAA,eAAe,aAAa;EACtB,KAAA,iBAAA,eAAe,aAAa;EAC/B,KAAA,cAAA,eAAe,aAAa;EAEzB,KAAA,QAAA,IAAI,eAAe;EACV,KAAA,iBAAA,IAAI,iBAAiB,MAAM,eAAe,cAAc;EAC7D,KAAA,YAAA,IAAI,gBAAgB,MAAM,EAAE,SAAS,cAAc,CAAC;EACnD,KAAA,aAAA,IAAI,iBAAiB,MAAM,eAAe,UAAU;EAClD,KAAA,eAAA,IAAI,iBAAiB,MAAM,eAAe,YAAY;EACpD,KAAA,iBAAA,IAAI,iBAAiB,MAAM,eAAe,cAAc;EACjE,KAAA,QAAA,IAAI,eAAe,MAAM,WAAW;EAEzB,KAAA,UAAA;EACU,KAAA,cAAA;EACM,KAAA,uBAAA;;;EAhClB,KAAA,UAAA;;;EAEG,KAAA,aAAA;GAC3B,OAAO,EAAE,MAAM,OAAO;GACtB,gBAAgB;IAAE,MAAM;IAAQ,WAAW;GAAkB;GAC7D,MAAM,EAAE,MAAM,OAAO;GACrB,WAAW;IAAE,MAAM;IAAQ,WAAW;GAAa;GACnD,aAAa,EAAE,MAAM,OAAO;GAC5B,UAAU,EAAE,MAAM,QAAQ;GAC1B,gBAAgB;IAAE,MAAM;IAAQ,WAAW;GAAkB;GAC7D,aAAa;IAAE,MAAM;IAAS,WAAW;GAAgB;EAC3D;;CAWA;CACA;CACA;CACA;CACA;CACA;CACA;CAEA;CACA;CACA;CAEA,oBAAmC;EACjC,MAAM,kBAAkB;EAExB,IAAI,KAAK,WAAW;EAEpB,KAAK,cAAc,IAAI,gBAAgB;EACvC,MAAM,SAAS,KAAK,YAAY;EAEhC,KAAK,UAAU,aAAa;GAC1B,kBAAkB;GAClB,uBAAuB,KAAK,cAA2B,oBAAoB;GAC3E,sBAAsB,KAAK;GAC3B,kBAAkB;IAChB,MAAM,OAAO,KAAK,WAAW;IAC7B,MAAM,SAAS,KAAK,aAAa;IAGjC,OAAO,KAAK,YAAY,CAAC,QAAQ,CAAC,aAAa;KAAE,GAAG;KAAM,GAAI,UAAU;MAAE,UAAU,CAAC;MAAG,UAAU,CAAC;KAAE;IAAG,CAAC;GAC3G;GACA,kBAAkB;IAChB,MAAM,QAAQ,KAAK,WAAW;IAC9B,IAAI,CAAC,OAAO,OAAO;IAEnB,OAAO,KAAK,MAAM,iBAAiB,MAAM,WAAW;GACtD;GACA,sBAAsB,KAAK,MAAM,eAAe;GAChD,2BAA2B,KAAK,MAAM,oBAAoB;GAC1D,gBAAgB,YAAY;IAC1B,MAAM,QAAQ,KAAK,WAAW;IAE9B,IAAI,OAAO,MAAM,KAAK,KAAK,MAAM,oBAAoB,OAAO,CAAC;GAC/D;GACA,gBAAgB,KAAK;GACrB,oBAAoB;IAClB,KAAK,yBAAyB,KAAK,eAAe,OAAO,oBAAoB,KAAK;GACpF;GACA,kBAAkB,KAAK,+BAA+B;GACtD,mBAAmB;IACjB,KAAK,MAAM,UAAU,KAAK,eAAe,KAAK;IAC9C,KAAK,cAAc,IAAI,YAAY,cAAc,EAAE,SAAS,KAAK,CAAC,CAAC;GACrE;GACA,iBAAiB;IACf,KAAK,MAAM,QAAQ,KAAK,eAAe,KAAK;IAC5C,KAAK,cAAc,IAAI,YAAY,YAAY,EAAE,SAAS,KAAK,CAAC,CAAC;GACnE;GACA,gBAAgB,KAAK,WAAW,cAAc,KAAK,MAAM,0BAA0B,KAAK,WAAW,SAAS;GAC5G,gBAAgB,KAAK,cAAc;EACrC,CAAC;EAED,kBAAkB,MAAM,KAAK,QAAQ,WAAW,EAAE,OAAO,CAAC;EAC1D,YAAY,MAAM,KAAK,QAAQ,SAAS;EACxC,KAAK,QAAQ,MAAM,gBAAgB,KAAK,cAAc,GAAG,EAAE,OAAO,CAAC;EAEnE,IAAe,CAAC,KAAK,WAAW,OAC9B,kBAAkB,KAAK,WAAW,KAAK,WAAW,WAAY;CAElE;CAEA,uBAAsC;EACpC,KAAK,+BAA+B;EACpC,KAAK,oBAAoB;EACzB,MAAM,qBAAqB;EAC3B,KAAK,aAAa,MAAM;EACxB,KAAK,cAAc;CACrB;CAEA,kBAAiC;EAC/B,KAAK,+BAA+B;EACpC,KAAK,oBAAoB;EACzB,KAAK,SAAS,QAAQ;EACtB,MAAM,gBAAgB;CACxB;CAKA,sBAA4B;EAC1B,KAAK,MAAM,QAAQ,KAAK,eAAe,KAAK;CAC9C;CAEA,iCAAuC;EACrC,KAAK,uBAAuB;EAC5B,KAAK,uBAAuB;CAC9B;CAEA,WAA8B,UAAgC;EAC5D,MAAM,WAAW,QAAQ;EACzB,KAAK,MAAM,SAAS;GAClB,OAAO,KAAK;GACZ,gBAAgB,KAAK;GACrB,MAAM,KAAK;GACX,WAAW,KAAK;GAChB,aAAa,KAAK;GAClB,UAAU,KAAK;GACf,gBAAgB,KAAK;GACrB,aAAa,KAAK;EACpB,CAAC;EACD,KAAK,MAAM,gBAAgB,KAAK,MAAM,MAAM;CAC9C;CAEA,OAA0B,UAAgC;EACxD,MAAM,OAAO,QAAQ;EAErB,IAAI,CAAC,KAAK,SAAS;EAEnB,MAAM,OAAO,KAAK,WAAW;EAC7B,MAAM,SAAS,KAAK,aAAa;EAEjC,IAAI,CAAC,MAAM;EAEX,KAAK,MAAM,SAAS,KAAK,QAAQ,MAAM,OAAO;EAC9C,MAAM,QAAQ;GAAE,GAAG;GAAM,GAAI,UAAU;IAAE,UAAU,CAAC;IAAG,UAAU,CAAC;GAAE;EAAG;EAEvE,KAAK,MAAM,SAAS,KAAK;EACzB,MAAM,QAAQ,KAAK,MAAM,SAAS;EAElC,MAAM,UAAU,qBAAqB,KAAK,QAAQ,mBAAmB,KAAK,CAAC;EAC3E,MAAM,aAAa,KAAK,MAAM,SAAS,KAAK;EAE5C,YAAY,MAAM,OAAO;EAGzB,oBAAoB,MAAM,OAAO,mBAAmB;EAGpD,KAAK,UAAU,SAAS;GACtB;GACA,cAAc;GACd,cAAc,KAAK,MAAM,oBAAoB,MAAM,cAAc;GACjE,YAAY;IACV,GAAG;IACH,cAAc,cAAc,WAAW,eAAe,KAAK,MAAM,KAAK;IACtE,kBAAkB,cAChB,WAAW,mBACX,KAAK,MAAM,OACX,KAAK,MAAM,mBAAmB,KAAK,CACrC;GACF;GACA,YAAY,KAAK,QAAQ;GACzB,cAAc,UAAU,WAAW,OAAO,MAAM,UAAU,EAAE,QAAQ,KAAK,MAAM,OAAO,CAAC;EACzF,CAAC;CACH;AACF"}
|
|
1
|
+
{"version":3,"file":"element.js","names":[],"sources":["../../../../src/ui/time-slider/element.ts"],"sourcesContent":["import { SliderCSSVars, TimeSliderCore, TimeSliderDataAttrs, type TimeSliderProps } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createSlider,\n createTimeSliderSeek,\n getTimeSliderCSSVars,\n logMissingFeature,\n type SliderApi,\n selectBuffer,\n selectControls,\n selectPlayback,\n selectTime,\n} from '@videojs/core/dom';\nimport { type Text, translateText } from '@videojs/core/i18n';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { ContextProvider } from '@videojs/element/context';\nimport { hasTimeRange, isMediaPlaying } from '@videojs/media';\nimport { applyStyles } from '@videojs/utils/dom';\nimport { formatTime } from '@videojs/utils/time';\n\nimport { i18nContext } from '../../i18n/context';\nimport { I18nController } from '../../i18n/controller';\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/controller';\nimport { sliderContext } from '../slider/context';\nimport { UIElement } from '../ui-element';\n\n/**\n * @fires drag-start - Fired when a pointer drag starts.\n * @fires drag-end - Fired when a pointer drag ends.\n */\nexport class TimeSliderElement extends UIElement {\n static readonly tagName = 'media-time-slider';\n\n static override properties = {\n label: { type: String },\n changeThrottle: { type: Number, attribute: 'change-throttle' },\n step: { type: Number },\n largeStep: { type: Number, attribute: 'large-step' },\n orientation: { type: String },\n disabled: { type: Boolean },\n thumbAlignment: { type: String, attribute: 'thumb-alignment' },\n pauseOnDrag: { type: Boolean, attribute: 'pause-on-drag' },\n } satisfies PropertyDeclarationMap<Exclude<keyof TimeSliderProps, 'value' | 'min' | 'max'>>;\n\n label: Text | string = '';\n changeThrottle = TimeSliderCore.defaultProps.changeThrottle;\n step = TimeSliderCore.defaultProps.step;\n largeStep = TimeSliderCore.defaultProps.largeStep;\n orientation = TimeSliderCore.defaultProps.orientation;\n disabled = TimeSliderCore.defaultProps.disabled;\n thumbAlignment = TimeSliderCore.defaultProps.thumbAlignment;\n pauseOnDrag = TimeSliderCore.defaultProps.pauseOnDrag;\n\n readonly #core = new TimeSliderCore();\n readonly #controlsState = new PlayerController(this, playerContext, selectControls);\n readonly #provider = new ContextProvider(this, { context: sliderContext });\n readonly #timeState = new PlayerController(this, playerContext, selectTime);\n readonly #bufferState = new PlayerController(this, playerContext, selectBuffer);\n readonly #playbackState = new PlayerController(this, playerContext, selectPlayback);\n readonly #seek = createTimeSliderSeek(SliderCSSVars.fill);\n readonly #i18n = new I18nController(this, i18nContext);\n\n #cssVars: Record<string, string> = {};\n #slider: SliderApi | null = null;\n #disconnect: AbortController | null = null;\n #releaseControlsLock: (() => void) | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n const signal = this.#disconnect.signal;\n\n let dragSeekPercent: number | undefined;\n\n const seek = (percent: number) => {\n const media = this.#timeState.value;\n\n if (media) {\n const time = this.#core.rawValueFromPercent(percent);\n\n this.#seek.seek(percent);\n media.seek(time);\n }\n };\n\n this.#slider = createSlider({\n getElement: () => this,\n getThumbElement: () => this.querySelector<HTMLElement>('media-slider-thumb'),\n getOrientation: () => this.orientation,\n isDisabled: () => {\n const time = this.#timeState.value;\n const buffer = this.#bufferState.value;\n\n // `bufferFeature` is optional: compositions that omit it still get a working slider, with an empty buffer.\n return this.disabled || !time || !hasTimeRange({ ...time, ...(buffer ?? { buffered: [], seekable: [] }) });\n },\n getPercent: () => {\n const media = this.#timeState.value;\n if (!media) return 0;\n\n return this.#core.percentFromValue(media.currentTime);\n },\n getStepPercent: () => this.#core.getStepPercent(),\n getLargeStepPercent: () => this.#core.getLargeStepPercent(),\n // Seek on each (throttled) change while dragging so the frame follows the thumb.\n // Presses and key steps seek once, on commit.\n onValueChange: (percent) => {\n if (!this.#slider?.input.current.dragging || percent === dragSeekPercent) return;\n\n dragSeekPercent = percent;\n seek(percent);\n },\n onValueCommit: (percent) => {\n // Skip the commit when the drag already sought this position.\n if (percent !== dragSeekPercent) seek(percent);\n\n dragSeekPercent = undefined;\n },\n changeThrottle: this.changeThrottle,\n onPressStart: () => {\n this.#releaseControlsLock ??= this.#controlsState.value?.requestControlsLock() ?? null;\n },\n onPressEnd: () => this.#releaseControlsVisibilityLock(),\n onDragStart: () => {\n this.#core.startDrag(this.#playbackState.value);\n this.dispatchEvent(new CustomEvent('drag-start', { bubbles: true }));\n },\n onDragEnd: () => {\n this.#core.endDrag(this.#playbackState.value);\n this.dispatchEvent(new CustomEvent('drag-end', { bubbles: true }));\n },\n adjustPercent: (raw, thumbSize, trackSize) => this.#core.adjustPercentForAlignment(raw, thumbSize, trackSize),\n // Only edge alignment depends on the slider's size.\n onResize: () => {\n if (this.thumbAlignment === 'edge') this.requestUpdate();\n },\n });\n\n applyElementProps(this, this.#slider.rootProps, { signal });\n applyStyles(this, this.#slider.rootStyle);\n this.#slider.input.subscribe(() => this.requestUpdate(), { signal });\n this.#seek.state.subscribe(() => this.requestUpdate(), { signal });\n\n if (__DEV__ && !this.#timeState.value) {\n logMissingFeature(this.localName, this.#timeState.displayName!);\n }\n }\n\n override disconnectedCallback(): void {\n this.#releaseControlsVisibilityLock();\n this.#resumeIfDragPaused();\n this.#seek.destroy();\n super.disconnectedCallback();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#releaseControlsVisibilityLock();\n this.#resumeIfDragPaused();\n this.#seek.destroy();\n this.#slider?.destroy();\n super.destroyCallback();\n }\n\n // createSlider's destroy() does not fire onDragEnd, so a teardown mid-drag\n // would leave playback paused. Called from both disconnect and destroy paths\n // before super so the PlayerController is still attached.\n #resumeIfDragPaused(): void {\n this.#core.endDrag(this.#playbackState.value);\n }\n\n #releaseControlsVisibilityLock(): void {\n this.#releaseControlsLock?.();\n this.#releaseControlsLock = null;\n }\n\n protected override willUpdate(_changed: PropertyValues): void {\n super.willUpdate(_changed);\n this.#core.setProps({\n label: this.label,\n changeThrottle: this.changeThrottle,\n step: this.step,\n largeStep: this.largeStep,\n orientation: this.orientation,\n disabled: this.disabled,\n thumbAlignment: this.thumbAlignment,\n pauseOnDrag: this.pauseOnDrag,\n });\n this.#core.setFormatLocale(this.#i18n.locale);\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n\n if (!this.#slider) return;\n\n const time = this.#timeState.value;\n const buffer = this.#bufferState.value;\n\n if (!time) {\n this.#seek.destroy();\n this.removeAttribute('data-playing');\n return;\n }\n\n this.#core.setInput(this.#slider.input.current);\n const media = { ...time, ...(buffer ?? { buffered: [], seekable: [] }) };\n\n this.#core.setMedia(media);\n const state = this.#core.getState();\n\n this.#seek.update(state.seeking, state.fillPercent, this);\n const percent = this.#seek.state.current.percent;\n\n this.toggleAttribute(\n 'data-playing',\n isMediaPlaying(this.#playbackState.value) &&\n !state.disabled &&\n !state.dragging &&\n !state.seeking &&\n percent === undefined\n );\n\n const fill = percent === undefined || state.dragging || state.disabled ? state : { ...state, fillPercent: percent };\n const cssVars = getTimeSliderCSSVars(this.#slider.adjustForAlignment(fill));\n const styles = Object.fromEntries(Object.entries(cssVars).filter(([name, value]) => this.#cssVars[name] !== value));\n\n applyStyles(this, styles);\n this.#cssVars = cssVars;\n\n const thumbAttrs = this.#core.getAttrs(state);\n\n // Domain-specific data attributes on root (includes data-seeking).\n applyStateDataAttrs(this, state, TimeSliderDataAttrs);\n\n // Provide context to child elements with base slider data attrs.\n this.#provider.setValue({\n state,\n stateAttrMap: TimeSliderDataAttrs,\n pointerValue: this.#core.rawValueFromPercent(state.pointerPercent),\n thumbAttrs: {\n ...thumbAttrs,\n 'aria-label': translateText(thumbAttrs['aria-label'], this.#i18n.value),\n 'aria-valuetext': translateText(\n thumbAttrs['aria-valuetext'],\n this.#i18n.value,\n this.#core.getValueTextParams(state)\n ),\n },\n thumbProps: this.#slider.thumbProps,\n formatValue: (value) => formatTime(value, state.duration, { locale: this.#i18n.locale }),\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -97,7 +97,9 @@ var VolumeSliderElement = class extends UIElement {
|
|
|
97
97
|
this.dispatchEvent(new CustomEvent("drag-end", { bubbles: true }));
|
|
98
98
|
},
|
|
99
99
|
adjustPercent: (raw, thumbSize, trackSize) => this.#core.adjustPercentForAlignment(raw, thumbSize, trackSize),
|
|
100
|
-
onResize: () =>
|
|
100
|
+
onResize: () => {
|
|
101
|
+
if (this.thumbAlignment === "edge") this.requestUpdate();
|
|
102
|
+
}
|
|
101
103
|
});
|
|
102
104
|
const wheelProps = createWheelStep({
|
|
103
105
|
isDisabled,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"element.js","names":[],"sources":["../../../../src/ui/volume-slider/element.ts"],"sourcesContent":["import { VolumeSliderCore, VolumeSliderDataAttrs, type VolumeSliderProps } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createSlider,\n createWheelStep,\n getSliderCSSVars,\n logMissingFeature,\n type SliderApi,\n selectControls,\n selectVolume,\n} from '@videojs/core/dom';\nimport { type Text, translateText } from '@videojs/core/i18n';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { ContextProvider } from '@videojs/element/context';\nimport { applyStyles } from '@videojs/utils/dom';\n\nimport { i18nContext } from '../../i18n/context';\nimport { I18nController } from '../../i18n/controller';\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/controller';\nimport { sliderContext } from '../slider/context';\nimport { UIElement } from '../ui-element';\n\n/**\n * @fires drag-start - Fired when a pointer drag starts.\n * @fires drag-end - Fired when a pointer drag ends.\n */\nexport class VolumeSliderElement extends UIElement {\n static readonly tagName = 'media-volume-slider';\n\n static override properties = {\n label: { type: String },\n step: { type: Number },\n largeStep: { type: Number, attribute: 'large-step' },\n wheelStep: { type: Number, attribute: 'wheel-step' },\n orientation: { type: String },\n disabled: { type: Boolean },\n thumbAlignment: { type: String, attribute: 'thumb-alignment' },\n } satisfies PropertyDeclarationMap<Exclude<keyof VolumeSliderProps, 'value' | 'min' | 'max'>>;\n\n label: Text | string = '';\n step = VolumeSliderCore.defaultProps.step;\n largeStep = VolumeSliderCore.defaultProps.largeStep;\n wheelStep = VolumeSliderCore.defaultProps.wheelStep;\n orientation = VolumeSliderCore.defaultProps.orientation;\n disabled = VolumeSliderCore.defaultProps.disabled;\n thumbAlignment = VolumeSliderCore.defaultProps.thumbAlignment;\n\n readonly #core = new VolumeSliderCore();\n readonly #controlsState = new PlayerController(this, playerContext, selectControls);\n readonly #provider = new ContextProvider(this, { context: sliderContext });\n readonly #volumeState = new PlayerController(this, playerContext, selectVolume);\n readonly #i18n = new I18nController(this, i18nContext);\n\n #slider: SliderApi | null = null;\n #disconnect: AbortController | null = null;\n #releaseControlsLock: (() => void) | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n const signal = this.#disconnect.signal;\n\n const isDisabled = () => {\n const volume = this.#volumeState.value;\n\n return this.disabled || !volume || volume.volumeAvailability !== 'available';\n };\n\n const getPercent = () => (this.#volumeState.value?.volume ?? 0) * 100;\n const getStepPercent = () => this.#core.getStepPercent();\n const setVolume = (percent: number) => this.#setVolume(percent);\n\n this.#slider = createSlider({\n getElement: () => this,\n getThumbElement: () => this.querySelector<HTMLElement>('media-slider-thumb'),\n getOrientation: () => this.orientation,\n isDisabled,\n getPercent,\n getStepPercent,\n getLargeStepPercent: () => this.#core.getLargeStepPercent(),\n onValueChange: setVolume,\n onValueCommit: setVolume,\n onPressStart: () => {\n this.#releaseControlsLock ??= this.#controlsState.value?.requestControlsLock() ?? null;\n },\n onPressEnd: () => this.#releaseControlsVisibilityLock(),\n onDragStart: () => {\n this.dispatchEvent(new CustomEvent('drag-start', { bubbles: true }));\n },\n onDragEnd: () => {\n this.dispatchEvent(new CustomEvent('drag-end', { bubbles: true }));\n },\n adjustPercent: (raw, thumbSize, trackSize) => this.#core.adjustPercentForAlignment(raw, thumbSize, trackSize),\n onResize: () => this.requestUpdate(),\n });\n\n const wheelProps = createWheelStep({\n isDisabled,\n getPercent,\n getStepPercent: () => this.#core.getWheelStepPercent(),\n onValueChange: (percent) => this.#volumeState.value?.setVolume(this.#core.rawValueFromPercent(percent) / 100),\n });\n\n applyElementProps(this, this.#slider.rootProps, { signal });\n applyElementProps(this, wheelProps, { signal });\n applyStyles(this, this.#slider.rootStyle);\n this.#slider.input.subscribe(() => this.requestUpdate(), { signal });\n\n if (__DEV__ && !this.#volumeState.value) {\n logMissingFeature(this.localName, this.#volumeState.displayName!);\n }\n }\n\n override disconnectedCallback(): void {\n this.#releaseControlsVisibilityLock();\n super.disconnectedCallback();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#releaseControlsVisibilityLock();\n this.#slider?.destroy();\n super.destroyCallback();\n }\n\n #releaseControlsVisibilityLock(): void {\n this.#releaseControlsLock?.();\n this.#releaseControlsLock = null;\n }\n\n protected override willUpdate(_changed: PropertyValues): void {\n super.willUpdate(_changed);\n this.#core.setProps(this);\n this.#core.setFormatLocale(this.#i18n.locale);\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n\n if (!this.#slider) return;\n\n const media = this.#volumeState.value;\n if (!media) return;\n\n this.#core.setInput(this.#slider.input.current);\n this.#core.setMedia(media);\n const state = this.#core.getState();\n\n const cssVars = getSliderCSSVars(this.#slider.adjustForAlignment(state));\n const thumbAttrs = this.#core.getAttrs(state);\n\n applyStyles(this, cssVars);\n\n // Apply data attributes to root.\n applyStateDataAttrs(this, state, VolumeSliderDataAttrs);\n applyElementProps(this, { hidden: state.hidden ? '' : undefined });\n\n // Provide context to child elements.\n this.#provider.setValue({\n state,\n stateAttrMap: VolumeSliderDataAttrs,\n pointerValue: this.#core.valueFromPercent(state.pointerPercent),\n thumbAttrs: {\n ...thumbAttrs,\n 'aria-label': translateText(thumbAttrs['aria-label'], this.#i18n.value),\n 'aria-valuetext': translateText(\n thumbAttrs['aria-valuetext'],\n this.#i18n.value,\n this.#core.getValueTextParams(state)\n ),\n },\n thumbProps: this.#slider.thumbProps,\n formatValue: (value) => `${Math.round(value)}%`,\n });\n }\n\n #setVolume(percent: number): void {\n const media = this.#volumeState.value;\n\n media?.setVolume(this.#core.valueFromPercent(percent) / 100);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"element.js","names":[],"sources":["../../../../src/ui/volume-slider/element.ts"],"sourcesContent":["import { VolumeSliderCore, VolumeSliderDataAttrs, type VolumeSliderProps } from '@videojs/core';\nimport {\n applyElementProps,\n applyStateDataAttrs,\n createSlider,\n createWheelStep,\n getSliderCSSVars,\n logMissingFeature,\n type SliderApi,\n selectControls,\n selectVolume,\n} from '@videojs/core/dom';\nimport { type Text, translateText } from '@videojs/core/i18n';\nimport type { PropertyDeclarationMap, PropertyValues } from '@videojs/element';\nimport { ContextProvider } from '@videojs/element/context';\nimport { applyStyles } from '@videojs/utils/dom';\n\nimport { i18nContext } from '../../i18n/context';\nimport { I18nController } from '../../i18n/controller';\nimport { playerContext } from '../../player/context';\nimport { PlayerController } from '../../player/controller';\nimport { sliderContext } from '../slider/context';\nimport { UIElement } from '../ui-element';\n\n/**\n * @fires drag-start - Fired when a pointer drag starts.\n * @fires drag-end - Fired when a pointer drag ends.\n */\nexport class VolumeSliderElement extends UIElement {\n static readonly tagName = 'media-volume-slider';\n\n static override properties = {\n label: { type: String },\n step: { type: Number },\n largeStep: { type: Number, attribute: 'large-step' },\n wheelStep: { type: Number, attribute: 'wheel-step' },\n orientation: { type: String },\n disabled: { type: Boolean },\n thumbAlignment: { type: String, attribute: 'thumb-alignment' },\n } satisfies PropertyDeclarationMap<Exclude<keyof VolumeSliderProps, 'value' | 'min' | 'max'>>;\n\n label: Text | string = '';\n step = VolumeSliderCore.defaultProps.step;\n largeStep = VolumeSliderCore.defaultProps.largeStep;\n wheelStep = VolumeSliderCore.defaultProps.wheelStep;\n orientation = VolumeSliderCore.defaultProps.orientation;\n disabled = VolumeSliderCore.defaultProps.disabled;\n thumbAlignment = VolumeSliderCore.defaultProps.thumbAlignment;\n\n readonly #core = new VolumeSliderCore();\n readonly #controlsState = new PlayerController(this, playerContext, selectControls);\n readonly #provider = new ContextProvider(this, { context: sliderContext });\n readonly #volumeState = new PlayerController(this, playerContext, selectVolume);\n readonly #i18n = new I18nController(this, i18nContext);\n\n #slider: SliderApi | null = null;\n #disconnect: AbortController | null = null;\n #releaseControlsLock: (() => void) | null = null;\n\n override connectedCallback(): void {\n super.connectedCallback();\n\n if (this.destroyed) return;\n\n this.#disconnect = new AbortController();\n const signal = this.#disconnect.signal;\n\n const isDisabled = () => {\n const volume = this.#volumeState.value;\n\n return this.disabled || !volume || volume.volumeAvailability !== 'available';\n };\n\n const getPercent = () => (this.#volumeState.value?.volume ?? 0) * 100;\n const getStepPercent = () => this.#core.getStepPercent();\n const setVolume = (percent: number) => this.#setVolume(percent);\n\n this.#slider = createSlider({\n getElement: () => this,\n getThumbElement: () => this.querySelector<HTMLElement>('media-slider-thumb'),\n getOrientation: () => this.orientation,\n isDisabled,\n getPercent,\n getStepPercent,\n getLargeStepPercent: () => this.#core.getLargeStepPercent(),\n onValueChange: setVolume,\n onValueCommit: setVolume,\n onPressStart: () => {\n this.#releaseControlsLock ??= this.#controlsState.value?.requestControlsLock() ?? null;\n },\n onPressEnd: () => this.#releaseControlsVisibilityLock(),\n onDragStart: () => {\n this.dispatchEvent(new CustomEvent('drag-start', { bubbles: true }));\n },\n onDragEnd: () => {\n this.dispatchEvent(new CustomEvent('drag-end', { bubbles: true }));\n },\n adjustPercent: (raw, thumbSize, trackSize) => this.#core.adjustPercentForAlignment(raw, thumbSize, trackSize),\n // Only edge alignment depends on the slider's size.\n onResize: () => {\n if (this.thumbAlignment === 'edge') this.requestUpdate();\n },\n });\n\n const wheelProps = createWheelStep({\n isDisabled,\n getPercent,\n getStepPercent: () => this.#core.getWheelStepPercent(),\n onValueChange: (percent) => this.#volumeState.value?.setVolume(this.#core.rawValueFromPercent(percent) / 100),\n });\n\n applyElementProps(this, this.#slider.rootProps, { signal });\n applyElementProps(this, wheelProps, { signal });\n applyStyles(this, this.#slider.rootStyle);\n this.#slider.input.subscribe(() => this.requestUpdate(), { signal });\n\n if (__DEV__ && !this.#volumeState.value) {\n logMissingFeature(this.localName, this.#volumeState.displayName!);\n }\n }\n\n override disconnectedCallback(): void {\n this.#releaseControlsVisibilityLock();\n super.disconnectedCallback();\n this.#disconnect?.abort();\n this.#disconnect = null;\n }\n\n override destroyCallback(): void {\n this.#releaseControlsVisibilityLock();\n this.#slider?.destroy();\n super.destroyCallback();\n }\n\n #releaseControlsVisibilityLock(): void {\n this.#releaseControlsLock?.();\n this.#releaseControlsLock = null;\n }\n\n protected override willUpdate(_changed: PropertyValues): void {\n super.willUpdate(_changed);\n this.#core.setProps(this);\n this.#core.setFormatLocale(this.#i18n.locale);\n }\n\n protected override update(_changed: PropertyValues): void {\n super.update(_changed);\n\n if (!this.#slider) return;\n\n const media = this.#volumeState.value;\n if (!media) return;\n\n this.#core.setInput(this.#slider.input.current);\n this.#core.setMedia(media);\n const state = this.#core.getState();\n\n const cssVars = getSliderCSSVars(this.#slider.adjustForAlignment(state));\n const thumbAttrs = this.#core.getAttrs(state);\n\n applyStyles(this, cssVars);\n\n // Apply data attributes to root.\n applyStateDataAttrs(this, state, VolumeSliderDataAttrs);\n applyElementProps(this, { hidden: state.hidden ? '' : undefined });\n\n // Provide context to child elements.\n this.#provider.setValue({\n state,\n stateAttrMap: VolumeSliderDataAttrs,\n pointerValue: this.#core.valueFromPercent(state.pointerPercent),\n thumbAttrs: {\n ...thumbAttrs,\n 'aria-label': translateText(thumbAttrs['aria-label'], this.#i18n.value),\n 'aria-valuetext': translateText(\n thumbAttrs['aria-valuetext'],\n this.#i18n.value,\n this.#core.getValueTextParams(state)\n ),\n },\n thumbProps: this.#slider.thumbProps,\n formatValue: (value) => `${Math.round(value)}%`,\n });\n }\n\n #setVolume(percent: number): void {\n const media = this.#volumeState.value;\n\n media?.setVolume(this.#core.valueFromPercent(percent) / 100);\n }\n}\n"],"mappings":"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"}
|
package/dist/dev/version.js
CHANGED
package/docs/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Browsers and rendering environments supported by Video.js 10, and how the packag
|
|
|
12
12
|
| Safari | 16.4 and later |
|
|
13
13
|
| Safari on iOS | 16.4 and later |
|
|
14
14
|
|
|
15
|
-
These versions account for
|
|
15
|
+
These versions account for 92.5% of global web usage according to [caniuse-lite](https://github.com/browserslist/caniuse-lite) 1.0.30001815, and this figure updates when we update that data.
|
|
16
16
|
|
|
17
17
|
We test in and fix bugs for these versions. Each minimum comes from a feature with no fallback: `:has()` sets Firefox, [`color-mix()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/color-mix) and [`oklch()`](https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/oklch) set Chrome and Edge (Chrome 111, Firefox 113, Safari 16.2), and the JavaScript sets Safari, because it uses ES2022 syntax and [`adoptedStyleSheets`](https://developer.mozilla.org/en-US/docs/Web/API/Document/adoptedStyleSheets). Newer JavaScript APIs are feature-detected.
|
|
18
18
|
|
|
@@ -36,16 +36,16 @@ The table reads the first fully supporting version of each feature from [caniuse
|
|
|
36
36
|
|
|
37
37
|
| Feature | Chrome and Edge | Firefox | Safari and iOS | Global support |
|
|
38
38
|
| --- | --- | --- | --- | --- |
|
|
39
|
-
| [`@scope`](https://caniuse.com/css-cascade-scope) Has a fallback. Packaged skins use :where() selectors instead; registry CSS skins need it. | 118 | 146 | 17.4 |
|
|
40
|
-
| [`@layer`](https://caniuse.com/css-cascade-layers) Required. No component styling. | 99 | 97 | 15.4 |
|
|
41
|
-
| [`:has()`](https://caniuse.com/css-has) Required. Menu and slider focus states are lost. | 105 | 121 | 15.4 | 94.
|
|
42
|
-
| [`@container`](https://caniuse.com/css-container-queries) Required. Controls do not adapt to player width. | 106 | 110 | 16 | 94.
|
|
43
|
-
| [`Media query range syntax`](https://caniuse.com/css-media-range-syntax) Required. Large-screen sizing is lost. | 104 | 63 | 16.4 | 94.
|
|
44
|
-
| [`:dir()`](https://caniuse.com/css-dir-pseudo) Has a fallback. Right-to-left layout follows the dir attribute instead. | 120 | 17 | 16.4 |
|
|
45
|
-
| [`Relative color syntax`](https://caniuse.com/css-relative-colors) Degrades. Control scrims fall back to color-mix(), and subtle shadows are lost. | 131 | 133 | 18 |
|
|
46
|
-
| [`scrollbar-color and scrollbar-width`](https://caniuse.com/css-scrollbar) Degrades. Menus show default scrollbars. | 121 | 64 | 26.2 |
|
|
47
|
-
| [`backdrop-filter`](https://caniuse.com/css-backdrop-filter) Degrades. Surfaces lose their blur. | 76 / 17 | 103 | 9 |
|
|
48
|
-
| [`Anchor positioning`](https://caniuse.com/css-anchor-positioning) Has a fallback. Popups are positioned by JavaScript. |
|
|
39
|
+
| [`@scope`](https://caniuse.com/css-cascade-scope) Has a fallback. Packaged skins use :where() selectors instead; registry CSS skins need it. | 118 | 146 | 17.4 | 91.7% |
|
|
40
|
+
| [`@layer`](https://caniuse.com/css-cascade-layers) Required. No component styling. | 99 | 97 | 15.4 | 96.0% |
|
|
41
|
+
| [`:has()`](https://caniuse.com/css-has) Required. Menu and slider focus states are lost. | 105 | 121 | 15.4 | 94.8% |
|
|
42
|
+
| [`@container`](https://caniuse.com/css-container-queries) Required. Controls do not adapt to player width. | 106 | 110 | 16 | 94.8% |
|
|
43
|
+
| [`Media query range syntax`](https://caniuse.com/css-media-range-syntax) Required. Large-screen sizing is lost. | 104 | 63 | 16.4 | 94.8% |
|
|
44
|
+
| [`:dir()`](https://caniuse.com/css-dir-pseudo) Has a fallback. Right-to-left layout follows the dir attribute instead. | 120 | 17 | 16.4 | 92.5% |
|
|
45
|
+
| [`Relative color syntax`](https://caniuse.com/css-relative-colors) Degrades. Control scrims fall back to color-mix(), and subtle shadows are lost. | 131 | 133 | 18 | 87.0% |
|
|
46
|
+
| [`scrollbar-color and scrollbar-width`](https://caniuse.com/css-scrollbar) Degrades. Menus show default scrollbars. | 121 | 64 | 26.2 | 87.0% |
|
|
47
|
+
| [`backdrop-filter`](https://caniuse.com/css-backdrop-filter) Degrades. Surfaces lose their blur. | 76 / 17 | 103 | 9 | 96.4% |
|
|
48
|
+
| [`Anchor positioning`](https://caniuse.com/css-anchor-positioning) Has a fallback. Popups are positioned by JavaScript. | Not supported | Not supported | 27 | 0.0% |
|
|
49
49
|
|
|
50
50
|
Older browsers than the baseline are not tested. Without `:has()`, `@container`, `@layer`, `color-mix()`, or `oklch()`, the skins lose focus states, layout, or colors.
|
|
51
51
|
|
|
@@ -121,7 +121,7 @@ The old `npx @videojs/cli docs` workflow was removed. `@videojs/cli` now contain
|
|
|
121
121
|
|
|
122
122
|
If your agent does not use the skill, start a new session or reload plugins, then ask it to use the Video.js skill explicitly. If it writes `videojs()`, `data-setup`, `registerPlugin`, or other Video.js 8 APIs, ask it to read the installed `llms.txt` before changing code.
|
|
123
123
|
|
|
124
|
-
Report problems with the skill in the [videojs/skills repository](https://github.com/videojs/skills/issues). Report package and documentation problems in [videojs/
|
|
124
|
+
Report problems with the skill in the [videojs/skills repository](https://github.com/videojs/skills/issues). Report package and documentation problems in [videojs/video.js](https://github.com/videojs/video.js/issues).
|
|
125
125
|
|
|
126
126
|
## Use the docs
|
|
127
127
|
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
# Build your own skin
|
|
2
|
+
|
|
3
|
+
Create a skin project, preview it locally, and compose your own player interface from Video.js UI components
|
|
4
|
+
|
|
5
|
+
A skin is the player interface: markup that arranges Video.js UI components inside the player, plus the styles that give it a look. The components handle playback state, keyboard support, and accessibility, so building your own skin is mostly a layout and design job. [Skins](./skins.md) explains how skins fit into Video.js.
|
|
6
|
+
|
|
7
|
+
If a packaged skin is already close to what you want, [Customize skins](./customize-skins.md) is less work.
|
|
8
|
+
|
|
9
|
+
## Create a skin project
|
|
10
|
+
|
|
11
|
+
The quickest way to start is a standalone skin project:
|
|
12
|
+
|
|
13
|
+
**npm**
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npx @videojs/cli skin create
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**pnpm**
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
pnpm dlx @videojs/cli skin create
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**yarn**
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @videojs/cli skin create --package-manager yarn
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**bun**
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
bunx @videojs/cli skin create
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The command asks for a name, a framework (React or HTML), a styling approach (Tailwind or CSS), a starting skin, and a preset (video, audio, live video, or live audio). The starting skin defaults to [Scaffold](../reference/components/video-scaffold-skin.md): every control wired up, with minimal styling and no transitions, so there’s little to undo.
|
|
38
|
+
|
|
39
|
+
The project goes in a folder named after the skin, so a skin called “My Skin” goes in `my-skin`. Open it and start the preview:
|
|
40
|
+
|
|
41
|
+
**npm**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
cd my-skin
|
|
45
|
+
npm run dev
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**pnpm**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
cd my-skin
|
|
52
|
+
pnpm dev
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
**yarn**
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
cd my-skin
|
|
59
|
+
yarn dev
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**bun**
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd my-skin
|
|
66
|
+
bun dev
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
The project has two parts:
|
|
70
|
+
|
|
71
|
+
- **`src/`** holds the skin and nothing else. Edit it however you like, including its markup, class names, theme tokens, and stylesheets.
|
|
72
|
+
- **`apps/preview/`** is a workbench that plays your skin. Use it to try different player sizes and aspect ratios, light and dark color schemes, right-to-left text, every built-in language, and playback settings such as autoplay and loop.
|
|
73
|
+
|
|
74
|
+
When you want to share it, deploy the workbench to Vercel, Netlify, or Cloudflare Pages:
|
|
75
|
+
|
|
76
|
+
**npm**
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
npm run deploy
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**pnpm**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
pnpm run deploy
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
**yarn**
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
yarn run deploy
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**bun**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
bun run deploy
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Add the host’s name to skip the question, as in `npm run deploy vercel`. With pnpm, keep the `run`, since `pnpm deploy` is a built-in pnpm command. When the skin is done, move `src/` into your app.
|
|
101
|
+
|
|
102
|
+
### Build it with a coding agent
|
|
103
|
+
|
|
104
|
+
If you work with a coding agent, such as Claude Code, Codex, or Cursor, it can do all of this for you. Install the Video.js skills, which include a skill for building skins:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
npx @videojs/cli agents skills
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Then ask your agent something like “Help me design my own Video.js skin for our podcast player.” It asks for the same choices as the command, creates the project, starts the workbench, and agrees a design with you before styling. It can also match an existing player’s look from a screenshot or a link, then checks its work against the reference and for accessibility before handing back. [Build with AI](./build-with-ai.md) covers installing the skills in each agent.
|
|
111
|
+
|
|
112
|
+
## Other starting points
|
|
113
|
+
|
|
114
|
+
- **Inside an existing app.** Add a skin’s source with [Install with Shadcn](./installation-shadcn.md) and pick **Scaffold** as the skin.
|
|
115
|
+
- **From nothing.** Put a [Container](../reference/components/player-container.md) inside your player and add the components you want, as in the example below.
|
|
116
|
+
|
|
117
|
+
No path requires Scaffold’s structure, its theme tokens, or any particular CSS approach.
|
|
118
|
+
|
|
119
|
+
## A minimal skin
|
|
120
|
+
|
|
121
|
+
This example shows how a skin fits together without Scaffold’s extra parts. It has a play button, a timeline, the current time, mute, fullscreen, keyboard shortcuts, screen reader announcements, and an error dialog. The player provides state, the Container is the skin’s root, and the media element goes inside the Container next to the controls.
|
|
122
|
+
|
|
123
|
+
**index.html**
|
|
124
|
+
|
|
125
|
+
```html
|
|
126
|
+
<script type="module">
|
|
127
|
+
import '@videojs/html/video/player';
|
|
128
|
+
import '@videojs/html/ui/container';
|
|
129
|
+
import '@videojs/html/ui/controls';
|
|
130
|
+
import '@videojs/html/ui/controls-content';
|
|
131
|
+
import '@videojs/html/ui/controls-group';
|
|
132
|
+
import '@videojs/html/ui/play-button';
|
|
133
|
+
import '@videojs/html/ui/time-slider';
|
|
134
|
+
import '@videojs/html/ui/slider-track';
|
|
135
|
+
import '@videojs/html/ui/slider-buffer';
|
|
136
|
+
import '@videojs/html/ui/slider-fill';
|
|
137
|
+
import '@videojs/html/ui/slider-thumb';
|
|
138
|
+
import '@videojs/html/ui/time';
|
|
139
|
+
import '@videojs/html/ui/mute-button';
|
|
140
|
+
import '@videojs/html/ui/fullscreen-button';
|
|
141
|
+
import '@videojs/html/ui/hotkey';
|
|
142
|
+
import '@videojs/html/ui/status-announcer';
|
|
143
|
+
import '@videojs/html/ui/error-dialog';
|
|
144
|
+
import '@videojs/html/ui/dialog-popup';
|
|
145
|
+
import '@videojs/html/ui/dialog-title';
|
|
146
|
+
import '@videojs/html/ui/dialog-description';
|
|
147
|
+
import '@videojs/html/ui/dialog-close';
|
|
148
|
+
</script>
|
|
149
|
+
|
|
150
|
+
<video-player>
|
|
151
|
+
<media-container class="video-skin">
|
|
152
|
+
<video src="video.mp4" playsinline></video>
|
|
153
|
+
|
|
154
|
+
<media-controls>
|
|
155
|
+
<media-controls-content class="video-skin-controls">
|
|
156
|
+
<media-time-slider class="video-skin-time-slider">
|
|
157
|
+
<media-slider-track class="video-skin-track">
|
|
158
|
+
<media-slider-buffer class="video-skin-buffer"></media-slider-buffer>
|
|
159
|
+
<media-slider-fill class="video-skin-fill"></media-slider-fill>
|
|
160
|
+
</media-slider-track>
|
|
161
|
+
<media-slider-thumb class="video-skin-thumb"></media-slider-thumb>
|
|
162
|
+
</media-time-slider>
|
|
163
|
+
|
|
164
|
+
<media-controls-group class="video-skin-controls-group" aria-label="Playback controls">
|
|
165
|
+
<media-play-button class="video-skin-play">
|
|
166
|
+
<span class="show-when-paused">Play</span>
|
|
167
|
+
<span class="show-when-playing">Pause</span>
|
|
168
|
+
</media-play-button>
|
|
169
|
+
<media-time type="current"></media-time>
|
|
170
|
+
<media-mute-button class="video-skin-mute">
|
|
171
|
+
<span class="show-when-muted">Unmute</span>
|
|
172
|
+
<span class="show-when-unmuted">Mute</span>
|
|
173
|
+
</media-mute-button>
|
|
174
|
+
<media-fullscreen-button class="video-skin-fullscreen">
|
|
175
|
+
<span class="show-when-fullscreen">Exit fullscreen</span>
|
|
176
|
+
<span class="show-when-not-fullscreen">Fullscreen</span>
|
|
177
|
+
</media-fullscreen-button>
|
|
178
|
+
</media-controls-group>
|
|
179
|
+
</media-controls-content>
|
|
180
|
+
</media-controls>
|
|
181
|
+
|
|
182
|
+
<media-hotkey keys="Space" action="togglePaused"></media-hotkey>
|
|
183
|
+
<media-hotkey keys="m" action="toggleMuted"></media-hotkey>
|
|
184
|
+
<media-hotkey keys="f" action="toggleFullscreen"></media-hotkey>
|
|
185
|
+
<media-hotkey keys="ArrowLeft" action="seekStep" value="-5"></media-hotkey>
|
|
186
|
+
<media-hotkey keys="ArrowRight" action="seekStep" value="5"></media-hotkey>
|
|
187
|
+
|
|
188
|
+
<media-status-announcer></media-status-announcer>
|
|
189
|
+
|
|
190
|
+
<media-error-dialog>
|
|
191
|
+
<media-dialog-popup class="video-skin-error">
|
|
192
|
+
<media-dialog-title></media-dialog-title>
|
|
193
|
+
<media-dialog-description></media-dialog-description>
|
|
194
|
+
<media-dialog-close></media-dialog-close>
|
|
195
|
+
</media-dialog-popup>
|
|
196
|
+
</media-error-dialog>
|
|
197
|
+
</media-container>
|
|
198
|
+
</video-player>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The `@videojs/html/video/player` import registers `<video-player>` with the video features, which hold the state these controls need. Some controls, such as Cast or Quality, depend on features that not every preset includes. Each control’s reference page names the feature it needs.
|
|
202
|
+
|
|
203
|
+
This CSS places the controls over the video, hides them when the viewer is idle, draws the timeline, and keeps the error dialog hidden until playback fails:
|
|
204
|
+
|
|
205
|
+
**video-skin.css**
|
|
206
|
+
|
|
207
|
+
```css
|
|
208
|
+
.video-skin {
|
|
209
|
+
position: relative;
|
|
210
|
+
display: block;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.video-skin video {
|
|
214
|
+
display: block;
|
|
215
|
+
width: 100%;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.video-skin-controls {
|
|
219
|
+
position: absolute;
|
|
220
|
+
inset: auto 0 0;
|
|
221
|
+
padding: 12px;
|
|
222
|
+
background: linear-gradient(to top, rgb(0 0 0 / 0.7), transparent);
|
|
223
|
+
color: white;
|
|
224
|
+
transition: opacity 0.25s;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/* Keep controls visible while something inside them has keyboard focus. */
|
|
228
|
+
.video-skin-controls:not([data-visible]):not(:has(:focus-visible)) {
|
|
229
|
+
opacity: 0;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.video-skin-controls-group {
|
|
233
|
+
display: flex;
|
|
234
|
+
gap: 8px;
|
|
235
|
+
align-items: center;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* The slider sets its progress as CSS custom properties. */
|
|
239
|
+
.video-skin-time-slider {
|
|
240
|
+
position: relative;
|
|
241
|
+
display: flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
height: 20px;
|
|
244
|
+
cursor: pointer;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.video-skin-track {
|
|
248
|
+
position: relative;
|
|
249
|
+
width: 100%;
|
|
250
|
+
height: 4px;
|
|
251
|
+
background: rgb(255 255 255 / 0.3);
|
|
252
|
+
border-radius: 9999px;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.video-skin-buffer,
|
|
256
|
+
.video-skin-fill {
|
|
257
|
+
position: absolute;
|
|
258
|
+
top: 0;
|
|
259
|
+
bottom: 0;
|
|
260
|
+
left: 0;
|
|
261
|
+
border-radius: inherit;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.video-skin-buffer {
|
|
265
|
+
width: var(--media-slider-buffer);
|
|
266
|
+
background: rgb(255 255 255 / 0.4);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.video-skin-fill {
|
|
270
|
+
width: var(--media-slider-fill);
|
|
271
|
+
background: white;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.video-skin-thumb {
|
|
275
|
+
position: absolute;
|
|
276
|
+
left: var(--media-slider-fill);
|
|
277
|
+
width: 12px;
|
|
278
|
+
height: 12px;
|
|
279
|
+
background: white;
|
|
280
|
+
border-radius: 50%;
|
|
281
|
+
translate: -50% 0;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.video-skin-error {
|
|
285
|
+
position: absolute;
|
|
286
|
+
inset: 0;
|
|
287
|
+
display: grid;
|
|
288
|
+
gap: 12px;
|
|
289
|
+
place-content: center;
|
|
290
|
+
padding: 24px;
|
|
291
|
+
background: rgb(0 0 0 / 0.85);
|
|
292
|
+
color: white;
|
|
293
|
+
text-align: center;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
.video-skin-error:not([data-open]) {
|
|
297
|
+
display: none;
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Each button in the HTML example holds a label for every state. Show only the one that matches:
|
|
302
|
+
|
|
303
|
+
**video-skin.css**
|
|
304
|
+
|
|
305
|
+
```css
|
|
306
|
+
.video-skin-play:not([data-paused]) .show-when-paused,
|
|
307
|
+
.video-skin-play[data-paused] .show-when-playing,
|
|
308
|
+
.video-skin-mute:not([data-muted]) .show-when-muted,
|
|
309
|
+
.video-skin-mute[data-muted] .show-when-unmuted,
|
|
310
|
+
.video-skin-fullscreen:not([data-fullscreen]) .show-when-fullscreen,
|
|
311
|
+
.video-skin-fullscreen[data-fullscreen] .show-when-not-fullscreen {
|
|
312
|
+
display: none;
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
From here, add the components your design needs.
|
|
317
|
+
|
|
318
|
+
## Pick the components
|
|
319
|
+
|
|
320
|
+
Each skin is made of the same building blocks. Use the ones your design needs; their reference pages cover props, state, data attributes, and examples.
|
|
321
|
+
|
|
322
|
+
| Purpose | Components |
|
|
323
|
+
| --- | --- |
|
|
324
|
+
| Player surface, fullscreen and activity target | [Container](../reference/components/player-container.md) |
|
|
325
|
+
| Show and hide controls with user activity | [Controls](../reference/components/controls.md) |
|
|
326
|
+
| Playback buttons | [Play button](../reference/components/play-button.md), [Seek button](../reference/components/seek-button.md), [Mute button](../reference/components/mute-button.md), [Playback rate button](../reference/components/playback-rate-button.md), [Live button](../reference/components/live-button.md) |
|
|
327
|
+
| Screen and device buttons | [Fullscreen button](../reference/components/fullscreen-button.md), [Picture-in-picture button](../reference/components/pip-button.md), [AirPlay button](../reference/components/airplay-button.md), [Cast button](../reference/components/cast-button.md), [Captions button](../reference/components/captions-button.md) |
|
|
328
|
+
| Timeline and volume | [Time slider](../reference/components/time-slider.md), [Volume slider](../reference/components/volume-slider.md), [Volume popover](../reference/components/volume-popover.md), [Thumbnail](../reference/components/thumbnail.md), [Time](../reference/components/time.md) |
|
|
329
|
+
| Menus and popups | [Menu](../reference/components/menu.md), [Popover](../reference/components/popover.md), [Tooltip](../reference/components/tooltip.md), and the radio groups for [captions](../reference/components/captions-radio-group.md), [quality](../reference/components/quality-radio-group.md), [playback rate](../reference/components/playback-rate-radio-group.md), and [audio tracks](../reference/components/audio-track-radio-group.md) |
|
|
330
|
+
| Media details and loading | [Title](../reference/components/title.md), [Poster](../reference/components/poster.md), [Buffering indicator](../reference/components/buffering-indicator.md) |
|
|
331
|
+
| Feedback after an action | [Seek indicator](../reference/components/seek-indicator.md), [Volume indicator](../reference/components/volume-indicator.md), [Status indicator](../reference/components/status-indicator.md) |
|
|
332
|
+
| Errors | [Error dialog](../reference/components/error-dialog.md) |
|
|
333
|
+
| Keyboard, gestures, and announcements | [Hotkey](../reference/components/hotkey.md), [Gesture](../reference/components/gesture.md), [Status announcer](../reference/components/status-announcer.md) |
|
|
334
|
+
| Icons | [Icons](../reference/components/icons.md) |
|
|
335
|
+
|
|
336
|
+
Some of these are easy to leave out by accident because they have little or no visible UI. Include the error dialog, keyboard shortcuts, and status announcer unless you replace them with your own.
|
|
337
|
+
|
|
338
|
+
Import the registration for every element you use, including the parts of compound components. Each reference page lists its imports.
|
|
339
|
+
|
|
340
|
+
To build a control Video.js doesn’t provide, follow [Build your own UI component](./build-your-own-component.md).
|
|
341
|
+
|
|
342
|
+
## Style it your way
|
|
343
|
+
|
|
344
|
+
The components bring no visual styles. You add the icons, text, and CSS. They describe their state with `data-*` attributes, such as `data-paused` on the play button, so you can style them with plain CSS, Tailwind, or anything else. [UI components](./ui-components.md) explains how. [Automatically show and hide controls](./controls.md) covers the controls’ visibility states.
|
|
345
|
+
|
|
346
|
+
Lay out controls in source order that matches their visual order, so keyboard focus follows the layout.
|
|
347
|
+
|
|
348
|
+
A player’s controls sit over a moving picture, in a frame whose size you don’t control, so a few design questions come up in every skin:
|
|
349
|
+
|
|
350
|
+
- **Surfaces over video.** Borders, shadows, and translucent backgrounds look different over every frame. [Shapes and surfaces](https://videojs.org/blog/videojs-v10-skin-design#shapes-and-surfaces) and [Letting the content influence the color](https://videojs.org/blog/videojs-v10-skin-design#letting-the-content-influence-the-color) cover how our skins handle them.
|
|
351
|
+
- **Readable controls.** Seek tracks need a visible target, icons need optical alignment, and time displays need fixed-width digits. See [Controls and typography](https://videojs.org/blog/videojs-v10-skin-design#controls-and-typography).
|
|
352
|
+
- **Motion.** Menus should open from the control that opened them and respond when they’re closed mid-transition. See [Motion and transitions](https://videojs.org/blog/videojs-v10-skin-design#motion-and-transitions).
|
|
353
|
+
- **Small players.** Captions, settings, picture-in-picture, and Cast all compete for space at narrow widths. See [Fitting the available space](https://videojs.org/blog/videojs-v10-skin-design#fitting-the-available-space).
|
|
354
|
+
- **Custom colors.** An accent color someone else picks still needs contrast against its text and the video. See [Customization and contrast](https://videojs.org/blog/videojs-v10-skin-design#customization-and-contrast).
|
|
355
|
+
|
|
356
|
+
[Design inspiration behind the Video.js v10 skins](https://videojs.org/blog/videojs-v10-skin-design) covers the thinking behind our own skins in full.
|
|
357
|
+
|
|
358
|
+
## Support the public CSS properties
|
|
359
|
+
|
|
360
|
+
If the skin is only for your own site, you can skip this.
|
|
361
|
+
|
|
362
|
+
If you want to offer it as a Video.js skin, support the same CSS custom properties as the packaged skins, such as `--media-accent-color` and `--media-border-radius`. People can then restyle your skin the same way they restyle ours. [Set the skin’s styles](./customize-skins.md#set-the-skins-styles) lists them. We’re still working out how to accept community skins into Video.js.
|
|
363
|
+
|
|
364
|
+
## Test it
|
|
365
|
+
|
|
366
|
+
Check the finished skin with real media, at the narrowest player size you support:
|
|
367
|
+
|
|
368
|
+
- Play, pause, seek, change volume, open every menu, and enter fullscreen.
|
|
369
|
+
- Use only a keyboard, then only touch. Focus stays visible and follows the layout, and controls hide when idle.
|
|
370
|
+
- Check loading, errors, ended playback, captions, and controls the browser doesn’t support.
|
|
371
|
+
- Check text and icon contrast over bright and dark footage, with forced colors, and with reduced motion.
|
|
372
|
+
|
|
373
|
+
[Accessibility](./accessibility.md) covers these checks in more detail.
|
|
374
|
+
|
|
375
|
+
## Related pages
|
|
376
|
+
|
|
377
|
+
### Guides
|
|
378
|
+
|
|
379
|
+
- [Skins](./skins.md): Packaged player designs that include both UI components and their styles.
|
|
380
|
+
- [Customize skins](./customize-skins.md): Style a packaged Video.js skin or add its source to change controls, layout, styles, and interactions
|
|
381
|
+
- [Build your own UI component](./build-your-own-component.md): Create custom player controls that read state, dispatch actions, and stay accessible.
|
package/docs/guides/cdn.md
CHANGED
|
@@ -36,8 +36,8 @@ A skin bundle registers every UI element its skin is built from. Any element the
|
|
|
36
36
|
Each [UI element](./ui-components.md) is its own bundle under `ui/`, for markup that a skin bundle does not already cover: a player-only bundle, [skin source](./customize-skins.md#style-skin-source) that adds a component the packaged skin lacks, or a [dialog](../reference/components/dialog.md) your page opens beside a packaged skin.
|
|
37
37
|
|
|
38
38
|
```html
|
|
39
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
40
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
39
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/video-player.js"></script>
|
|
40
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/ui/play-button.js"></script>
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
Each path mirrors its npm subpath: `ui/play-button.js` registers the element that `@videojs/html/ui/play-button` does. Compound components list one bundle per part in their reference page’s Import section, and all of the bundles share chunks with the player.
|
|
@@ -47,8 +47,8 @@ Each path mirrors its npm subpath: `ui/play-button.js` registers the element tha
|
|
|
47
47
|
The default presets play through the browser’s own `<video>` and `<audio>`. Every other [media component](./media-sources.md) is its own bundle under `media/`, loaded beside the player bundle:
|
|
48
48
|
|
|
49
49
|
```html
|
|
50
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
51
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
50
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/video.js"></script>
|
|
51
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/media/hlsjs-video.js"></script>
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
Each path mirrors its npm subpath. Elements with more than one playback engine keep the extra flavors in a directory named for the element, such as `media/mux-video/spf.js`. Load one flavor per page: every flavor claims the same tag name, and the first registration wins.
|
|
@@ -58,9 +58,9 @@ Each path mirrors its npm subpath. Elements with more than one playback engine k
|
|
|
58
58
|
Each [extension](./architecture.md) is its own bundle under `extensions/`, loaded beside the player and media bundles:
|
|
59
59
|
|
|
60
60
|
```html
|
|
61
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
62
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
63
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
61
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/video.js"></script>
|
|
62
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/media/mux-video.js"></script>
|
|
63
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/extensions/mux-data.js"></script>
|
|
64
64
|
```
|
|
65
65
|
|
|
66
66
|
As with media, each path mirrors its npm subpath: `extensions/mux-data.js` registers the element that `@videojs/html/extensions/mux-data` does.
|
|
@@ -70,8 +70,8 @@ As with media, each path mirrors its npm subpath: `extensions/mux-data.js` regis
|
|
|
70
70
|
English ships inside the skin bundles. Each other locale is a bundle under `locales/` that registers its translations on import. Load it before the player script to avoid a flash of English:
|
|
71
71
|
|
|
72
72
|
```html
|
|
73
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
74
|
-
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.0
|
|
73
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/locales/es.js"></script>
|
|
74
|
+
<script type="module" src="https://cdn.jsdelivr.net/npm/@videojs/cdn@10.2.0/video.js"></script>
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
One bundle exists per locale pack, plus bare-language aliases such as `pt`. For custom strings, see [Internationalize the player](./internationalization.md).
|
|
@@ -127,7 +127,7 @@ Installed files belong to your project, so an update replaces your local copy. C
|
|
|
127
127
|
npx shadcn@latest add @videojs/video --overwrite
|
|
128
128
|
```
|
|
129
129
|
|
|
130
|
-
To understand how skins fit into Video.js, read [Skins](./skins.md). To create a control instead of editing one, follow [Build your own component](./build-your-own-component.md).
|
|
130
|
+
To understand how skins fit into Video.js, read [Skins](./skins.md). To design a new interface from a minimal starting point, follow [Build your own skin](./build-your-own-skin.md). To create a control instead of editing one, follow [Build your own component](./build-your-own-component.md).
|
|
131
131
|
|
|
132
132
|
## Related pages
|
|
133
133
|
|
|
@@ -138,4 +138,5 @@ To understand how skins fit into Video.js, read [Skins](./skins.md). To create a
|
|
|
138
138
|
### Guides
|
|
139
139
|
|
|
140
140
|
- [Skins](./skins.md): Packaged player designs that include both UI components and their styles.
|
|
141
|
+
- [Build your own skin](./build-your-own-skin.md): Create a skin project, preview it locally, and compose your own player interface from Video.js UI components
|
|
141
142
|
- [Build your own UI component](./build-your-own-component.md): Create custom player controls that read state, dispatch actions, and stay accessible.
|