mirror of https://git.lenooby09.tech/LeNooby09/social-app.git
at samuel/exp-cli 85 lines 2.1 kB view raw
1import {type ForwardedRef, useEffect, useMemo, useRef} from 'react' 2import {type ScrollView} from 'react-native' 3import {Platform} from 'react-native' 4 5import {mergeRefs} from '#/lib/merge-refs' 6 7type Props<Scrollable extends ScrollView = ScrollView> = { 8 cursor?: string 9 outerRef?: ForwardedRef<Scrollable> 10} 11 12export function useDraggableScroll<Scrollable extends ScrollView = ScrollView>({ 13 outerRef, 14 cursor = 'grab', 15}: Props<Scrollable> = {}) { 16 const ref = useRef<Scrollable>(null) 17 18 useEffect(() => { 19 if (Platform.OS !== 'web' || !ref.current) { 20 return 21 } 22 const slider = ref.current as unknown as HTMLDivElement 23 if (!slider) { 24 return 25 } 26 let isDragging = false 27 let isMouseDown = false 28 let startX = 0 29 let scrollLeft = 0 30 31 const mouseDown = (e: MouseEvent) => { 32 isMouseDown = true 33 startX = e.pageX - slider.offsetLeft 34 scrollLeft = slider.scrollLeft 35 36 slider.style.cursor = cursor 37 } 38 39 const mouseUp = () => { 40 if (isDragging) { 41 slider.addEventListener('click', e => e.stopPropagation(), {once: true}) 42 } 43 44 isMouseDown = false 45 isDragging = false 46 slider.style.cursor = 'default' 47 } 48 49 const mouseMove = (e: MouseEvent) => { 50 if (!isMouseDown) { 51 return 52 } 53 54 // Require n pixels momement before start of drag (3 in this case ) 55 const x = e.pageX - slider.offsetLeft 56 if (Math.abs(x - startX) < 3) { 57 return 58 } 59 60 isDragging = true 61 e.preventDefault() 62 const walk = x - startX 63 slider.scrollLeft = scrollLeft - walk 64 } 65 66 slider.addEventListener('mousedown', mouseDown) 67 window.addEventListener('mouseup', mouseUp) 68 window.addEventListener('mousemove', mouseMove) 69 70 return () => { 71 slider.removeEventListener('mousedown', mouseDown) 72 window.removeEventListener('mouseup', mouseUp) 73 window.removeEventListener('mousemove', mouseMove) 74 } 75 }, [cursor]) 76 77 const refs = useMemo( 78 () => mergeRefs(outerRef ? [ref, outerRef] : [ref]), 79 [ref, outerRef], 80 ) 81 82 return { 83 refs, 84 } 85}