UNPKG

@aidenlx/player

Version:

Headless web components that make integrating media on the a web a breeze.

151 lines (150 loc) 4.92 kB
import { __decorateClass } from "../../chunks/chunk.LNH2V2XS.js"; import { DisposalBin, eventListener, IntersectionController, PageController, vdsEvent } from "@vidstack/foundation"; import { html, LitElement } from "lit"; import { property } from "lit/decorators.js"; class MediaVisibilityElement extends LitElement { constructor() { super(...arguments); this.viewportEnterDelay = 0; this.pageChangeType = "state"; this.pageEnterDelay = 0; this.intersectionThreshold = 1; this._isIntersecting = false; this._mediaProviderDisposal = new DisposalBin(); this._handleMediaProviderConnect = eventListener(this, "vds-media-provider-connect", (event) => { const { element, onDisconnect } = event.detail; this._mediaProvider = element; this._mediaProviderDisposal.add(() => { this._mediaProvider = void 0; }); onDisconnect(() => { this._mediaProviderDisposal.empty(); }); }); this._hasIntersected = false; this.intersectionController = new IntersectionController(this, { root: this.intersectionRoot ? document.querySelector(this.intersectionRoot) : null, threshold: this.intersectionThreshold }, (entries) => { window.clearTimeout(this._intersectionTimeout); const entry = entries[0]; this._isIntersecting = entry.isIntersecting; if (this._hasIntersected) { if (entry.isIntersecting) { this._intersectionTimeout = window.setTimeout(() => { this._triggerOnEnter(this.enterViewport); this._intersectionTimeout = void 0; }, this.viewportEnterDelay); } else if (this.exitViewport) { this._isIntersecting = false; this._triggerOnExit(this.exitViewport); } } this._hasIntersected = true; this._dispatchVisibilityChange(); }); this.pageController = new PageController(this, ({ state, visibility }) => { window.clearTimeout(this._pageTimeout); if (!this.isIntersecting) return; const newState = this.pageChangeType === "state" ? state : visibility; if (newState === "hidden") { this._triggerOnExit(this.exitPage); } else if (this.enterViewport) { this._pageTimeout = window.setTimeout(() => { this._triggerOnEnter(this.enterPage); this._pageTimeout = void 0; }, this.pageEnterDelay); } this._dispatchVisibilityChange(); }); } get isIntersecting() { return this._isIntersecting; } disconnectedCallback() { super.disconnectedCallback(); this._hasIntersected = false; this._mediaProviderDisposal.empty(); } render() { return html`<slot></slot>`; } get mediaProvider() { return this._mediaProvider; } _triggerOnEnter(mediaAction) { if (!this._mediaProvider) return; if (mediaAction === "play") { this._mediaProvider.paused = false; } else if (mediaAction === "unmute") { this._mediaProvider.muted = false; } } _triggerOnExit(mediaAction) { if (!this._mediaProvider) return; if (mediaAction === "pause") { this._mediaProvider.paused = true; } else if (mediaAction === "mute") { this._mediaProvider.muted = true; } } _dispatchVisibilityChange() { if (!this._mediaProvider) return; this.dispatchEvent(vdsEvent("vds-media-visibility-change", { bubbles: true, composed: true, detail: { provider: this._mediaProvider, viewport: { isIntersecting: this.isIntersecting }, page: { state: this.pageController.state, visibility: this.pageController.visibility } } })); } } __decorateClass([ property({ attribute: "enter-viewport" }) ], MediaVisibilityElement.prototype, "enterViewport", 2); __decorateClass([ property({ attribute: "exit-viewport" }) ], MediaVisibilityElement.prototype, "exitViewport", 2); __decorateClass([ property({ type: Number, attribute: "viewport-enter-delay" }) ], MediaVisibilityElement.prototype, "viewportEnterDelay", 2); __decorateClass([ property({ attribute: "enter-page" }) ], MediaVisibilityElement.prototype, "enterPage", 2); __decorateClass([ property({ attribute: "exit-page" }) ], MediaVisibilityElement.prototype, "exitPage", 2); __decorateClass([ property({ attribute: "page-change-type" }) ], MediaVisibilityElement.prototype, "pageChangeType", 2); __decorateClass([ property({ type: Number, attribute: "page-enter-delay" }) ], MediaVisibilityElement.prototype, "pageEnterDelay", 2); __decorateClass([ property({ attribute: "intersection-root" }) ], MediaVisibilityElement.prototype, "intersectionRoot", 2); __decorateClass([ property({ type: Number, attribute: "intersection-threshold" }) ], MediaVisibilityElement.prototype, "intersectionThreshold", 2); export { MediaVisibilityElement };