webapp/src/components/_shared/Slider.tsx

138 lines
3.8 KiB
TypeScript
Raw Normal View History

2023-02-09 22:54:53 +00:00
import { Swiper, Navigation, Pagination, Lazy, Thumbs } from 'swiper'
2022-09-09 11:53:35 +00:00
import type { SwiperOptions } from 'swiper'
import 'swiper/scss'
import 'swiper/scss/navigation'
import 'swiper/scss/pagination'
2023-02-09 22:54:53 +00:00
import 'swiper/scss/lazy'
import 'swiper/scss/thumbs'
2022-09-09 11:53:35 +00:00
import './Slider.scss'
2023-02-09 22:54:53 +00:00
import { createEffect, createSignal, JSX, Show } from 'solid-js'
2022-11-27 17:02:04 +00:00
import { Icon } from './Icon'
2023-02-09 22:54:53 +00:00
import { clsx } from 'clsx'
2022-09-09 11:53:35 +00:00
interface SliderProps {
title?: string
slidesPerView?: number
isCardsWithCover?: boolean
2022-11-27 17:02:04 +00:00
children?: JSX.Element
2023-02-09 22:54:53 +00:00
class?: string
isPageGallery?: boolean
hasThumbs?: boolean
2022-09-09 11:53:35 +00:00
}
export default (props: SliderProps) => {
let el: HTMLDivElement | undefined
2023-02-09 22:54:53 +00:00
let thumbsEl: HTMLDivElement | undefined
2022-09-09 11:53:35 +00:00
let pagEl: HTMLDivElement | undefined
let nextEl: HTMLDivElement | undefined
let prevEl: HTMLDivElement | undefined
const isCardsWithCover = typeof props.isCardsWithCover === 'boolean' ? props.isCardsWithCover : true
2023-02-09 22:54:53 +00:00
const [swiper, setSwiper] = createSignal<Swiper>()
const [swiperThumbs, setSwiperThumbs] = createSignal<Swiper>()
2022-09-09 11:53:35 +00:00
const opts: SwiperOptions = {
2023-02-09 22:54:53 +00:00
lazy: true,
2022-11-04 14:25:55 +00:00
roundLengths: true,
2022-09-09 11:53:35 +00:00
loop: true,
centeredSlides: true,
slidesPerView: 1,
2023-02-09 22:54:53 +00:00
modules: [Navigation, Pagination, Lazy, Thumbs],
2022-09-09 11:53:35 +00:00
speed: 500,
navigation: { nextEl, prevEl },
breakpoints: {
768: {
slidesPerView: props.slidesPerView > 0 ? props.slidesPerView : 1.66666,
spaceBetween: isCardsWithCover ? 8 : 26
},
992: {
slidesPerView: props.slidesPerView > 0 ? props.slidesPerView : 1.66666,
spaceBetween: isCardsWithCover ? 8 : 52
2022-09-09 11:53:35 +00:00
}
2023-02-09 22:54:53 +00:00
},
thumbs: {
swiper: swiperThumbs()
2022-09-09 11:53:35 +00:00
}
}
2023-02-09 22:54:53 +00:00
createEffect(() => {
if (props.hasThumbs && !!thumbsEl) {
setTimeout(() => {
setSwiperThumbs(
new Swiper(thumbsEl, {
slidesPerView: 'auto',
modules: [Lazy, Thumbs],
lazy: true,
roundLengths: true,
spaceBetween: 20,
freeMode: true,
breakpoints: {
768: {
direction: 'vertical'
}
}
})
)
}, 500)
}
})
2022-09-09 11:53:35 +00:00
createEffect(() => {
if (!swiper() && !!el) {
setTimeout(() => {
2023-02-09 22:54:53 +00:00
if (swiperThumbs()) {
opts.thumbs = {
swiper: swiperThumbs()
}
opts.pagination = {
el: '.swiper-pagination',
type: 'fraction'
}
}
2022-09-09 11:53:35 +00:00
setSwiper(new Swiper(el, opts))
}, 500)
}
})
2022-09-09 11:53:35 +00:00
return (
<div class="floor floor--important">
2022-11-20 21:23:12 +00:00
<div class="wide-container">
<div class="row">
<h2 class="col-12">{props.title}</h2>
2023-02-09 22:54:53 +00:00
<div class="sliders-container">
<div
class={clsx('swiper', props.class)}
classList={{
'cards-with-cover': isCardsWithCover,
'swiper--page-gallery': props.isPageGallery
}}
ref={el}
>
<div class="swiper-wrapper">{props.children}</div>
<div class="slider-arrow-next" ref={nextEl} onClick={() => swiper()?.slideNext()}>
<Icon name="slider-arrow" class={'icon'} />
</div>
<div class="slider-arrow-prev" ref={prevEl} onClick={() => swiper()?.slidePrev()}>
<Icon name="slider-arrow" class={'icon'} />
</div>
<div class="swiper-pagination" ref={pagEl} />
2022-11-27 17:30:59 +00:00
</div>
2023-02-09 22:54:53 +00:00
<Show when={props.hasThumbs}>
<div class="thumbs-container">
<div class="swiper swiper--thumbs" ref={thumbsEl}>
<div class="swiper-wrapper">{props.children}</div>
</div>
</div>
</Show>
2022-11-27 17:30:59 +00:00
</div>
2022-11-20 21:23:12 +00:00
</div>
2022-09-09 11:53:35 +00:00
</div>
</div>
)
}