diff --git a/src/components/shared/Carousel.jsx b/src/components/shared/Carousel.jsx index 7d6637c..1c2d231 100644 --- a/src/components/shared/Carousel.jsx +++ b/src/components/shared/Carousel.jsx @@ -1,4 +1,4 @@ -import React, { useRef, useCallback } from 'react'; +import React, { useRef, useCallback, useState } from 'react'; function Carousel({ children, @@ -8,24 +8,57 @@ function Carousel({ showLabels = true, className = '' }) { - const touchStart = useRef(null); + const touchStartX = useRef(null); + const touchStartY = useRef(null); + const trackRef = useRef(null); + const [dragOffset, setDragOffset] = useState(0); + const [isDragging, setIsDragging] = useState(false); const itemCount = React.Children.count(children); + + const SWIPE_THRESHOLD = 50; const handleTouchStart = useCallback((e) => { - touchStart.current = e.touches[0].clientX; + touchStartX.current = e.touches[0].clientX; + touchStartY.current = e.touches[0].clientY; + setIsDragging(true); }, []); + const handleTouchMove = useCallback((e) => { + if (!touchStartX.current || !isDragging) return; + + const currentX = e.touches[0].clientX; + const currentY = e.touches[0].clientY; + const diffX = currentX - touchStartX.current; + const diffY = Math.abs(currentY - touchStartY.current); + + // Only drag horizontally if not scrolling vertically + if (Math.abs(diffX) > diffY) { + // Add resistance at edges + let offset = diffX; + if ((activeIndex === 0 && diffX > 0) || (activeIndex === itemCount - 1 && diffX < 0)) { + offset = diffX * 0.25; + } + setDragOffset(offset); + } + }, [isDragging, activeIndex, itemCount]); + const handleTouchEnd = useCallback((e) => { - if (!touchStart.current) return; - const diff = touchStart.current - e.changedTouches[0].clientX; - if (Math.abs(diff) > 50) { + if (!touchStartX.current) return; + + const diff = touchStartX.current - e.changedTouches[0].clientX; + + if (Math.abs(diff) > SWIPE_THRESHOLD) { if (diff > 0 && activeIndex < itemCount - 1) { setActiveIndex(activeIndex + 1); } else if (diff < 0 && activeIndex > 0) { setActiveIndex(activeIndex - 1); } } - touchStart.current = null; + + touchStartX.current = null; + touchStartY.current = null; + setDragOffset(0); + setIsDragging(false); }, [activeIndex, setActiveIndex, itemCount]); const handleKeyDown = useCallback((e) => { @@ -36,18 +69,41 @@ function Carousel({ } }, [activeIndex, setActiveIndex, itemCount]); + // Calculate transform with drag offset + const baseTransform = -(activeIndex * 100); + const dragPercent = trackRef.current + ? (dragOffset / trackRef.current.offsetWidth) * 100 + : 0; + const transform = baseTransform + dragPercent; + return ( -