FormidableLabs / react-swipeable

React swipe event handler hook
https://commerce.nearform.com/open-source/react-swipeable
MIT License
1.99k stars 146 forks source link

Allow calling e.preventDefault() myself #301

Closed VsevolodGolovanov closed 2 years ago

VsevolodGolovanov commented 2 years ago

Describe the bug I'm only in interested in some swipes, namely ones starting at the edges of the screen:

const handlers = useSwipeable({
        onSwiping: ({
            first, initial, dir, deltaX, event
        }) => {
            if (initial[0] === 0)
                // garbage
                return;
            lastDeltaX[0] = lastDeltaX[1];
            lastDeltaX[1] = deltaX;
            let dragging = false;
            const left = parseInt(jQuery(navPanelSelector).css("left"));
            if (first) {
                if (left === 0) {
                    if (dir === "Right" && (initial[0] / window.innerWidth < swipeThreshold)) {
                        // started dragging open panel right
                        dragging = true;
                    }
                } else {
                    if (dir === "Left" && (1 - initial[0] / window.innerWidth < swipeThreshold)) {
                        // started dragging closed panel left
                        dragging = true;
                    }
                }
            } else if (left !== 0 && left !== window.innerWidth) {
                // continuing to drag
                dragging = true;
            }

            if (dragging) {
                let newLeft =
                    _.round((initial[0] + deltaX) / window.innerWidth * 100, 2);
                newLeft = Math.min(Math.max(newLeft, 1), window.innerWidth - 1);
                jQuery(navPanelSelector).css("left", `${newLeft}%`);
                event.preventDefault();
            }
        },
        onSwiped: ({initial, deltaX}) => {
            const left = parseInt(jQuery(navPanelSelector).css("left"));
            if (left !== 0 && left !== window.innerWidth) {
                const deltaDeltaX = lastDeltaX[1] - lastDeltaX[0];
                const xpct = (initial[0] + deltaX) / window.innerWidth * 100;
                // if the user simply let it go, then move to closest side; otherwise move in the last drag direction
                const newLeft = Math.abs(deltaDeltaX) <= 1 ? (xpct > 50 ? 100 : 0) : (deltaDeltaX > 0 ? 100 : 0);
                jQuery(navPanelSelector).animate({left: `${newLeft}%`});
            }
        }

Problem is, I have to set the preventDefaultTouchmoveEvent property to make the listener passive=false, but then react-swipeable calls e.preventDefault() itself, preventing scrolling when it shouldn't.

Steps or Sandbox to reproduce

Expected behavior I wish there was a way to have a passive=false listener without react-swipeable calling e.preventDefault() for all swipes.

Device/Browser

Additional context

hartzis commented 2 years ago

@VsevolodGolovanov you're totally right and react-swipeable is about to have this capability in v7

I hope to release v7 this month.