node_modules ignore

This commit is contained in:
2025-05-08 23:43:47 +02:00
parent e19d52f172
commit 4574544c9f
65041 changed files with 10593536 additions and 0 deletions

13
server/node_modules/media-chrome/dist/menu/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,13 @@
export { MediaChromeMenu } from './media-chrome-menu.js';
export { MediaChromeMenuItem } from './media-chrome-menu-item.js';
export { MediaSettingsMenu } from './media-settings-menu.js';
export { MediaSettingsMenuItem } from './media-settings-menu-item.js';
export { MediaSettingsMenuButton } from './media-settings-menu-button.js';
export { MediaAudioTrackMenu } from './media-audio-track-menu.js';
export { MediaAudioTrackMenuButton } from './media-audio-track-menu-button.js';
export { MediaCaptionsMenu } from './media-captions-menu.js';
export { MediaCaptionsMenuButton } from './media-captions-menu-button.js';
export { MediaPlaybackRateMenu } from './media-playback-rate-menu.js';
export { MediaPlaybackRateMenuButton } from './media-playback-rate-menu-button.js';
export { MediaRenditionMenu } from './media-rendition-menu.js';
export { MediaRenditionMenuButton } from './media-rendition-menu-button.js';

28
server/node_modules/media-chrome/dist/menu/index.js generated vendored Normal file
View File

@@ -0,0 +1,28 @@
import { MediaChromeMenu } from "./media-chrome-menu.js";
import { MediaChromeMenuItem } from "./media-chrome-menu-item.js";
import { MediaSettingsMenu } from "./media-settings-menu.js";
import { MediaSettingsMenuItem } from "./media-settings-menu-item.js";
import { MediaSettingsMenuButton } from "./media-settings-menu-button.js";
import { MediaAudioTrackMenu } from "./media-audio-track-menu.js";
import { MediaAudioTrackMenuButton } from "./media-audio-track-menu-button.js";
import { MediaCaptionsMenu } from "./media-captions-menu.js";
import { MediaCaptionsMenuButton } from "./media-captions-menu-button.js";
import { MediaPlaybackRateMenu } from "./media-playback-rate-menu.js";
import { MediaPlaybackRateMenuButton } from "./media-playback-rate-menu-button.js";
import { MediaRenditionMenu } from "./media-rendition-menu.js";
import { MediaRenditionMenuButton } from "./media-rendition-menu-button.js";
export {
MediaAudioTrackMenu,
MediaAudioTrackMenuButton,
MediaCaptionsMenu,
MediaCaptionsMenuButton,
MediaChromeMenu,
MediaChromeMenuItem,
MediaPlaybackRateMenu,
MediaPlaybackRateMenuButton,
MediaRenditionMenu,
MediaRenditionMenuButton,
MediaSettingsMenu,
MediaSettingsMenuButton,
MediaSettingsMenuItem
};

View File

@@ -0,0 +1,26 @@
import { MediaChromeMenuButton } from './media-chrome-menu-button.js';
/**
* @attr {string} mediaaudiotrackenabled - (read-only) Set to the selected audio track id.
* @attr {(unavailable|unsupported)} mediaaudiotrackunavailable - (read-only) Set if audio track selection is unavailable.
*
* @cssproperty [--media-audio-track-menu-button-display = inline-flex] - `display` property of button.
*/
declare class MediaAudioTrackMenuButton extends MediaChromeMenuButton {
static get observedAttributes(): string[];
constructor();
connectedCallback(): void;
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement(): HTMLElement | null;
/**
* Get enabled audio track id.
* @return {string}
*/
get mediaAudioTrackEnabled(): string;
set mediaAudioTrackEnabled(id: string);
}
export { MediaAudioTrackMenuButton };
export default MediaAudioTrackMenuButton;

View File

@@ -0,0 +1,77 @@
import { MediaUIAttributes } from "../constants.js";
import { MediaChromeMenuButton } from "./media-chrome-menu-button.js";
import { globalThis, document } from "../utils/server-safe-globals.js";
import { nouns, tooltipLabels } from "../labels/labels.js";
import {
getStringAttr,
setStringAttr,
getMediaController
} from "../utils/element-utils.js";
const audioTrackIcon = (
/*html*/
`<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M11 17H9.5V7H11v10Zm-3-3H6.5v-4H8v4Zm6-5h-1.5v6H14V9Zm3 7h-1.5V8H17v8Z"/>
<path d="M22 12c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2s10 4.477 10 10Zm-2 0a8 8 0 1 0-16 0 8 8 0 0 0 16 0Z"/>
</svg>`
);
const slotTemplate = document.createElement("template");
slotTemplate.innerHTML = /*html*/
`
<style>
:host([aria-expanded="true"]) slot[name=tooltip] {
display: none;
}
</style>
<slot name="icon">${audioTrackIcon}</slot>
`;
class MediaAudioTrackMenuButton extends MediaChromeMenuButton {
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED,
MediaUIAttributes.MEDIA_AUDIO_TRACK_UNAVAILABLE
];
}
constructor() {
super({ slotTemplate, tooltipContent: tooltipLabels.AUDIO_TRACK_MENU });
}
connectedCallback() {
super.connectedCallback();
this.setAttribute("aria-label", nouns.AUDIO_TRACKS());
}
attributeChangedCallback(attrName, oldValue, newValue) {
super.attributeChangedCallback(attrName, oldValue, newValue);
}
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement() {
var _a;
if (this.invokeTarget != void 0)
return super.invokeTargetElement;
return (_a = getMediaController(this)) == null ? void 0 : _a.querySelector("media-audio-track-menu");
}
/**
* Get enabled audio track id.
* @return {string}
*/
get mediaAudioTrackEnabled() {
var _a;
return (_a = getStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED)) != null ? _a : "";
}
set mediaAudioTrackEnabled(id) {
setStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED, id);
}
}
if (!globalThis.customElements.get("media-audio-track-menu-button")) {
globalThis.customElements.define(
"media-audio-track-menu-button",
MediaAudioTrackMenuButton
);
}
var media_audio_track_menu_button_default = MediaAudioTrackMenuButton;
export {
MediaAudioTrackMenuButton,
media_audio_track_menu_button_default as default
};

View File

@@ -0,0 +1,32 @@
import { MediaChromeMenu } from './media-chrome-menu.js';
import { TextTrackLike } from '../utils/TextTrackLike.js';
/**
* @extends {MediaChromeMenu}
*
* @slot - Default slotted elements.node
* @slot header - An element shown at the top of the menu.
* @slot checked-indicator - An icon element indicating a checked menu-item.
*
* @attr {string} mediaaudiotrackenabled - (read-only) Set to the enabled audio track.
* @attr {string} mediaaudiotracklist - (read-only) Set to the audio track list.
*/
declare class MediaAudioTrackMenu extends MediaChromeMenu {
#private;
static get observedAttributes(): string[];
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
connectedCallback(): void;
disconnectedCallback(): void;
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement(): HTMLElement;
get mediaAudioTrackList(): TextTrackLike[];
set mediaAudioTrackList(list: TextTrackLike[]);
/**
* Get enabled audio track id.
*/
get mediaAudioTrackEnabled(): string;
set mediaAudioTrackEnabled(id: string);
}
export { MediaAudioTrackMenu };
export default MediaAudioTrackMenu;

View File

@@ -0,0 +1,144 @@
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 _audioTrackList, _prevState, _render, render_fn, _onChange, onChange_fn;
import { globalThis } from "../utils/server-safe-globals.js";
import { MediaUIAttributes, MediaUIEvents } from "../constants.js";
import { parseAudioTrackList } from "../utils/utils.js";
import {
MediaChromeMenu,
createMenuItem,
createIndicator
} from "./media-chrome-menu.js";
import {
getStringAttr,
setStringAttr,
getMediaController
} from "../utils/element-utils.js";
class MediaAudioTrackMenu extends MediaChromeMenu {
constructor() {
super(...arguments);
__privateAdd(this, _render);
__privateAdd(this, _onChange);
__privateAdd(this, _audioTrackList, []);
__privateAdd(this, _prevState, void 0);
}
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_AUDIO_TRACK_LIST,
MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED,
MediaUIAttributes.MEDIA_AUDIO_TRACK_UNAVAILABLE
];
}
attributeChangedCallback(attrName, oldValue, newValue) {
super.attributeChangedCallback(attrName, oldValue, newValue);
if (attrName === MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED && oldValue !== newValue) {
this.value = newValue;
} else if (attrName === MediaUIAttributes.MEDIA_AUDIO_TRACK_LIST && oldValue !== newValue) {
__privateSet(this, _audioTrackList, parseAudioTrackList(newValue != null ? newValue : ""));
__privateMethod(this, _render, render_fn).call(this);
}
}
connectedCallback() {
super.connectedCallback();
this.addEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement() {
var _a;
if (this.anchor !== "auto")
return super.anchorElement;
return (_a = getMediaController(this)) == null ? void 0 : _a.querySelector(
"media-audio-track-menu-button"
);
}
get mediaAudioTrackList() {
return __privateGet(this, _audioTrackList);
}
set mediaAudioTrackList(list) {
__privateSet(this, _audioTrackList, list);
__privateMethod(this, _render, render_fn).call(this);
}
/**
* Get enabled audio track id.
*/
get mediaAudioTrackEnabled() {
var _a;
return (_a = getStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED)) != null ? _a : "";
}
set mediaAudioTrackEnabled(id) {
setStringAttr(this, MediaUIAttributes.MEDIA_AUDIO_TRACK_ENABLED, id);
}
}
_audioTrackList = new WeakMap();
_prevState = new WeakMap();
_render = new WeakSet();
render_fn = function() {
if (__privateGet(this, _prevState) === JSON.stringify(this.mediaAudioTrackList))
return;
__privateSet(this, _prevState, JSON.stringify(this.mediaAudioTrackList));
const audioTrackList = this.mediaAudioTrackList;
this.defaultSlot.textContent = "";
for (const audioTrack of audioTrackList) {
const text = this.formatMenuItemText(audioTrack.label, audioTrack);
const item = createMenuItem({
type: "radio",
text,
value: `${audioTrack.id}`,
checked: audioTrack.enabled
});
item.prepend(createIndicator(this, "checked-indicator"));
this.defaultSlot.append(item);
}
};
_onChange = new WeakSet();
onChange_fn = function() {
if (this.value == null)
return;
const event = new globalThis.CustomEvent(
MediaUIEvents.MEDIA_AUDIO_TRACK_REQUEST,
{
composed: true,
bubbles: true,
detail: this.value
}
);
this.dispatchEvent(event);
};
if (!globalThis.customElements.get("media-audio-track-menu")) {
globalThis.customElements.define(
"media-audio-track-menu",
MediaAudioTrackMenu
);
}
var media_audio_track_menu_default = MediaAudioTrackMenu;
export {
MediaAudioTrackMenu,
media_audio_track_menu_default as default
};

View File

@@ -0,0 +1,38 @@
import { MediaChromeMenuButton } from './media-chrome-menu-button.js';
import { TextTrackLike } from '../utils/TextTrackLike.js';
/**
* @slot on - An element that will be shown while closed captions or subtitles are on.
* @slot off - An element that will be shown while closed captions or subtitles are off.
* @slot icon - An element for representing on and off states in a single icon
*
* @attr {string} mediasubtitleslist - (read-only) A list of all subtitles and captions.
* @attr {string} mediasubtitlesshowing - (read-only) A list of the showing subtitles and captions.
*
* @cssproperty [--media-captions-menu-button-display = inline-flex] - `display` property of button.
*/
declare class MediaCaptionsMenuButton extends MediaChromeMenuButton {
#private;
static get observedAttributes(): string[];
constructor(options?: Record<string, any>);
connectedCallback(): void;
attributeChangedCallback(attrName: string, oldValue: string, newValue: string): void;
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement(): HTMLElement | null;
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesList(): TextTrackLike[];
set mediaSubtitlesList(list: TextTrackLike[]);
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesShowing(): TextTrackLike[];
set mediaSubtitlesShowing(list: TextTrackLike[]);
}
export { MediaCaptionsMenuButton };
export default MediaCaptionsMenuButton;

View File

