@mango-iiif/av 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,5 +2,6 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ - Fixed `<mango-av-player>` failing to resolve and attach media when given an already-loaded `AVPlayerController`.
5
6
  - Audio artwork no longer displays the Canvas label as a visible title by default. Hosts can opt in to custom text with `audioArt.title`.
6
7
  - Fixed a cross-origin audio regression where enabling audio artwork visualization could route otherwise playable media through a CORS-unsafe Web Audio graph and produce silence. Visualizer loads now establish their CORS policy before assigning the source URL and automatically fall back once to ordinary HTML audio for servers without CORS support.
@@ -124,6 +124,7 @@ var MangoAVPlayerElement = class extends AVControllerElement {
124
124
  this.#transcriptCues = [];
125
125
  this.#render();
126
126
  void this.#loadTranscript();
127
+ void this.#resolveSource();
127
128
  }
128
129
  handleControllerEvent(type, event) {
129
130
  if (type === "av-configchange") {
@@ -351,4 +352,4 @@ export {
351
352
  MangoAVPlayerElement,
352
353
  defineMangoAVPlayer
353
354
  };
354
- //# sourceMappingURL=chunk-YHTJZXOE.js.map
355
+ //# sourceMappingURL=chunk-YX6L6CUF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/components/mango-av-player.ts"],"sourcesContent":["import { AVControllerElement } from './controller-element';\nimport { componentTheme } from './component-styles';\nimport { ensureMediaChrome } from './media-chrome';\nimport { AudioArtVisualizer, audioArtContentHtml, audioArtTranscriptHtml, resolveAudioVisualizerMode, syncAudioArtTranscript } from './audio-art';\nimport { loadTranscript } from '../transcript';\nimport type { AVCanvas, AVManifest, AVPlayerConfig, AVPlayerEventMap, JsonObject, MediaSource, TranscriptCue } from '../types';\nimport { escapeHtml, formatString, resolveStrings } from '../utils';\nimport { applyMediaSource, resolveAudioMediaPolicy } from './media-policy';\n\nlet hlsElementRegistration: Promise<unknown> | undefined;\nconst ensureHlsElement = (): Promise<unknown> => {\n hlsElementRegistration ??= import('hls-video-element');\n return hlsElementRegistration;\n};\n\nconst styles = `${componentTheme}\n :host { --mango-av-player-aspect-ratio: 16 / 9; }\n .player { background: #08080a; border-radius: var(--mango-av-radius); color: white; overflow: clip; position: relative; }\n media-controller { display: block; width: 100%; }\n media-controller:not([audio]) { aspect-ratio: var(--mango-av-player-aspect-ratio); }\n video, hls-video { display: block; height: 100%; object-fit: contain; width: 100%; }\n audio { width: 100%; }\n media-control-bar { width: 100%; }\n .audio-art { --mango-av-wave-edge-strength: 0%; --mango-av-wave-mid-strength: 0%; --mango-av-wave-rise: 8%; --mango-av-wave-strength: 0%; align-items: center; aspect-ratio: 16 / 7; background: linear-gradient(#09080d, #111019); display: flex; justify-content: center; overflow: hidden; padding: 2rem; position: relative; text-align: center; }\n .audio-art.visualizer--pulse { background: radial-gradient(ellipse 140% 72% at 50% calc(100% + var(--mango-av-wave-rise)), color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-strength), transparent) 0%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-mid-strength), transparent) 40%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-edge-strength), transparent) 62%, transparent 78%), linear-gradient(#09080d, #111019); }\n .audio-art-text { display: contents; }\n .audio-art-visualizer-canvas { height: 100%; inset: 0; pointer-events: none; position: absolute; width: 100%; }\n .audio-art-title { font-size: clamp(1.1rem, 3vw, 2rem); font-weight: 700; position: relative; z-index: 1; }\n .audio-art-transcript { height: 100%; inset: 0; overflow: hidden; position: absolute; z-index: 1; }\n .audio-art-cue { align-items: center; display: flex; flex-direction: column; font-size: clamp(.7rem, 1.3vw, .875rem); font-weight: 550; gap: .15rem; left: 12%; line-height: 1.35; position: absolute; right: 12%; top: 50%; transition: opacity 360ms ease, transform 480ms cubic-bezier(.22, 1, .36, 1); }\n .audio-art-transcript.seeking .audio-art-cue { transition: none; }\n .audio-art-cue.active { font-size: clamp(.78rem, 1.5vw, 1rem); font-weight: 650; }\n .audio-art-cue > span:last-child { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }\n .audio-art-speaker { font-size: .7em; letter-spacing: .04em; text-transform: uppercase; }\n .toolbar { align-items: center; background: #151518; display: flex; flex-wrap: wrap; gap: .5rem; justify-content: space-between; padding: .55rem .7rem; }\n .toolbar button, .toolbar select { background: #29292e; border: 1px solid #44444a; border-radius: .35rem; color: white; padding: .4rem .55rem; }\n .group { align-items: center; display: flex; gap: .45rem; }\n .error { background: #fff0f0; color: #8a1717; padding: 1rem; }\n .sr-only { clip: rect(0,0,0,0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }\n`;\n\nexport class MangoAVPlayerElement extends AVControllerElement {\n static observedAttributes = ['manifest-url', 'config'];\n\n #root: ShadowRoot;\n #manifestInput: JsonObject | string | undefined;\n #config: AVPlayerConfig = {};\n #resolvedSourceUrl: string | undefined;\n #sourceToken = 0;\n #fallbackSourceUrl: string | undefined;\n #transcriptCues: TranscriptCue[] = [];\n #transcriptToken = 0;\n #visualizer = new AudioArtVisualizer();\n\n constructor() {\n super();\n this.#root = this.attachShadow({ mode: 'open' });\n }\n\n get manifest(): JsonObject | string | undefined {\n return this.#manifestInput;\n }\n\n set manifest(value: JsonObject | string | undefined) {\n this.#manifestInput = value;\n if (this.isConnected && value !== undefined) void this.load(value);\n }\n\n get config(): AVPlayerConfig {\n return this.#config;\n }\n\n set config(value: AVPlayerConfig) {\n this.#config = value;\n this.controller.configure(value);\n this.#render();\n }\n\n override connectedCallback(): void {\n this.#readConfigAttribute();\n void ensureMediaChrome(this.controller.config.preferredLanguages[0]);\n super.connectedCallback();\n const source = this.#manifestInput ?? this.getAttribute('manifest-url') ?? undefined;\n if (source !== undefined && !this.controller.manifest) void this.load(source);\n }\n\n override disconnectedCallback(): void {\n this.#visualizer.disconnect();\n super.disconnectedCallback();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected || oldValue === newValue) return;\n if (name === 'manifest-url' && newValue) {\n this.#manifestInput = newValue;\n void this.load(newValue);\n } else if (name === 'config') {\n this.#readConfigAttribute();\n this.#render();\n }\n }\n\n async load(input: JsonObject | string): Promise<AVManifest> {\n this.#manifestInput = input;\n return await this.controller.load(input);\n }\n\n play(): Promise<void> { return this.controller.play(); }\n pause(): void { this.controller.pause(); }\n seekTo(time: number): void { this.controller.seekTo(time); }\n selectCanvas(indexOrId: number | string, options?: { time?: number; autoplay?: boolean }): AVCanvas | undefined {\n return this.controller.selectCanvas(indexOrId, options);\n }\n\n protected controllerChanged(): void {\n this.#resetSourceLoad();\n this.#transcriptCues = [];\n this.#render();\n void this.#loadTranscript();\n void this.#resolveSource();\n }\n\n protected handleControllerEvent<K extends keyof AVPlayerEventMap>(type: K, event: CustomEvent<AVPlayerEventMap[K]>): void {\n if (type === 'av-configchange') {\n this.#resetSourceLoad();\n void ensureMediaChrome(this.controller.config.preferredLanguages[0]).then(() => {\n this.#render();\n void this.#loadTranscript();\n void this.#resolveSource();\n });\n } else if (type === 'av-ready' || type === 'av-canvaschange') {\n this.#resetSourceLoad();\n this.#transcriptCues = [];\n if (this.controller.source?.isHls) void ensureHlsElement();\n this.#render();\n void this.#loadTranscript();\n void this.#resolveSource();\n } else if (type === 'av-sourcechange') {\n this.#resetSourceLoad();\n if (this.controller.source?.isHls) void ensureHlsElement();\n this.#render();\n void this.#resolveSource();\n } else if (type === 'av-error') {\n this.#resolvedSourceUrl = undefined;\n this.#render();\n } else if (type === 'av-seek') {\n syncAudioArtTranscript(this.#root, (event.detail as AVPlayerEventMap['av-seek']).to, true);\n } else if (type === 'av-timeupdate' || type === 'av-statechange') {\n syncAudioArtTranscript(this.#root, this.controller.state.currentTime);\n }\n this.dispatchEvent(new CustomEvent(type, { detail: event.detail, bubbles: true, composed: true }));\n }\n\n #readConfigAttribute(): void {\n const value = this.getAttribute('config');\n if (!value) return;\n try {\n this.#config = JSON.parse(value) as AVPlayerConfig;\n this.controller.configure(this.#config);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n #render(): void {\n this.#visualizer.disconnect();\n const state = this.controller.state;\n const canvas = this.controller.canvas;\n const source = this.controller.source;\n const ui = resolveStrings(this.controller.config.strings);\n this.#root.innerHTML = `<style>${styles}</style>\n <div class=\"player\">\n ${state.status === 'loading' ? `<p role=\"status\">${escapeHtml(ui.loadingManifest)}</p>` : ''}\n ${state.status === 'error' ? `<div class=\"error\" role=\"alert\">${escapeHtml(state.error?.message ?? ui.unableToLoadMedia)}</div>` : ''}\n ${canvas && source ? this.#readyHtml(canvas, source) : state.status !== 'loading' && state.status !== 'error' ? `<div class=\"audio-art\"><span>${escapeHtml(ui.noMediaLoaded)}</span></div>` : ''}\n </div>`;\n const media = this.#root.querySelector('video, audio, hls-video') as HTMLMediaElement | null;\n if (media && this.#resolvedSourceUrl) this.#activateMedia(media, this.#resolvedSourceUrl);\n syncAudioArtTranscript(this.#root, this.controller.state.currentTime);\n this.#bind();\n }\n\n #readyHtml(canvas: AVCanvas, source: MediaSource): string {\n const controls = this.controller.config.controls;\n const manifest = this.controller.manifest;\n const kind = source.kind;\n const ui = resolveStrings(this.controller.config.strings);\n const language = this.controller.config.preferredLanguages.find((value) => value !== 'none');\n const showSourceSelector = controls.sourceSelector && canvas.sources.length > 1;\n const showToolbar = controls.navigation || controls.autoAdvance || showSourceSelector;\n const visualizerMode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);\n return `<media-controller ${kind === 'audio' ? 'audio' : ''} ${language ? `lang=\"${escapeHtml(language)}\"` : ''}>\n ${kind === 'audio' ? `<div class=\"audio-art ${visualizerMode ? `visualizer visualizer--${visualizerMode}` : ''}\">${audioArtContentHtml(canvas.label, this.controller.config.audioArt.title ?? '', this.#transcriptCues, Boolean(this.controller.config.audioArt.transcript), visualizerMode)}</div>` : ''}\n ${this.#mediaHtml(canvas, source)}\n <slot name=\"overlay\"></slot>\n <slot name=\"controls\">\n <media-control-bar>\n <media-play-button></media-play-button>\n ${controls.seek ? `<media-seek-backward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-backward-button><media-seek-forward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-forward-button>` : ''}\n <media-time-display showduration></media-time-display>\n ${controls.seek ? '<media-time-range></media-time-range>' : ''}\n ${controls.volume ? '<media-mute-button></media-mute-button><media-volume-range></media-volume-range>' : ''}\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu-button></media-captions-menu-button>' : ''}\n ${controls.playbackRate ? '<media-playback-rate-menu-button></media-playback-rate-menu-button>' : ''}\n ${controls.pictureInPicture && kind === 'video' ? '<media-pip-button></media-pip-button>' : ''}\n ${controls.fullscreen && kind === 'video' ? '<media-fullscreen-button></media-fullscreen-button>' : ''}\n </media-control-bar>\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu hidden></media-captions-menu>' : ''}\n ${controls.playbackRate ? `<media-playback-rate-menu rates=\"${this.controller.config.playbackRates.join(' ')}\" hidden></media-playback-rate-menu>` : ''}\n </slot>\n </media-controller>\n ${showToolbar ? `<div class=\"toolbar\">\n ${controls.navigation ? `<div class=\"group\">\n <button type=\"button\" data-action=\"previous\" ${canvas.index === 0 ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.previousSection)}\">← ${escapeHtml(ui.previous)}</button>\n <button type=\"button\" data-action=\"next\" ${canvas.index === (manifest?.canvases.length ?? 1) - 1 && !this.controller.state.repeat ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.nextSection)}\">${escapeHtml(ui.next)} →</button>\n </div>` : ''}\n ${showSourceSelector || controls.autoAdvance ? `<div class=\"group\">\n ${showSourceSelector ? `<label><span class=\"sr-only\">${escapeHtml(ui.mediaSource)}</span><select data-action=\"source\">${canvas.sources.map((item, index) => `<option value=\"${index}\" ${index === this.controller.state.sourceIndex ? 'selected' : ''}>${escapeHtml(item.label ?? item.format ?? formatString(ui.sourceNumber, { number: index + 1 }))}</option>`).join('')}</select></label>` : ''}\n ${controls.autoAdvance ? `<label><input type=\"checkbox\" data-action=\"auto-advance\" ${this.controller.state.autoAdvance ? 'checked' : ''}> ${escapeHtml(ui.autoAdvance)}</label>` : ''}\n </div>` : ''}\n </div>` : ''}`;\n }\n\n #mediaHtml(canvas: AVCanvas, source: MediaSource): string {\n const tag = source.isHls ? 'hls-video' : source.kind;\n const attributes = [\n 'slot=\"media\"',\n `preload=\"${this.controller.config.preload}\"`,\n this.controller.config.crossorigin ? `crossorigin=\"${this.controller.config.crossorigin}\"` : '',\n source.kind === 'video' && canvas.poster ? `poster=\"${escapeHtml(canvas.poster)}\"` : '',\n `aria-label=\"${escapeHtml(canvas.label)}\"`,\n `data-canvasindex=\"${canvas.index}\"`,\n ].filter(Boolean).join(' ');\n const tracks = canvas.tracks.map((track) => `<track src=\"${escapeHtml(track.src)}\" kind=\"${track.kind}\" label=\"${escapeHtml(track.label)}\" ${track.language ? `srclang=\"${escapeHtml(track.language)}\"` : ''} ${track.default ? 'default' : ''}>`).join('');\n return `<${tag} ${attributes}>${tracks}</${tag}>`;\n }\n\n #bind(): void {\n this.#root.querySelector<HTMLElement>('[data-action=previous]')?.addEventListener('click', () => this.controller.previous({ autoplay: this.controller.state.status === 'playing' }));\n this.#root.querySelector<HTMLElement>('[data-action=next]')?.addEventListener('click', () => this.controller.next({ autoplay: this.controller.state.status === 'playing' }));\n this.#root.querySelector<HTMLSelectElement>('[data-action=source]')?.addEventListener('change', (event) => this.controller.selectSource(Number((event.target as HTMLSelectElement).value)));\n this.#root.querySelector<HTMLInputElement>('[data-action=auto-advance]')?.addEventListener('change', (event) => this.controller.setAutoAdvance((event.target as HTMLInputElement).checked));\n }\n\n async #resolveSource(): Promise<void> {\n const token = ++this.#sourceToken;\n try {\n const url = await this.controller.resolvedSourceUrl();\n if (token !== this.#sourceToken || !url) return;\n this.#resolvedSourceUrl = url;\n const media = this.#root.querySelector('video, audio, hls-video') as HTMLMediaElement | null;\n if (media) this.#activateMedia(media, url);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n #activateMedia(media: HTMLMediaElement, sourceUrl: string): void {\n const mode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);\n const policy = resolveAudioMediaPolicy(\n sourceUrl,\n this.controller.config.crossorigin,\n this.controller.crossoriginExplicit,\n media instanceof HTMLAudioElement ? mode : undefined,\n this.#fallbackSourceUrl === sourceUrl,\n );\n if (media instanceof HTMLAudioElement && policy.implicitCors) {\n media.addEventListener('error', (event) => {\n if (this.#fallbackSourceUrl === sourceUrl) return;\n event.stopImmediatePropagation();\n this.#fallbackToOrdinaryAudio(media, sourceUrl);\n }, { once: true });\n }\n if (media instanceof HTMLAudioElement && mode && policy.visualize) {\n const connect = () => {\n const art = this.#root.querySelector<HTMLElement>('.audio-art.visualizer');\n if (art && media.isConnected && (media.currentSrc === sourceUrl || media.src === sourceUrl)) {\n this.#visualizer.connect(media, art, mode);\n }\n };\n media.addEventListener('loadedmetadata', connect, { once: true });\n if (media.readyState >= HTMLMediaElement.HAVE_METADATA) queueMicrotask(connect);\n }\n this.controller.attachMedia(media);\n applyMediaSource(media, sourceUrl, policy.crossOrigin);\n }\n\n #fallbackToOrdinaryAudio(failed: HTMLAudioElement, sourceUrl: string): void {\n this.#fallbackSourceUrl = sourceUrl;\n this.#visualizer.disconnect();\n const requestedTime = this.controller.state.currentTime;\n const shouldPlay = this.controller.state.status === 'playing' || !failed.paused;\n const replacement = failed.cloneNode(true) as HTMLAudioElement;\n replacement.removeAttribute('src');\n replacement.removeAttribute('crossorigin');\n replacement.volume = failed.volume;\n replacement.muted = failed.muted;\n replacement.playbackRate = failed.playbackRate;\n const hadFocus = this.#root.activeElement === failed;\n failed.replaceWith(replacement);\n this.controller.attachMedia(replacement);\n this.controller.seekTo(requestedTime);\n if (hadFocus) replacement.focus();\n const art = this.#root.querySelector<HTMLElement>('.audio-art');\n art?.classList.remove('visualizer');\n applyMediaSource(replacement, sourceUrl);\n if (shouldPlay) replacement.addEventListener('loadedmetadata', () => void replacement.play().catch(() => undefined), { once: true });\n this.controller.dispatchEvent(new CustomEvent('av-visualizerfallback', {\n detail: { canvasId: this.controller.canvas?.id ?? '', sourceUrl, reason: 'cors' },\n }));\n }\n\n #resetSourceLoad(): void {\n this.#sourceToken += 1;\n this.#resolvedSourceUrl = undefined;\n this.#fallbackSourceUrl = undefined;\n this.#visualizer.disconnect();\n }\n\n async #loadTranscript(): Promise<void> {\n const resource = this.controller.canvas?.transcripts[0];\n if (!resource || !this.controller.config.audioArt.transcript) return;\n const token = ++this.#transcriptToken;\n const options: Parameters<typeof loadTranscript>[1] = {};\n if (this.controller.config.fetch) options.fetch = this.controller.config.fetch;\n if (this.controller.config.requestInit) options.requestInit = this.controller.config.requestInit;\n if (this.controller.config.transcript.showNotes !== undefined) options.showNotes = this.controller.config.transcript.showNotes;\n if (this.controller.config.transcript.showMetadata !== undefined) options.showMetadata = this.controller.config.transcript.showMetadata;\n try {\n const cues = await loadTranscript(resource, options);\n if (token !== this.#transcriptToken) return;\n this.#transcriptCues = cues;\n const art = this.#root.querySelector<HTMLElement>('.audio-art');\n const canvas = this.controller.canvas;\n if (art && canvas && this.controller.source?.kind === 'audio') {\n const text = art.querySelector<HTMLElement>('.audio-art-text');\n if (text) text.innerHTML = audioArtTranscriptHtml(canvas.label, this.controller.config.audioArt.title ?? '', cues, true);\n syncAudioArtTranscript(art, this.controller.state.currentTime);\n }\n } catch (cause) {\n if (token !== this.#transcriptToken) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n}\n\nexport const defineMangoAVPlayer = (tagName = 'mango-av-player'): typeof MangoAVPlayerElement => {\n if (typeof customElements === 'undefined') return MangoAVPlayerElement;\n if (!customElements.get(tagName)) customElements.define(tagName, MangoAVPlayerElement);\n return MangoAVPlayerElement;\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AASA,IAAI;AACJ,IAAM,mBAAmB,MAAwB;AAC/C,6BAA2B,OAAO,mBAAmB;AACrD,SAAO;AACT;AAEA,IAAM,SAAS,GAAG,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA0BzB,IAAM,uBAAN,cAAmC,oBAAoB;AAAA,EAC5D,OAAO,qBAAqB,CAAC,gBAAgB,QAAQ;AAAA,EAErD;AAAA,EACA;AAAA,EACA,UAA0B,CAAC;AAAA,EAC3B;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA,kBAAmC,CAAC;AAAA,EACpC,mBAAmB;AAAA,EACnB,cAAc,IAAI,mBAAmB;AAAA,EAErC,cAAc;AACZ,UAAM;AACN,SAAK,QAAQ,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAAA,EACjD;AAAA,EAEA,IAAI,WAA4C;AAC9C,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,SAAS,OAAwC;AACnD,SAAK,iBAAiB;AACtB,QAAI,KAAK,eAAe,UAAU,OAAW,MAAK,KAAK,KAAK,KAAK;AAAA,EACnE;AAAA,EAEA,IAAI,SAAyB;AAC3B,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAO,OAAuB;AAChC,SAAK,UAAU;AACf,SAAK,WAAW,UAAU,KAAK;AAC/B,SAAK,QAAQ;AAAA,EACf;AAAA,EAES,oBAA0B;AACjC,SAAK,qBAAqB;AAC1B,SAAK,kBAAkB,KAAK,WAAW,OAAO,mBAAmB,CAAC,CAAC;AACnE,UAAM,kBAAkB;AACxB,UAAM,SAAS,KAAK,kBAAkB,KAAK,aAAa,cAAc,KAAK;AAC3E,QAAI,WAAW,UAAa,CAAC,KAAK,WAAW,SAAU,MAAK,KAAK,KAAK,MAAM;AAAA,EAC9E;AAAA,EAES,uBAA6B;AACpC,SAAK,YAAY,WAAW;AAC5B,UAAM,qBAAqB;AAAA,EAC7B;AAAA,EAEA,yBAAyB,MAAc,UAAyB,UAA+B;AAC7F,QAAI,CAAC,KAAK,eAAe,aAAa,SAAU;AAChD,QAAI,SAAS,kBAAkB,UAAU;AACvC,WAAK,iBAAiB;AACtB,WAAK,KAAK,KAAK,QAAQ;AAAA,IACzB,WAAW,SAAS,UAAU;AAC5B,WAAK,qBAAqB;AAC1B,WAAK,QAAQ;AAAA,IACf;AAAA,EACF;AAAA,EAEA,MAAM,KAAK,OAAiD;AAC1D,SAAK,iBAAiB;AACtB,WAAO,MAAM,KAAK,WAAW,KAAK,KAAK;AAAA,EACzC;AAAA,EAEA,OAAsB;AAAE,WAAO,KAAK,WAAW,KAAK;AAAA,EAAG;AAAA,EACvD,QAAc;AAAE,SAAK,WAAW,MAAM;AAAA,EAAG;AAAA,EACzC,OAAO,MAAoB;AAAE,SAAK,WAAW,OAAO,IAAI;AAAA,EAAG;AAAA,EAC3D,aAAa,WAA4B,SAAuE;AAC9G,WAAO,KAAK,WAAW,aAAa,WAAW,OAAO;AAAA,EACxD;AAAA,EAEU,oBAA0B;AAClC,SAAK,iBAAiB;AACtB,SAAK,kBAAkB,CAAC;AACxB,SAAK,QAAQ;AACb,SAAK,KAAK,gBAAgB;AAC1B,SAAK,KAAK,eAAe;AAAA,EAC3B;AAAA,EAEU,sBAAwD,MAAS,OAA+C;AACxH,QAAI,SAAS,mBAAmB;AAC9B,WAAK,iBAAiB;AACtB,WAAK,kBAAkB,KAAK,WAAW,OAAO,mBAAmB,CAAC,CAAC,EAAE,KAAK,MAAM;AAC9E,aAAK,QAAQ;AACb,aAAK,KAAK,gBAAgB;AAC1B,aAAK,KAAK,eAAe;AAAA,MAC3B,CAAC;AAAA,IACH,WAAW,SAAS,cAAc,SAAS,mBAAmB;AAC5D,WAAK,iBAAiB;AACtB,WAAK,kBAAkB,CAAC;AACxB,UAAI,KAAK,WAAW,QAAQ,MAAO,MAAK,iBAAiB;AACzD,WAAK,QAAQ;AACb,WAAK,KAAK,gBAAgB;AAC1B,WAAK,KAAK,eAAe;AAAA,IAC3B,WAAW,SAAS,mBAAmB;AACrC,WAAK,iBAAiB;AACtB,UAAI,KAAK,WAAW,QAAQ,MAAO,MAAK,iBAAiB;AACzD,WAAK,QAAQ;AACb,WAAK,KAAK,eAAe;AAAA,IAC3B,WAAW,SAAS,YAAY;AAC9B,WAAK,qBAAqB;AAC1B,WAAK,QAAQ;AAAA,IACf,WAAW,SAAS,WAAW;AAC7B,6BAAuB,KAAK,OAAQ,MAAM,OAAuC,IAAI,IAAI;AAAA,IAC3F,WAAW,SAAS,mBAAmB,SAAS,kBAAkB;AAChE,6BAAuB,KAAK,OAAO,KAAK,WAAW,MAAM,WAAW;AAAA,IACtE;AACA,SAAK,cAAc,IAAI,YAAY,MAAM,EAAE,QAAQ,MAAM,QAAQ,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AAAA,EACnG;AAAA,EAEA,uBAA6B;AAC3B,UAAM,QAAQ,KAAK,aAAa,QAAQ;AACxC,QAAI,CAAC,MAAO;AACZ,QAAI;AACF,WAAK,UAAU,KAAK,MAAM,KAAK;AAC/B,WAAK,WAAW,UAAU,KAAK,OAAO;AAAA,IACxC,SAAS,OAAO;AACd,YAAM,QAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACtE,WAAK,cAAc,IAAI,YAAY,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AAAA,IACtG;AAAA,EACF;AAAA,EAEA,UAAgB;AACd,SAAK,YAAY,WAAW;AAC5B,UAAM,QAAQ,KAAK,WAAW;AAC9B,UAAM,SAAS,KAAK,WAAW;AAC/B,UAAM,SAAS,KAAK,WAAW;AAC/B,UAAM,KAAK,eAAe,KAAK,WAAW,OAAO,OAAO;AACxD,SAAK,MAAM,YAAY,UAAU,MAAM;AAAA;AAAA,UAEjC,MAAM,WAAW,YAAY,oBAAoB,WAAW,GAAG,eAAe,CAAC,SAAS,EAAE;AAAA,UAC1F,MAAM,WAAW,UAAU,mCAAmC,WAAW,MAAM,OAAO,WAAW,GAAG,iBAAiB,CAAC,WAAW,EAAE;AAAA,UACnI,UAAU,SAAS,KAAK,WAAW,QAAQ,MAAM,IAAI,MAAM,WAAW,aAAa,MAAM,WAAW,UAAU,gCAAgC,WAAW,GAAG,aAAa,CAAC,kBAAkB,EAAE;AAAA;AAEpM,UAAM,QAAQ,KAAK,MAAM,cAAc,yBAAyB;AAChE,QAAI,SAAS,KAAK,mBAAoB,MAAK,eAAe,OAAO,KAAK,kBAAkB;AACxF,2BAAuB,KAAK,OAAO,KAAK,WAAW,MAAM,WAAW;AACpE,SAAK,MAAM;AAAA,EACb;AAAA,EAEA,WAAW,QAAkB,QAA6B;AACxD,UAAM,WAAW,KAAK,WAAW,OAAO;AACxC,UAAM,WAAW,KAAK,WAAW;AACjC,UAAM,OAAO,OAAO;AACpB,UAAM,KAAK,eAAe,KAAK,WAAW,OAAO,OAAO;AACxD,UAAM,WAAW,KAAK,WAAW,OAAO,mBAAmB,KAAK,CAAC,UAAU,UAAU,MAAM;AAC3F,UAAM,qBAAqB,SAAS,kBAAkB,OAAO,QAAQ,SAAS;AAC9E,UAAM,cAAc,SAAS,cAAc,SAAS,eAAe;AACnE,UAAM,iBAAiB,2BAA2B,KAAK,WAAW,OAAO,SAAS,UAAU;AAC5F,WAAO,qBAAqB,SAAS,UAAU,UAAU,EAAE,IAAI,WAAW,SAAS,WAAW,QAAQ,CAAC,MAAM,EAAE;AAAA,QAC3G,SAAS,UAAU,yBAAyB,iBAAiB,0BAA0B,cAAc,KAAK,EAAE,KAAK,oBAAoB,OAAO,OAAO,KAAK,WAAW,OAAO,SAAS,SAAS,IAAI,KAAK,iBAAiB,QAAQ,KAAK,WAAW,OAAO,SAAS,UAAU,GAAG,cAAc,CAAC,WAAW,EAAE;AAAA,QACvS,KAAK,WAAW,QAAQ,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,YAK3B,SAAS,OAAO,2CAA2C,SAAS,eAAe,EAAE,yEAAyE,SAAS,eAAe,EAAE,mCAAmC,EAAE;AAAA;AAAA,YAE7N,SAAS,OAAO,0CAA0C,EAAE;AAAA,YAC5D,SAAS,SAAS,qFAAqF,EAAE;AAAA,YACzG,SAAS,YAAY,OAAO,OAAO,SAAS,IAAI,8DAA8D,EAAE;AAAA,YAChH,SAAS,eAAe,wEAAwE,EAAE;AAAA,YAClG,SAAS,oBAAoB,SAAS,UAAU,0CAA0C,EAAE;AAAA,YAC5F,SAAS,cAAc,SAAS,UAAU,wDAAwD,EAAE;AAAA;AAAA,UAEtG,SAAS,YAAY,OAAO,OAAO,SAAS,IAAI,uDAAuD,EAAE;AAAA,UACzG,SAAS,eAAe,oCAAoC,KAAK,WAAW,OAAO,cAAc,KAAK,GAAG,CAAC,yCAAyC,EAAE;AAAA;AAAA;AAAA,MAGzJ,cAAc;AAAA,QACZ,SAAS,aAAa;AAAA,uDACyB,OAAO,UAAU,IAAI,aAAa,EAAE,gBAAgB,WAAW,GAAG,eAAe,CAAC,YAAO,WAAW,GAAG,QAAQ,CAAC;AAAA,mDACpH,OAAO,WAAW,UAAU,SAAS,UAAU,KAAK,KAAK,CAAC,KAAK,WAAW,MAAM,SAAS,aAAa,EAAE,gBAAgB,WAAW,GAAG,WAAW,CAAC,KAAK,WAAW,GAAG,IAAI,CAAC;AAAA,gBAC7M,EAAE;AAAA,QACV,sBAAsB,SAAS,cAAc;AAAA,UAC3C,qBAAqB,gCAAgC,WAAW,GAAG,WAAW,CAAC,uCAAuC,OAAO,QAAQ,IAAI,CAAC,MAAM,UAAU,kBAAkB,KAAK,KAAK,UAAU,KAAK,WAAW,MAAM,cAAc,aAAa,EAAE,IAAI,WAAW,KAAK,SAAS,KAAK,UAAU,aAAa,GAAG,cAAc,EAAE,QAAQ,QAAQ,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC,sBAAsB,EAAE;AAAA,UACjY,SAAS,cAAc,4DAA4D,KAAK,WAAW,MAAM,cAAc,YAAY,EAAE,KAAK,WAAW,GAAG,WAAW,CAAC,aAAa,EAAE;AAAA,gBAC7K,EAAE;AAAA,cACJ,EAAE;AAAA,EACd;AAAA,EAEA,WAAW,QAAkB,QAA6B;AACxD,UAAM,MAAM,OAAO,QAAQ,cAAc,OAAO;AAChD,UAAM,aAAa;AAAA,MACjB;AAAA,MACA,YAAY,KAAK,WAAW,OAAO,OAAO;AAAA,MAC1C,KAAK,WAAW,OAAO,cAAc,gBAAgB,KAAK,WAAW,OAAO,WAAW,MAAM;AAAA,MAC7F,OAAO,SAAS,WAAW,OAAO,SAAS,WAAW,WAAW,OAAO,MAAM,CAAC,MAAM;AAAA,MACrF,eAAe,WAAW,OAAO,KAAK,CAAC;AAAA,MACvC,qBAAqB,OAAO,KAAK;AAAA,IACnC,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG;AAC1B,UAAM,SAAS,OAAO,OAAO,IAAI,CAAC,UAAU,eAAe,WAAW,MAAM,GAAG,CAAC,WAAW,MAAM,IAAI,YAAY,WAAW,MAAM,KAAK,CAAC,KAAK,MAAM,WAAW,YAAY,WAAW,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,MAAM,UAAU,YAAY,EAAE,GAAG,EAAE,KAAK,EAAE;AAC1P,WAAO,IAAI,GAAG,IAAI,UAAU,IAAI,MAAM,KAAK,GAAG;AAAA,EAChD;AAAA,EAEA,QAAc;AACZ,SAAK,MAAM,cAA2B,wBAAwB,GAAG,iBAAiB,SAAS,MAAM,KAAK,WAAW,SAAS,EAAE,UAAU,KAAK,WAAW,MAAM,WAAW,UAAU,CAAC,CAAC;AACnL,SAAK,MAAM,cAA2B,oBAAoB,GAAG,iBAAiB,SAAS,MAAM,KAAK,WAAW,KAAK,EAAE,UAAU,KAAK,WAAW,MAAM,WAAW,UAAU,CAAC,CAAC;AAC3K,SAAK,MAAM,cAAiC,sBAAsB,GAAG,iBAAiB,UAAU,CAAC,UAAU,KAAK,WAAW,aAAa,OAAQ,MAAM,OAA6B,KAAK,CAAC,CAAC;AAC1L,SAAK,MAAM,cAAgC,4BAA4B,GAAG,iBAAiB,UAAU,CAAC,UAAU,KAAK,WAAW,eAAgB,MAAM,OAA4B,OAAO,CAAC;AAAA,EAC5L;AAAA,EAEA,MAAM,iBAAgC;AACpC,UAAM,QAAQ,EAAE,KAAK;AACrB,QAAI;AACF,YAAM,MAAM,MAAM,KAAK,WAAW,kBAAkB;AACpD,UAAI,UAAU,KAAK,gBAAgB,CAAC,IAAK;AACzC,WAAK,qBAAqB;AAC1B,YAAM,QAAQ,KAAK,MAAM,cAAc,yBAAyB;AAChE,UAAI,MAAO,MAAK,eAAe,OAAO,GAAG;AAAA,IAC3C,SAAS,OAAO;AACd,YAAM,QAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACtE,WAAK,cAAc,IAAI,YAAY,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AAAA,IACtG;AAAA,EACF;AAAA,EAEA,eAAe,OAAyB,WAAyB;AAC/D,UAAM,OAAO,2BAA2B,KAAK,WAAW,OAAO,SAAS,UAAU;AAClF,UAAM,SAAS;AAAA,MACb;AAAA,MACA,KAAK,WAAW,OAAO;AAAA,MACvB,KAAK,WAAW;AAAA,MAChB,iBAAiB,mBAAmB,OAAO;AAAA,MAC3C,KAAK,uBAAuB;AAAA,IAC9B;AACA,QAAI,iBAAiB,oBAAoB,OAAO,cAAc;AAC5D,YAAM,iBAAiB,SAAS,CAAC,UAAU;AACzC,YAAI,KAAK,uBAAuB,UAAW;AAC3C,cAAM,yBAAyB;AAC/B,aAAK,yBAAyB,OAAO,SAAS;AAAA,MAChD,GAAG,EAAE,MAAM,KAAK,CAAC;AAAA,IACnB;AACA,QAAI,iBAAiB,oBAAoB,QAAQ,OAAO,WAAW;AACjE,YAAM,UAAU,MAAM;AACpB,cAAM,MAAM,KAAK,MAAM,cAA2B,uBAAuB;AACzE,YAAI,OAAO,MAAM,gBAAgB,MAAM,eAAe,aAAa,MAAM,QAAQ,YAAY;AAC3F,eAAK,YAAY,QAAQ,OAAO,KAAK,IAAI;AAAA,QAC3C;AAAA,MACF;AACA,YAAM,iBAAiB,kBAAkB,SAAS,EAAE,MAAM,KAAK,CAAC;AAChE,UAAI,MAAM,cAAc,iBAAiB,cAAe,gBAAe,OAAO;AAAA,IAChF;AACA,SAAK,WAAW,YAAY,KAAK;AACjC,qBAAiB,OAAO,WAAW,OAAO,WAAW;AAAA,EACvD;AAAA,EAEA,yBAAyB,QAA0B,WAAyB;AAC1E,SAAK,qBAAqB;AAC1B,SAAK,YAAY,WAAW;AAC5B,UAAM,gBAAgB,KAAK,WAAW,MAAM;AAC5C,UAAM,aAAa,KAAK,WAAW,MAAM,WAAW,aAAa,CAAC,OAAO;AACzE,UAAM,cAAc,OAAO,UAAU,IAAI;AACzC,gBAAY,gBAAgB,KAAK;AACjC,gBAAY,gBAAgB,aAAa;AACzC,gBAAY,SAAS,OAAO;AAC5B,gBAAY,QAAQ,OAAO;AAC3B,gBAAY,eAAe,OAAO;AAClC,UAAM,WAAW,KAAK,MAAM,kBAAkB;AAC9C,WAAO,YAAY,WAAW;AAC9B,SAAK,WAAW,YAAY,WAAW;AACvC,SAAK,WAAW,OAAO,aAAa;AACpC,QAAI,SAAU,aAAY,MAAM;AAChC,UAAM,MAAM,KAAK,MAAM,cAA2B,YAAY;AAC9D,SAAK,UAAU,OAAO,YAAY;AAClC,qBAAiB,aAAa,SAAS;AACvC,QAAI,WAAY,aAAY,iBAAiB,kBAAkB,MAAM,KAAK,YAAY,KAAK,EAAE,MAAM,MAAM,MAAS,GAAG,EAAE,MAAM,KAAK,CAAC;AACnI,SAAK,WAAW,cAAc,IAAI,YAAY,yBAAyB;AAAA,MACrE,QAAQ,EAAE,UAAU,KAAK,WAAW,QAAQ,MAAM,IAAI,WAAW,QAAQ,OAAO;AAAA,IAClF,CAAC,CAAC;AAAA,EACJ;AAAA,EAEA,mBAAyB;AACvB,SAAK,gBAAgB;AACrB,SAAK,qBAAqB;AAC1B,SAAK,qBAAqB;AAC1B,SAAK,YAAY,WAAW;AAAA,EAC9B;AAAA,EAEA,MAAM,kBAAiC;AACrC,UAAM,WAAW,KAAK,WAAW,QAAQ,YAAY,CAAC;AACtD,QAAI,CAAC,YAAY,CAAC,KAAK,WAAW,OAAO,SAAS,WAAY;AAC9D,UAAM,QAAQ,EAAE,KAAK;AACrB,UAAM,UAAgD,CAAC;AACvD,QAAI,KAAK,WAAW,OAAO,MAAO,SAAQ,QAAQ,KAAK,WAAW,OAAO;AACzE,QAAI,KAAK,WAAW,OAAO,YAAa,SAAQ,cAAc,KAAK,WAAW,OAAO;AACrF,QAAI,KAAK,WAAW,OAAO,WAAW,cAAc,OAAW,SAAQ,YAAY,KAAK,WAAW,OAAO,WAAW;AACrH,QAAI,KAAK,WAAW,OAAO,WAAW,iBAAiB,OAAW,SAAQ,eAAe,KAAK,WAAW,OAAO,WAAW;AAC3H,QAAI;AACF,YAAM,OAAO,MAAM,eAAe,UAAU,OAAO;AACnD,UAAI,UAAU,KAAK,iBAAkB;AACrC,WAAK,kBAAkB;AACvB,YAAM,MAAM,KAAK,MAAM,cAA2B,YAAY;AAC9D,YAAM,SAAS,KAAK,WAAW;AAC/B,UAAI,OAAO,UAAU,KAAK,WAAW,QAAQ,SAAS,SAAS;AAC7D,cAAM,OAAO,IAAI,cAA2B,iBAAiB;AAC7D,YAAI,KAAM,MAAK,YAAY,uBAAuB,OAAO,OAAO,KAAK,WAAW,OAAO,SAAS,SAAS,IAAI,MAAM,IAAI;AACvH,+BAAuB,KAAK,KAAK,WAAW,MAAM,WAAW;AAAA,MAC/D;AAAA,IACF,SAAS,OAAO;AACd,UAAI,UAAU,KAAK,iBAAkB;AACrC,YAAM,QAAQ,iBAAiB,QAAQ,QAAQ,IAAI,MAAM,OAAO,KAAK,CAAC;AACtE,WAAK,cAAc,IAAI,YAAY,YAAY,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,MAAM,UAAU,KAAK,CAAC,CAAC;AAAA,IACtG;AAAA,EACF;AACF;AAEO,IAAM,sBAAsB,CAAC,UAAU,sBAAmD;AAC/F,MAAI,OAAO,mBAAmB,YAAa,QAAO;AAClD,MAAI,CAAC,eAAe,IAAI,OAAO,EAAG,gBAAe,OAAO,SAAS,oBAAoB;AACrF,SAAO;AACT;","names":[]}
package/dist/index.js CHANGED
@@ -14,7 +14,7 @@ import {
14
14
  import {
15
15
  MangoAVPlayerElement,
16
16
  defineMangoAVPlayer
17
- } from "./chunk-YHTJZXOE.js";
17
+ } from "./chunk-YX6L6CUF.js";
18
18
  import "./chunk-ELGGWWDS.js";
19
19
  import {
20
20
  MangoAVTranscriptElement,
package/dist/player.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MangoAVPlayerElement,
3
3
  defineMangoAVPlayer
4
- } from "./chunk-YHTJZXOE.js";
4
+ } from "./chunk-YX6L6CUF.js";
5
5
  import "./chunk-ELGGWWDS.js";
6
6
  import "./chunk-C4H46HDS.js";
7
7
  import "./chunk-CIAQZ2EB.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mango-iiif/av",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Framework-free IIIF audio and video components powered by Media Chrome.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/mango-av-player.ts"],"sourcesContent":["import { AVControllerElement } from './controller-element';\nimport { componentTheme } from './component-styles';\nimport { ensureMediaChrome } from './media-chrome';\nimport { AudioArtVisualizer, audioArtContentHtml, audioArtTranscriptHtml, resolveAudioVisualizerMode, syncAudioArtTranscript } from './audio-art';\nimport { loadTranscript } from '../transcript';\nimport type { AVCanvas, AVManifest, AVPlayerConfig, AVPlayerEventMap, JsonObject, MediaSource, TranscriptCue } from '../types';\nimport { escapeHtml, formatString, resolveStrings } from '../utils';\nimport { applyMediaSource, resolveAudioMediaPolicy } from './media-policy';\n\nlet hlsElementRegistration: Promise<unknown> | undefined;\nconst ensureHlsElement = (): Promise<unknown> => {\n hlsElementRegistration ??= import('hls-video-element');\n return hlsElementRegistration;\n};\n\nconst styles = `${componentTheme}\n :host { --mango-av-player-aspect-ratio: 16 / 9; }\n .player { background: #08080a; border-radius: var(--mango-av-radius); color: white; overflow: clip; position: relative; }\n media-controller { display: block; width: 100%; }\n media-controller:not([audio]) { aspect-ratio: var(--mango-av-player-aspect-ratio); }\n video, hls-video { display: block; height: 100%; object-fit: contain; width: 100%; }\n audio { width: 100%; }\n media-control-bar { width: 100%; }\n .audio-art { --mango-av-wave-edge-strength: 0%; --mango-av-wave-mid-strength: 0%; --mango-av-wave-rise: 8%; --mango-av-wave-strength: 0%; align-items: center; aspect-ratio: 16 / 7; background: linear-gradient(#09080d, #111019); display: flex; justify-content: center; overflow: hidden; padding: 2rem; position: relative; text-align: center; }\n .audio-art.visualizer--pulse { background: radial-gradient(ellipse 140% 72% at 50% calc(100% + var(--mango-av-wave-rise)), color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-strength), transparent) 0%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-mid-strength), transparent) 40%, color-mix(in srgb, var(--mango-av-accent) var(--mango-av-wave-edge-strength), transparent) 62%, transparent 78%), linear-gradient(#09080d, #111019); }\n .audio-art-text { display: contents; }\n .audio-art-visualizer-canvas { height: 100%; inset: 0; pointer-events: none; position: absolute; width: 100%; }\n .audio-art-title { font-size: clamp(1.1rem, 3vw, 2rem); font-weight: 700; position: relative; z-index: 1; }\n .audio-art-transcript { height: 100%; inset: 0; overflow: hidden; position: absolute; z-index: 1; }\n .audio-art-cue { align-items: center; display: flex; flex-direction: column; font-size: clamp(.7rem, 1.3vw, .875rem); font-weight: 550; gap: .15rem; left: 12%; line-height: 1.35; position: absolute; right: 12%; top: 50%; transition: opacity 360ms ease, transform 480ms cubic-bezier(.22, 1, .36, 1); }\n .audio-art-transcript.seeking .audio-art-cue { transition: none; }\n .audio-art-cue.active { font-size: clamp(.78rem, 1.5vw, 1rem); font-weight: 650; }\n .audio-art-cue > span:last-child { display: -webkit-box; overflow: hidden; -webkit-box-orient: vertical; -webkit-line-clamp: 2; }\n .audio-art-speaker { font-size: .7em; letter-spacing: .04em; text-transform: uppercase; }\n .toolbar { align-items: center; background: #151518; display: flex; flex-wrap: wrap; gap: .5rem; justify-content: space-between; padding: .55rem .7rem; }\n .toolbar button, .toolbar select { background: #29292e; border: 1px solid #44444a; border-radius: .35rem; color: white; padding: .4rem .55rem; }\n .group { align-items: center; display: flex; gap: .45rem; }\n .error { background: #fff0f0; color: #8a1717; padding: 1rem; }\n .sr-only { clip: rect(0,0,0,0); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; }\n`;\n\nexport class MangoAVPlayerElement extends AVControllerElement {\n static observedAttributes = ['manifest-url', 'config'];\n\n #root: ShadowRoot;\n #manifestInput: JsonObject | string | undefined;\n #config: AVPlayerConfig = {};\n #resolvedSourceUrl: string | undefined;\n #sourceToken = 0;\n #fallbackSourceUrl: string | undefined;\n #transcriptCues: TranscriptCue[] = [];\n #transcriptToken = 0;\n #visualizer = new AudioArtVisualizer();\n\n constructor() {\n super();\n this.#root = this.attachShadow({ mode: 'open' });\n }\n\n get manifest(): JsonObject | string | undefined {\n return this.#manifestInput;\n }\n\n set manifest(value: JsonObject | string | undefined) {\n this.#manifestInput = value;\n if (this.isConnected && value !== undefined) void this.load(value);\n }\n\n get config(): AVPlayerConfig {\n return this.#config;\n }\n\n set config(value: AVPlayerConfig) {\n this.#config = value;\n this.controller.configure(value);\n this.#render();\n }\n\n override connectedCallback(): void {\n this.#readConfigAttribute();\n void ensureMediaChrome(this.controller.config.preferredLanguages[0]);\n super.connectedCallback();\n const source = this.#manifestInput ?? this.getAttribute('manifest-url') ?? undefined;\n if (source !== undefined && !this.controller.manifest) void this.load(source);\n }\n\n override disconnectedCallback(): void {\n this.#visualizer.disconnect();\n super.disconnectedCallback();\n }\n\n attributeChangedCallback(name: string, oldValue: string | null, newValue: string | null): void {\n if (!this.isConnected || oldValue === newValue) return;\n if (name === 'manifest-url' && newValue) {\n this.#manifestInput = newValue;\n void this.load(newValue);\n } else if (name === 'config') {\n this.#readConfigAttribute();\n this.#render();\n }\n }\n\n async load(input: JsonObject | string): Promise<AVManifest> {\n this.#manifestInput = input;\n return await this.controller.load(input);\n }\n\n play(): Promise<void> { return this.controller.play(); }\n pause(): void { this.controller.pause(); }\n seekTo(time: number): void { this.controller.seekTo(time); }\n selectCanvas(indexOrId: number | string, options?: { time?: number; autoplay?: boolean }): AVCanvas | undefined {\n return this.controller.selectCanvas(indexOrId, options);\n }\n\n protected controllerChanged(): void {\n this.#resetSourceLoad();\n this.#transcriptCues = [];\n this.#render();\n void this.#loadTranscript();\n }\n\n protected handleControllerEvent<K extends keyof AVPlayerEventMap>(type: K, event: CustomEvent<AVPlayerEventMap[K]>): void {\n if (type === 'av-configchange') {\n this.#resetSourceLoad();\n void ensureMediaChrome(this.controller.config.preferredLanguages[0]).then(() => {\n this.#render();\n void this.#loadTranscript();\n void this.#resolveSource();\n });\n } else if (type === 'av-ready' || type === 'av-canvaschange') {\n this.#resetSourceLoad();\n this.#transcriptCues = [];\n if (this.controller.source?.isHls) void ensureHlsElement();\n this.#render();\n void this.#loadTranscript();\n void this.#resolveSource();\n } else if (type === 'av-sourcechange') {\n this.#resetSourceLoad();\n if (this.controller.source?.isHls) void ensureHlsElement();\n this.#render();\n void this.#resolveSource();\n } else if (type === 'av-error') {\n this.#resolvedSourceUrl = undefined;\n this.#render();\n } else if (type === 'av-seek') {\n syncAudioArtTranscript(this.#root, (event.detail as AVPlayerEventMap['av-seek']).to, true);\n } else if (type === 'av-timeupdate' || type === 'av-statechange') {\n syncAudioArtTranscript(this.#root, this.controller.state.currentTime);\n }\n this.dispatchEvent(new CustomEvent(type, { detail: event.detail, bubbles: true, composed: true }));\n }\n\n #readConfigAttribute(): void {\n const value = this.getAttribute('config');\n if (!value) return;\n try {\n this.#config = JSON.parse(value) as AVPlayerConfig;\n this.controller.configure(this.#config);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n #render(): void {\n this.#visualizer.disconnect();\n const state = this.controller.state;\n const canvas = this.controller.canvas;\n const source = this.controller.source;\n const ui = resolveStrings(this.controller.config.strings);\n this.#root.innerHTML = `<style>${styles}</style>\n <div class=\"player\">\n ${state.status === 'loading' ? `<p role=\"status\">${escapeHtml(ui.loadingManifest)}</p>` : ''}\n ${state.status === 'error' ? `<div class=\"error\" role=\"alert\">${escapeHtml(state.error?.message ?? ui.unableToLoadMedia)}</div>` : ''}\n ${canvas && source ? this.#readyHtml(canvas, source) : state.status !== 'loading' && state.status !== 'error' ? `<div class=\"audio-art\"><span>${escapeHtml(ui.noMediaLoaded)}</span></div>` : ''}\n </div>`;\n const media = this.#root.querySelector('video, audio, hls-video') as HTMLMediaElement | null;\n if (media && this.#resolvedSourceUrl) this.#activateMedia(media, this.#resolvedSourceUrl);\n syncAudioArtTranscript(this.#root, this.controller.state.currentTime);\n this.#bind();\n }\n\n #readyHtml(canvas: AVCanvas, source: MediaSource): string {\n const controls = this.controller.config.controls;\n const manifest = this.controller.manifest;\n const kind = source.kind;\n const ui = resolveStrings(this.controller.config.strings);\n const language = this.controller.config.preferredLanguages.find((value) => value !== 'none');\n const showSourceSelector = controls.sourceSelector && canvas.sources.length > 1;\n const showToolbar = controls.navigation || controls.autoAdvance || showSourceSelector;\n const visualizerMode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);\n return `<media-controller ${kind === 'audio' ? 'audio' : ''} ${language ? `lang=\"${escapeHtml(language)}\"` : ''}>\n ${kind === 'audio' ? `<div class=\"audio-art ${visualizerMode ? `visualizer visualizer--${visualizerMode}` : ''}\">${audioArtContentHtml(canvas.label, this.controller.config.audioArt.title ?? '', this.#transcriptCues, Boolean(this.controller.config.audioArt.transcript), visualizerMode)}</div>` : ''}\n ${this.#mediaHtml(canvas, source)}\n <slot name=\"overlay\"></slot>\n <slot name=\"controls\">\n <media-control-bar>\n <media-play-button></media-play-button>\n ${controls.seek ? `<media-seek-backward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-backward-button><media-seek-forward-button seekoffset=\"${controls.skipSeconds ?? 10}\"></media-seek-forward-button>` : ''}\n <media-time-display showduration></media-time-display>\n ${controls.seek ? '<media-time-range></media-time-range>' : ''}\n ${controls.volume ? '<media-mute-button></media-mute-button><media-volume-range></media-volume-range>' : ''}\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu-button></media-captions-menu-button>' : ''}\n ${controls.playbackRate ? '<media-playback-rate-menu-button></media-playback-rate-menu-button>' : ''}\n ${controls.pictureInPicture && kind === 'video' ? '<media-pip-button></media-pip-button>' : ''}\n ${controls.fullscreen && kind === 'video' ? '<media-fullscreen-button></media-fullscreen-button>' : ''}\n </media-control-bar>\n ${controls.captions && canvas.tracks.length > 0 ? '<media-captions-menu hidden></media-captions-menu>' : ''}\n ${controls.playbackRate ? `<media-playback-rate-menu rates=\"${this.controller.config.playbackRates.join(' ')}\" hidden></media-playback-rate-menu>` : ''}\n </slot>\n </media-controller>\n ${showToolbar ? `<div class=\"toolbar\">\n ${controls.navigation ? `<div class=\"group\">\n <button type=\"button\" data-action=\"previous\" ${canvas.index === 0 ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.previousSection)}\">← ${escapeHtml(ui.previous)}</button>\n <button type=\"button\" data-action=\"next\" ${canvas.index === (manifest?.canvases.length ?? 1) - 1 && !this.controller.state.repeat ? 'disabled' : ''} aria-label=\"${escapeHtml(ui.nextSection)}\">${escapeHtml(ui.next)} →</button>\n </div>` : ''}\n ${showSourceSelector || controls.autoAdvance ? `<div class=\"group\">\n ${showSourceSelector ? `<label><span class=\"sr-only\">${escapeHtml(ui.mediaSource)}</span><select data-action=\"source\">${canvas.sources.map((item, index) => `<option value=\"${index}\" ${index === this.controller.state.sourceIndex ? 'selected' : ''}>${escapeHtml(item.label ?? item.format ?? formatString(ui.sourceNumber, { number: index + 1 }))}</option>`).join('')}</select></label>` : ''}\n ${controls.autoAdvance ? `<label><input type=\"checkbox\" data-action=\"auto-advance\" ${this.controller.state.autoAdvance ? 'checked' : ''}> ${escapeHtml(ui.autoAdvance)}</label>` : ''}\n </div>` : ''}\n </div>` : ''}`;\n }\n\n #mediaHtml(canvas: AVCanvas, source: MediaSource): string {\n const tag = source.isHls ? 'hls-video' : source.kind;\n const attributes = [\n 'slot=\"media\"',\n `preload=\"${this.controller.config.preload}\"`,\n this.controller.config.crossorigin ? `crossorigin=\"${this.controller.config.crossorigin}\"` : '',\n source.kind === 'video' && canvas.poster ? `poster=\"${escapeHtml(canvas.poster)}\"` : '',\n `aria-label=\"${escapeHtml(canvas.label)}\"`,\n `data-canvasindex=\"${canvas.index}\"`,\n ].filter(Boolean).join(' ');\n const tracks = canvas.tracks.map((track) => `<track src=\"${escapeHtml(track.src)}\" kind=\"${track.kind}\" label=\"${escapeHtml(track.label)}\" ${track.language ? `srclang=\"${escapeHtml(track.language)}\"` : ''} ${track.default ? 'default' : ''}>`).join('');\n return `<${tag} ${attributes}>${tracks}</${tag}>`;\n }\n\n #bind(): void {\n this.#root.querySelector<HTMLElement>('[data-action=previous]')?.addEventListener('click', () => this.controller.previous({ autoplay: this.controller.state.status === 'playing' }));\n this.#root.querySelector<HTMLElement>('[data-action=next]')?.addEventListener('click', () => this.controller.next({ autoplay: this.controller.state.status === 'playing' }));\n this.#root.querySelector<HTMLSelectElement>('[data-action=source]')?.addEventListener('change', (event) => this.controller.selectSource(Number((event.target as HTMLSelectElement).value)));\n this.#root.querySelector<HTMLInputElement>('[data-action=auto-advance]')?.addEventListener('change', (event) => this.controller.setAutoAdvance((event.target as HTMLInputElement).checked));\n }\n\n async #resolveSource(): Promise<void> {\n const token = ++this.#sourceToken;\n try {\n const url = await this.controller.resolvedSourceUrl();\n if (token !== this.#sourceToken || !url) return;\n this.#resolvedSourceUrl = url;\n const media = this.#root.querySelector('video, audio, hls-video') as HTMLMediaElement | null;\n if (media) this.#activateMedia(media, url);\n } catch (cause) {\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n\n #activateMedia(media: HTMLMediaElement, sourceUrl: string): void {\n const mode = resolveAudioVisualizerMode(this.controller.config.audioArt.visualizer);\n const policy = resolveAudioMediaPolicy(\n sourceUrl,\n this.controller.config.crossorigin,\n this.controller.crossoriginExplicit,\n media instanceof HTMLAudioElement ? mode : undefined,\n this.#fallbackSourceUrl === sourceUrl,\n );\n if (media instanceof HTMLAudioElement && policy.implicitCors) {\n media.addEventListener('error', (event) => {\n if (this.#fallbackSourceUrl === sourceUrl) return;\n event.stopImmediatePropagation();\n this.#fallbackToOrdinaryAudio(media, sourceUrl);\n }, { once: true });\n }\n if (media instanceof HTMLAudioElement && mode && policy.visualize) {\n const connect = () => {\n const art = this.#root.querySelector<HTMLElement>('.audio-art.visualizer');\n if (art && media.isConnected && (media.currentSrc === sourceUrl || media.src === sourceUrl)) {\n this.#visualizer.connect(media, art, mode);\n }\n };\n media.addEventListener('loadedmetadata', connect, { once: true });\n if (media.readyState >= HTMLMediaElement.HAVE_METADATA) queueMicrotask(connect);\n }\n this.controller.attachMedia(media);\n applyMediaSource(media, sourceUrl, policy.crossOrigin);\n }\n\n #fallbackToOrdinaryAudio(failed: HTMLAudioElement, sourceUrl: string): void {\n this.#fallbackSourceUrl = sourceUrl;\n this.#visualizer.disconnect();\n const requestedTime = this.controller.state.currentTime;\n const shouldPlay = this.controller.state.status === 'playing' || !failed.paused;\n const replacement = failed.cloneNode(true) as HTMLAudioElement;\n replacement.removeAttribute('src');\n replacement.removeAttribute('crossorigin');\n replacement.volume = failed.volume;\n replacement.muted = failed.muted;\n replacement.playbackRate = failed.playbackRate;\n const hadFocus = this.#root.activeElement === failed;\n failed.replaceWith(replacement);\n this.controller.attachMedia(replacement);\n this.controller.seekTo(requestedTime);\n if (hadFocus) replacement.focus();\n const art = this.#root.querySelector<HTMLElement>('.audio-art');\n art?.classList.remove('visualizer');\n applyMediaSource(replacement, sourceUrl);\n if (shouldPlay) replacement.addEventListener('loadedmetadata', () => void replacement.play().catch(() => undefined), { once: true });\n this.controller.dispatchEvent(new CustomEvent('av-visualizerfallback', {\n detail: { canvasId: this.controller.canvas?.id ?? '', sourceUrl, reason: 'cors' },\n }));\n }\n\n #resetSourceLoad(): void {\n this.#sourceToken += 1;\n this.#resolvedSourceUrl = undefined;\n this.#fallbackSourceUrl = undefined;\n this.#visualizer.disconnect();\n }\n\n async #loadTranscript(): Promise<void> {\n const resource = this.controller.canvas?.transcripts[0];\n if (!resource || !this.controller.config.audioArt.transcript) return;\n const token = ++this.#transcriptToken;\n const options: Parameters<typeof loadTranscript>[1] = {};\n if (this.controller.config.fetch) options.fetch = this.controller.config.fetch;\n if (this.controller.config.requestInit) options.requestInit = this.controller.config.requestInit;\n if (this.controller.config.transcript.showNotes !== undefined) options.showNotes = this.controller.config.transcript.showNotes;\n if (this.controller.config.transcript.showMetadata !== undefined) options.showMetadata = this.controller.config.transcript.showMetadata;\n try {\n const cues = await loadTranscript(resource, options);\n if (token !== this.#transcriptToken) return;\n this.#transcriptCues = cues;\n const art = this.#root.querySelector<HTMLElement>('.audio-art');\n const canvas = this.controller.canvas;\n if (art && canvas && this.controller.source?.kind === 'audio') {\n const text = art.querySelector<HTMLElement>('.audio-art-text');\n if (text) text.innerHTML = audioArtTranscriptHtml(canvas.label, this.controller.config.audioArt.title ?? '', cues, true);\n syncAudioArtTranscript(art, this.controller.state.currentTime);\n }\n } catch (cause) {\n if (token !== this.#transcriptToken) return;\n const error = cause instanceof Error ? cause : new Error(String(cause));\n this.dispatchEvent(new CustomEvent('av-error', { detail: { error }, bubbles: true, composed: true }));\n }\n }\n}\n\nexport const defineMangoAVPlayer = (tagName = 'mango-av-player'): typeof MangoAVPlayerElement => {\n if (typeof customElements === 'undefined') return MangoAVPlayerElement;\n if (!customElements.get(tagName)) customElements.define(tagName, MangoAVPlayerElement);\n return MangoAVPlayerElement;\n};\n"],"mappings":"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","names":[]}