import { MediaChromeButton } from './media-chrome-button.js';
import { globalThis } from './utils/server-safe-globals.js';
import { MediaUIEvents, MediaUIAttributes } from './constants.js';
import { getNumericAttr, setNumericAttr, getSlotted, updateIconText } from './utils/element-utils.js';
import { t } from './utils/i18n.js';
export const Attributes = {
SEEK_OFFSET: 'seekoffset',
};
const DEFAULT_SEEK_OFFSET = 30;
const backwardIcon = (seekOffset: number) => `
`;
function getSlotTemplateHTML(_attrs: Record, props: Record) {
return /*html*/ `
${backwardIcon(props.seekOffset)}
`;
}
const updateAriaLabel = (el: MediaSeekBackwardButton, seekOffset: number): void => {
el.setAttribute('aria-label', t('seek back {seekOffset} seconds', { seekOffset: seekOffset }));
};
function getTooltipContentHTML() {
return t('Seek backward');
}
const DEFAULT_TIME = 0;
/**
* @slot icon - The element shown for the seek backward button’s display.
*
* @attr {string} seekoffset - Adjusts how much time (in seconds) the playhead should seek backward.
* @attr {string} mediacurrenttime - (read-only) Set to the current media time.
*
* @cssproperty [--media-seek-backward-button-display = inline-flex] - `display` property of button.
*/
class MediaSeekBackwardButton extends MediaChromeButton {
static getSlotTemplateHTML = getSlotTemplateHTML;
static getTooltipContentHTML = getTooltipContentHTML;
static get observedAttributes(): string[] {
return [
...super.observedAttributes,
MediaUIAttributes.MEDIA_CURRENT_TIME,
Attributes.SEEK_OFFSET,
];
}
connectedCallback(): void {
super.connectedCallback();
this.seekOffset = getNumericAttr(
this,
Attributes.SEEK_OFFSET,
DEFAULT_SEEK_OFFSET
);
}
attributeChangedCallback(
attrName: string,
_oldValue: string | null,
newValue: string | null
): void {
super.attributeChangedCallback(attrName, _oldValue, newValue);
updateAriaLabel(this, this.seekOffset);
if (attrName === Attributes.SEEK_OFFSET) {
this.seekOffset = getNumericAttr(
this,
Attributes.SEEK_OFFSET,
DEFAULT_SEEK_OFFSET
);
}
}
// Own props
/**
* Seek amount in seconds
*/
get seekOffset(): number {
return getNumericAttr(this, Attributes.SEEK_OFFSET, DEFAULT_SEEK_OFFSET);
}
set seekOffset(value: number) {
setNumericAttr(this, Attributes.SEEK_OFFSET, value);
this.setAttribute(
'aria-label',
t('seek back {seekOffset} seconds', { seekOffset: this.seekOffset })
);
updateIconText(getSlotted(this, 'icon'), this.seekOffset as any);
}
// Props derived from Media UI Attributes
/**
* The current time in seconds
*/
get mediaCurrentTime(): number {
return getNumericAttr(
this,
MediaUIAttributes.MEDIA_CURRENT_TIME,
DEFAULT_TIME
);
}
set mediaCurrentTime(time: number) {
setNumericAttr(this, MediaUIAttributes.MEDIA_CURRENT_TIME, time);
}
handleClick(): void {
const detail = Math.max(this.mediaCurrentTime - this.seekOffset, 0);
const evt = new globalThis.CustomEvent(MediaUIEvents.MEDIA_SEEK_REQUEST, {
composed: true,
bubbles: true,
detail,
});
this.dispatchEvent(evt);
}
}
if (!globalThis.customElements.get('media-seek-backward-button')) {
globalThis.customElements.define(
'media-seek-backward-button',
MediaSeekBackwardButton
);
}
export default MediaSeekBackwardButton;