@@ -13,11 +13,6 @@ export interface Options {
13
13
onLongPressEnd ?: ( event : EventType ) => void ;
14
14
}
15
15
16
- const touchSupported =
17
- isBrowser &&
18
- // @ts -ignore
19
- ( 'ontouchstart' in window || ( window . DocumentTouch && document instanceof DocumentTouch ) ) ;
20
-
21
16
function useLongPress (
22
17
onLongPress : ( event : EventType ) => void ,
23
18
target : BasicTarget ,
@@ -30,6 +25,8 @@ function useLongPress(
30
25
const timerRef = useRef < ReturnType < typeof setTimeout > > ( ) ;
31
26
const isTriggeredRef = useRef ( false ) ;
32
27
const pervPositionRef = useRef ( { x : 0 , y : 0 } ) ;
28
+ const mousePressed = useRef ( false ) ;
29
+ const touchPressed = useRef ( false ) ;
33
30
const hasMoveThreshold = ! ! (
34
31
( moveThreshold ?. x && moveThreshold . x > 0 ) ||
35
32
( moveThreshold ?. y && moveThreshold . y > 0 )
@@ -60,7 +57,6 @@ function useLongPress(
60
57
clientY : event . touches [ 0 ] . clientY ,
61
58
} ;
62
59
}
63
-
64
60
if ( event instanceof MouseEvent ) {
65
61
return {
66
62
clientX : event . clientX ,
@@ -73,64 +69,119 @@ function useLongPress(
73
69
return { clientX : 0 , clientY : 0 } ;
74
70
}
75
71
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
+
77
83
if ( hasMoveThreshold ) {
78
84
const { clientX, clientY } = getClientPosition ( event ) ;
79
85
pervPositionRef . current . x = clientX ;
80
86
pervPositionRef . current . y = clientY ;
81
87
}
82
- timerRef . current = setTimeout ( ( ) => {
83
- onLongPressRef . current ( event ) ;
84
- isTriggeredRef . current = true ;
85
- } , delay ) ;
88
+ createTimer ( event ) ;
86
89
} ;
87
90
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 ) => {
89
104
if ( timerRef . current && overThreshold ( event ) ) {
90
105
clearTimeout ( timerRef . current ) ;
91
106
timerRef . current = undefined ;
92
107
}
93
108
} ;
94
109
95
- const onEnd = ( event : EventType , shouldTriggerClick : boolean = false ) => {
110
+ const onTouchEnd = ( event : TouchEvent ) => {
111
+ if ( ! touchPressed . current ) return ;
112
+ touchPressed . current = false ;
113
+
96
114
if ( timerRef . current ) {
97
115
clearTimeout ( timerRef . current ) ;
116
+ timerRef . current = undefined ;
98
117
}
118
+
99
119
if ( isTriggeredRef . current ) {
100
120
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 ;
101
135
}
102
- if ( shouldTriggerClick && ! isTriggeredRef . current && onClickRef . current ) {
136
+
137
+ if ( isTriggeredRef . current ) {
138
+ onLongPressEndRef . current ?.( event ) ;
139
+ } else if ( onClickRef . current ) {
103
140
onClickRef . current ( event ) ;
104
141
}
105
142
isTriggeredRef . current = false ;
106
143
} ;
107
144
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 ) ;
119
168
}
169
+
120
170
return ( ) => {
121
171
if ( timerRef . current ) {
122
172
clearTimeout ( timerRef . current ) ;
123
173
isTriggeredRef . current = false ;
124
174
}
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 ) ;
134
185
}
135
186
} ;
136
187
} ,
0 commit comments