evcc-io/assets/js/utils/swipe.ts

49 lines
1.5 KiB
TypeScript

interface SwipeOptions {
onSwipeLeft?: () => void;
onSwipeRight?: () => void;
ignoreSelector?: string;
minDistance?: number;
maxDuration?: number;
}
export function attachSwipeHandler(el: HTMLElement, options: SwipeOptions): () => void {
const minDistance = options.minDistance ?? 60;
const maxDuration = options.maxDuration ?? 600;
let startX = 0;
let startY = 0;
let startTime = 0;
let ignored = false;
const onTouchStart = (e: TouchEvent) => {
if (e.touches.length !== 1) {
ignored = true;
return;
}
const target = e.target as Element | null;
ignored = !!(options.ignoreSelector && target?.closest(options.ignoreSelector));
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
startTime = Date.now();
};
const onTouchEnd = (e: TouchEvent) => {
if (ignored) return;
const touch = e.changedTouches[0];
if (!touch) return;
const dx = touch.clientX - startX;
const dy = touch.clientY - startY;
if (Date.now() - startTime > maxDuration) return;
if (Math.abs(dx) < minDistance) return;
if (Math.abs(dy) >= Math.abs(dx)) return;
if (dx < 0) options.onSwipeLeft?.();
else options.onSwipeRight?.();
};
el.addEventListener("touchstart", onTouchStart, { passive: true });
el.addEventListener("touchend", onTouchEnd, { passive: true });
return () => {
el.removeEventListener("touchstart", onTouchStart);
el.removeEventListener("touchend", onTouchEnd);
};
}