import { useState , useCallback , useEffect } from 'react' ; const POSITION = { x : 0 , y : 0 } ; export default function useDraggable ( ) { const [ state , setState ] = useState ( { isDragging : false , origin : POSITION , position : POSITION , } ) ; const onMouseDown = useCallback ( event => { event . stopPropagation ( ) ; event . preventDefault ( ) ; const { clientX , clientY } = event ; setState ( state => ( { ... state , isDragging : true , origin : { x : clientX , y : clientY } , } ) ) ; } , [ ] ) ; const onMouseMove = useCallback ( event => { const position = { x : event . clientX - state . origin . x , y : event . clientY - state . origin . y , } ; setState ( state => ( { ... state , position , } ) ) ; } , [ state . origin ] ) ; const onMouseUp = useCallback ( ( ) => { setState ( state => ( { ... state , isDragging : false , } ) ) ; } , [ ] ) ; useEffect ( ( ) => { if ( state . isDragging ) { window . addEventListener ( 'mousemove' , onMouseMove ) ; window . addEventListener ( 'mouseup' , onMouseUp ) ; } else { window . removeEventListener ( 'mousemove' , onMouseMove ) ; window . removeEventListener ( 'mouseup' , onMouseUp ) ; setState ( state => ( { ... state , position : { x : 0 , y : 0 } } ) ) ; } } , [ state . isDragging , onMouseMove , onMouseUp ] ) ; return { onMouseDown , isDragging : state . isDragging , position : state . position , } ; }