Files
housesof/apps/website/src/components/organisms/PostersGrid/PostersGrid.svelte

125 lines
3.5 KiB
Svelte

<style lang="scss">
@import "./PostersGrid";
</style>
<script lang="ts">
import { getContext } from 'svelte'
import EmblaCarousel, { type EmblaCarouselType } from 'embla-carousel'
// Components
import Poster from '$components/molecules/Poster/Poster.svelte'
import { debounce } from 'utils/actions'
let {
posters,
}: {
posters: any[]
} = $props()
let innerWidth = $state<number>()
let carouselEl = $state<HTMLElement>(undefined)
let carousel = $state<EmblaCarouselType>()
let currentSlide = $state(0)
let carouselDots = $state([])
const { shopProducts }: any = getContext('shop')
/** Navigate to specific slide */
const goToSlide = (index = 0) => {
carousel.scrollTo(index)
}
/** Init Carousel */
const initCarousel = () => {
if (innerWidth < 1200) {
if (!carousel) {
carousel = EmblaCarousel(carouselEl, {
slidesToScroll: innerWidth < 550 ? 1 : 2,
})
// On init
carousel.on('init', () => {
// Define amounts of dots
carouselDots = carousel.scrollSnapList()
})
// On slide change
carousel.on('select', () => {
// Define current slide
currentSlide = carousel.selectedScrollSnap()
})
// On resize
carousel.on('resize', () => {
// Redefine options
carousel.reInit({
slidesToScroll: innerWidth < 550 ? 1 : 2
})
// Define amounts of dots
carouselDots = carousel.scrollSnapList()
// Define current slide
currentSlide = carousel.selectedScrollSnap()
})
}
} else {
if (carousel) {
destroyCarousel()
}
}
}
/** Destroy carousel */
const destroyCarousel = () => {
carousel.destroy()
carousel = undefined
}
/** Destroy carousel for larger screens */
const handleResize = debounce(initCarousel, 200)
$effect(() => {
if (innerWidth < 1200) {
initCarousel()
}
// Destroy
return () => {
if (carousel) {
carousel.destroy()
}
}
})
</script>
<svelte:window
bind:innerWidth
onresize={handleResize}
/>
<section class="shop-page__posters grid">
<h3>View all of our available posters</h3>
{#if posters}
<div class="set" bind:this={carouselEl}>
<div class="set__content">
{#each posters as { location, photos_product }}
<Poster
location={location}
image={photos_product.length && photos_product[1].directus_files_id}
product={shopProducts.find(item => item.slug.includes(location.slug))}
/>
{/each}
</div>
{#if carousel}
<ul class="set__dots">
{#each carouselDots as _, index}
<li class:is-active={index === currentSlide}>
<button onclick={() => goToSlide(index)} aria-label="Go to slide #{index + 1}"></button>
</li>
{/each}
</ul>
{/if}
</div>
{/if}
</section>