import { globalThis } from '../utils/server-safe-globals.js';
import { MediaUIAttributes } from '../constants.js';
import { MediaChromeMenuButton } from './media-chrome-menu-button.js';
import { getMediaController } from '../utils/element-utils.js';
import {
areSubsOn,
parseTextTracksStr,
stringifyTextTrackList,
} from '../utils/captions.js';
import { TextTrackLike } from '../utils/TextTrackLike.js';
import { t } from '../utils/i18n.js';
const ccIconOn = ``;
const ccIconOff = ``;
function getSlotTemplateHTML() {
return /*html*/ `
${ccIconOn}${ccIconOff}
`;
}
function getTooltipContentHTML() {
return t('Captions');
}
const updateAriaChecked = (el: HTMLElement): void => {
el.setAttribute('data-captions-enabled', areSubsOn(el).toString());
};
const updateAriaLabel = (el: HTMLElement): void => {
el.setAttribute('aria-label', t('closed captions'));
};
/**
* @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.
*/
class MediaCaptionsMenuButton extends MediaChromeMenuButton {
static getSlotTemplateHTML = getSlotTemplateHTML;
static getTooltipContentHTML = getTooltipContentHTML;
static get observedAttributes(): string[] {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_SUBTITLES_LIST,
MediaUIAttributes.MEDIA_SUBTITLES_SHOWING,
MediaUIAttributes.MEDIA_LANG
];
}
connectedCallback(): void {
super.connectedCallback();
updateAriaLabel(this);
updateAriaChecked(this);
}
attributeChangedCallback(
attrName: string,
oldValue: string,
newValue: string
): void {
super.attributeChangedCallback(attrName, oldValue, newValue);
if (attrName === MediaUIAttributes.MEDIA_SUBTITLES_SHOWING) {
updateAriaChecked(this);
}
else if (attrName === MediaUIAttributes.MEDIA_LANG) {
updateAriaLabel(this);
}
}
/**
* Returns the element with the id specified by the `invoketarget` attribute.
* @return {HTMLElement | null}
*/
get invokeTargetElement(): HTMLElement | null {
if (this.invokeTarget != undefined) return super.invokeTargetElement;
return getMediaController(this)?.querySelector('media-captions-menu');
}
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesList(): TextTrackLike[] {
return getSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST);
}
set mediaSubtitlesList(list: TextTrackLike[]) {
setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_LIST, list);
}
/**
* An array of TextTrack-like objects.
* Objects must have the properties: kind, language, and label.
*/
get mediaSubtitlesShowing(): TextTrackLike[] {
return getSubtitlesListAttr(
this,
MediaUIAttributes.MEDIA_SUBTITLES_SHOWING
);
}
set mediaSubtitlesShowing(list: TextTrackLike[]) {
setSubtitlesListAttr(this, MediaUIAttributes.MEDIA_SUBTITLES_SHOWING, list);
}
}
/**
* @param el - Should be HTMLElement but issues with globalThis shim
* @param attrName - The attribute name to get
* @returns An array of TextTrack-like objects.
*/
const getSubtitlesListAttr = (
el: HTMLElement,
attrName: string
): TextTrackLike[] => {
const attrVal = el.getAttribute(attrName);
return attrVal ? parseTextTracksStr(attrVal) : [];
};
/**
*
* @param el - Should be HTMLElement but issues with globalThis shim
* @param attrName - The attribute name to set
* @param list - An array of TextTrack-like objects
*/
const setSubtitlesListAttr = (
el: HTMLElement,
attrName: string,
list: TextTrackLike[]
): void => {
// null, undefined, and empty arrays are treated as "no value" here
if (!list?.length) {
el.removeAttribute(attrName);
return;
}
// don't set if the new value is the same as existing
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
);
}
export { MediaCaptionsMenuButton };
export default MediaCaptionsMenuButton;