Skip to content

Commit 2073a71

Browse files
authored
[Flare] Press includes button type (facebook#16100)
1. Allow auxillary button clicks (i.e., middle mouse button) to trigger 'onPressStart' and 'onPressEnd', but never 'onPress'. 2. Report the button type – 'primary' or 'auxillary' – on the press event.
1 parent 23b8a25 commit 2073a71

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

packages/react-events/src/dom/Press.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ type PressEventType =
8989
| 'contextmenu';
9090

9191
type PressEvent = {|
92+
button: 'primary' | 'auxillary',
9293
defaultPrevented: boolean,
9394
target: Element | Document,
9495
type: PressEventType,
@@ -165,6 +166,7 @@ function createPressEvent(
165166
defaultPrevented: boolean,
166167
): PressEvent {
167168
const timeStamp = context.getTimeStamp();
169+
let button = 'primary';
168170
let clientX = null;
169171
let clientY = null;
170172
let pageX = null;
@@ -186,8 +188,12 @@ function createPressEvent(
186188
if (eventObject) {
187189
({clientX, clientY, pageX, pageY, screenX, screenY} = eventObject);
188190
}
191+
if (nativeEvent.button === 1) {
192+
button = 'auxillary';
193+
}
189194
}
190195
return {
196+
button,
191197
defaultPrevented,
192198
target,
193199
type,
@@ -706,11 +712,11 @@ const PressResponder: ReactDOMEventResponder = {
706712
state.activePointerId = touchEvent.identifier;
707713
}
708714

709-
// Ignore any device buttons except left-mouse and touch/pen contact.
710-
// Additionally we ignore left-mouse + ctrl-key with Macs as that
715+
// Ignore any device buttons except primary/auxillary and touch/pen contact.
716+
// Additionally we ignore primary-button + ctrl-key with Macs as that
711717
// acts like right-click and opens the contextmenu.
712718
if (
713-
nativeEvent.button > 0 ||
719+
nativeEvent.button > 1 ||
714720
(isMac && isMouseEvent && nativeEvent.ctrlKey)
715721
) {
716722
return;
@@ -962,7 +968,10 @@ const PressResponder: ReactDOMEventResponder = {
962968
state,
963969
);
964970
}
965-
if (state.isPressWithinResponderRegion) {
971+
if (
972+
state.isPressWithinResponderRegion &&
973+
nativeEvent.button !== 1
974+
) {
966975
if (
967976
!(
968977
wasLongPressed &&

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

Lines changed: 63 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,28 @@ describe('Event responder: Press', () => {
136136
);
137137
});
138138

139+
it('is called after auxillary-button "pointerdown" event', () => {
140+
ref.current.dispatchEvent(
141+
createEvent('pointerdown', {button: 1, pointerType: 'mouse'}),
142+
);
143+
expect(onPressStart).toHaveBeenCalledTimes(1);
144+
expect(onPressStart).toHaveBeenCalledWith(
145+
expect.objectContaining({
146+
button: 'auxillary',
147+
pointerType: 'mouse',
148+
type: 'pressstart',
149+
}),
150+
);
151+
});
152+
139153
it('ignores browser emulated events', () => {
140154
ref.current.dispatchEvent(createEvent('pointerdown'));
141155
ref.current.dispatchEvent(createEvent('touchstart'));
142156
ref.current.dispatchEvent(createEvent('mousedown'));
143157
expect(onPressStart).toHaveBeenCalledTimes(1);
144158
});
145159

146-
it('ignores any events not caused by left-click or touch/pen contact', () => {
147-
ref.current.dispatchEvent(createEvent('pointerdown', {button: 1}));
160+
it('ignores any events not caused by primary/auxillary-click or touch/pen contact', () => {
148161
ref.current.dispatchEvent(createEvent('pointerdown', {button: 5}));
149162
ref.current.dispatchEvent(createEvent('mousedown', {button: 2}));
150163
expect(onPressStart).toHaveBeenCalledTimes(0);
@@ -330,6 +343,23 @@ describe('Event responder: Press', () => {
330343
);
331344
});
332345

346+
it('is called after auxillary-button "pointerup" event', () => {
347+
ref.current.dispatchEvent(
348+
createEvent('pointerdown', {button: 1, pointerType: 'mouse'}),
349+
);
350+
ref.current.dispatchEvent(
351+
createEvent('pointerup', {button: 1, pointerType: 'mouse'}),
352+
);
353+
expect(onPressEnd).toHaveBeenCalledTimes(1);
354+
expect(onPressEnd).toHaveBeenCalledWith(
355+
expect.objectContaining({
356+
button: 'auxillary',
357+
pointerType: 'mouse',
358+
type: 'pressend',
359+
}),
360+
);
361+
});
362+
333363
it('ignores browser emulated events', () => {
334364
ref.current.dispatchEvent(
335365
createEvent('pointerdown', {pointerType: 'touch'}),
@@ -664,6 +694,21 @@ describe('Event responder: Press', () => {
664694
);
665695
});
666696

697+
it('is not called after auxillary-button press', () => {
698+
const element = (
699+
<Press onPress={onPress}>
700+
<div ref={ref} />
701+
</Press>
702+
);
703+
ReactDOM.render(element, container);
704+
705+
ref.current.dispatchEvent(createEvent('pointerdown', {button: 1}));
706+
ref.current.dispatchEvent(
707+
createEvent('pointerup', {button: 1, clientX: 10, clientY: 10}),
708+
);
709+
expect(onPress).not.toHaveBeenCalled();
710+
});
711+
667712
it('is called after valid "keyup" event', () => {
668713
ref.current.dispatchEvent(createKeyboardEvent('keydown', {key: 'Enter'}));
669714
ref.current.dispatchEvent(createKeyboardEvent('keyup', {key: 'Enter'}));
@@ -709,6 +754,22 @@ describe('Event responder: Press', () => {
709754
expect(onPress).toHaveBeenCalledTimes(1);
710755
});
711756

757+
it('is called with modifier keys', () => {
758+
ref.current.dispatchEvent(
759+
createEvent('pointerdown', {metaKey: true, pointerType: 'mouse'}),
760+
);
761+
ref.current.dispatchEvent(
762+
createEvent('pointerup', {metaKey: true, pointerType: 'mouse'}),
763+
);
764+
expect(onPress).toHaveBeenCalledWith(
765+
expect.objectContaining({
766+
pointerType: 'mouse',
767+
type: 'press',
768+
metaKey: true,
769+
}),
770+
);
771+
});
772+
712773
// No PointerEvent fallbacks
713774
// TODO: jsdom missing APIs
714775
// it('is called after "touchend" event', () => {

0 commit comments

Comments
 (0)