@@ -0,0 +1,143 @@
var __accessCheck = (obj, member, msg) => {
if (!member.has(obj))
throw TypeError("Cannot " + msg);
};
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 _captionsReady;
import { globalThis, document } from "../utils/server-safe-globals.js";
import { MediaUIAttributes } from "../constants.js";
import { nouns, tooltipLabels } from "../labels/labels.js";
import { MediaChromeMenuButton } from "./media-chrome-menu-button.js";
import { getMediaController } from "../utils/element-utils.js";
import {
areSubsOn,
parseTextTracksStr,
stringifyTextTrackList
} from "../utils/captions.js";
const ccIconOn = `<svg aria-hidden="true" viewBox="0 0 26 24">
<path d="M22.83 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.39 9.45a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.92 3.92 0 0 1 .92-2.77 3.18 3.18 0 0 1 2.43-1 2.94 2.94 0 0 1 2.13.78c.364.359.62.813.74 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.17 1.61 1.61 0 0 0-1.29.58 2.79 2.79 0 0 0-.5 1.89 3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.48 1.48 0 0 0 1-.37 2.1 2.1 0 0 0 .59-1.14l1.4.44a3.23 3.23 0 0 1-1.07 1.69Zm7.22 0a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.88 3.88 0 0 1 .93-2.77 3.14 3.14 0 0 1 2.42-1 3 3 0 0 1 2.16.82 2.8 2.8 0 0 1 .73 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.21 1.61 1.61 0 0 0-1.29.58A2.79 2.79 0 0 0 15 12a3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.44 1.44 0 0 0 1-.37 2.1 2.1 0 0 0 .6-1.15l1.4.44a3.17 3.17 0 0 1-1.1 1.7Z"/>
</svg>`;
const ccIconOff = `<svg aria-hidden="true" viewBox="0 0 26 24">
<path d="M17.73 14.09a1.4 1.4 0 0 1-1 .37 1.579 1.579 0 0 1-1.27-.58A3 3 0 0 1 15 12a2.8 2.8 0 0 1 .5-1.85 1.63 1.63 0 0 1 1.29-.57 1.47 1.47 0 0 1 1.51 1.2l1.43-.34A2.89 2.89 0 0 0 19 9.07a3 3 0 0 0-2.14-.78 3.14 3.14 0 0 0-2.42 1 3.91 3.91 0 0 0-.93 2.78 3.74 3.74 0 0 0 .92 2.66 3.07 3.07 0 0 0 2.34 1 3.07 3.07 0 0 0 1.91-.57 3.17 3.17 0 0 0 1.07-1.74l-1.4-.45c-.083.43-.3.822-.62 1.12Zm-7.22 0a1.43 1.43 0 0 1-1 .37 1.58 1.58 0 0 1-1.27-.58A3 3 0 0 1 7.76 12a2.8 2.8 0 0 1 .5-1.85 1.63 1.63 0 0 1 1.29-.57 1.47 1.47 0 0 1 1.51 1.2l1.43-.34a2.81 2.81 0 0 0-.74-1.32 2.94 2.94 0 0 0-2.13-.78 3.18 3.18 0 0 0-2.43 1 4 4 0 0 0-.92 2.78 3.74 3.74 0 0 0 .92 2.66 3.07 3.07 0 0 0 2.34 1 3.07 3.07 0 0 0 1.91-.57 3.23 3.23 0 0 0 1.07-1.74l-1.4-.45a2.06 2.06 0 0 1-.6 1.07Zm12.32-8.41a2.59 2.59 0 0 0-2.3-2.51C18.72 3.05 15.86 3 13 3c-2.86 0-5.72.05-7.53.17a2.59 2.59 0 0 0-2.3 2.51c-.23 4.207-.23 8.423 0 12.63a2.57 2.57 0 0 0 2.3 2.5c1.81.13 4.67.19 7.53.19 2.86 0 5.72-.06 7.53-.19a2.57 2.57 0 0 0 2.3-2.5c.23-4.207.23-8.423 0-12.63Zm-1.49 12.53a1.11 1.11 0 0 1-.91 1.11c-1.67.11-4.45.18-7.43.18-2.98 0-5.76-.07-7.43-.18a1.11 1.11 0 0 1-.91-1.11c-.21-4.14-.21-8.29 0-12.43a1.11 1.11 0 0 1 .91-1.11C7.24 4.56 10 4.49 13 4.49s5.76.07 7.43.18a1.11 1.11 0 0 1 .91 1.11c.21 4.14.21 8.29 0 12.43Z"/>
</svg>`;
const slotTemplate = document.createElement("template");
slotTemplate.innerHTML = /*html*/
`
<style>
:host([aria-checked="true"]) slot[name=off] {
display: none !important;
}
${/* Double negative, but safer if display doesn't equal 'block' */
""}
:host(:not([aria-checked="true"])) slot[name=on] {
display: none !important;
}
:host([aria-expanded="true"]) slot[name=tooltip] {
display: none;
}
</style>
<slot name="icon">
<slot name="on">${ccIconOn}</slot>
<slot name="off">${ccIconOff}</slot>
</slot>
`;
const updateAriaChecked = (el) => {
el.setAttribute("aria-checked", areSubsOn(el).toString());
};
class MediaCaptionsMenuButton extends MediaChromeMenuButton {
constructor(options = {}) {
super({ slotTemplate, tooltipContent: tooltipLabels.CAPTIONS, ...options });
__privateAdd(this, _captionsReady, void 0);
__privateSet(this, _captionsReady, false);
}
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_SUBTITLES_LIST,
MediaUIAttributes.MEDIA_SUBTITLES_SHOWING
];
}
connectedCallback() {
super.connectedCallback();
this.setAttribute("aria-label", nouns.CLOSED_CAPTIONS());
updateAriaChecked(this);
}
attributeChangedCallback(attrName, oldValue, newValue) {
super.attributeChangedCallback(attrName, oldValue, newValue);
if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_SHOWING) {
updateAriaChecked(this);
}
}
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement() {
var _a;
if (this.invokeTarget != void 0)
return super.invokeTargetElement;
return (_a = getMediaController(this)) == null ? void 0 : _a.querySelector("media-captions-menu");
}
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesList() {
return getSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST);
}
set mediaSubtitlesList(list) {
setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST, list);
}
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesShowing() {
return getSubtitlesListAttr(
this,
MediaUIAttributes.MEDIA_SUBTITLES_SHOWING
);
}
set mediaSubtitlesShowing(list) {
setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_SHOWING, list);
}
}
_captionsReady = new WeakMap();
const getSubtitlesListAttr = (el, attrName) => {
const attrVal = el.getAttribute(attrName);
return attrVal ? parseTextTracksStr(attrVal) : [];
};
const setSubtitlesListAttr = (el, attrName, list) => {
if (!(list == null ? void 0 : list.length)) {
el.removeAttribute(attrName);
return;
}
const newValStr = stringifyTextTrackList(list);
const oldVal = el.getAttribute(attrName);
if (oldVal === newValStr)
return;
el.setAttribute(attrName, newValStr);
};
if (!globalThis.customElements.get("media-captions-menu-button")) {
globalThis.customElements.define(
"media-captions-menu-button",
MediaCaptionsMenuButton
);
}
var media_captions_menu_button_default = MediaCaptionsMenuButton;
export {
MediaCaptionsMenuButton,
media_captions_menu_button_default as default
};

View File

