@videojs/html 10.0.0-beta.15 → 10.0.0-beta.16
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/cdn/audio-minimal-ui.dev.js +4 -5
- package/cdn/audio-minimal-ui.js +1 -1
- package/cdn/audio-minimal.dev.js +7 -8
- package/cdn/audio-minimal.dev.js.map +1 -1
- package/cdn/audio-minimal.js +1 -1
- package/cdn/audio-minimal.js.map +1 -1
- package/cdn/audio-ui.dev.js +5 -5
- package/cdn/audio-ui.js +1 -1
- package/cdn/audio.dev.js +23 -7
- package/cdn/audio.dev.js.map +1 -1
- package/cdn/audio.js +1 -1
- package/cdn/audio.js.map +1 -1
- package/cdn/background.dev.js +3 -3
- package/cdn/background.js +1 -1
- package/cdn/background.js.map +1 -1
- package/cdn/context-C-IpVHEt.js +14 -0
- package/cdn/context-C-IpVHEt.js.map +1 -0
- package/cdn/{context-BjrbhiSk.js → context-CvJ83xGk.js} +2 -83
- package/cdn/context-CvJ83xGk.js.map +1 -0
- package/cdn/create-player-B_oNyyb5.js +7 -0
- package/cdn/create-player-B_oNyyb5.js.map +1 -0
- package/cdn/{create-player-p9xCO0yC.js → create-player-DckZq-sE.js} +56 -1416
- package/cdn/create-player-DckZq-sE.js.map +1 -0
- package/cdn/{hls-BriQI4q1.js → hls-CJCXZSGG.js} +8 -11
- package/cdn/{hls-BriQI4q1.js.map → hls-CJCXZSGG.js.map} +1 -1
- package/cdn/{hls-26YJVjvD.js → hls-lPH0rWmB.js} +3 -3
- package/cdn/{hls-26YJVjvD.js.map → hls-lPH0rWmB.js.map} +1 -1
- package/cdn/hotkey-B7OaweHa.js +154 -0
- package/cdn/hotkey-B7OaweHa.js.map +1 -0
- package/cdn/hotkey-BLEt77Z0.js +2 -0
- package/cdn/hotkey-BLEt77Z0.js.map +1 -0
- package/cdn/media/dash-video.dev.js +3 -4
- package/cdn/media/dash-video.dev.js.map +1 -1
- package/cdn/media/dash-video.js +2 -2
- package/cdn/media/hls-video.dev.js +4 -5
- package/cdn/media/hls-video.dev.js.map +1 -1
- package/cdn/media/hls-video.js +1 -1
- package/cdn/media/hls-video.js.map +1 -1
- package/cdn/media/mux-audio.dev.d.ts +1 -0
- package/cdn/media/mux-audio.dev.js +29 -0
- package/cdn/media/mux-audio.dev.js.map +1 -0
- package/cdn/media/mux-audio.js +2 -0
- package/cdn/media/mux-audio.js.map +1 -0
- package/cdn/media/mux-video.dev.js +5 -3099
- package/cdn/media/mux-video.dev.js.map +1 -1
- package/cdn/media/mux-video.js +1 -24
- package/cdn/media/mux-video.js.map +1 -1
- package/cdn/media/native-hls-video.dev.js +4 -4
- package/cdn/media/native-hls-video.js +1 -1
- package/cdn/media/simple-hls-video.dev.js +965 -680
- package/cdn/media/simple-hls-video.dev.js.map +1 -1
- package/cdn/media/simple-hls-video.js +6 -6
- package/cdn/media/simple-hls-video.js.map +1 -1
- package/cdn/{media-attach-mixin-DfKkofgF.js → media-attach-mixin-CMH1ziXP.js} +2 -2
- package/cdn/{media-attach-mixin-DfKkofgF.js.map → media-attach-mixin-CMH1ziXP.js.map} +1 -1
- package/cdn/{media-attach-mixin-Dv2D43tb.js → media-attach-mixin-DUzmXEJ3.js} +2 -2
- package/cdn/{media-attach-mixin-Dv2D43tb.js.map → media-attach-mixin-DUzmXEJ3.js.map} +1 -1
- package/cdn/{media-props-mixin-Dc5dpCV4.js → media-props-mixin-CZLZIhGT.js} +92 -8
- package/cdn/media-props-mixin-CZLZIhGT.js.map +1 -0
- package/cdn/media-props-mixin-DrjlZybt.js +47 -0
- package/cdn/media-props-mixin-DrjlZybt.js.map +1 -0
- package/cdn/{minimal-BUUGNZK7.js → minimal-D9Dw-L2P.js} +1 -1
- package/cdn/{minimal-BUUGNZK7.js.map → minimal-D9Dw-L2P.js.map} +1 -1
- package/cdn/{minimal-CJGOJ6pE.js → minimal-Dc5nNl_-.js} +1 -1
- package/cdn/{minimal-CJGOJ6pE.js.map → minimal-Dc5nNl_-.js.map} +1 -1
- package/cdn/mux-CBXn2z5k.js +3102 -0
- package/cdn/mux-CBXn2z5k.js.map +1 -0
- package/cdn/mux-DmGzBNIq.js +25 -0
- package/cdn/mux-DmGzBNIq.js.map +1 -0
- package/cdn/{native-hls-D2rfyyyW.js → native-hls-BCOLtRUl.js} +2 -3
- package/cdn/{native-hls-D2rfyyyW.js.map → native-hls-BCOLtRUl.js.map} +1 -1
- package/cdn/native-hls-BU8--1Kg.js +2 -0
- package/cdn/{native-hls-CjRvSXAJ.js.map → native-hls-BU8--1Kg.js.map} +1 -1
- package/cdn/player-DAmuLGE1.js +2 -0
- package/cdn/{player-Cz9-_j7J.js.map → player-DAmuLGE1.js.map} +1 -1
- package/cdn/{player-D0bhjT8X.js → player-Dbl1MUJ2.js} +3 -3
- package/cdn/{player-D0bhjT8X.js.map → player-Dbl1MUJ2.js.map} +1 -1
- package/cdn/poster-B9COb7AR.js +2 -0
- package/cdn/poster-B9COb7AR.js.map +1 -0
- package/cdn/poster-qAhnKWea.js +480 -0
- package/cdn/poster-qAhnKWea.js.map +1 -0
- package/cdn/{skin-element-DB-cKAAx.js → skin-element-DbmY-ske.js} +2 -2
- package/cdn/{skin-element-DB-cKAAx.js.map → skin-element-DbmY-ske.js.map} +1 -1
- package/cdn/{skin-element-zakTHELS.js → skin-element-ih3VrnYx.js} +2 -2
- package/cdn/{skin-element-zakTHELS.js.map → skin-element-ih3VrnYx.js.map} +1 -1
- package/cdn/video-minimal-ui.dev.js +4 -5
- package/cdn/video-minimal-ui.js +1 -1
- package/cdn/video-minimal.dev.js +7 -8
- package/cdn/video-minimal.dev.js.map +1 -1
- package/cdn/video-minimal.js +1 -1
- package/cdn/video-minimal.js.map +1 -1
- package/cdn/video-ui.dev.js +5 -5
- package/cdn/video-ui.js +1 -1
- package/cdn/video.dev.js +26 -7
- package/cdn/video.dev.js.map +1 -1
- package/cdn/video.js +1 -1
- package/cdn/video.js.map +1 -1
- package/cdn/volume-slider-BbIc1N4U.js +8 -0
- package/cdn/volume-slider-BbIc1N4U.js.map +1 -0
- package/cdn/{volume-slider-Co5X4Z1t.js → volume-slider-C6ek7oC9.js} +1855 -386
- package/cdn/volume-slider-C6ek7oC9.js.map +1 -0
- package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
- package/dist/default/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
- package/dist/default/_virtual/inline-css_src/define/audio/skin.js +1 -1
- package/dist/default/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
- package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
- package/dist/default/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
- package/dist/default/_virtual/inline-css_src/define/video/skin.js +1 -1
- package/dist/default/_virtual/inline-css_src/define/video/skin.js.map +1 -1
- package/dist/default/define/audio/minimal-skin.css +23 -0
- package/dist/default/define/audio/skin.css +23 -0
- package/dist/default/define/audio/skin.js +1 -1
- package/dist/default/define/audio/skin.js.map +1 -1
- package/dist/default/define/audio/ui.js +1 -0
- package/dist/default/define/background/skin.js +1 -1
- package/dist/default/define/media/mux-audio.js +13 -0
- package/dist/default/define/media/mux-audio.js.map +1 -0
- package/dist/default/define/skin-element.js +1 -1
- package/dist/default/define/ui/hotkey.js +7 -0
- package/dist/default/define/ui/hotkey.js.map +1 -0
- package/dist/default/define/ui/slider.js +1 -1
- package/dist/default/define/ui/time-slider.js +1 -1
- package/dist/default/define/ui/volume-slider.js +1 -1
- package/dist/default/define/video/minimal-skin.css +23 -0
- package/dist/default/define/video/skin.css +23 -0
- package/dist/default/define/video/skin.js +1 -1
- package/dist/default/define/video/skin.js.map +1 -1
- package/dist/default/define/video/ui.js +1 -0
- package/dist/default/index.js +5 -1
- package/dist/default/media/container-element.js +16 -0
- package/dist/default/media/container-element.js.map +1 -1
- package/dist/default/media/mux-audio/index.js +18 -0
- package/dist/default/media/mux-audio/index.js.map +1 -0
- package/dist/default/player/context.js.map +1 -1
- package/dist/default/ui/alert-dialog/alert-dialog-element.js +1 -0
- package/dist/default/ui/alert-dialog/alert-dialog-element.js.map +1 -1
- package/dist/default/ui/buffering-indicator/buffering-indicator-element.js +1 -0
- package/dist/default/ui/buffering-indicator/buffering-indicator-element.js.map +1 -1
- package/dist/default/ui/captions-button/captions-button-element.js +1 -0
- package/dist/default/ui/captions-button/captions-button-element.js.map +1 -1
- package/dist/default/ui/error-dialog/error-dialog-element.js +1 -0
- package/dist/default/ui/error-dialog/error-dialog-element.js.map +1 -1
- package/dist/default/ui/fullscreen-button/fullscreen-button-element.js +1 -0
- package/dist/default/ui/fullscreen-button/fullscreen-button-element.js.map +1 -1
- package/dist/default/ui/hotkey/aria-key-shortcuts-controller.js +28 -0
- package/dist/default/ui/hotkey/aria-key-shortcuts-controller.js.map +1 -0
- package/dist/default/ui/hotkey/hotkey-element.js +81 -0
- package/dist/default/ui/hotkey/hotkey-element.js.map +1 -0
- package/dist/default/ui/media-button-element.js +9 -1
- package/dist/default/ui/media-button-element.js.map +1 -1
- package/dist/default/ui/mute-button/mute-button-element.js +1 -0
- package/dist/default/ui/mute-button/mute-button-element.js.map +1 -1
- package/dist/default/ui/pip-button/pip-button-element.js +1 -0
- package/dist/default/ui/pip-button/pip-button-element.js.map +1 -1
- package/dist/default/ui/play-button/play-button-element.js +1 -0
- package/dist/default/ui/play-button/play-button-element.js.map +1 -1
- package/dist/default/ui/popover/popover-element.js +7 -55
- package/dist/default/ui/popover/popover-element.js.map +1 -1
- package/dist/default/ui/position-controller.js +76 -0
- package/dist/default/ui/position-controller.js.map +1 -0
- package/dist/default/ui/slider/slider-element.js +1 -1
- package/dist/default/ui/slider/slider-preview-element.js +1 -1
- package/dist/default/ui/time-slider/time-slider-element.js +5 -5
- package/dist/default/ui/time-slider/time-slider-element.js.map +1 -1
- package/dist/default/ui/tooltip/tooltip-element.js +8 -54
- package/dist/default/ui/tooltip/tooltip-element.js.map +1 -1
- package/dist/default/ui/volume-slider/volume-slider-element.js +1 -1
- package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js +1 -1
- package/dist/dev/_virtual/inline-css_src/define/audio/minimal-skin.js.map +1 -1
- package/dist/dev/_virtual/inline-css_src/define/audio/skin.js +1 -1
- package/dist/dev/_virtual/inline-css_src/define/audio/skin.js.map +1 -1
- package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js +1 -1
- package/dist/dev/_virtual/inline-css_src/define/video/minimal-skin.js.map +1 -1
- package/dist/dev/_virtual/inline-css_src/define/video/skin.js +1 -1
- package/dist/dev/_virtual/inline-css_src/define/video/skin.js.map +1 -1
- package/dist/dev/define/audio/minimal-skin.css +23 -0
- package/dist/dev/define/audio/skin.css +23 -0
- package/dist/dev/define/audio/skin.d.ts.map +1 -1
- package/dist/dev/define/audio/skin.js +16 -0
- package/dist/dev/define/audio/skin.js.map +1 -1
- package/dist/dev/define/audio/ui.js +1 -0
- package/dist/dev/define/background/skin.js +1 -1
- package/dist/dev/define/media/mux-audio.d.ts +14 -0
- package/dist/dev/define/media/mux-audio.d.ts.map +1 -0
- package/dist/dev/define/media/mux-audio.js +13 -0
- package/dist/dev/define/media/mux-audio.js.map +1 -0
- package/dist/dev/define/skin-element.d.ts +1 -1
- package/dist/dev/define/skin-element.js +1 -1
- package/dist/dev/define/ui/hotkey.d.ts +9 -0
- package/dist/dev/define/ui/hotkey.d.ts.map +1 -0
- package/dist/dev/define/ui/hotkey.js +7 -0
- package/dist/dev/define/ui/hotkey.js.map +1 -0
- package/dist/dev/define/ui/slider.js +1 -1
- package/dist/dev/define/ui/time-slider.js +1 -1
- package/dist/dev/define/ui/volume-slider.js +1 -1
- package/dist/dev/define/video/minimal-skin.css +23 -0
- package/dist/dev/define/video/skin.css +23 -0
- package/dist/dev/define/video/skin.d.ts.map +1 -1
- package/dist/dev/define/video/skin.js +19 -0
- package/dist/dev/define/video/skin.js.map +1 -1
- package/dist/dev/define/video/ui.js +1 -0
- package/dist/dev/index.d.ts +6 -2
- package/dist/dev/index.js +5 -1
- package/dist/dev/media/container-element.d.ts +3 -0
- package/dist/dev/media/container-element.d.ts.map +1 -1
- package/dist/dev/media/container-element.js +16 -0
- package/dist/dev/media/container-element.js.map +1 -1
- package/dist/dev/media/mux-audio/index.d.ts +11 -0
- package/dist/dev/media/mux-audio/index.d.ts.map +1 -0
- package/dist/dev/media/mux-audio/index.js +18 -0
- package/dist/dev/media/mux-audio/index.js.map +1 -0
- package/dist/dev/player/context.d.ts +4 -2
- package/dist/dev/player/context.d.ts.map +1 -1
- package/dist/dev/player/context.js.map +1 -1
- package/dist/dev/ui/alert-dialog/alert-dialog-element.d.ts.map +1 -1
- package/dist/dev/ui/alert-dialog/alert-dialog-element.js +1 -0
- package/dist/dev/ui/alert-dialog/alert-dialog-element.js.map +1 -1
- package/dist/dev/ui/buffering-indicator/buffering-indicator-element.d.ts.map +1 -1
- package/dist/dev/ui/buffering-indicator/buffering-indicator-element.js +1 -0
- package/dist/dev/ui/buffering-indicator/buffering-indicator-element.js.map +1 -1
- package/dist/dev/ui/captions-button/captions-button-element.d.ts +1 -0
- package/dist/dev/ui/captions-button/captions-button-element.d.ts.map +1 -1
- package/dist/dev/ui/captions-button/captions-button-element.js +1 -0
- package/dist/dev/ui/captions-button/captions-button-element.js.map +1 -1
- package/dist/dev/ui/context-part-element.d.ts +1 -1
- package/dist/dev/ui/error-dialog/error-dialog-element.d.ts.map +1 -1
- package/dist/dev/ui/error-dialog/error-dialog-element.js +1 -0
- package/dist/dev/ui/error-dialog/error-dialog-element.js.map +1 -1
- package/dist/dev/ui/fullscreen-button/fullscreen-button-element.d.ts +1 -0
- package/dist/dev/ui/fullscreen-button/fullscreen-button-element.d.ts.map +1 -1
- package/dist/dev/ui/fullscreen-button/fullscreen-button-element.js +1 -0
- package/dist/dev/ui/fullscreen-button/fullscreen-button-element.js.map +1 -1
- package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.d.ts +15 -0
- package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.d.ts.map +1 -0
- package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.js +28 -0
- package/dist/dev/ui/hotkey/aria-key-shortcuts-controller.js.map +1 -0
- package/dist/dev/ui/hotkey/hotkey-element.d.ts +21 -0
- package/dist/dev/ui/hotkey/hotkey-element.d.ts.map +1 -0
- package/dist/dev/ui/hotkey/hotkey-element.js +81 -0
- package/dist/dev/ui/hotkey/hotkey-element.js.map +1 -0
- package/dist/dev/ui/media-button-element.d.ts +2 -0
- package/dist/dev/ui/media-button-element.d.ts.map +1 -1
- package/dist/dev/ui/media-button-element.js +9 -1
- package/dist/dev/ui/media-button-element.js.map +1 -1
- package/dist/dev/ui/mute-button/mute-button-element.d.ts +1 -0
- package/dist/dev/ui/mute-button/mute-button-element.d.ts.map +1 -1
- package/dist/dev/ui/mute-button/mute-button-element.js +1 -0
- package/dist/dev/ui/mute-button/mute-button-element.js.map +1 -1
- package/dist/dev/ui/pip-button/pip-button-element.d.ts +1 -0
- package/dist/dev/ui/pip-button/pip-button-element.d.ts.map +1 -1
- package/dist/dev/ui/pip-button/pip-button-element.js +1 -0
- package/dist/dev/ui/pip-button/pip-button-element.js.map +1 -1
- package/dist/dev/ui/play-button/play-button-element.d.ts +1 -0
- package/dist/dev/ui/play-button/play-button-element.d.ts.map +1 -1
- package/dist/dev/ui/play-button/play-button-element.js +1 -0
- package/dist/dev/ui/play-button/play-button-element.js.map +1 -1
- package/dist/dev/ui/popover/popover-element.d.ts.map +1 -1
- package/dist/dev/ui/popover/popover-element.js +7 -55
- package/dist/dev/ui/popover/popover-element.js.map +1 -1
- package/dist/dev/ui/position-controller.js +76 -0
- package/dist/dev/ui/position-controller.js.map +1 -0
- package/dist/dev/ui/slider/slider-element.js +1 -1
- package/dist/dev/ui/slider/slider-preview-element.d.ts +21 -0
- package/dist/dev/ui/slider/slider-preview-element.d.ts.map +1 -0
- package/dist/dev/ui/slider/slider-preview-element.js +1 -1
- package/dist/dev/ui/time-slider/time-slider-element.d.ts +2 -2
- package/dist/dev/ui/time-slider/time-slider-element.js +5 -5
- package/dist/dev/ui/time-slider/time-slider-element.js.map +1 -1
- package/dist/dev/ui/tooltip/tooltip-element.d.ts.map +1 -1
- package/dist/dev/ui/tooltip/tooltip-element.js +8 -54
- package/dist/dev/ui/tooltip/tooltip-element.js.map +1 -1
- package/dist/dev/ui/volume-slider/volume-slider-element.js +1 -1
- package/package.json +8 -8
- package/cdn/context-BjrbhiSk.js.map +0 -1
- package/cdn/context-CdkhXQEw.js +0 -14
- package/cdn/context-CdkhXQEw.js.map +0 -1
- package/cdn/create-player-BqU8r8H4.js +0 -7
- package/cdn/create-player-BqU8r8H4.js.map +0 -1
- package/cdn/create-player-p9xCO0yC.js.map +0 -1
- package/cdn/delegate-B626t_Va.js +0 -2
- package/cdn/delegate-B626t_Va.js.map +0 -1
- package/cdn/delegate-BCw-LjP_.js +0 -56
- package/cdn/delegate-BCw-LjP_.js.map +0 -1
- package/cdn/media-props-mixin-Bd_N2HWy.js +0 -47
- package/cdn/media-props-mixin-Bd_N2HWy.js.map +0 -1
- package/cdn/media-props-mixin-Dc5dpCV4.js.map +0 -1
- package/cdn/native-hls-CjRvSXAJ.js +0 -2
- package/cdn/player-Cz9-_j7J.js +0 -2
- package/cdn/poster-2FPYTjyv.js +0 -2
- package/cdn/poster-2FPYTjyv.js.map +0 -1
- package/cdn/poster-gVT-J1-z.js +0 -215
- package/cdn/poster-gVT-J1-z.js.map +0 -1
- package/cdn/volume-slider-Co5X4Z1t.js.map +0 -1
- package/cdn/volume-slider-D18sXnIA.js +0 -8
- package/cdn/volume-slider-D18sXnIA.js.map +0 -1
- /package/cdn/{minimal-ui-BL9eBXck.js → minimal-ui-DXFwjywa.js} +0 -0
- /package/cdn/{minimal-ui-a1UOKF79.js → minimal-ui-jrmrxIOn.js} +0 -0
- /package/cdn/{ui-CFIgmrlA.js → ui-18UYtw8D.js} +0 -0
- /package/cdn/{ui-Ccp_LyCf.js → ui-8HVY3XSt.js} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { C as
|
|
2
|
-
import {
|
|
1
|
+
import { C as noop, D as isNull, E as isFunction, O as isNumber, S as createState, T as AbortControllerRegistry, _ as pipFeature, a as MediaElement, b as controlsFeature, d as volumeFeature, f as timeFeature, g as playbackFeature, h as playbackRateFeature, j as resolveEventTarget, k as isUndefined, m as sourceFeature, n as PlayerController, o as ContextProvider, p as textTrackFeature, r as SnapshotController, s as ContextConsumer, v as fullscreenFeature, w as throwNoTargetError, x as bufferFeature, y as errorFeature } from "./create-player-DckZq-sE.js";
|
|
2
|
+
import { t as listen } from "./listen-w-Aun0yN.js";
|
|
3
|
+
import { i as createContext, o as safeDefine, r as playerContext, t as containerContext } from "./context-CvJ83xGk.js";
|
|
3
4
|
|
|
4
5
|
//#region ../utils/dist/dom/direction.js
|
|
5
6
|
/** Check whether an element's text direction is right-to-left. */
|
|
@@ -9,6 +10,98 @@ function isRTL(element) {
|
|
|
9
10
|
return getComputedStyle(element).direction === "rtl";
|
|
10
11
|
}
|
|
11
12
|
|
|
13
|
+
//#endregion
|
|
14
|
+
//#region ../utils/dist/dom/supports.js
|
|
15
|
+
function supportsAnchorPositioning() {
|
|
16
|
+
return typeof CSS !== "undefined" && CSS.supports("anchor-name: --a");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region ../utils/dist/dom/platform.js
|
|
21
|
+
function isMacOS() {
|
|
22
|
+
return typeof navigator !== "undefined" && /mac/i.test(navigator.userAgent);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region ../utils/dist/dom/popover.js
|
|
27
|
+
function tryShowPopover(el) {
|
|
28
|
+
try {
|
|
29
|
+
el?.showPopover?.();
|
|
30
|
+
} catch {}
|
|
31
|
+
}
|
|
32
|
+
function tryHidePopover(el) {
|
|
33
|
+
try {
|
|
34
|
+
el?.hidePopover?.();
|
|
35
|
+
} catch {}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region ../utils/dist/dom/predicates.js
|
|
40
|
+
const EDITABLE_INPUT_TYPES = new Set([
|
|
41
|
+
"text",
|
|
42
|
+
"search",
|
|
43
|
+
"url",
|
|
44
|
+
"tel",
|
|
45
|
+
"email",
|
|
46
|
+
"password",
|
|
47
|
+
"number"
|
|
48
|
+
]);
|
|
49
|
+
function isEditableElement(el) {
|
|
50
|
+
if (el instanceof HTMLTextAreaElement) return true;
|
|
51
|
+
if (el instanceof HTMLSelectElement) return true;
|
|
52
|
+
if (el instanceof HTMLInputElement) return EDITABLE_INPUT_TYPES.has(el.type.toLowerCase());
|
|
53
|
+
if (!(el instanceof HTMLElement)) return false;
|
|
54
|
+
const editable = el.getAttribute("contenteditable");
|
|
55
|
+
return editable !== null && editable !== "false";
|
|
56
|
+
}
|
|
57
|
+
/** Whether the keyboard event target is an editable element (input, textarea, etc). */
|
|
58
|
+
function isEditableTarget(event) {
|
|
59
|
+
const target = resolveEventTarget(event);
|
|
60
|
+
return target instanceof Element && isEditableElement(target);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region ../utils/dist/string/casing.js
|
|
65
|
+
function kebabCase(str) {
|
|
66
|
+
return str.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
//#endregion
|
|
70
|
+
//#region ../utils/dist/dom/style.js
|
|
71
|
+
function applyStyles(element, styles) {
|
|
72
|
+
for (const [prop, value] of Object.entries(styles)) if (typeof value === "string") {
|
|
73
|
+
const key = prop.startsWith("--") ? prop : kebabCase(prop);
|
|
74
|
+
element.style.setProperty(key, value);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function resolveCSSLength(el, value) {
|
|
78
|
+
const trimmed = value.trim();
|
|
79
|
+
if (!trimmed) return 0;
|
|
80
|
+
const parsed = Number.parseFloat(trimmed);
|
|
81
|
+
if (Number.isNaN(parsed)) return 0;
|
|
82
|
+
if (/^-?\d*\.?\d+$/.test(trimmed) || trimmed.endsWith("px")) return parsed;
|
|
83
|
+
const doc = el.ownerDocument;
|
|
84
|
+
const root = doc?.documentElement;
|
|
85
|
+
if (trimmed.endsWith("rem")) return parsed * (root ? Number.parseFloat(getComputedStyle(root).fontSize) || 16 : 16);
|
|
86
|
+
if (trimmed.endsWith("em")) return parsed * (el instanceof HTMLElement ? Number.parseFloat(getComputedStyle(el).fontSize) || 16 : 16);
|
|
87
|
+
if (!doc) return parsed;
|
|
88
|
+
const measurementEl = doc.createElement("div");
|
|
89
|
+
measurementEl.style.position = "absolute";
|
|
90
|
+
measurementEl.style.visibility = "hidden";
|
|
91
|
+
measurementEl.style.pointerEvents = "none";
|
|
92
|
+
measurementEl.style.inlineSize = trimmed;
|
|
93
|
+
measurementEl.style.blockSize = "0";
|
|
94
|
+
measurementEl.style.padding = "0";
|
|
95
|
+
measurementEl.style.border = "0";
|
|
96
|
+
measurementEl.style.inset = "0";
|
|
97
|
+
const parent = doc.body ?? doc.documentElement;
|
|
98
|
+
if (!parent) return parsed;
|
|
99
|
+
parent.appendChild(measurementEl);
|
|
100
|
+
const pixels = measurementEl.getBoundingClientRect().width;
|
|
101
|
+
measurementEl.remove();
|
|
102
|
+
return Number.isFinite(pixels) ? pixels : parsed;
|
|
103
|
+
}
|
|
104
|
+
|
|
12
105
|
//#endregion
|
|
13
106
|
//#region ../utils/dist/object/defaults.js
|
|
14
107
|
/**
|
|
@@ -28,250 +121,1695 @@ function defaults(object, defaultValues) {
|
|
|
28
121
|
}
|
|
29
122
|
|
|
30
123
|
//#endregion
|
|
31
|
-
//#region ../
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
124
|
+
//#region ../utils/dist/object/pick.js
|
|
125
|
+
/**
|
|
126
|
+
* Creates a new object with only the specified keys.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* const obj = { a: 1, b: 2, c: 3 };
|
|
130
|
+
* pick(obj, ['a', 'c']); // { a: 1, c: 3 }
|
|
131
|
+
*/
|
|
132
|
+
function pick(obj, keys) {
|
|
133
|
+
const result = {};
|
|
134
|
+
for (const key of keys) result[key] = obj[key];
|
|
135
|
+
return result;
|
|
37
136
|
}
|
|
38
137
|
|
|
39
138
|
//#endregion
|
|
40
|
-
//#region ../
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
139
|
+
//#region ../store/dist/dev/core/selector.js
|
|
140
|
+
const stateContext = {
|
|
141
|
+
target: throwNoTargetError,
|
|
142
|
+
signals: new AbortControllerRegistry(),
|
|
143
|
+
get: throwNoTargetError,
|
|
144
|
+
set: throwNoTargetError
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Create a type-safe selector for a slice's state.
|
|
148
|
+
*
|
|
149
|
+
* The selector returns the slice's state, or `undefined` if the slice
|
|
150
|
+
* is not configured in the store.
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* ```ts
|
|
154
|
+
* const selectPlayback = createSelector(playbackSlice);
|
|
155
|
+
* selectPlayback(store.state); // { paused, play, pause, ... } | undefined
|
|
156
|
+
* selectPlayback.displayName; // 'playback' (from slice name)
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @param slice - The slice to create a selector for.
|
|
160
|
+
*/
|
|
161
|
+
function createSelector(slice) {
|
|
162
|
+
const initialState = slice.state(stateContext);
|
|
163
|
+
const keys = Object.keys(initialState);
|
|
164
|
+
const firstKey = keys[0];
|
|
165
|
+
if (!firstKey) return Object.assign(() => void 0, { displayName: slice.name });
|
|
166
|
+
return Object.assign((state) => {
|
|
167
|
+
if (!(firstKey in state)) return void 0;
|
|
168
|
+
return pick(state, keys);
|
|
169
|
+
}, { displayName: slice.name });
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
//#endregion
|
|
173
|
+
//#region ../utils/dist/function/throttle.js
|
|
174
|
+
/**
|
|
175
|
+
* Throttle: limits `fn` to at most once per `ms` window.
|
|
176
|
+
*
|
|
177
|
+
* - Default (no options): trailing-edge only — the first call schedules a
|
|
178
|
+
* timer; subsequent calls within the window update the arguments. The
|
|
179
|
+
* function fires once per window with the latest arguments.
|
|
180
|
+
* - `{ leading: true }`: leading + trailing — the first call invokes
|
|
181
|
+
* immediately and opens a cooldown window. Subsequent calls within the
|
|
182
|
+
* window are coalesced to a single trailing-edge invocation.
|
|
183
|
+
*/
|
|
184
|
+
function throttle(fn, ms, options) {
|
|
185
|
+
const leading = options?.leading ?? false;
|
|
186
|
+
let timerId = null;
|
|
187
|
+
let latestArgs;
|
|
188
|
+
let hasPending = false;
|
|
189
|
+
function startCooldown() {
|
|
190
|
+
timerId = setTimeout(() => {
|
|
191
|
+
timerId = null;
|
|
192
|
+
if (hasPending) {
|
|
193
|
+
hasPending = false;
|
|
194
|
+
fn(...latestArgs);
|
|
195
|
+
startCooldown();
|
|
196
|
+
}
|
|
197
|
+
}, ms);
|
|
198
|
+
}
|
|
199
|
+
const throttled = (...args) => {
|
|
200
|
+
latestArgs = args;
|
|
201
|
+
if (leading) if (timerId === null) {
|
|
202
|
+
fn(...latestArgs);
|
|
203
|
+
startCooldown();
|
|
204
|
+
} else hasPending = true;
|
|
205
|
+
else {
|
|
206
|
+
if (timerId !== null) return;
|
|
207
|
+
timerId = setTimeout(() => {
|
|
208
|
+
timerId = null;
|
|
209
|
+
fn(...latestArgs);
|
|
210
|
+
}, ms);
|
|
211
|
+
}
|
|
45
212
|
};
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
213
|
+
throttled.cancel = () => {
|
|
214
|
+
if (timerId !== null) {
|
|
215
|
+
clearTimeout(timerId);
|
|
216
|
+
timerId = null;
|
|
217
|
+
}
|
|
218
|
+
hasPending = false;
|
|
219
|
+
};
|
|
220
|
+
return throttled;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region ../core/dist/dev/dom/store/selectors.js
|
|
225
|
+
/** Select the buffer state (buffered ranges, percent buffered). */
|
|
226
|
+
const selectBuffer = createSelector(bufferFeature);
|
|
227
|
+
/** Select the controls state (controls visible, user-active). */
|
|
228
|
+
const selectControls = createSelector(controlsFeature);
|
|
229
|
+
/** Select the error state (error, dismissed, dismissError). */
|
|
230
|
+
const selectError = createSelector(errorFeature);
|
|
231
|
+
/** Select the fullscreen state (fullscreen active, availability). */
|
|
232
|
+
const selectFullscreen = createSelector(fullscreenFeature);
|
|
233
|
+
/** Select the PiP state (picture-in-picture active, availability). */
|
|
234
|
+
const selectPiP = createSelector(pipFeature);
|
|
235
|
+
/** Select the playback state (paused, ended, play, pause, toggle). */
|
|
236
|
+
const selectPlayback = createSelector(playbackFeature);
|
|
237
|
+
/** Select the playback rate state (playbackRate, playbackRates, setPlaybackRate). */
|
|
238
|
+
const selectPlaybackRate = createSelector(playbackRateFeature);
|
|
239
|
+
/** Select the source state (src, type). */
|
|
240
|
+
const selectSource = createSelector(sourceFeature);
|
|
241
|
+
/** Select the text track state (chapters cues, thumbnail cues). */
|
|
242
|
+
const selectTextTrack = createSelector(textTrackFeature);
|
|
243
|
+
/** Select the time state (currentTime, duration, seek). */
|
|
244
|
+
const selectTime = createSelector(timeFeature);
|
|
245
|
+
/** Select the volume state (volume, muted, setVolume, setMuted). */
|
|
246
|
+
const selectVolume = createSelector(volumeFeature);
|
|
247
|
+
|
|
248
|
+
//#endregion
|
|
249
|
+
//#region ../core/dist/dev/dom/hotkey/aria.js
|
|
250
|
+
const ARIA_MODIFIER_MAP = {
|
|
251
|
+
shift: "Shift",
|
|
252
|
+
ctrl: "Control",
|
|
253
|
+
alt: "Alt",
|
|
254
|
+
meta: "Meta"
|
|
255
|
+
};
|
|
256
|
+
const MODIFIER_ORDER = [
|
|
257
|
+
"ctrl",
|
|
258
|
+
"shift",
|
|
259
|
+
"alt",
|
|
260
|
+
"meta"
|
|
261
|
+
];
|
|
262
|
+
/**
|
|
263
|
+
* Convert parsed key bindings to a WAI-ARIA `aria-keyshortcuts` formatted string.
|
|
264
|
+
*
|
|
265
|
+
* @example
|
|
266
|
+
* ```ts
|
|
267
|
+
* toAriaKeyShortcut(parseHotkeyPattern('Ctrl+Shift+f'));
|
|
268
|
+
* // "Control+Shift+f"
|
|
269
|
+
*
|
|
270
|
+
* toAriaKeyShortcut([...parseHotkeyPattern('k'), ...parseHotkeyPattern('Space')]);
|
|
271
|
+
* // "k Space"
|
|
272
|
+
* ```
|
|
273
|
+
*/
|
|
274
|
+
function toAriaKeyShortcut(bindings) {
|
|
275
|
+
return bindings.map((b) => {
|
|
276
|
+
const parts = [];
|
|
277
|
+
for (const mod of MODIFIER_ORDER) if (b.modifiers.has(mod)) parts.push(ARIA_MODIFIER_MAP[mod]);
|
|
278
|
+
parts.push(b.originalKey);
|
|
279
|
+
return parts.join("+");
|
|
280
|
+
}).join(" ");
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
//#endregion
|
|
284
|
+
//#region ../core/dist/dev/dom/hotkey/coordinator.js
|
|
285
|
+
const ACTIVATION_KEYS = new Set([" ", "Enter"]);
|
|
286
|
+
/** Whether the event is an activation key on an interactive element (button, slider). */
|
|
287
|
+
function isInteractiveActivation(event) {
|
|
288
|
+
if (!ACTIVATION_KEYS.has(event.key)) return false;
|
|
289
|
+
const target = resolveEventTarget(event);
|
|
290
|
+
if (!(target instanceof HTMLElement)) return false;
|
|
291
|
+
if (target instanceof HTMLButtonElement) return true;
|
|
292
|
+
const role = target.getAttribute("role");
|
|
293
|
+
return role === "button" || role === "slider";
|
|
294
|
+
}
|
|
295
|
+
var HotkeyCoordinator = class {
|
|
296
|
+
#target;
|
|
297
|
+
#bindings = [];
|
|
298
|
+
#nextId = 0;
|
|
299
|
+
#disconnect = null;
|
|
300
|
+
#docDisconnect = null;
|
|
301
|
+
/** Action name → bound keys. Controls query this to set `aria-keyshortcuts`. */
|
|
302
|
+
#ariaRegistry = /* @__PURE__ */ new Map();
|
|
303
|
+
#destroyed = false;
|
|
304
|
+
constructor(target) {
|
|
305
|
+
this.#target = target;
|
|
306
|
+
}
|
|
307
|
+
add(options) {
|
|
308
|
+
const parsed = parseHotkeyPattern(options.keys);
|
|
309
|
+
const binding = {
|
|
310
|
+
parsed,
|
|
311
|
+
options,
|
|
312
|
+
id: this.#nextId++
|
|
313
|
+
};
|
|
314
|
+
this.#bindings.push(binding);
|
|
315
|
+
this.#sortBindings();
|
|
316
|
+
if (options.action) this.#addToAriaRegistry(options.action, parsed);
|
|
317
|
+
if (options.target === "document") this.#connectDocument();
|
|
318
|
+
else this.#connect();
|
|
319
|
+
let removed = false;
|
|
320
|
+
return () => {
|
|
321
|
+
if (removed) return;
|
|
322
|
+
removed = true;
|
|
323
|
+
const idx = this.#bindings.indexOf(binding);
|
|
324
|
+
if (idx !== -1) this.#bindings.splice(idx, 1);
|
|
325
|
+
if (options.action) this.#removeFromAriaRegistry(options.action, parsed);
|
|
326
|
+
this.#maybeDisconnect();
|
|
327
|
+
};
|
|
53
328
|
}
|
|
54
|
-
|
|
55
|
-
|
|
329
|
+
getAriaKeys(action) {
|
|
330
|
+
const bindings = this.#ariaRegistry.get(action);
|
|
331
|
+
if (!bindings?.length) return void 0;
|
|
332
|
+
return toAriaKeyShortcut(bindings);
|
|
56
333
|
}
|
|
57
|
-
|
|
58
|
-
this.#
|
|
334
|
+
destroy() {
|
|
335
|
+
if (this.#destroyed) return;
|
|
336
|
+
this.#destroyed = true;
|
|
337
|
+
this.#disconnect?.abort();
|
|
338
|
+
this.#disconnect = null;
|
|
339
|
+
this.#docDisconnect?.abort();
|
|
340
|
+
this.#docDisconnect = null;
|
|
341
|
+
this.#bindings = [];
|
|
342
|
+
this.#ariaRegistry.clear();
|
|
343
|
+
}
|
|
344
|
+
#sortBindings() {
|
|
345
|
+
this.#bindings.sort((a, b) => {
|
|
346
|
+
const specDiff = b.parsed[0].modifiers.size - a.parsed[0].modifiers.size;
|
|
347
|
+
if (specDiff !== 0) return specDiff;
|
|
348
|
+
return a.id - b.id;
|
|
349
|
+
});
|
|
59
350
|
}
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
};
|
|
351
|
+
#connect() {
|
|
352
|
+
if (this.#disconnect) return;
|
|
353
|
+
this.#disconnect = new AbortController();
|
|
354
|
+
listen(this.#target, "keydown", this.#handleEvent, { signal: this.#disconnect.signal });
|
|
355
|
+
}
|
|
356
|
+
#connectDocument() {
|
|
357
|
+
if (this.#docDisconnect) return;
|
|
358
|
+
this.#docDisconnect = new AbortController();
|
|
359
|
+
listen(document, "keydown", this.#handleEvent, { signal: this.#docDisconnect.signal });
|
|
360
|
+
}
|
|
361
|
+
#maybeDisconnect() {
|
|
362
|
+
const hasPlayer = this.#bindings.some((b) => b.options.target !== "document");
|
|
363
|
+
const hasDoc = this.#bindings.some((b) => b.options.target === "document");
|
|
364
|
+
if (!hasPlayer) {
|
|
365
|
+
this.#disconnect?.abort();
|
|
366
|
+
this.#disconnect = null;
|
|
367
|
+
}
|
|
368
|
+
if (!hasDoc) {
|
|
369
|
+
this.#docDisconnect?.abort();
|
|
370
|
+
this.#docDisconnect = null;
|
|
371
|
+
}
|
|
69
372
|
}
|
|
70
|
-
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
373
|
+
#handleEvent = (event) => {
|
|
374
|
+
if (event.key === "Unidentified") return;
|
|
375
|
+
if (isInteractiveActivation(event)) return;
|
|
376
|
+
const editable = isEditableTarget(event);
|
|
377
|
+
for (const binding of this.#bindings) {
|
|
378
|
+
const { options, parsed } = binding;
|
|
379
|
+
if (options.disabled) continue;
|
|
380
|
+
if (event.repeat && options.repeatable === false) continue;
|
|
381
|
+
if (options.target === "document" !== (event.currentTarget === document)) continue;
|
|
382
|
+
for (const p of parsed) {
|
|
383
|
+
if (!matchesHotkeyEvent(p, event)) continue;
|
|
384
|
+
if (editable && p.modifiers.size === 0) continue;
|
|
385
|
+
event.preventDefault();
|
|
386
|
+
options.onActivate(event, p.originalKey);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
#addToAriaRegistry(action, bindings) {
|
|
392
|
+
let existing = this.#ariaRegistry.get(action);
|
|
393
|
+
if (!existing) {
|
|
394
|
+
existing = [];
|
|
395
|
+
this.#ariaRegistry.set(action, existing);
|
|
396
|
+
}
|
|
397
|
+
existing.push(...bindings);
|
|
398
|
+
}
|
|
399
|
+
#removeFromAriaRegistry(action, bindings) {
|
|
400
|
+
const existing = this.#ariaRegistry.get(action);
|
|
401
|
+
if (!existing) return;
|
|
402
|
+
const filtered = existing.filter((b) => !bindings.includes(b));
|
|
403
|
+
if (filtered.length === 0) this.#ariaRegistry.delete(action);
|
|
404
|
+
else this.#ariaRegistry.set(action, filtered);
|
|
77
405
|
}
|
|
78
406
|
};
|
|
79
407
|
|
|
80
408
|
//#endregion
|
|
81
|
-
//#region ../core/dist/dev/
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
409
|
+
//#region ../core/dist/dev/dom/hotkey/hotkey.js
|
|
410
|
+
const MODIFIER_KEYS = new Set([
|
|
411
|
+
"shift",
|
|
412
|
+
"ctrl",
|
|
413
|
+
"alt",
|
|
414
|
+
"meta"
|
|
415
|
+
]);
|
|
416
|
+
/**
|
|
417
|
+
* Parse a key pattern string into one or more bindings.
|
|
418
|
+
*
|
|
419
|
+
* @example
|
|
420
|
+
* ```ts
|
|
421
|
+
* parseHotkeyPattern('>');
|
|
422
|
+
* // [{ modifiers: Set(), key: '>', originalKey: '>' }]
|
|
423
|
+
*
|
|
424
|
+
* parseHotkeyPattern('0-9');
|
|
425
|
+
* // 10 bindings, one per digit
|
|
426
|
+
* ```
|
|
427
|
+
*/
|
|
428
|
+
function parseHotkeyPattern(pattern) {
|
|
429
|
+
if (pattern === "0-9") return Array.from({ length: 10 }, (_, i) => ({
|
|
430
|
+
modifiers: /* @__PURE__ */ new Set(),
|
|
431
|
+
key: String(i),
|
|
432
|
+
originalKey: String(i)
|
|
433
|
+
}));
|
|
434
|
+
const segments = pattern.split("+");
|
|
435
|
+
const rawKey = segments.pop();
|
|
436
|
+
const modifiers = /* @__PURE__ */ new Set();
|
|
437
|
+
for (const seg of segments) {
|
|
438
|
+
const lower = seg.toLowerCase();
|
|
439
|
+
if (lower === "mod") modifiers.add(isMacOS() ? "meta" : "ctrl");
|
|
440
|
+
else if (MODIFIER_KEYS.has(lower)) modifiers.add(lower);
|
|
441
|
+
else console.warn(`[vjs-hotkey] Unknown modifier: "${seg}" in pattern "${pattern}"`);
|
|
442
|
+
}
|
|
443
|
+
return [{
|
|
444
|
+
modifiers,
|
|
445
|
+
key: rawKey === "Space" ? " " : rawKey.toLowerCase(),
|
|
446
|
+
originalKey: rawKey
|
|
447
|
+
}];
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Single non-letter character — layout-dependent modifiers (Shift, Alt/Option)
|
|
451
|
+
* were used to produce the character itself, not as deliberate modifiers
|
|
452
|
+
* (e.g. Shift+. → ">", Option+Shift → ">" on some Mac layouts).
|
|
453
|
+
* Letters excluded because Shift changes case intentionally (k vs K).
|
|
454
|
+
* Named keys excluded because event.key.length > 1 (ArrowLeft, Tab, etc.).
|
|
455
|
+
*/
|
|
456
|
+
function isImplicitModifierKey(key) {
|
|
457
|
+
return key.length === 1 && !/[a-z]/i.test(key);
|
|
458
|
+
}
|
|
459
|
+
/** Whether a parsed binding matches a keyboard event. */
|
|
460
|
+
function matchesHotkeyEvent(binding, event) {
|
|
461
|
+
if (event.key === "Unidentified") return false;
|
|
462
|
+
if (event.key.toLowerCase() !== binding.key) return false;
|
|
463
|
+
const implicit = isImplicitModifierKey(event.key);
|
|
464
|
+
const shiftKey = implicit ? event.shiftKey && binding.modifiers.has("shift") : event.shiftKey;
|
|
465
|
+
const altKey = implicit ? event.altKey && binding.modifiers.has("alt") : event.altKey;
|
|
466
|
+
if (shiftKey !== binding.modifiers.has("shift")) return false;
|
|
467
|
+
if (event.ctrlKey !== binding.modifiers.has("ctrl")) return false;
|
|
468
|
+
if (altKey !== binding.modifiers.has("alt")) return false;
|
|
469
|
+
if (event.metaKey !== binding.modifiers.has("meta")) return false;
|
|
470
|
+
return true;
|
|
471
|
+
}
|
|
472
|
+
const coordinators = /* @__PURE__ */ new WeakMap();
|
|
473
|
+
/** Look up the coordinator for a target element, if one exists. */
|
|
474
|
+
function findHotkeyCoordinator(target) {
|
|
475
|
+
return coordinators.get(target);
|
|
476
|
+
}
|
|
477
|
+
function getCoordinator(target) {
|
|
478
|
+
let coordinator = coordinators.get(target);
|
|
479
|
+
if (!coordinator) {
|
|
480
|
+
coordinator = new HotkeyCoordinator(target);
|
|
481
|
+
coordinators.set(target, coordinator);
|
|
482
|
+
}
|
|
483
|
+
return coordinator;
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Register a hotkey binding on a target element.
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```ts
|
|
490
|
+
* const cleanup = createHotkey(container, {
|
|
491
|
+
* keys: 'k',
|
|
492
|
+
* onActivate: () => store.paused ? store.play() : store.pause(),
|
|
493
|
+
* });
|
|
494
|
+
*
|
|
495
|
+
* // Later: remove the binding
|
|
496
|
+
* cleanup();
|
|
497
|
+
* ```
|
|
498
|
+
*
|
|
499
|
+
* @returns A cleanup function that removes the binding.
|
|
500
|
+
*/
|
|
501
|
+
function createHotkey(target, options) {
|
|
502
|
+
return getCoordinator(target).add(options);
|
|
503
|
+
}
|
|
87
504
|
|
|
88
505
|
//#endregion
|
|
89
|
-
//#region ../core/dist/dev/
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
state =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
506
|
+
//#region ../core/dist/dev/dom/ui/dismiss-layer.js
|
|
507
|
+
function createDismissLayer(options) {
|
|
508
|
+
const { transition } = options;
|
|
509
|
+
const state = transition.state;
|
|
510
|
+
const abort = new AbortController();
|
|
511
|
+
let docAbort = null;
|
|
512
|
+
function open() {
|
|
513
|
+
if (abort.signal.aborted) return null;
|
|
514
|
+
const { active, status } = state.current;
|
|
515
|
+
if (active && status !== "ending") return null;
|
|
516
|
+
if (status === "ending") transition.cancel();
|
|
517
|
+
return transition.open();
|
|
518
|
+
}
|
|
519
|
+
function close(element) {
|
|
520
|
+
const { active, status } = state.current;
|
|
521
|
+
if (abort.signal.aborted || !active || status === "ending") return null;
|
|
522
|
+
return transition.close(element);
|
|
523
|
+
}
|
|
524
|
+
function setupDocumentListeners() {
|
|
525
|
+
cleanupDocumentListeners();
|
|
526
|
+
if (typeof document === "undefined") return;
|
|
527
|
+
docAbort = new AbortController();
|
|
528
|
+
const { signal } = docAbort;
|
|
529
|
+
listen(document, "keydown", handleKeydown, { signal });
|
|
530
|
+
options.onDocumentActive?.(signal);
|
|
531
|
+
}
|
|
532
|
+
function cleanupDocumentListeners() {
|
|
533
|
+
docAbort?.abort();
|
|
534
|
+
docAbort = null;
|
|
535
|
+
}
|
|
536
|
+
function handleKeydown(event) {
|
|
537
|
+
if (event.key !== "Escape") return;
|
|
538
|
+
if (!state.current.active) return;
|
|
539
|
+
if (!(options.closeOnEscape?.() ?? true)) return;
|
|
540
|
+
options.onEscapeDismiss(event);
|
|
541
|
+
}
|
|
542
|
+
const unsubscribe = state.subscribe(() => {
|
|
543
|
+
if (state.current.active) setupDocumentListeners();
|
|
544
|
+
else cleanupDocumentListeners();
|
|
545
|
+
});
|
|
546
|
+
abort.signal.addEventListener("abort", () => {
|
|
547
|
+
unsubscribe();
|
|
548
|
+
transition.destroy();
|
|
549
|
+
cleanupDocumentListeners();
|
|
550
|
+
});
|
|
551
|
+
function destroy() {
|
|
552
|
+
if (abort.signal.aborted) return;
|
|
553
|
+
abort.abort();
|
|
97
554
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
555
|
+
return {
|
|
556
|
+
input: state,
|
|
557
|
+
open,
|
|
558
|
+
close,
|
|
559
|
+
signal: abort.signal,
|
|
560
|
+
destroy
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
//#endregion
|
|
565
|
+
//#region ../core/dist/dev/dom/ui/alert-dialog.js
|
|
566
|
+
function createAlertDialog(options) {
|
|
567
|
+
const { onOpenChange } = options;
|
|
568
|
+
let element = null;
|
|
569
|
+
let previousFocus = null;
|
|
570
|
+
let elementAbort = null;
|
|
571
|
+
const layer = createDismissLayer({
|
|
572
|
+
transition: options.transition,
|
|
573
|
+
closeOnEscape: options.closeOnEscape,
|
|
574
|
+
onEscapeDismiss(event) {
|
|
575
|
+
event.stopPropagation();
|
|
576
|
+
applyClose();
|
|
110
577
|
}
|
|
578
|
+
});
|
|
579
|
+
const state = layer.input;
|
|
580
|
+
function applyOpen() {
|
|
581
|
+
previousFocus = document.activeElement;
|
|
582
|
+
const opening = layer.open();
|
|
583
|
+
if (!opening) return;
|
|
584
|
+
onOpenChange(true);
|
|
585
|
+
requestAnimationFrame(() => {
|
|
586
|
+
if (layer.signal.aborted || !state.current.active) return;
|
|
587
|
+
element?.focus();
|
|
588
|
+
});
|
|
589
|
+
opening.then(() => {
|
|
590
|
+
if (layer.signal.aborted || !state.current.active) return;
|
|
591
|
+
options.onOpenChangeComplete?.(true);
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
function applyClose() {
|
|
595
|
+
const closing = layer.close(element);
|
|
596
|
+
if (!closing) return;
|
|
597
|
+
onOpenChange(false);
|
|
598
|
+
closing.then(() => {
|
|
599
|
+
if (layer.signal.aborted) return;
|
|
600
|
+
if (previousFocus) {
|
|
601
|
+
previousFocus.focus();
|
|
602
|
+
previousFocus = null;
|
|
603
|
+
}
|
|
604
|
+
options.onOpenChangeComplete?.(false);
|
|
605
|
+
});
|
|
111
606
|
}
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
607
|
+
function setupElementListeners() {
|
|
608
|
+
cleanupElementListeners();
|
|
609
|
+
if (!element) return;
|
|
610
|
+
elementAbort = new AbortController();
|
|
611
|
+
const { signal } = elementAbort;
|
|
612
|
+
listen(element, "click", handleElementClick, { signal });
|
|
613
|
+
}
|
|
614
|
+
function cleanupElementListeners() {
|
|
615
|
+
elementAbort?.abort();
|
|
616
|
+
elementAbort = null;
|
|
617
|
+
}
|
|
618
|
+
function handleElementClick(event) {
|
|
619
|
+
if (event.target instanceof HTMLButtonElement) applyClose();
|
|
620
|
+
}
|
|
621
|
+
function setElement(el) {
|
|
622
|
+
element = el;
|
|
623
|
+
setupElementListeners();
|
|
624
|
+
}
|
|
625
|
+
layer.signal.addEventListener("abort", () => {
|
|
626
|
+
cleanupElementListeners();
|
|
627
|
+
element = null;
|
|
628
|
+
previousFocus = null;
|
|
629
|
+
});
|
|
630
|
+
return {
|
|
631
|
+
input: state,
|
|
632
|
+
open: applyOpen,
|
|
633
|
+
close: applyClose,
|
|
634
|
+
setElement,
|
|
635
|
+
destroy: layer.destroy
|
|
636
|
+
};
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
//#endregion
|
|
640
|
+
//#region ../core/dist/dev/dom/ui/button.js
|
|
641
|
+
function createButton(options) {
|
|
642
|
+
const { onActivate, isDisabled } = options;
|
|
643
|
+
return {
|
|
644
|
+
role: "button",
|
|
645
|
+
tabIndex: 0,
|
|
646
|
+
onClick(event) {
|
|
647
|
+
if (isDisabled()) {
|
|
648
|
+
event.preventDefault();
|
|
649
|
+
return;
|
|
650
|
+
}
|
|
651
|
+
onActivate();
|
|
652
|
+
},
|
|
653
|
+
onPointerDown(event) {
|
|
654
|
+
if (isDisabled()) event.preventDefault();
|
|
655
|
+
},
|
|
656
|
+
onMouseDown(event) {
|
|
657
|
+
if (isDisabled()) event.preventDefault();
|
|
658
|
+
},
|
|
659
|
+
onKeyDown(event) {
|
|
660
|
+
if (event.target !== event.currentTarget) return;
|
|
661
|
+
if (isDisabled()) {
|
|
662
|
+
if (event.key !== "Tab") event.preventDefault();
|
|
663
|
+
return;
|
|
664
|
+
}
|
|
665
|
+
if (event.key === "Enter") {
|
|
666
|
+
event.preventDefault();
|
|
667
|
+
onActivate();
|
|
668
|
+
} else if (event.key === " ") event.preventDefault();
|
|
669
|
+
},
|
|
670
|
+
onKeyUp(event) {
|
|
671
|
+
if (event.target !== event.currentTarget) return;
|
|
672
|
+
if (isDisabled()) return;
|
|
673
|
+
if (event.key === " ") onActivate();
|
|
674
|
+
}
|
|
675
|
+
};
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
//#endregion
|
|
679
|
+
//#region ../core/dist/dev/dom/ui/popover/popover.js
|
|
680
|
+
function createPopover(options) {
|
|
681
|
+
const { onOpenChange, closeOnOutsideClick } = options;
|
|
682
|
+
let triggerEl = null;
|
|
683
|
+
let popupEl = null;
|
|
684
|
+
let hoverTimeout = null;
|
|
685
|
+
const capturedPointers = /* @__PURE__ */ new Set();
|
|
686
|
+
const layer = createDismissLayer({
|
|
687
|
+
transition: options.transition,
|
|
688
|
+
closeOnEscape: options.closeOnEscape,
|
|
689
|
+
onEscapeDismiss(event) {
|
|
690
|
+
event.preventDefault();
|
|
691
|
+
applyClose("escape", event);
|
|
692
|
+
},
|
|
693
|
+
onDocumentActive(signal) {
|
|
694
|
+
listen(document, "pointerdown", handleDocumentPointerdown, {
|
|
695
|
+
capture: true,
|
|
696
|
+
signal
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
const state = layer.input;
|
|
701
|
+
function clearHoverTimeout() {
|
|
702
|
+
if (hoverTimeout !== null) {
|
|
703
|
+
clearTimeout(hoverTimeout);
|
|
704
|
+
hoverTimeout = null;
|
|
116
705
|
}
|
|
117
706
|
}
|
|
118
|
-
|
|
707
|
+
function canHover() {
|
|
708
|
+
return globalThis.matchMedia?.("(hover: hover)")?.matches ?? false;
|
|
709
|
+
}
|
|
710
|
+
function canOpenOnFocus() {
|
|
711
|
+
if (!canHover()) return false;
|
|
712
|
+
return globalThis.matchMedia?.("(pointer: fine)")?.matches ?? false;
|
|
713
|
+
}
|
|
714
|
+
function canToggleOnClick() {
|
|
715
|
+
if (!options.openOnHover?.()) return true;
|
|
716
|
+
return canHover();
|
|
717
|
+
}
|
|
718
|
+
/**
|
|
719
|
+
* The transition handler manages animation lifecycle via `createState`:
|
|
720
|
+
*
|
|
721
|
+
* **Open:** `transition.open()` patches `{ active: true, status: 'starting' }`.
|
|
722
|
+
* After one RAF it patches `{ status: 'idle' }` and the promise resolves.
|
|
723
|
+
* Frameworks render `data-starting-style` / `data-ending-style` via
|
|
724
|
+
* `getPopupAttrs(state)` — no imperative DOM mutation needed.
|
|
725
|
+
*
|
|
726
|
+
* **Close:** `transition.close(el)` patches `{ status: 'ending' }` (keeping
|
|
727
|
+
* `active: true` so the element stays mounted). After a double-RAF it waits
|
|
728
|
+
* for `getAnimations()` to settle, then patches `{ active: false, status: 'idle' }`.
|
|
729
|
+
*
|
|
730
|
+
* `onOpenChange` fires immediately (before animations).
|
|
731
|
+
* `onOpenChangeComplete` fires after animations finish.
|
|
732
|
+
*/
|
|
733
|
+
function applyOpen(reason, event) {
|
|
734
|
+
const opening = layer.open();
|
|
735
|
+
if (!opening) return;
|
|
736
|
+
onOpenChange(true, event ? {
|
|
737
|
+
reason,
|
|
738
|
+
event
|
|
739
|
+
} : { reason });
|
|
740
|
+
opening.then(() => {
|
|
741
|
+
if (layer.signal.aborted || !state.current.active) return;
|
|
742
|
+
options.onOpenChangeComplete?.(true);
|
|
743
|
+
});
|
|
744
|
+
}
|
|
745
|
+
function applyClose(reason, event) {
|
|
746
|
+
const closing = layer.close(popupEl);
|
|
747
|
+
if (!closing) return;
|
|
748
|
+
onOpenChange(false, event ? {
|
|
749
|
+
reason,
|
|
750
|
+
event
|
|
751
|
+
} : { reason });
|
|
752
|
+
closing.then(() => {
|
|
753
|
+
if (layer.signal.aborted) return;
|
|
754
|
+
tryHidePopover(popupEl);
|
|
755
|
+
options.onOpenChangeComplete?.(false);
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
function open(reason = "click") {
|
|
759
|
+
applyOpen(reason);
|
|
760
|
+
}
|
|
761
|
+
function close(reason = "click") {
|
|
762
|
+
applyClose(reason);
|
|
763
|
+
}
|
|
764
|
+
function handleDocumentPointerdown(event) {
|
|
765
|
+
if (!closeOnOutsideClick() || !state.current.active) return;
|
|
766
|
+
const path = event.composedPath();
|
|
767
|
+
if (triggerEl && path.includes(triggerEl) || popupEl && path.includes(popupEl)) return;
|
|
768
|
+
applyClose("outside-click", event);
|
|
769
|
+
}
|
|
770
|
+
layer.signal.addEventListener("abort", () => {
|
|
771
|
+
clearHoverTimeout();
|
|
772
|
+
capturedPointers.clear();
|
|
773
|
+
triggerEl = null;
|
|
774
|
+
popupEl = null;
|
|
775
|
+
});
|
|
776
|
+
const triggerProps = {
|
|
777
|
+
onClick(event) {
|
|
778
|
+
if (!canToggleOnClick()) return;
|
|
779
|
+
if (state.current.active && state.current.status !== "ending") applyClose("click", event);
|
|
780
|
+
else applyOpen("click", event);
|
|
781
|
+
},
|
|
782
|
+
onPointerEnter(_event) {
|
|
783
|
+
if (!options.openOnHover?.()) return;
|
|
784
|
+
if (!canHover()) return;
|
|
785
|
+
clearHoverTimeout();
|
|
786
|
+
if (state.current.active) return;
|
|
787
|
+
const delay = options.delay?.() ?? 300;
|
|
788
|
+
hoverTimeout = setTimeout(() => applyOpen("hover"), delay);
|
|
789
|
+
},
|
|
790
|
+
onPointerLeave(_event) {
|
|
791
|
+
if (!options.openOnHover?.()) return;
|
|
792
|
+
if (!canHover()) return;
|
|
793
|
+
clearHoverTimeout();
|
|
794
|
+
if (!state.current.active) return;
|
|
795
|
+
const closeDelay = options.closeDelay?.() ?? 0;
|
|
796
|
+
hoverTimeout = setTimeout(() => applyClose("hover"), closeDelay);
|
|
797
|
+
},
|
|
798
|
+
onFocusIn(_event) {
|
|
799
|
+
if (options.openOnHover?.()) {
|
|
800
|
+
if (!canOpenOnFocus()) return;
|
|
801
|
+
applyOpen("focus");
|
|
802
|
+
}
|
|
803
|
+
},
|
|
804
|
+
onFocusOut(event) {
|
|
805
|
+
const relatedTarget = event.relatedTarget;
|
|
806
|
+
if (relatedTarget && (triggerEl?.contains(relatedTarget) || popupEl?.contains(relatedTarget))) return;
|
|
807
|
+
if (options.openOnHover?.()) applyClose("blur");
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
const popupProps = {
|
|
811
|
+
onPointerEnter(_event) {
|
|
812
|
+
if (!options.openOnHover?.()) return;
|
|
813
|
+
clearHoverTimeout();
|
|
814
|
+
},
|
|
815
|
+
onPointerLeave(_event) {
|
|
816
|
+
if (!options.openOnHover?.()) return;
|
|
817
|
+
if (capturedPointers.size > 0) return;
|
|
818
|
+
clearHoverTimeout();
|
|
819
|
+
if (!state.current.active) return;
|
|
820
|
+
const closeDelay = options.closeDelay?.() ?? 0;
|
|
821
|
+
hoverTimeout = setTimeout(() => applyClose("hover"), closeDelay);
|
|
822
|
+
},
|
|
823
|
+
onGotPointerCapture(event) {
|
|
824
|
+
capturedPointers.add(event.pointerId);
|
|
825
|
+
},
|
|
826
|
+
onLostPointerCapture(event) {
|
|
827
|
+
capturedPointers.delete(event.pointerId);
|
|
828
|
+
},
|
|
829
|
+
onFocusOut(event) {
|
|
830
|
+
const relatedTarget = event.relatedTarget;
|
|
831
|
+
if (relatedTarget && (triggerEl?.contains(relatedTarget) || popupEl?.contains(relatedTarget))) return;
|
|
832
|
+
applyClose("blur");
|
|
833
|
+
}
|
|
834
|
+
};
|
|
835
|
+
function setTriggerElement(el) {
|
|
836
|
+
triggerEl = el;
|
|
837
|
+
}
|
|
838
|
+
function setPopupElement(el) {
|
|
839
|
+
if (!el && popupEl && state.current.active) tryHidePopover(popupEl);
|
|
840
|
+
popupEl = el;
|
|
841
|
+
if (el) {
|
|
842
|
+
if (state.current.active) tryShowPopover(el);
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
return {
|
|
846
|
+
input: state,
|
|
847
|
+
triggerProps,
|
|
848
|
+
popupProps,
|
|
849
|
+
get triggerElement() {
|
|
850
|
+
return triggerEl;
|
|
851
|
+
},
|
|
852
|
+
setTriggerElement,
|
|
853
|
+
setPopupElement,
|
|
854
|
+
open,
|
|
855
|
+
close,
|
|
856
|
+
destroy: layer.destroy
|
|
857
|
+
};
|
|
858
|
+
}
|
|
119
859
|
|
|
120
860
|
//#endregion
|
|
121
|
-
//#region ../core/dist/dev/core/ui/
|
|
122
|
-
const
|
|
861
|
+
//#region ../core/dist/dev/core/ui/popover/popover-css-vars.js
|
|
862
|
+
const PopoverCSSVars = {
|
|
863
|
+
sideOffset: "--media-popover-side-offset",
|
|
864
|
+
alignOffset: "--media-popover-align-offset",
|
|
865
|
+
anchorWidth: "--media-popover-anchor-width",
|
|
866
|
+
anchorHeight: "--media-popover-anchor-height",
|
|
867
|
+
availableWidth: "--media-popover-available-width",
|
|
868
|
+
availableHeight: "--media-popover-available-height"
|
|
869
|
+
};
|
|
123
870
|
|
|
124
871
|
//#endregion
|
|
125
|
-
//#region ../core/dist/dev/
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
872
|
+
//#region ../core/dist/dev/dom/ui/popover/popover-positioning.js
|
|
873
|
+
const OPPOSITE_SIDE = {
|
|
874
|
+
top: "bottom",
|
|
875
|
+
bottom: "top",
|
|
876
|
+
left: "right",
|
|
877
|
+
right: "left"
|
|
878
|
+
};
|
|
879
|
+
/**
|
|
880
|
+
* Get positioning styles for the popup element.
|
|
881
|
+
*
|
|
882
|
+
* When the browser supports CSS Anchor Positioning, returns native CSS properties
|
|
883
|
+
* that reference the provided CSS var names for side/align offsets — no JS offset
|
|
884
|
+
* values needed.
|
|
885
|
+
*
|
|
886
|
+
* When rects are provided and anchor positioning is unsupported, falls back to
|
|
887
|
+
* manual JS-computed positioning. The caller must resolve offset CSS vars via
|
|
888
|
+
* `getComputedStyle` and pass them as `offsets`.
|
|
889
|
+
*
|
|
890
|
+
* Returns camelCase keys for standard CSS properties and `--*` keys for
|
|
891
|
+
* custom properties — compatible with both React's `style` prop and
|
|
892
|
+
* `applyStyles()` from `@videojs/utils/dom`.
|
|
893
|
+
*/
|
|
894
|
+
function getAnchorPositionStyle(anchorName, opts, triggerRect, popupRect, boundaryRect, offsets, cssVars = PopoverCSSVars) {
|
|
895
|
+
if (supportsAnchorPositioning()) return getAnchorPositionCSS(anchorName, opts, cssVars);
|
|
896
|
+
if (triggerRect && popupRect) return {
|
|
897
|
+
...getManualPositionStyle(triggerRect, popupRect, opts, offsets ?? {
|
|
898
|
+
sideOffset: 0,
|
|
899
|
+
alignOffset: 0
|
|
900
|
+
}),
|
|
901
|
+
...boundaryRect ? getPositioningCSSVars(triggerRect, boundaryRect, opts.side, cssVars) : {},
|
|
902
|
+
position: "fixed",
|
|
903
|
+
inset: "auto",
|
|
904
|
+
margin: "0"
|
|
130
905
|
};
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
906
|
+
return {};
|
|
907
|
+
}
|
|
908
|
+
/** Generate style to set on the trigger for CSS Anchor Positioning. */
|
|
909
|
+
function getAnchorNameStyle(anchorName) {
|
|
910
|
+
if (!supportsAnchorPositioning()) return {};
|
|
911
|
+
return { anchorName: `--${anchorName}` };
|
|
912
|
+
}
|
|
913
|
+
function getAnchorPositionCSS(anchorName, opts, cssVars = PopoverCSSVars) {
|
|
914
|
+
const SIDE_OFFSET_VAR = `var(${cssVars.sideOffset}, 0px)`;
|
|
915
|
+
const ALIGN_OFFSET_VAR = `var(${cssVars.alignOffset}, 0px)`;
|
|
916
|
+
const { side, align } = opts;
|
|
917
|
+
const style = {
|
|
918
|
+
positionAnchor: `--${anchorName}`,
|
|
919
|
+
position: "fixed",
|
|
920
|
+
inset: "auto",
|
|
921
|
+
margin: "0",
|
|
922
|
+
justifySelf: "normal",
|
|
923
|
+
alignSelf: "normal",
|
|
924
|
+
marginInlineStart: "0",
|
|
925
|
+
marginBlockStart: "0"
|
|
926
|
+
};
|
|
927
|
+
const insetProp = OPPOSITE_SIDE[side];
|
|
928
|
+
if (side === "top" || side === "bottom") {
|
|
929
|
+
style[insetProp] = `calc(anchor(${side}) + ${SIDE_OFFSET_VAR})`;
|
|
930
|
+
if (align === "start") style.left = `calc(anchor(left) + ${ALIGN_OFFSET_VAR})`;
|
|
931
|
+
else if (align === "end") style.right = `calc(anchor(right) + ${ALIGN_OFFSET_VAR})`;
|
|
932
|
+
else {
|
|
933
|
+
style.justifySelf = "anchor-center";
|
|
934
|
+
style.marginInlineStart = ALIGN_OFFSET_VAR;
|
|
935
|
+
}
|
|
936
|
+
} else {
|
|
937
|
+
style[insetProp] = `calc(anchor(${side}) + ${SIDE_OFFSET_VAR})`;
|
|
938
|
+
if (align === "start") style.top = `calc(anchor(top) + ${ALIGN_OFFSET_VAR})`;
|
|
939
|
+
else if (align === "end") style.bottom = `calc(anchor(bottom) + ${ALIGN_OFFSET_VAR})`;
|
|
940
|
+
else {
|
|
941
|
+
style.alignSelf = "anchor-center";
|
|
942
|
+
style.marginBlockStart = ALIGN_OFFSET_VAR;
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
return style;
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Compute CSS variables for sizing constraints relative to the anchor/boundary.
|
|
949
|
+
*
|
|
950
|
+
* Accepts a `cssVars` map so the same logic works for both popover
|
|
951
|
+
* (`--media-popover-*`) and tooltip (`--media-tooltip-*`) namespaces.
|
|
952
|
+
*/
|
|
953
|
+
function getPositioningCSSVars(triggerRect, boundaryRect, side, cssVars = PopoverCSSVars) {
|
|
954
|
+
const vars = {};
|
|
955
|
+
vars[cssVars.anchorWidth] = `${triggerRect.width}px`;
|
|
956
|
+
vars[cssVars.anchorHeight] = `${triggerRect.height}px`;
|
|
957
|
+
if (side === "top" || side === "bottom") {
|
|
958
|
+
vars[cssVars.availableHeight] = side === "top" ? `${triggerRect.top - boundaryRect.top}px` : `${boundaryRect.bottom - triggerRect.bottom}px`;
|
|
959
|
+
vars[cssVars.availableWidth] = `${boundaryRect.width}px`;
|
|
960
|
+
} else {
|
|
961
|
+
vars[cssVars.availableWidth] = side === "left" ? `${triggerRect.left - boundaryRect.left}px` : `${boundaryRect.right - triggerRect.right}px`;
|
|
962
|
+
vars[cssVars.availableHeight] = `${boundaryRect.height}px`;
|
|
963
|
+
}
|
|
964
|
+
return vars;
|
|
965
|
+
}
|
|
966
|
+
/**
|
|
967
|
+
* Compute manual positioning when CSS Anchor Positioning is not supported.
|
|
968
|
+
*
|
|
969
|
+
* Returns inline `top`/`left` styles in **viewport coordinates** for use
|
|
970
|
+
* with `position: fixed` (the popup is in the top layer). All rects from
|
|
971
|
+
* `getBoundingClientRect()` are already viewport-relative.
|
|
972
|
+
*
|
|
973
|
+
* Offsets are resolved by the caller from CSS custom properties via
|
|
974
|
+
* `getComputedStyle()` and passed as `offsets`.
|
|
975
|
+
*/
|
|
976
|
+
function getManualPositionStyle(triggerRect, popupRect, opts, offsets = {
|
|
977
|
+
sideOffset: 0,
|
|
978
|
+
alignOffset: 0
|
|
979
|
+
}) {
|
|
980
|
+
const { side, align } = opts;
|
|
981
|
+
const { sideOffset, alignOffset } = offsets;
|
|
982
|
+
let top = 0;
|
|
983
|
+
let left = 0;
|
|
984
|
+
if (side === "top") top = triggerRect.top - popupRect.height - sideOffset;
|
|
985
|
+
else if (side === "bottom") top = triggerRect.bottom + sideOffset;
|
|
986
|
+
else if (side === "left") left = triggerRect.left - popupRect.width - sideOffset;
|
|
987
|
+
else left = triggerRect.right + sideOffset;
|
|
988
|
+
if (side === "top" || side === "bottom") if (align === "start") left = triggerRect.left + alignOffset;
|
|
989
|
+
else if (align === "end") left = triggerRect.right - popupRect.width + alignOffset;
|
|
990
|
+
else left = triggerRect.left + (triggerRect.width - popupRect.width) / 2 + alignOffset;
|
|
991
|
+
else if (align === "start") top = triggerRect.top + alignOffset;
|
|
992
|
+
else if (align === "end") top = triggerRect.bottom - popupRect.height + alignOffset;
|
|
993
|
+
else top = triggerRect.top + (triggerRect.height - popupRect.height) / 2 + alignOffset;
|
|
994
|
+
return {
|
|
995
|
+
top: `${top}px`,
|
|
996
|
+
left: `${left}px`
|
|
997
|
+
};
|
|
998
|
+
}
|
|
999
|
+
/**
|
|
1000
|
+
* Read side-offset and align-offset CSS custom properties from the
|
|
1001
|
+
* popup element's computed style, returning numeric pixel values.
|
|
1002
|
+
*/
|
|
1003
|
+
function resolveOffsets(el, cssVars = PopoverCSSVars) {
|
|
1004
|
+
const computed = getComputedStyle(el);
|
|
1005
|
+
return {
|
|
1006
|
+
sideOffset: resolveCSSLength(el, computed.getPropertyValue(cssVars.sideOffset)),
|
|
1007
|
+
alignOffset: resolveCSSLength(el, computed.getPropertyValue(cssVars.alignOffset))
|
|
1008
|
+
};
|
|
1009
|
+
}
|
|
1010
|
+
/**
|
|
1011
|
+
* Measure the popup's layout box for positioning.
|
|
1012
|
+
*
|
|
1013
|
+
* `getBoundingClientRect()` includes active transforms, which causes the
|
|
1014
|
+
* fallback position to drift while opening/closing animations scale the popup.
|
|
1015
|
+
* Using `offsetWidth`/`offsetHeight` preserves the untransformed size.
|
|
1016
|
+
*/
|
|
1017
|
+
function getPopupPositionRect(el) {
|
|
1018
|
+
const rect = el.getBoundingClientRect();
|
|
1019
|
+
const width = el.offsetWidth || rect.width;
|
|
1020
|
+
const height = el.offsetHeight || rect.height;
|
|
1021
|
+
const adjustedRect = {
|
|
1022
|
+
...rect,
|
|
1023
|
+
width,
|
|
1024
|
+
height,
|
|
1025
|
+
right: rect.left + width,
|
|
1026
|
+
bottom: rect.top + height
|
|
1027
|
+
};
|
|
1028
|
+
return {
|
|
1029
|
+
...adjustedRect,
|
|
1030
|
+
toJSON: () => adjustedRect
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
//#endregion
|
|
1035
|
+
//#region ../utils/dist/number/number.js
|
|
1036
|
+
/** Clamp a value between min and max (inclusive). */
|
|
1037
|
+
function clamp(value, min, max) {
|
|
1038
|
+
return Math.max(min, Math.min(max, value));
|
|
1039
|
+
}
|
|
1040
|
+
/** Snap a value to the nearest step, offset from min. */
|
|
1041
|
+
function roundToStep(value, step, min) {
|
|
1042
|
+
const nearest = Math.round((value - min) / step) * step + min;
|
|
1043
|
+
const dot = `${step}`.indexOf(".");
|
|
1044
|
+
return dot === -1 ? nearest : Number(nearest.toFixed(`${step}`.length - dot - 1));
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
//#endregion
|
|
1048
|
+
//#region ../core/dist/dev/dom/utils/pointer.js
|
|
1049
|
+
/** Convert a pointer event position to a 0–100 percent along an element's rect. */
|
|
1050
|
+
function getPercentFromPointerEvent(event, rect, orientation, isRTL) {
|
|
1051
|
+
let ratio;
|
|
1052
|
+
if (orientation === "vertical") ratio = 1 - (event.clientY - rect.top) / rect.height;
|
|
1053
|
+
else if (isRTL) ratio = (rect.right - event.clientX) / rect.width;
|
|
1054
|
+
else ratio = (event.clientX - rect.left) / rect.width;
|
|
1055
|
+
if (!Number.isFinite(ratio)) return 0;
|
|
1056
|
+
return clamp(ratio * 100, 0, 100);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
//#endregion
|
|
1060
|
+
//#region ../core/dist/dev/dom/ui/slider.js
|
|
1061
|
+
function createSlider(options) {
|
|
1062
|
+
const input = createState({
|
|
1063
|
+
pointerPercent: 0,
|
|
1064
|
+
dragPercent: 0,
|
|
1065
|
+
dragging: false,
|
|
1066
|
+
pointing: false,
|
|
1067
|
+
focused: false
|
|
135
1068
|
});
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
1069
|
+
const abort = new AbortController();
|
|
1070
|
+
const changeThrottleMs = options.changeThrottle ?? 0;
|
|
1071
|
+
let isDragging = false, cachedRTL = false, cachedRect = null, capturedPointerId = null, lastDragPercent = 0, committedOnRelease = false;
|
|
1072
|
+
const throttledChange = changeThrottleMs > 0 ? throttle((percent) => options.onValueChange?.(percent), changeThrottleMs, { leading: true }) : null;
|
|
1073
|
+
/** Fire `onValueChange` — throttled during drag when `changeThrottle > 0`. */
|
|
1074
|
+
function fireChange(percent, duringDrag) {
|
|
1075
|
+
if (duringDrag && throttledChange) throttledChange(percent);
|
|
1076
|
+
else options.onValueChange?.(percent);
|
|
1077
|
+
}
|
|
1078
|
+
function releaseCapture() {
|
|
1079
|
+
if (isNull(capturedPointerId)) return;
|
|
1080
|
+
const id = capturedPointerId;
|
|
1081
|
+
capturedPointerId = null;
|
|
1082
|
+
try {
|
|
1083
|
+
options.getElement().releasePointerCapture(id);
|
|
1084
|
+
} catch {}
|
|
140
1085
|
}
|
|
141
|
-
|
|
142
|
-
|
|
1086
|
+
function endDrag() {
|
|
1087
|
+
if (!isDragging) input.patch({ pointing: false });
|
|
1088
|
+
else {
|
|
1089
|
+
if (!committedOnRelease) options.onValueCommit?.(lastDragPercent);
|
|
1090
|
+
isDragging = false;
|
|
1091
|
+
input.patch({
|
|
1092
|
+
dragging: false,
|
|
1093
|
+
pointing: false
|
|
1094
|
+
});
|
|
1095
|
+
options.onDragEnd?.();
|
|
1096
|
+
}
|
|
1097
|
+
committedOnRelease = false;
|
|
1098
|
+
cleanup();
|
|
1099
|
+
}
|
|
1100
|
+
function cleanup() {
|
|
1101
|
+
throttledChange?.cancel();
|
|
1102
|
+
capturedPointerId = null;
|
|
1103
|
+
cachedRect = null;
|
|
1104
|
+
}
|
|
1105
|
+
const rootProps = {
|
|
1106
|
+
onPointerDown(event) {
|
|
1107
|
+
if (options.isDisabled()) return;
|
|
1108
|
+
event.preventDefault();
|
|
1109
|
+
const el = options.getElement();
|
|
1110
|
+
cachedRect = el.getBoundingClientRect();
|
|
1111
|
+
cachedRTL = options.isRTL();
|
|
1112
|
+
committedOnRelease = false;
|
|
1113
|
+
releaseCapture();
|
|
1114
|
+
capturedPointerId = event.pointerId;
|
|
1115
|
+
el.setPointerCapture(event.pointerId);
|
|
1116
|
+
const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
|
|
1117
|
+
isDragging = true;
|
|
1118
|
+
lastDragPercent = percent;
|
|
1119
|
+
input.patch({
|
|
1120
|
+
pointing: true,
|
|
1121
|
+
dragging: true,
|
|
1122
|
+
pointerPercent: percent,
|
|
1123
|
+
dragPercent: percent
|
|
1124
|
+
});
|
|
1125
|
+
options.onDragStart?.();
|
|
1126
|
+
options.onValueChange?.(percent);
|
|
1127
|
+
options.getThumbElement?.()?.focus({
|
|
1128
|
+
preventScroll: true,
|
|
1129
|
+
focusVisible: false
|
|
1130
|
+
});
|
|
1131
|
+
},
|
|
1132
|
+
onPointerMove(event) {
|
|
1133
|
+
if (options.isDisabled()) return;
|
|
1134
|
+
if (!isNull(capturedPointerId)) {
|
|
1135
|
+
if (event.pointerType !== "touch" && event.buttons === 0) {
|
|
1136
|
+
endDrag();
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
|
|
1140
|
+
lastDragPercent = percent;
|
|
1141
|
+
input.patch({
|
|
1142
|
+
dragPercent: percent,
|
|
1143
|
+
pointerPercent: percent
|
|
1144
|
+
});
|
|
1145
|
+
fireChange(percent, true);
|
|
1146
|
+
return;
|
|
1147
|
+
}
|
|
1148
|
+
const percent = getPercentFromPointerEvent(event, options.getElement().getBoundingClientRect(), options.getOrientation(), options.isRTL());
|
|
1149
|
+
input.patch({
|
|
1150
|
+
pointing: true,
|
|
1151
|
+
pointerPercent: percent
|
|
1152
|
+
});
|
|
1153
|
+
},
|
|
1154
|
+
onPointerUp(event) {
|
|
1155
|
+
if (isNull(capturedPointerId)) return;
|
|
1156
|
+
const percent = getPercentFromPointerEvent(event, cachedRect, options.getOrientation(), cachedRTL);
|
|
1157
|
+
throttledChange?.cancel();
|
|
1158
|
+
options.onValueChange?.(percent);
|
|
1159
|
+
options.onValueCommit?.(percent);
|
|
1160
|
+
committedOnRelease = true;
|
|
1161
|
+
},
|
|
1162
|
+
onPointerLeave() {
|
|
1163
|
+
if (!isNull(capturedPointerId)) return;
|
|
1164
|
+
input.patch({ pointing: false });
|
|
1165
|
+
},
|
|
1166
|
+
onLostPointerCapture() {
|
|
1167
|
+
endDrag();
|
|
1168
|
+
}
|
|
1169
|
+
};
|
|
1170
|
+
const thumbProps = {
|
|
1171
|
+
onKeyDown(event) {
|
|
1172
|
+
if (options.isDisabled()) {
|
|
1173
|
+
if (event.key !== "Tab") event.preventDefault();
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
const stepPercent = options.getStepPercent();
|
|
1177
|
+
const largeStepPercent = options.getLargeStepPercent();
|
|
1178
|
+
const rounded = roundToStep(options.getPercent(), stepPercent, 0);
|
|
1179
|
+
const horizontalSign = options.isRTL() ? -1 : 1;
|
|
1180
|
+
const step = event.shiftKey ? largeStepPercent : stepPercent;
|
|
1181
|
+
let newPercent = null;
|
|
1182
|
+
switch (event.key) {
|
|
1183
|
+
case "ArrowRight":
|
|
1184
|
+
newPercent = rounded + step * horizontalSign;
|
|
1185
|
+
break;
|
|
1186
|
+
case "ArrowLeft":
|
|
1187
|
+
newPercent = rounded - step * horizontalSign;
|
|
1188
|
+
break;
|
|
1189
|
+
case "ArrowUp":
|
|
1190
|
+
newPercent = rounded + step;
|
|
1191
|
+
break;
|
|
1192
|
+
case "ArrowDown":
|
|
1193
|
+
newPercent = rounded - step;
|
|
1194
|
+
break;
|
|
1195
|
+
case "PageUp":
|
|
1196
|
+
newPercent = rounded + largeStepPercent;
|
|
1197
|
+
break;
|
|
1198
|
+
case "PageDown":
|
|
1199
|
+
newPercent = rounded - largeStepPercent;
|
|
1200
|
+
break;
|
|
1201
|
+
case "Home":
|
|
1202
|
+
newPercent = 0;
|
|
1203
|
+
break;
|
|
1204
|
+
case "End":
|
|
1205
|
+
newPercent = 100;
|
|
1206
|
+
break;
|
|
1207
|
+
default:
|
|
1208
|
+
if (!event.metaKey && !event.ctrlKey && !event.altKey && event.key >= "0" && event.key <= "9") newPercent = Number(event.key) * 10;
|
|
1209
|
+
break;
|
|
1210
|
+
}
|
|
1211
|
+
if (newPercent !== null) {
|
|
1212
|
+
event.preventDefault();
|
|
1213
|
+
newPercent = clamp(newPercent, 0, 100);
|
|
1214
|
+
input.patch({
|
|
1215
|
+
pointerPercent: newPercent,
|
|
1216
|
+
dragPercent: newPercent
|
|
1217
|
+
});
|
|
1218
|
+
options.onValueChange?.(newPercent);
|
|
1219
|
+
options.onValueCommit?.(newPercent);
|
|
1220
|
+
}
|
|
1221
|
+
},
|
|
1222
|
+
onFocus() {
|
|
1223
|
+
input.patch({ focused: true });
|
|
1224
|
+
},
|
|
1225
|
+
onBlur() {
|
|
1226
|
+
input.patch({ focused: false });
|
|
1227
|
+
}
|
|
1228
|
+
};
|
|
1229
|
+
function adjustForAlignment(state) {
|
|
1230
|
+
if (!options.adjustPercent || state.thumbAlignment !== "edge") return state;
|
|
1231
|
+
const rootEl = options.getElement();
|
|
1232
|
+
const thumbEl = options.getThumbElement?.();
|
|
1233
|
+
if (!thumbEl) return state;
|
|
1234
|
+
const isHorizontal = state.orientation === "horizontal";
|
|
1235
|
+
const thumbSize = isHorizontal ? thumbEl.offsetWidth : thumbEl.offsetHeight;
|
|
1236
|
+
const trackSize = isHorizontal ? rootEl.offsetWidth : rootEl.offsetHeight;
|
|
1237
|
+
return {
|
|
1238
|
+
...state,
|
|
1239
|
+
fillPercent: options.adjustPercent(state.fillPercent, thumbSize, trackSize),
|
|
1240
|
+
pointerPercent: options.adjustPercent(state.pointerPercent, thumbSize, trackSize)
|
|
1241
|
+
};
|
|
143
1242
|
}
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
if (customLabel) return customLabel;
|
|
149
|
-
} else if (label) return label;
|
|
150
|
-
return state.subtitlesShowing ? "Disable captions" : "Enable captions";
|
|
1243
|
+
let resizeObserver = null;
|
|
1244
|
+
if (options.onResize) {
|
|
1245
|
+
resizeObserver = new ResizeObserver(() => options.onResize());
|
|
1246
|
+
resizeObserver.observe(options.getElement());
|
|
151
1247
|
}
|
|
152
|
-
|
|
1248
|
+
return {
|
|
1249
|
+
input,
|
|
1250
|
+
rootProps,
|
|
1251
|
+
rootStyle: {
|
|
1252
|
+
touchAction: "none",
|
|
1253
|
+
userSelect: "none"
|
|
1254
|
+
},
|
|
1255
|
+
thumbProps,
|
|
1256
|
+
adjustForAlignment,
|
|
1257
|
+
destroy() {
|
|
1258
|
+
if (abort.signal.aborted) return;
|
|
1259
|
+
abort.abort();
|
|
1260
|
+
resizeObserver?.disconnect();
|
|
1261
|
+
releaseCapture();
|
|
1262
|
+
cleanup();
|
|
1263
|
+
}
|
|
1264
|
+
};
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
//#endregion
|
|
1268
|
+
//#region ../core/dist/dev/core/ui/slider/slider-css-vars.js
|
|
1269
|
+
/** CSS custom property names for slider visual state. */
|
|
1270
|
+
const SliderCSSVars = {
|
|
1271
|
+
fill: "--media-slider-fill",
|
|
1272
|
+
pointer: "--media-slider-pointer",
|
|
1273
|
+
buffer: "--media-slider-buffer"
|
|
1274
|
+
};
|
|
1275
|
+
|
|
1276
|
+
//#endregion
|
|
1277
|
+
//#region ../core/dist/dev/dom/ui/slider-css-vars.js
|
|
1278
|
+
function getSliderCSSVars(state) {
|
|
1279
|
+
return {
|
|
1280
|
+
[SliderCSSVars.fill]: `${state.fillPercent.toFixed(3)}%`,
|
|
1281
|
+
[SliderCSSVars.pointer]: `${state.pointerPercent.toFixed(3)}%`
|
|
1282
|
+
};
|
|
1283
|
+
}
|
|
1284
|
+
function getTimeSliderCSSVars(state) {
|
|
1285
|
+
return {
|
|
1286
|
+
...getSliderCSSVars(state),
|
|
1287
|
+
[SliderCSSVars.buffer]: `${state.bufferPercent.toFixed(3)}%`
|
|
1288
|
+
};
|
|
1289
|
+
}
|
|
1290
|
+
/** Compute structural positioning styles for a slider preview element. */
|
|
1291
|
+
function getSliderPreviewStyle(width, overflow) {
|
|
1292
|
+
const halfWidth = width / 2;
|
|
1293
|
+
return {
|
|
1294
|
+
position: "absolute",
|
|
1295
|
+
left: overflow === "visible" ? `calc(var(${SliderCSSVars.pointer}) - ${halfWidth}px)` : `min(max(0px, calc(var(${SliderCSSVars.pointer}) - ${halfWidth}px)), calc(100% - ${width}px))`,
|
|
1296
|
+
width: "max-content",
|
|
1297
|
+
pointerEvents: "none"
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
|
|
1301
|
+
//#endregion
|
|
1302
|
+
//#region ../core/dist/dev/core/ui/thumbnail/thumbnail-core.js
|
|
1303
|
+
var ThumbnailCore = class {
|
|
1304
|
+
findActiveThumbnail(thumbnails, time) {
|
|
1305
|
+
if (thumbnails.length === 0) return void 0;
|
|
1306
|
+
let low = 0;
|
|
1307
|
+
let high = thumbnails.length - 1;
|
|
1308
|
+
let result;
|
|
1309
|
+
while (low <= high) {
|
|
1310
|
+
const mid = low + high >>> 1;
|
|
1311
|
+
const image = thumbnails[mid];
|
|
1312
|
+
if (time >= image.startTime) {
|
|
1313
|
+
result = image;
|
|
1314
|
+
low = mid + 1;
|
|
1315
|
+
} else high = mid - 1;
|
|
1316
|
+
}
|
|
1317
|
+
return result;
|
|
1318
|
+
}
|
|
1319
|
+
/**
|
|
1320
|
+
* Parse CSS constraint strings into numeric `ThumbnailConstraints`.
|
|
1321
|
+
*
|
|
1322
|
+
* Accepts any object with string `minWidth`/`maxWidth`/`minHeight`/`maxHeight`
|
|
1323
|
+
* properties — `CSSStyleDeclaration` satisfies this structurally.
|
|
1324
|
+
*/
|
|
1325
|
+
parseConstraints(raw) {
|
|
1326
|
+
const minW = parseFloat(raw.minWidth);
|
|
1327
|
+
const maxW = parseFloat(raw.maxWidth);
|
|
1328
|
+
const minH = parseFloat(raw.minHeight);
|
|
1329
|
+
const maxH = parseFloat(raw.maxHeight);
|
|
153
1330
|
return {
|
|
154
|
-
|
|
155
|
-
|
|
1331
|
+
minWidth: Number.isFinite(minW) ? minW : 0,
|
|
1332
|
+
maxWidth: Number.isFinite(maxW) ? maxW : Infinity,
|
|
1333
|
+
minHeight: Number.isFinite(minH) ? minH : 0,
|
|
1334
|
+
maxHeight: Number.isFinite(maxH) ? maxH : Infinity
|
|
156
1335
|
};
|
|
157
1336
|
}
|
|
158
|
-
|
|
159
|
-
|
|
1337
|
+
/**
|
|
1338
|
+
* Calculate a uniform scale factor that fits `tileWidth × tileHeight` within the
|
|
1339
|
+
* given CSS min/max constraints while preserving aspect ratio.
|
|
1340
|
+
*
|
|
1341
|
+
* - Scales down when the tile exceeds max constraints.
|
|
1342
|
+
* - Scales up when the tile is smaller than min constraints.
|
|
1343
|
+
* - Returns `1` when no scaling is needed.
|
|
1344
|
+
*/
|
|
1345
|
+
calculateScale(tileWidth, tileHeight, constraints) {
|
|
1346
|
+
const { minWidth, maxWidth, minHeight, maxHeight } = constraints;
|
|
1347
|
+
const maxRatio = Math.min(maxWidth / tileWidth, maxHeight / tileHeight);
|
|
1348
|
+
const minRatio = Math.max(minWidth / tileWidth, minHeight / tileHeight);
|
|
1349
|
+
if (Number.isFinite(maxRatio) && maxRatio < 1) return maxRatio;
|
|
1350
|
+
if (Number.isFinite(minRatio) && minRatio > 1) return minRatio;
|
|
1351
|
+
return 1;
|
|
160
1352
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
1353
|
+
/**
|
|
1354
|
+
* Compute container and image dimensions for the current thumbnail, scaled to
|
|
1355
|
+
* fit within the element's CSS min/max constraints.
|
|
1356
|
+
*
|
|
1357
|
+
* The container clips the sprite sheet via `overflow: hidden`, and the image is
|
|
1358
|
+
* positioned with `transform: translate()` to show the correct tile.
|
|
1359
|
+
*/
|
|
1360
|
+
resize(thumbnail, imgNaturalWidth, imgNaturalHeight, constraints) {
|
|
1361
|
+
const tileWidth = thumbnail.width ?? imgNaturalWidth;
|
|
1362
|
+
const tileHeight = thumbnail.height ?? imgNaturalHeight;
|
|
1363
|
+
if (!tileWidth || !tileHeight) return void 0;
|
|
1364
|
+
const scale = this.calculateScale(tileWidth, tileHeight, constraints);
|
|
1365
|
+
const coordX = thumbnail.coords?.x ?? 0;
|
|
1366
|
+
const coordY = thumbnail.coords?.y ?? 0;
|
|
1367
|
+
const inset = scale !== 1 ? 1 : 0;
|
|
1368
|
+
return {
|
|
1369
|
+
scale,
|
|
1370
|
+
containerWidth: Math.max(0, Math.floor(tileWidth * scale) - inset * 2),
|
|
1371
|
+
containerHeight: Math.max(0, Math.floor(tileHeight * scale) - inset * 2),
|
|
1372
|
+
imageWidth: Math.ceil(imgNaturalWidth * scale),
|
|
1373
|
+
imageHeight: Math.ceil(imgNaturalHeight * scale),
|
|
1374
|
+
offsetX: Math.ceil(coordX * scale) + inset,
|
|
1375
|
+
offsetY: Math.ceil(coordY * scale) + inset
|
|
1376
|
+
};
|
|
170
1377
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
1378
|
+
getState(loading, error, thumbnail) {
|
|
1379
|
+
return {
|
|
1380
|
+
loading,
|
|
1381
|
+
error,
|
|
1382
|
+
hidden: !loading && !thumbnail
|
|
1383
|
+
};
|
|
1384
|
+
}
|
|
1385
|
+
getAttrs(_state) {
|
|
1386
|
+
return {
|
|
1387
|
+
role: "img",
|
|
1388
|
+
"aria-hidden": "true"
|
|
1389
|
+
};
|
|
174
1390
|
}
|
|
175
1391
|
};
|
|
176
1392
|
|
|
177
1393
|
//#endregion
|
|
178
|
-
//#region ../core/dist/dev/
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
1394
|
+
//#region ../core/dist/dev/dom/ui/thumbnail.js
|
|
1395
|
+
function createThumbnail(options) {
|
|
1396
|
+
const { getContainer, getImg, onStateChange } = options;
|
|
1397
|
+
const core = new ThumbnailCore();
|
|
1398
|
+
const abort = new AbortController();
|
|
1399
|
+
const signal = abort.signal;
|
|
1400
|
+
let loading = false;
|
|
1401
|
+
let error = false;
|
|
1402
|
+
let naturalWidth = 0;
|
|
1403
|
+
let naturalHeight = 0;
|
|
1404
|
+
let lastSrc = "";
|
|
1405
|
+
let imgBound = false;
|
|
1406
|
+
let resizeObserver = null;
|
|
1407
|
+
function onImgLoad() {
|
|
1408
|
+
const img = getImg();
|
|
1409
|
+
if (img) {
|
|
1410
|
+
naturalWidth = img.naturalWidth;
|
|
1411
|
+
naturalHeight = img.naturalHeight;
|
|
1412
|
+
}
|
|
1413
|
+
loading = false;
|
|
1414
|
+
error = false;
|
|
1415
|
+
onStateChange();
|
|
1416
|
+
}
|
|
1417
|
+
function onImgError() {
|
|
1418
|
+
loading = false;
|
|
1419
|
+
error = true;
|
|
1420
|
+
onStateChange();
|
|
1421
|
+
}
|
|
1422
|
+
function bindImg(img) {
|
|
1423
|
+
listen(img, "load", onImgLoad, { signal });
|
|
1424
|
+
listen(img, "error", onImgError, { signal });
|
|
1425
|
+
}
|
|
1426
|
+
function ensureBindings() {
|
|
1427
|
+
if (!imgBound) {
|
|
1428
|
+
const img = getImg();
|
|
1429
|
+
if (img) {
|
|
1430
|
+
bindImg(img);
|
|
1431
|
+
imgBound = true;
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
if (!resizeObserver) {
|
|
1435
|
+
const container = getContainer();
|
|
1436
|
+
if (container) {
|
|
1437
|
+
resizeObserver = new ResizeObserver(onStateChange);
|
|
1438
|
+
resizeObserver.observe(container);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
}
|
|
1442
|
+
function updateSrc(url) {
|
|
1443
|
+
ensureBindings();
|
|
1444
|
+
const src = url ?? "";
|
|
1445
|
+
if (src === lastSrc) return;
|
|
1446
|
+
lastSrc = src;
|
|
1447
|
+
if (src) {
|
|
1448
|
+
loading = true;
|
|
1449
|
+
error = false;
|
|
1450
|
+
} else {
|
|
1451
|
+
loading = false;
|
|
1452
|
+
error = false;
|
|
1453
|
+
naturalWidth = 0;
|
|
1454
|
+
naturalHeight = 0;
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
function connect() {
|
|
1458
|
+
ensureBindings();
|
|
1459
|
+
const img = getImg();
|
|
1460
|
+
if (img?.complete && lastSrc) {
|
|
1461
|
+
if (img.naturalWidth > 0) {
|
|
1462
|
+
naturalWidth = img.naturalWidth;
|
|
1463
|
+
naturalHeight = img.naturalHeight;
|
|
1464
|
+
loading = false;
|
|
1465
|
+
error = false;
|
|
1466
|
+
} else {
|
|
1467
|
+
loading = false;
|
|
1468
|
+
error = true;
|
|
1469
|
+
}
|
|
1470
|
+
onStateChange();
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
function destroy() {
|
|
1474
|
+
abort.abort();
|
|
1475
|
+
resizeObserver?.disconnect();
|
|
1476
|
+
resizeObserver = null;
|
|
1477
|
+
}
|
|
1478
|
+
return {
|
|
1479
|
+
get loading() {
|
|
1480
|
+
return loading;
|
|
1481
|
+
},
|
|
1482
|
+
get error() {
|
|
1483
|
+
return error;
|
|
1484
|
+
},
|
|
1485
|
+
get naturalWidth() {
|
|
1486
|
+
return naturalWidth;
|
|
1487
|
+
},
|
|
1488
|
+
get naturalHeight() {
|
|
1489
|
+
return naturalHeight;
|
|
1490
|
+
},
|
|
1491
|
+
readConstraints() {
|
|
1492
|
+
const el = getContainer();
|
|
1493
|
+
if (!el) return {
|
|
1494
|
+
minWidth: 0,
|
|
1495
|
+
maxWidth: Infinity,
|
|
1496
|
+
minHeight: 0,
|
|
1497
|
+
maxHeight: Infinity
|
|
1498
|
+
};
|
|
1499
|
+
return core.parseConstraints(getComputedStyle(el));
|
|
1500
|
+
},
|
|
1501
|
+
updateSrc,
|
|
1502
|
+
connect,
|
|
1503
|
+
destroy
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
1506
|
+
|
|
1507
|
+
//#endregion
|
|
1508
|
+
//#region ../core/dist/dev/dom/ui/tooltip/tooltip.js
|
|
1509
|
+
/** Map popover reasons to tooltip reasons, filtering out click/outside-click. */
|
|
1510
|
+
const REASON_MAP = {
|
|
1511
|
+
hover: "hover",
|
|
1512
|
+
focus: "focus",
|
|
1513
|
+
escape: "escape",
|
|
1514
|
+
blur: "blur"
|
|
182
1515
|
};
|
|
1516
|
+
function createTooltip(options) {
|
|
1517
|
+
const popoverOpts = {
|
|
1518
|
+
transition: options.transition,
|
|
1519
|
+
onOpenChange(open, details) {
|
|
1520
|
+
const reason = REASON_MAP[details.reason];
|
|
1521
|
+
if (!reason) return;
|
|
1522
|
+
const group = options.group?.();
|
|
1523
|
+
if (open) group?.notifyOpen();
|
|
1524
|
+
else group?.notifyClose();
|
|
1525
|
+
const tooltipDetails = details.event ? {
|
|
1526
|
+
reason,
|
|
1527
|
+
event: details.event
|
|
1528
|
+
} : { reason };
|
|
1529
|
+
options.onOpenChange(open, tooltipDetails);
|
|
1530
|
+
},
|
|
1531
|
+
closeOnEscape: () => true,
|
|
1532
|
+
closeOnOutsideClick: () => false,
|
|
1533
|
+
openOnHover: () => true,
|
|
1534
|
+
delay: () => {
|
|
1535
|
+
const group = options.group?.();
|
|
1536
|
+
if (group?.shouldSkipDelay()) return 0;
|
|
1537
|
+
return options.delay?.() ?? group?.delay ?? 600;
|
|
1538
|
+
},
|
|
1539
|
+
closeDelay: () => {
|
|
1540
|
+
const group = options.group?.();
|
|
1541
|
+
return options.closeDelay?.() ?? group?.closeDelay ?? 0;
|
|
1542
|
+
}
|
|
1543
|
+
};
|
|
1544
|
+
if (options.onOpenChangeComplete) popoverOpts.onOpenChangeComplete = options.onOpenChangeComplete;
|
|
1545
|
+
const popover = createPopover(popoverOpts);
|
|
1546
|
+
let isPointerDown = false;
|
|
1547
|
+
const { onClick: _, ...baseTriggerProps } = popover.triggerProps;
|
|
1548
|
+
const triggerProps = {
|
|
1549
|
+
...baseTriggerProps,
|
|
1550
|
+
onPointerDown() {
|
|
1551
|
+
isPointerDown = true;
|
|
1552
|
+
},
|
|
1553
|
+
onPointerEnter(event) {
|
|
1554
|
+
if (options.disabled?.()) return;
|
|
1555
|
+
if (event.pointerType === "touch") return;
|
|
1556
|
+
baseTriggerProps.onPointerEnter(event);
|
|
1557
|
+
},
|
|
1558
|
+
onFocusIn(event) {
|
|
1559
|
+
if (options.disabled?.()) return;
|
|
1560
|
+
if (isPointerDown) {
|
|
1561
|
+
isPointerDown = false;
|
|
1562
|
+
return;
|
|
1563
|
+
}
|
|
1564
|
+
baseTriggerProps.onFocusIn(event);
|
|
1565
|
+
}
|
|
1566
|
+
};
|
|
1567
|
+
const popupProps = {
|
|
1568
|
+
...popover.popupProps,
|
|
1569
|
+
onPointerEnter(event) {
|
|
1570
|
+
if (options.disableHoverablePopup?.()) return;
|
|
1571
|
+
popover.popupProps.onPointerEnter(event);
|
|
1572
|
+
}
|
|
1573
|
+
};
|
|
1574
|
+
return {
|
|
1575
|
+
...popover,
|
|
1576
|
+
triggerProps,
|
|
1577
|
+
popupProps,
|
|
1578
|
+
get triggerElement() {
|
|
1579
|
+
return popover.triggerElement;
|
|
1580
|
+
},
|
|
1581
|
+
open: () => popover.open("hover"),
|
|
1582
|
+
close: () => popover.close("hover")
|
|
1583
|
+
};
|
|
1584
|
+
}
|
|
1585
|
+
|
|
1586
|
+
//#endregion
|
|
1587
|
+
//#region ../core/dist/dev/dom/ui/transition.js
|
|
1588
|
+
/**
|
|
1589
|
+
* Manages open/close transition lifecycle via `createState`.
|
|
1590
|
+
*
|
|
1591
|
+
* **Open:** patches `{ active: true, status: 'starting' }`, then after a
|
|
1592
|
+
* double-RAF patches `{ status: 'idle' }` so the browser paints the
|
|
1593
|
+
* initial ("from") state before transitioning.
|
|
1594
|
+
*
|
|
1595
|
+
* **Close:** patches `{ status: 'ending' }` (keeping `active: true` so the
|
|
1596
|
+
* element stays mounted), then after a double-RAF waits for
|
|
1597
|
+
* `getAnimations()` to settle before patching `{ active: false, status: 'idle' }`.
|
|
1598
|
+
*/
|
|
1599
|
+
function createTransition() {
|
|
1600
|
+
const state = createState({
|
|
1601
|
+
active: false,
|
|
1602
|
+
status: "idle"
|
|
1603
|
+
});
|
|
1604
|
+
let destroyed = false;
|
|
1605
|
+
let rafId1 = 0;
|
|
1606
|
+
let rafId2 = 0;
|
|
1607
|
+
function open() {
|
|
1608
|
+
cancelAnimationFrame(rafId1);
|
|
1609
|
+
cancelAnimationFrame(rafId2);
|
|
1610
|
+
rafId1 = 0;
|
|
1611
|
+
rafId2 = 0;
|
|
1612
|
+
state.patch({
|
|
1613
|
+
active: true,
|
|
1614
|
+
status: "starting"
|
|
1615
|
+
});
|
|
1616
|
+
return new Promise((resolve) => {
|
|
1617
|
+
rafId1 = requestAnimationFrame(() => {
|
|
1618
|
+
rafId1 = 0;
|
|
1619
|
+
rafId2 = requestAnimationFrame(() => {
|
|
1620
|
+
rafId2 = 0;
|
|
1621
|
+
if (destroyed || !state.current.active) return resolve();
|
|
1622
|
+
state.patch({ status: "idle" });
|
|
1623
|
+
resolve();
|
|
1624
|
+
});
|
|
1625
|
+
});
|
|
1626
|
+
});
|
|
1627
|
+
}
|
|
1628
|
+
function close(el) {
|
|
1629
|
+
cancelAnimationFrame(rafId1);
|
|
1630
|
+
cancelAnimationFrame(rafId2);
|
|
1631
|
+
rafId1 = 0;
|
|
1632
|
+
rafId2 = 0;
|
|
1633
|
+
state.patch({ status: "ending" });
|
|
1634
|
+
return new Promise((resolve) => {
|
|
1635
|
+
rafId1 = requestAnimationFrame(() => {
|
|
1636
|
+
rafId1 = 0;
|
|
1637
|
+
rafId2 = requestAnimationFrame(() => {
|
|
1638
|
+
rafId2 = 0;
|
|
1639
|
+
if (destroyed) return resolve();
|
|
1640
|
+
waitForAnimations(el).finally(() => {
|
|
1641
|
+
if (destroyed || state.current.status !== "ending") return resolve();
|
|
1642
|
+
state.patch({
|
|
1643
|
+
active: false,
|
|
1644
|
+
status: "idle"
|
|
1645
|
+
});
|
|
1646
|
+
resolve();
|
|
1647
|
+
});
|
|
1648
|
+
});
|
|
1649
|
+
});
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
function cancel() {
|
|
1653
|
+
cancelAnimationFrame(rafId1);
|
|
1654
|
+
cancelAnimationFrame(rafId2);
|
|
1655
|
+
rafId1 = 0;
|
|
1656
|
+
rafId2 = 0;
|
|
1657
|
+
if (state.current.status !== "idle") state.patch({ status: "idle" });
|
|
1658
|
+
}
|
|
1659
|
+
return {
|
|
1660
|
+
state,
|
|
1661
|
+
open,
|
|
1662
|
+
close,
|
|
1663
|
+
cancel,
|
|
1664
|
+
destroy() {
|
|
1665
|
+
if (destroyed) return;
|
|
1666
|
+
destroyed = true;
|
|
1667
|
+
cancel();
|
|
1668
|
+
}
|
|
1669
|
+
};
|
|
1670
|
+
}
|
|
1671
|
+
function waitForAnimations(el) {
|
|
1672
|
+
if (!el) return Promise.resolve();
|
|
1673
|
+
const animations = el.getAnimations?.() ?? [];
|
|
1674
|
+
if (animations.length === 0) return Promise.resolve();
|
|
1675
|
+
return Promise.all(animations.map((a) => a.finished)).then(noop, noop);
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
//#endregion
|
|
1679
|
+
//#region ../core/dist/dev/dom/ui/wheel-step.js
|
|
1680
|
+
function createWheelStep(options) {
|
|
1681
|
+
return { onWheel(event) {
|
|
1682
|
+
if (options.isDisabled()) return;
|
|
1683
|
+
const direction = Math.sign(event.deltaY);
|
|
1684
|
+
if (direction === 0) return;
|
|
1685
|
+
event.preventDefault();
|
|
1686
|
+
const stepPercent = options.getStepPercent();
|
|
1687
|
+
const newPercent = clamp(options.getPercent() - direction * stepPercent, 0, 100);
|
|
1688
|
+
options.onValueChange?.(newPercent);
|
|
1689
|
+
} };
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
//#endregion
|
|
1693
|
+
//#region ../core/dist/dev/dom/utils/element-props.js
|
|
1694
|
+
/**
|
|
1695
|
+
* Apply props to a DOM element.
|
|
1696
|
+
*
|
|
1697
|
+
* Handles both attributes and event listeners:
|
|
1698
|
+
* - Event props (onClick, onKeyDown, etc.) are attached as listeners
|
|
1699
|
+
* - Boolean props: `true` sets empty attribute, `false` removes
|
|
1700
|
+
* - `undefined` removes the attribute
|
|
1701
|
+
* - Other props are set as string attributes
|
|
1702
|
+
*/
|
|
1703
|
+
function applyElementProps(element, props, options) {
|
|
1704
|
+
const signal = options?.signal;
|
|
1705
|
+
for (const [key, value] of Object.entries(props)) if (isFunction(value) && key.startsWith("on")) listen(element, key.slice(2).toLowerCase(), value, signal ? { signal } : void 0);
|
|
1706
|
+
else if (isUndefined(value) || value === false) element.removeAttribute(key);
|
|
1707
|
+
else if (value === true) element.setAttribute(key, "");
|
|
1708
|
+
else element.setAttribute(key, String(value));
|
|
1709
|
+
}
|
|
183
1710
|
|
|
184
1711
|
//#endregion
|
|
185
|
-
//#region ../core/dist/dev/
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
return {
|
|
194
|
-
visible: media.controlsVisible,
|
|
195
|
-
userActive: media.userActive
|
|
196
|
-
};
|
|
197
|
-
}
|
|
198
|
-
};
|
|
1712
|
+
//#region ../core/dist/dev/dom/utils/log.js
|
|
1713
|
+
const warned = /* @__PURE__ */ new Set();
|
|
1714
|
+
function logMissingFeature(displayName, featureName) {
|
|
1715
|
+
const key = `${displayName}:${featureName}`;
|
|
1716
|
+
if (warned.has(key)) return;
|
|
1717
|
+
warned.add(key);
|
|
1718
|
+
console.warn(`${displayName} requires ${featureName} feature`);
|
|
1719
|
+
}
|
|
199
1720
|
|
|
200
1721
|
//#endregion
|
|
201
|
-
//#region ../core/dist/dev/
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
1722
|
+
//#region ../core/dist/dev/dom/utils/state-data-attrs.js
|
|
1723
|
+
/**
|
|
1724
|
+
* Apply state as data attributes to an element.
|
|
1725
|
+
*
|
|
1726
|
+
* - `true` → sets `data-keyname=""`
|
|
1727
|
+
* - truthy string/number → sets `data-keyname="value"`
|
|
1728
|
+
* - falsy → removes the attribute
|
|
1729
|
+
*
|
|
1730
|
+
* @example
|
|
1731
|
+
* ```ts
|
|
1732
|
+
* const state = { paused: true, ended: false };
|
|
1733
|
+
* applyStateDataAttrs(element, state);
|
|
1734
|
+
* // element has data-paused="", data-ended is removed
|
|
1735
|
+
* ```
|
|
1736
|
+
*/
|
|
1737
|
+
function applyStateDataAttrs(element, state, map) {
|
|
1738
|
+
for (const key in state) {
|
|
1739
|
+
if (map && !(key in map)) continue;
|
|
1740
|
+
const name = map?.[key] ?? toDataAttrName(key), value = state[key];
|
|
1741
|
+
if (value === true) element.setAttribute(name, "");
|
|
1742
|
+
else if (value) element.setAttribute(name, String(value));
|
|
1743
|
+
else element.removeAttribute(name);
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
function toDataAttrName(key) {
|
|
1747
|
+
return `data-${key.toLowerCase()}`;
|
|
1748
|
+
}
|
|
206
1749
|
|
|
207
1750
|
//#endregion
|
|
208
|
-
//#region ../core/dist/dev/core/ui/
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
1751
|
+
//#region ../core/dist/dev/core/ui/transition.js
|
|
1752
|
+
function getTransitionFlags(status) {
|
|
1753
|
+
return {
|
|
1754
|
+
transitionStarting: status === "starting",
|
|
1755
|
+
transitionEnding: status === "ending"
|
|
1756
|
+
};
|
|
1757
|
+
}
|
|
213
1758
|
|
|
214
1759
|
//#endregion
|
|
215
|
-
//#region ../core/dist/dev/core/ui/
|
|
216
|
-
var
|
|
1760
|
+
//#region ../core/dist/dev/core/ui/alert-dialog/alert-dialog-core.js
|
|
1761
|
+
var AlertDialogCore = class {
|
|
217
1762
|
static defaultProps = {
|
|
218
|
-
|
|
219
|
-
|
|
1763
|
+
open: false,
|
|
1764
|
+
defaultOpen: false
|
|
220
1765
|
};
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
constructor(props) {
|
|
229
|
-
if (props) this.setProps(props);
|
|
1766
|
+
/** Accept props for API consistency. Props are consumed by platform layers. */
|
|
1767
|
+
setProps(_props) {}
|
|
1768
|
+
#input = null;
|
|
1769
|
+
#titleId = void 0;
|
|
1770
|
+
#descriptionId = void 0;
|
|
1771
|
+
setInput(input) {
|
|
1772
|
+
this.#input = input;
|
|
230
1773
|
}
|
|
231
|
-
|
|
232
|
-
this.#
|
|
1774
|
+
setTitleId(id) {
|
|
1775
|
+
this.#titleId = id;
|
|
233
1776
|
}
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
if (isFunction(label)) {
|
|
237
|
-
const customLabel = label(state);
|
|
238
|
-
if (customLabel) return customLabel;
|
|
239
|
-
} else if (label) return label;
|
|
240
|
-
return state.fullscreen ? "Exit fullscreen" : "Enter fullscreen";
|
|
1777
|
+
setDescriptionId(id) {
|
|
1778
|
+
this.#descriptionId = id;
|
|
241
1779
|
}
|
|
242
|
-
|
|
1780
|
+
getState() {
|
|
1781
|
+
const input = this.#input;
|
|
243
1782
|
return {
|
|
244
|
-
|
|
245
|
-
|
|
1783
|
+
open: input.active,
|
|
1784
|
+
status: input.status,
|
|
1785
|
+
titleId: this.#titleId,
|
|
1786
|
+
descriptionId: this.#descriptionId,
|
|
1787
|
+
...getTransitionFlags(input.status)
|
|
246
1788
|
};
|
|
247
1789
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
availability: media.fullscreenAvailability
|
|
256
|
-
});
|
|
257
|
-
this.state.patch({ label: this.getLabel(this.state.current) });
|
|
258
|
-
return this.state.current;
|
|
259
|
-
}
|
|
260
|
-
async toggle(media) {
|
|
261
|
-
if (this.#props.disabled) return;
|
|
262
|
-
if (media.fullscreenAvailability !== "available") return;
|
|
263
|
-
try {
|
|
264
|
-
if (media.fullscreen) await media.exitFullscreen();
|
|
265
|
-
else await media.requestFullscreen();
|
|
266
|
-
} catch {}
|
|
1790
|
+
getAttrs(state) {
|
|
1791
|
+
return {
|
|
1792
|
+
role: "alertdialog",
|
|
1793
|
+
"aria-modal": "true",
|
|
1794
|
+
"aria-labelledby": state.titleId,
|
|
1795
|
+
"aria-describedby": state.descriptionId
|
|
1796
|
+
};
|
|
267
1797
|
}
|
|
268
1798
|
};
|
|
269
1799
|
|
|
270
1800
|
//#endregion
|
|
271
|
-
//#region ../core/dist/dev/core/ui/
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
1801
|
+
//#region ../core/dist/dev/core/ui/alert-dialog/alert-dialog-data-attrs.js
|
|
1802
|
+
const AlertDialogDataAttrs = {
|
|
1803
|
+
open: "data-open",
|
|
1804
|
+
transitionStarting: "data-starting-style",
|
|
1805
|
+
transitionEnding: "data-ending-style"
|
|
1806
|
+
};
|
|
1807
|
+
|
|
1808
|
+
//#endregion
|
|
1809
|
+
//#region ../core/dist/dev/core/ui/error-dialog/error-dialog-core.js
|
|
1810
|
+
/** Error-dialog core: an alert dialog whose open state is driven by media error state. */
|
|
1811
|
+
var ErrorDialogCore = class extends AlertDialogCore {
|
|
1812
|
+
setProps() {}
|
|
275
1813
|
};
|
|
276
1814
|
|
|
277
1815
|
//#endregion
|
|
@@ -339,69 +1877,6 @@ const MuteButtonDataAttrs = {
|
|
|
339
1877
|
volumeLevel: "data-volume-level"
|
|
340
1878
|
};
|
|
341
1879
|
|
|
342
|
-
//#endregion
|
|
343
|
-
//#region ../core/dist/dev/core/ui/pip-button/pip-button-core.js
|
|
344
|
-
var PiPButtonCore = class PiPButtonCore {
|
|
345
|
-
static defaultProps = {
|
|
346
|
-
label: "",
|
|
347
|
-
disabled: false
|
|
348
|
-
};
|
|
349
|
-
state = createState({
|
|
350
|
-
pip: false,
|
|
351
|
-
availability: "available",
|
|
352
|
-
label: ""
|
|
353
|
-
});
|
|
354
|
-
#props = { ...PiPButtonCore.defaultProps };
|
|
355
|
-
#media = null;
|
|
356
|
-
constructor(props) {
|
|
357
|
-
if (props) this.setProps(props);
|
|
358
|
-
}
|
|
359
|
-
setProps(props) {
|
|
360
|
-
this.#props = defaults(props, PiPButtonCore.defaultProps);
|
|
361
|
-
}
|
|
362
|
-
getLabel(state) {
|
|
363
|
-
const { label } = this.#props;
|
|
364
|
-
if (isFunction(label)) {
|
|
365
|
-
const customLabel = label(state);
|
|
366
|
-
if (customLabel) return customLabel;
|
|
367
|
-
} else if (label) return label;
|
|
368
|
-
return state.pip ? "Exit picture-in-picture" : "Enter picture-in-picture";
|
|
369
|
-
}
|
|
370
|
-
getAttrs(state) {
|
|
371
|
-
return {
|
|
372
|
-
"aria-label": this.getLabel(state),
|
|
373
|
-
"aria-disabled": this.#props.disabled ? "true" : void 0
|
|
374
|
-
};
|
|
375
|
-
}
|
|
376
|
-
setMedia(media) {
|
|
377
|
-
this.#media = media;
|
|
378
|
-
}
|
|
379
|
-
getState() {
|
|
380
|
-
const media = this.#media;
|
|
381
|
-
this.state.patch({
|
|
382
|
-
pip: media.pip,
|
|
383
|
-
availability: media.pipAvailability
|
|
384
|
-
});
|
|
385
|
-
this.state.patch({ label: this.getLabel(this.state.current) });
|
|
386
|
-
return this.state.current;
|
|
387
|
-
}
|
|
388
|
-
async toggle(media) {
|
|
389
|
-
if (this.#props.disabled) return;
|
|
390
|
-
if (media.pipAvailability !== "available") return;
|
|
391
|
-
try {
|
|
392
|
-
if (media.pip) await media.exitPictureInPicture();
|
|
393
|
-
else await media.requestPictureInPicture();
|
|
394
|
-
} catch {}
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
|
-
|
|
398
|
-
//#endregion
|
|
399
|
-
//#region ../core/dist/dev/core/ui/pip-button/pip-button-data-attrs.js
|
|
400
|
-
const PiPButtonDataAttrs = {
|
|
401
|
-
pip: "data-pip",
|
|
402
|
-
availability: "data-availability"
|
|
403
|
-
};
|
|
404
|
-
|
|
405
1880
|
//#endregion
|
|
406
1881
|
//#region ../core/dist/dev/core/ui/play-button/play-button-core.js
|
|
407
1882
|
var PlayButtonCore = class PlayButtonCore {
|
|
@@ -585,22 +2060,6 @@ const PopoverDataAttrs = {
|
|
|
585
2060
|
transitionEnding: "data-ending-style"
|
|
586
2061
|
};
|
|
587
2062
|
|
|
588
|
-
//#endregion
|
|
589
|
-
//#region ../core/dist/dev/core/ui/poster/poster-core.js
|
|
590
|
-
var PosterCore = class {
|
|
591
|
-
#media = null;
|
|
592
|
-
setMedia(media) {
|
|
593
|
-
this.#media = media;
|
|
594
|
-
}
|
|
595
|
-
getState() {
|
|
596
|
-
return { visible: !this.#media.started };
|
|
597
|
-
}
|
|
598
|
-
};
|
|
599
|
-
|
|
600
|
-
//#endregion
|
|
601
|
-
//#region ../core/dist/dev/core/ui/poster/poster-data-attrs.js
|
|
602
|
-
const PosterDataAttrs = { visible: "data-visible" };
|
|
603
|
-
|
|
604
2063
|
//#endregion
|
|
605
2064
|
//#region ../core/dist/dev/core/ui/seek-button/seek-button-core.js
|
|
606
2065
|
var SeekButtonCore = class SeekButtonCore {
|
|
@@ -1028,7 +2487,7 @@ var TimeSliderCore = class TimeSliderCore extends SliderCore {
|
|
|
1028
2487
|
static defaultProps = {
|
|
1029
2488
|
...SliderCore.defaultProps,
|
|
1030
2489
|
label: "Seek",
|
|
1031
|
-
|
|
2490
|
+
changeThrottle: 100
|
|
1032
2491
|
};
|
|
1033
2492
|
#props = { ...TimeSliderCore.defaultProps };
|
|
1034
2493
|
#media = null;
|
|
@@ -1048,14 +2507,12 @@ var TimeSliderCore = class TimeSliderCore extends SliderCore {
|
|
|
1048
2507
|
}
|
|
1049
2508
|
getState() {
|
|
1050
2509
|
const { duration, currentTime, seeking, buffered } = this.#media;
|
|
1051
|
-
const { dragging, dragPercent } = this.input;
|
|
1052
2510
|
super.setProps({
|
|
1053
2511
|
...this.#props,
|
|
1054
2512
|
min: 0,
|
|
1055
2513
|
max: duration
|
|
1056
2514
|
});
|
|
1057
|
-
const
|
|
1058
|
-
const base = super.getSliderState(value);
|
|
2515
|
+
const base = super.getSliderState(currentTime);
|
|
1059
2516
|
const bufferedEnd = buffered.length > 0 ? buffered[buffered.length - 1][1] : 0;
|
|
1060
2517
|
const bufferPercent = duration > 0 ? bufferedEnd / duration * 100 : 0;
|
|
1061
2518
|
return {
|
|
@@ -1071,11 +2528,13 @@ var TimeSliderCore = class TimeSliderCore extends SliderCore {
|
|
|
1071
2528
|
}
|
|
1072
2529
|
getAttrs(state) {
|
|
1073
2530
|
const base = super.getAttrs(state);
|
|
1074
|
-
const
|
|
2531
|
+
const announceValue = state.dragging ? this.rawValueFromPercent(state.pointerPercent) : state.value;
|
|
2532
|
+
const currentPhrase = formatTimeAsPhrase(announceValue);
|
|
1075
2533
|
const durationPhrase = formatTimeAsPhrase(state.duration);
|
|
1076
2534
|
const valuetext = durationPhrase ? `${currentPhrase} of ${durationPhrase}` : currentPhrase;
|
|
1077
2535
|
return {
|
|
1078
2536
|
...base,
|
|
2537
|
+
"aria-valuenow": announceValue,
|
|
1079
2538
|
"aria-valuetext": valuetext
|
|
1080
2539
|
};
|
|
1081
2540
|
}
|
|
@@ -1249,6 +2708,29 @@ const VolumeSliderDataAttrs = {
|
|
|
1249
2708
|
availability: "data-availability"
|
|
1250
2709
|
};
|
|
1251
2710
|
|
|
2711
|
+
//#endregion
|
|
2712
|
+
//#region src/ui/hotkey/aria-key-shortcuts-controller.ts
|
|
2713
|
+
/** Provides `aria-keyshortcuts` for a given hotkey action name. */
|
|
2714
|
+
var AriaKeyShortcutsController = class {
|
|
2715
|
+
#action;
|
|
2716
|
+
#container;
|
|
2717
|
+
constructor(host, action) {
|
|
2718
|
+
this.#action = action;
|
|
2719
|
+
this.#container = new ContextConsumer(host, {
|
|
2720
|
+
context: containerContext,
|
|
2721
|
+
subscribe: true
|
|
2722
|
+
});
|
|
2723
|
+
host.addController(this);
|
|
2724
|
+
}
|
|
2725
|
+
get value() {
|
|
2726
|
+
const container = this.#container.value?.container;
|
|
2727
|
+
if (!container) return void 0;
|
|
2728
|
+
return findHotkeyCoordinator(container)?.getAriaKeys(this.#action);
|
|
2729
|
+
}
|
|
2730
|
+
hostConnected() {}
|
|
2731
|
+
hostDisconnected() {}
|
|
2732
|
+
};
|
|
2733
|
+
|
|
1252
2734
|
//#endregion
|
|
1253
2735
|
//#region src/ui/media-button-element.ts
|
|
1254
2736
|
/** Abstract base for HTML custom elements that render a media-control button. */
|
|
@@ -1257,6 +2739,7 @@ var MediaButtonElement = class extends MediaElement {
|
|
|
1257
2739
|
super(..._args);
|
|
1258
2740
|
this.disabled = false;
|
|
1259
2741
|
this.label = "";
|
|
2742
|
+
this.hotkeyAction = void 0;
|
|
1260
2743
|
}
|
|
1261
2744
|
static {
|
|
1262
2745
|
this.properties = {
|
|
@@ -1268,8 +2751,11 @@ var MediaButtonElement = class extends MediaElement {
|
|
|
1268
2751
|
return this.core.state;
|
|
1269
2752
|
}
|
|
1270
2753
|
#disconnect = null;
|
|
2754
|
+
#hotkeyRegistry = null;
|
|
1271
2755
|
connectedCallback() {
|
|
1272
2756
|
super.connectedCallback();
|
|
2757
|
+
if (this.destroyed) return;
|
|
2758
|
+
if (this.hotkeyAction && !this.#hotkeyRegistry) this.#hotkeyRegistry = new AriaKeyShortcutsController(this, this.hotkeyAction);
|
|
1273
2759
|
this.#disconnect = new AbortController();
|
|
1274
2760
|
const buttonProps = createButton({
|
|
1275
2761
|
onActivate: () => this.activate(this.mediaState.value),
|
|
@@ -1297,7 +2783,10 @@ var MediaButtonElement = class extends MediaElement {
|
|
|
1297
2783
|
if (!media) return;
|
|
1298
2784
|
this.core.setMedia(media);
|
|
1299
2785
|
const state = this.core.getState();
|
|
1300
|
-
applyElementProps(this,
|
|
2786
|
+
applyElementProps(this, {
|
|
2787
|
+
...this.core.getAttrs?.(state),
|
|
2788
|
+
"aria-keyshortcuts": this.#hotkeyRegistry?.value
|
|
2789
|
+
});
|
|
1301
2790
|
applyStateDataAttrs(this, state, this.stateAttrMap);
|
|
1302
2791
|
}
|
|
1303
2792
|
};
|
|
@@ -1432,6 +2921,7 @@ var ErrorDialogElement = class extends MediaElement {
|
|
|
1432
2921
|
}
|
|
1433
2922
|
connectedCallback() {
|
|
1434
2923
|
super.connectedCallback();
|
|
2924
|
+
if (this.destroyed) return;
|
|
1435
2925
|
this.#dialog = createAlertDialog({
|
|
1436
2926
|
transition: createTransition(),
|
|
1437
2927
|
onOpenChange: (nextOpen) => {
|
|
@@ -1490,6 +2980,7 @@ var MuteButtonElement = class extends MediaButtonElement {
|
|
|
1490
2980
|
this.core = new MuteButtonCore();
|
|
1491
2981
|
this.stateAttrMap = MuteButtonDataAttrs;
|
|
1492
2982
|
this.mediaState = new PlayerController(this, playerContext, selectVolume);
|
|
2983
|
+
this.hotkeyAction = "toggleMuted";
|
|
1493
2984
|
}
|
|
1494
2985
|
static {
|
|
1495
2986
|
this.tagName = "media-mute-button";
|
|
@@ -1511,6 +3002,7 @@ var PlayButtonElement = class extends MediaButtonElement {
|
|
|
1511
3002
|
this.core = new PlayButtonCore();
|
|
1512
3003
|
this.stateAttrMap = PlayButtonDataAttrs;
|
|
1513
3004
|
this.mediaState = new PlayerController(this, playerContext, selectPlayback);
|
|
3005
|
+
this.hotkeyAction = "togglePaused";
|
|
1514
3006
|
}
|
|
1515
3007
|
static {
|
|
1516
3008
|
this.tagName = "media-play-button";
|
|
@@ -1545,6 +3037,79 @@ var PlaybackRateButtonElement = class extends MediaButtonElement {
|
|
|
1545
3037
|
//#region src/define/ui/playback-rate-button.ts
|
|
1546
3038
|
safeDefine(PlaybackRateButtonElement);
|
|
1547
3039
|
|
|
3040
|
+
//#endregion
|
|
3041
|
+
//#region src/ui/position-controller.ts
|
|
3042
|
+
/**
|
|
3043
|
+
* Reactive controller that manages JS-fallback positioning for floating
|
|
3044
|
+
* popup elements (tooltips, popovers). Tracks scroll, resize, and
|
|
3045
|
+
* ResizeObserver events to keep the popup aligned with its trigger.
|
|
3046
|
+
*
|
|
3047
|
+
* When native CSS Anchor Positioning is supported, `sync()` is a no-op.
|
|
3048
|
+
*/
|
|
3049
|
+
var PositionController = class {
|
|
3050
|
+
#host;
|
|
3051
|
+
#abort = null;
|
|
3052
|
+
#frame = 0;
|
|
3053
|
+
#resizeObserver = null;
|
|
3054
|
+
#trigger = null;
|
|
3055
|
+
constructor(host) {
|
|
3056
|
+
this.#host = host;
|
|
3057
|
+
host.addController(this);
|
|
3058
|
+
}
|
|
3059
|
+
/** Discover a trigger element linked via `commandfor` attribute. */
|
|
3060
|
+
findTrigger() {
|
|
3061
|
+
if (!this.#host.id) return null;
|
|
3062
|
+
return this.#host.getRootNode().querySelector(`[commandfor="${this.#host.id}"]`);
|
|
3063
|
+
}
|
|
3064
|
+
/** Start or update position tracking for the given trigger. */
|
|
3065
|
+
sync(trigger) {
|
|
3066
|
+
if (supportsAnchorPositioning()) return;
|
|
3067
|
+
if (!trigger) return;
|
|
3068
|
+
if (this.#abort && this.#trigger === trigger) return;
|
|
3069
|
+
this.cleanup();
|
|
3070
|
+
this.#abort = new AbortController();
|
|
3071
|
+
this.#trigger = trigger;
|
|
3072
|
+
const { signal } = this.#abort;
|
|
3073
|
+
const reposition = () => {
|
|
3074
|
+
cancelAnimationFrame(this.#frame);
|
|
3075
|
+
this.#frame = requestAnimationFrame(() => {
|
|
3076
|
+
if (signal.aborted) return;
|
|
3077
|
+
this.#host.requestUpdate();
|
|
3078
|
+
});
|
|
3079
|
+
};
|
|
3080
|
+
window.addEventListener("scroll", reposition, {
|
|
3081
|
+
capture: true,
|
|
3082
|
+
passive: true,
|
|
3083
|
+
signal
|
|
3084
|
+
});
|
|
3085
|
+
window.addEventListener("resize", reposition, { signal });
|
|
3086
|
+
if (typeof ResizeObserver === "function") {
|
|
3087
|
+
this.#resizeObserver = new ResizeObserver(() => {
|
|
3088
|
+
reposition();
|
|
3089
|
+
});
|
|
3090
|
+
this.#resizeObserver.observe(trigger);
|
|
3091
|
+
this.#resizeObserver.observe(this.#host);
|
|
3092
|
+
}
|
|
3093
|
+
reposition();
|
|
3094
|
+
}
|
|
3095
|
+
/** Stop all position tracking. */
|
|
3096
|
+
cleanup() {
|
|
3097
|
+
this.#abort?.abort();
|
|
3098
|
+
this.#abort = null;
|
|
3099
|
+
this.#trigger = null;
|
|
3100
|
+
cancelAnimationFrame(this.#frame);
|
|
3101
|
+
this.#frame = 0;
|
|
3102
|
+
this.#resizeObserver?.disconnect();
|
|
3103
|
+
this.#resizeObserver = null;
|
|
3104
|
+
}
|
|
3105
|
+
hostDisconnected() {
|
|
3106
|
+
this.cleanup();
|
|
3107
|
+
}
|
|
3108
|
+
hostDestroyed() {
|
|
3109
|
+
this.cleanup();
|
|
3110
|
+
}
|
|
3111
|
+
};
|
|
3112
|
+
|
|
1548
3113
|
//#endregion
|
|
1549
3114
|
//#region src/ui/popover/popover-element.ts
|
|
1550
3115
|
var PopoverElement = class extends MediaElement {
|
|
@@ -1594,15 +3159,12 @@ var PopoverElement = class extends MediaElement {
|
|
|
1594
3159
|
};
|
|
1595
3160
|
}
|
|
1596
3161
|
#core = new PopoverCore();
|
|
3162
|
+
#position = new PositionController(this);
|
|
1597
3163
|
#popover = null;
|
|
1598
3164
|
#snapshot = null;
|
|
1599
3165
|
#disconnect = null;
|
|
1600
3166
|
#triggerAbort = null;
|
|
1601
3167
|
#currentTrigger = null;
|
|
1602
|
-
#positionAbort = null;
|
|
1603
|
-
#positionFrame = 0;
|
|
1604
|
-
#resizeObserver = null;
|
|
1605
|
-
#positionTrigger = null;
|
|
1606
3168
|
connectedCallback() {
|
|
1607
3169
|
super.connectedCallback();
|
|
1608
3170
|
if (this.destroyed) return;
|
|
@@ -1633,12 +3195,10 @@ var PopoverElement = class extends MediaElement {
|
|
|
1633
3195
|
}
|
|
1634
3196
|
disconnectedCallback() {
|
|
1635
3197
|
super.disconnectedCallback();
|
|
1636
|
-
this.#cleanupPositioning();
|
|
1637
3198
|
this.#disconnect?.abort();
|
|
1638
3199
|
this.#disconnect = null;
|
|
1639
3200
|
}
|
|
1640
3201
|
destroyCallback() {
|
|
1641
|
-
this.#cleanupPositioning();
|
|
1642
3202
|
this.#cleanupTrigger();
|
|
1643
3203
|
this.#popover?.destroy();
|
|
1644
3204
|
super.destroyCallback();
|
|
@@ -1655,7 +3215,7 @@ var PopoverElement = class extends MediaElement {
|
|
|
1655
3215
|
update(_changed) {
|
|
1656
3216
|
super.update(_changed);
|
|
1657
3217
|
if (!this.#popover) return;
|
|
1658
|
-
const triggerEl = this.#findTrigger();
|
|
3218
|
+
const triggerEl = this.#position.findTrigger();
|
|
1659
3219
|
this.#syncTrigger(triggerEl);
|
|
1660
3220
|
const input = this.#popover.input.current;
|
|
1661
3221
|
this.#core.setInput(input);
|
|
@@ -1669,7 +3229,7 @@ var PopoverElement = class extends MediaElement {
|
|
|
1669
3229
|
applyStyles(this.#currentTrigger, getAnchorNameStyle(this.id));
|
|
1670
3230
|
}
|
|
1671
3231
|
if (!state.open) {
|
|
1672
|
-
this.#
|
|
3232
|
+
this.#position.cleanup();
|
|
1673
3233
|
return;
|
|
1674
3234
|
}
|
|
1675
3235
|
const posOpts = {
|
|
@@ -1684,15 +3244,11 @@ var PopoverElement = class extends MediaElement {
|
|
|
1684
3244
|
const offsets = resolveOffsets(this);
|
|
1685
3245
|
applyStyles(this, getAnchorPositionStyle(this.id, posOpts, triggerRect, selfRect, boundaryRect, offsets));
|
|
1686
3246
|
}
|
|
1687
|
-
this.#
|
|
1688
|
-
}
|
|
1689
|
-
#findTrigger() {
|
|
1690
|
-
if (!this.id) return null;
|
|
1691
|
-
return this.getRootNode().querySelector(`[commandfor="${this.id}"]`);
|
|
3247
|
+
this.#position.sync(this.#currentTrigger);
|
|
1692
3248
|
}
|
|
1693
3249
|
#syncTrigger(triggerEl) {
|
|
1694
3250
|
if (triggerEl === this.#currentTrigger) return;
|
|
1695
|
-
this.#
|
|
3251
|
+
this.#position.cleanup();
|
|
1696
3252
|
this.#cleanupTrigger();
|
|
1697
3253
|
this.#currentTrigger = triggerEl;
|
|
1698
3254
|
this.#popover?.setTriggerElement(triggerEl);
|
|
@@ -1714,46 +3270,6 @@ var PopoverElement = class extends MediaElement {
|
|
|
1714
3270
|
this.#triggerAbort = null;
|
|
1715
3271
|
this.#currentTrigger = null;
|
|
1716
3272
|
}
|
|
1717
|
-
#syncPositioning() {
|
|
1718
|
-
if (supportsAnchorPositioning()) return;
|
|
1719
|
-
const triggerEl = this.#currentTrigger;
|
|
1720
|
-
if (!triggerEl) return;
|
|
1721
|
-
if (this.#positionAbort && this.#positionTrigger === triggerEl) return;
|
|
1722
|
-
this.#cleanupPositioning();
|
|
1723
|
-
this.#positionAbort = new AbortController();
|
|
1724
|
-
this.#positionTrigger = triggerEl;
|
|
1725
|
-
const { signal } = this.#positionAbort;
|
|
1726
|
-
const reposition = () => {
|
|
1727
|
-
cancelAnimationFrame(this.#positionFrame);
|
|
1728
|
-
this.#positionFrame = requestAnimationFrame(() => {
|
|
1729
|
-
if (signal.aborted) return;
|
|
1730
|
-
this.requestUpdate();
|
|
1731
|
-
});
|
|
1732
|
-
};
|
|
1733
|
-
window.addEventListener("scroll", reposition, {
|
|
1734
|
-
capture: true,
|
|
1735
|
-
passive: true,
|
|
1736
|
-
signal
|
|
1737
|
-
});
|
|
1738
|
-
window.addEventListener("resize", reposition, { signal });
|
|
1739
|
-
if (typeof ResizeObserver === "function") {
|
|
1740
|
-
this.#resizeObserver = new ResizeObserver(() => {
|
|
1741
|
-
reposition();
|
|
1742
|
-
});
|
|
1743
|
-
this.#resizeObserver.observe(triggerEl);
|
|
1744
|
-
this.#resizeObserver.observe(this);
|
|
1745
|
-
}
|
|
1746
|
-
reposition();
|
|
1747
|
-
}
|
|
1748
|
-
#cleanupPositioning() {
|
|
1749
|
-
this.#positionAbort?.abort();
|
|
1750
|
-
this.#positionAbort = null;
|
|
1751
|
-
this.#positionTrigger = null;
|
|
1752
|
-
cancelAnimationFrame(this.#positionFrame);
|
|
1753
|
-
this.#positionFrame = 0;
|
|
1754
|
-
this.#resizeObserver?.disconnect();
|
|
1755
|
-
this.#resizeObserver = null;
|
|
1756
|
-
}
|
|
1757
3273
|
};
|
|
1758
3274
|
|
|
1759
3275
|
//#endregion
|
|
@@ -2183,7 +3699,7 @@ var TimeSliderElement = class extends MediaElement {
|
|
|
2183
3699
|
constructor(..._args) {
|
|
2184
3700
|
super(..._args);
|
|
2185
3701
|
this.label = TimeSliderCore.defaultProps.label;
|
|
2186
|
-
this.
|
|
3702
|
+
this.changeThrottle = TimeSliderCore.defaultProps.changeThrottle;
|
|
2187
3703
|
this.step = TimeSliderCore.defaultProps.step;
|
|
2188
3704
|
this.largeStep = TimeSliderCore.defaultProps.largeStep;
|
|
2189
3705
|
this.orientation = TimeSliderCore.defaultProps.orientation;
|
|
@@ -2196,9 +3712,9 @@ var TimeSliderElement = class extends MediaElement {
|
|
|
2196
3712
|
static {
|
|
2197
3713
|
this.properties = {
|
|
2198
3714
|
label: { type: String },
|
|
2199
|
-
|
|
3715
|
+
changeThrottle: {
|
|
2200
3716
|
type: Number,
|
|
2201
|
-
attribute: "
|
|
3717
|
+
attribute: "change-throttle"
|
|
2202
3718
|
},
|
|
2203
3719
|
step: { type: Number },
|
|
2204
3720
|
largeStep: {
|
|
@@ -2241,7 +3757,7 @@ var TimeSliderElement = class extends MediaElement {
|
|
|
2241
3757
|
const media = this.#timeState.value;
|
|
2242
3758
|
if (media) media.seek(this.#core.rawValueFromPercent(percent));
|
|
2243
3759
|
},
|
|
2244
|
-
|
|
3760
|
+
changeThrottle: this.changeThrottle,
|
|
2245
3761
|
onDragStart: () => {
|
|
2246
3762
|
this.dispatchEvent(new CustomEvent("drag-start", { bubbles: true }));
|
|
2247
3763
|
},
|
|
@@ -2358,17 +3874,15 @@ var TooltipElement = class extends MediaElement {
|
|
|
2358
3874
|
}
|
|
2359
3875
|
#core = new TooltipCore();
|
|
2360
3876
|
#groupConsumer = new ContextConsumer(this, { context: tooltipGroupContext });
|
|
3877
|
+
#position = new PositionController(this);
|
|
2361
3878
|
#tooltip = null;
|
|
2362
3879
|
#snapshot = null;
|
|
2363
3880
|
#disconnect = null;
|
|
2364
3881
|
#triggerAbort = null;
|
|
2365
3882
|
#currentTrigger = null;
|
|
2366
|
-
#positionAbort = null;
|
|
2367
|
-
#positionFrame = 0;
|
|
2368
|
-
#resizeObserver = null;
|
|
2369
|
-
#positionTrigger = null;
|
|
2370
3883
|
connectedCallback() {
|
|
2371
3884
|
super.connectedCallback();
|
|
3885
|
+
if (this.destroyed) return;
|
|
2372
3886
|
this.#disconnect = new AbortController();
|
|
2373
3887
|
this.#tooltip = createTooltip({
|
|
2374
3888
|
transition: createTransition(),
|
|
@@ -2396,7 +3910,6 @@ var TooltipElement = class extends MediaElement {
|
|
|
2396
3910
|
}
|
|
2397
3911
|
disconnectedCallback() {
|
|
2398
3912
|
super.disconnectedCallback();
|
|
2399
|
-
this.#cleanupPositioning();
|
|
2400
3913
|
this.#cleanupTrigger();
|
|
2401
3914
|
this.#tooltip?.destroy();
|
|
2402
3915
|
this.#tooltip = null;
|
|
@@ -2415,7 +3928,7 @@ var TooltipElement = class extends MediaElement {
|
|
|
2415
3928
|
update(_changed) {
|
|
2416
3929
|
super.update(_changed);
|
|
2417
3930
|
if (!this.#tooltip) return;
|
|
2418
|
-
const triggerEl = this.#findTrigger();
|
|
3931
|
+
const triggerEl = this.#position.findTrigger();
|
|
2419
3932
|
this.#syncTrigger(triggerEl);
|
|
2420
3933
|
const input = this.#tooltip.input.current;
|
|
2421
3934
|
this.#core.setInput(input);
|
|
@@ -2426,7 +3939,7 @@ var TooltipElement = class extends MediaElement {
|
|
|
2426
3939
|
else tryHidePopover(this);
|
|
2427
3940
|
if (this.#currentTrigger) applyStyles(this.#currentTrigger, getAnchorNameStyle(this.id));
|
|
2428
3941
|
if (!state.open) {
|
|
2429
|
-
this.#
|
|
3942
|
+
this.#position.cleanup();
|
|
2430
3943
|
return;
|
|
2431
3944
|
}
|
|
2432
3945
|
const posOpts = {
|
|
@@ -2441,15 +3954,11 @@ var TooltipElement = class extends MediaElement {
|
|
|
2441
3954
|
const offsets = resolveOffsets(this, TooltipCSSVars);
|
|
2442
3955
|
applyStyles(this, getAnchorPositionStyle(this.id, posOpts, triggerRect, selfRect, boundaryRect, offsets, TooltipCSSVars));
|
|
2443
3956
|
}
|
|
2444
|
-
this.#
|
|
2445
|
-
}
|
|
2446
|
-
#findTrigger() {
|
|
2447
|
-
if (!this.id) return null;
|
|
2448
|
-
return this.getRootNode().querySelector(`[commandfor="${this.id}"]`);
|
|
3957
|
+
this.#position.sync(this.#currentTrigger);
|
|
2449
3958
|
}
|
|
2450
3959
|
#syncTrigger(triggerEl) {
|
|
2451
3960
|
if (triggerEl === this.#currentTrigger) return;
|
|
2452
|
-
this.#
|
|
3961
|
+
this.#position.cleanup();
|
|
2453
3962
|
this.#cleanupTrigger();
|
|
2454
3963
|
this.#currentTrigger = triggerEl;
|
|
2455
3964
|
this.#tooltip?.setTriggerElement(triggerEl);
|
|
@@ -2471,46 +3980,6 @@ var TooltipElement = class extends MediaElement {
|
|
|
2471
3980
|
this.#triggerAbort = null;
|
|
2472
3981
|
this.#currentTrigger = null;
|
|
2473
3982
|
}
|
|
2474
|
-
#syncPositioning() {
|
|
2475
|
-
if (supportsAnchorPositioning()) return;
|
|
2476
|
-
const triggerEl = this.#currentTrigger;
|
|
2477
|
-
if (!triggerEl) return;
|
|
2478
|
-
if (this.#positionAbort && this.#positionTrigger === triggerEl) return;
|
|
2479
|
-
this.#cleanupPositioning();
|
|
2480
|
-
this.#positionAbort = new AbortController();
|
|
2481
|
-
this.#positionTrigger = triggerEl;
|
|
2482
|
-
const { signal } = this.#positionAbort;
|
|
2483
|
-
const reposition = () => {
|
|
2484
|
-
cancelAnimationFrame(this.#positionFrame);
|
|
2485
|
-
this.#positionFrame = requestAnimationFrame(() => {
|
|
2486
|
-
if (signal.aborted) return;
|
|
2487
|
-
this.requestUpdate();
|
|
2488
|
-
});
|
|
2489
|
-
};
|
|
2490
|
-
window.addEventListener("scroll", reposition, {
|
|
2491
|
-
capture: true,
|
|
2492
|
-
passive: true,
|
|
2493
|
-
signal
|
|
2494
|
-
});
|
|
2495
|
-
window.addEventListener("resize", reposition, { signal });
|
|
2496
|
-
if (typeof ResizeObserver === "function") {
|
|
2497
|
-
this.#resizeObserver = new ResizeObserver(() => {
|
|
2498
|
-
reposition();
|
|
2499
|
-
});
|
|
2500
|
-
this.#resizeObserver.observe(triggerEl);
|
|
2501
|
-
this.#resizeObserver.observe(this);
|
|
2502
|
-
}
|
|
2503
|
-
reposition();
|
|
2504
|
-
}
|
|
2505
|
-
#cleanupPositioning() {
|
|
2506
|
-
this.#positionAbort?.abort();
|
|
2507
|
-
this.#positionAbort = null;
|
|
2508
|
-
this.#positionTrigger = null;
|
|
2509
|
-
cancelAnimationFrame(this.#positionFrame);
|
|
2510
|
-
this.#positionFrame = 0;
|
|
2511
|
-
this.#resizeObserver?.disconnect();
|
|
2512
|
-
this.#resizeObserver = null;
|
|
2513
|
-
}
|
|
2514
3983
|
};
|
|
2515
3984
|
|
|
2516
3985
|
//#endregion
|
|
@@ -2685,5 +4154,5 @@ safeDefine(SliderTrackElement);
|
|
|
2685
4154
|
safeDefine(SliderValueElement);
|
|
2686
4155
|
|
|
2687
4156
|
//#endregion
|
|
2688
|
-
export {
|
|
2689
|
-
//# sourceMappingURL=volume-slider-
|
|
4157
|
+
export { createHotkey as a, selectPiP as c, selectTextTrack as d, selectTime as f, logMissingFeature as i, selectPlayback as l, defaults as m, MediaButtonElement as n, selectControls as o, selectVolume as p, applyStateDataAttrs as r, selectFullscreen as s, ContextPartElement as t, selectPlaybackRate as u };
|
|
4158
|
+
//# sourceMappingURL=volume-slider-C6ek7oC9.js.map
|