Skip to content

Commit

Permalink
[react-events] Tap responder (#16628)
Browse files Browse the repository at this point in the history
This is a partial replacement for the 'Press' responder:

1. `useTap` is scoped to pointers (no keyboard support). Our current thinking is
that "responders" should be limited to working with pointers, and that they can
be combined with 'useKeyboard' in user-space. For example, we might create a
'usePress' hook in user-space that combines 'useTap' with 'useKeyboard' to react
to both pointers and keyboard interactions.

2. `useTap` cancels the gesture once the pointer moves over an element that is
not within the responder target's subtree. This differs from `usePress` (and
React Native), where the gesture remains active after the pointer exits the
target's subtree and is restarted once the pointer reenters. One of the
drawbacks with the `usePress` behavior is that it requires repeatedly measuring
DOM elements (which can cause jank) to perform hit region tests. `useTap` avoids
doing this and relies on `document.elementFromPoint` only to support the
TouchEvent fallbacks.

3. `useTap` calls `onTapUpdate` when the active gesture's state changes,
`onTapEnd` when the gesture successfully completes. and `onTapCancel` when it
fails. There is no `onTap` callback. `usePress` did not explicitly report back
when the gesture failed, and product developers were confused about the
difference between `onPress` and `onPressEnd`.

4. `useTap` explicitly separates the PointerEvent implementation from the
MouseEvent/TouchEvent fallback.

5. `useTap` has better unit test coverage . All pointer types and the fallback
environment are tested. The shape of the gesture state object is also defined
and tested.
  • Loading branch information
necolas committed Sep 5, 2019
1 parent e86146e commit 9ce8711
Show file tree
Hide file tree
Showing 14 changed files with 1,470 additions and 42 deletions.
9 changes: 3 additions & 6 deletions packages/react-dom/src/events/DOMEventResponderSystem.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const eventResponderContext: ReactDOMResponderContext = {
}
}
},
isTargetWithinResponder(target: Element | Document): boolean {
isTargetWithinResponder(target: null | Element | Document): boolean {
validateResponderContext();
if (target != null) {
let fiber = getClosestInstanceFromNode(target);
Expand All @@ -135,7 +135,7 @@ const eventResponderContext: ReactDOMResponderContext = {
}
return false;
},
isTargetWithinResponderScope(target: Element | Document): boolean {
isTargetWithinResponderScope(target: null | Element | Document): boolean {
validateResponderContext();
const componentInstance = ((currentInstance: any): ReactDOMEventResponderInstance);
const responder = componentInstance.responder;
Expand All @@ -158,7 +158,7 @@ const eventResponderContext: ReactDOMResponderContext = {
return false;
},
isTargetWithinNode(
childTarget: Element | Document,
childTarget: null | Element | Document,
parentTarget: Element | Document,
): boolean {
validateResponderContext();
Expand Down Expand Up @@ -390,11 +390,9 @@ function createDOMResponderEvent(
): ReactDOMResponderEvent {
const {buttons, pointerType} = (nativeEvent: any);
let eventPointerType = '';
let pointerId = null;

if (pointerType !== undefined) {
eventPointerType = pointerType;
pointerId = (nativeEvent: any).pointerId;
} else if (nativeEvent.key !== undefined) {
eventPointerType = 'keyboard';
} else if (buttons !== undefined) {
Expand All @@ -407,7 +405,6 @@ function createDOMResponderEvent(
nativeEvent: nativeEvent,
passive,
passiveSupported,
pointerId,
pointerType: eventPointerType,
target: nativeEventTarget,
type: topLevelType,
Expand Down
7 changes: 7 additions & 0 deletions packages/react-events/npm/tap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-events-tap.production.min.js');
} else {
module.exports = require('./cjs/react-events-tap.development.js');
}
1 change: 1 addition & 0 deletions packages/react-events/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"press.js",
"scroll.js",
"swipe.js",
"tap.js",
"build-info.json",
"cjs/",
"umd/"
Expand Down
16 changes: 11 additions & 5 deletions packages/react-events/src/dom/Press.js
Original file line number Diff line number Diff line change
Expand Up @@ -521,7 +521,7 @@ const pressResponderImpl = {
props: PressProps,
state: PressState,
): void {
const {pointerId, pointerType, type} = event;
const {pointerType, type} = event;
if (props.disabled) {
removeRootEventTypes(context, state);
Expand Down Expand Up @@ -584,7 +584,7 @@ const pressResponderImpl = {
state.pointerType = pointerType;
const pressTarget = (state.pressTarget = context.getResponderNode());
if (isPointerEvent) {
state.activePointerId = pointerId;
state.activePointerId = nativeEvent.pointerId;
} else if (isTouchEvent) {
const touchEvent = getTouchFromPressEvent(nativeEvent);
if (touchEvent === null) {
Expand Down Expand Up @@ -652,7 +652,7 @@ const pressResponderImpl = {
props: PressProps,
state: PressState,
): void {
let {pointerId, pointerType, target, type} = event;
let {pointerType, target, type} = event;
const nativeEvent: any = event.nativeEvent;
const isPressed = state.isPressed;
Expand All @@ -672,7 +672,10 @@ const pressResponderImpl = {
if (previousPointerType !== pointerType) {
return;
}
if (type === 'pointermove' && activePointerId !== pointerId) {
if (
type === 'pointermove' &&
activePointerId !== nativeEvent.pointerId
) {
return;
} else if (type === 'touchmove') {
touchEvent = getTouchById(nativeEvent, activePointerId);
Expand Down Expand Up @@ -733,7 +736,10 @@ const pressResponderImpl = {
const buttons = state.buttons;
let isKeyboardEvent = false;
let touchEvent;
if (type === 'pointerup' && activePointerId !== pointerId) {
if (
type === 'pointerup' &&
activePointerId !== nativeEvent.pointerId
) {
return;
} else if (type === 'touchend') {
touchEvent = getTouchById(nativeEvent, activePointerId);
Expand Down
Loading

0 comments on commit 9ce8711

Please sign in to comment.