Files
caperren-com/src/components/CustomCarousel.astro

174 lines
6.4 KiB
Plaintext

---
import {Image} from 'astro:assets';
import type {carouselGroup} from "@interfaces/image-carousel.ts";
const groupToShow: carouselGroup = Astro.props.carouselGroup;
---
<custom-carousel class="flex flex-col relative w-full"
data-custom-carousel={groupToShow.animation}
data-custom-carousel-interval={groupToShow.interval}>
<!-- Carousel wrapper -->
<div class="relative overflow-hidden h-56 md:h-156">
{
groupToShow.images.map((image, index) => (
<div class="hidden duration-700 ease-in-out" data-custom-carousel-item>
<Image src={image}
class="relative sm:max-w-xl md:max-w-3xl lg:max-w-5xl xl:max-w-7xl -translate-x-1/2 -translate-y-1/2 top-1/2 left-1/2"
alt="..."
loading="eager"/>
</div>
))
}
</div>
{(groupToShow.images.length > 1) && (
<!-- Slider indicators -->
<div class="absolute z-30 flex -translate-x-1/2 bottom-8 md:bottom-2 left-1/2 space-x-3 rounded-full">
{
groupToShow.images.map((_, index) => (
<button type="button"
class="w-3 h-3 rounded-full bg-black hover:bg-caperren-green-light"
aria-current={index ? "false" : "true"}
aria-label={index.toString()}
data-custom-carousel-slide-to={index}></button>
))
}
</div>
<!-- Slider controls -->
<button
type="button"
class="absolute top-0 start-0 z-30 flex items-center justify-center h-full px-4 cursor-pointer group focus:outline-none"
data-custom-carousel-prev
>
<span class="inline-flex items-center justify-center w-10 h-10 rounded-full ring-2 ring-caperren-green/25 bg-black/25 group-hover:bg-black/75">
<svg
class="h-4 w-4 text-caperren-green group-hover:text-caperren-green-light"
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 6 10"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M5 1 1 5l4 4"
/>
</svg>
<span class="hidden">Previous</span>
</span>
</button>
<button
type="button"
class="absolute top-0 end-0 z-30 flex items-center justify-center h-full px-4 cursor-pointer group focus:outline-none"
data-custom-carousel-next
>
<span class="inline-flex items-center justify-center w-10 h-10 rounded-full ring-2 ring-caperren-green/25 bg-black/25 group-hover:bg-black/75">
<svg
class="h-4 w-4 text-caperren-green group-hover:text-caperren-green-light "
aria-hidden="true"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 6 10"
>
<path
stroke="currentColor"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="m1 9 4-4-4-4"
/>
</svg>
<span class="hidden">Next</span>
</span>
</button>
)}
</custom-carousel>
<script>
import {Carousel, type CarouselItem, type CarouselOptions, type IndicatorItem} from 'flowbite';
class CustomCarousel extends HTMLElement {
_slide: boolean;
_items: CarouselItem[];
_options: CarouselOptions;
_carousel: Carousel;
constructor() {
super();
this._slide = this.getAttribute('data-custom-carousel') === 'slide';
this._items = this._getItems();
this._options = this._getOptions();
this._carousel = new Carousel(this, this._items, this._options);
if (this._slide) this._carousel.cycle();
this._attachHandlers()
}
_getItems = (): CarouselItem[] => {
let customItems = this.querySelectorAll('[data-custom-carousel-item]') || [];
return Array.from(customItems).map(
(item, index): CarouselItem => {
return {el: item as HTMLElement, position: index}
}
)
}
_getOptions = (): CarouselOptions => {
let customIndicators = this.querySelectorAll('[data-custom-carousel-slide-to]') || [];
return {
defaultPosition: 1,
interval: this.dataset.customCarouselInterval ? Number(this.dataset.customCarouselInterval) : 8000,
indicators: {
activeClasses: 'border-2 border-caperren-green bg-black',
inactiveClasses: 'bg-caperren-green/40 hover:bg-caperren-green-light',
items: Array.from(customIndicators).map(
(item, index): IndicatorItem => {
return {
el: item as HTMLElement,
position: Number(item.getAttribute('data-custom-carousel-slide-to'))
}
}
)
}
}
}
_attachHandlers = (): void => {
// Controls
const carouselNextEl = this.querySelector(
'[data-custom-carousel-next]'
);
const carouselPrevEl = this.querySelector(
'[data-custom-carousel-prev]'
);
if (carouselNextEl) {
carouselNextEl.addEventListener('click', () => {
this._carousel.next();
});
}
if (carouselPrevEl) {
carouselPrevEl.addEventListener('click', () => {
this._carousel.prev();
});
}
}
}
customElements.define('custom-carousel', CustomCarousel)
</script>