@mattebox/player 0.1.0 → 0.3.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 +4 -3
- package/dist/cdn/mattebox-player.min.js +222 -198
- package/dist/compose.d.ts +5 -0
- package/dist/compose.d.ts.map +1 -0
- package/dist/compose.js +31 -0
- package/dist/compose.js.map +1 -0
- package/dist/controls/chapters.d.ts +29 -0
- package/dist/controls/chapters.d.ts.map +1 -0
- package/dist/controls/chapters.js +81 -0
- package/dist/controls/chapters.js.map +1 -0
- package/dist/controls/cues.d.ts +8 -3
- package/dist/controls/cues.d.ts.map +1 -1
- package/dist/controls/cues.js +44 -10
- package/dist/controls/cues.js.map +1 -1
- package/dist/controls/fullscreen.d.ts +9 -9
- package/dist/controls/fullscreen.d.ts.map +1 -1
- package/dist/controls/fullscreen.js +17 -21
- package/dist/controls/fullscreen.js.map +1 -1
- package/dist/controls/icons.d.ts +1 -3
- package/dist/controls/icons.d.ts.map +1 -1
- package/dist/controls/icons.js +3 -6
- package/dist/controls/icons.js.map +1 -1
- package/dist/controls/menu.d.ts +14 -11
- package/dist/controls/menu.d.ts.map +1 -1
- package/dist/controls/menu.js +39 -34
- package/dist/controls/menu.js.map +1 -1
- package/dist/controls/session.d.ts +27 -0
- package/dist/controls/session.d.ts.map +1 -0
- package/dist/controls/session.js +36 -0
- package/dist/controls/session.js.map +1 -0
- package/dist/controls/slider.d.ts +6 -6
- package/dist/controls/slider.d.ts.map +1 -1
- package/dist/controls/slider.js +18 -13
- package/dist/controls/slider.js.map +1 -1
- package/dist/dom.d.ts +4 -10
- package/dist/dom.d.ts.map +1 -1
- package/dist/dom.js +4 -24
- package/dist/dom.js.map +1 -1
- package/dist/element-entry.d.ts +4 -0
- package/dist/element-entry.d.ts.map +1 -0
- package/dist/element-entry.js +9 -0
- package/dist/element-entry.js.map +1 -0
- package/dist/element.d.ts +54 -14
- package/dist/element.d.ts.map +1 -1
- package/dist/element.js +154 -73
- package/dist/element.js.map +1 -1
- package/dist/elements/audio-menu.d.ts +24 -0
- package/dist/elements/audio-menu.d.ts.map +1 -0
- package/dist/elements/audio-menu.js +70 -0
- package/dist/elements/audio-menu.js.map +1 -0
- package/dist/elements/chapters-menu.d.ts +12 -0
- package/dist/elements/chapters-menu.d.ts.map +1 -0
- package/dist/elements/chapters-menu.js +67 -0
- package/dist/elements/chapters-menu.js.map +1 -0
- package/dist/elements/component.d.ts +45 -0
- package/dist/elements/component.d.ts.map +1 -0
- package/dist/elements/component.js +90 -0
- package/dist/elements/component.js.map +1 -0
- package/dist/elements/control-bar.d.ts +75 -0
- package/dist/elements/control-bar.d.ts.map +1 -0
- package/dist/elements/control-bar.js +339 -0
- package/dist/elements/control-bar.js.map +1 -0
- package/dist/elements/current-time.d.ts +5 -0
- package/dist/elements/current-time.d.ts.map +1 -0
- package/dist/elements/current-time.js +27 -0
- package/dist/elements/current-time.js.map +1 -0
- package/dist/elements/drm-badge.d.ts +29 -0
- package/dist/elements/drm-badge.d.ts.map +1 -0
- package/dist/elements/drm-badge.js +145 -0
- package/dist/elements/drm-badge.js.map +1 -0
- package/dist/elements/duration.d.ts +6 -0
- package/dist/elements/duration.d.ts.map +1 -0
- package/dist/elements/duration.js +23 -0
- package/dist/elements/duration.js.map +1 -0
- package/dist/elements/error-screen.d.ts +17 -0
- package/dist/elements/error-screen.d.ts.map +1 -0
- package/dist/elements/error-screen.js +103 -0
- package/dist/elements/error-screen.js.map +1 -0
- package/dist/elements/fullscreen-button.d.ts +19 -0
- package/dist/elements/fullscreen-button.d.ts.map +1 -0
- package/dist/elements/fullscreen-button.js +55 -0
- package/dist/elements/fullscreen-button.js.map +1 -0
- package/dist/elements/live-button.d.ts +12 -0
- package/dist/elements/live-button.d.ts.map +1 -0
- package/dist/elements/live-button.js +96 -0
- package/dist/elements/live-button.js.map +1 -0
- package/dist/elements/menu-element.d.ts +22 -0
- package/dist/elements/menu-element.d.ts.map +1 -0
- package/dist/elements/menu-element.js +31 -0
- package/dist/elements/menu-element.js.map +1 -0
- package/dist/elements/mute-button.d.ts +12 -0
- package/dist/elements/mute-button.d.ts.map +1 -0
- package/dist/elements/mute-button.js +61 -0
- package/dist/elements/mute-button.js.map +1 -0
- package/dist/elements/panels.d.ts +15 -0
- package/dist/elements/panels.d.ts.map +1 -0
- package/dist/elements/panels.js +55 -0
- package/dist/elements/panels.js.map +1 -0
- package/dist/elements/pip-button.d.ts +13 -0
- package/dist/elements/pip-button.d.ts.map +1 -0
- package/dist/elements/pip-button.js +56 -0
- package/dist/elements/pip-button.js.map +1 -0
- package/dist/elements/play-button.d.ts +12 -0
- package/dist/elements/play-button.d.ts.map +1 -0
- package/dist/elements/play-button.js +60 -0
- package/dist/elements/play-button.js.map +1 -0
- package/dist/elements/quality-menu.d.ts +11 -0
- package/dist/elements/quality-menu.d.ts.map +1 -0
- package/dist/elements/quality-menu.js +72 -0
- package/dist/elements/quality-menu.js.map +1 -0
- package/dist/elements/remaining-time.d.ts +6 -0
- package/dist/elements/remaining-time.d.ts.map +1 -0
- package/dist/elements/remaining-time.js +26 -0
- package/dist/elements/remaining-time.js.map +1 -0
- package/dist/elements/seek-bar.d.ts +83 -0
- package/dist/elements/seek-bar.d.ts.map +1 -0
- package/dist/elements/seek-bar.js +352 -0
- package/dist/elements/seek-bar.js.map +1 -0
- package/dist/elements/shared.d.ts +27 -0
- package/dist/elements/shared.d.ts.map +1 -0
- package/dist/elements/shared.js +155 -0
- package/dist/elements/shared.js.map +1 -0
- package/dist/elements/skip-button.d.ts +14 -0
- package/dist/elements/skip-button.d.ts.map +1 -0
- package/dist/elements/skip-button.js +60 -0
- package/dist/elements/skip-button.js.map +1 -0
- package/dist/elements/spacer.d.ts +4 -0
- package/dist/elements/spacer.d.ts.map +1 -0
- package/dist/elements/spacer.js +9 -0
- package/dist/elements/spacer.js.map +1 -0
- package/dist/elements/speed-menu.d.ts +18 -0
- package/dist/elements/speed-menu.d.ts.map +1 -0
- package/dist/elements/speed-menu.js +56 -0
- package/dist/elements/speed-menu.js.map +1 -0
- package/dist/elements/start-button.d.ts +23 -0
- package/dist/elements/start-button.d.ts.map +1 -0
- package/dist/elements/start-button.js +120 -0
- package/dist/elements/start-button.js.map +1 -0
- package/dist/elements/subtitles-menu.d.ts +17 -0
- package/dist/elements/subtitles-menu.d.ts.map +1 -0
- package/dist/elements/subtitles-menu.js +108 -0
- package/dist/elements/subtitles-menu.js.map +1 -0
- package/dist/elements/time-element.d.ts +14 -0
- package/dist/elements/time-element.d.ts.map +1 -0
- package/dist/elements/time-element.js +29 -0
- package/dist/elements/time-element.js.map +1 -0
- package/dist/elements/volume-slider.d.ts +10 -0
- package/dist/elements/volume-slider.d.ts.map +1 -0
- package/dist/elements/volume-slider.js +46 -0
- package/dist/elements/volume-slider.js.map +1 -0
- package/dist/elements/volume.d.ts +9 -0
- package/dist/elements/volume.d.ts.map +1 -0
- package/dist/elements/volume.js +52 -0
- package/dist/elements/volume.js.map +1 -0
- package/dist/entries/audio-menu.d.ts +5 -0
- package/dist/entries/audio-menu.d.ts.map +1 -0
- package/dist/entries/audio-menu.js +8 -0
- package/dist/entries/audio-menu.js.map +1 -0
- package/dist/entries/chapters-menu.d.ts +5 -0
- package/dist/entries/chapters-menu.d.ts.map +1 -0
- package/dist/entries/chapters-menu.js +9 -0
- package/dist/entries/chapters-menu.js.map +1 -0
- package/dist/entries/control-bar.d.ts +5 -0
- package/dist/entries/control-bar.d.ts.map +1 -0
- package/dist/entries/control-bar.js +8 -0
- package/dist/entries/control-bar.js.map +1 -0
- package/dist/entries/current-time.d.ts +5 -0
- package/dist/entries/current-time.d.ts.map +1 -0
- package/dist/entries/current-time.js +8 -0
- package/dist/entries/current-time.js.map +1 -0
- package/dist/entries/drm-badge.d.ts +5 -0
- package/dist/entries/drm-badge.d.ts.map +1 -0
- package/dist/entries/drm-badge.js +8 -0
- package/dist/entries/drm-badge.js.map +1 -0
- package/dist/entries/duration.d.ts +5 -0
- package/dist/entries/duration.d.ts.map +1 -0
- package/dist/entries/duration.js +8 -0
- package/dist/entries/duration.js.map +1 -0
- package/dist/entries/error-screen.d.ts +5 -0
- package/dist/entries/error-screen.d.ts.map +1 -0
- package/dist/entries/error-screen.js +8 -0
- package/dist/entries/error-screen.js.map +1 -0
- package/dist/entries/fullscreen-button.d.ts +5 -0
- package/dist/entries/fullscreen-button.d.ts.map +1 -0
- package/dist/entries/fullscreen-button.js +8 -0
- package/dist/entries/fullscreen-button.js.map +1 -0
- package/dist/entries/live-button.d.ts +5 -0
- package/dist/entries/live-button.d.ts.map +1 -0
- package/dist/entries/live-button.js +8 -0
- package/dist/entries/live-button.js.map +1 -0
- package/dist/entries/mute-button.d.ts +5 -0
- package/dist/entries/mute-button.d.ts.map +1 -0
- package/dist/entries/mute-button.js +8 -0
- package/dist/entries/mute-button.js.map +1 -0
- package/dist/entries/panels.d.ts +5 -0
- package/dist/entries/panels.d.ts.map +1 -0
- package/dist/entries/panels.js +8 -0
- package/dist/entries/panels.js.map +1 -0
- package/dist/entries/pip-button.d.ts +5 -0
- package/dist/entries/pip-button.d.ts.map +1 -0
- package/dist/entries/pip-button.js +8 -0
- package/dist/entries/pip-button.js.map +1 -0
- package/dist/entries/play-button.d.ts +5 -0
- package/dist/entries/play-button.d.ts.map +1 -0
- package/dist/entries/play-button.js +8 -0
- package/dist/entries/play-button.js.map +1 -0
- package/dist/entries/quality-menu.d.ts +5 -0
- package/dist/entries/quality-menu.d.ts.map +1 -0
- package/dist/entries/quality-menu.js +8 -0
- package/dist/entries/quality-menu.js.map +1 -0
- package/dist/entries/remaining-time.d.ts +5 -0
- package/dist/entries/remaining-time.d.ts.map +1 -0
- package/dist/entries/remaining-time.js +9 -0
- package/dist/entries/remaining-time.js.map +1 -0
- package/dist/entries/seek-bar.d.ts +5 -0
- package/dist/entries/seek-bar.d.ts.map +1 -0
- package/dist/entries/seek-bar.js +8 -0
- package/dist/entries/seek-bar.js.map +1 -0
- package/dist/entries/skip-button.d.ts +5 -0
- package/dist/entries/skip-button.d.ts.map +1 -0
- package/dist/entries/skip-button.js +8 -0
- package/dist/entries/skip-button.js.map +1 -0
- package/dist/entries/spacer.d.ts +5 -0
- package/dist/entries/spacer.d.ts.map +1 -0
- package/dist/entries/spacer.js +8 -0
- package/dist/entries/spacer.js.map +1 -0
- package/dist/entries/speed-menu.d.ts +5 -0
- package/dist/entries/speed-menu.d.ts.map +1 -0
- package/dist/entries/speed-menu.js +8 -0
- package/dist/entries/speed-menu.js.map +1 -0
- package/dist/entries/start-button.d.ts +5 -0
- package/dist/entries/start-button.d.ts.map +1 -0
- package/dist/entries/start-button.js +8 -0
- package/dist/entries/start-button.js.map +1 -0
- package/dist/entries/subtitles-menu.d.ts +5 -0
- package/dist/entries/subtitles-menu.d.ts.map +1 -0
- package/dist/entries/subtitles-menu.js +8 -0
- package/dist/entries/subtitles-menu.js.map +1 -0
- package/dist/entries/volume-slider.d.ts +5 -0
- package/dist/entries/volume-slider.d.ts.map +1 -0
- package/dist/entries/volume-slider.js +8 -0
- package/dist/entries/volume-slider.js.map +1 -0
- package/dist/entries/volume.d.ts +7 -0
- package/dist/entries/volume.d.ts.map +1 -0
- package/dist/entries/volume.js +10 -0
- package/dist/entries/volume.js.map +1 -0
- package/dist/es2015/compose.js +33 -0
- package/dist/es2015/controls/chapters.js +61 -0
- package/dist/es2015/controls/cues.js +39 -11
- package/dist/es2015/controls/fullscreen.js +25 -23
- package/dist/es2015/controls/icons.js +5 -9
- package/dist/es2015/controls/menu.js +39 -35
- package/dist/es2015/controls/session.js +40 -0
- package/dist/es2015/controls/slider.js +18 -13
- package/dist/es2015/controls/time.js +1 -5
- package/dist/es2015/dom.js +5 -25
- package/dist/es2015/element-entry.js +10 -0
- package/dist/es2015/element.js +118 -65
- package/dist/es2015/elements/audio-menu.js +68 -0
- package/dist/es2015/elements/chapters-menu.js +68 -0
- package/dist/es2015/elements/component.js +85 -0
- package/dist/es2015/elements/control-bar.js +299 -0
- package/dist/es2015/elements/current-time.js +27 -0
- package/dist/es2015/elements/drm-badge.js +138 -0
- package/dist/es2015/elements/duration.js +23 -0
- package/dist/es2015/elements/error-screen.js +97 -0
- package/dist/es2015/elements/fullscreen-button.js +49 -0
- package/dist/es2015/elements/live-button.js +97 -0
- package/dist/es2015/elements/menu-element.js +39 -0
- package/dist/es2015/elements/mute-button.js +60 -0
- package/dist/es2015/elements/panels.js +52 -0
- package/dist/es2015/elements/pip-button.js +56 -0
- package/dist/es2015/elements/play-button.js +68 -0
- package/dist/es2015/elements/quality-menu.js +68 -0
- package/dist/es2015/elements/remaining-time.js +26 -0
- package/dist/es2015/elements/seek-bar.js +314 -0
- package/dist/es2015/elements/shared.js +155 -0
- package/dist/es2015/elements/skip-button.js +59 -0
- package/dist/es2015/elements/spacer.js +11 -0
- package/dist/es2015/elements/speed-menu.js +60 -0
- package/dist/es2015/elements/start-button.js +124 -0
- package/dist/es2015/elements/subtitles-menu.js +103 -0
- package/dist/es2015/elements/time-element.js +38 -0
- package/dist/es2015/elements/volume-slider.js +47 -0
- package/dist/es2015/elements/volume.js +52 -0
- package/dist/es2015/entries/audio-menu.js +7 -0
- package/dist/es2015/entries/chapters-menu.js +7 -0
- package/dist/es2015/entries/control-bar.js +7 -0
- package/dist/es2015/entries/current-time.js +7 -0
- package/dist/es2015/entries/drm-badge.js +7 -0
- package/dist/es2015/entries/duration.js +7 -0
- package/dist/es2015/entries/error-screen.js +7 -0
- package/dist/es2015/entries/fullscreen-button.js +7 -0
- package/dist/es2015/entries/live-button.js +7 -0
- package/dist/es2015/entries/mute-button.js +7 -0
- package/dist/es2015/entries/panels.js +7 -0
- package/dist/es2015/entries/pip-button.js +7 -0
- package/dist/es2015/entries/play-button.js +7 -0
- package/dist/es2015/entries/quality-menu.js +7 -0
- package/dist/es2015/entries/remaining-time.js +7 -0
- package/dist/es2015/entries/seek-bar.js +7 -0
- package/dist/es2015/entries/skip-button.js +7 -0
- package/dist/es2015/entries/spacer.js +7 -0
- package/dist/es2015/entries/speed-menu.js +7 -0
- package/dist/es2015/entries/start-button.js +7 -0
- package/dist/es2015/entries/subtitles-menu.js +7 -0
- package/dist/es2015/entries/volume-slider.js +7 -0
- package/dist/es2015/entries/volume.js +9 -0
- package/dist/es2015/host.js +23 -0
- package/dist/es2015/index.js +48 -9
- package/dist/es2015/labels.js +14 -0
- package/dist/es2015/style.js +40 -292
- package/dist/es2015/{panels/error.js → surface.js} +3 -3
- package/dist/es2015/tags.js +28 -0
- package/dist/host.d.ts +26 -0
- package/dist/host.d.ts.map +1 -0
- package/dist/host.js +23 -0
- package/dist/host.js.map +1 -0
- package/dist/index.d.ts +84 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +24 -8
- package/dist/index.js.map +1 -1
- package/dist/labels.d.ts +7 -0
- package/dist/labels.d.ts.map +1 -0
- package/dist/labels.js +12 -0
- package/dist/labels.js.map +1 -0
- package/dist/style.d.ts +10 -2
- package/dist/style.d.ts.map +1 -1
- package/dist/style.js +40 -292
- package/dist/style.js.map +1 -1
- package/dist/surface.d.ts +15 -0
- package/dist/surface.d.ts.map +1 -0
- package/dist/{panels/error.js → surface.js} +3 -3
- package/dist/surface.js.map +1 -0
- package/dist/tags.d.ts +26 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.js +26 -0
- package/dist/tags.js.map +1 -0
- package/package.json +22 -2
- package/dist/controls/bar.d.ts +0 -56
- package/dist/controls/bar.d.ts.map +0 -1
- package/dist/controls/bar.js +0 -245
- package/dist/controls/bar.js.map +0 -1
- package/dist/controls/buttons.d.ts +0 -13
- package/dist/controls/buttons.d.ts.map +0 -1
- package/dist/controls/buttons.js +0 -157
- package/dist/controls/buttons.js.map +0 -1
- package/dist/controls/control.d.ts +0 -12
- package/dist/controls/control.d.ts.map +0 -1
- package/dist/controls/control.js +0 -2
- package/dist/controls/control.js.map +0 -1
- package/dist/controls/keys.d.ts +0 -26
- package/dist/controls/keys.d.ts.map +0 -1
- package/dist/controls/keys.js +0 -66
- package/dist/controls/keys.js.map +0 -1
- package/dist/controls/live.d.ts +0 -10
- package/dist/controls/live.d.ts.map +0 -1
- package/dist/controls/live.js +0 -59
- package/dist/controls/live.js.map +0 -1
- package/dist/controls/menus.d.ts +0 -43
- package/dist/controls/menus.d.ts.map +0 -1
- package/dist/controls/menus.js +0 -262
- package/dist/controls/menus.js.map +0 -1
- package/dist/controls/options.d.ts +0 -44
- package/dist/controls/options.d.ts.map +0 -1
- package/dist/controls/options.js +0 -54
- package/dist/controls/options.js.map +0 -1
- package/dist/controls/screens.d.ts +0 -22
- package/dist/controls/screens.d.ts.map +0 -1
- package/dist/controls/screens.js +0 -69
- package/dist/controls/screens.js.map +0 -1
- package/dist/controls/seek.d.ts +0 -52
- package/dist/controls/seek.d.ts.map +0 -1
- package/dist/controls/seek.js +0 -215
- package/dist/controls/seek.js.map +0 -1
- package/dist/controls/speed.d.ts +0 -8
- package/dist/controls/speed.d.ts.map +0 -1
- package/dist/controls/speed.js +0 -34
- package/dist/controls/speed.js.map +0 -1
- package/dist/controls/volume.d.ts +0 -8
- package/dist/controls/volume.d.ts.map +0 -1
- package/dist/controls/volume.js +0 -29
- package/dist/controls/volume.js.map +0 -1
- package/dist/es2015/controls/bar.js +0 -227
- package/dist/es2015/controls/buttons.js +0 -146
- package/dist/es2015/controls/keys.js +0 -60
- package/dist/es2015/controls/live.js +0 -60
- package/dist/es2015/controls/menus.js +0 -258
- package/dist/es2015/controls/options.js +0 -46
- package/dist/es2015/controls/screens.js +0 -74
- package/dist/es2015/controls/seek.js +0 -203
- package/dist/es2015/controls/speed.js +0 -41
- package/dist/es2015/controls/volume.js +0 -30
- package/dist/es2015/panels/drm.js +0 -29
- package/dist/es2015/panels/live.js +0 -48
- package/dist/es2015/panels/quality.js +0 -52
- package/dist/es2015/panels/tracks.js +0 -47
- package/dist/panels/drm.d.ts +0 -8
- package/dist/panels/drm.d.ts.map +0 -1
- package/dist/panels/drm.js +0 -36
- package/dist/panels/drm.js.map +0 -1
- package/dist/panels/error.d.ts +0 -13
- package/dist/panels/error.d.ts.map +0 -1
- package/dist/panels/error.js.map +0 -1
- package/dist/panels/live.d.ts +0 -3
- package/dist/panels/live.d.ts.map +0 -1
- package/dist/panels/live.js +0 -56
- package/dist/panels/live.js.map +0 -1
- package/dist/panels/panel.d.ts +0 -13
- package/dist/panels/panel.d.ts.map +0 -1
- package/dist/panels/panel.js +0 -2
- package/dist/panels/panel.js.map +0 -1
- package/dist/panels/quality.d.ts +0 -3
- package/dist/panels/quality.d.ts.map +0 -1
- package/dist/panels/quality.js +0 -59
- package/dist/panels/quality.js.map +0 -1
- package/dist/panels/tracks.d.ts +0 -3
- package/dist/panels/tracks.d.ts.map +0 -1
- package/dist/panels/tracks.js +0 -49
- package/dist/panels/tracks.js.map +0 -1
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { el } from "../dom.js";
|
|
2
|
-
import { glyph, icon } from "./icons.js";
|
|
3
|
-
//#region src/controls/buttons.ts
|
|
4
|
-
/**
|
|
5
|
-
* The buttons: play/pause, mute, fullscreen. Each reads the video on the
|
|
6
|
-
* events the video already fires, swaps its glyph and its name, and writes
|
|
7
|
-
* one thing back on click. The glyph is decoration; the name is on the
|
|
8
|
-
* button, where a screen reader reads it.
|
|
9
|
-
*/
|
|
10
|
-
/** A button with its glyph. `control` is the generic name, so `::part(control)` reaches every one. */
|
|
11
|
-
function button(name, first) {
|
|
12
|
-
const node = el("button", `control ${name}-button`);
|
|
13
|
-
node.type = "button";
|
|
14
|
-
const svg = icon(first);
|
|
15
|
-
node.append(svg);
|
|
16
|
-
return [node, svg];
|
|
17
|
-
}
|
|
18
|
-
function listen(target, names, fn) {
|
|
19
|
-
for (const name of names) target.addEventListener(name, fn);
|
|
20
|
-
return () => {
|
|
21
|
-
for (const name of names) target.removeEventListener(name, fn);
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
function playButton(video, flag) {
|
|
25
|
-
const [root, svg] = button("play", "play");
|
|
26
|
-
function render() {
|
|
27
|
-
const paused = video.paused;
|
|
28
|
-
const name = video.ended ? "replay" : paused ? "play" : "pause";
|
|
29
|
-
glyph(svg, name);
|
|
30
|
-
root.setAttribute("aria-label", video.ended ? "Replay" : paused ? "Play" : "Pause");
|
|
31
|
-
flag("playing", !paused);
|
|
32
|
-
}
|
|
33
|
-
function click() {
|
|
34
|
-
if (video.paused) video.play().catch(() => void 0);
|
|
35
|
-
else video.pause();
|
|
36
|
-
}
|
|
37
|
-
root.addEventListener("click", click);
|
|
38
|
-
const off = listen(video, [
|
|
39
|
-
"play",
|
|
40
|
-
"pause",
|
|
41
|
-
"ended",
|
|
42
|
-
"emptied"
|
|
43
|
-
], render);
|
|
44
|
-
render();
|
|
45
|
-
return {
|
|
46
|
-
root,
|
|
47
|
-
dispose() {
|
|
48
|
-
root.removeEventListener("click", click);
|
|
49
|
-
off();
|
|
50
|
-
}
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
function muteButton(video, flag) {
|
|
54
|
-
const [root, svg] = button("mute", "volume-high");
|
|
55
|
-
function render() {
|
|
56
|
-
const silent = video.muted || video.volume === 0;
|
|
57
|
-
const name = silent ? "mute" : video.volume <= .5 ? "volume-low" : "volume-high";
|
|
58
|
-
glyph(svg, name);
|
|
59
|
-
root.setAttribute("aria-label", silent ? "Unmute" : "Mute");
|
|
60
|
-
root.setAttribute("aria-pressed", String(video.muted));
|
|
61
|
-
flag("muted", silent);
|
|
62
|
-
}
|
|
63
|
-
function click() {
|
|
64
|
-
if (video.muted) {
|
|
65
|
-
video.muted = false;
|
|
66
|
-
if (video.volume === 0) video.volume = 1;
|
|
67
|
-
} else video.muted = true;
|
|
68
|
-
}
|
|
69
|
-
root.addEventListener("click", click);
|
|
70
|
-
const off = listen(video, ["volumechange", "emptied"], render);
|
|
71
|
-
render();
|
|
72
|
-
return {
|
|
73
|
-
root,
|
|
74
|
-
dispose() {
|
|
75
|
-
root.removeEventListener("click", click);
|
|
76
|
-
off();
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
}
|
|
80
|
-
/** The glyph for a skip amount: the set draws 10 and 30, and a plain arrow says the rest. */
|
|
81
|
-
function skipGlyph(back, amount) {
|
|
82
|
-
const side = back ? "seek-backward" : "seek-forward";
|
|
83
|
-
if (amount === 10 || amount === 30) return `${side}-${amount}`;
|
|
84
|
-
return side;
|
|
85
|
-
}
|
|
86
|
-
/** Moves the playhead by `seconds`, negative for back, within what the video can reach. */
|
|
87
|
-
function skipButton(video, seconds) {
|
|
88
|
-
const back = seconds < 0;
|
|
89
|
-
const amount = Math.abs(seconds);
|
|
90
|
-
const [root] = button(back ? "skip-back" : "skip-forward", skipGlyph(back, amount));
|
|
91
|
-
root.setAttribute("aria-label", `${back ? "Back" : "Forward"} ${amount} seconds`);
|
|
92
|
-
function click() {
|
|
93
|
-
const ranges = video.seekable;
|
|
94
|
-
const end = Number.isFinite(video.duration) ? video.duration : ranges.length > 0 ? ranges.end(ranges.length - 1) : video.currentTime;
|
|
95
|
-
video.currentTime = Math.min(end, Math.max(0, video.currentTime + seconds));
|
|
96
|
-
}
|
|
97
|
-
root.addEventListener("click", click);
|
|
98
|
-
return {
|
|
99
|
-
root,
|
|
100
|
-
dispose() {
|
|
101
|
-
root.removeEventListener("click", click);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
function pipButton(api, flag) {
|
|
106
|
-
const [root, svg] = button("pip", "picture-in-picture");
|
|
107
|
-
root.hidden = !api.supported;
|
|
108
|
-
function render() {
|
|
109
|
-
const active = api.active();
|
|
110
|
-
glyph(svg, active ? "picture-in-picture-exit" : "picture-in-picture");
|
|
111
|
-
root.setAttribute("aria-label", active ? "Leave picture in picture" : "Picture in picture");
|
|
112
|
-
flag("pip", active);
|
|
113
|
-
}
|
|
114
|
-
root.addEventListener("click", api.toggle);
|
|
115
|
-
const off = api.watch(render);
|
|
116
|
-
render();
|
|
117
|
-
return {
|
|
118
|
-
root,
|
|
119
|
-
dispose() {
|
|
120
|
-
root.removeEventListener("click", api.toggle);
|
|
121
|
-
off();
|
|
122
|
-
}
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
function fullscreenButton(api, flag) {
|
|
126
|
-
const [root, svg] = button("fullscreen", "fullscreen");
|
|
127
|
-
root.hidden = !api.supported;
|
|
128
|
-
function render() {
|
|
129
|
-
const active = api.active();
|
|
130
|
-
glyph(svg, active ? "fullscreen-exit" : "fullscreen");
|
|
131
|
-
root.setAttribute("aria-label", active ? "Exit fullscreen" : "Enter fullscreen");
|
|
132
|
-
flag("fullscreen", active);
|
|
133
|
-
}
|
|
134
|
-
root.addEventListener("click", api.toggle);
|
|
135
|
-
const off = api.watch(render);
|
|
136
|
-
render();
|
|
137
|
-
return {
|
|
138
|
-
root,
|
|
139
|
-
dispose() {
|
|
140
|
-
root.removeEventListener("click", api.toggle);
|
|
141
|
-
off();
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
|
-
//#endregion
|
|
146
|
-
export { button, fullscreenButton, muteButton, pipButton, playButton, skipButton };
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
//#region src/controls/keys.ts
|
|
2
|
-
function toggle(video) {
|
|
3
|
-
if (video.paused) video.play().catch(() => void 0);
|
|
4
|
-
else video.pause();
|
|
5
|
-
}
|
|
6
|
-
/** The end the playhead can reach: the duration, or the seekable end for live. */
|
|
7
|
-
function end(video) {
|
|
8
|
-
if (Number.isFinite(video.duration)) return video.duration;
|
|
9
|
-
const ranges = video.seekable;
|
|
10
|
-
return ranges.length > 0 ? ranges.end(ranges.length - 1) : video.currentTime;
|
|
11
|
-
}
|
|
12
|
-
function keys(options) {
|
|
13
|
-
const { host, stage, own, video } = options;
|
|
14
|
-
function onKey(event) {
|
|
15
|
-
if (event.defaultPrevented || event.altKey || event.ctrlKey || event.metaKey) return;
|
|
16
|
-
const onButton = event.composedPath()[0] instanceof HTMLButtonElement;
|
|
17
|
-
switch (event.key) {
|
|
18
|
-
case " ":
|
|
19
|
-
if (onButton) return;
|
|
20
|
-
toggle(video);
|
|
21
|
-
break;
|
|
22
|
-
case "k":
|
|
23
|
-
case "K":
|
|
24
|
-
toggle(video);
|
|
25
|
-
break;
|
|
26
|
-
case "m":
|
|
27
|
-
case "M":
|
|
28
|
-
video.muted = !video.muted;
|
|
29
|
-
break;
|
|
30
|
-
case "f":
|
|
31
|
-
case "F":
|
|
32
|
-
options.fullscreen.toggle();
|
|
33
|
-
break;
|
|
34
|
-
case "ArrowLeft":
|
|
35
|
-
video.currentTime = Math.max(0, video.currentTime - options.step);
|
|
36
|
-
break;
|
|
37
|
-
case "ArrowRight":
|
|
38
|
-
video.currentTime = Math.min(end(video), video.currentTime + options.step);
|
|
39
|
-
break;
|
|
40
|
-
default: return;
|
|
41
|
-
}
|
|
42
|
-
event.preventDefault();
|
|
43
|
-
}
|
|
44
|
-
function onClick(event) {
|
|
45
|
-
const path = event.composedPath();
|
|
46
|
-
if (own.some((node) => path.includes(node))) return;
|
|
47
|
-
toggle(video);
|
|
48
|
-
}
|
|
49
|
-
host.addEventListener("keydown", onKey);
|
|
50
|
-
stage.addEventListener("click", onClick);
|
|
51
|
-
return {
|
|
52
|
-
root: stage,
|
|
53
|
-
dispose() {
|
|
54
|
-
host.removeEventListener("keydown", onKey);
|
|
55
|
-
stage.removeEventListener("click", onClick);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
//#endregion
|
|
60
|
-
export { keys };
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { el, state } from "../dom.js";
|
|
2
|
-
//#region src/controls/live.ts
|
|
3
|
-
/**
|
|
4
|
-
* The live button: a dot and the word, the dot red at the edge and grey
|
|
5
|
-
* behind it, the way viewers read it everywhere. Shown once the stream has
|
|
6
|
-
* an availability window, which is what makes it live; disabled at the
|
|
7
|
-
* edge, where there is nowhere to go; a click seeks to the edge. The same
|
|
8
|
-
* test the live panel uses.
|
|
9
|
-
*
|
|
10
|
-
* Without a seek bar, when the window is too narrow to be worth one, there
|
|
11
|
-
* is nowhere to come back from either: the dot stays red and the button
|
|
12
|
-
* stays inert, whatever the playhead does.
|
|
13
|
-
*/
|
|
14
|
-
function liveButton(video) {
|
|
15
|
-
const root = el("button", "control live-button");
|
|
16
|
-
root.type = "button";
|
|
17
|
-
const dot = el("span", "live-dot");
|
|
18
|
-
root.append(dot, el("span", "live-text", "LIVE"));
|
|
19
|
-
root.setAttribute("aria-label", "Go to the live edge");
|
|
20
|
-
root.hidden = true;
|
|
21
|
-
let live;
|
|
22
|
-
let bar = true;
|
|
23
|
-
function tick() {
|
|
24
|
-
const on = live !== void 0 && live.edge !== null;
|
|
25
|
-
root.hidden = !on;
|
|
26
|
-
if (!on) return;
|
|
27
|
-
const atEdge = !bar || (live === null || live === void 0 ? void 0 : live.atEdge) === true;
|
|
28
|
-
root.disabled = atEdge;
|
|
29
|
-
state(root, "control live-button", { "at-edge": atEdge });
|
|
30
|
-
state(dot, "live-dot", { "at-edge": atEdge });
|
|
31
|
-
root.setAttribute("aria-label", atEdge ? "At the live edge" : "Go to the live edge");
|
|
32
|
-
}
|
|
33
|
-
function click() {
|
|
34
|
-
live === null || live === void 0 || live.seekToEdge();
|
|
35
|
-
}
|
|
36
|
-
root.addEventListener("click", click);
|
|
37
|
-
video.addEventListener("timeupdate", tick);
|
|
38
|
-
tick();
|
|
39
|
-
return {
|
|
40
|
-
root,
|
|
41
|
-
attach(found) {
|
|
42
|
-
live = found;
|
|
43
|
-
tick();
|
|
44
|
-
},
|
|
45
|
-
detach() {
|
|
46
|
-
live = void 0;
|
|
47
|
-
tick();
|
|
48
|
-
},
|
|
49
|
-
seekable(on) {
|
|
50
|
-
bar = on;
|
|
51
|
-
tick();
|
|
52
|
-
},
|
|
53
|
-
dispose() {
|
|
54
|
-
root.removeEventListener("click", click);
|
|
55
|
-
video.removeEventListener("timeupdate", tick);
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
//#endregion
|
|
60
|
-
export { liveButton };
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
import { el } from "../dom.js";
|
|
2
|
-
import { namespaces } from "../namespaces.js";
|
|
3
|
-
import { icon } from "./icons.js";
|
|
4
|
-
import { menu } from "./menu.js";
|
|
5
|
-
//#region src/controls/menus.ts
|
|
6
|
-
const AUTO = "auto";
|
|
7
|
-
const OFF = "off";
|
|
8
|
-
/** The subtitle looks, as attribute name, choices, and default. */
|
|
9
|
-
const SUBTITLE_SIZE = "subtitle-size";
|
|
10
|
-
const SUBTITLE_BACKGROUND = "subtitle-background";
|
|
11
|
-
const SIZES = [
|
|
12
|
-
["small", "Small"],
|
|
13
|
-
["medium", "Medium"],
|
|
14
|
-
["large", "Large"],
|
|
15
|
-
["xlarge", "Extra large"]
|
|
16
|
-
];
|
|
17
|
-
const BACKGROUNDS = [
|
|
18
|
-
["none", "None"],
|
|
19
|
-
["dark", "Dark"],
|
|
20
|
-
["solid", "Solid"]
|
|
21
|
-
];
|
|
22
|
-
/** A rendition's height when the manifest declared one, its bitrate otherwise. */
|
|
23
|
-
function renditionLabel(rendition) {
|
|
24
|
-
if (rendition.height !== void 0) return `${rendition.height}p`;
|
|
25
|
-
return `${Math.round(rendition.bitrate / 1e3)} kbps`;
|
|
26
|
-
}
|
|
27
|
-
/** The language, then the role, then the id: whichever the manifest gave. */
|
|
28
|
-
function trackLabel(track) {
|
|
29
|
-
const parts = [track.lang, track.role].filter((part) => part !== void 0);
|
|
30
|
-
return parts.length === 0 ? track.id : parts.join(" · ");
|
|
31
|
-
}
|
|
32
|
-
/** The quality menu: the pin, where "auto" means none. Hidden without renditions. */
|
|
33
|
-
const qualityMenu = ({ engine }) => {
|
|
34
|
-
const quality = engine.quality;
|
|
35
|
-
const control = menu({
|
|
36
|
-
name: "quality",
|
|
37
|
-
label: "Quality",
|
|
38
|
-
icon: "settings"
|
|
39
|
-
});
|
|
40
|
-
function render() {
|
|
41
|
-
var _quality$pinned;
|
|
42
|
-
const items = [[AUTO, "Auto"]];
|
|
43
|
-
for (const rendition of quality.renditions) items.push([rendition.id, renditionLabel(rendition)]);
|
|
44
|
-
control.fill([{
|
|
45
|
-
name: "rendition",
|
|
46
|
-
items,
|
|
47
|
-
value: (_quality$pinned = quality.pinned) !== null && _quality$pinned !== void 0 ? _quality$pinned : AUTO,
|
|
48
|
-
onSelect(value) {
|
|
49
|
-
if (value === AUTO) quality.auto();
|
|
50
|
-
else quality.pin(value);
|
|
51
|
-
render();
|
|
52
|
-
}
|
|
53
|
-
}]);
|
|
54
|
-
control.root.hidden = quality.renditions.length === 0;
|
|
55
|
-
}
|
|
56
|
-
const offs = [
|
|
57
|
-
engine.on("tracks:changed", render),
|
|
58
|
-
engine.on("quality:constraints-unsatisfiable", render),
|
|
59
|
-
engine.on("quality:pin-unsatisfiable", render)
|
|
60
|
-
];
|
|
61
|
-
render();
|
|
62
|
-
return {
|
|
63
|
-
root: control.root,
|
|
64
|
-
dispose() {
|
|
65
|
-
for (const off of offs) off();
|
|
66
|
-
control.dispose();
|
|
67
|
-
}
|
|
68
|
-
};
|
|
69
|
-
};
|
|
70
|
-
/** The tracks of one content type as menu items, with the active one. */
|
|
71
|
-
function trackItems(engine, contentType, off) {
|
|
72
|
-
var _tracks$active$id, _tracks$active;
|
|
73
|
-
const tracks = engine.tracks;
|
|
74
|
-
const available = tracks.available.filter((track) => track.contentType === contentType);
|
|
75
|
-
const items = off ? [[OFF, "Off"]] : [];
|
|
76
|
-
for (const track of available) items.push([track.id, trackLabel(track)]);
|
|
77
|
-
return [
|
|
78
|
-
items,
|
|
79
|
-
(_tracks$active$id = (_tracks$active = tracks.active(contentType)) === null || _tracks$active === void 0 ? void 0 : _tracks$active.id) !== null && _tracks$active$id !== void 0 ? _tracks$active$id : OFF,
|
|
80
|
-
available.length
|
|
81
|
-
];
|
|
82
|
-
}
|
|
83
|
-
/** The audio menu. Hidden unless there is a choice to make. */
|
|
84
|
-
const audioMenu = ({ engine }) => {
|
|
85
|
-
const control = menu({
|
|
86
|
-
name: "audio",
|
|
87
|
-
label: "Audio",
|
|
88
|
-
icon: "music"
|
|
89
|
-
});
|
|
90
|
-
function render() {
|
|
91
|
-
const [items, active, count] = trackItems(engine, "audio", false);
|
|
92
|
-
control.fill([{
|
|
93
|
-
name: "track",
|
|
94
|
-
items,
|
|
95
|
-
value: active,
|
|
96
|
-
onSelect(value) {
|
|
97
|
-
engine.tracks.select(value);
|
|
98
|
-
render();
|
|
99
|
-
}
|
|
100
|
-
}]);
|
|
101
|
-
control.root.hidden = count < 2;
|
|
102
|
-
}
|
|
103
|
-
const offs = [engine.on("tracks:changed", render), engine.on("tracks:selected", render)];
|
|
104
|
-
render();
|
|
105
|
-
return {
|
|
106
|
-
root: control.root,
|
|
107
|
-
dispose() {
|
|
108
|
-
for (const off of offs) off();
|
|
109
|
-
control.dispose();
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
};
|
|
113
|
-
/** An attribute's value where it is one of the choices, else the default. */
|
|
114
|
-
function choice(host, attribute, choices, fallback) {
|
|
115
|
-
const value = host.getAttribute(attribute);
|
|
116
|
-
return value !== null && choices.some(([id]) => id === value) ? value : fallback;
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* The subtitles menu, with "off" because a text selection is releasable
|
|
120
|
-
* and an audio one is not, and a Settings page behind it with the size and
|
|
121
|
-
* the background. The glyph says whether a track is on.
|
|
122
|
-
*/
|
|
123
|
-
const textMenu = ({ engine, host }) => {
|
|
124
|
-
const control = menu({
|
|
125
|
-
name: "text",
|
|
126
|
-
label: "Subtitles",
|
|
127
|
-
icon: "closed-captions"
|
|
128
|
-
});
|
|
129
|
-
function looks(attribute, name, label, choices, fallback) {
|
|
130
|
-
return {
|
|
131
|
-
name,
|
|
132
|
-
label,
|
|
133
|
-
items: choices,
|
|
134
|
-
value: choice(host, attribute, choices, fallback),
|
|
135
|
-
onSelect(value) {
|
|
136
|
-
host.setAttribute(attribute, value);
|
|
137
|
-
render();
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
function render() {
|
|
142
|
-
const [items, active, count] = trackItems(engine, "text", true);
|
|
143
|
-
control.fill([{
|
|
144
|
-
name: "track",
|
|
145
|
-
label: "Track",
|
|
146
|
-
items,
|
|
147
|
-
value: active,
|
|
148
|
-
onSelect(value) {
|
|
149
|
-
if (value === OFF) engine.tracks.deselect("text");
|
|
150
|
-
else engine.tracks.select(value);
|
|
151
|
-
render();
|
|
152
|
-
}
|
|
153
|
-
}, {
|
|
154
|
-
name: "settings",
|
|
155
|
-
label: "Settings",
|
|
156
|
-
entries: [looks(SUBTITLE_SIZE, "size", "Size", SIZES, "medium"), looks(SUBTITLE_BACKGROUND, "background", "Background", BACKGROUNDS, "dark")]
|
|
157
|
-
}]);
|
|
158
|
-
control.show(active === OFF ? "closed-captions" : "closed-captions-on");
|
|
159
|
-
control.root.hidden = count === 0;
|
|
160
|
-
}
|
|
161
|
-
const offs = [engine.on("tracks:changed", render), engine.on("tracks:selected", render)];
|
|
162
|
-
render();
|
|
163
|
-
return {
|
|
164
|
-
root: control.root,
|
|
165
|
-
dispose() {
|
|
166
|
-
for (const off of offs) off();
|
|
167
|
-
control.dispose();
|
|
168
|
-
}
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
/** The name a viewer knows a key system by. */
|
|
172
|
-
function keySystemName(id) {
|
|
173
|
-
if (id.startsWith("com.widevine")) return "Widevine";
|
|
174
|
-
if (id.startsWith("com.microsoft.playready")) return "PlayReady";
|
|
175
|
-
if (id.startsWith("com.apple.fps")) return "FairPlay";
|
|
176
|
-
return id;
|
|
177
|
-
}
|
|
178
|
-
/** "3 keys: usable ×2, expired ×1", or "no key yet". */
|
|
179
|
-
function sessionsText(sessions) {
|
|
180
|
-
var _counts$get;
|
|
181
|
-
if (sessions.length === 0) return "no key yet";
|
|
182
|
-
const counts = /* @__PURE__ */ new Map();
|
|
183
|
-
for (const session of sessions) counts.set(session.status, ((_counts$get = counts.get(session.status)) !== null && _counts$get !== void 0 ? _counts$get : 0) + 1);
|
|
184
|
-
const parts = [];
|
|
185
|
-
for (const [status, count] of counts) parts.push(count > 1 ? `${status} ×${count}` : status);
|
|
186
|
-
return `${sessions.length} ${sessions.length === 1 ? "key" : "keys"}: ${parts.join(", ")}`;
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* A lock over `engine.drm`, hidden until a key session opens and absent
|
|
190
|
-
* without the EME stages. Hover or focus shows what it knows: the key
|
|
191
|
-
* system, and the key sessions with their statuses.
|
|
192
|
-
*/
|
|
193
|
-
const drmBadge = ({ engine }) => {
|
|
194
|
-
const drm = namespaces(engine).drm;
|
|
195
|
-
const root = el("span", "badge drm-badge");
|
|
196
|
-
root.setAttribute("role", "img");
|
|
197
|
-
root.append(icon("lock-closed"));
|
|
198
|
-
root.hidden = true;
|
|
199
|
-
if (drm === void 0) return {
|
|
200
|
-
root,
|
|
201
|
-
dispose() {}
|
|
202
|
-
};
|
|
203
|
-
const tooltip = el("div", "tooltip drm-tooltip");
|
|
204
|
-
tooltip.setAttribute("role", "tooltip");
|
|
205
|
-
const system = el("div", "tooltip-title drm-tooltip-title");
|
|
206
|
-
const id = el("div", "tooltip-text drm-tooltip-id");
|
|
207
|
-
const keys = el("div", "tooltip-text drm-tooltip-keys");
|
|
208
|
-
tooltip.append(system, id, keys);
|
|
209
|
-
tooltip.hidden = true;
|
|
210
|
-
root.append(tooltip);
|
|
211
|
-
root.tabIndex = 0;
|
|
212
|
-
function render() {
|
|
213
|
-
var _drm$keySystem, _drm$sessions;
|
|
214
|
-
const name = (_drm$keySystem = drm === null || drm === void 0 ? void 0 : drm.keySystem) !== null && _drm$keySystem !== void 0 ? _drm$keySystem : null;
|
|
215
|
-
root.hidden = name === null;
|
|
216
|
-
if (name === null) return;
|
|
217
|
-
const sessions = (_drm$sessions = drm === null || drm === void 0 ? void 0 : drm.sessions) !== null && _drm$sessions !== void 0 ? _drm$sessions : [];
|
|
218
|
-
system.textContent = keySystemName(name);
|
|
219
|
-
id.textContent = name;
|
|
220
|
-
keys.textContent = sessionsText(sessions);
|
|
221
|
-
root.setAttribute("aria-label", `Protected by ${keySystemName(name)}, ${sessionsText(sessions)}`);
|
|
222
|
-
}
|
|
223
|
-
function show() {
|
|
224
|
-
tooltip.hidden = false;
|
|
225
|
-
}
|
|
226
|
-
function hide() {
|
|
227
|
-
tooltip.hidden = true;
|
|
228
|
-
}
|
|
229
|
-
root.addEventListener("pointerenter", show);
|
|
230
|
-
root.addEventListener("pointerleave", hide);
|
|
231
|
-
root.addEventListener("focus", show);
|
|
232
|
-
root.addEventListener("blur", hide);
|
|
233
|
-
const offs = [
|
|
234
|
-
engine.on("drm:keysystem", render),
|
|
235
|
-
engine.on("drm:keystatus", render),
|
|
236
|
-
engine.on("drm:encrypted", render)
|
|
237
|
-
];
|
|
238
|
-
render();
|
|
239
|
-
return {
|
|
240
|
-
root,
|
|
241
|
-
dispose() {
|
|
242
|
-
for (const off of offs) off();
|
|
243
|
-
root.removeEventListener("pointerenter", show);
|
|
244
|
-
root.removeEventListener("pointerleave", hide);
|
|
245
|
-
root.removeEventListener("focus", show);
|
|
246
|
-
root.removeEventListener("blur", hide);
|
|
247
|
-
}
|
|
248
|
-
};
|
|
249
|
-
};
|
|
250
|
-
/** By the name the layout knows them by. */
|
|
251
|
-
const MENUS = {
|
|
252
|
-
subtitles: textMenu,
|
|
253
|
-
audio: audioMenu,
|
|
254
|
-
quality: qualityMenu,
|
|
255
|
-
drm: drmBadge
|
|
256
|
-
};
|
|
257
|
-
//#endregion
|
|
258
|
-
export { MENUS, SUBTITLE_BACKGROUND, SUBTITLE_SIZE, audioMenu, drmBadge, qualityMenu, textMenu };
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
//#region src/controls/options.ts
|
|
2
|
-
/** The buttons row by default. `drm`, the lock, is a control the row can carry and does not by default. */
|
|
3
|
-
const LAYOUT = "skip-back play skip-forward volume | speed subtitles audio quality pip fullscreen";
|
|
4
|
-
const DEFAULTS = {
|
|
5
|
-
idleMs: 3e3,
|
|
6
|
-
seekStep: 5,
|
|
7
|
-
seekPage: 30,
|
|
8
|
-
skipBack: 10,
|
|
9
|
-
skipForward: 10,
|
|
10
|
-
start: 1,
|
|
11
|
-
liveWindow: 3,
|
|
12
|
-
layout: LAYOUT
|
|
13
|
-
};
|
|
14
|
-
/** Each option's attribute. */
|
|
15
|
-
const ATTRIBUTES = {
|
|
16
|
-
idleMs: "idle-ms",
|
|
17
|
-
seekStep: "seek-step",
|
|
18
|
-
seekPage: "seek-page",
|
|
19
|
-
skipBack: "skip-back",
|
|
20
|
-
skipForward: "skip-forward",
|
|
21
|
-
start: "start",
|
|
22
|
-
liveWindow: "live-window",
|
|
23
|
-
layout: "layout"
|
|
24
|
-
};
|
|
25
|
-
const NUMERIC = Object.keys(DEFAULTS).filter((key) => key !== "layout");
|
|
26
|
-
/** The attribute where it is a non-negative number, else the option, else the default; the layout as given. */
|
|
27
|
-
function resolve(options, attribute) {
|
|
28
|
-
var _ref, _attribute;
|
|
29
|
-
const out = {};
|
|
30
|
-
for (const key of NUMERIC) {
|
|
31
|
-
const raw = attribute(ATTRIBUTES[key]);
|
|
32
|
-
const set = raw === null ? NaN : Number(raw);
|
|
33
|
-
const given = options === null || options === void 0 ? void 0 : options[key];
|
|
34
|
-
out[key] = Number.isFinite(set) && set >= 0 ? set : given !== void 0 && Number.isFinite(given) && given >= 0 ? given : DEFAULTS[key];
|
|
35
|
-
}
|
|
36
|
-
out.layout = (_ref = (_attribute = attribute(ATTRIBUTES.layout)) !== null && _attribute !== void 0 ? _attribute : options === null || options === void 0 ? void 0 : options.layout) !== null && _ref !== void 0 ? _ref : DEFAULTS.layout;
|
|
37
|
-
return out;
|
|
38
|
-
}
|
|
39
|
-
/** A layout as two lists of names, left and right of the `|`. Unknown names are the caller's to drop. */
|
|
40
|
-
function clusters(layout) {
|
|
41
|
-
const [left = "", right = ""] = layout.split("|");
|
|
42
|
-
const names = (part) => part.split(/\s+/).filter((name) => name !== "");
|
|
43
|
-
return [names(left), names(right)];
|
|
44
|
-
}
|
|
45
|
-
//#endregion
|
|
46
|
-
export { ATTRIBUTES, DEFAULTS, LAYOUT, clusters, resolve };
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { el } from "../dom.js";
|
|
2
|
-
import { glyph, icon } from "./icons.js";
|
|
3
|
-
//#region src/controls/screens.ts
|
|
4
|
-
/** `shown` false keeps it out entirely, which is what the `start` knob at zero asks. */
|
|
5
|
-
function startButton(video, flag, shown = true) {
|
|
6
|
-
const root = el("button", "control start-button");
|
|
7
|
-
root.type = "button";
|
|
8
|
-
const svg = icon("play");
|
|
9
|
-
root.append(svg);
|
|
10
|
-
function render() {
|
|
11
|
-
const paused = video.paused;
|
|
12
|
-
const name = video.ended ? "replay" : "play";
|
|
13
|
-
glyph(svg, name);
|
|
14
|
-
root.setAttribute("aria-label", video.ended ? "Replay" : "Play");
|
|
15
|
-
root.hidden = !shown || !paused;
|
|
16
|
-
flag("paused", paused);
|
|
17
|
-
}
|
|
18
|
-
function click() {
|
|
19
|
-
video.play().catch(() => void 0);
|
|
20
|
-
}
|
|
21
|
-
const names = [
|
|
22
|
-
"play",
|
|
23
|
-
"pause",
|
|
24
|
-
"ended",
|
|
25
|
-
"emptied"
|
|
26
|
-
];
|
|
27
|
-
root.addEventListener("click", click);
|
|
28
|
-
for (const name of names) video.addEventListener(name, render);
|
|
29
|
-
render();
|
|
30
|
-
return {
|
|
31
|
-
root,
|
|
32
|
-
dispose() {
|
|
33
|
-
root.removeEventListener("click", click);
|
|
34
|
-
for (const name of names) video.removeEventListener(name, render);
|
|
35
|
-
root.remove();
|
|
36
|
-
}
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
function errorScreen(retry) {
|
|
40
|
-
const root = el("div", "error-screen");
|
|
41
|
-
root.setAttribute("role", "alert");
|
|
42
|
-
const box = el("div", "error-box");
|
|
43
|
-
const title = el("div", "error-title", "Playback failed");
|
|
44
|
-
const category = el("span", "value error-category");
|
|
45
|
-
const code = el("span", "value error-code");
|
|
46
|
-
const detail = el("div", "error-detail");
|
|
47
|
-
detail.append(category, el("span", "error-separator", " · "), code);
|
|
48
|
-
const button = el("button", "control error-retry", "Retry");
|
|
49
|
-
button.type = "button";
|
|
50
|
-
button.addEventListener("click", retry);
|
|
51
|
-
box.append(title, detail, button);
|
|
52
|
-
root.append(box);
|
|
53
|
-
root.hidden = true;
|
|
54
|
-
return {
|
|
55
|
-
root,
|
|
56
|
-
show(error) {
|
|
57
|
-
category.textContent = error.category;
|
|
58
|
-
code.textContent = error.code;
|
|
59
|
-
root.hidden = false;
|
|
60
|
-
},
|
|
61
|
-
clear() {
|
|
62
|
-
root.hidden = true;
|
|
63
|
-
},
|
|
64
|
-
shown() {
|
|
65
|
-
return !root.hidden;
|
|
66
|
-
},
|
|
67
|
-
dispose() {
|
|
68
|
-
button.removeEventListener("click", retry);
|
|
69
|
-
root.remove();
|
|
70
|
-
}
|
|
71
|
-
};
|
|
72
|
-
}
|
|
73
|
-
//#endregion
|
|
74
|
-
export { errorScreen, startButton };
|