Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 17 additions & 7 deletions packages/react-events/docs/Press.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Press

The `Press` module responds to press events on the element it wraps. Press
events are dispatched for `mouse`, `pen`, `touch`, and `keyboard` pointer types.
Press events are only dispatched for keyboards when pressing the Enter or
Spacebar keys. If neither `onPress` nor `onLongPress` are called, this signifies
that the press ended outside of the element hit bounds (i.e., the user aborted
the press).
events are dispatched for `mouse`, `pen`, `touch`, `trackpad`, and `keyboard`
pointer types. Press events are only dispatched for keyboards when pressing the
Enter or Spacebar keys. If neither `onPress` nor `onLongPress` are called, this
signifies that the press ended outside of the element hit bounds (i.e., the user
aborted the press).

Press events do not propagate between `Press` event responders.

Expand Down Expand Up @@ -37,9 +37,9 @@ const Button = (props) => (

```js
type PressEvent = {
pointerType: 'mouse' | 'touch' | 'pen' | 'keyboard',
pointerType: 'mouse' | 'touch' | 'pen' | 'trackpad' | 'keyboard',
target: Element,
type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange'
type: 'press' | 'pressstart' | 'pressend' | 'presschange' | 'pressmove' | 'longpress' | 'longpresschange' | 'contextmenu'
}

type PressOffset = {
Expand Down Expand Up @@ -71,6 +71,16 @@ released before the threshold is exceeded.

Disables all `Press` events.

### disableContextMenu: boolean = false

Disables the native context menu so that it is never shown and `onContextMenu`
is never called.

### onContextMenu: (e: PressEvent) => void

Called when the context menu is shown. When a press is active, the context menu
will only be shown (and the press cancelled) if `preventDefault` is `false`.

### onLongPress: (e: PressEvent) => void

Called once the element has been pressed for the length of `delayLongPress`. If
Expand Down
8 changes: 8 additions & 0 deletions packages/react-events/src/Press.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {DiscreteEvent, UserBlockingEvent} from 'shared/ReactTypes';

type PressProps = {
disabled: boolean,
disableContextMenu: boolean,
delayLongPress: number,
delayPressEnd: number,
delayPressStart: number,
Expand Down Expand Up @@ -727,6 +728,12 @@ const PressResponder = {
}

case 'contextmenu': {
if (props.disableContextMenu) {
// Skip dispatching of onContextMenu below
nativeEvent.preventDefault();
return;
}

if (isPressed) {
if (props.preventDefault !== false) {
// Skip dispatching of onContextMenu below
Expand All @@ -735,6 +742,7 @@ const PressResponder = {
}
dispatchCancel(event, context, props, state);
}

if (props.onContextMenu) {
dispatchEvent(
event,
Expand Down
16 changes: 16 additions & 0 deletions packages/react-events/src/__tests__/Press-test.internal.js
Original file line number Diff line number Diff line change
Expand Up @@ -2838,6 +2838,22 @@ describe('Event responder: Press', () => {
ref.current.dispatchEvent(createEvent('contextmenu'));
expect(onContextMenu).toHaveBeenCalledTimes(0);
});

it('is not called if "disableContextMenu" is true', () => {
const onContextMenu = jest.fn();
const ref = React.createRef();
const element = (
<Press disableContextMenu={true} onContextMenu={onContextMenu}>
<div ref={ref} />
</Press>
);
ReactDOM.render(element, container);
ref.current.dispatchEvent(
createEvent('pointerdown', {pointerType: 'mouse', button: 2}),
);
ref.current.dispatchEvent(createEvent('contextmenu'));
expect(onContextMenu).toHaveBeenCalledTimes(0);
});
});

it('should work correctly with stopPropagation set to true', () => {
Expand Down