@@ -0,0 +1,39 @@
import { MediaChromeMenu } from './media-chrome-menu.js';
import { TextTrackLike } from '../utils/TextTrackLike.js';
/**
* @extends {MediaChromeMenu}
*
* @slot - Default slotted elements.
* @slot header - An element shown at the top of the menu.
* @slot checked-indicator - An icon element indicating a checked menu-item.
* @slot captions-indicator - An icon element indicating an item with closed captions.
*
* @attr {string} mediasubtitleslist - (read-only) A list of all subtitles and captions.
* @attr {boolean} mediasubtitlesshowing - (read-only) A list of the showing subtitles and captions.
*/
declare class MediaCaptionsMenu extends MediaChromeMenu {
#private;
static template: HTMLTemplateElement;
static get observedAttributes(): string[];
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
connectedCallback(): void;
disconnectedCallback(): void;
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement(): HTMLElement;
/**
* @type {Array<object>} An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesList(): TextTrackLike[];
set mediaSubtitlesList(list: TextTrackLike[]);
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesShowing(): TextTrackLike[];
set mediaSubtitlesShowing(list: TextTrackLike[]);
}
export { MediaCaptionsMenu };
export default MediaCaptionsMenu;

View File

@@ -0,0 +1,197 @@
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 _prevState, _render, render_fn, _onChange, onChange_fn;
import { globalThis, document } from "../utils/server-safe-globals.js";
import { MediaUIAttributes, MediaUIEvents } from "../constants.js";
import { getMediaController } from "../utils/element-utils.js";
import {
MediaChromeMenu,
createMenuItem,
createIndicator
} from "./media-chrome-menu.js";
import {
parseTextTracksStr,
stringifyTextTrackList,
formatTextTrackObj
} from "../utils/captions.js";
const ccIcon = (
/*html*/
`
<svg aria-hidden="true" viewBox="0 0 26 24" part="captions-indicator indicator">
<path d="M22.83 5.68a2.58 2.58 0 0 0-2.3-2.5c-3.62-.24-11.44-.24-15.06 0a2.58 2.58 0 0 0-2.3 2.5c-.23 4.21-.23 8.43 0 12.64a2.58 2.58 0 0 0 2.3 2.5c3.62.24 11.44.24 15.06 0a2.58 2.58 0 0 0 2.3-2.5c.23-4.21.23-8.43 0-12.64Zm-11.39 9.45a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.92 3.92 0 0 1 .92-2.77 3.18 3.18 0 0 1 2.43-1 2.94 2.94 0 0 1 2.13.78c.364.359.62.813.74 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.17 1.61 1.61 0 0 0-1.29.58 2.79 2.79 0 0 0-.5 1.89 3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.48 1.48 0 0 0 1-.37 2.1 2.1 0 0 0 .59-1.14l1.4.44a3.23 3.23 0 0 1-1.07 1.69Zm7.22 0a3.07 3.07 0 0 1-1.91.57 3.06 3.06 0 0 1-2.34-1 3.75 3.75 0 0 1-.92-2.67 3.88 3.88 0 0 1 .93-2.77 3.14 3.14 0 0 1 2.42-1 3 3 0 0 1 2.16.82 2.8 2.8 0 0 1 .73 1.31l-1.43.35a1.49 1.49 0 0 0-1.51-1.21 1.61 1.61 0 0 0-1.29.58A2.79 2.79 0 0 0 15 12a3 3 0 0 0 .49 1.93 1.61 1.61 0 0 0 1.27.58 1.44 1.44 0 0 0 1-.37 2.1 2.1 0 0 0 .6-1.15l1.4.44a3.17 3.17 0 0 1-1.1 1.7Z"/>
</svg>`
);
const template = document.createElement("template");
template.innerHTML = MediaChromeMenu.template.innerHTML + /*html*/
`
<slot name="captions-indicator" hidden>${ccIcon}</slot>`;
class MediaCaptionsMenu extends MediaChromeMenu {
constructor() {
super(...arguments);
__privateAdd(this, _render);
__privateAdd(this, _onChange);
__privateAdd(this, _prevState, void 0);
}
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_SUBTITLES_LIST,
MediaUIAttributes.MEDIA_SUBTITLES_SHOWING
];
}
attributeChangedCallback(attrName, oldValue, newValue) {
super.attributeChangedCallback(attrName, oldValue, newValue);
if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_LIST && oldValue !== newValue) {
__privateMethod(this, _render, render_fn).call(this);
} else if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_SHOWING && oldValue !== newValue) {
this.value = newValue;
}
}
connectedCallback() {
super.connectedCallback();
this.addEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement() {
if (this.anchor !== "auto")
return super.anchorElement;
return getMediaController(this).querySelector("media-captions-menu-button");
}
/**
* @type {Array<object>} An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesList() {
return getSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST);
}
set mediaSubtitlesList(list) {
setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST, list);
}
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesShowing() {
return getSubtitlesListAttr(
this,
MediaUIAttributes.MEDIA_SUBTITLES_SHOWING
);
}
set mediaSubtitlesShowing(list) {
setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_SHOWING, list);
}
}
_prevState = new WeakMap();
_render = new WeakSet();
render_fn = function() {
var _a;
if (__privateGet(this, _prevState) === JSON.stringify(this.mediaSubtitlesList))
return;
__privateSet(this, _prevState, JSON.stringify(this.mediaSubtitlesList));
this.defaultSlot.textContent = "";
const isOff = !this.value;
const item = createMenuItem({
type: "radio",
text: this.formatMenuItemText("Off"),
value: "off",
checked: isOff
});
item.prepend(createIndicator(this, "checked-indicator"));
this.defaultSlot.append(item);
const subtitlesList = this.mediaSubtitlesList;
for (const subs of subtitlesList) {
const item2 = createMenuItem({
type: "radio",
text: this.formatMenuItemText(subs.label, subs),
value: formatTextTrackObj(subs),
checked: this.value == formatTextTrackObj(subs)
});
item2.prepend(createIndicator(this, "checked-indicator"));
const type = (_a = subs.kind) != null ? _a : "subs";
if (type === "captions") {
item2.append(createIndicator(this, "captions-indicator"));
}
this.defaultSlot.append(item2);
}
};
_onChange = new WeakSet();
onChange_fn = function() {
const showingSubs = this.mediaSubtitlesShowing;
const showingSubsStr = this.getAttribute(
MediaUIAttributes.MEDIA_SUBTITLES_SHOWING
);
const localStateChange = this.value !== showingSubsStr;
if ((showingSubs == null ? void 0 : showingSubs.length) && localStateChange) {
this.dispatchEvent(
new globalThis.CustomEvent(
MediaUIEvents.MEDIA_DISABLE_SUBTITLES_REQUEST,
{
composed: true,
bubbles: true,
detail: showingSubs
}
)
);
}
if (!this.value || !localStateChange)
return;
const event = new globalThis.CustomEvent(
MediaUIEvents.MEDIA_SHOW_SUBTITLES_REQUEST,
{
composed: true,
bubbles: true,
detail: this.value
}
);
this.dispatchEvent(event);
};
MediaCaptionsMenu.template = template;
const getSubtitlesListAttr = (el, attrName) => {
const attrVal = el.getAttribute(attrName);
return attrVal ? parseTextTracksStr(attrVal) : [];
};
const setSubtitlesListAttr = (el, attrName, list) => {
if (!(list == null ? void 0 : list.length)) {
el.removeAttribute(attrName);
return;
}
const newValStr = stringifyTextTrackList(list);
const oldVal = el.getAttribute(attrName);
if (oldVal === newValStr)
return;
el.setAttribute(attrName, newValStr);
};
if (!globalThis.customElements.get("media-captions-menu")) {
globalThis.customElements.define("media-captions-menu", MediaCaptionsMenu);
}
var media_captions_menu_default = MediaCaptionsMenu;
export {
MediaCaptionsMenu,
media_captions_menu_default as default
};

View File

@@ -0,0 +1,17 @@
import { MediaChromeButton } from '../media-chrome-button.js';
/**
* @attr {string} invoketarget - The id of the element to invoke when clicked.
*/
declare class MediaChromeMenuButton extends MediaChromeButton {
connectedCallback(): void;
get invokeTarget(): string | null;
set invokeTarget(value: string | null);
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement(): HTMLElement | null;
handleClick(): void;
}
export { MediaChromeMenuButton };
export default MediaChromeMenuButton;

View File

@@ -0,0 +1,48 @@
import { MediaChromeButton } from "../media-chrome-button.js";
import { globalThis } from "../utils/server-safe-globals.js";
import { InvokeEvent } from "../utils/events.js";
import { getDocumentOrShadowRoot } from "../utils/element-utils.js";
class MediaChromeMenuButton extends MediaChromeButton {
connectedCallback() {
super.connectedCallback();
if (this.invokeTargetElement) {
this.setAttribute("aria-haspopup", "menu");
}
}
get invokeTarget() {
return this.getAttribute("invoketarget");
}
set invokeTarget(value) {
this.setAttribute("invoketarget", `${value}`);
}
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement() {
var _a;
if (this.invokeTarget) {
return (_a = getDocumentOrShadowRoot(this)) == null ? void 0 : _a.querySelector(
`#${this.invokeTarget}`
);
}
return null;
}
handleClick() {
var _a;
(_a = this.invokeTargetElement) == null ? void 0 : _a.dispatchEvent(
new InvokeEvent({ relatedTarget: this })
);
}
}
if (!globalThis.customElements.get("media-chrome-menu-button")) {
globalThis.customElements.define(
"media-chrome-menu-button",
MediaChromeMenuButton
);
}
var media_chrome_menu_button_default = MediaChromeMenuButton;
export {
MediaChromeMenuButton,
media_chrome_menu_button_default as default
};

View File

@@ -0,0 +1,68 @@
import { globalThis } from '../utils/server-safe-globals.js';
import type MediaChromeMenu from './media-chrome-menu.js';
export declare const Attributes: {
TYPE: string;
VALUE: string;
CHECKED: string;
DISABLED: string;
};
/**
* @extends {HTMLElement}
* @slot - Default slotted elements.
*
* @attr {(''|'radio'|'checkbox')} type - This attribute indicates the kind of command, and can be one of three values.
* @attr {boolean} disabled - The Boolean disabled attribute makes the element not mutable or focusable.
*
* @cssproperty --media-menu-item-opacity - `opacity` of menu-item content.
* @cssproperty --media-menu-item-transition - `transition` of menu-item.
* @cssproperty --media-menu-item-checked-background - `background` of checked menu-item.
* @cssproperty --media-menu-item-outline - `outline` menu-item.
* @cssproperty --media-menu-item-outline-offset - `outline-offset` of menu-item.
* @cssproperty --media-menu-item-hover-background - `background` of hovered menu-item.
* @cssproperty --media-menu-item-hover-outline - `outline` of hovered menu-item.
* @cssproperty --media-menu-item-hover-outline-offset - `outline-offset` of hovered menu-item.
* @cssproperty --media-menu-item-focus-shadow - `box-shadow` of the :focus-visible state.
* @cssproperty --media-menu-item-icon-height - `height` of icon.
* @cssproperty --media-menu-item-description-max-width - `max-width` of description.
* @cssproperty --media-menu-item-checked-indicator-display - `display` of checked indicator.
*
* @cssproperty --media-icon-color - `fill` color of icon.
* @cssproperty --media-menu-icon-height - `height` of icon.
*
* @cssproperty --media-menu-item-indicator-fill - `fill` color of indicator icon.
* @cssproperty --media-menu-item-indicator-height - `height` of menu-item indicator.
*/
declare class MediaChromeMenuItem extends globalThis.HTMLElement {
#private;
static template: HTMLTemplateElement;
static get observedAttributes(): string[];
constructor();
enable(): void;
disable(): void;
handleEvent(event: any): void;
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
connectedCallback(): void;
disconnectedCallback(): void;
get invokeTarget(): string;
set invokeTarget(value: string);
/**
* Returns the element with the id specified by the `invoketarget` attribute
* or the slotted submenu element.
*/
get invokeTargetElement(): MediaChromeMenu | null;
/**
* Returns the slotted submenu element.
*/
get submenuElement(): MediaChromeMenu | null;
get type(): string;
set type(val: string);
get value(): string;
set value(val: string);
get text(): string;
get checked(): boolean;
set checked(value: boolean);
handleClick(event: any): void;
get keysUsed(): string[];
}
export { MediaChromeMenuItem };
export default MediaChromeMenuItem;

View File

@@ -0,0 +1,439 @@
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 _dirty, _ownerElement, _handleSlotChange, handleSlotChange_fn, _submenuConnected, submenuConnected_fn, _submenuDisconnected, submenuDisconnected_fn, _handleMenuItem, _handleKeyUp, handleKeyUp_fn, _handleKeyDown, handleKeyDown_fn, _reset, reset_fn;
import { globalThis, document } from "../utils/server-safe-globals.js";
import { InvokeEvent } from "../utils/events.js";
import {
getDocumentOrShadowRoot,
containsComposedNode
} from "../utils/element-utils.js";
const template = document.createElement("template");
template.innerHTML = /*html*/
`
<style>
:host {
transition: var(--media-menu-item-transition,
background .15s linear,
opacity .2s ease-in-out
);
outline: var(--media-menu-item-outline, 0);
outline-offset: var(--media-menu-item-outline-offset, -1px);
cursor: pointer;
display: flex;
align-items: center;
align-self: stretch;
justify-self: stretch;
white-space: nowrap;
white-space-collapse: collapse;
text-wrap: nowrap;
padding: .4em .8em .4em 1em;
}
:host(:focus-visible) {
box-shadow: var(--media-menu-item-focus-shadow, inset 0 0 0 2px rgb(27 127 204 / .9));
outline: var(--media-menu-item-hover-outline, 0);
outline-offset: var(--media-menu-item-hover-outline-offset, var(--media-menu-item-outline-offset, -1px));
}
:host(:hover) {
cursor: pointer;
background: var(--media-menu-item-hover-background, rgb(92 92 102 / .5));
outline: var(--media-menu-item-hover-outline);
outline-offset: var(--media-menu-item-hover-outline-offset, var(--media-menu-item-outline-offset, -1px));
}
:host([aria-checked="true"]) {
background: var(--media-menu-item-checked-background);
}
:host([hidden]) {
display: none;
}
:host([disabled]) {
pointer-events: none;
color: rgba(255, 255, 255, .3);
}
slot:not([name]) {
width: 100%;
}
slot:not([name="submenu"]) {
display: inline-flex;
align-items: center;
transition: inherit;
opacity: var(--media-menu-item-opacity, 1);
}
slot[name="description"] {
justify-content: end;
}
slot[name="description"] > span {
display: inline-block;
margin-inline: 1em .2em;
max-width: var(--media-menu-item-description-max-width, 100px);
text-overflow: ellipsis;
overflow: hidden;
font-size: .8em;
font-weight: 400;
text-align: right;
position: relative;
top: .04em;
}
slot[name="checked-indicator"] {
display: none;
}
:host(:is([role="menuitemradio"],[role="menuitemcheckbox"])) slot[name="checked-indicator"] {
display: var(--media-menu-item-checked-indicator-display, inline-block);
}
${/* For all slotted icons in prefix and suffix. */
""}
svg, img, ::slotted(svg), ::slotted(img) {
height: var(--media-menu-item-icon-height, var(--media-control-height, 24px));
fill: var(--media-icon-color, var(--media-primary-color, rgb(238 238 238)));
display: block;
}
${/* Only for indicator icons like checked-indicator or captions-indicator. */
""}
[part~="indicator"],
::slotted([part~="indicator"]) {
fill: var(--media-menu-item-indicator-fill,
var(--media-icon-color, var(--media-primary-color, rgb(238 238 238))));
height: var(--media-menu-item-indicator-height, 1.25em);
margin-right: .5ch;
}
[part~="checked-indicator"] {
visibility: hidden;
}
:host([aria-checked="true"]) [part~="checked-indicator"] {
visibility: visible;
}
</style>
<slot name="checked-indicator">
<svg aria-hidden="true" viewBox="0 1 24 24" part="checked-indicator indicator">
<path d="m10 15.17 9.193-9.191 1.414 1.414-10.606 10.606-6.364-6.364 1.414-1.414 4.95 4.95Z"/>
</svg>
</slot>
<slot name="prefix"></slot>
<slot></slot>
<slot name="description"></slot>
<slot name="suffix"></slot>
<slot name="submenu"></slot>
`;
const Attributes = {
TYPE: "type",
VALUE: "value",
CHECKED: "checked",
DISABLED: "disabled"
};
class MediaChromeMenuItem extends globalThis.HTMLElement {
constructor() {
super();
__privateAdd(this, _handleSlotChange);
__privateAdd(this, _submenuConnected);
__privateAdd(this, _submenuDisconnected);
__privateAdd(this, _handleKeyUp);
__privateAdd(this, _handleKeyDown);
__privateAdd(this, _reset);
__privateAdd(this, _dirty, false);
__privateAdd(this, _ownerElement, void 0);
/**
* If there is a slotted submenu the fallback content of the description slot
* is populated with the text of the first checked item.
*/
__privateAdd(this, _handleMenuItem, () => {
var _a, _b;
this.setAttribute("submenusize", `${this.submenuElement.items.length}`);
const descriptionSlot = this.shadowRoot.querySelector(
'slot[name="description"]'
);
const checkedItem = (_a = this.submenuElement.checkedItems) == null ? void 0 : _a[0];
const description = (_b = checkedItem == null ? void 0 : checkedItem.dataset.description) != null ? _b : checkedItem == null ? void 0 : checkedItem.text;
const span = document.createElement("span");
span.textContent = description != null ? description : "";
descriptionSlot.replaceChildren(span);
});
if (!this.shadowRoot) {
this.attachShadow({ mode: "open" });
this.shadowRoot.append(this.constructor.template.content.cloneNode(true));
}
this.shadowRoot.addEventListener("slotchange", this);
}
static get observedAttributes() {
return [
Attributes.TYPE,
Attributes.DISABLED,
Attributes.CHECKED,
Attributes.VALUE
];
}
enable() {
if (!this.hasAttribute("tabindex")) {
this.setAttribute("tabindex", "-1");
}
if (isCheckable(this) && !this.hasAttribute("aria-checked")) {
this.setAttribute("aria-checked", "false");
}
this.addEventListener("click", this);
this.addEventListener("keydown", this);
}
disable() {
this.removeAttribute("tabindex");
this.removeEventListener("click", this);
this.removeEventListener("keydown", this);
this.removeEventListener("keyup", this);
}
handleEvent(event) {
switch (event.type) {
case "slotchange":
__privateMethod(this, _handleSlotChange, handleSlotChange_fn).call(this, event);
break;
case "click":
this.handleClick(event);
break;
case "keydown":
__privateMethod(this, _handleKeyDown, handleKeyDown_fn).call(this, event);
break;
case "keyup":
__privateMethod(this, _handleKeyUp, handleKeyUp_fn).call(this, event);
break;
}
}
attributeChangedCallback(attrName, oldValue, newValue) {
if (attrName === Attributes.CHECKED && isCheckable(this) && !__privateGet(this, _dirty)) {
this.setAttribute("aria-checked", newValue != null ? "true" : "false");
} else if (attrName === Attributes.TYPE && newValue !== oldValue) {
this.role = "menuitem" + newValue;
} else if (attrName === Attributes.DISABLED && newValue !== oldValue) {
if (newValue == null) {
this.enable();
} else {
this.disable();
}
}
}
connectedCallback() {
if (!this.hasAttribute(Attributes.DISABLED)) {
this.enable();
}
this.role = "menuitem" + this.type;
__privateSet(this, _ownerElement, closestMenuItemsContainer(this, this.parentNode));
__privateMethod(this, _reset, reset_fn).call(this);
}
disconnectedCallback() {
this.disable();
__privateMethod(this, _reset, reset_fn).call(this);
__privateSet(this, _ownerElement, null);
}
get invokeTarget() {
return this.getAttribute("invoketarget");
}
set invokeTarget(value) {
this.setAttribute("invoketarget", `${value}`);
}
/**
* Returns the element with the id specified by the `invoketarget` attribute
* or the slotted submenu element.
*/
get invokeTargetElement() {
var _a;
if (this.invokeTarget) {
return (_a = getDocumentOrShadowRoot(this)) == null ? void 0 : _a.querySelector(
`#${this.invokeTarget}`
);
}
return this.submenuElement;
}
/**
* Returns the slotted submenu element.
*/
get submenuElement() {
const submenuSlot = this.shadowRoot.querySelector(
'slot[name="submenu"]'
);
return submenuSlot.assignedElements({
flatten: true
})[0];
}
get type() {
var _a;
return (_a = this.getAttribute(Attributes.TYPE)) != null ? _a : "";
}
set type(val) {
this.setAttribute(Attributes.TYPE, `${val}`);
}
get value() {
var _a;
return (_a = this.getAttribute(Attributes.VALUE)) != null ? _a : this.text;
}
set value(val) {
this.setAttribute(Attributes.VALUE, val);
}
get text() {
var _a;
return ((_a = this.textContent) != null ? _a : "").trim();
}
get checked() {
if (!isCheckable(this))
return void 0;
return this.getAttribute("aria-checked") === "true";
}
set checked(value) {
if (!isCheckable(this))
return;
__privateSet(this, _dirty, true);
this.setAttribute("aria-checked", value ? "true" : "false");
if (value) {
this.part.add("checked");
} else {
this.part.remove("checked");
}
}
handleClick(event) {
if (isCheckable(this))
return;
if (this.invokeTargetElement && containsComposedNode(this, event.target)) {
this.invokeTargetElement.dispatchEvent(
new InvokeEvent({ relatedTarget: this })
);
}
}
get keysUsed() {
return ["Enter", " "];
}
}
_dirty = new WeakMap();
_ownerElement = new WeakMap();
_handleSlotChange = new WeakSet();
handleSlotChange_fn = function(event) {
const slot = event.target;
const isDefaultSlot = !(slot == null ? void 0 : slot.name);
if (isDefaultSlot) {
for (const node of slot.assignedNodes({ flatten: true })) {
if (node instanceof Text && node.textContent.trim() === "") {
node.remove();
}
}
}
if (slot.name === "submenu") {
if (this.submenuElement) {
__privateMethod(this, _submenuConnected, submenuConnected_fn).call(this);
} else {
__privateMethod(this, _submenuDisconnected, submenuDisconnected_fn).call(this);
}
}
};
_submenuConnected = new WeakSet();
submenuConnected_fn = async function() {
this.setAttribute("aria-haspopup", "menu");
this.setAttribute("aria-expanded", `${!this.submenuElement.hidden}`);
this.submenuElement.addEventListener("change", __privateGet(this, _handleMenuItem));
this.submenuElement.addEventListener("addmenuitem", __privateGet(this, _handleMenuItem));
this.submenuElement.addEventListener(
"removemenuitem",
__privateGet(this, _handleMenuItem)
);
__privateGet(this, _handleMenuItem).call(this);
};
_submenuDisconnected = new WeakSet();
submenuDisconnected_fn = function() {
this.removeAttribute("aria-haspopup");
this.removeAttribute("aria-expanded");
this.submenuElement.removeEventListener("change", __privateGet(this, _handleMenuItem));
this.submenuElement.removeEventListener(
"addmenuitem",
__privateGet(this, _handleMenuItem)
);
this.submenuElement.removeEventListener(
"removemenuitem",
__privateGet(this, _handleMenuItem)
);
__privateGet(this, _handleMenuItem).call(this);
};
_handleMenuItem = new WeakMap();
_handleKeyUp = new WeakSet();
handleKeyUp_fn = function(event) {
const { key } = event;
if (!this.keysUsed.includes(key)) {
this.removeEventListener("keyup", __privateMethod(this, _handleKeyUp, handleKeyUp_fn));
return;
}
this.handleClick(event);
};
_handleKeyDown = new WeakSet();
handleKeyDown_fn = function(event) {
const { metaKey, altKey, key } = event;
if (metaKey || altKey || !this.keysUsed.includes(key)) {
this.removeEventListener("keyup", __privateMethod(this, _handleKeyUp, handleKeyUp_fn));
return;
}
this.addEventListener("keyup", __privateMethod(this, _handleKeyUp, handleKeyUp_fn), { once: true });
};
_reset = new WeakSet();
reset_fn = function() {
var _a;
const items = (_a = __privateGet(this, _ownerElement)) == null ? void 0 : _a.radioGroupItems;
if (!items)
return;
let checkedItem = items.filter((item) => item.getAttribute("aria-checked") === "true").pop();
if (!checkedItem)
checkedItem = items[0];
for (const item of items) {
item.setAttribute("aria-checked", "false");
}
checkedItem == null ? void 0 : checkedItem.setAttribute("aria-checked", "true");
};
MediaChromeMenuItem.template = template;
function isCheckable(item) {
return item.type === "radio" || item.type === "checkbox";
}
function closestMenuItemsContainer(childNode, parentNode) {
if (!childNode)
return null;
const { host } = childNode.getRootNode();
if (!parentNode && host)
return closestMenuItemsContainer(childNode, host);
if (parentNode == null ? void 0 : parentNode.items)
return parentNode;
return closestMenuItemsContainer(parentNode, parentNode == null ? void 0 : parentNode.parentNode);
}
if (!globalThis.customElements.get("media-chrome-menu-item")) {
globalThis.customElements.define(
"media-chrome-menu-item",
MediaChromeMenuItem
);
}
var media_chrome_menu_item_default = MediaChromeMenuItem;
export {
Attributes,
MediaChromeMenuItem,
media_chrome_menu_item_default as default
};

View File

@@ -0,0 +1,97 @@
import { globalThis } from '../utils/server-safe-globals.js';
import MediaChromeMenuItem from './media-chrome-menu-item.js';
export declare function createMenuItem({ type, text, value, checked, }: {
type?: string;
text: string;
value: string;
checked: boolean;
}): MediaChromeMenuItem;
export declare function createIndicator(el: HTMLElement, name: string): Node | "";
export declare const Attributes: {
readonly STYLE: "style";
readonly HIDDEN: "hidden";
readonly DISABLED: "disabled";
readonly ANCHOR: "anchor";
};
/**
* @extends {HTMLElement}
*
* @slot - Default slotted elements.
* @slot header - An element shown at the top of the menu.
* @slot checked-indicator - An icon element indicating a checked menu-item.
*
* @attr {boolean} disabled - The Boolean disabled attribute makes the element not mutable or focusable.
* @attr {string} mediacontroller - The element `id` of the media controller to connect to (if not nested within).
*
* @cssproperty --media-primary-color - Default color of text / icon.
* @cssproperty --media-secondary-color - Default color of background.
* @cssproperty --media-text-color - `color` of text.
*
* @cssproperty --media-control-background - `background` of control.
* @cssproperty --media-menu-display - `display` of menu.
* @cssproperty --media-menu-layout - Set to `row` for a horizontal menu design.
* @cssproperty --media-menu-flex-direction - `flex-direction` of menu.
* @cssproperty --media-menu-gap - `gap` between menu items.
* @cssproperty --media-menu-background - `background` of menu.
* @cssproperty --media-menu-border-radius - `border-radius` of menu.
* @cssproperty --media-menu-border - `border` of menu.
* @cssproperty --media-menu-transition-in - `transition` of menu when showing.
* @cssproperty --media-menu-transition-out - `transition` of menu when hiding.
* @cssproperty --media-menu-visibility - `visibility` of menu when showing.
* @cssproperty --media-menu-hidden-visibility - `visibility` of menu when hiding.
* @cssproperty --media-menu-max-height - `max-height` of menu.
* @cssproperty --media-menu-hidden-max-height - `max-height` of menu when hiding.
* @cssproperty --media-menu-opacity - `opacity` of menu when showing.
* @cssproperty --media-menu-hidden-opacity - `opacity` of menu when hiding.
* @cssproperty --media-menu-transform-in - `transform` of menu when showing.
* @cssproperty --media-menu-transform-out - `transform` of menu when hiding.
*
* @cssproperty --media-font - `font` shorthand property.
* @cssproperty --media-font-weight - `font-weight` property.
* @cssproperty --media-font-family - `font-family` property.
* @cssproperty --media-font-size - `font-size` property.
* @cssproperty --media-text-content-height - `line-height` of text.
*
* @cssproperty --media-icon-color - `fill` color of icon.
* @cssproperty --media-menu-icon-height - `height` of icon.
* @cssproperty --media-menu-item-checked-indicator-display - `display` of check indicator.
* @cssproperty --media-menu-item-checked-background - `background` of checked menu item.
* @cssproperty --media-menu-item-max-width - `max-width` of menu item text.
*/
declare class MediaChromeMenu extends globalThis.HTMLElement {
#private;
static template: HTMLTemplateElement;
static get observedAttributes(): string[];
static formatMenuItemText(text: string): string;
nativeEl: HTMLElement;
container: HTMLElement;
defaultSlot: HTMLSlotElement;
constructor();
enable(): void;
disable(): void;
handleEvent(event: Event): void;
connectedCallback(): void;
disconnectedCallback(): void;
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
formatMenuItemText(text: string, data?: any): any;
get anchor(): string;
set anchor(value: string);
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement(): HTMLElement;
/**
* Returns the menu items.
*/
get items(): MediaChromeMenuItem[];
get radioGroupItems(): MediaChromeMenuItem[];
get checkedItems(): MediaChromeMenuItem[];
get value(): string;
set value(newValue: string);
focus(): void;
handleSelect(event: MouseEvent | KeyboardEvent): void;
get keysUsed(): string[];
handleMove(event: KeyboardEvent): void;
}
export { MediaChromeMenu };
export default MediaChromeMenu;

View File

@@ -0,0 +1,818 @@
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 _mediaController, _previouslyFocused, _invokerElement, _previousItems, _mutationObserver, _isPopover, _cssRule, _handleSlotChange, handleSlotChange_fn, _handleMenuItems, _updateLayoutStyle, updateLayoutStyle_fn, _handleInvoke, handleInvoke_fn, _handleOpen, handleOpen_fn, _handleClosed, handleClosed_fn, _handleBoundsResize, _handleMenuResize, _positionMenu, positionMenu_fn, _resizeMenu, resizeMenu_fn, _handleClick, handleClick_fn, _backButtonElement, backButtonElement_get, _handleToggle, handleToggle_fn, _checkSubmenuHasExpanded, checkSubmenuHasExpanded_fn, _handleFocusOut, handleFocusOut_fn, _handleKeyDown, handleKeyDown_fn, _getItem, getItem_fn, _getTabItem, getTabItem_fn, _setTabItem, setTabItem_fn, _selectItem, selectItem_fn;
import { MediaStateReceiverAttributes } from "../constants.js";
import { globalThis, document } from "../utils/server-safe-globals.js";
import { computePosition } from "../utils/anchor-utils.js";
import { observeResize, unobserveResize } from "../utils/resize-observer.js";
import { ToggleEvent, InvokeEvent } from "../utils/events.js";
import {
getActiveElement,
containsComposedNode,
closestComposedNode,
insertCSSRule,
getMediaController,
getAttributeMediaController,
getDocumentOrShadowRoot
} from "../utils/element-utils.js";
function createMenuItem({
type,
text,
value,
checked
}) {
const item = document.createElement(
"media-chrome-menu-item"
);
item.type = type != null ? type : "";
item.part.add("menu-item");
if (type)
item.part.add(type);
item.value = value;
item.checked = checked;
const label = document.createElement("span");
label.textContent = text;
item.append(label);
return item;
}
function createIndicator(el, name) {
let customIndicator = el.querySelector(`:scope > [slot="${name}"]`);
if ((customIndicator == null ? void 0 : customIndicator.nodeName) == "SLOT")
customIndicator = customIndicator.assignedElements({ flatten: true })[0];
if (customIndicator) {
customIndicator = customIndicator.cloneNode(true);
return customIndicator;
}
const fallbackIndicator = el.shadowRoot.querySelector(
`[name="${name}"] > svg`
);
if (fallbackIndicator) {
return fallbackIndicator.cloneNode(true);
}
return "";
}
const template = document.createElement("template");
template.innerHTML = /*html*/
`
<style>
:host {
font: var(--media-font,
var(--media-font-weight, normal)
var(--media-font-size, 14px) /
var(--media-text-content-height, var(--media-control-height, 24px))
var(--media-font-family, helvetica neue, segoe ui, roboto, arial, sans-serif));
color: var(--media-text-color, var(--media-primary-color, rgb(238 238 238)));
background: var(--media-menu-background, var(--media-control-background, var(--media-secondary-color, rgb(20 20 30 / .8))));
border-radius: var(--media-menu-border-radius);
border: var(--media-menu-border, none);
display: var(--media-menu-display, inline-flex);
transition: var(--media-menu-transition-in,
visibility 0s,
opacity .2s ease-out,
transform .15s ease-out,
left .2s ease-in-out,
min-width .2s ease-in-out,
min-height .2s ease-in-out
) !important;
${/* ^^Prevent transition override by media-container */
""}
visibility: var(--media-menu-visibility, visible);
opacity: var(--media-menu-opacity, 1);
max-height: var(--media-menu-max-height, var(--_menu-max-height, 300px));
transform: var(--media-menu-transform-in, translateY(0) scale(1));
flex-direction: column;
${/* Prevent overflowing a flex container */
""}
min-height: 0;
position: relative;
bottom: var(--_menu-bottom);
box-sizing: border-box;
}
:host([hidden]) {
transition: var(--media-menu-transition-out,
visibility .15s ease-in,
opacity .15s ease-in,
transform .15s ease-in
) !important;
visibility: var(--media-menu-hidden-visibility, hidden);
opacity: var(--media-menu-hidden-opacity, 0);
max-height: var(--media-menu-hidden-max-height,
var(--media-menu-max-height, var(--_menu-max-height, 300px)));
transform: var(--media-menu-transform-out, translateY(2px) scale(.99));
pointer-events: none;
}
:host([slot="submenu"]) {
background: none;
width: 100%;
min-height: 100%;
position: absolute;
bottom: 0;
right: -100%;
}
#container {
display: flex;
flex-direction: column;
min-height: 0;
transition: transform .2s ease-out;
transform: translate(0, 0);
}
#container.has-expanded {
transition: transform .2s ease-in;
transform: translate(-100%, 0);
}
button {
background: none;
color: inherit;
border: none;
padding: 0;
font: inherit;
outline: inherit;
display: inline-flex;
align-items: center;
}
slot[name="header"][hidden] {
display: none;
}
slot[name="header"] > *,
slot[name="header"]::slotted(*) {
padding: .4em .7em;
border-bottom: 1px solid rgb(255 255 255 / .25);
cursor: default;
}
slot[name="header"] > button[part~="back"],
slot[name="header"]::slotted(button[part~="back"]) {
cursor: pointer;
}
svg[part~="back"] {
height: var(--media-menu-icon-height, var(--media-control-height, 24px));
fill: var(--media-icon-color, var(--media-primary-color, rgb(238 238 238)));
display: block;
margin-right: .5ch;
}
slot:not([name]) {
gap: var(--media-menu-gap);
flex-direction: var(--media-menu-flex-direction, column);
overflow: var(--media-menu-overflow, hidden auto);
display: flex;
min-height: 0;
}
:host([role="menu"]) slot:not([name]) {
padding-block: .4em;
}
slot:not([name])::slotted([role="menu"]) {
background: none;
}
media-chrome-menu-item > span {
margin-right: .5ch;
max-width: var(--media-menu-item-max-width);
text-overflow: ellipsis;
overflow: hidden;
}
</style>
<style id="layout-row" media="width:0">
slot[name="header"] > *,
slot[name="header"]::slotted(*) {
padding: .4em .5em;
}
slot:not([name]) {
gap: var(--media-menu-gap, .25em);
flex-direction: var(--media-menu-flex-direction, row);
padding-inline: .5em;
}
media-chrome-menu-item {
padding: .3em .5em;
}
media-chrome-menu-item[aria-checked="true"] {
background: var(--media-menu-item-checked-background, rgb(255 255 255 / .2));
}
${/* In row layout hide the checked indicator completely. */
""}
media-chrome-menu-item::part(checked-indicator) {
display: var(--media-menu-item-checked-indicator-display, none);
}
</style>
<div id="container">
<slot name="header" hidden>
<button part="back button" aria-label="Back to previous menu">
<slot name="back-icon">
<svg aria-hidden="true" viewBox="0 0 20 24" part="back indicator">
<path d="m11.88 17.585.742-.669-4.2-4.665 4.2-4.666-.743-.669-4.803 5.335 4.803 5.334Z"/>
</svg>
</slot>
<slot name="title"></slot>
</button>
</slot>
<slot></slot>
</div>
<slot name="checked-indicator" hidden></slot>
`;
const Attributes = {
STYLE: "style",
HIDDEN: "hidden",
DISABLED: "disabled",
ANCHOR: "anchor"
};
class MediaChromeMenu extends globalThis.HTMLElement {
constructor() {
super();
__privateAdd(this, _handleSlotChange);
/**
* Sets the layout style for the menu.
* It can be a row or column layout. e.g. playback-rate-menu
*/
__privateAdd(this, _updateLayoutStyle);
__privateAdd(this, _handleInvoke);
__privateAdd(this, _handleOpen);
__privateAdd(this, _handleClosed);
/**
* Updates the popover menu position based on the anchor element.
* @param {number} [menuWidth]
*/
__privateAdd(this, _positionMenu);
/**
* Resize this menu to fit the submenu.
* @param {boolean} animate
*/
__privateAdd(this, _resizeMenu);
__privateAdd(this, _handleClick);
__privateAdd(this, _backButtonElement);
/**
* Handle the toggle event of submenus.
* Closes all other open submenus when opening a submenu.
* Resizes this menu to fit the submenu.
*
* @param {ToggleEvent} event
*/
__privateAdd(this, _handleToggle);
/**
* Check if any submenu is expanded and update the container class accordingly.
* When the CSS :has() selector is supported, this can be done with CSS only.
*/
__privateAdd(this, _checkSubmenuHasExpanded);
__privateAdd(this, _handleFocusOut);
__privateAdd(this, _handleKeyDown);
__privateAdd(this, _getItem);
__privateAdd(this, _getTabItem);
__privateAdd(this, _setTabItem);
__privateAdd(this, _selectItem);
__privateAdd(this, _mediaController, null);
__privateAdd(this, _previouslyFocused, null);
__privateAdd(this, _invokerElement, null);
__privateAdd(this, _previousItems, /* @__PURE__ */ new Set());
__privateAdd(this, _mutationObserver, void 0);
__privateAdd(this, _isPopover, false);
__privateAdd(this, _cssRule, null);
/**
* Fires an event when a menu item is added or removed.
* This is needed to update the description slot of an ancestor menu item.
*/
__privateAdd(this, _handleMenuItems, () => {
const previousItems = __privateGet(this, _previousItems);
const currentItems = new Set(this.items);
for (const item of previousItems) {
if (!currentItems.has(item)) {
this.dispatchEvent(new CustomEvent("removemenuitem", { detail: item }));
}
}
for (const item of currentItems) {
if (!previousItems.has(item)) {
this.dispatchEvent(new CustomEvent("addmenuitem", { detail: item }));
}
}
__privateSet(this, _previousItems, currentItems);
});
__privateAdd(this, _handleBoundsResize, () => {
__privateMethod(this, _positionMenu, positionMenu_fn).call(this);
__privateMethod(this, _resizeMenu, resizeMenu_fn).call(this, false);
});
__privateAdd(this, _handleMenuResize, () => {
__privateMethod(this, _positionMenu, positionMenu_fn).call(this);
});
if (!this.shadowRoot) {
this.attachShadow({ mode: "open" });
this.nativeEl = this.constructor.template.content.cloneNode(true);
this.shadowRoot.append(this.nativeEl);
}
this.container = this.shadowRoot.querySelector("#container");
this.defaultSlot = this.shadowRoot.querySelector(
"slot:not([name])"
);
this.shadowRoot.addEventListener("slotchange", this);
__privateSet(this, _mutationObserver, new MutationObserver(__privateGet(this, _handleMenuItems)));
__privateGet(this, _mutationObserver).observe(this.defaultSlot, { childList: true });
}
static get observedAttributes() {
return [
Attributes.DISABLED,
Attributes.HIDDEN,
Attributes.STYLE,
Attributes.ANCHOR,
MediaStateReceiverAttributes.MEDIA_CONTROLLER
];
}
static formatMenuItemText(text) {
return text;
}
enable() {
this.addEventListener("click", this);
this.addEventListener("focusout", this);
this.addEventListener("keydown", this);
this.addEventListener("invoke", this);
this.addEventListener("toggle", this);
}
disable() {
this.removeEventListener("click", this);
this.removeEventListener("focusout", this);
this.removeEventListener("keyup", this);
this.removeEventListener("invoke", this);
this.removeEventListener("toggle", this);
}
handleEvent(event) {
switch (event.type) {
case "slotchange":
__privateMethod(this, _handleSlotChange, handleSlotChange_fn).call(this, event);
break;
case "invoke":
__privateMethod(this, _handleInvoke, handleInvoke_fn).call(this, event);
break;
case "click":
__privateMethod(this, _handleClick, handleClick_fn).call(this, event);
break;
case "toggle":
__privateMethod(this, _handleToggle, handleToggle_fn).call(this, event);
break;
case "focusout":
__privateMethod(this, _handleFocusOut, handleFocusOut_fn).call(this, event);
break;
case "keydown":
__privateMethod(this, _handleKeyDown, handleKeyDown_fn).call(this, event);
break;
}
}
connectedCallback() {
var _a, _b;
__privateSet(this, _cssRule, insertCSSRule(this.shadowRoot, ":host"));
__privateMethod(this, _updateLayoutStyle, updateLayoutStyle_fn).call(this);
if (!this.hasAttribute("disabled")) {
this.enable();
}
if (!this.role) {
this.role = "menu";
}
__privateSet(this, _mediaController, getAttributeMediaController(this));
(_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.associateElement) == null ? void 0 : _b.call(_a, this);
if (!this.hidden) {
observeResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));
observeResize(this, __privateGet(this, _handleMenuResize));
}
}
disconnectedCallback() {
var _a, _b;
unobserveResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));
unobserveResize(this, __privateGet(this, _handleMenuResize));
this.disable();
(_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);
__privateSet(this, _mediaController, null);
}
attributeChangedCallback(attrName, oldValue, newValue) {
var _a, _b, _c, _d;
if (attrName === Attributes.HIDDEN && newValue !== oldValue) {
if (!__privateGet(this, _isPopover))
__privateSet(this, _isPopover, true);
if (this.hidden) {
__privateMethod(this, _handleClosed, handleClosed_fn).call(this);
} else {
__privateMethod(this, _handleOpen, handleOpen_fn).call(this);
}
this.dispatchEvent(
new ToggleEvent({
oldState: this.hidden ? "open" : "closed",
newState: this.hidden ? "closed" : "open",
bubbles: true
})
);
} else if (attrName === MediaStateReceiverAttributes.MEDIA_CONTROLLER) {
if (oldValue) {
(_b = (_a = __privateGet(this, _mediaController)) == null ? void 0 : _a.unassociateElement) == null ? void 0 : _b.call(_a, this);
__privateSet(this, _mediaController, null);
}
if (newValue && this.isConnected) {
__privateSet(this, _mediaController, getAttributeMediaController(this));
(_d = (_c = __privateGet(this, _mediaController)) == null ? void 0 : _c.associateElement) == null ? void 0 : _d.call(_c, this);
}
} else if (attrName === Attributes.DISABLED && newValue !== oldValue) {
if (newValue == null) {
this.enable();
} else {
this.disable();
}
} else if (attrName === Attributes.STYLE && newValue !== oldValue) {
__privateMethod(this, _updateLayoutStyle, updateLayoutStyle_fn).call(this);
}
}
formatMenuItemText(text, data) {
return this.constructor.formatMenuItemText(text, data);
}
get anchor() {
return this.getAttribute("anchor");
}
set anchor(value) {
this.setAttribute("anchor", `${value}`);
}
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement() {
var _a;
if (this.anchor) {
return (_a = getDocumentOrShadowRoot(this)) == null ? void 0 : _a.querySelector(`#${this.anchor}`);
}
return null;
}
/**
* Returns the menu items.
*/
get items() {
return this.defaultSlot.assignedElements({ flatten: true }).filter(isMenuItem);
}
get radioGroupItems() {
return this.items.filter((item) => item.role === "menuitemradio");
}
get checkedItems() {
return this.items.filter((item) => item.checked);
}
get value() {
var _a, _b;
return (_b = (_a = this.checkedItems[0]) == null ? void 0 : _a.value) != null ? _b : "";
}
set value(newValue) {
const item = this.items.find((item2) => item2.value === newValue);
if (!item)
return;
__privateMethod(this, _selectItem, selectItem_fn).call(this, item);
}
focus() {
__privateSet(this, _previouslyFocused, getActiveElement());
if (this.items.length) {
__privateMethod(this, _setTabItem, setTabItem_fn).call(this, this.items[0]);
this.items[0].focus();
return;
}
const focusable = this.querySelector(
'[autofocus], [tabindex]:not([tabindex="-1"]), [role="menu"]'
);
focusable == null ? void 0 : focusable.focus();
}
handleSelect(event) {
var _a;
const item = __privateMethod(this, _getItem, getItem_fn).call(this, event);
if (!item)
return;
__privateMethod(this, _selectItem, selectItem_fn).call(this, item, item.type === "checkbox");
if (__privateGet(this, _invokerElement) && !this.hidden) {
(_a = __privateGet(this, _previouslyFocused)) == null ? void 0 : _a.focus();
this.hidden = true;
}
}
get keysUsed() {
return [
"Enter",
"Escape",
"Tab",
" ",
"ArrowDown",
"ArrowUp",
"Home",
"End"
];
}
handleMove(event) {
var _a, _b;
const { key } = event;
const items = this.items;
const currentItem = (_b = (_a = __privateMethod(this, _getItem, getItem_fn).call(this, event)) != null ? _a : __privateMethod(this, _getTabItem, getTabItem_fn).call(this)) != null ? _b : items[0];
const currentIndex = items.indexOf(currentItem);
let index = Math.max(0, currentIndex);
if (key === "ArrowDown") {
index++;
} else if (key === "ArrowUp") {
index--;
} else if (event.key === "Home") {
index = 0;
} else if (event.key === "End") {
index = items.length - 1;
}
if (index < 0) {
index = items.length - 1;
}
if (index > items.length - 1) {
index = 0;
}
__privateMethod(this, _setTabItem, setTabItem_fn).call(this, items[index]);
items[index].focus();
}
}
_mediaController = new WeakMap();
_previouslyFocused = new WeakMap();
_invokerElement = new WeakMap();
_previousItems = new WeakMap();
_mutationObserver = new WeakMap();
_isPopover = new WeakMap();
_cssRule = new WeakMap();
_handleSlotChange = new WeakSet();
handleSlotChange_fn = function(event) {
const slot = event.target;
for (const node of slot.assignedNodes({ flatten: true })) {
if (node.nodeType === 3 && node.textContent.trim() === "") {
node.remove();
}
}
if (["header", "title"].includes(slot.name)) {
const header = this.shadowRoot.querySelector(
'slot[name="header"]'
);
header.hidden = slot.assignedNodes().length === 0;
}
if (!slot.name) {
__privateGet(this, _handleMenuItems).call(this);
}
};
_handleMenuItems = new WeakMap();
_updateLayoutStyle = new WeakSet();
updateLayoutStyle_fn = function() {
var _a;
const layoutRowStyle = this.shadowRoot.querySelector("#layout-row");
const menuLayout = (_a = getComputedStyle(this).getPropertyValue("--media-menu-layout")) == null ? void 0 : _a.trim();
layoutRowStyle.setAttribute("media", menuLayout === "row" ? "" : "width:0");
};
_handleInvoke = new WeakSet();
handleInvoke_fn = function(event) {
__privateSet(this, _invokerElement, event.relatedTarget);
if (!containsComposedNode(this, event.relatedTarget)) {
this.hidden = !this.hidden;
}
};
_handleOpen = new WeakSet();
handleOpen_fn = function() {
var _a;
(_a = __privateGet(this, _invokerElement)) == null ? void 0 : _a.setAttribute("aria-expanded", "true");
this.addEventListener("transitionend", () => this.focus(), { once: true });
observeResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));
observeResize(this, __privateGet(this, _handleMenuResize));
};
_handleClosed = new WeakSet();
handleClosed_fn = function() {
var _a;
(_a = __privateGet(this, _invokerElement)) == null ? void 0 : _a.setAttribute("aria-expanded", "false");
unobserveResize(getBoundsElement(this), __privateGet(this, _handleBoundsResize));
unobserveResize(this, __privateGet(this, _handleMenuResize));
};
_handleBoundsResize = new WeakMap();
_handleMenuResize = new WeakMap();
_positionMenu = new WeakSet();
positionMenu_fn = function(menuWidth) {
if (this.hasAttribute("mediacontroller") && !this.anchor)
return;
if (this.hidden || !this.anchorElement)
return;
const { x, y } = computePosition({
anchor: this.anchorElement,
floating: this,
placement: "top-start"
});
menuWidth != null ? menuWidth : menuWidth = this.offsetWidth;
const bounds = getBoundsElement(this);
const boundsRect = bounds.getBoundingClientRect();
const right = boundsRect.width - x - menuWidth;
const bottom = boundsRect.height - y - this.offsetHeight;
const { style } = __privateGet(this, _cssRule);
style.setProperty("position", "absolute");
style.setProperty("right", `${Math.max(0, right)}px`);
style.setProperty("--_menu-bottom", `${bottom}px`);
const computedStyle = getComputedStyle(this);
const isBottomCalc = style.getPropertyValue("--_menu-bottom") === computedStyle.bottom;
const realBottom = isBottomCalc ? bottom : parseFloat(computedStyle.bottom);
const maxHeight = boundsRect.height - realBottom - parseFloat(computedStyle.marginBottom);
this.style.setProperty("--_menu-max-height", `${maxHeight}px`);
};
_resizeMenu = new WeakSet();
resizeMenu_fn = function(animate) {
const expandedMenuItem = this.querySelector(
'[role="menuitem"][aria-haspopup][aria-expanded="true"]'
);
const expandedSubmenu = expandedMenuItem == null ? void 0 : expandedMenuItem.querySelector(
'[role="menu"]'
);
const { style } = __privateGet(this, _cssRule);
if (!animate) {
style.setProperty("--media-menu-transition-in", "none");
}
if (expandedSubmenu) {
const height = expandedSubmenu.offsetHeight;
const width = Math.max(
expandedSubmenu.offsetWidth,
expandedMenuItem.offsetWidth
);
this.style.setProperty("min-width", `${width}px`);
this.style.setProperty("min-height", `${height}px`);
__privateMethod(this, _positionMenu, positionMenu_fn).call(this, width);
} else {
this.style.removeProperty("min-width");
this.style.removeProperty("min-height");
__privateMethod(this, _positionMenu, positionMenu_fn).call(this);
}
style.removeProperty("--media-menu-transition-in");
};
_handleClick = new WeakSet();
handleClick_fn = function(event) {
var _a;
event.stopPropagation();
if (event.composedPath().includes(__privateGet(this, _backButtonElement, backButtonElement_get))) {
(_a = __privateGet(this, _previouslyFocused)) == null ? void 0 : _a.focus();
this.hidden = true;
return;
}
const item = __privateMethod(this, _getItem, getItem_fn).call(this, event);
if (!item || item.hasAttribute("disabled"))
return;
__privateMethod(this, _setTabItem, setTabItem_fn).call(this, item);
this.handleSelect(event);
};
_backButtonElement = new WeakSet();
backButtonElement_get = function() {
var _a;
const headerSlot = this.shadowRoot.querySelector(
'slot[name="header"]'
);
return (_a = headerSlot.assignedElements({ flatten: true })) == null ? void 0 : _a.find(
(el) => el.matches('button[part~="back"]')
);
};
_handleToggle = new WeakSet();
handleToggle_fn = function(event) {
if (event.target === this)
return;
__privateMethod(this, _checkSubmenuHasExpanded, checkSubmenuHasExpanded_fn).call(this);
const menuItemsWithSubmenu = Array.from(
this.querySelectorAll('[role="menuitem"][aria-haspopup]')
);
for (const item of menuItemsWithSubmenu) {
if (item.invokeTargetElement == event.target)
continue;
if (event.newState == "open" && item.getAttribute("aria-expanded") == "true" && !item.invokeTargetElement.hidden) {
item.invokeTargetElement.dispatchEvent(
new InvokeEvent({ relatedTarget: item })
);
}
}
for (const item of menuItemsWithSubmenu) {
item.setAttribute("aria-expanded", `${!item.submenuElement.hidden}`);
}
__privateMethod(this, _resizeMenu, resizeMenu_fn).call(this, true);
};
_checkSubmenuHasExpanded = new WeakSet();
checkSubmenuHasExpanded_fn = function() {
const selector = '[role="menuitem"] > [role="menu"]:not([hidden])';
const expandedMenuItem = this.querySelector(selector);
this.container.classList.toggle("has-expanded", !!expandedMenuItem);
};
_handleFocusOut = new WeakSet();
handleFocusOut_fn = function(event) {
var _a;
if (!containsComposedNode(this, event.relatedTarget)) {
if (__privateGet(this, _isPopover)) {
(_a = __privateGet(this, _previouslyFocused)) == null ? void 0 : _a.focus();
}
if (__privateGet(this, _invokerElement) && __privateGet(this, _invokerElement) !== event.relatedTarget && !this.hidden) {
this.hidden = true;
}
}
};
_handleKeyDown = new WeakSet();
handleKeyDown_fn = function(event) {
var _a, _b, _c, _d, _e;
const { key, ctrlKey, altKey, metaKey } = event;
if (ctrlKey || altKey || metaKey) {
return;
}
if (!this.keysUsed.includes(key)) {
return;
}
event.preventDefault();
event.stopPropagation();
if (key === "Tab") {
if (__privateGet(this, _isPopover)) {
this.hidden = true;
return;
}
if (event.shiftKey) {
(_b = (_a = this.previousElementSibling) == null ? void 0 : _a.focus) == null ? void 0 : _b.call(_a);
} else {
(_d = (_c = this.nextElementSibling) == null ? void 0 : _c.focus) == null ? void 0 : _d.call(_c);
}
this.blur();
} else if (key === "Escape") {
(_e = __privateGet(this, _previouslyFocused)) == null ? void 0 : _e.focus();
if (__privateGet(this, _isPopover)) {
this.hidden = true;
}
} else if (key === "Enter" || key === " ") {
this.handleSelect(event);
} else {
this.handleMove(event);
}
};
_getItem = new WeakSet();
getItem_fn = function(event) {
return event.composedPath().find((el) => {
return ["menuitemradio", "menuitemcheckbox"].includes(
el.role
);
});
};
_getTabItem = new WeakSet();
getTabItem_fn = function() {
return this.items.find((item) => item.tabIndex === 0);
};
_setTabItem = new WeakSet();
setTabItem_fn = function(tabItem) {
for (const item of this.items) {
item.tabIndex = item === tabItem ? 0 : -1;
}
};
_selectItem = new WeakSet();
selectItem_fn = function(item, toggle) {
const oldCheckedItems = [...this.checkedItems];
if (item.type === "radio") {
this.radioGroupItems.forEach((el) => el.checked = false);
}
if (toggle) {
item.checked = !item.checked;
} else {
item.checked = true;
}
if (this.checkedItems.some((opt, i) => opt != oldCheckedItems[i])) {
this.dispatchEvent(
new Event("change", { bubbles: true, composed: true })
);
}
};
MediaChromeMenu.template = template;
function isMenuItem(element) {
return ["menuitem", "menuitemradio", "menuitemcheckbox"].includes(
element == null ? void 0 : element.role
);
}
function getBoundsElement(host) {
var _a;
return (_a = host.getAttribute("bounds") ? closestComposedNode(host, `#${host.getAttribute("bounds")}`) : getMediaController(host) || host.parentElement) != null ? _a : host;
}
if (!globalThis.customElements.get("media-chrome-menu")) {
globalThis.customElements.define("media-chrome-menu", MediaChromeMenu);
}
var media_chrome_menu_default = MediaChromeMenu;
export {
Attributes,
MediaChromeMenu,
createIndicator,
createMenuItem,
media_chrome_menu_default as default
};

