vidstack
Version:
Build awesome media experiences on the web.
1,163 lines (1,127 loc) • 129 kB
JavaScript
import { signal, effect, createContext, hasProvidedContext, useContext, provideContext, peek, isWriteSignal, StoreFactory, useStore, computed, onDispose, scoped, tick } from 'maverick.js';
import { ComponentController, Component, defineElement, prop, defineProp, method } from 'maverick.js/element';
import { s as scopedRaf, A as ARIAKeyShortcuts, a as setAttributeIfEmpty, o as onPress, u as useMedia, b as setARIALabel, i as isTrackCaptionKind, I as IS_SAFARI, f as functionThrottle, c as findActiveCue, d as canChangeVolume, e as onTrackChapterChange, g as isElementParent, h as isCueActive, p as preconnect } from './media-core.js';
import { $$_create_component, $$_create_walker, $$_effect, $$_attr, $$_next_element, $$_create_template, $$_listen, $$_ref, $$_setup_custom_element, $$_insert_at_marker_lite, $$_peek, $$_clone, $$_insert_lite, $$_computed, $$_next_template, $$_scoped } from 'maverick.js/dom';
import { I as Icon } from './icons/icon.js';
import { listenEvent, setAttribute, ariaBool as ariaBool$1, isNull, isNumber, setStyle, isDOMEvent, isKeyboardEvent, isUndefined, animationFrameThrottle, isDOMElement, isPointerEvent, isMouseEvent, isTouchEvent, kebabToCamelCase, createDisposalBin } from 'maverick.js/std';
import { CaptionsRenderer, renderVTTCueString, updateTimedVTTCueNodes } from 'media-captions';
function round(num, decimalPlaces = 2) {
return Number(num.toFixed(decimalPlaces));
}
function getNumberOfDecimalPlaces(num) {
return String(num).split(".")[1]?.length ?? 0;
}
function clampNumber(min, value, max) {
return Math.max(min, Math.min(max, value));
}
let $keyboard = signal(false);
{
listenEvent(document, "pointerdown", () => {
$keyboard.set(false);
});
listenEvent(document, "keydown", (e) => {
if (e.metaKey || e.altKey || e.ctrlKey)
return;
$keyboard.set(true);
});
}
class FocusVisibleController extends ComponentController {
_focused = signal(false);
onConnect(el) {
effect(() => {
if (!$keyboard()) {
this._focused.set(false);
updateFocusAttr(el, false);
this.listen("pointerenter", this._onPointerEnter.bind(this));
this.listen("pointerleave", this._onPointerLeave.bind(this));
return;
}
const active = document.activeElement === el;
this._focused.set(active);
updateFocusAttr(el, active);
this.listen("focus", this._onFocus.bind(this));
this.listen("blur", this._onBlur.bind(this));
});
}
focused() {
return this._focused();
}
_onFocus() {
this._focused.set(true);
updateFocusAttr(this.el, true);
}
_onBlur() {
this._focused.set(false);
updateFocusAttr(this.el, false);
}
_onPointerEnter() {
updateHoverAttr(this.el, true);
}
_onPointerLeave() {
updateHoverAttr(this.el, false);
}
}
function updateFocusAttr(el, isFocused) {
setAttribute(el, "data-focus", isFocused);
setAttribute(el, "data-hocus", isFocused);
}
function updateHoverAttr(el, isHovering) {
setAttribute(el, "data-hocus", isHovering);
setAttribute(el, "data-hover", isHovering);
}
const tooltipContext = createContext();
class Tooltip extends Component {
static el = defineElement({
tagName: "media-tooltip",
props: { position: "top center" }
});
onAttach(el) {
if (hasProvidedContext(tooltipContext)) {
scopedRaf(() => {
if (!el.isConnected)
return;
const tooltip = useContext(tooltipContext);
tooltip._attachTooltip(el);
});
}
this.setAttributes({
position: this.$props.position
});
}
}
let id = 0;
class TooltipController extends ComponentController {
constructor(instance) {
super(instance);
provideContext(tooltipContext, {
_attachTooltip: this._attachTooltip.bind(this)
});
}
_attachTooltip(tooltipEl) {
const tooltipId = `media-tooltip-${++id}`;
setAttribute(this.el, "aria-describedby", tooltipId);
setAttribute(tooltipEl, "id", tooltipId);
setAttribute(tooltipEl, "role", "tooltip");
this.el.removeAttribute("aria-label");
}
}
var __defProp$3 = Object.defineProperty;
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
var __decorateClass$3 = (decorators, target, key, kind) => {
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
for (var i = decorators.length - 1, decorator; i >= 0; i--)
if (decorator = decorators[i])
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
if (kind && result)
__defProp$3(target, key, result);
return result;
};
const toggleButtonProps = {
disabled: false,
defaultPressed: false,
defaultAppearance: false
};
class ToggleButton extends Component {
static el = defineElement({
tagName: "media-toggle-button",
props: toggleButtonProps
});
_pressed = signal(false);
_keyShortcut;
constructor(instance) {
super(instance);
new FocusVisibleController(instance);
new TooltipController(instance);
if (this._keyShortcut)
new ARIAKeyShortcuts(instance, this._keyShortcut);
}
get pressed() {
return peek(this._pressed);
}
onAttach(el) {
if (isWriteSignal(this._pressed)) {
this._pressed.set(this.$props.defaultPressed());
}
setAttributeIfEmpty(el, "tabindex", "0");
setAttributeIfEmpty(el, "role", "button");
const { disabled, defaultAppearance } = this.$props;
this.setAttributes({
disabled,
"default-appearance": defaultAppearance,
"data-pressed": this._pressed,
"aria-pressed": this._isARIAPressed.bind(this),
"data-media-button": true
});
}
onConnect(el) {
onPress(el, this._onMaybePress.bind(this));
}
_isARIAPressed() {
return ariaBool$1(this._pressed());
}
_onPress(event) {
if (isWriteSignal(this._pressed)) {
this._pressed.set((p) => !p);
}
}
_onMaybePress(event) {
const disabled = this.$props.disabled();
if (disabled) {
if (disabled)
event.stopImmediatePropagation();
return;
}
event.preventDefault();
this._onPress(event);
}
}
__decorateClass$3([
prop
], ToggleButton.prototype, "pressed", 1);
var Icon$56 = `<path d="M8.66667 6.66667C8.29848 6.66667 8 6.96514 8 7.33333V24.6667C8 25.0349 8.29848 25.3333 8.66667 25.3333H12.6667C13.0349 25.3333 13.3333 25.0349 13.3333 24.6667V7.33333C13.3333 6.96514 13.0349 6.66667 12.6667 6.66667H8.66667Z" fill="currentColor"/> <path d="M19.3333 6.66667C18.9651 6.66667 18.6667 6.96514 18.6667 7.33333V24.6667C18.6667 25.0349 18.9651 25.3333 19.3333 25.3333H23.3333C23.7015 25.3333 24 25.0349 24 24.6667V7.33333C24 6.96514 23.7015 6.66667 23.3333 6.66667H19.3333Z" fill="currentColor"/>`;
var Icon$59 = `<path d="M10.6667 6.6548C10.6667 6.10764 11.2894 5.79346 11.7295 6.11862L24.377 15.4634C24.7377 15.7298 24.7377 16.2692 24.3771 16.5357L11.7295 25.8813C11.2895 26.2065 10.6667 25.8923 10.6667 25.3451L10.6667 6.6548Z" fill="currentColor"/>`;
var Icon$71 = `<path d="M15.6038 12.2147C16.0439 12.5399 16.6667 12.2257 16.6667 11.6786V10.1789C16.6667 10.1001 16.7351 10.0384 16.8134 10.0479C20.1116 10.4494 22.6667 13.2593 22.6667 16.6659C22.6667 20.3481 19.6817 23.3332 15.9995 23.3332C12.542 23.3332 9.69927 20.7014 9.36509 17.332C9.32875 16.9655 9.03371 16.6662 8.66548 16.6662L6.66655 16.6666C6.29841 16.6666 5.99769 16.966 6.02187 17.3334C6.36494 22.5454 10.7012 26.6667 16 26.6667C21.5228 26.6667 26 22.1895 26 16.6667C26 11.4103 21.9444 7.10112 16.7916 6.69757C16.7216 6.69209 16.6667 6.63396 16.6667 6.56372V4.98824C16.6667 4.44106 16.0439 4.12689 15.6038 4.45206L11.0765 7.79738C10.7159 8.06387 10.7159 8.60326 11.0766 8.86973L15.6038 12.2147Z" fill="currentColor"/>`;
class PlayButton extends ToggleButton {
static el = defineElement({
tagName: "media-play-button",
props: toggleButtonProps
});
_media;
_keyShortcut = "togglePaused";
onAttach(el) {
this._media = useMedia();
this._pressed = this._isPressed.bind(this);
super.onAttach(el);
setARIALabel(el, this._getLabel.bind(this));
const { paused, ended } = this._media.$store;
this.setAttributes({
"data-paused": paused,
"data-ended": ended
});
}
_onPress(event) {
const remote = this._media.remote;
this._pressed() ? remote.pause(event) : remote.play(event);
}
_isPressed() {
const { paused } = this._media.$store;
return !paused();
}
_getLabel() {
const { paused } = this._media.$store;
return paused() ? "Play" : "Pause";
}
render() {
return [
$$_create_component(Icon, { paths: Icon$59, slot: "play" }),
$$_create_component(Icon, { paths: Icon$71, slot: "replay" }),
$$_create_component(Icon, { paths: Icon$56, slot: "pause" })
];
}
}
var Icon$24 = `<path d="M8 28.0003C8 27.6321 8.29848 27.3336 8.66667 27.3336H23.3333C23.7015 27.3336 24 27.6321 24 28.0003V29.3336C24 29.7018 23.7015 30.0003 23.3333 30.0003H8.66667C8.29848 30.0003 8 29.7018 8 29.3336V28.0003Z" fill="currentColor"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M4.66602 6.66699C4.29783 6.66699 3.99935 6.96547 3.99935 7.33366V24.667C3.99935 25.0352 4.29783 25.3337 4.66602 25.3337H27.3327C27.7009 25.3337 27.9994 25.0352 27.9994 24.667V7.33366C27.9994 6.96547 27.7009 6.66699 27.3327 6.66699H4.66602ZM8.66659 21.3333C8.2984 21.3333 7.99992 21.0349 7.99992 20.6667V11.3333C7.99992 10.9651 8.2984 10.6667 8.66659 10.6667H13.9999C14.3681 10.6667 14.6666 10.9651 14.6666 11.3333V12.6667C14.6666 13.0349 14.3681 13.3333 13.9999 13.3333H10.7999C10.7263 13.3333 10.6666 13.393 10.6666 13.4667V18.5333C10.6666 18.607 10.7263 18.6667 10.7999 18.6667H13.9999C14.3681 18.6667 14.6666 18.9651 14.6666 19.3333V20.6667C14.6666 21.0349 14.3681 21.3333 13.9999 21.3333H8.66659ZM17.9999 21.3333C17.6317 21.3333 17.3333 21.0349 17.3333 20.6667V11.3333C17.3333 10.9651 17.6317 10.6667 17.9999 10.6667H23.3333C23.7014 10.6667 23.9999 10.9651 23.9999 11.3333V12.6667C23.9999 13.0349 23.7014 13.3333 23.3333 13.3333H20.1333C20.0596 13.3333 19.9999 13.393 19.9999 13.4667V18.5333C19.9999 18.607 20.0596 18.6667 20.1333 18.6667H23.3333C23.7014 18.6667 23.9999 18.9651 23.9999 19.3333V20.6667C23.9999 21.0349 23.7014 21.3333 23.3333 21.3333H17.9999Z" fill="currentColor"/>`;
var Icon$25 = `<path fill-rule="evenodd" clip-rule="evenodd" d="M4.6661 6.66699C4.29791 6.66699 3.99943 6.96547 3.99943 7.33366V24.667C3.99943 25.0352 4.29791 25.3337 4.6661 25.3337H27.3328C27.701 25.3337 27.9994 25.0352 27.9994 24.667V7.33366C27.9994 6.96547 27.701 6.66699 27.3328 6.66699H4.6661ZM8.66667 21.3333C8.29848 21.3333 8 21.0349 8 20.6667V11.3333C8 10.9651 8.29848 10.6667 8.66667 10.6667H14C14.3682 10.6667 14.6667 10.9651 14.6667 11.3333V12.6667C14.6667 13.0349 14.3682 13.3333 14 13.3333H10.8C10.7264 13.3333 10.6667 13.393 10.6667 13.4667V18.5333C10.6667 18.607 10.7264 18.6667 10.8 18.6667H14C14.3682 18.6667 14.6667 18.9651 14.6667 19.3333V20.6667C14.6667 21.0349 14.3682 21.3333 14 21.3333H8.66667ZM18 21.3333C17.6318 21.3333 17.3333 21.0349 17.3333 20.6667V11.3333C17.3333 10.9651 17.6318 10.6667 18 10.6667H23.3333C23.7015 10.6667 24 10.9651 24 11.3333V12.6667C24 13.0349 23.7015 13.3333 23.3333 13.3333H20.1333C20.0597 13.3333 20 13.393 20 13.4667V18.5333C20 18.607 20.0597 18.6667 20.1333 18.6667H23.3333C23.7015 18.6667 24 18.9651 24 19.3333V20.6667C24 21.0349 23.7015 21.3333 23.3333 21.3333H18Z" fill="currentColor"/>`;
function ariaBool(value) {
return value ? "true" : "false";
}
function $ariaBool(signal) {
return () => ariaBool(signal());
}
class CaptionButton extends ToggleButton {
static el = defineElement({
tagName: "media-caption-button",
props: toggleButtonProps
});
_media;
_keyShortcut = "toggleCaptions";
onAttach(el) {
this._media = useMedia();
this._pressed = this._isPressed.bind(this);
super.onAttach(el);
setARIALabel(el, this._getLabel.bind(this));
this.setAttributes({
"aria-hidden": $ariaBool(this._isHidden.bind(this))
});
}
_onPress(event) {
this._media.remote.toggleCaptions(event);
}
_isPressed() {
const { textTrack } = this._media.$store, track = textTrack();
return !!track && isTrackCaptionKind(track);
}
_isHidden() {
const { textTracks } = this._media.$store;
return textTracks().filter(isTrackCaptionKind).length == 0;
}
_getLabel() {
const { textTrack } = this._media.$store;
return textTrack() ? "Closed-Captions Off" : "Closed-Captions On";
}
render() {
return [
$$_create_component(Icon, { paths: Icon$24, slot: "on" }),
$$_create_component(Icon, { paths: Icon$25, slot: "off" })
];
}
}
var Icon$37 = `<path d="M19.3334 13.3333C18.9652 13.3333 18.6667 13.0349 18.6667 12.6667L18.6667 7.33333C18.6667 6.96514 18.9652 6.66666 19.3334 6.66666H21.3334C21.7015 6.66666 22 6.96514 22 7.33333V9.86666C22 9.9403 22.0597 10 22.1334 10L24.6667 10C25.0349 10 25.3334 10.2985 25.3334 10.6667V12.6667C25.3334 13.0349 25.0349 13.3333 24.6667 13.3333L19.3334 13.3333Z" fill="currentColor"/> <path d="M13.3334 19.3333C13.3334 18.9651 13.0349 18.6667 12.6667 18.6667H7.33335C6.96516 18.6667 6.66669 18.9651 6.66669 19.3333V21.3333C6.66669 21.7015 6.96516 22 7.33335 22H9.86669C9.94032 22 10 22.0597 10 22.1333L10 24.6667C10 25.0349 10.2985 25.3333 10.6667 25.3333H12.6667C13.0349 25.3333 13.3334 25.0349 13.3334 24.6667L13.3334 19.3333Z" fill="currentColor"/> <path d="M18.6667 24.6667C18.6667 25.0349 18.9652 25.3333 19.3334 25.3333H21.3334C21.7015 25.3333 22 25.0349 22 24.6667V22.1333C22 22.0597 22.0597 22 22.1334 22H24.6667C25.0349 22 25.3334 21.7015 25.3334 21.3333V19.3333C25.3334 18.9651 25.0349 18.6667 24.6667 18.6667L19.3334 18.6667C18.9652 18.6667 18.6667 18.9651 18.6667 19.3333L18.6667 24.6667Z" fill="currentColor"/> <path d="M10.6667 13.3333H12.6667C13.0349 13.3333 13.3334 13.0349 13.3334 12.6667L13.3334 10.6667V7.33333C13.3334 6.96514 13.0349 6.66666 12.6667 6.66666H10.6667C10.2985 6.66666 10 6.96514 10 7.33333L10 9.86666C10 9.9403 9.94033 10 9.86669 10L7.33335 10C6.96516 10 6.66669 10.2985 6.66669 10.6667V12.6667C6.66669 13.0349 6.96516 13.3333 7.33335 13.3333L10.6667 13.3333Z" fill="currentColor"/>`;
var Icon$38 = `<path d="M25.3299 7.26517C25.2958 6.929 25.0119 6.66666 24.6667 6.66666H19.3334C18.9652 6.66666 18.6667 6.96514 18.6667 7.33333V9.33333C18.6667 9.70152 18.9652 10 19.3334 10L21.8667 10C21.9403 10 22 10.0597 22 10.1333V12.6667C22 13.0349 22.2985 13.3333 22.6667 13.3333H24.6667C25.0349 13.3333 25.3334 13.0349 25.3334 12.6667V7.33333C25.3334 7.31032 25.3322 7.28758 25.3299 7.26517Z" fill="currentColor"/> <path d="M22 21.8667C22 21.9403 21.9403 22 21.8667 22L19.3334 22C18.9652 22 18.6667 22.2985 18.6667 22.6667V24.6667C18.6667 25.0349 18.9652 25.3333 19.3334 25.3333L24.6667 25.3333C25.0349 25.3333 25.3334 25.0349 25.3334 24.6667V19.3333C25.3334 18.9651 25.0349 18.6667 24.6667 18.6667H22.6667C22.2985 18.6667 22 18.9651 22 19.3333V21.8667Z" fill="currentColor"/> <path d="M12.6667 22H10.1334C10.0597 22 10 21.9403 10 21.8667V19.3333C10 18.9651 9.70154 18.6667 9.33335 18.6667H7.33335C6.96516 18.6667 6.66669 18.9651 6.66669 19.3333V24.6667C6.66669 25.0349 6.96516 25.3333 7.33335 25.3333H12.6667C13.0349 25.3333 13.3334 25.0349 13.3334 24.6667V22.6667C13.3334 22.2985 13.0349 22 12.6667 22Z" fill="currentColor"/> <path d="M10 12.6667V10.1333C10 10.0597 10.0597 10 10.1334 10L12.6667 10C13.0349 10 13.3334 9.70152 13.3334 9.33333V7.33333C13.3334 6.96514 13.0349 6.66666 12.6667 6.66666H7.33335C6.96516 6.66666 6.66669 6.96514 6.66669 7.33333V12.6667C6.66669 13.0349 6.96516 13.3333 7.33335 13.3333H9.33335C9.70154 13.3333 10 13.0349 10 12.6667Z" fill="currentColor"/>`;
class FullscreenButton extends ToggleButton {
static el = defineElement({
tagName: "media-fullscreen-button",
props: {
...toggleButtonProps,
target: "prefer-media"
}
});
_media;
_keyShortcut = "toggleFullscreen";
onAttach(el) {
this._media = useMedia();
this._pressed = this._isPressed.bind(this);
super.onAttach(el);
setARIALabel(el, this._getLabel.bind(this));
const { fullscreen } = this._media.$store;
this.setAttributes({
"aria-hidden": $ariaBool(this._isHidden.bind(this)),
"data-fullscreen": fullscreen
});
}
_onPress(event) {
const remote = this._media.remote, target = this.$props.target();
this._pressed() ? remote.exitFullscreen(target, event) : remote.enterFullscreen(target, event);
}
_isPressed() {
const { fullscreen } = this._media.$store;
return fullscreen();
}
_isHidden() {
const { canFullscreen } = this._media.$store;
return !canFullscreen();
}
_getLabel() {
const { fullscreen } = this._media.$store;
return fullscreen() ? "Exit Fullscreen" : "Enter Fullscreen";
}
render() {
return [
$$_create_component(Icon, { paths: Icon$38, slot: "enter" }),
$$_create_component(Icon, { paths: Icon$37, slot: "exit" })
];
}
}
var Icon$52 = `<path d="M17.5091 24.6594C17.5091 25.2066 16.8864 25.5208 16.4463 25.1956L9.44847 20.0252C9.42553 20.0083 9.39776 19.9991 9.36923 19.9991H4.66667C4.29848 19.9991 4 19.7006 4 19.3325V12.6658C4 12.2976 4.29848 11.9991 4.66667 11.9991H9.37115C9.39967 11.9991 9.42745 11.99 9.45039 11.973L16.4463 6.8036C16.8863 6.47842 17.5091 6.79259 17.5091 7.33977L17.5091 24.6594Z" fill="currentColor"/> <path d="M28.8621 13.6422C29.1225 13.3818 29.1225 12.9597 28.8621 12.6994L27.9193 11.7566C27.659 11.4962 27.2368 11.4962 26.9765 11.7566L24.7134 14.0197C24.6613 14.0717 24.5769 14.0717 24.5248 14.0197L22.262 11.7568C22.0016 11.4964 21.5795 11.4964 21.3191 11.7568L20.3763 12.6996C20.116 12.9599 20.116 13.382 20.3763 13.6424L22.6392 15.9053C22.6913 15.9573 22.6913 16.0418 22.6392 16.0938L20.3768 18.3562C20.1165 18.6166 20.1165 19.0387 20.3768 19.299L21.3196 20.2419C21.58 20.5022 22.0021 20.5022 22.2624 20.2418L24.5248 17.9795C24.5769 17.9274 24.6613 17.9274 24.7134 17.9795L26.976 20.2421C27.2363 20.5024 27.6585 20.5024 27.9188 20.2421L28.8616 19.2992C29.122 19.0389 29.122 18.6168 28.8616 18.3564L26.599 16.0938C26.547 16.0418 26.547 15.9573 26.599 15.9053L28.8621 13.6422Z" fill="currentColor"/>`;
var Icon$101 = `<path d="M17.5091 24.6595C17.5091 25.2066 16.8864 25.5208 16.4463 25.1956L9.44847 20.0252C9.42553 20.0083 9.39776 19.9992 9.36923 19.9992H4.66667C4.29848 19.9992 4 19.7007 4 19.3325V12.6658C4 12.2976 4.29848 11.9992 4.66667 11.9992H9.37115C9.39967 11.9992 9.42745 11.99 9.45039 11.9731L16.4463 6.80363C16.8863 6.47845 17.5091 6.79262 17.5091 7.3398L17.5091 24.6595Z" fill="currentColor"/> <path d="M27.5091 9.33336C27.8773 9.33336 28.1758 9.63184 28.1758 10V22C28.1758 22.3682 27.8773 22.6667 27.5091 22.6667H26.1758C25.8076 22.6667 25.5091 22.3682 25.5091 22V10C25.5091 9.63184 25.8076 9.33336 26.1758 9.33336L27.5091 9.33336Z" fill="currentColor"/> <path d="M22.1758 12C22.544 12 22.8424 12.2985 22.8424 12.6667V19.3334C22.8424 19.7016 22.544 20 22.1758 20H20.8424C20.4743 20 20.1758 19.7016 20.1758 19.3334V12.6667C20.1758 12.2985 20.4743 12 20.8424 12H22.1758Z" fill="currentColor"/>`;
var Icon$102 = `<path d="M17.5091 24.6594C17.5091 25.2066 16.8864 25.5207 16.4463 25.1956L9.44847 20.0252C9.42553 20.0083 9.39776 19.9991 9.36923 19.9991H4.66667C4.29848 19.9991 4 19.7006 4 19.3324V12.6658C4 12.2976 4.29848 11.9991 4.66667 11.9991H9.37115C9.39967 11.9991 9.42745 11.99 9.45039 11.973L16.4463 6.80358C16.8863 6.4784 17.5091 6.79258 17.5091 7.33975L17.5091 24.6594Z" fill="currentColor"/> <path d="M22.8424 12.6667C22.8424 12.2985 22.544 12 22.1758 12H20.8424C20.4743 12 20.1758 12.2985 20.1758 12.6667V19.3333C20.1758 19.7015 20.4743 20 20.8424 20H22.1758C22.544 20 22.8424 19.7015 22.8424 19.3333V12.6667Z" fill="currentColor"/>`;
class MuteButton extends ToggleButton {
static el = defineElement({
tagName: "media-mute-button",
props: toggleButtonProps
});
_media;
_keyShortcut = "toggleMuted";
onAttach(el) {
this._media = useMedia();
this._pressed = this._isPressed.bind(this);
setARIALabel(el, this._getLabel.bind(this));
this.setAttributes({
"data-muted": this._pressed,
"data-volume": this._getVolumeText.bind(this)
});
super.onAttach(el);
}
_onPress(event) {
const remote = this._media.remote;
this._pressed() ? remote.unmute(event) : remote.mute(event);
}
_isPressed() {
const { muted, volume } = this._media.$store;
return muted() || volume() === 0;
}
_getLabel() {
return this._pressed() ? "Unmute" : "Mute";
}
_getVolumeText() {
const { muted, volume } = this._media.$store, $volume = volume();
if (muted() || $volume === 0)
return "muted";
else if ($volume >= 0.5)
return "high";
else if ($volume < 0.5)
return "low";
}
render() {
return [
$$_create_component(Icon, { paths: Icon$101, slot: "volume-high" }),
$$_create_component(Icon, { paths: Icon$102, slot: "volume-low" }),
$$_create_component(Icon, { paths: Icon$52, slot: "volume-muted" })
];
}
}
var Icon$57 = `<path d="M5.33334 26V19.4667C5.33334 19.393 5.39304 19.3333 5.46668 19.3333H7.86668C7.94031 19.3333 8.00001 19.393 8.00001 19.4667V23.3333C8.00001 23.7015 8.29849 24 8.66668 24H23.3333C23.7015 24 24 23.7015 24 23.3333V8.66666C24 8.29847 23.7015 7.99999 23.3333 7.99999H19.4667C19.393 7.99999 19.3333 7.9403 19.3333 7.86666V5.46666C19.3333 5.39302 19.393 5.33333 19.4667 5.33333H26C26.3682 5.33333 26.6667 5.63181 26.6667 5.99999V26C26.6667 26.3682 26.3682 26.6667 26 26.6667H6.00001C5.63182 26.6667 5.33334 26.3682 5.33334 26Z" fill="currentColor"/> <path d="M14.0098 8.42359H10.806C10.6872 8.42359 10.6277 8.56721 10.7117 8.6512L16.5491 14.4886C16.8094 14.7489 16.8094 15.171 16.5491 15.4314L15.3234 16.657C15.0631 16.9174 14.641 16.9174 14.3806 16.657L8.63739 10.9138C8.55339 10.8298 8.40978 10.8893 8.40978 11.0081V14.0236C8.40978 14.3918 8.1113 14.6903 7.74311 14.6903H6.00978C5.64159 14.6903 5.34311 14.3918 5.34311 14.0236L5.34311 6.02359C5.34311 5.6554 5.64159 5.35692 6.00978 5.35692L14.0098 5.35692C14.378 5.35692 14.6764 5.6554 14.6764 6.02359V7.75692C14.6764 8.12511 14.378 8.42359 14.0098 8.42359Z" fill="currentColor"/>`;
var Icon$58 = `<path d="M16 15.3333C15.6318 15.3333 15.3333 15.6318 15.3333 16V20C15.3333 20.3682 15.6318 20.6667 16 20.6667H21.3333C21.7015 20.6667 22 20.3682 22 20V16C22 15.6318 21.7015 15.3333 21.3333 15.3333H16Z" fill="currentColor"/> <path fill-rule="evenodd" clip-rule="evenodd" d="M5.33333 7.33334C5.33333 6.96515 5.63181 6.66667 5.99999 6.66667H26C26.3682 6.66667 26.6667 6.96515 26.6667 7.33334V24.6667C26.6667 25.0349 26.3682 25.3333 26 25.3333H5.99999C5.63181 25.3333 5.33333 25.0349 5.33333 24.6667V7.33334ZM7.99999 10C7.99999 9.63182 8.29847 9.33334 8.66666 9.33334H23.3333C23.7015 9.33334 24 9.63182 24 10V22C24 22.3682 23.7015 22.6667 23.3333 22.6667H8.66666C8.29847 22.6667 7.99999 22.3682 7.99999 22V10Z" fill="currentColor"/>`;
class PIPButton extends ToggleButton {
static el = defineElement({
tagName: "media-pip-button",
props: toggleButtonProps
});
_media;
_keyShortcut = "togglePictureInPicture";
onAttach(el) {
this._media = useMedia();
this._pressed = this._isPressed.bind(this);
super.onAttach(el);
setARIALabel(el, this._getLabel.bind(this));
const { pictureInPicture } = this._media.$store;
this.setAttributes({
"aria-hidden": $ariaBool(this._isHidden.bind(this)),
"data-pip": pictureInPicture
});
}
_onPress(event) {
const remote = this._media.remote;
this._pressed() ? remote.exitPictureInPicture(event) : remote.enterPictureInPicture(event);
}
_isPressed() {
const { pictureInPicture } = this._media.$store;
return pictureInPicture();
}
_isHidden() {
const { canPictureInPicture } = this._media.$store;
return !canPictureInPicture();
}
_getLabel() {
const { pictureInPicture } = this._media.$store;
return pictureInPicture() ? "Exit Picture In Picture" : "Enter Picture In Picture";
}
render() {
return [
$$_create_component(Icon, { paths: Icon$58, slot: "enter" }),
$$_create_component(Icon, { paths: Icon$57, slot: "exit" })
];
}
}
var Icon$77 = `<path d="M15.6038 12.2148C16.0439 12.5399 16.6667 12.2257 16.6667 11.6786V10.1789C16.6667 10.1001 16.7351 10.0384 16.8134 10.0479C20.1116 10.4494 22.6667 13.2593 22.6667 16.6659C22.6667 20.3481 19.6817 23.3332 15.9995 23.3332C12.542 23.3332 9.69927 20.7015 9.36509 17.332C9.32875 16.9655 9.03371 16.6662 8.66548 16.6662L6.66655 16.6666C6.29841 16.6666 5.99769 16.966 6.02187 17.3334C6.36494 22.5454 10.7012 26.6667 16 26.6667C21.5228 26.6667 26 22.1895 26 16.6667C26 11.4103 21.9444 7.10112 16.7916 6.69758C16.7216 6.69209 16.6667 6.63396 16.6667 6.56372V4.98824C16.6667 4.44106 16.0439 4.12689 15.6038 4.45207L11.0765 7.79738C10.7159 8.06387 10.7159 8.60327 11.0766 8.86974L15.6038 12.2148Z" fill="currentColor"/>`;
var Icon$81 = `<path d="M16.4167 12.2148C15.9766 12.5399 15.3538 12.2257 15.3538 11.6786V10.1789C15.3538 10.1001 15.2854 10.0384 15.2072 10.0479C11.9089 10.4494 9.35384 13.2593 9.35384 16.6659C9.35384 20.3481 12.3389 23.3332 16.0211 23.3332C19.4785 23.3332 22.3212 20.7015 22.6554 17.332C22.6918 16.9655 22.9868 16.6662 23.355 16.6662L25.354 16.6666C25.7221 16.6666 26.0228 16.966 25.9986 17.3334C25.6556 22.5454 21.3193 26.6667 16.0205 26.6667C10.4977 26.6667 6.02051 22.1895 6.02051 16.6667C6.02051 11.4103 10.0761 7.10112 15.2289 6.69758C15.2989 6.69209 15.3538 6.63396 15.3538 6.56372V4.98824C15.3538 4.44106 15.9766 4.12689 16.4167 4.45207L20.944 7.79738C21.3046 8.06387 21.3046 8.60327 20.9439 8.86974L16.4167 12.2148Z" fill="currentColor"/>`;
class SeekButton extends Component {
static el = defineElement({
tagName: "media-seek-button",
props: {
disabled: false,
defaultAppearance: false,
seconds: 30
}
});
_media;
constructor(instance) {
super(instance);
this._media = useMedia();
new FocusVisibleController(instance);
new TooltipController(instance);
}
onAttach(el) {
setAttributeIfEmpty(el, "tabindex", "0");
setAttributeIfEmpty(el, "role", "button");
setARIALabel(el, this._getLabel.bind(this));
const { seconds, defaultAppearance } = this.$props;
this.setAttributes({
seconds,
"default-appearance": defaultAppearance,
"aria-hidden": $ariaBool(this._isHidden.bind(this)),
"data-media-button": true
});
}
onConnect(el) {
onPress(el, this._onPress.bind(this));
}
_isHidden() {
const { canSeek } = this._media.$store;
return !canSeek();
}
_getLabel() {
const { seconds } = this.$props;
return `Seek ${seconds() > 0 ? "forward" : "backward"} ${seconds()} seconds`;
}
_onPress(event) {
const { seconds, disabled } = this.$props;
if (disabled())
return;
const { currentTime } = this._media.$store, seekTo = currentTime() + seconds();
this._media.remote.seek(seekTo, event);
}
render() {
return [
$$_create_component(Icon, { paths: Icon$77, slot: "backward" }),
$$_create_component(Icon, { paths: Icon$81, slot: "forward" })
];
}
}
const SliderStoreFactory = new StoreFactory({
min: 0,
max: 100,
value: 50,
pointerValue: 0,
focused: false,
dragging: false,
pointing: false,
get interactive() {
return this.dragging || this.focused || this.pointing;
},
get fillRate() {
return calcRate(this.min, this.max, this.value);
},
get fillPercent() {
return this.fillRate * 100;
},
get pointerRate() {
return calcRate(this.min, this.max, this.pointerValue);
},
get pointerPercent() {
return this.pointerRate * 100;
}
});
function calcRate(min, max, value) {
const range = max - min, offset = value - min;
return range > 0 ? offset / range : 0;
}
const sliderProps = {
min: 0,
max: 100,
disabled: false,
value: 100,
step: 1,
keyStep: 1,
shiftKeyMultiplier: 5,
trackClass: null,
trackFillClass: null,
trackProgressClass: null,
thumbContainerClass: null,
thumbClass: null
};
function getClampedValue(min, max, value, step) {
return clampNumber(min, round(value, getNumberOfDecimalPlaces(step)), max);
}
function getValueFromRate(min, max, rate, step) {
const boundRate = clampNumber(0, rate, 1), range = max - min, fill = range * boundRate, stepRatio = fill / step, steps = step * stepRatio;
return min + steps;
}
const SliderKeyDirection = {
Left: -1,
ArrowLeft: -1,
Up: 1,
ArrowUp: 1,
Right: 1,
ArrowRight: 1,
Down: -1,
ArrowDown: -1
};
class SliderEventsController extends ComponentController {
constructor(instance, _delegate, _media) {
super(instance);
this._delegate = _delegate;
this._media = _media;
}
onConnect() {
effect(this._attachEventListeners.bind(this));
effect(this._attachPointerListeners.bind(this));
if (this._delegate._swipeGesture) {
scopedRaf(() => {
const outlet = this._media.player?.querySelector("media-outlet");
if (outlet) {
this._outlet = outlet;
listenEvent(outlet, "touchstart", this._onTouchStart.bind(this));
listenEvent(outlet, "touchmove", this._onTouchMove.bind(this));
}
});
}
}
_outlet = null;
_touchX = null;
_touchStartValue = null;
_onTouchStart(event) {
this._touchX = event.touches[0].clientX;
}
_onTouchMove(event) {
if (isNull(this._touchX))
return;
event.preventDefault();
if (this.$store.dragging())
return;
const diff = event.touches[0].clientX - this._touchX;
if (Math.abs(diff) > 20) {
this._touchX = event.touches[0].clientX;
this._touchStartValue = this.$store.value();
this._onStartDragging(this._touchStartValue, event);
}
}
_attachEventListeners() {
if (this._delegate._isDisabled())
return;
this.listen("focus", this._onFocus.bind(this));
this.listen("pointerenter", this._onPointerEnter.bind(this));
this.listen("pointermove", this._onPointerMove.bind(this));
this.listen("pointerleave", this._onPointerLeave.bind(this));
this.listen("pointerdown", this._onPointerDown.bind(this));
this.listen("keydown", this._onKeyDown.bind(this));
this.listen("keyup", this._onKeyUp.bind(this));
}
_attachPointerListeners() {
if (this._delegate._isDisabled() || !this.$store.dragging())
return;
listenEvent(document, "pointerup", this._onDocumentPointerUp.bind(this));
listenEvent(document, "pointermove", this._onDocumentPointerMove.bind(this));
if (IS_SAFARI) {
listenEvent(document, "touchmove", this._onDocumentTouchMove.bind(this), {
passive: false
});
}
}
_onFocus() {
this._updatePointerValue(this.$store.value());
}
_updateValue(newValue, trigger) {
const { value, min, max, dragging } = this.$store;
const clampedValue = Math.max(min(), Math.min(newValue, max()));
value.set(clampedValue);
const event = this.createEvent("value-change", { detail: clampedValue, trigger });
this.el.dispatchEvent(event);
this._delegate._onValueChange(event);
if (dragging()) {
const event2 = this.createEvent("drag-value-change", { detail: clampedValue, trigger });
this.el.dispatchEvent(event2);
this._delegate._onDragValueChange(event2);
}
}
_updatePointerValue(value, trigger) {
const { pointerValue, dragging } = this.$store;
pointerValue.set(value);
this.dispatch("pointer-value-change", { detail: value, trigger });
if (dragging()) {
const dir = this._delegate._orientation === "vertical" ? "bottom" : "left", size = this._delegate._orientation === "vertical" ? "height" : "width";
if (this._trackFill && !this.el?.hasAttribute("data-chapters")) {
this._trackFill.style[size] = value + "%";
}
if (this._thumb) {
this._thumb.style[dir] = value + "%";
}
this._updateValue(value, trigger);
}
}
_getPointerValue(event) {
let thumbPositionRate, rect = this.el.getBoundingClientRect(), { min, max } = this.$store;
if (this._delegate._orientation === "vertical") {
const { bottom: trackBottom, height: trackHeight } = rect;
thumbPositionRate = (trackBottom - event.clientY) / trackHeight;
} else {
if (this._touchX && isNumber(this._touchStartValue)) {
const { width } = this._outlet.getBoundingClientRect(), rate = (event.clientX - this._touchX) / width, range = max() - min(), diff = range * Math.abs(rate);
thumbPositionRate = (rate < 0 ? this._touchStartValue - diff : this._touchStartValue + diff) / range;
} else {
const { left: trackLeft, width: trackWidth } = rect;
thumbPositionRate = (event.clientX - trackLeft) / trackWidth;
}
}
return Math.max(
min(),
Math.min(
max(),
this._delegate._roundValue(
getValueFromRate(min(), max(), thumbPositionRate, this._delegate._getStep())
)
)
);
}
_onPointerEnter(event) {
this.$store.pointing.set(true);
}
_onPointerMove(event) {
const { dragging } = this.$store;
if (dragging())
return;
this._updatePointerValue(this._getPointerValue(event), event);
}
_onPointerLeave(event) {
this.$store.pointing.set(false);
}
_onPointerDown(event) {
if (event.button !== 0)
return;
const value = this._getPointerValue(event);
this._onStartDragging(value, event);
this._updatePointerValue(value, event);
}
_thumb = null;
_trackFill = null;
_onStartDragging(value, trigger) {
const { dragging } = this.$store;
if (dragging())
return;
dragging.set(true);
this._thumb = this.el.querySelector(
'shadow-root > div[part="thumb-container"]'
);
this._trackFill = this.el.querySelector(
'shadow-root > div[part~="track-fill"]'
);
this._media.remote.pauseUserIdle(trigger);
const event = this.createEvent("drag-start", { detail: value, trigger });
this.el.dispatchEvent(event);
this._delegate._onDragStart(event);
}
_onStopDragging(value, trigger) {
const { dragging } = this.$store;
if (!dragging())
return;
dragging.set(false);
if (this._trackFill) {
setStyle(this._trackFill, "width", null);
this._trackFill = null;
}
if (this._thumb) {
setStyle(this._thumb, "left", null);
setStyle(this._thumb, "bottom", null);
this._thumb = null;
}
this._media.remote.resumeUserIdle(trigger);
const event = this.createEvent("drag-end", { detail: value, trigger });
this.el.dispatchEvent(event);
this._delegate._onDragEnd(event);
this._touchX = null;
this._touchStartValue = null;
}
// -------------------------------------------------------------------------------------------
// Keyboard Events
// -------------------------------------------------------------------------------------------
_lastDownKey;
_onKeyDown(event) {
if (isDOMEvent(event)) {
const trigger = event.trigger;
if (isKeyboardEvent(trigger))
event = trigger;
else
return;
}
const { key } = event;
const { min, max } = this.$store;
let newValue;
if (key === "Home" || key === "PageUp") {
newValue = min();
} else if (key === "End" || key === "PageDown") {
newValue = max();
} else if (!event.metaKey && /[0-9]/.test(key)) {
newValue = (max() - min()) / 10 * Number(key);
}
if (!isUndefined(newValue)) {
this._updatePointerValue(newValue, event);
this._updateValue(newValue, event);
return;
}
const value = this._getKeyValue(event);
if (!value)
return;
const repeat = key === this._lastDownKey;
if (!this.$store.dragging() && repeat)
this._onStartDragging(value, event);
this._updatePointerValue(value, event);
if (!repeat)
this._updateValue(value, event);
this._lastDownKey = key;
}
_onKeyUp(event) {
if (isDOMEvent(event)) {
const trigger = event.trigger;
if (isKeyboardEvent(trigger))
event = trigger;
else
return;
}
this._lastDownKey = "";
const { dragging, value } = this.$store;
if (!dragging())
return;
const newValue = this._getKeyValue(event) ?? value();
this._updatePointerValue(newValue);
this._onStopDragging(newValue, event);
}
_getKeyValue(event) {
const { key, shiftKey } = event, isValidKey = Object.keys(SliderKeyDirection).includes(key);
if (!isValidKey)
return;
const { shiftKeyMultiplier } = this.$props;
const { value } = this.$store, step = this._delegate._getStep(), keyStep = this._delegate._getKeyStep();
const modifiedStep = !shiftKey ? keyStep : keyStep * shiftKeyMultiplier(), direction = Number(SliderKeyDirection[key]), diff = modifiedStep * direction, steps = (value() + diff) / step;
return Number((step * steps).toFixed(3));
}
// -------------------------------------------------------------------------------------------
// Document (Pointer Events)
// -------------------------------------------------------------------------------------------
_onDocumentPointerUp(event) {
if (event.button !== 0)
return;
const value = this._getPointerValue(event);
this._updatePointerValue(value, event);
this._onStopDragging(value, event);
}
_onDocumentTouchMove(event) {
event.preventDefault();
}
_onDocumentPointerMove = functionThrottle(
(event) => {
this._updatePointerValue(this._getPointerValue(event), event);
},
20,
{ leading: true }
);
}
const sliderValueFormatContext = createContext(() => ({}));
const $$_templ$h = /* @__PURE__ */ $$_create_template(`<!$><div part="track"></div>`), $$_templ_2$6 = /* @__PURE__ */ $$_create_template(`<!$><div part="track track-fill"></div>`), $$_templ_3$1 = /* @__PURE__ */ $$_create_template(`<!$><div part="track track-progress"></div>`), $$_templ_4 = /* @__PURE__ */ $$_create_template(`<!$><div part="thumb-container"><!$><div part="thumb"></div></div>`);
class Slider extends Component {
static el = defineElement({
tagName: "media-slider",
props: sliderProps,
store: SliderStoreFactory
});
_media;
_readonly = false;
_orientation = "";
constructor(instance) {
super(instance);
provideContext(sliderValueFormatContext);
this._media = useMedia();
new SliderEventsController(instance, this, this._media);
const focus = new FocusVisibleController(instance);
this.$store.focused = focus.focused.bind(focus);
}
onAttach(el) {
setAttributeIfEmpty(el, "role", "slider");
setAttributeIfEmpty(el, "tabindex", "0");
setAttributeIfEmpty(el, "aria-orientation", "horizontal");
setAttributeIfEmpty(el, "autocomplete", "off");
this._orientation = el.getAttribute("aria-orientation") || "";
if (!this._readonly) {
effect(this._watchMinMax.bind(this));
effect(this._watchDisabled.bind(this));
}
effect(this._watchValue.bind(this));
this._setAttrs();
}
onConnect(el) {
this._setupPreview();
}
render() {
const { trackClass, trackFillClass, trackProgressClass, thumbContainerClass, thumbClass } = this.$props;
return [
(() => {
const [$$_root, $$_walker] = $$_create_walker($$_templ$h);
$$_effect(() => $$_attr($$_root, "class", trackClass()));
return $$_root;
})(),
(() => {
const [$$_root, $$_walker] = $$_create_walker($$_templ_2$6);
$$_effect(() => $$_attr($$_root, "class", trackFillClass()));
return $$_root;
})(),
(() => {
const [$$_root, $$_walker] = $$_create_walker($$_templ_3$1);
$$_effect(() => $$_attr($$_root, "class", trackProgressClass()));
return $$_root;
})(),
(() => {
const [$$_root, $$_walker] = $$_create_walker($$_templ_4), $$_el = $$_next_element($$_walker);
$$_effect(() => $$_attr($$_root, "class", thumbContainerClass()));
$$_effect(() => $$_attr($$_el, "class", thumbClass()));
return $$_root;
})()
];
}
// -------------------------------------------------------------------------------------------
// Props
// -------------------------------------------------------------------------------------------
_getStep() {
return this.$props.step();
}
_getKeyStep() {
return this.$props.keyStep();
}
_roundValue(value) {
return Math.round(value);
}
_isDisabled() {
return this.$props.disabled();
}
// -------------------------------------------------------------------------------------------
// Watch
// -------------------------------------------------------------------------------------------
_watchMinMax() {
const { min, max } = this.$props;
this.$store.min.set(min());
this.$store.max.set(max());
}
_watchDisabled() {
if (!this._isDisabled())
return;
const { dragging, pointing } = this.$store;
dragging.set(false);
pointing.set(false);
}
_watchValue() {
const { dragging, value, min, max } = this.$store;
if (peek(dragging))
return;
value.set(getClampedValue(min(), max(), value(), this._getStep()));
}
// -------------------------------------------------------------------------------------------
// ARIA
// -------------------------------------------------------------------------------------------
_getARIADisabled() {
return ariaBool$1(this._isDisabled());
}
_getARIAValueMin() {
return this.$props.min();
}
_getARIAValueMax() {
return this.$props.max();
}
_getARIAValueNow() {
const { value } = this.$store;
return Math.round(value());
}
_getARIAValueText() {
const { value, max } = this.$store;
return round(value() / max() * 100, 2) + "%";
}
// -------------------------------------------------------------------------------------------
// Attributes
// -------------------------------------------------------------------------------------------
_setAttrs() {
const { disabled } = this.$props, { dragging, interactive, pointing } = this.$store;
this.setAttributes({
disabled,
"data-dragging": dragging,
"data-pointing": pointing,
"data-interactive": interactive,
"aria-disabled": this._getARIADisabled.bind(this),
"aria-valuemin": this._getARIAValueMin.bind(this),
"aria-valuemax": this._getARIAValueMax.bind(this),
"aria-valuenow": this._getARIAValueNow.bind(this),
"aria-valuetext": this._getARIAValueText.bind(this),
"data-styled": this._isStyled.bind(this),
"data-media-slider": true
});
effect(this._watchCSSVars.bind(this));
}
_isStyled() {
return !!this.$props.trackClass();
}
_watchCSSVars() {
const { fillPercent, pointerPercent } = this.$store;
this._updateSliderVars(round(fillPercent(), 3), round(pointerPercent(), 3));
}
_updateSliderVars = animationFrameThrottle(
(fillPercent, pointerPercent) => {
this.el?.style.setProperty("--slider-fill-percent", fillPercent + "%");
this.el?.style.setProperty("--slider-pointer-percent", pointerPercent + "%");
}
);
// -------------------------------------------------------------------------------------------
// Preview
// -------------------------------------------------------------------------------------------
_preview = null;
_setupPreview() {
this._preview = this.el.querySelector('[slot="preview"]');
if (!this._preview)
return;
effect(this._watchPreview.bind(this));
Promise.resolve().then(function () { return preview; }).then(({ setupPreviewStyles }) => {
setupPreviewStyles(this._preview, this._orientation);
});
}
_watchPreview() {
if (this._isDisabled() || !this._preview)
return;
window.requestAnimationFrame(this._onPreviewResize);
const observer = new ResizeObserver(this._onPreviewResize);
observer.observe(this._preview);
return () => observer.disconnect();
}
_onPreviewResize = animationFrameThrottle(() => {
if (!this._preview)
return;
const rect = this._preview.getBoundingClientRect();
setStyle(this._preview, "--computed-width", rect.width + "px");
setStyle(this._preview, "--computed-height", rect.height + "px");
});
// -------------------------------------------------------------------------------------------
// Events
// -------------------------------------------------------------------------------------------
_onValueChange(event) {
}
_onDragStart(event) {
}
_onDragEnd(event) {
}
_onDragValueChange(event) {
}
}
const $$_templ$g = /* @__PURE__ */ $$_create_template(`<!$><img part="img" loading="eager" decoding="async" aria-hidden="true" />`);
class Thumbnail extends Component {
static el = defineElement({
tagName: "media-thumbnail",
props: { time: 0 }
});
_media;
_img = null;
_coords = null;
_styleResets = [];
_src = signal("");
_loaded = signal(false);
_activeCue = signal(null);
constructor(instance) {
super(instance);
this._media = useMedia();
}
onAttach() {
this.setAttributes({
"data-loading": this._isLoading.bind(this),
"aria-hidden": $ariaBool(this._isHidden.bind(this))
});
}
onConnect() {
effect(this._onLoadStart.bind(this));
effect(this._onFindActiveCue.bind(this));
effect(this._onResolveThumbnail.bind(this));
}
_onLoadStart() {
this._src();
this._media.$store.thumbnails();
this._loaded.set(false);
}
_onLoaded() {
this._loaded.set(true);
this._requestResize();
}
_isLoading() {
return !this._isHidden() && !this._loaded();
}
_isHidden() {
const { duration, thumbnailCues } = this._media.$store;
return !Number.isFinite(duration()) || thumbnailCues().length === 0;
}
_onFindActiveCue() {
const { time } = this.$props, { duration, thumbnailCues } = this._media.$store, _cues = thumbnailCues(), _time = time();
if (!_cues || !Number.isFinite(duration())) {
this._activeCue.set(null);
return;
}
this._activeCue.set(findActiveCue(_time, _cues));
}
_onImgRef(el) {
this._img = el;
}
_onResolveThumbnail() {
const activeCue = this._activeCue(), thumbnails = peek(this._media.$store.thumbnails);
if (!thumbnails || !activeCue) {
this._src.set("");
this._resetStyles();
return;
}
const [_src, _coords = ""] = (activeCue.text || "").split("#");
this._coords = this._resolveThumbnailCoords(_coords);
if (!this._coords) {
this._resetStyles();
return;
}
this._src.set(this._resolveThumbnailSrc(thumbnails, _src));
this._requestResize();
}
_resolveThumbnailSrc(baseURL, src) {
return !/https?:/.test(src) ? `${baseURL.split("/").slice(0, -1).join("/")}${src.replace(/^\/?/, "/")}`.replace(
/^\/\//,
"/"
) : src;
}
_resolveThumbnailCoords(coords) {
const [props, values] = coords.split("="), resolvedCoords = {}, coordValues = values?.split(",");
if (!props || !values)
return null;
for (let i = 0; i < props.length; i++)
resolvedCoords[props[i]] = +coordValues[i];
return resolvedCoords;
}
_requestResize = animationFrameThrottle(this._resize.bind(this));
_resize() {
if (!this._img || !this._coords || !this.el)
return;
const { w, h, x, y } = this._coords, { maxWidth, maxHeight, minWidth, minHeight } = getComputedStyle(this.el), minRatio = Math.max(parseInt(minWidth) / w, parseInt(minHeight) / h), maxRatio = Math.min(parseInt(maxWidth) / w, parseInt(maxHeight) / h), scale = maxRatio < 1 ? maxRatio : minRatio > 1 ? minRatio : 1;
this._style(this.el, "--thumbnail-width", `${w * scale}px`);
this._style(this.el, "--thumbnail-height", `${h * scale}px`);
this._style(this._img, "width", `${this._img.naturalWidth * scale}px`);
this._style(this._img, "height", `${this._img.naturalHeight * scale}px`);
this._style(this._img, "transform", `translate(-${x * scale}px, -${y * scale}px)`);
}
_style(el, name, value) {
el.style.setProperty(name, value);
this._styleResets.push(() => el.style.removeProperty(name));
}
_resetStyles() {
for (const reset of this._styleResets)
reset();
this._styleResets = [];
}
render() {
const { crossorigin } = this._media.$store;
return (() => {
const [$$_root, $$_walker] = $$_create_walker($$_templ$g);
$$_effect(() => $$_attr($$_root, "src", this._src()));
$$_effect(() => $$_attr($$_root, "crossorigin", crossorigin()));
$$_listen($$_root, "load", this._onLoaded.bind(this));
$$_ref($$_root, this._onImgRef.bind(this));
return $$_root;
})();
}
}
const $$_templ$f = /* @__PURE__ */ $$_create_template(`<!$><media-thumbnail part="thumbnail" mk-d></media-thumbnail>`);
class SliderThumbnail extends Component {
static el = defineElement({
tagName: "media-slider-thumbnail"
});
static register = [Thumbnail];
_media;
_slider;
constructor(instance) {
super(instance);
this._media = useMedia();
this._slider = useStore(SliderStoreFactory);
}
_getTime() {
const { duration } = this._media.$store;
return this._slider.pointerRate() * duration();
}
render() {
const time = this._getTime.bind(this);
return (() => {
const [$$_root, $$_walker] = $$_create_walker($$_templ$f);
$$_effect(() => $$_attr($$_root, "time", time()));
$$_setup_custom_element($$_root);
return $$_root;
})();
}
}
const $$_templ$e = /* @__PURE__ */ $$_create_template(`<!$><video muted="" playsinline="" preload="auto" part="video" style="max-width: unset"></video>`);
class SliderVideo extends Component {
static el = defineElement({
tagName: "media-slider-video",
props: { src: void 0 }
});
_media;
_slider;
_video = null;
_canPlay = signal(false);
_error = signal(false);
_src;
_hidden;
onAttach() {
this._media = useMedia();
this._slider = useStore(SliderStoreFactory);
this._src = computed(this._getSrc.bind(