@@ -21,29 +21,33 @@ import {
21
21
isMac ,
22
22
dispatchDiscreteEvent ,
23
23
dispatchUserBlockingEvent ,
24
+ getTouchById ,
25
+ hasModifierKey ,
24
26
} from './shared' ;
25
27
26
- type TapProps = { |
27
- disabled : boolean ,
28
- preventDefault : boolean ,
29
- onTapCancel : ( e : TapEvent ) => void ,
30
- onTapChange : boolean => void ,
31
- onTapEnd : ( e : TapEvent ) => void ,
32
- onTapStart : ( e : TapEvent ) => void ,
33
- onTapUpdate : ( e : TapEvent ) => void ,
34
- | } ;
35
-
36
- type TapState = {
28
+ type TapProps = $ReadOnly < { |
29
+ disabled ?: boolean ,
30
+ maximumDistance ?: number ,
31
+ preventDefault ?: boolean ,
32
+ onTapCancel ?: ( e : TapEvent ) => void ,
33
+ onTapChange ?: boolean => void ,
34
+ onTapEnd ?: ( e : TapEvent ) => void ,
35
+ onTapStart ?: ( e : TapEvent ) => void ,
36
+ onTapUpdate ?: ( e : TapEvent ) => void ,
37
+ | } > ;
38
+
39
+ type TapState = { |
37
40
activePointerId : null | number ,
38
41
buttons : 0 | 1 | 4 ,
39
42
gestureState : TapGestureState ,
40
43
ignoreEmulatedEvents : boolean ,
44
+ initialPosition : { | x : number , y : number | } ,
41
45
isActive : boolean ,
42
46
pointerType : PointerType ,
43
47
responderTarget : null | Element ,
44
48
rootEvents : null | Array < string > ,
45
49
shouldPreventClick : boolean ,
46
- } ;
50
+ | } ;
47
51
48
52
type TapEventType =
49
53
| 'tap-cancel'
@@ -76,10 +80,10 @@ type TapGestureState = {|
76
80
y : number ,
77
81
| } ;
78
82
79
- type TapEvent = { |
83
+ type TapEvent = $ReadOnly < { |
80
84
...TapGestureState ,
81
85
type : TapEventType ,
82
- | } ;
86
+ | } > ;
83
87
84
88
/**
85
89
* Native event dependencies
@@ -120,6 +124,7 @@ function createInitialState(): TapState {
120
124
buttons : 0 ,
121
125
ignoreEmulatedEvents : false ,
122
126
isActive : false ,
127
+ initialPosition : { x : 0 , y : 0 } ,
123
128
pointerType : '' ,
124
129
responderTarget : null ,
125
130
rootEvents : null ,
@@ -299,23 +304,6 @@ function removeRootEventTypes(
299
304
* Managing pointers
300
305
*/
301
306
302
- function getTouchById (
303
- nativeEvent : TouchEvent ,
304
- pointerId : null | number ,
305
- ) : null | Touch {
306
- if ( pointerId != null ) {
307
- const changedTouches = nativeEvent . changedTouches ;
308
- for ( let i = 0 ; i < changedTouches . length ; i ++ ) {
309
- const touch = changedTouches [ i ] ;
310
- if ( touch . identifier === pointerId ) {
311
- return touch ;
312
- }
313
- }
314
- return null ;
315
- }
316
- return null ;
317
- }
318
-
319
307
function getHitTarget (
320
308
event : ReactDOMResponderEvent ,
321
309
context : ReactDOMResponderContext ,
@@ -362,14 +350,6 @@ function isActivePointer(
362
350
}
363
351
}
364
352
365
- function isModifiedTap ( event : ReactDOMResponderEvent ) : boolean {
366
- const nativeEvent : any = event . nativeEvent ;
367
- const { altKey, ctrlKey, metaKey, shiftKey} = nativeEvent ;
368
- return (
369
- altKey === true || ctrlKey === true || metaKey === true || shiftKey === true
370
- ) ;
371
- }
372
-
373
353
function shouldActivate ( event : ReactDOMResponderEvent ) : boolean {
374
354
const nativeEvent : any = event . nativeEvent ;
375
355
const pointerType = event . pointerType ;
@@ -511,7 +491,12 @@ const responderImpl = {
511
491
state . pointerType = event . pointerType ;
512
492
state . responderTarget = context . getResponderNode ( ) ;
513
493
state . shouldPreventClick = props . preventDefault !== false ;
514
- state . gestureState = createGestureState ( context , props , state , event ) ;
494
+
495
+ const gestureState = createGestureState ( context , props , state , event ) ;
496
+ state . gestureState = gestureState ;
497
+ state . initialPosition . x = gestureState . x ;
498
+ state . initialPosition . y = gestureState . y ;
499
+
515
500
dispatchStart ( context , props , state ) ;
516
501
dispatchChange ( context , props , state ) ;
517
502
addRootEventTypes ( rootEventTypes , context , state ) ;
@@ -549,7 +534,26 @@ const responderImpl = {
549
534
550
535
if ( state . isActive && isActivePointer ( event , state ) ) {
551
536
state . gestureState = createGestureState ( context , props , state , event ) ;
552
- if ( context . isTargetWithinResponder ( hitTarget ) ) {
537
+ let shouldUpdate = true ;
538
+
539
+ if ( ! context . isTargetWithinResponder ( hitTarget ) ) {
540
+ shouldUpdate = false ;
541
+ } else if (
542
+ props . maximumDistance != null &&
543
+ props . maximumDistance >= 10
544
+ ) {
545
+ const maxDistance = props . maximumDistance ;
546
+ const initialPosition = state . initialPosition ;
547
+ const currentPosition = state . gestureState ;
548
+ const moveX = initialPosition . x - currentPosition . x ;
549
+ const moveY = initialPosition . y - currentPosition . y ;
550
+ const moveDistance = Math . sqrt ( moveX * moveX + moveY * moveY ) ;
551
+ if ( moveDistance > maxDistance ) {
552
+ shouldUpdate = false ;
553
+ }
554
+ }
555
+
556
+ if ( shouldUpdate ) {
553
557
dispatchUpdate ( context , props , state ) ;
554
558
} else {
555
559
state . isActive = false ;
@@ -577,7 +581,7 @@ const responderImpl = {
577
581
dispatchChange ( context , props , state ) ;
578
582
if ( context . isTargetWithinResponder ( hitTarget ) ) {
579
583
// Determine whether to call preventDefault on subsequent native events.
580
- if ( isModifiedTap ( event ) ) {
584
+ if ( hasModifierKey ( event ) ) {
581
585
state . shouldPreventClick = false ;
582
586
}
583
587
dispatchEnd ( context , props , state ) ;
0 commit comments