AbiirSkincare/Hydrogen/web/app/lib/useSwipeNavigate.ts

52 lines
1.5 KiB
TypeScript

import {useCallback, useRef} from 'react';
import type {TouchEvent} from 'react';
export type UseSwipeNavigateOptions = {
/** Minimum horizontal movement (px) to count as a swipe */
threshold?: number;
/** Ignore swipe if vertical movement exceeds this (px) — avoids fighting page scroll */
maxVerticalDelta?: number;
};
/**
* Touch swipe on a carousel: finger left → next, finger right → previous.
*/
export function useSwipeNavigate(
onPrev: () => void,
onNext: () => void,
options: UseSwipeNavigateOptions = {},
) {
const {threshold = 44, maxVerticalDelta = 100} = options;
const startX = useRef<number | null>(null);
const startY = useRef<number | null>(null);
const onTouchStart = useCallback((e: TouchEvent) => {
if (e.touches.length !== 1) return;
startX.current = e.touches[0].clientX;
startY.current = e.touches[0].clientY;
}, []);
const onTouchEnd = useCallback(
(e: TouchEvent) => {
const x0 = startX.current;
const y0 = startY.current;
startX.current = null;
startY.current = null;
if (x0 == null || y0 == null) return;
const t = e.changedTouches[0];
if (!t) return;
const dx = t.clientX - x0;
const dy = Math.abs(t.clientY - y0);
if (dy > maxVerticalDelta) return;
if (dx > threshold) {
onPrev();
} else if (dx < -threshold) {
onNext();
}
},
[maxVerticalDelta, onNext, onPrev, threshold],
);
return {onTouchStart, onTouchEnd};
}