UNPKG

media-chrome

Version:

Custom elements (web components) for making audio and video player controls that look great in your website or app.

261 lines (258 loc) • 8.6 kB
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 _template, _prevTemplate, _prevTemplateId, _observer, _upgradeProperty, upgradeProperty_fn, _updateTemplate, updateTemplate_fn, _renderBind; import { MediaStateChangeEvents } from "./constants.js"; import { globalThis, document } from "./utils/server-safe-globals.js"; import { TemplateInstance } from "./utils/template-parts.js"; import { processor } from "./utils/template-processor.js"; import { camelCase, isNumericString } from "./utils/utils.js"; export * from "./utils/template-parts.js"; const observedMediaAttributes = { mediatargetlivewindow: "targetlivewindow", mediastreamtype: "streamtype" }; const prependTemplate = document.createElement("template"); prependTemplate.innerHTML = /*html*/ ` <style> :host { display: inline-block; line-height: 0; } media-controller { width: 100%; height: 100%; } media-captions-button:not([mediasubtitleslist]), media-captions-menu:not([mediasubtitleslist]), media-captions-menu-button:not([mediasubtitleslist]), media-audio-track-menu[mediaaudiotrackunavailable], media-audio-track-menu-button[mediaaudiotrackunavailable], media-rendition-menu[mediarenditionunavailable], media-rendition-menu-button[mediarenditionunavailable], media-volume-range[mediavolumeunavailable], media-airplay-button[mediaairplayunavailable], media-fullscreen-button[mediafullscreenunavailable], media-cast-button[mediacastunavailable], media-pip-button[mediapipunavailable] { display: none; } </style> `; class MediaThemeElement extends globalThis.HTMLElement { constructor() { super(); __privateAdd(this, _upgradeProperty); __privateAdd(this, _updateTemplate); __privateAdd(this, _template, void 0); __privateAdd(this, _prevTemplate, void 0); __privateAdd(this, _prevTemplateId, void 0); __privateAdd(this, _observer, void 0); __privateAdd(this, _renderBind, void 0); if (this.shadowRoot) { this.renderRoot = this.shadowRoot; } else { this.renderRoot = this.attachShadow({ mode: "open" }); this.createRenderer(); } __privateSet(this, _observer, new MutationObserver((mutationList) => { var _a; if (this.mediaController && !((_a = this.mediaController) == null ? void 0 : _a.breakpointsComputed)) return; if (mutationList.some((mutation) => { const target = mutation.target; if (target === this) return true; if (target.localName !== "media-controller") return false; if (observedMediaAttributes[mutation.attributeName]) return true; if (mutation.attributeName.startsWith("breakpoint")) return true; return false; })) { this.render(); } })); __privateSet(this, _renderBind, this.render.bind(this)); __privateMethod(this, _upgradeProperty, upgradeProperty_fn).call(this, "template"); } /** @type {HTMLElement & { breakpointsComputed?: boolean }} */ get mediaController() { return this.renderRoot.querySelector("media-controller"); } get template() { var _a; return (_a = __privateGet(this, _template)) != null ? _a : this.constructor.template; } set template(value) { if (value === null) { this.removeAttribute("template"); return; } if (typeof value === "string") { this.setAttribute("template", value); } else if (value instanceof HTMLTemplateElement) { __privateSet(this, _template, value); __privateSet(this, _prevTemplateId, null); this.createRenderer(); } } get props() { var _a, _b, _c; const observedAttributes = [ ...Array.from((_b = (_a = this.mediaController) == null ? void 0 : _a.attributes) != null ? _b : []).filter( ({ name }) => { return observedMediaAttributes[name] || name.startsWith("breakpoint"); } ), ...Array.from(this.attributes) ]; const props = {}; for (const attr of observedAttributes) { const name = (_c = observedMediaAttributes[attr.name]) != null ? _c : camelCase(attr.name); let { value } = attr; if (value != null) { if (isNumericString(value)) { value = parseFloat(value); } props[name] = value === "" ? true : value; } else { props[name] = false; } } return props; } attributeChangedCallback(attrName, oldValue, newValue) { if (attrName === "template" && oldValue != newValue) { __privateMethod(this, _updateTemplate, updateTemplate_fn).call(this); } } connectedCallback() { this.addEventListener( MediaStateChangeEvents.BREAKPOINTS_COMPUTED, __privateGet(this, _renderBind) ); __privateGet(this, _observer).observe(this, { attributes: true }); __privateGet(this, _observer).observe(this.renderRoot, { attributes: true, subtree: true }); __privateMethod(this, _updateTemplate, updateTemplate_fn).call(this); } disconnectedCallback() { this.removeEventListener( MediaStateChangeEvents.BREAKPOINTS_COMPUTED, __privateGet(this, _renderBind) ); __privateGet(this, _observer).disconnect(); } createRenderer() { if (this.template instanceof HTMLTemplateElement && this.template !== __privateGet(this, _prevTemplate)) { __privateSet(this, _prevTemplate, this.template); this.renderer = new TemplateInstance( this.template, this.props, // @ts-ignore this.constructor.processor ); this.renderRoot.textContent = ""; this.renderRoot.append( prependTemplate.content.cloneNode(true), this.renderer ); } } render() { var _a; (_a = this.renderer) == null ? void 0 : _a.update(this.props); } } _template = new WeakMap(); _prevTemplate = new WeakMap(); _prevTemplateId = new WeakMap(); _observer = new WeakMap(); _upgradeProperty = new WeakSet(); upgradeProperty_fn = function(prop) { if (Object.prototype.hasOwnProperty.call(this, prop)) { const value = this[prop]; delete this[prop]; this[prop] = value; } }; _updateTemplate = new WeakSet(); updateTemplate_fn = function() { var _a; const templateId = this.getAttribute("template"); if (!templateId || templateId === __privateGet(this, _prevTemplateId)) return; const rootNode = this.getRootNode(); const template = (_a = rootNode == null ? void 0 : rootNode.getElementById) == null ? void 0 : _a.call( rootNode, templateId ); if (template) { __privateSet(this, _prevTemplateId, templateId); __privateSet(this, _template, template); this.createRenderer(); return; } if (isValidUrl(templateId)) { __privateSet(this, _prevTemplateId, templateId); request(templateId).then((data) => { const template2 = document.createElement("template"); template2.innerHTML = data; __privateSet(this, _template, template2); this.createRenderer(); }).catch(console.error); } }; _renderBind = new WeakMap(); MediaThemeElement.observedAttributes = ["template"]; MediaThemeElement.processor = processor; function isValidUrl(url) { if (!/^(\/|\.\/|https?:\/\/)/.test(url)) return false; const base = /^https?:\/\//.test(url) ? void 0 : location.origin; try { new URL(url, base); } catch (e) { return false; } return true; } async function request(resource) { const response = await fetch(resource); if (response.status !== 200) { throw new Error( `Failed to load resource: the server responded with a status of ${response.status}` ); } return response.text(); } if (!globalThis.customElements.get("media-theme")) { globalThis.customElements.define("media-theme", MediaThemeElement); } export { MediaThemeElement };