@@ -21,29 +21,33 @@ import {
2121 isMac ,
2222 dispatchDiscreteEvent ,
2323 dispatchUserBlockingEvent ,
24+ getTouchById ,
25+ hasModifierKey ,
2426} from './shared' ;
2527
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 = { |
3740 activePointerId : null | number ,
3841 buttons : 0 | 1 | 4 ,
3942 gestureState : TapGestureState ,
4043 ignoreEmulatedEvents : boolean ,
44+ initialPosition : { | x : number , y : number | } ,
4145 isActive : boolean ,
4246 pointerType : PointerType ,
4347 responderTarget : null | Element ,
4448 rootEvents : null | Array < string > ,
4549 shouldPreventClick : boolean ,
46- } ;
50+ | } ;
4751
4852type TapEventType =
4953 | 'tap-cancel'
@@ -76,10 +80,10 @@ type TapGestureState = {|
7680 y : number ,
7781| } ;
7882
79- type TapEvent = { |
83+ type TapEvent = $ReadOnly < { |
8084 ...TapGestureState ,
8185 type : TapEventType ,
82- | } ;
86+ | } > ;
8387
8488/**
8589 * Native event dependencies
@@ -120,6 +124,7 @@ function createInitialState(): TapState {
120124 buttons : 0 ,
121125 ignoreEmulatedEvents : false ,
122126 isActive : false ,
127+ initialPosition : { x : 0 , y : 0 } ,
123128 pointerType : '' ,
124129 responderTarget : null ,
125130 rootEvents : null ,
@@ -299,23 +304,6 @@ function removeRootEventTypes(
299304 * Managing pointers
300305 */
301306
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-
319307function getHitTarget (
320308 event : ReactDOMResponderEvent ,
321309 context : ReactDOMResponderContext ,
@@ -362,14 +350,6 @@ function isActivePointer(
362350 }
363351}
364352
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-
373353function shouldActivate ( event : ReactDOMResponderEvent ) : boolean {
374354 const nativeEvent : any = event . nativeEvent ;
375355 const pointerType = event . pointerType ;
@@ -511,7 +491,12 @@ const responderImpl = {
511491 state . pointerType = event . pointerType ;
512492 state . responderTarget = context . getResponderNode ( ) ;
513493 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+
515500 dispatchStart ( context , props , state ) ;
516501 dispatchChange ( context , props , state ) ;
517502 addRootEventTypes ( rootEventTypes , context , state ) ;
@@ -549,7 +534,26 @@ const responderImpl = {
549534
550535 if ( state . isActive && isActivePointer ( event , state ) ) {
551536 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 ) {
553557 dispatchUpdate ( context , props , state ) ;
554558 } else {
555559 state . isActive = false ;
@@ -577,7 +581,7 @@ const responderImpl = {
577581 dispatchChange ( context , props , state ) ;
578582 if ( context . isTargetWithinResponder ( hitTarget ) ) {
579583 // Determine whether to call preventDefault on subsequent native events.
580- if ( isModifiedTap ( event ) ) {
584+ if ( hasModifierKey ( event ) ) {
581585 state . shouldPreventClick = false ;
582586 }
583587 dispatchEnd ( context , props , state ) ;
0 commit comments