@alegendstale/holly-components
Version:
Reusable UI components created using lit
139 lines (131 loc) • 4.26 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { css, html, LitElement } from 'lit';
import { query } from 'lit/decorators.js';
import { EventEmitter } from '../../utils/EventEmitter.js';
import { condCustomElement } from '../../decorators/condCustomElement.js';
let CarouselScroller = class CarouselScroller extends LitElement {
constructor() {
super();
this.slotChildren = [];
this.emitter = new EventEmitter();
this.currentSlide = 0;
this.debouncers = new WeakMap();
this.emitter.on('slotsLoaded', (slotChildren) => {
this.slotChildren = slotChildren;
});
}
disconnectedCallback() {
super.disconnectedCallback();
this.emitter.clear();
}
render() {
return html `
<div class="container">
<button =${this.scrollToPrevSlide}><</button>
<button =${this.scrollToNextSlide}>></button>
<div>
<slot =${this.slotChange}></slot>
</div>
</div>
`;
}
getCurrentSlide() {
return this.slotChildren[this.currentSlide - 1];
}
scrollToPrevSlide() {
this.currentSlide =
this.currentSlide === 0
? (this.currentSlide = this.slotChildren.length - 1)
: this.currentSlide - 1;
this.slotChildren
.at(this.currentSlide)
?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
scrollToNextSlide() {
this.currentSlide =
this.currentSlide === this.slotChildren.length - 1
? 0
: this.currentSlide + 1;
this.slotChildren
.at(this.currentSlide)
?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
slotChange() {
const slotElements = Array.from(this.slotEl
.assignedElements()
.map((element) => element));
clearTimeout(this.debouncers.get(this.slotEl));
const timeoutId = setTimeout(() => this.emitter.emit('slotsLoaded', slotElements), 100);
this.debouncers.set(this.slotEl, timeoutId);
}
};
CarouselScroller.styles = css `
:host {
--padding: 40px;
--margin: 80px;
}
.container {
width: 600px;
height: 400px;
margin: 20px;
border-radius: 20px;
overflow: hidden;
position: relative;
& > button {
position: absolute;
width: var(--padding);
height: calc(var(--padding) * 2);
z-index: 1;
background-color: #00000080;
border: none;
bottom: calc(50% - var(--padding));
font-size: 32px;
&:hover {
background-color: #6352b880;
}
&:nth-child(1) {
left: 0;
border-top-right-radius: 314px;
border-bottom-right-radius: 314px;
}
&:nth-child(2) {
right: 0;
border-top-left-radius: 314px;
border-bottom-left-radius: 314px;
}
}
& > div {
display: flex;
overflow-x: scroll;
position: relative;
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
scrollbar-width: none;
padding: 0 var(--padding);
}
::slotted(*) {
display: flex;
flex-direction: column;
justify-content: center;
min-height: calc(400px - var(--margin));
min-width: calc(600px - var(--margin));
max-height: calc(400px - var(--margin));
max-width: calc(600px - var(--margin));
background: white;
scroll-snap-align: center;
padding: calc(var(--margin) / 2);
}
}
`;
__decorate([
query('slot')
], CarouselScroller.prototype, "slotEl", void 0);
CarouselScroller = __decorate([
condCustomElement('carousel-scroller')
], CarouselScroller);
export { CarouselScroller };