From 9cfa9e380da2a91cbc923ce7cd926af9dfe1dbb9 Mon Sep 17 00:00:00 2001 From: Saugat Malla Date: Tue, 5 May 2026 19:04:20 -0400 Subject: [PATCH 1/3] 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 953cb7b..2e9fc14 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 e47c051b0ebb1bfd15f2f400d9badbc65aa6e763 Mon Sep 17 00:00:00 2001 From: Saugat Malla Date: Thu, 7 May 2026 19:54:13 -0400 Subject: [PATCH 2/3] 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 (