1
- import React , { useEffect , useLayoutEffect , useRef } from 'react'
1
+ import React , { useCallback , useEffect , useLayoutEffect , useRef } from 'react'
2
2
import {
3
3
TouchableHighlightProps ,
4
4
TouchableOpacity ,
@@ -34,13 +34,16 @@ export const Touchable = React.forwardRef(
34
34
analyticsValue,
35
35
onLongPress : _onLongPress ,
36
36
onPress : _onPress ,
37
+ onPressIn : _onPressIn ,
38
+ onPressOut : _onPressOut ,
37
39
selectable,
38
40
tooltip,
39
41
...props
40
42
} : TouchableProps ,
41
43
ref ,
42
44
) => {
43
45
const touchableRef = useRef < TouchableOpacity > ( null )
46
+ const pressInPagePointRef = useRef ( { x : 0 , y : 0 } )
44
47
45
48
useLayoutEffect ( ( ) => {
46
49
if ( typeof ref === 'function' ) {
@@ -63,35 +66,79 @@ export const Touchable = React.forwardRef(
63
66
if ( ! tooltip && node . removeAttribute ) node . removeAttribute ( 'title' )
64
67
} , [ touchableRef . current , tooltip ] )
65
68
66
- const onPress : typeof _onPress = analyticsLabel
67
- ? e => {
69
+ const onLongPress : typeof _onLongPress =
70
+ _onLongPress ||
71
+ ( tooltip && Platform . supportsTouch
72
+ ? ( ) => {
73
+ alert ( tooltip )
74
+ }
75
+ : undefined )
76
+
77
+ const onPressIn = useCallback < NonNullable < TouchableProps [ 'onPressIn' ] > > (
78
+ e => {
79
+ if ( Platform . OS === 'web' ) {
80
+ pressInPagePointRef . current = {
81
+ x : e . nativeEvent . pageX ,
82
+ y : e . nativeEvent . pageY ,
83
+ }
84
+ }
85
+
86
+ if ( _onPressIn ) _onPressIn ( e )
87
+ } ,
88
+ [ _onPressIn ] ,
89
+ )
90
+
91
+ const onPressOut = useCallback < NonNullable < TouchableProps [ 'onPressOut' ] > > (
92
+ e => {
93
+ if ( _onPressOut ) _onPressOut ( e )
94
+
95
+ if ( Platform . OS === 'web' ) {
96
+ const [ x , y ] = [ e . nativeEvent . pageX , e . nativeEvent . pageY ]
97
+ if (
98
+ Math . abs ( pressInPagePointRef . current . x - x ) > 1 ||
99
+ Math . abs ( pressInPagePointRef . current . y - y ) > 1
100
+ ) {
101
+ e . preventDefault ( )
102
+ }
103
+ }
104
+ } ,
105
+ [ _onPressOut ] ,
106
+ )
107
+
108
+ const onPress = useCallback < NonNullable < TouchableProps [ 'onPress' ] > > (
109
+ e => {
110
+ if ( analyticsLabel ) {
68
111
analytics . trackEvent (
69
112
analyticsCategory || 'button' ,
70
113
analyticsAction || 'press' ,
71
114
analyticsLabel ,
72
115
analyticsValue ,
73
116
)
74
- if ( _onPress ) _onPress ( e )
75
117
}
76
- : _onPress
77
118
78
- const onLongPress : typeof _onLongPress =
79
- _onLongPress ||
80
- ( tooltip && Platform . supportsTouch
81
- ? ( ) => {
82
- alert ( tooltip )
83
- }
84
- : undefined )
119
+ if ( e && e . isDefaultPrevented ( ) ) return
120
+ if ( _onPress ) _onPress ( e )
121
+ } ,
122
+ [
123
+ _onPress ,
124
+ analyticsCategory || 'button' ,
125
+ analyticsAction || 'press' ,
126
+ analyticsLabel ,
127
+ analyticsValue ,
128
+ ] ,
129
+ )
85
130
86
131
return (
87
132
< TouchableComponent
88
133
{ ...props }
89
134
ref = { touchableRef }
90
135
data-touchable
91
136
data-touchable-disabled = { ! ! props . disabled }
92
- data-touchable-onpress = { ! ! onPress }
137
+ data-touchable-onpress = { ! ! _onPress }
93
138
onLongPress = { onLongPress }
94
139
onPress = { onPress }
140
+ onPressIn = { onPressIn }
141
+ onPressOut = { onPressOut }
95
142
style = { [
96
143
props . disabled && { opacity : 0.5 } ,
97
144
selectable === true && ( { userSelect : undefined } as any ) ,
0 commit comments