Files
pole-book/server/node_modules/media-chrome/dist/cjs/media-container.js

540 lines
19 KiB
JavaScript

var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
var __privateGet = (obj, member, getter) => {
__accessCheck(obj, member, "read from private field");
return getter ? getter.call(obj) : member.get(obj);
};
var __privateAdd = (obj, member, value) => {
if (member.has(obj))
throw TypeError("Cannot add the same private member more than once");
member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
};
var __privateSet = (obj, member, value, setter) => {
__accessCheck(obj, member, "write to private field");
setter ? setter.call(obj, value) : member.set(obj, value);
return value;
};
var __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
var media_container_exports = {};
__export(media_container_exports, {
Attributes: () => Attributes,
MediaContainer: () => MediaContainer,
default: () => media_container_default
});
module.exports = __toCommonJS(media_container_exports);
var import_server_safe_globals = require("./utils/server-safe-globals.js");
var import_constants = require("./constants.js");
var import_labels = require("./labels/labels.js");
var import_resize_observer = require("./utils/resize-observer.js");
var import_media_gesture_receiver = require("./media-gesture-receiver.js");
var _pointerDownTimeStamp, _currentMedia, _inactiveTimeout, _autohide, _handlePointerMove, handlePointerMove_fn, _handlePointerUp, handlePointerUp_fn, _setInactive, setInactive_fn, _setActive, setActive_fn, _scheduleInactive, scheduleInactive_fn;
const Attributes = {
AUDIO: "audio",
AUTOHIDE: "autohide",
BREAKPOINTS: "breakpoints",
GESTURES_DISABLED: "gesturesdisabled",
KEYBOARD_CONTROL: "keyboardcontrol",
NO_AUTOHIDE: "noautohide",
USER_INACTIVE: "userinactive"
};
const template = import_server_safe_globals.document.createElement("template");
template.innerHTML = /*html*/
`
<style>
${/*
* outline on media is turned off because it is allowed to get focus to faciliate hotkeys.
* However, on keyboard interactions, the focus outline is shown,
* which is particularly noticeable when going fullscreen via hotkeys.
*/
""}
:host([${import_constants.MediaUIAttributes.MEDIA_IS_FULLSCREEN}]) ::slotted([slot=media]) {
outline: none;
}
:host {
box-sizing: border-box;
position: relative;
display: inline-block;
line-height: 0;
background-color: var(--media-background-color, #000);
}
:host(:not([${Attributes.AUDIO}])) [part~=layer]:not([part~=media-layer]) {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
display: flex;
flex-flow: column nowrap;
align-items: start;
pointer-events: none;
background: none;
}
slot[name=media] {
display: var(--media-slot-display, contents);
}
${/*
* when in audio mode, hide the slotted media element by default
*/
""}
:host([${Attributes.AUDIO}]) slot[name=media] {
display: var(--media-slot-display, none);
}
${/*
* when in audio mode, hide the gesture-layer which causes media-controller to be taller than the control bar
*/
""}
:host([${Attributes.AUDIO}]) [part~=layer][part~=gesture-layer] {
height: 0;
display: block;
}
${/*
* if gestures are disabled, don't accept pointer-events
*/
""}
:host(:not([${Attributes.AUDIO}])[${Attributes.GESTURES_DISABLED}]) ::slotted([slot=gestures-chrome]),
:host(:not([${Attributes.AUDIO}])[${Attributes.GESTURES_DISABLED}]) media-gesture-receiver[slot=gestures-chrome] {
display: none;
}
${/*
* any slotted element that isn't a poster or media slot should be pointer-events auto
* we'll want to add here any slotted elements that shouldn't get pointer-events by default when slotted
*/
""}
::slotted(:not([slot=media]):not([slot=poster]):not(media-loading-indicator):not([hidden])) {
pointer-events: auto;
}
:host(:not([${Attributes.AUDIO}])) *[part~=layer][part~=centered-layer] {
align-items: center;
justify-content: center;
}
:host(:not([${Attributes.AUDIO}])) ::slotted(media-gesture-receiver[slot=gestures-chrome]),
:host(:not([${Attributes.AUDIO}])) media-gesture-receiver[slot=gestures-chrome] {
align-self: stretch;
flex-grow: 1;
}
slot[name=middle-chrome] {
display: inline;
flex-grow: 1;
pointer-events: none;
background: none;
}
${/* Position the media and poster elements to fill the container */
""}
::slotted([slot=media]),
::slotted([slot=poster]) {
width: 100%;
height: 100%;
}
${/* Video specific styles */
""}
:host(:not([${Attributes.AUDIO}])) .spacer {
flex-grow: 1;
}
${/* Safari needs this to actually make the element fill the window */
""}
:host(:-webkit-full-screen) {
${/* Needs to use !important otherwise easy to break */
""}
width: 100% !important;
height: 100% !important;
}
${/* Only add these if auto hide is not disabled */
""}
::slotted(:not([slot=media]):not([slot=poster]):not([${Attributes.NO_AUTOHIDE}]):not([hidden])) {
opacity: 1;
transition: opacity 0.25s;
}
${/* Hide controls when inactive, not paused, not audio and auto hide not disabled */
""}
:host([${Attributes.USER_INACTIVE}]:not([${import_constants.MediaUIAttributes.MEDIA_PAUSED}]):not([${import_constants.MediaUIAttributes.MEDIA_IS_AIRPLAYING}]):not([${import_constants.MediaUIAttributes.MEDIA_IS_CASTING}]):not([${Attributes.AUDIO}])) ::slotted(:not([slot=media]):not([slot=poster]):not([${Attributes.NO_AUTOHIDE}])) {
opacity: 0;
transition: opacity 1s;
}
:host([${Attributes.USER_INACTIVE}]:not([${import_constants.MediaUIAttributes.MEDIA_PAUSED}]):not([${import_constants.MediaUIAttributes.MEDIA_IS_CASTING}]):not([${Attributes.AUDIO}])) ::slotted([slot=media]) {
cursor: none;
}
::slotted(media-control-bar) {
align-self: stretch;
}
${/* ::slotted([slot=poster]) doesn't work for slot fallback content so hide parent slot instead */
""}
:host(:not([${Attributes.AUDIO}])[${import_constants.MediaUIAttributes.MEDIA_HAS_PLAYED}]) slot[name=poster] {
display: none;
}
::slotted([role="menu"]) {
align-self: end;
}
::slotted([role="dialog"]) {
align-self: center;
}
</style>
<slot name="media" part="layer media-layer"></slot>
<slot name="poster" part="layer poster-layer"></slot>
<slot name="gestures-chrome" part="layer gesture-layer">
<media-gesture-receiver slot="gestures-chrome"></media-gesture-receiver>
</slot>
<span part="layer vertical-layer">
<slot name="top-chrome" part="top chrome"></slot>
<slot name="middle-chrome" part="middle chrome"></slot>
<slot name="centered-chrome" part="layer centered-layer center centered chrome"></slot>
${/* default, effectively "bottom-chrome" */
""}
<slot part="bottom chrome"></slot>
</span>
`;
const MEDIA_UI_ATTRIBUTE_NAMES = Object.values(import_constants.MediaUIAttributes);
const defaultBreakpoints = "sm:384 md:576 lg:768 xl:960";
function resizeCallback(entry) {
setBreakpoints(entry.target, entry.contentRect.width);
}
function setBreakpoints(container, width) {
var _a;
if (!container.isConnected)
return;
const breakpoints = (_a = container.getAttribute(Attributes.BREAKPOINTS)) != null ? _a : defaultBreakpoints;
const ranges = createBreakpointMap(breakpoints);
const activeBreakpoints = getBreakpoints(ranges, width);
let changed = false;
Object.keys(ranges).forEach((name) => {
if (activeBreakpoints.includes(name)) {
if (!container.hasAttribute(`breakpoint${name}`)) {
container.setAttribute(`breakpoint${name}`, "");
changed = true;
}
return;
}
if (container.hasAttribute(`breakpoint${name}`)) {
container.removeAttribute(`breakpoint${name}`);
changed = true;
}
});
if (changed) {
const evt = new CustomEvent(import_constants.MediaStateChangeEvents.BREAKPOINTS_CHANGE, {
detail: activeBreakpoints
});
container.dispatchEvent(evt);
}
}
function createBreakpointMap(breakpoints) {
const pairs = breakpoints.split(/\s+/);
return Object.fromEntries(pairs.map((pair) => pair.split(":")));
}
function getBreakpoints(breakpoints, width) {
return Object.keys(breakpoints).filter((name) => {
return width >= parseInt(breakpoints[name]);
});
}
class MediaContainer extends import_server_safe_globals.globalThis.HTMLElement {
constructor() {
super();
__privateAdd(this, _handlePointerMove);
__privateAdd(this, _handlePointerUp);
__privateAdd(this, _setInactive);
__privateAdd(this, _setActive);
__privateAdd(this, _scheduleInactive);
__privateAdd(this, _pointerDownTimeStamp, 0);
__privateAdd(this, _currentMedia, null);
__privateAdd(this, _inactiveTimeout, null);
__privateAdd(this, _autohide, void 0);
this.breakpointsComputed = false;
if (!this.shadowRoot) {
this.attachShadow({ mode: "open" });
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
const mutationCallback = (mutationsList) => {
const media = this.media;
for (const mutation of mutationsList) {
if (mutation.type === "childList") {
mutation.removedNodes.forEach((node) => {
if (node.slot == "media" && mutation.target == this) {
let previousSibling = mutation.previousSibling && mutation.previousSibling.previousElementSibling;
if (!previousSibling || !media) {
this.mediaUnsetCallback(node);
} else {
let wasFirst = previousSibling.slot !== "media";
while ((previousSibling = previousSibling.previousSibling) !== null) {
if (previousSibling.slot == "media")
wasFirst = false;
}
if (wasFirst)
this.mediaUnsetCallback(node);
}
}
});
if (media) {
mutation.addedNodes.forEach((node) => {
if (node === media) {
this.handleMediaUpdated(media);
}
});
}
}
}
};
const mutationObserver = new MutationObserver(mutationCallback);
mutationObserver.observe(this, { childList: true, subtree: true });
let pendingResizeCb = false;
const deferResizeCallback = (entry) => {
if (pendingResizeCb)
return;
setTimeout(() => {
resizeCallback(entry);
pendingResizeCb = false;
if (!this.breakpointsComputed) {
this.breakpointsComputed = true;
this.dispatchEvent(
new CustomEvent(import_constants.MediaStateChangeEvents.BREAKPOINTS_COMPUTED, {
bubbles: true,
composed: true
})
);
}
}, 0);
pendingResizeCb = true;
};
(0, import_resize_observer.observeResize)(this, deferResizeCallback);
const chainedSlot = this.querySelector(
":scope > slot[slot=media]"
);
if (chainedSlot) {
chainedSlot.addEventListener("slotchange", () => {
const slotEls = chainedSlot.assignedElements({ flatten: true });
if (!slotEls.length) {
if (__privateGet(this, _currentMedia)) {
this.mediaUnsetCallback(__privateGet(this, _currentMedia));
}
return;
}
this.handleMediaUpdated(this.media);
});
}
}
static get observedAttributes() {
return [Attributes.AUTOHIDE, Attributes.GESTURES_DISABLED].concat(MEDIA_UI_ATTRIBUTE_NAMES).filter(
(name) => ![
import_constants.MediaUIAttributes.MEDIA_RENDITION_LIST,
import_constants.MediaUIAttributes.MEDIA_AUDIO_TRACK_LIST,
import_constants.MediaUIAttributes.MEDIA_CHAPTERS_CUES,
import_constants.MediaUIAttributes.MEDIA_WIDTH,
import_constants.MediaUIAttributes.MEDIA_HEIGHT
].includes(name)
);
}
// Could share this code with media-chrome-html-element instead
attributeChangedCallback(attrName, oldValue, newValue) {
if (attrName.toLowerCase() == Attributes.AUTOHIDE) {
this.autohide = newValue;
}
}
// First direct child with slot=media, or null
/**
* @returns {HTMLVideoElement &
* {buffered,
* webkitEnterFullscreen?,
* webkitExitFullscreen?,
* requestCast?,
* webkitShowPlaybackTargetPicker?,
* videoTracks?,
* }}
*/
get media() {
let media = this.querySelector(":scope > [slot=media]");
if ((media == null ? void 0 : media.nodeName) == "SLOT")
media = media.assignedElements({ flatten: true })[0];
return media;
}
/**
* @param {HTMLMediaElement} media
*/
async handleMediaUpdated(media) {
if (!media)
return;
__privateSet(this, _currentMedia, media);
if (media.localName.includes("-")) {
await import_server_safe_globals.globalThis.customElements.whenDefined(media.localName);
}
this.mediaSetCallback(media);
}
connectedCallback() {
var _a;
const isAudioChrome = this.getAttribute(Attributes.AUDIO) != null;
const label = isAudioChrome ? import_labels.nouns.AUDIO_PLAYER() : import_labels.nouns.VIDEO_PLAYER();
this.setAttribute("role", "region");
this.setAttribute("aria-label", label);
this.handleMediaUpdated(this.media);
this.setAttribute(Attributes.USER_INACTIVE, "");
this.addEventListener("pointerdown", this);
this.addEventListener("pointermove", this);
this.addEventListener("pointerup", this);
this.addEventListener("mouseleave", this);
this.addEventListener("keyup", this);
(_a = import_server_safe_globals.globalThis.window) == null ? void 0 : _a.addEventListener("mouseup", this);
}
disconnectedCallback() {
var _a;
if (this.media) {
this.mediaUnsetCallback(this.media);
}
(_a = import_server_safe_globals.globalThis.window) == null ? void 0 : _a.removeEventListener("mouseup", this);
}
/**
* @abstract
* @param {HTMLMediaElement} media
*/
mediaSetCallback(media) {
}
// eslint-disable-line
/**
* @param {HTMLMediaElement} media
*/
mediaUnsetCallback(media) {
__privateSet(this, _currentMedia, null);
}
handleEvent(event) {
switch (event.type) {
case "pointerdown":
__privateSet(this, _pointerDownTimeStamp, event.timeStamp);
break;
case "pointermove":
__privateMethod(this, _handlePointerMove, handlePointerMove_fn).call(this, event);
break;
case "pointerup":
__privateMethod(this, _handlePointerUp, handlePointerUp_fn).call(this, event);
break;
case "mouseleave":
__privateMethod(this, _setInactive, setInactive_fn).call(this);
break;
case "mouseup":
this.removeAttribute(Attributes.KEYBOARD_CONTROL);
break;
case "keyup":
__privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);
this.setAttribute(Attributes.KEYBOARD_CONTROL, "");
break;
}
}
set autohide(seconds) {
const parsedSeconds = Number(seconds);
__privateSet(this, _autohide, isNaN(parsedSeconds) ? 0 : parsedSeconds);
}
get autohide() {
return (__privateGet(this, _autohide) === void 0 ? 2 : __privateGet(this, _autohide)).toString();
}
}
_pointerDownTimeStamp = new WeakMap();
_currentMedia = new WeakMap();
_inactiveTimeout = new WeakMap();
_autohide = new WeakMap();
_handlePointerMove = new WeakSet();
handlePointerMove_fn = function(event) {
if (event.pointerType !== "mouse") {
const MAX_TAP_DURATION = 250;
if (event.timeStamp - __privateGet(this, _pointerDownTimeStamp) < MAX_TAP_DURATION)
return;
}
__privateMethod(this, _setActive, setActive_fn).call(this);
clearTimeout(__privateGet(this, _inactiveTimeout));
if ([this, this.media].includes(event.target)) {
__privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);
}
};
_handlePointerUp = new WeakSet();
handlePointerUp_fn = function(event) {
if (event.pointerType === "touch") {
const controlsVisible = !this.hasAttribute(Attributes.USER_INACTIVE);
if ([this, this.media].includes(event.target) && controlsVisible) {
__privateMethod(this, _setInactive, setInactive_fn).call(this);
} else {
__privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);
}
} else if (event.composedPath().some(
(el) => ["media-play-button", "media-fullscreen-button"].includes(
el == null ? void 0 : el.localName
)
)) {
__privateMethod(this, _scheduleInactive, scheduleInactive_fn).call(this);
}
};
_setInactive = new WeakSet();
setInactive_fn = function() {
if (__privateGet(this, _autohide) < 0)
return;
if (this.hasAttribute(Attributes.USER_INACTIVE))
return;
this.setAttribute(Attributes.USER_INACTIVE, "");
const evt = new import_server_safe_globals.globalThis.CustomEvent(
import_constants.MediaStateChangeEvents.USER_INACTIVE,
{ composed: true, bubbles: true, detail: true }
);
this.dispatchEvent(evt);
};
_setActive = new WeakSet();
setActive_fn = function() {
if (!this.hasAttribute(Attributes.USER_INACTIVE))
return;
this.removeAttribute(Attributes.USER_INACTIVE);
const evt = new import_server_safe_globals.globalThis.CustomEvent(
import_constants.MediaStateChangeEvents.USER_INACTIVE,
{ composed: true, bubbles: true, detail: false }
);
this.dispatchEvent(evt);
};
_scheduleInactive = new WeakSet();
scheduleInactive_fn = function() {
__privateMethod(this, _setActive, setActive_fn).call(this);
clearTimeout(__privateGet(this, _inactiveTimeout));
const autohide = parseInt(this.autohide);
if (autohide < 0)
return;
__privateSet(this, _inactiveTimeout, setTimeout(() => {
__privateMethod(this, _setInactive, setInactive_fn).call(this);
}, autohide * 1e3));
};
if (!import_server_safe_globals.globalThis.customElements.get("media-container")) {
import_server_safe_globals.globalThis.customElements.define("media-container", MediaContainer);
}
var media_container_default = MediaContainer;