From 436eccc8b894ec3d713fd9fab03cf94b8ec004f6 Mon Sep 17 00:00:00 2001 From: empyrical Date: Mon, 24 Sep 2018 09:57:39 -0600 Subject: [PATCH 1/4] Add flow types to PanResponder --- .../Experimental/SwipeableRow/SwipeableRow.js | 36 ++-- Libraries/Interaction/PanResponder.js | 176 +++++++++++++----- Libraries/Types/CoreEventTypes.js | 6 + 3 files changed, 158 insertions(+), 60 deletions(-) diff --git a/Libraries/Experimental/SwipeableRow/SwipeableRow.js b/Libraries/Experimental/SwipeableRow/SwipeableRow.js index 7bf67dae28cfe8..fb9cc1df409090 100644 --- a/Libraries/Experimental/SwipeableRow/SwipeableRow.js +++ b/Libraries/Experimental/SwipeableRow/SwipeableRow.js @@ -25,6 +25,9 @@ const View = require('View'); const createReactClass = require('create-react-class'); const emptyFunction = require('fbjs/lib/emptyFunction'); +import type {LayoutEvent, PressEvent} from 'CoreEventTypes'; +import type {GestureState} from 'PanResponder'; + const IS_RTL = I18nManager.isRTL; // NOTE: Eventually convert these consts to an input object of configurations @@ -204,7 +207,7 @@ const SwipeableRow = createReactClass({ this._animateToClosedPosition(); }, - _onSwipeableViewLayout(event: Object): void { + _onSwipeableViewLayout(event: LayoutEvent): void { this.setState({ isSwipeableViewRendered: true, rowHeight: event.nativeEvent.layout.height, @@ -212,16 +215,19 @@ const SwipeableRow = createReactClass({ }, _handleMoveShouldSetPanResponderCapture( - event: Object, - gestureState: Object, + event: PressEvent, + gestureState: GestureState, ): boolean { // Decides whether a swipe is responded to by this component or its child return gestureState.dy < 10 && this._isValidSwipe(gestureState); }, - _handlePanResponderGrant(event: Object, gestureState: Object): void {}, + _handlePanResponderGrant( + event: PressEvent, + gestureState: GestureState, + ): void {}, - _handlePanResponderMove(event: Object, gestureState: Object): void { + _handlePanResponderMove(event: PressEvent, gestureState: GestureState): void { if (this._isSwipingExcessivelyRightFromClosedPosition(gestureState)) { return; } @@ -235,22 +241,24 @@ const SwipeableRow = createReactClass({ } }, - _isSwipingRightFromClosed(gestureState: Object): boolean { + _isSwipingRightFromClosed(gestureState: GestureState): boolean { const gestureStateDx = IS_RTL ? -gestureState.dx : gestureState.dx; return this._previousLeft === CLOSED_LEFT_POSITION && gestureStateDx > 0; }, - _swipeFullSpeed(gestureState: Object): void { + _swipeFullSpeed(gestureState: GestureState): void { this.state.currentLeft.setValue(this._previousLeft + gestureState.dx); }, - _swipeSlowSpeed(gestureState: Object): void { + _swipeSlowSpeed(gestureState: GestureState): void { this.state.currentLeft.setValue( this._previousLeft + gestureState.dx / SLOW_SPEED_SWIPE_FACTOR, ); }, - _isSwipingExcessivelyRightFromClosedPosition(gestureState: Object): boolean { + _isSwipingExcessivelyRightFromClosedPosition( + gestureState: GestureState, + ): boolean { /** * We want to allow a BIT of right swipe, to allow users to know that * swiping is available, but swiping right does not do anything @@ -264,8 +272,8 @@ const SwipeableRow = createReactClass({ }, _onPanResponderTerminationRequest( - event: Object, - gestureState: Object, + event: PressEvent, + gestureState: GestureState, ): boolean { return false; }, @@ -338,7 +346,7 @@ const SwipeableRow = createReactClass({ }, // Ignore swipes due to user's finger moving slightly when tapping - _isValidSwipe(gestureState: Object): boolean { + _isValidSwipe(gestureState: GestureState): boolean { if ( this.props.preventSwipeRight && this._previousLeft === CLOSED_LEFT_POSITION && @@ -350,7 +358,7 @@ const SwipeableRow = createReactClass({ return Math.abs(gestureState.dx) > HORIZONTAL_SWIPE_DISTANCE_THRESHOLD; }, - _shouldAnimateRemainder(gestureState: Object): boolean { + _shouldAnimateRemainder(gestureState: GestureState): boolean { /** * If user has swiped past a certain distance, animate the rest of the way * if they let go @@ -361,7 +369,7 @@ const SwipeableRow = createReactClass({ ); }, - _handlePanResponderEnd(event: Object, gestureState: Object): void { + _handlePanResponderEnd(event: PressEvent, gestureState: GestureState): void { const horizontalDistance = IS_RTL ? -gestureState.dx : gestureState.dx; if (this._isSwipingRightFromClosed(gestureState)) { this.props.onOpen(); diff --git a/Libraries/Interaction/PanResponder.js b/Libraries/Interaction/PanResponder.js index 1015ec20de165d..9e0560045d1c48 100644 --- a/Libraries/Interaction/PanResponder.js +++ b/Libraries/Interaction/PanResponder.js @@ -4,6 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * + * @flow * @format */ @@ -12,6 +13,8 @@ const InteractionManager = require('./InteractionManager'); const TouchHistoryMath = require('./TouchHistoryMath'); +import type {PressEvent} from 'CoreEventTypes'; + const currentCentroidXOfTouchesChangedAfter = TouchHistoryMath.currentCentroidXOfTouchesChangedAfter; const currentCentroidYOfTouchesChangedAfter = @@ -121,6 +124,74 @@ const currentCentroidY = TouchHistoryMath.currentCentroidY; * [PanResponder example in RNTester](https://github.com/facebook/react-native/blob/master/RNTester/js/PanResponderExample.js) */ +export type GestureState = {| + /** + * ID of the gestureState - persisted as long as there at least one touch on screen + */ + stateID: number, + /** + * The latest screen coordinates of the recently-moved touch + */ + moveX: number, + /** + * The latest screen coordinates of the recently-moved touch + */ + moveY: number, + /** + * The screen coordinates of the responder grant + */ + x0: number, + /** + * The screen coordinates of the responder grant + */ + y0: number, + /** + * Accumulated distance of the gesture since the touch started + */ + dx: number, + /** + * Accumulated distance of the gesture since the touch started + */ + dy: number, + /** + * Current velocity of the gesture + */ + vx: number, + /** + * Current velocity of the gesture + */ + vy: number, + /** + * Number of touches currently on screen + */ + numberActiveTouches: number, + /** + * @private + */ + _accountsForMovesUpTo: number, +|}; + +type PanResponderCallback = ( + event: PressEvent, + gestureState: GestureState, +) => mixed; + +type PanResponderConfig = $ReadOnly<{| + onMoveShouldSetPanResponder?: ?PanResponderCallback, + onMoveShouldSetPanResponderCapture?: ?PanResponderCallback, + onStartShouldSetPanResponder?: ?PanResponderCallback, + onStartShouldSetPanResponderCapture?: ?PanResponderCallback, + onPanResponderReject?: ?PanResponderCallback, + onPanResponderGrant?: ?PanResponderCallback, + onPanResponderStart?: ?PanResponderCallback, + onPanResponderEnd?: ?PanResponderCallback, + onPanResponderRelease?: ?PanResponderCallback, + onPanResponderMove?: ?PanResponderCallback, + onPanResponderTerminate?: ?PanResponderCallback, + onPanResponderTerminationRequest?: ?PanResponderCallback, + onShouldBlockNativeResponder?: ?PanResponderCallback, +|}>; + const PanResponder = { /** * @@ -185,7 +256,7 @@ const PanResponder = { * - vx/vy: Velocity. */ - _initializeGestureState: function(gestureState) { + _initializeGestureState(gestureState: GestureState) { gestureState.moveX = 0; gestureState.moveY = 0; gestureState.x0 = 0; @@ -223,7 +294,10 @@ const PanResponder = { * typical responder callback pattern (without using `PanResponder`), but * avoids more dispatches than necessary. */ - _updateGestureStateOnMove: function(gestureState, touchHistory) { + _updateGestureStateOnMove( + gestureState: GestureState, + touchHistory: $PropertyType, + ) { gestureState.numberActiveTouches = touchHistory.numberActiveTouches; gestureState.moveX = currentCentroidXOfTouchesChangedAfter( touchHistory, @@ -290,40 +364,50 @@ const PanResponder = { * accordingly. (numberActiveTouches) may not be totally accurate unless you * are the responder. */ - create: function(config) { + create(config: PanResponderConfig) { const interactionState = { handle: (null: ?number), }; - const gestureState = { + const gestureState: GestureState = { // Useful for debugging stateID: Math.random(), + moveX: 0, + moveY: 0, + x0: 0, + y0: 0, + dx: 0, + dy: 0, + vx: 0, + vy: 0, + numberActiveTouches: 0, + _accountsForMovesUpTo: 0, }; - PanResponder._initializeGestureState(gestureState); const panHandlers = { - onStartShouldSetResponder: function(e) { - return config.onStartShouldSetPanResponder === undefined + onStartShouldSetResponder(event: PressEvent) { + return config.onStartShouldSetPanResponder == null ? false - : config.onStartShouldSetPanResponder(e, gestureState); + : config.onStartShouldSetPanResponder(event, gestureState); }, - onMoveShouldSetResponder: function(e) { - return config.onMoveShouldSetPanResponder === undefined + onMoveShouldSetResponder(event: PressEvent) { + return config.onMoveShouldSetPanResponder == null ? false - : config.onMoveShouldSetPanResponder(e, gestureState); + : config.onMoveShouldSetPanResponder(event, gestureState); }, - onStartShouldSetResponderCapture: function(e) { + onStartShouldSetResponderCapture(event: PressEvent) { // TODO: Actually, we should reinitialize the state any time // touches.length increases from 0 active to > 0 active. - if (e.nativeEvent.touches.length === 1) { + if (event.nativeEvent.touches.length === 1) { PanResponder._initializeGestureState(gestureState); } - gestureState.numberActiveTouches = e.touchHistory.numberActiveTouches; - return config.onStartShouldSetPanResponderCapture !== undefined - ? config.onStartShouldSetPanResponderCapture(e, gestureState) + gestureState.numberActiveTouches = + event.touchHistory.numberActiveTouches; + return config.onStartShouldSetPanResponderCapture != null + ? config.onStartShouldSetPanResponderCapture(event, gestureState) : false; }, - onMoveShouldSetResponderCapture: function(e) { - const touchHistory = e.touchHistory; + onMoveShouldSetResponderCapture(event: PressEvent) { + const touchHistory = event.touchHistory; // Responder system incorrectly dispatches should* to current responder // Filter out any touch moves past the first one - we would have // already processed multi-touch geometry during the first event. @@ -335,56 +419,56 @@ const PanResponder = { } PanResponder._updateGestureStateOnMove(gestureState, touchHistory); return config.onMoveShouldSetPanResponderCapture - ? config.onMoveShouldSetPanResponderCapture(e, gestureState) + ? config.onMoveShouldSetPanResponderCapture(event, gestureState) : false; }, - onResponderGrant: function(e) { + onResponderGrant(event: PressEvent) { if (!interactionState.handle) { interactionState.handle = InteractionManager.createInteractionHandle(); } - gestureState.x0 = currentCentroidX(e.touchHistory); - gestureState.y0 = currentCentroidY(e.touchHistory); + gestureState.x0 = currentCentroidX(event.touchHistory); + gestureState.y0 = currentCentroidY(event.touchHistory); gestureState.dx = 0; gestureState.dy = 0; if (config.onPanResponderGrant) { - config.onPanResponderGrant(e, gestureState); + config.onPanResponderGrant(event, gestureState); } // TODO: t7467124 investigate if this can be removed - return config.onShouldBlockNativeResponder === undefined + return config.onShouldBlockNativeResponder == null ? true - : config.onShouldBlockNativeResponder(); + : config.onShouldBlockNativeResponder(event, gestureState); }, - onResponderReject: function(e) { + onResponderReject(event: PressEvent) { clearInteractionHandle( interactionState, config.onPanResponderReject, - e, + event, gestureState, ); }, - onResponderRelease: function(e) { + onResponderRelease(event: PressEvent) { clearInteractionHandle( interactionState, config.onPanResponderRelease, - e, + event, gestureState, ); PanResponder._initializeGestureState(gestureState); }, - onResponderStart: function(e) { - const touchHistory = e.touchHistory; + onResponderStart(event: PressEvent) { + const touchHistory = event.touchHistory; gestureState.numberActiveTouches = touchHistory.numberActiveTouches; if (config.onPanResponderStart) { - config.onPanResponderStart(e, gestureState); + config.onPanResponderStart(event, gestureState); } }, - onResponderMove: function(e) { - const touchHistory = e.touchHistory; + onResponderMove(event: PressEvent) { + const touchHistory = event.touchHistory; // Guard against the dispatch of two touch moves when there are two // simultaneously changed touches. if ( @@ -397,35 +481,35 @@ const PanResponder = { // already processed multi-touch geometry during the first event. PanResponder._updateGestureStateOnMove(gestureState, touchHistory); if (config.onPanResponderMove) { - config.onPanResponderMove(e, gestureState); + config.onPanResponderMove(event, gestureState); } }, - onResponderEnd: function(e) { - const touchHistory = e.touchHistory; + onResponderEnd(event: PressEvent) { + const touchHistory = event.touchHistory; gestureState.numberActiveTouches = touchHistory.numberActiveTouches; clearInteractionHandle( interactionState, config.onPanResponderEnd, - e, + event, gestureState, ); }, - onResponderTerminate: function(e) { + onResponderTerminate(event: PressEvent) { clearInteractionHandle( interactionState, config.onPanResponderTerminate, - e, + event, gestureState, ); PanResponder._initializeGestureState(gestureState); }, - onResponderTerminationRequest: function(e) { - return config.onPanResponderTerminationRequest === undefined + onResponderTerminationRequest(event: PressEvent) { + return config.onPanResponderTerminationRequest == null ? true - : config.onPanResponderTerminationRequest(e, gestureState); + : config.onPanResponderTerminationRequest(event, gestureState); }, }; return { @@ -439,9 +523,9 @@ const PanResponder = { function clearInteractionHandle( interactionState: {handle: ?number}, - callback: Function, - event: Object, - gestureState: Object, + callback: ?PanResponderCallback, + event: PressEvent, + gestureState: GestureState, ) { if (interactionState.handle) { InteractionManager.clearInteractionHandle(interactionState.handle); diff --git a/Libraries/Types/CoreEventTypes.js b/Libraries/Types/CoreEventTypes.js index 5e55adfb3b2946..5126063fa0bf09 100644 --- a/Libraries/Types/CoreEventTypes.js +++ b/Libraries/Types/CoreEventTypes.js @@ -26,6 +26,12 @@ export type SyntheticEvent = $ReadOnly<{| persist: () => void, target: ?number, timeStamp: number, + touchHistory: $ReadOnly<{| + indexOfSingleActiveTouch: number, + mostRecentTimeStamp: number, + numberActiveTouches: number, + touchBank: $ReadOnlyArray, + |}>, type: ?string, |}>; From 69c87f455305b56d1e2bff276658ebe58d09dab6 Mon Sep 17 00:00:00 2001 From: empyrical Date: Mon, 24 Sep 2018 11:40:20 -0600 Subject: [PATCH 2/4] Only show on Responder-related events --- Libraries/Types/CoreEventTypes.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Libraries/Types/CoreEventTypes.js b/Libraries/Types/CoreEventTypes.js index 5126063fa0bf09..5ae3580a256c6a 100644 --- a/Libraries/Types/CoreEventTypes.js +++ b/Libraries/Types/CoreEventTypes.js @@ -26,13 +26,17 @@ export type SyntheticEvent = $ReadOnly<{| persist: () => void, target: ?number, timeStamp: number, + type: ?string, +|}>; + +export type ResponderSyntheticEvent = $ReadOnly<{| + ...SyntheticEvent, touchHistory: $ReadOnly<{| indexOfSingleActiveTouch: number, mostRecentTimeStamp: number, numberActiveTouches: number, touchBank: $ReadOnlyArray, |}>, - type: ?string, |}>; export type Layout = $ReadOnly<{| @@ -63,7 +67,7 @@ export type TextLayoutEvent = SyntheticEvent< |}>, >; -export type PressEvent = SyntheticEvent< +export type PressEvent = ResponderSyntheticEvent< $ReadOnly<{| changedTouches: $ReadOnlyArray<$PropertyType>, force: number, From d0d348f4a3114170c9794997fee83200ee23b453 Mon Sep 17 00:00:00 2001 From: empyrical Date: Mon, 24 Sep 2018 19:08:56 -0600 Subject: [PATCH 3/4] Clean up and add more types --- Libraries/Interaction/PanResponder.js | 63 +++++++++++++++------------ Libraries/Types/CoreEventTypes.js | 15 ++++++- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/Libraries/Interaction/PanResponder.js b/Libraries/Interaction/PanResponder.js index 9e0560045d1c48..51b02d1d0bbcd7 100644 --- a/Libraries/Interaction/PanResponder.js +++ b/Libraries/Interaction/PanResponder.js @@ -171,25 +171,32 @@ export type GestureState = {| _accountsForMovesUpTo: number, |}; -type PanResponderCallback = ( +type ActiveCallback = ( event: PressEvent, gestureState: GestureState, -) => mixed; +) => boolean; + +type PassiveCallback = (event: PressEvent, gestureState: GestureState) => mixed; type PanResponderConfig = $ReadOnly<{| - onMoveShouldSetPanResponder?: ?PanResponderCallback, - onMoveShouldSetPanResponderCapture?: ?PanResponderCallback, - onStartShouldSetPanResponder?: ?PanResponderCallback, - onStartShouldSetPanResponderCapture?: ?PanResponderCallback, - onPanResponderReject?: ?PanResponderCallback, - onPanResponderGrant?: ?PanResponderCallback, - onPanResponderStart?: ?PanResponderCallback, - onPanResponderEnd?: ?PanResponderCallback, - onPanResponderRelease?: ?PanResponderCallback, - onPanResponderMove?: ?PanResponderCallback, - onPanResponderTerminate?: ?PanResponderCallback, - onPanResponderTerminationRequest?: ?PanResponderCallback, - onShouldBlockNativeResponder?: ?PanResponderCallback, + onMoveShouldSetPanResponder?: ?ActiveCallback, + onMoveShouldSetPanResponderCapture?: ?ActiveCallback, + onStartShouldSetPanResponder?: ?ActiveCallback, + onStartShouldSetPanResponderCapture?: ?ActiveCallback, + /** + * The body of `onResponderGrant` returns a bool, but the vast majority of + * callsites return void and this TODO notice is found in it: + * TODO: t7467124 investigate if this can be removed + */ + onPanResponderGrant?: ?(PassiveCallback | ActiveCallback), + onPanResponderReject?: ?PassiveCallback, + onPanResponderStart?: ?PassiveCallback, + onPanResponderEnd?: ?PassiveCallback, + onPanResponderRelease?: ?PassiveCallback, + onPanResponderMove?: ?PassiveCallback, + onPanResponderTerminate?: ?PassiveCallback, + onPanResponderTerminationRequest?: ?ActiveCallback, + onShouldBlockNativeResponder?: ?ActiveCallback, |}>; const PanResponder = { @@ -383,17 +390,17 @@ const PanResponder = { _accountsForMovesUpTo: 0, }; const panHandlers = { - onStartShouldSetResponder(event: PressEvent) { + onStartShouldSetResponder(event: PressEvent): boolean { return config.onStartShouldSetPanResponder == null ? false : config.onStartShouldSetPanResponder(event, gestureState); }, - onMoveShouldSetResponder(event: PressEvent) { + onMoveShouldSetResponder(event: PressEvent): boolean { return config.onMoveShouldSetPanResponder == null ? false : config.onMoveShouldSetPanResponder(event, gestureState); }, - onStartShouldSetResponderCapture(event: PressEvent) { + onStartShouldSetResponderCapture(event: PressEvent): boolean { // TODO: Actually, we should reinitialize the state any time // touches.length increases from 0 active to > 0 active. if (event.nativeEvent.touches.length === 1) { @@ -406,7 +413,7 @@ const PanResponder = { : false; }, - onMoveShouldSetResponderCapture(event: PressEvent) { + onMoveShouldSetResponderCapture(event: PressEvent): boolean { const touchHistory = event.touchHistory; // Responder system incorrectly dispatches should* to current responder // Filter out any touch moves past the first one - we would have @@ -423,7 +430,7 @@ const PanResponder = { : false; }, - onResponderGrant(event: PressEvent) { + onResponderGrant(event: PressEvent): boolean { if (!interactionState.handle) { interactionState.handle = InteractionManager.createInteractionHandle(); } @@ -440,7 +447,7 @@ const PanResponder = { : config.onShouldBlockNativeResponder(event, gestureState); }, - onResponderReject(event: PressEvent) { + onResponderReject(event: PressEvent): void { clearInteractionHandle( interactionState, config.onPanResponderReject, @@ -449,7 +456,7 @@ const PanResponder = { ); }, - onResponderRelease(event: PressEvent) { + onResponderRelease(event: PressEvent): void { clearInteractionHandle( interactionState, config.onPanResponderRelease, @@ -459,7 +466,7 @@ const PanResponder = { PanResponder._initializeGestureState(gestureState); }, - onResponderStart(event: PressEvent) { + onResponderStart(event: PressEvent): void { const touchHistory = event.touchHistory; gestureState.numberActiveTouches = touchHistory.numberActiveTouches; if (config.onPanResponderStart) { @@ -467,7 +474,7 @@ const PanResponder = { } }, - onResponderMove(event: PressEvent) { + onResponderMove(event: PressEvent): void { const touchHistory = event.touchHistory; // Guard against the dispatch of two touch moves when there are two // simultaneously changed touches. @@ -485,7 +492,7 @@ const PanResponder = { } }, - onResponderEnd(event: PressEvent) { + onResponderEnd(event: PressEvent): void { const touchHistory = event.touchHistory; gestureState.numberActiveTouches = touchHistory.numberActiveTouches; clearInteractionHandle( @@ -496,7 +503,7 @@ const PanResponder = { ); }, - onResponderTerminate(event: PressEvent) { + onResponderTerminate(event: PressEvent): void { clearInteractionHandle( interactionState, config.onPanResponderTerminate, @@ -506,7 +513,7 @@ const PanResponder = { PanResponder._initializeGestureState(gestureState); }, - onResponderTerminationRequest(event: PressEvent) { + onResponderTerminationRequest(event: PressEvent): boolean { return config.onPanResponderTerminationRequest == null ? true : config.onPanResponderTerminationRequest(event, gestureState); @@ -523,7 +530,7 @@ const PanResponder = { function clearInteractionHandle( interactionState: {handle: ?number}, - callback: ?PanResponderCallback, + callback: ?(ActiveCallback | PassiveCallback), event: PressEvent, gestureState: GestureState, ) { diff --git a/Libraries/Types/CoreEventTypes.js b/Libraries/Types/CoreEventTypes.js index 5ae3580a256c6a..1abd02571c2d3b 100644 --- a/Libraries/Types/CoreEventTypes.js +++ b/Libraries/Types/CoreEventTypes.js @@ -35,7 +35,20 @@ export type ResponderSyntheticEvent = $ReadOnly<{| indexOfSingleActiveTouch: number, mostRecentTimeStamp: number, numberActiveTouches: number, - touchBank: $ReadOnlyArray, + touchBank: $ReadOnlyArray< + $ReadOnly<{| + touchActive: boolean, + startPageX: number, + startPageY: number, + startTimeStamp: number, + currentPageX: number, + currentPageY: number, + currentTimeStamp: number, + previousPageX: number, + previousPageY: number, + previousTimeStamp: number, + |}>, + >, |}>, |}>; From c5095bfd5aa54a892581327bae4a2c10269979dd Mon Sep 17 00:00:00 2001 From: empyrical Date: Mon, 24 Sep 2018 22:48:23 -0600 Subject: [PATCH 4/4] Clean up documentation comments for GestureState --- Libraries/Interaction/PanResponder.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Libraries/Interaction/PanResponder.js b/Libraries/Interaction/PanResponder.js index 51b02d1d0bbcd7..3275b9afe36410 100644 --- a/Libraries/Interaction/PanResponder.js +++ b/Libraries/Interaction/PanResponder.js @@ -129,43 +129,55 @@ export type GestureState = {| * ID of the gestureState - persisted as long as there at least one touch on screen */ stateID: number, + /** * The latest screen coordinates of the recently-moved touch */ moveX: number, + /** * The latest screen coordinates of the recently-moved touch */ moveY: number, + /** * The screen coordinates of the responder grant */ x0: number, + /** * The screen coordinates of the responder grant */ y0: number, + /** * Accumulated distance of the gesture since the touch started */ dx: number, + /** * Accumulated distance of the gesture since the touch started */ dy: number, + /** * Current velocity of the gesture */ vx: number, + /** * Current velocity of the gesture */ vy: number, + /** * Number of touches currently on screen */ numberActiveTouches: number, + /** + * All `gestureState` accounts for timeStamps up until this value + * * @private */ _accountsForMovesUpTo: number,