@aidenlx/player
Version:
Headless web components that make integrating media on the a web a breeze.
151 lines (150 loc) • 4.92 kB
JavaScript
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
};