View File

@@ -0,0 +1,37 @@
import { MediaChromeMenuButton } from './media-chrome-menu-button.js';
import { AttributeTokenList } from '../utils/attribute-token-list.js';
export declare const Attributes: {
RATES: string;
};
export declare const DEFAULT_RATES: number[];
export declare const DEFAULT_RATE = 1;
/**
* @attr {string} rates - Set custom playback rates for the user to choose from.
* @attr {string} mediaplaybackrate - (read-only) Set to the media playback rate.
*
* @cssproperty [--media-playback-rate-menu-button-display = inline-flex] - `display` property of button.
*/
declare class MediaPlaybackRateMenuButton extends MediaChromeMenuButton {
#private;
static get observedAttributes(): string[];
container: HTMLSlotElement;
constructor(options?: {});
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
/**
* Returns the element with the id specified by the `invoketarget` attribute.
*/
get invokeTargetElement(): HTMLElement | null;
/**
* Will return a DOMTokenList.
* Setting a value will accept an array of numbers.
*/
get rates(): AttributeTokenList | number[] | undefined;
set rates(value: AttributeTokenList | number[] | undefined);
/**
* The current playback rate
*/
get mediaPlaybackRate(): number;
set mediaPlaybackRate(value: number);
}
export { MediaPlaybackRateMenuButton };
export default MediaPlaybackRateMenuButton;

