fix: improve infinite carousel navigation and transition handling
- Updated the track index logic to prevent navigation while at clone positions, ensuring smoother transitions. - Enhanced the handleTransitionEnd function to only respond to the track's own transform transitions, improving event handling accuracy. - Adjusted dependencies in useCallback hooks for better performance and reliability.
This commit is contained in:
parent
a0f97cdec4
commit
d5294dc580
@ -48,10 +48,13 @@ export function useInfiniteCarousel<T>({ items }: { items: T[] }) {
|
||||
const startAuto = useCallback(() => {
|
||||
if (autoRef.current) clearInterval(autoRef.current);
|
||||
autoRef.current = setInterval(() => {
|
||||
setTrackIndex(prev => prev + 1);
|
||||
setTrackIndex(prev => {
|
||||
if (prev <= 0 || prev >= total + 1) return prev;
|
||||
return prev + 1;
|
||||
});
|
||||
setIsTransitioning(true);
|
||||
}, AUTO_INTERVAL);
|
||||
}, []);
|
||||
}, [total]);
|
||||
|
||||
const stopAuto = useCallback(() => {
|
||||
if (autoRef.current) {
|
||||
@ -65,15 +68,22 @@ export function useInfiniteCarousel<T>({ items }: { items: T[] }) {
|
||||
return stopAuto;
|
||||
}, [startAuto, stopAuto]);
|
||||
|
||||
const handleTransitionEnd = useCallback(() => {
|
||||
if (trackIndex >= total + 1) {
|
||||
setIsTransitioning(false);
|
||||
setTrackIndex(1);
|
||||
} else if (trackIndex <= 0) {
|
||||
setIsTransitioning(false);
|
||||
setTrackIndex(total);
|
||||
}
|
||||
}, [trackIndex, total]);
|
||||
const handleTransitionEnd = useCallback(
|
||||
(e: React.TransitionEvent) => {
|
||||
// Only respond to the track's own transform transition,
|
||||
// not bubbled events from child slide transitions (scale/opacity/filter)
|
||||
if (e.target !== e.currentTarget || e.propertyName !== "transform") return;
|
||||
|
||||
if (trackIndex >= total + 1) {
|
||||
setIsTransitioning(false);
|
||||
setTrackIndex(1);
|
||||
} else if (trackIndex <= 0) {
|
||||
setIsTransitioning(false);
|
||||
setTrackIndex(total);
|
||||
}
|
||||
},
|
||||
[trackIndex, total]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
if (isTransitioning) return;
|
||||
@ -83,11 +93,15 @@ export function useInfiniteCarousel<T>({ items }: { items: T[] }) {
|
||||
|
||||
const navigate = useCallback(
|
||||
(updater: number | ((prev: number) => number)) => {
|
||||
setTrackIndex(updater);
|
||||
setTrackIndex(prev => {
|
||||
// Block navigation while at a clone position (snap-back pending)
|
||||
if (prev <= 0 || prev >= total + 1) return prev;
|
||||
return typeof updater === "function" ? updater(prev) : updater;
|
||||
});
|
||||
setIsTransitioning(true);
|
||||
startAuto();
|
||||
},
|
||||
[startAuto]
|
||||
[startAuto, total]
|
||||
);
|
||||
|
||||
const goTo = useCallback((i: number) => navigate(i + 1), [navigate]);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user