@progressive-development/pd-content
Version:
Progressive Development content components.
207 lines (196 loc) • 5.39 kB
JavaScript
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 };