View File

@@ -0,0 +1,127 @@
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 _rates;
import { globalThis, document } from "../utils/server-safe-globals.js";
import { MediaUIAttributes } from "../constants.js";
import { nouns, tooltipLabels } from "../labels/labels.js";
import { MediaChromeMenuButton } from "./media-chrome-menu-button.js";
import { AttributeTokenList } from "../utils/attribute-token-list.js";
import {
getNumericAttr,
setNumericAttr,
getMediaController
} from "../utils/element-utils.js";
const Attributes = {
RATES: "rates"
};
const DEFAULT_RATES = [1, 1.2, 1.5, 1.7, 2];
const DEFAULT_RATE = 1;
const slotTemplate = document.createElement("template");
slotTemplate.innerHTML = /*html*/
`
<style>
:host {
min-width: 5ch;
padding: var(--media-button-padding, var(--media-control-padding, 10px 5px));
}
:host([aria-expanded="true"]) slot[name=tooltip] {
display: none;
}
</style>
<slot name="icon"></slot>
`;
class MediaPlaybackRateMenuButton extends MediaChromeMenuButton {
constructor(options = {}) {
super({
slotTemplate,
tooltipContent: tooltipLabels.PLAYBACK_RATE,
...options
});
__privateAdd(this, _rates, new AttributeTokenList(this, Attributes.RATES, {
defaultValue: DEFAULT_RATES
}));
this.container = this.shadowRoot.querySelector('slot[name="icon"]');
this.container.innerHTML = `${DEFAULT_RATE}x`;
}
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_PLAYBACK_RATE,
Attributes.RATES
];
}
attributeChangedCallback(attrName, oldValue, newValue) {
super.attributeChangedCallback(attrName, oldValue, newValue);
if (attrName === Attributes.RATES) {
__privateGet(this, _rates).value = newValue;
}
if (attrName === MediaUIAttributes.MEDIA_PLAYBACK_RATE) {
const newPlaybackRate = newValue ? +newValue : Number.NaN;
const playbackRate = !Number.isNaN(newPlaybackRate) ? newPlaybackRate : DEFAULT_RATE;
this.container.innerHTML = `${playbackRate}x`;
this.setAttribute("aria-label", nouns.PLAYBACK_RATE({ playbackRate }));
}
}
/**
* Returns the element with the id specified by the `invoketarget` attribute.
*/
get invokeTargetElement() {
if (this.invokeTarget != void 0)
return super.invokeTargetElement;
return getMediaController(this).querySelector("media-playback-rate-menu");
}
/**
* Will return a DOMTokenList.
* Setting a value will accept an array of numbers.
*/
get rates() {
return __privateGet(this, _rates);
}
set rates(value) {
if (!value) {
__privateGet(this, _rates).value = "";
} else if (Array.isArray(value)) {
__privateGet(this, _rates).value = value.join(" ");
}
}
/**
* The current playback rate
*/
get mediaPlaybackRate() {
return getNumericAttr(
this,
MediaUIAttributes.MEDIA_PLAYBACK_RATE,
DEFAULT_RATE
);
}
set mediaPlaybackRate(value) {
setNumericAttr(this, MediaUIAttributes.MEDIA_PLAYBACK_RATE, value);
}
}
_rates = new WeakMap();
if (!globalThis.customElements.get("media-playback-rate-menu-button")) {
globalThis.customElements.define(
"media-playback-rate-menu-button",
MediaPlaybackRateMenuButton
);
}
var media_playback_rate_menu_button_default = MediaPlaybackRateMenuButton;
export {
Attributes,
DEFAULT_RATE,
DEFAULT_RATES,
MediaPlaybackRateMenuButton,
media_playback_rate_menu_button_default as default
};

