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(() => {
|
const startAuto = useCallback(() => {
|
||||||
if (autoRef.current) clearInterval(autoRef.current);
|
if (autoRef.current) clearInterval(autoRef.current);
|
||||||
autoRef.current = setInterval(() => {
|
autoRef.current = setInterval(() => {
|
||||||
setTrackIndex(prev => prev + 1);
|
setTrackIndex(prev => {
|
||||||
|
if (prev <= 0 || prev >= total + 1) return prev;
|
||||||
|
return prev + 1;
|
||||||
|
});
|
||||||
setIsTransitioning(true);
|
setIsTransitioning(true);
|
||||||
}, AUTO_INTERVAL);
|
}, AUTO_INTERVAL);
|
||||||
}, []);
|
}, [total]);
|
||||||
|
|
||||||
const stopAuto = useCallback(() => {
|
const stopAuto = useCallback(() => {
|
||||||
if (autoRef.current) {
|
if (autoRef.current) {
|
||||||
@ -65,7 +68,12 @@ export function useInfiniteCarousel<T>({ items }: { items: T[] }) {
|
|||||||
return stopAuto;
|
return stopAuto;
|
||||||
}, [startAuto, stopAuto]);
|
}, [startAuto, stopAuto]);
|
||||||
|
|
||||||
const handleTransitionEnd = useCallback(() => {
|
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) {
|
if (trackIndex >= total + 1) {
|
||||||
setIsTransitioning(false);
|
setIsTransitioning(false);
|
||||||
setTrackIndex(1);
|
setTrackIndex(1);
|
||||||
@ -73,7 +81,9 @@ export function useInfiniteCarousel<T>({ items }: { items: T[] }) {
|
|||||||
setIsTransitioning(false);
|
setIsTransitioning(false);
|
||||||
setTrackIndex(total);
|
setTrackIndex(total);
|
||||||
}
|
}
|
||||||
}, [trackIndex, total]);
|
},
|
||||||
|
[trackIndex, total]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isTransitioning) return;
|
if (isTransitioning) return;
|
||||||
@ -83,11 +93,15 @@ export function useInfiniteCarousel<T>({ items }: { items: T[] }) {
|
|||||||
|
|
||||||
const navigate = useCallback(
|
const navigate = useCallback(
|
||||||
(updater: number | ((prev: number) => number)) => {
|
(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);
|
setIsTransitioning(true);
|
||||||
startAuto();
|
startAuto();
|
||||||
},
|
},
|
||||||
[startAuto]
|
[startAuto, total]
|
||||||
);
|
);
|
||||||
|
|
||||||
const goTo = useCallback((i: number) => navigate(i + 1), [navigate]);
|
const goTo = useCallback((i: number) => navigate(i + 1), [navigate]);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user