diff --git a/src/Selectable.tsx b/src/Selectable.tsx index 6abf819..5ce8b78 100644 --- a/src/Selectable.tsx +++ b/src/Selectable.tsx @@ -171,6 +171,10 @@ function Selectable( const onMouseMove = (e: MouseEvent | TouchEvent) => { if (isMouseDowning) { + // Prevent scroll on mobile + if (e instanceof TouchEvent) { + e.preventDefault(); + } const { clientX, clientY } = getClientXY(e); moveClient.current = { x: clientX, y: clientY }; const { left, top } = scrollContainer.getBoundingClientRect(); @@ -248,12 +252,17 @@ function Selectable( }; const onMouseDown = (e: MouseEvent | TouchEvent) => { - if (e instanceof MouseEvent && e.button !== 0) { + const isMouseEvent = e instanceof MouseEvent; + if (isMouseEvent && e.button !== 0) { return; } - // disable text selection, but it will prevent default scroll behavior when mouse move, so we used `useScroll` - e.preventDefault(); + // Disable text selection, but it will prevent default scroll behavior when mouse move, so we used `useScroll` + // And it will prevent click events on mobile devices, so don't trigger it + if (isMouseEvent) { + e.preventDefault(); + } + isMouseDowning = true; if (selectStartRangeRef.current !== 'all') { diff --git a/src/hooks/useScroll.ts b/src/hooks/useScroll.ts index 8f34b41..3e51aa8 100644 --- a/src/hooks/useScroll.ts +++ b/src/hooks/useScroll.ts @@ -1,4 +1,4 @@ -import { useRef } from 'react'; +import { useEffect, useRef } from 'react'; import { getClientXY } from '../utils'; const SCROLL_STEP = 4; @@ -11,41 +11,24 @@ export default function useScroll() { const leftRaf = useRef(null); const rightRaf = useRef(null); - const cancelTopRaf = () => { - if (topRaf.current) { - cancelAnimationFrame(topRaf.current); - topRaf.current = null; - } - }; - - const cancelBottomRaf = () => { - if (bottomRaf.current) { - cancelAnimationFrame(bottomRaf.current); - bottomRaf.current = null; - } - }; - - const cancelLeftRaf = () => { - if (leftRaf.current) { - cancelAnimationFrame(leftRaf.current); - leftRaf.current = null; - } - }; - - const cancelRightRaf = () => { - if (rightRaf.current) { - cancelAnimationFrame(rightRaf.current); - rightRaf.current = null; + const cancelRaf = (raf: React.MutableRefObject) => { + if (raf.current) { + cancelAnimationFrame(raf.current); + raf.current = null; } }; const cancelScroll = () => { - cancelTopRaf(); - cancelBottomRaf(); - cancelLeftRaf(); - cancelRightRaf(); + cancelRaf(topRaf); + cancelRaf(bottomRaf); + cancelRaf(leftRaf); + cancelRaf(rightRaf); }; + useEffect(() => { + return cancelScroll; + }, []); + const smoothScroll = (e: MouseEvent | TouchEvent, _container: HTMLElement) => { const container = _container === document.body ? document.documentElement : _container; const { clientX, clientY } = getClientXY(e); @@ -64,7 +47,7 @@ export default function useScroll() { callback(); } } else { - cancelTopRaf(); + cancelRaf(topRaf); } // bottom @@ -84,7 +67,7 @@ export default function useScroll() { callback(); } } else { - cancelBottomRaf(); + cancelRaf(bottomRaf); } // left @@ -101,7 +84,7 @@ export default function useScroll() { callback(); } } else { - cancelLeftRaf(); + cancelRaf(leftRaf); } // right @@ -121,7 +104,7 @@ export default function useScroll() { callback(); } } else { - cancelRightRaf(); + cancelRaf(rightRaf); } };