View File

@@ -0,0 +1,40 @@
import { AttributeTokenList } from '../utils/attribute-token-list.js';
import { MediaChromeMenu } from './media-chrome-menu.js';
export declare const Attributes: {
RATES: string;
};
/**
* @extends {MediaChromeMenu}
*
* @slot - Default slotted elements.
* @slot header - An element shown at the top of the menu.
* @slot checked-indicator - An icon element indicating a checked menu-item.
*
* @attr {string} rates - Set custom playback rates for the user to choose from.
* @attr {string} mediaplaybackrate - (read-only) Set to the media playback rate.
*/
declare class MediaPlaybackRateMenu extends MediaChromeMenu {
#private;
static get observedAttributes(): string[];
constructor();
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
connectedCallback(): void;
disconnectedCallback(): void;
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement(): HTMLElement;
/**
* Will return a DOMTokenList.
* Setting a value will accept an array of numbers.
*/
get rates(): AttributeTokenList | number[] | undefined;
set rates(value: AttributeTokenList | number[] | undefined);
/**
* The current playback rate
*/
get mediaPlaybackRate(): number;
set mediaPlaybackRate(value: number);
}
export { MediaPlaybackRateMenu };
export default MediaPlaybackRateMenu;

View File

@@ -0,0 +1,149 @@
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 __privateMethod = (obj, member, method) => {
__accessCheck(obj, member, "access private method");
return method;
};
var _rates, _render, render_fn, _onChange, onChange_fn;
import { globalThis } from "../utils/server-safe-globals.js";
import { MediaUIAttributes, MediaUIEvents } from "../constants.js";
import { AttributeTokenList } from "../utils/attribute-token-list.js";
import {
getNumericAttr,
setNumericAttr,
getMediaController
} from "../utils/element-utils.js";
import { DEFAULT_RATES, DEFAULT_RATE } from "../media-playback-rate-button.js";
import {
MediaChromeMenu,
createMenuItem,
createIndicator
} from "./media-chrome-menu.js";
const Attributes = {
RATES: "rates"
};
class MediaPlaybackRateMenu extends MediaChromeMenu {
constructor() {
super();
__privateAdd(this, _render);
__privateAdd(this, _onChange);
__privateAdd(this, _rates, new AttributeTokenList(this, Attributes.RATES, {
defaultValue: DEFAULT_RATES
}));
__privateMethod(this, _render, render_fn).call(this);
}
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_PLAYBACK_RATE,
Attributes.RATES
];
}
attributeChangedCallback(attrName, oldValue, newValue) {
super.attributeChangedCallback(attrName, oldValue, newValue);
if (attrName === MediaUIAttributes.MEDIA_PLAYBACK_RATE && oldValue != newValue) {
this.value = newValue;
} else if (attrName === Attributes.RATES && oldValue != newValue) {
__privateGet(this, _rates).value = newValue;
__privateMethod(this, _render, render_fn).call(this);
}
}
connectedCallback() {
super.connectedCallback();
this.addEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement() {
if (this.anchor !== "auto")
return super.anchorElement;
return getMediaController(this).querySelector(
"media-playback-rate-menu-button"
);
}
/**
* Will return a DOMTokenList.
* Setting a value will accept an array of numbers.
*/
get rates() {
return __privateGet(this, _rates);
}
set rates(value) {
if (!value) {
__privateGet(this, _rates).value = "";
} else if (Array.isArray(value)) {
__privateGet(this, _rates).value = value.join(" ");
}
__privateMethod(this, _render, render_fn).call(this);
}
/**
* The current playback rate
*/
get mediaPlaybackRate() {
return getNumericAttr(
this,
MediaUIAttributes.MEDIA_PLAYBACK_RATE,
DEFAULT_RATE
);
}
set mediaPlaybackRate(value) {
setNumericAttr(this, MediaUIAttributes.MEDIA_PLAYBACK_RATE, value);
}
}
_rates = new WeakMap();
_render = new WeakSet();
render_fn = function() {
this.defaultSlot.textContent = "";
for (const rate of this.rates) {
const item = createMenuItem({
type: "radio",
text: this.formatMenuItemText(`${rate}x`, rate),
value: rate,
checked: this.mediaPlaybackRate == rate
});
item.prepend(createIndicator(this, "checked-indicator"));
this.defaultSlot.append(item);
}
};
_onChange = new WeakSet();
onChange_fn = function() {
if (!this.value)
return;
const event = new globalThis.CustomEvent(
MediaUIEvents.MEDIA_PLAYBACK_RATE_REQUEST,
{
composed: true,
bubbles: true,
detail: this.value
}
);
this.dispatchEvent(event);
};
if (!globalThis.customElements.get("media-playback-rate-menu")) {
globalThis.customElements.define(
"media-playback-rate-menu",
MediaPlaybackRateMenu
);
}
var media_playback_rate_menu_default = MediaPlaybackRateMenu;
export {
Attributes,
MediaPlaybackRateMenu,
media_playback_rate_menu_default as default
};

