@aidenlx/player
Version:
Headless web components that make integrating media on the a web a breeze.
140 lines (137 loc) • 3.74 kB
JavaScript
import {
__decorateClass
} from "../../chunks/chunk.LNH2V2XS.js";
import { createIntersectionController, isUndefined, preconnect } from "@vidstack/foundation";
import { css, html, LitElement } from "lit";
import { property, state } from "lit/decorators.js";
import { ifDefined } from "lit/directives/if-defined.js";
import { MediaRemoteControl, mediaStoreSubscription } from "../../media";
const didPreconnect = /* @__PURE__ */ new Set();
class PosterElement extends LitElement {
constructor() {
super();
this.__canLoad = false;
this._mediaRemoteControl = new MediaRemoteControl(this);
mediaStoreSubscription(this, "currentPoster", ($poster) => {
window.requestAnimationFrame(() => {
if (!this.__canLoad && !didPreconnect.has($poster)) {
preconnect($poster, "prefetch");
didPreconnect.add($poster);
}
});
this.__src = $poster;
if (this.__canLoad) {
this._setImgLoadingAttr();
}
});
mediaStoreSubscription(this, "canLoad", ($canLoad) => {
if (isUndefined(this.loading)) {
this._handleCanLoadChange($canLoad);
}
});
const intersectionController = createIntersectionController(this, { threshold: 0 }, (entries) => {
if (this.loading !== "lazy") {
intersectionController.hostDisconnected();
return;
}
if (entries[0]?.isIntersecting) {
this._handleCanLoadChange(true);
intersectionController.hostDisconnected();
}
});
}
static get styles() {
return [
css`
:host {
display: block;
contain: content;
pointer-events: none;
object-fit: cover;
box-sizing: border-box;
}
:host([hidden]) {
display: none;
}
img {
display: block;
width: 100%;
height: 100%;
pointer-events: none;
object-fit: inherit;
object-position: inherit;
user-select: none;
-webkit-user-select: none;
box-sizing: border-box;
}
`
];
}
get src() {
return this.__src;
}
connectedCallback() {
super.connectedCallback();
if (this.loading === "eager") {
this._handleCanLoadChange(true);
}
this._mediaRemoteControl.hidePoster();
}
disconnectedCallback() {
this._mediaRemoteControl.showPoster();
super.disconnectedCallback();
this.__src = void 0;
this._handleCanLoadChange(false);
}
render() {
return html`
<img
part="img"
src=${ifDefined(this.__canLoad ? this.src : null)}
alt=${ifDefined(this.alt)}
@load=${this._handleImgLoad}
@error=${this._handleImgError}
/>
`;
}
_setImgLoadingAttr() {
this.removeAttribute("img-error");
this.removeAttribute("img-loaded");
if (this.__canLoad && this.src) {
this.setAttribute("img-loading", "");
}
}
_handleImgLoad() {
this.removeAttribute("img-loading");
this.setAttribute("img-loaded", "");
}
_handleImgError() {
this.removeAttribute("img-loading");
this.setAttribute("img-error", "");
}
_handleCanLoadChange(canLoad) {
if (canLoad) {
this._setImgLoadingAttr();
} else {
this.removeAttribute("img-error");
this.removeAttribute("img-loaded");
this.removeAttribute("img-loading");
}
this.__canLoad = canLoad;
}
}
__decorateClass([
state()
], PosterElement.prototype, "__src", 2);
__decorateClass([
state()
], PosterElement.prototype, "__canLoad", 2);
__decorateClass([
property()
], PosterElement.prototype, "loading", 2);
__decorateClass([
property()
], PosterElement.prototype, "alt", 2);
export {
PosterElement
};