import { useWindowWidth } from '../../hooks/useWindowWidth'; import { motion } from 'framer-motion'; import { ReactNode, useEffect, useReducer, useRef, useState } from 'react'; import { useSwipeable } from 'react-swipeable'; import { SliderControls } from './SliderControls'; export function SliderWithScaling({ slides, SlideElement, className = '', childClassName = '', alignItems = 'start', slideSizes: [minWidth, minHeight, minWidthScaled, minHeightScaled], controlsPosition, }: { slides: T[]; SlideElement: (_: T) => ReactNode; className?: string; childClassName?: string; alignItems?: 'start' | 'center' | 'end'; slideSizes: [string, string, string, string]; controlsPosition: 'top' | 'bottom'; }) { const width = useWindowWidth(); const baseoffset = width >= 1024 ? (-width / 1600) * 507 + 8 : (-width * +minWidth.slice(0, -2)) / 100 + 8; const [slide, setSlide] = useState(0); const [sliderOffset, setSliderOffset] = useState(baseoffset); const [transiting, setTransiting] = useState(false); const [currentSliding, setCurrentSliding] = useState< 'prev' | 'next' | null >(); const sliderRef = useRef(null); const itemRef = useRef(null); const [order, dispatch] = useReducer( (state: typeof slides, action: 'prev' | 'next') => { setTransiting(true); switch (action) { case 'prev': setSlide(slide => (slide === 0 ? slides.length - 1 : slide - 1)); setSliderOffset(2 * baseoffset); return [state[state.length - 3], ...state.slice(0, -1)]; case 'next': setSlide(slide => (slide === slides.length - 1 ? 0 : slide + 1)); setSliderOffset(0); return [...state.slice(1), state[2]]; default: return state; } }, [slides[slides.length - 1], ...slides, slides[0]], ); useEffect(() => { const sliderRefCurrent = sliderRef.current; sliderRefCurrent?.addEventListener('transitionend', () => { setTransiting(false); setCurrentSliding(null); }); return () => { sliderRefCurrent?.removeEventListener('transitionend', () => { setTransiting(false); setCurrentSliding(null); }); }; }, []); function nextSlide() { // if (!transiting) { // } setCurrentSliding('next'); dispatch('next'); } function prevSlide() { // if (!transiting) { // } setCurrentSliding('prev'); dispatch('prev'); } useEffect(() => { setSliderOffset(baseoffset); }, [baseoffset, order, slide]); const handlers = useSwipeable({ onSwipedLeft: nextSlide, onSwipedRight: prevSlide, trackMouse: true, preventScrollOnSwipe: true, touchEventOptions: { passive: false }, }); return (
{order.map((slide, index) => ( slides.length ? '456' : '') } initial={ currentSliding === 'next' && index === 0 ? { minWidth: minWidthScaled, minHeight: minHeightScaled } : index === 3 ? { minWidth, minHeight } : {} } transition={{ duration: 1, type: 'just' }} animate={ index === 1 ? { minWidth: minWidthScaled, minHeight: minHeightScaled, } : { minWidth, minHeight, transition: { duration: index === 3 ? 0.0001 : 1 }, } } className={'pointer-events-none ' + childClassName} > ))}
= 640 ? 132 : ((width - 32) / 328) * 196} height={width >= 640 ? 66 : 58} className={ 'absolute ' + (controlsPosition === 'top' ? 'top-[75px]' : 'bottom-0 sm:self-end self-center') } />
); }