View File

@@ -0,0 +1,25 @@
import { MediaChromeMenuButton } from './media-chrome-menu-button.js';
/**
* @attr {string} mediarenditionselected - (read-only) Set to the selected rendition id.
* @attr {(unavailable|unsupported)} mediarenditionunavailable - (read-only) Set if rendition selection is unavailable.
*
* @cssproperty [--media-rendition-menu-button-display = inline-flex] - `display` property of button.
*/
declare class MediaRenditionMenuButton extends MediaChromeMenuButton {
static get observedAttributes(): string[];
constructor();
connectedCallback(): void;
/**
* Returns the element with the id specified by the `invoketarget` attribute.
*/
get invokeTargetElement(): HTMLElement | null;
/**
* Get selected rendition id.
*/
get mediaRenditionSelected(): string;
set mediaRenditionSelected(id: string);
get mediaHeight(): number;
set mediaHeight(height: number);
}
export { MediaRenditionMenuButton };
export default MediaRenditionMenuButton;

View File

@@ -0,0 +1,78 @@
import { MediaUIAttributes } from "../constants.js";
import { MediaChromeMenuButton } from "./media-chrome-menu-button.js";
import { globalThis, document } from "../utils/server-safe-globals.js";
import { nouns, tooltipLabels } from "../labels/labels.js";
import {
getStringAttr,
setStringAttr,
getMediaController,
getNumericAttr,
setNumericAttr
} from "../utils/element-utils.js";
const renditionIcon = (
/*html*/
`<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M13.5 2.5h2v6h-2v-2h-11v-2h11v-2Zm4 2h4v2h-4v-2Zm-12 4h2v6h-2v-2h-3v-2h3v-2Zm4 2h12v2h-12v-2Zm1 4h2v6h-2v-2h-8v-2h8v-2Zm4 2h7v2h-7v-2Z" />
</svg>`
);
const slotTemplate = document.createElement("template");
slotTemplate.innerHTML = /*html*/
`
<style>
:host([aria-expanded="true"]) slot[name=tooltip] {
display: none;
}
</style>
<slot name="icon">${renditionIcon}</slot>
`;
class MediaRenditionMenuButton extends MediaChromeMenuButton {
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_RENDITION_SELECTED,
MediaUIAttributes.MEDIA_RENDITION_UNAVAILABLE,
MediaUIAttributes.MEDIA_HEIGHT
];
}
constructor() {
super({ slotTemplate, tooltipContent: tooltipLabels.RENDITIONS });
}
connectedCallback() {
super.connectedCallback();
this.setAttribute("aria-label", nouns.QUALITY());
}
/**
* Returns the element with the id specified by the `invoketarget` attribute.
*/
get invokeTargetElement() {
if (this.invokeTarget != void 0)
return super.invokeTargetElement;
return getMediaController(this).querySelector("media-rendition-menu");
}
/**
* Get selected rendition id.
*/
get mediaRenditionSelected() {
return getStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED);
}
set mediaRenditionSelected(id) {
setStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED, id);
}
get mediaHeight() {
return getNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT);
}
set mediaHeight(height) {
setNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT, height);
}
}
if (!globalThis.customElements.get("media-rendition-menu-button")) {
globalThis.customElements.define(
"media-rendition-menu-button",
MediaRenditionMenuButton
);
}
var media_rendition_menu_button_default = MediaRenditionMenuButton;
export {
MediaRenditionMenuButton,
media_rendition_menu_button_default as default
};

