import { useKeenSlider } from 'keen-slider/react' import React, { Children, isValidElement, useState, useRef, useEffect, } from 'react' import cn from 'classnames' import { a } from '@react-spring/web' import s from './ProductSlider.module.css' import ProductSliderControl from '../ProductSliderControl' interface ProductSliderProps { children: React.ReactNode[] className?: string } const ProductSlider: React.FC = ({ children, className = '', }) => { const [currentSlide, setCurrentSlide] = useState(0) const [isMounted, setIsMounted] = useState(false) const sliderContainerRef = useRef(null) const thumbsContainerRef = useRef(null) const [ref, slider] = useKeenSlider({ loop: true, slides: { perView: 1 }, created: () => setIsMounted(true), slideChanged(s) { const slideNumber = s.track.details.rel setCurrentSlide(slideNumber) if (thumbsContainerRef.current) { const $el = document.getElementById(`thumb-${slideNumber}`) if (slideNumber >= 3) { thumbsContainerRef.current.scrollLeft = $el!.offsetLeft } else { thumbsContainerRef.current.scrollLeft = 0 } } }, }) // Stop the history navigation gesture on touch devices useEffect(() => { const preventNavigation = (event: TouchEvent) => { // Center point of the touch area const touchXPosition = event.touches[0].pageX // Size of the touch area const touchXRadius = event.touches[0].radiusX || 0 // We set a threshold (10px) on both sizes of the screen, // if the touch area overlaps with the screen edges // it's likely to trigger the navigation. We prevent the // touchstart event in that case. if ( touchXPosition - touchXRadius < 10 || touchXPosition + touchXRadius > window.innerWidth - 10 ) event.preventDefault() } const slider = sliderContainerRef.current! slider.addEventListener('touchstart', preventNavigation) return () => { if (slider) { slider.removeEventListener('touchstart', preventNavigation) } } }, []) const onPrev = React.useCallback(() => slider.current?.prev(), [slider]) const onNext = React.useCallback(() => slider.current?.next(), [slider]) return (
{slider && } {Children.map(children, (child) => { // Add the keen-slider__slide className to children if (isValidElement(child)) { return { ...child, props: { ...child.props, className: `${ child.props.className ? `${child.props.className} ` : '' }keen-slider__slide`, }, } } return child })}
{slider && Children.map(children, (child, idx) => { if (isValidElement(child)) { return { ...child, props: { ...child.props, className: cn(child.props.className, s.thumb, { [s.selected]: currentSlide === idx, }), id: `thumb-${idx}`, onClick: () => { slider.current?.moveToIdx(idx) }, }, } } return child })}
) } export default ProductSlider