UNPKG

@progressive-development/pd-content

Version:

Progressive Development content components.

207 lines (196 loc) 5.39 kB
import { LitElement, css, html } from 'lit'; import { property } from 'lit/decorators.js'; import { classMap } from 'lit/directives/class-map.js'; import Hammer from 'hammerjs'; import '@progressive-development/pd-icon/pd-icon'; var __defProp = Object.defineProperty; var __decorateClass = (decorators, target, key, kind) => { var result = void 0 ; for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (decorator(target, key, result) ) || result; if (result) __defProp(target, key, result); return result; }; let timer; class PdPanelViewer extends LitElement { constructor() { super(...arguments); this.withProgress = false; this.deltaCalc = 3; this._index = 0; // eslint-disable-next-line no-undef this._panData = {}; this._update = {}; } static { this.styles = css` :host { display: flex; flex-direction: column; width: 100%; max-width: var(--pd-panel-width, 1170px); overflow: var(--pd-panel-overflow, hidden); background-color: var(--pd-panel-viewer-bg-col); } .panel-container { position: relative; height: var(--pd-panel-height, 60vh); width: 100%; display: flex; flex-direction: column; padding: 0 2rem; box-sizing: border-box; } pd-icon { position: absolute; top: calc(50% - 25px); height: 50px; cursor: pointer; } #prev { left: 0; } #next { right: 0; } #progress { position: relative; height: 20px; width: 50%; margin: 0.5rem auto; display: grid; grid-auto-flow: column; grid-auto-columns: 1fr; grid-gap: 10px; align-content: center; align-self: flex-end; } #progress > div { background: var(--pd-panel-progress-col, grey); height: 4px; transition: background 0.3s linear; cursor: pointer; } #progress > div.watched { background: var(--pd-panel-progress-col, yellow); } ::slotted(*) { position: absolute; width: 100%; height: calc(100%); transition: transform 0.35s ease-out; left: 0; } `; } get index() { return this._index; } set index(value) { this.children[this._index].dispatchEvent(new CustomEvent("exited")); this.children[value].dispatchEvent(new CustomEvent("entered")); this._index = value; } render() { return html` <div class="panel-container"> <slot></slot> <pd-icon id="prev" icon="previousArrow" activeIcon ?disabled="${this.index <= 0}" @click=${this.previous} ></pd-icon> <pd-icon id="next" icon="nextArrow" activeIcon ?disabled="${this.index === this.children.length - 1}" @click=${this.next} ></pd-icon> </div> ${this.withProgress ? html` <div id="progress"> ${Array.from(this.children).map( (childEl, i) => html` <div @click="${() => { this._index = i; }}" class=${classMap({ watched: i <= this.index })} ></div>` )} </div>` : ""} `; } firstUpdated() { const hammerVal = new Hammer(this); hammerVal.on("pan", (panEvent) => { this._panData = panEvent; }); const ro = new ResizeObserver((entries) => { entries.forEach(() => { window.clearTimeout(timer); timer = setTimeout(() => { this.requestUpdate(); }, 100); }); }); ro.observe(this); } update(changedProperties) { const { isFinal = false } = this._panData; let { deltaX = 0 } = this._panData; const width = this.clientWidth; const minScale = 0.8; if (!changedProperties.has("_index") && isFinal) { if (deltaX > width / this.deltaCalc) { this.previous(); } else if (deltaX < -width / this.deltaCalc) { this.next(); } } deltaX = isFinal ? 0 : deltaX; Array.from(this.children).forEach((el, i) => { const x = (i - this.index) * width + deltaX; const u = deltaX / width + (i - this.index); const v = -Math.abs(u * (1 - minScale)) + 1; const scale = Math.max(v, minScale); el.style.transform = `translate3d(${x}px,0,0) scale(${scale})`; el.style.opacity = scale; }); super.update(changedProperties); } /* Advance to the next story card if possible */ next() { this.index = Math.max( 0, Math.min(this.children.length - 1, this.index + 1) ); this._update = false; } /* Go back to the previous story card if possible */ previous() { this.index = Math.max( 0, Math.min(this.children.length - 1, this.index - 1) ); this._update = false; } } __decorateClass([ property({ type: Boolean }) ], PdPanelViewer.prototype, "withProgress"); __decorateClass([ property({ type: Number }) ], PdPanelViewer.prototype, "deltaCalc"); __decorateClass([ property({ type: Number, state: true }) ], PdPanelViewer.prototype, "_index"); __decorateClass([ property({ type: Object, state: true }) ], PdPanelViewer.prototype, "_panData"); __decorateClass([ property({ type: Boolean, state: true }) ], PdPanelViewer.prototype, "_update"); export { PdPanelViewer };