View File

@@ -0,0 +1,34 @@
import { MediaChromeMenu } from './media-chrome-menu.js';
import { Rendition } from '../media-store/state-mediator.js';
/**
* @extends {MediaChromeMenu}
*
* @slot - Default slotted elements.
* @slot header - An element shown at the top of the menu.
* @slot checked-indicator - An icon element indicating a checked menu-item.
*
* @attr {string} mediarenditionselected - (read-only) Set to the selected rendition id.
* @attr {string} mediarenditionlist - (read-only) Set to the rendition list.
*/
declare class MediaRenditionMenu extends MediaChromeMenu {
#private;
static get observedAttributes(): string[];
attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null): void;
connectedCallback(): void;
disconnectedCallback(): void;
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement(): HTMLElement;
get mediaRenditionList(): Rendition[];
set mediaRenditionList(list: Rendition[]);
/**
* Get selected rendition id.
*/
get mediaRenditionSelected(): string;
set mediaRenditionSelected(id: string);
get mediaHeight(): number;
set mediaHeight(height: number);
}
export { MediaRenditionMenu };
export default MediaRenditionMenu;

View File

@@ -0,0 +1,170 @@
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 _renditionList, _prevState, _render, render_fn, _onChange, onChange_fn;
import { globalThis } from "../utils/server-safe-globals.js";
import { MediaUIAttributes, MediaUIEvents } from "../constants.js";
import {
getMediaController,
getStringAttr,
setStringAttr,
getNumericAttr,
setNumericAttr
} from "../utils/element-utils.js";
import { parseRenditionList } from "../utils/utils.js";
import {
MediaChromeMenu,
createMenuItem,
createIndicator
} from "./media-chrome-menu.js";
class MediaRenditionMenu extends MediaChromeMenu {
constructor() {
super(...arguments);
__privateAdd(this, _render);
__privateAdd(this, _onChange);
__privateAdd(this, _renditionList, []);
__privateAdd(this, _prevState, {});
}
static get observedAttributes() {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_RENDITION_LIST,
MediaUIAttributes.MEDIA_RENDITION_SELECTED,
MediaUIAttributes.MEDIA_RENDITION_UNAVAILABLE,
MediaUIAttributes.MEDIA_HEIGHT
];
}
attributeChangedCallback(attrName, oldValue, newValue) {
super.attributeChangedCallback(attrName, oldValue, newValue);
if (attrName === MediaUIAttributes.MEDIA_RENDITION_SELECTED && oldValue !== newValue) {
this.value = newValue != null ? newValue : "auto";
} else if (attrName === MediaUIAttributes.MEDIA_RENDITION_LIST && oldValue !== newValue) {
__privateSet(this, _renditionList, parseRenditionList(newValue));
__privateMethod(this, _render, render_fn).call(this);
} else if (attrName === MediaUIAttributes.MEDIA_HEIGHT && oldValue !== newValue) {
__privateMethod(this, _render, render_fn).call(this);
}
}
connectedCallback() {
super.connectedCallback();
this.addEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
disconnectedCallback() {
super.disconnectedCallback();
this.removeEventListener("change", __privateMethod(this, _onChange, onChange_fn));
}
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement() {
if (this.anchor !== "auto")
return super.anchorElement;
return getMediaController(this).querySelector(
"media-rendition-menu-button"
);
}
get mediaRenditionList() {
return __privateGet(this, _renditionList);
}
set mediaRenditionList(list) {
__privateSet(this, _renditionList, list);
__privateMethod(this, _render, render_fn).call(this);
}
/**
* Get selected rendition id.
*/
get mediaRenditionSelected() {
return getStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED);
}
set mediaRenditionSelected(id) {
setStringAttr(this, MediaUIAttributes.MEDIA_RENDITION_SELECTED, id);
}
get mediaHeight() {
return getNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT);
}
set mediaHeight(height) {
setNumericAttr(this, MediaUIAttributes.MEDIA_HEIGHT, height);
}
}
_renditionList = new WeakMap();
_prevState = new WeakMap();
_render = new WeakSet();
render_fn = function() {
if (__privateGet(this, _prevState).mediaRenditionList === JSON.stringify(this.mediaRenditionList) && __privateGet(this, _prevState).mediaHeight === this.mediaHeight)
return;
__privateGet(this, _prevState).mediaRenditionList = JSON.stringify(this.mediaRenditionList);
__privateGet(this, _prevState).mediaHeight = this.mediaHeight;
const renditionList = this.mediaRenditionList.sort(
(a, b) => b.height - a.height
);
for (const rendition of renditionList) {
rendition.selected = rendition.id === this.mediaRenditionSelected;
}
this.defaultSlot.textContent = "";
const isAuto = !this.mediaRenditionSelected;
for (const rendition of renditionList) {
const text = this.formatMenuItemText(
`${Math.min(rendition.width, rendition.height)}p`,
rendition
);
const item2 = createMenuItem({
type: "radio",
text,
value: `${rendition.id}`,
checked: rendition.selected && !isAuto
});
item2.prepend(createIndicator(this, "checked-indicator"));
this.defaultSlot.append(item2);
}
const item = createMenuItem({
type: "radio",
text: this.formatMenuItemText("Auto"),
value: "auto",
checked: isAuto
});
const autoDescription = this.mediaHeight > 0 ? `Auto (${this.mediaHeight}p)` : "Auto";
item.dataset.description = autoDescription;
item.prepend(createIndicator(this, "checked-indicator"));
this.defaultSlot.append(item);
};
_onChange = new WeakSet();
onChange_fn = function() {
if (this.value == null)
return;
const event = new globalThis.CustomEvent(
MediaUIEvents.MEDIA_RENDITION_REQUEST,
{
composed: true,
bubbles: true,
detail: this.value
}
);
this.dispatchEvent(event);
};
if (!globalThis.customElements.get("media-rendition-menu")) {
globalThis.customElements.define("media-rendition-menu", MediaRenditionMenu);
}
var media_rendition_menu_default = MediaRenditionMenu;
export {
MediaRenditionMenu,
media_rendition_menu_default as default
};

View File

@@ -0,0 +1,16 @@
import { MediaChromeMenuButton } from './media-chrome-menu-button.js';
/**
* @attr {string} target - CSS id selector for the element to be targeted by the button.
*/
declare class MediaSettingsMenuButton extends MediaChromeMenuButton {
static get observedAttributes(): string[];
constructor();
connectedCallback(): void;
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement(): HTMLElement | null;
}
export { MediaSettingsMenuButton };
export default MediaSettingsMenuButton;

View File

@@ -0,0 +1,50 @@
import { MediaChromeMenuButton } from "./media-chrome-menu-button.js";
import { globalThis, document } from "../utils/server-safe-globals.js";
import { getMediaController } from "../utils/element-utils.js";
import { nouns, tooltipLabels } from "../labels/labels.js";
const slotTemplate = document.createElement("template");
slotTemplate.innerHTML = /*html*/
`
<style>
:host([aria-expanded="true"]) slot[name=tooltip] {
display: none;
}
</style>
<slot name="icon">
<svg aria-hidden="true" viewBox="0 0 24 24">
<path d="M4.5 14.5a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm7.5 0a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Zm7.5 0a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5Z"/>
</svg>
</slot>
`;
class MediaSettingsMenuButton extends MediaChromeMenuButton {
static get observedAttributes() {
return [...super.observedAttributes, "target"];
}
constructor() {
super({ slotTemplate, tooltipContent: tooltipLabels.SETTINGS });
}
connectedCallback() {
super.connectedCallback();
this.setAttribute("aria-label", nouns.SETTINGS());
}
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement() {
if (this.invokeTarget != void 0)
return super.invokeTargetElement;
return getMediaController(this).querySelector("media-settings-menu");
}
}
if (!globalThis.customElements.get("media-settings-menu-button")) {
globalThis.customElements.define(
"media-settings-menu-button",
MediaSettingsMenuButton
);
}
var media_settings_menu_button_default = MediaSettingsMenuButton;
export {
MediaSettingsMenuButton,
media_settings_menu_button_default as default
};

View File

@@ -0,0 +1,6 @@
import { MediaChromeMenuItem } from './media-chrome-menu-item.js';
declare class MediaSettingsMenuItem extends MediaChromeMenuItem {
static template: HTMLTemplateElement;
}
export { MediaSettingsMenuItem };
export default MediaSettingsMenuItem;

View File

@@ -0,0 +1,38 @@
var _a;
import { globalThis, document } from "../utils/server-safe-globals.js";
import { MediaChromeMenuItem } from "./media-chrome-menu-item.js";
const template = document.createElement("template");
template.innerHTML = MediaChromeMenuItem.template.innerHTML + /*html*/
`
<style>
slot:not([name="submenu"]) {
opacity: var(--media-settings-menu-item-opacity, var(--media-menu-item-opacity));
}
:host([aria-expanded="true"]:hover) {
background: transparent;
}
</style>
`;
if ((_a = template.content) == null ? void 0 : _a.querySelector) {
template.content.querySelector('slot[name="suffix"]').innerHTML = /*html*/
`
<svg aria-hidden="true" viewBox="0 0 20 24">
<path d="m8.12 17.585-.742-.669 4.2-4.665-4.2-4.666.743-.669 4.803 5.335-4.803 5.334Z"/>
</svg>
`;
}
class MediaSettingsMenuItem extends MediaChromeMenuItem {
}
MediaSettingsMenuItem.template = template;
if (!globalThis.customElements.get("media-settings-menu-item")) {
globalThis.customElements.define(
"media-settings-menu-item",
MediaSettingsMenuItem
);
}
var media_settings_menu_item_default = MediaSettingsMenuItem;
export {
MediaSettingsMenuItem,
media_settings_menu_item_default as default
};

View File

@@ -0,0 +1,15 @@
import { MediaChromeMenu } from './media-chrome-menu.js';
/**
* @extends {MediaChromeMenu}
*
* @cssproperty --media-settings-menu-justify-content - `justify-content` of the menu.
*/
declare class MediaSettingsMenu extends MediaChromeMenu {
static template: HTMLTemplateElement;
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement(): HTMLElement;
}
export { MediaSettingsMenu };
export default MediaSettingsMenu;

View File

@@ -0,0 +1,53 @@
import { globalThis, document } from "../utils/server-safe-globals.js";
import { MediaChromeMenu } from "./media-chrome-menu.js";
import { getMediaController } from "../utils/element-utils.js";
const template = document.createElement("template");
template.innerHTML = MediaChromeMenu.template.innerHTML + /*html*/
`
<style>
:host {
background: var(--media-settings-menu-background,
var(--media-menu-background,
var(--media-control-background,
var(--media-secondary-color, rgb(20 20 30 / .8)))));
min-width: var(--media-settings-menu-min-width, 170px);
border-radius: 2px 2px 0 0;
overflow: hidden;
}
:host([role="menu"]) {
${/* Bottom fix setting menu items for animation when the height expands. */
""}
justify-content: end;
}
slot:not([name]) {
justify-content: var(--media-settings-menu-justify-content);
flex-direction: var(--media-settings-menu-flex-direction, column);
overflow: visible;
}
#container.has-expanded {
--media-settings-menu-item-opacity: 0;
}
</style>
`;
class MediaSettingsMenu extends MediaChromeMenu {
/**
* Returns the anchor element when it is a floating menu.
*/
get anchorElement() {
if (this.anchor !== "auto")
return super.anchorElement;
return getMediaController(this).querySelector("media-settings-menu-button");
}
}
MediaSettingsMenu.template = template;
if (!globalThis.customElements.get("media-settings-menu")) {
globalThis.customElements.define("media-settings-menu", MediaSettingsMenu);
}
var media_settings_menu_default = MediaSettingsMenu;
export {
MediaSettingsMenu,
media_settings_menu_default as default
};