fix: carousel image lightbox

This commit is contained in:
gosangam
2026-08-09 11:11:35 +05:30
parent df49e7afcc
commit baf36d3d67
4 changed files with 220 additions and 130 deletions
+51
View File
@@ -0,0 +1,51 @@
"use client";
/**
* useTapGuard — tells a genuine tap apart from a swipe on a natively-scrolling
* strip (CSS scroll-snap carousels).
*
* Browsers still fire a `click` after some swipe gestures, so a plain onClick
* on a slide would trigger mid-swipe. Snapshot the pointer position AND the
* scroller's offset on pointerdown, then check both when the click arrives:
*
* • pointer travel — catches a drag that didn't scroll (e.g. hit the end)
* • scroll movement — catches an inertial swipe, where the pointer barely
* moves before `click` fires but the strip is already gliding
*
* Either signal alone misses cases, hence both. No staleness risk: a click is
* always immediately preceded by a pointerdown on the same element.
*/
import { useRef, type RefObject } from "react";
/** Pointer travel (px) still considered a tap rather than a drag. */
const MOVE_TOLERANCE = 8;
/** Scroll movement (px) still considered "didn't scroll". */
const SCROLL_TOLERANCE = 4;
type PointerLike = { clientX: number; clientY: number };
export function useTapGuard(scrollerRef: RefObject<HTMLElement | null>) {
const start = useRef({ x: 0, y: 0, scrollLeft: 0 });
function onPointerDown(e: PointerLike) {
start.current = {
x: e.clientX,
y: e.clientY,
scrollLeft: scrollerRef.current?.scrollLeft ?? 0,
};
}
function wasTap(e: PointerLike) {
const moved =
Math.abs(e.clientX - start.current.x) > MOVE_TOLERANCE ||
Math.abs(e.clientY - start.current.y) > MOVE_TOLERANCE;
const scrolled =
Math.abs(
(scrollerRef.current?.scrollLeft ?? 0) - start.current.scrollLeft,
) > SCROLL_TOLERANCE;
return !moved && !scrolled;
}
return { onPointerDown, wasTap };
}