Skip to content

Commit 296c439

Browse files
necolastrueadm
authored andcommitted
Add Press event prop types and fix a check in Safari (#15288)
* Add PressProps type to event module * Move default Press event delays to constants * Fix right-click press check for Safari * Prettier and Linter * Use event.key in press responder event.keyCode is a deprecated API * Remove unused props from Press event module
1 parent 4482fdd commit 296c439

File tree

2 files changed

+55
-20
lines changed

2 files changed

+55
-20
lines changed

packages/react-events/src/Press.js

+54-18
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
import type {EventResponderContext} from 'events/EventTypes';
1111
import {REACT_EVENT_COMPONENT_TYPE} from 'shared/ReactSymbols';
1212

13+
// const DEFAULT_PRESS_DELAY_MS = 0;
14+
// const DEFAULT_PRESS_END_DELAY_MS = 0;
15+
// const DEFAULT_PRESS_START_DELAY_MS = 0;
16+
const DEFAULT_LONG_PRESS_DELAY_MS = 1000;
17+
1318
const targetEventTypes = [
1419
{name: 'click', passive: false},
1520
{name: 'keydown', passive: false},
@@ -26,6 +31,21 @@ if (typeof window !== 'undefined' && window.PointerEvent === undefined) {
2631
rootEventTypes.push({name: 'mouseup', passive: false});
2732
}
2833

34+
type PressProps = {
35+
disabled: boolean,
36+
delayLongPress: number,
37+
delayPressEnd: number,
38+
delayPressStart: number,
39+
onLongPress: (e: Object) => void,
40+
onLongPressChange: boolean => void,
41+
onLongPressShouldCancelPress: () => boolean,
42+
onPress: (e: Object) => void,
43+
onPressChange: boolean => void,
44+
onPressEnd: (e: Object) => void,
45+
onPressStart: (e: Object) => void,
46+
pressRententionOffset: Object,
47+
};
48+
2949
type PressState = {
3050
defaultPrevented: boolean,
3151
isAnchorTouched: boolean,
@@ -47,7 +67,7 @@ function dispatchPressEvent(
4767

4868
function dispatchPressStartEvents(
4969
context: EventResponderContext,
50-
props: Object,
70+
props: PressProps,
5171
state: PressState,
5272
): void {
5373
function dispatchPressChangeEvent(bool) {
@@ -64,7 +84,11 @@ function dispatchPressStartEvents(
6484
dispatchPressChangeEvent(true);
6585
}
6686
if ((props.onLongPress || props.onLongPressChange) && !state.isLongPressed) {
67-
const delayLongPress = calculateDelayMS(props.delayLongPress, 0, 1000);
87+
const delayLongPress = calculateDelayMS(
88+
props.delayLongPress,
89+
0,
90+
DEFAULT_LONG_PRESS_DELAY_MS,
91+
);
6892

6993
state.longPressTimeout = setTimeout(() => {
7094
state.isLongPressed = true;
@@ -105,7 +129,7 @@ function dispatchPressStartEvents(
105129

106130
function dispatchPressEndEvents(
107131
context: EventResponderContext,
108-
props: Object,
132+
props: PressProps,
109133
state: PressState,
110134
): void {
111135
if (state.longPressTimeout !== null) {
@@ -138,6 +162,11 @@ function isAnchorTagElement(eventTarget: EventTarget): boolean {
138162
return (eventTarget: any).nodeName === 'A';
139163
}
140164

165+
function isValidKeyPress(key: string): boolean {
166+
// Accessibility for keyboards. Space and Enter only.
167+
return key === ' ' || key === 'Enter';
168+
}
169+
141170
function calculateDelayMS(delay: ?number, min = 0, fallback = 0) {
142171
const maybeNumber = delay == null ? null : delay;
143172
return Math.max(min, maybeNumber != null ? maybeNumber : fallback);
@@ -158,22 +187,18 @@ const PressResponder = {
158187
},
159188
handleEvent(
160189
context: EventResponderContext,
161-
props: Object,
190+
props: PressProps,
162191
state: PressState,
163192
): void {
164193
const {eventTarget, eventType, event} = context;
165194

166195
switch (eventType) {
167196
case 'keydown': {
168-
if (!props.onPress || context.isTargetOwned(eventTarget)) {
169-
return;
170-
}
171-
const isValidKeyPress =
172-
(event: any).which === 13 ||
173-
(event: any).which === 32 ||
174-
(event: any).keyCode === 13;
175-
176-
if (!isValidKeyPress) {
197+
if (
198+
!props.onPress ||
199+
context.isTargetOwned(eventTarget) ||
200+
!isValidKeyPress((event: any).key)
201+
) {
177202
return;
178203
}
179204
let keyPressEventListener = props.onPress;
@@ -196,8 +221,12 @@ const PressResponder = {
196221
dispatchPressEvent(context, state, 'press', keyPressEventListener);
197222
break;
198223
}
224+
225+
/**
226+
* Touch event implementations are only needed for Safari, which lacks
227+
* support for pointer events.
228+
*/
199229
case 'touchstart':
200-
// Touch events are for Safari, which lack pointer event support.
201230
if (!state.isPressed && !context.isTargetOwned(eventTarget)) {
202231
// We bail out of polyfilling anchor tags, given the same heuristics
203232
// explained above in regards to needing to use click events.
@@ -213,7 +242,6 @@ const PressResponder = {
213242

214243
break;
215244
case 'touchend': {
216-
// Touch events are for Safari, which lack pointer event support
217245
if (state.isAnchorTouched) {
218246
return;
219247
}
@@ -253,14 +281,21 @@ const PressResponder = {
253281
}
254282
break;
255283
}
284+
285+
/**
286+
* Respond to pointer events and fall back to mouse.
287+
*/
256288
case 'pointerdown':
257289
case 'mousedown': {
258290
if (
259291
!state.isPressed &&
260292
!context.isTargetOwned(eventTarget) &&
261293
!state.shouldSkipMouseAfterTouch
262294
) {
263-
if ((event: any).pointerType === 'mouse') {
295+
if (
296+
(event: any).pointerType === 'mouse' ||
297+
eventType === 'mousedown'
298+
) {
264299
// Ignore if we are pressing on hit slop area with mouse
265300
if (
266301
context.isPositionWithinTouchHitTarget(
@@ -282,8 +317,8 @@ const PressResponder = {
282317
}
283318
break;
284319
}
285-
case 'mouseup':
286-
case 'pointerup': {
320+
case 'pointerup':
321+
case 'mouseup': {
287322
if (state.isPressed) {
288323
if (state.shouldSkipMouseAfterTouch) {
289324
state.shouldSkipMouseAfterTouch = false;
@@ -320,6 +355,7 @@ const PressResponder = {
320355
state.isAnchorTouched = false;
321356
break;
322357
}
358+
323359
case 'scroll':
324360
case 'touchcancel':
325361
case 'contextmenu':

packages/react-events/src/__tests__/Press-test.internal.js

+1-2
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,7 @@ describe('Press event responder', () => {
8383

8484
events = [];
8585
const keyDownEvent = new KeyboardEvent('keydown', {
86-
which: 13,
87-
keyCode: 13,
86+
key: 'Enter',
8887
bubbles: true,
8988
cancelable: true,
9089
});

0 commit comments

Comments
 (0)