import { globalThis } from './utils/server-safe-globals.js'; import { MediaChromeDialog } from './media-chrome-dialog.js'; function getSlotTemplateHTML(_attrs: Record) { return /*html*/ ` ${formatKeyboardShortcuts()} `; } function formatKeyboardShortcuts() { const shortcuts = [ { keys: ['Space', 'k'], description: 'Toggle Playback' }, { keys: ['m'], description: 'Toggle mute' }, { keys: ['f'], description: 'Toggle fullscreen' }, { keys: ['c'], description: 'Toggle captions or subtitles, if available' }, { keys: ['p'], description: 'Toggle Picture in Picture' }, { keys: ['←', 'j'], description: 'Seek back 10s' }, { keys: ['→', 'l'], description: 'Seek forward 10s' }, { keys: ['↑'], description: 'Turn volume up' }, { keys: ['↓'], description: 'Turn volume down' }, { keys: ['< (SHIFT+,)'], description: 'Decrease playback rate' }, { keys: ['> (SHIFT+.)'], description: 'Increase playback rate' }, ]; const rows = shortcuts.map(({ keys, description }) => { const keyCombo = keys.map((key, index) => index > 0 ? `or${key}` : `${key}` ).join(''); return `
${keyCombo}
${description} `; }).join(''); return `

Keyboard Shortcuts

${rows}
`; } class MediaKeyboardShortcutsDialog extends MediaChromeDialog { static getSlotTemplateHTML = getSlotTemplateHTML; connectedCallback() { super.connectedCallback(); if (this.open) { this.addEventListener('click', this.#clickHandler); document.addEventListener('keydown', this.#keyDownHandler); } } disconnectedCallback() { this.removeEventListener('click', this.#clickHandler); document.removeEventListener('keydown', this.#keyDownHandler); } attributeChangedCallback(attrName: string, oldValue: string | null, newValue: string | null) { super.attributeChangedCallback(attrName, oldValue, newValue); if (attrName === 'open') { if (this.open) { this.addEventListener('click', this.#clickHandler); document.addEventListener('keydown', this.#keyDownHandler); } else { this.removeEventListener('click', this.#clickHandler); document.removeEventListener('keydown', this.#keyDownHandler); } } } #clickHandler = (e: MouseEvent) => { if (!this.open) return; const content = this.shadowRoot?.querySelector('#content'); if (!content) return; // Check if click is on the background (outside content) const path = e.composedPath(); const isClickOnHost = path[0] === this || path.includes(this); const isClickInsideContent = path.includes(content); if (isClickOnHost && !isClickInsideContent) { this.open = false; } }; #keyDownHandler = (e: KeyboardEvent) => { if (!this.open) return; const isShiftSlash = e.shiftKey && (e.key === '/' || e.key === '?'); if ((e.key === 'Escape' || isShiftSlash) && !e.ctrlKey && !e.altKey && !e.metaKey) { this.open = false; e.preventDefault(); e.stopPropagation(); } }; } if (!globalThis.customElements.get('media-keyboard-shortcuts-dialog')) { globalThis.customElements.define('media-keyboard-shortcuts-dialog', MediaKeyboardShortcutsDialog); } export { MediaKeyboardShortcutsDialog }; export default MediaKeyboardShortcutsDialog;