From 4115cbc01ac26af04d56ff979ca73b46fad596f5 Mon Sep 17 00:00:00 2001 From: Saugat Malla Date: Tue, 5 May 2026 19:04:20 -0400 Subject: [PATCH 1/4] fix: add pointer cancel event to handle cancelled pointer on touch devices --- package.json | 2 +- src/lib/components/gallery-main.jsx | 24 ++++++++++++++---------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/package.json b/package.json index 1d67cd2..76ab03f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@wethegit/react-gallery", - "version": "4.0.2", + "version": "4.0.1", "description": "A customizable, accessible gallery component for React projects.", "files": [ "dist" diff --git a/src/lib/components/gallery-main.jsx b/src/lib/components/gallery-main.jsx index d0fa8b6..c50dc3e 100644 --- a/src/lib/components/gallery-main.jsx +++ b/src/lib/components/gallery-main.jsx @@ -19,6 +19,17 @@ export const GalleryMain = ({ renderGalleryItem, className, ...props }) => { swipeThreshold, } = useGallery() + const handlePointerCancel = useCallback(() => { + setTouchState((prevState) => ({ + ...prevState, + isDragging: false, + xOffset: 0, + start: 0, + offsetting: false, + scrolling: false, + })) + }, [setTouchState]) + const handlePointerDown = useCallback(() => { if (!draggable) return @@ -99,24 +110,16 @@ export const GalleryMain = ({ renderGalleryItem, className, ...props }) => { else previous() } - // reset all the touchState values. - setTouchState((prevState) => ({ - ...prevState, - isDragging: false, - xOffset: 0, - start: 0, - offsetting: false, - scrolling: false, - })) + handlePointerCancel() } }, [ draggable, touchState.isDragging, touchState.xOffset, swipeThreshold, - setTouchState, next, previous, + handlePointerCancel, ]) return ( @@ -125,6 +128,7 @@ export const GalleryMain = ({ renderGalleryItem, className, ...props }) => { onPointerDown={draggable ? handlePointerDown : null} onPointerMove={draggable ? handlePointerMove : null} onPointerUp={draggable ? handlePointerUp : null} + onPointerCancel={draggable ? handlePointerCancel : null} style={{ "--selected": activeIndex, "--total": galleryItems.length }} {...props} > From c8998a90606b1fc63b1e301ca70f42ae572f0f65 Mon Sep 17 00:00:00 2001 From: Saugat Malla Date: Thu, 7 May 2026 19:54:13 -0400 Subject: [PATCH 2/4] fix: add setPointerCapture to allow pointer to observe outside of the gallery --- src/lib/components/gallery-main.jsx | 63 ++++++++++++++++++----------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/src/lib/components/gallery-main.jsx b/src/lib/components/gallery-main.jsx index c50dc3e..4cc2f16 100644 --- a/src/lib/components/gallery-main.jsx +++ b/src/lib/components/gallery-main.jsx @@ -19,7 +19,7 @@ export const GalleryMain = ({ renderGalleryItem, className, ...props }) => { swipeThreshold, } = useGallery() - const handlePointerCancel = useCallback(() => { + const resetTouchState = useCallback(() => { setTouchState((prevState) => ({ ...prevState, isDragging: false, @@ -30,11 +30,14 @@ export const GalleryMain = ({ renderGalleryItem, className, ...props }) => { })) }, [setTouchState]) - const handlePointerDown = useCallback(() => { - if (!draggable) return - - setTouchState((prevState) => ({ ...prevState, isDragging: true })) - }, [draggable, setTouchState]) + const handlePointerDown = useCallback( + (event) => { + if (!draggable) return + event.currentTarget.setPointerCapture?.(event.pointerId) + setTouchState((prevState) => ({ ...prevState, isDragging: true })) + }, + [draggable, setTouchState] + ) const handlePointerMove = useCallback( (event) => { @@ -96,31 +99,43 @@ export const GalleryMain = ({ renderGalleryItem, className, ...props }) => { ] ) - const handlePointerUp = useCallback(() => { - if (!draggable) return + const handlePointerUp = useCallback( + (event) => { + if (!draggable) return - if (touchState.isDragging) { - /* + event.currentTarget.releasePointerCapture?.(event.pointerId) + if (touchState.isDragging) { + /* check if the offset value is more than the swipeThreshold. if it is then we'll move to the next or prev item in the gallery, otherwise it'll just spring back to the current position. */ - if (Math.abs(touchState.xOffset) > swipeThreshold) { - if (touchState.xOffset < 0) next() - else previous() + if (Math.abs(touchState.xOffset) > swipeThreshold) { + if (touchState.xOffset < 0) next() + else previous() + } + + resetTouchState() } + }, + [ + draggable, + touchState.isDragging, + touchState.xOffset, + swipeThreshold, + next, + previous, + resetTouchState, + ] + ) - handlePointerCancel() - } - }, [ - draggable, - touchState.isDragging, - touchState.xOffset, - swipeThreshold, - next, - previous, - handlePointerCancel, - ]) + const handlePointerCancel = useCallback( + (event) => { + event.currentTarget.releasePointerCapture?.(event.pointerId) + resetTouchState() + }, + [resetTouchState] + ) return (