@@ -13,11 +13,6 @@ export interface Options {
1313 onLongPressEnd ?: ( event : EventType ) => void ;
1414}
1515
16- const touchSupported =
17- isBrowser &&
18- // @ts -ignore
19- ( 'ontouchstart' in window || ( window . DocumentTouch && document instanceof DocumentTouch ) ) ;
20-
2116function useLongPress (
2217 onLongPress : ( event : EventType ) => void ,
2318 target : BasicTarget ,
@@ -30,6 +25,8 @@ function useLongPress(
3025 const timerRef = useRef < ReturnType < typeof setTimeout > > ( ) ;
3126 const isTriggeredRef = useRef ( false ) ;
3227 const pervPositionRef = useRef ( { x : 0 , y : 0 } ) ;
28+ const mousePressed = useRef ( false ) ;
29+ const touchPressed = useRef ( false ) ;
3330 const hasMoveThreshold = ! ! (
3431 ( moveThreshold ?. x && moveThreshold . x > 0 ) ||
3532 ( moveThreshold ?. y && moveThreshold . y > 0 )
@@ -60,7 +57,6 @@ function useLongPress(
6057 clientY : event . touches [ 0 ] . clientY ,
6158 } ;
6259 }
63-
6460 if ( event instanceof MouseEvent ) {
6561 return {
6662 clientX : event . clientX ,
@@ -73,64 +69,119 @@ function useLongPress(
7369 return { clientX : 0 , clientY : 0 } ;
7470 }
7571
76- const onStart = ( event : EventType ) => {
72+ const createTimer = ( event : EventType ) => {
73+ timerRef . current = setTimeout ( ( ) => {
74+ onLongPressRef . current ( event ) ;
75+ isTriggeredRef . current = true ;
76+ } , delay ) ;
77+ } ;
78+
79+ const onTouchStart = ( event : TouchEvent ) => {
80+ if ( touchPressed . current ) return ;
81+ touchPressed . current = true ;
82+
7783 if ( hasMoveThreshold ) {
7884 const { clientX, clientY } = getClientPosition ( event ) ;
7985 pervPositionRef . current . x = clientX ;
8086 pervPositionRef . current . y = clientY ;
8187 }
82- timerRef . current = setTimeout ( ( ) => {
83- onLongPressRef . current ( event ) ;
84- isTriggeredRef . current = true ;
85- } , delay ) ;
88+ createTimer ( event ) ;
8689 } ;
8790
88- const onMove = ( event : TouchEvent ) => {
91+ const onMouseDown = ( event : MouseEvent ) => {
92+ if ( ( event as any ) ?. sourceCapabilities ?. firesTouchEvents ) return ;
93+
94+ mousePressed . current = true ;
95+
96+ if ( hasMoveThreshold ) {
97+ pervPositionRef . current . x = event . clientX ;
98+ pervPositionRef . current . y = event . clientY ;
99+ }
100+ createTimer ( event ) ;
101+ } ;
102+
103+ const onMove = ( event : EventType ) => {
89104 if ( timerRef . current && overThreshold ( event ) ) {
90105 clearTimeout ( timerRef . current ) ;
91106 timerRef . current = undefined ;
92107 }
93108 } ;
94109
95- const onEnd = ( event : EventType , shouldTriggerClick : boolean = false ) => {
110+ const onTouchEnd = ( event : TouchEvent ) => {
111+ if ( ! touchPressed . current ) return ;
112+ touchPressed . current = false ;
113+
96114 if ( timerRef . current ) {
97115 clearTimeout ( timerRef . current ) ;
116+ timerRef . current = undefined ;
98117 }
118+
99119 if ( isTriggeredRef . current ) {
100120 onLongPressEndRef . current ?.( event ) ;
121+ } else if ( onClickRef . current ) {
122+ onClickRef . current ( event ) ;
123+ }
124+ isTriggeredRef . current = false ;
125+ } ;
126+
127+ const onMouseUp = ( event : MouseEvent ) => {
128+ if ( ( event as any ) ?. sourceCapabilities ?. firesTouchEvents ) return ;
129+ if ( ! mousePressed . current ) return ;
130+ mousePressed . current = false ;
131+
132+ if ( timerRef . current ) {
133+ clearTimeout ( timerRef . current ) ;
134+ timerRef . current = undefined ;
101135 }
102- if ( shouldTriggerClick && ! isTriggeredRef . current && onClickRef . current ) {
136+
137+ if ( isTriggeredRef . current ) {
138+ onLongPressEndRef . current ?.( event ) ;
139+ } else if ( onClickRef . current ) {
103140 onClickRef . current ( event ) ;
104141 }
105142 isTriggeredRef . current = false ;
106143 } ;
107144
108- const onEndWithClick = ( event : EventType ) => onEnd ( event , true ) ;
109-
110- if ( ! touchSupported ) {
111- targetElement . addEventListener ( 'mousedown' , onStart ) ;
112- targetElement . addEventListener ( 'mouseup' , onEndWithClick ) ;
113- targetElement . addEventListener ( 'mouseleave' , onEnd ) ;
114- if ( hasMoveThreshold ) targetElement . addEventListener ( 'mousemove' , onMove ) ;
115- } else {
116- targetElement . addEventListener ( 'touchstart' , onStart ) ;
117- targetElement . addEventListener ( 'touchend' , onEndWithClick ) ;
118- if ( hasMoveThreshold ) targetElement . addEventListener ( 'touchmove' , onMove ) ;
145+ const onMouseLeave = ( event : MouseEvent ) => {
146+ if ( ! mousePressed . current ) return ;
147+ mousePressed . current = false ;
148+
149+ if ( timerRef . current ) {
150+ clearTimeout ( timerRef . current ) ;
151+ timerRef . current = undefined ;
152+ }
153+ if ( isTriggeredRef . current ) {
154+ onLongPressEndRef . current ?.( event ) ;
155+ isTriggeredRef . current = false ;
156+ }
157+ } ;
158+
159+ targetElement . addEventListener ( 'mousedown' , onMouseDown ) ;
160+ targetElement . addEventListener ( 'mouseup' , onMouseUp ) ;
161+ targetElement . addEventListener ( 'mouseleave' , onMouseLeave ) ;
162+ targetElement . addEventListener ( 'touchstart' , onTouchStart ) ;
163+ targetElement . addEventListener ( 'touchend' , onTouchEnd ) ;
164+
165+ if ( hasMoveThreshold ) {
166+ targetElement . addEventListener ( 'mousemove' , onMove ) ;
167+ targetElement . addEventListener ( 'touchmove' , onMove ) ;
119168 }
169+
120170 return ( ) => {
121171 if ( timerRef . current ) {
122172 clearTimeout ( timerRef . current ) ;
123173 isTriggeredRef . current = false ;
124174 }
125- if ( ! touchSupported ) {
126- targetElement . removeEventListener ( 'mousedown' , onStart ) ;
127- targetElement . removeEventListener ( 'mouseup' , onEndWithClick ) ;
128- targetElement . removeEventListener ( 'mouseleave' , onEnd ) ;
129- if ( hasMoveThreshold ) targetElement . removeEventListener ( 'mousemove' , onMove ) ;
130- } else {
131- targetElement . removeEventListener ( 'touchstart' , onStart ) ;
132- targetElement . removeEventListener ( 'touchend' , onEndWithClick ) ;
133- if ( hasMoveThreshold ) targetElement . removeEventListener ( 'touchmove' , onMove ) ;
175+
176+ targetElement . removeEventListener ( 'mousedown' , onMouseDown ) ;
177+ targetElement . removeEventListener ( 'mouseup' , onMouseUp ) ;
178+ targetElement . removeEventListener ( 'mouseleave' , onMouseLeave ) ;
179+ targetElement . removeEventListener ( 'touchstart' , onTouchStart ) ;
180+ targetElement . removeEventListener ( 'touchend' , onTouchEnd ) ;
181+
182+ if ( hasMoveThreshold ) {
183+ targetElement . removeEventListener ( 'mousemove' , onMove ) ;
184+ targetElement . removeEventListener ( 'touchmove' , onMove ) ;
134185 }
135186 } ;
136187 } ,
0 commit comments