Files
85f842fd-67b5-449f-a3d6-408…/src/components/sections/hero/heroCarouselLogo/useCarouselFullscreen.ts
2025-12-26 17:23:44 +02:00

104 lines
2.9 KiB
TypeScript

import { useEffect, useRef, useState, useCallback } from "react";
interface UseCarouselFullscreenProps {
totalSlides: number;
autoplayDelay?: number;
}
interface UseCarouselFullscreenReturn {
currentSlide: number;
progressRefs: React.MutableRefObject<(HTMLDivElement | null)[]>;
goToSlide: (index: number) => void;
}
export const useCarouselFullscreen = ({
totalSlides,
autoplayDelay = 3000,
}: UseCarouselFullscreenProps): UseCarouselFullscreenReturn => {
const [currentSlide, setCurrentSlide] = useState(0);
const progressRefs = useRef<(HTMLDivElement | null)[]>([]);
const animationFrameRef = useRef<number | null>(null);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const previousSlideRef = useRef<number>(0);
const resetProgressBars = useCallback(
(fromIndex: number, isLooping: boolean = false) => {
if (animationFrameRef.current) {
cancelAnimationFrame(animationFrameRef.current);
}
progressRefs.current.forEach((bar, index) => {
if (bar) {
if (isLooping || index >= fromIndex) {
bar.style.transform = "translateX(-100%)";
} else {
bar.style.transform = "translateX(0%)";
}
}
});
},
[]
);
const animateProgress = useCallback(
(index: number, prevIndex: number) => {
const isLooping = prevIndex === totalSlides - 1 && index === 0;
resetProgressBars(index, isLooping);
if (!progressRefs.current[index]) return;
let startTime: number | null = null;
const animate = (timestamp: number) => {
if (!startTime) startTime = timestamp;
const elapsed = timestamp - startTime;
const progress = Math.min(elapsed / autoplayDelay, 1);
const translateValue = -100 + progress * 100;
if (progressRefs.current[index]) {
progressRefs.current[index]!.style.transform = `translateX(${translateValue}%)`;
}
if (progress < 1) {
animationFrameRef.current = requestAnimationFrame(animate);
}
};
animationFrameRef.current = requestAnimationFrame(animate);
},
[autoplayDelay, resetProgressBars, totalSlides]
);
const goToSlide = useCallback((index: number) => {
setCurrentSlide(index);
}, []);
useEffect(() => {
animateProgress(currentSlide, previousSlideRef.current);
previousSlideRef.current = currentSlide;
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
intervalRef.current = setInterval(() => {
setCurrentSlide((prev) => (prev + 1) % totalSlides);
}, autoplayDelay);
return () => {
if (intervalRef.current) {
clearInterval(intervalRef.current);
}
if (animationFrameRef.current) {
cancelAnimationFrame(animationFrameRef.current);
}
};
}, [currentSlide, totalSlides, autoplayDelay, animateProgress]);
return {
currentSlide,
progressRefs,
goToSlide,
};
};