[Flare] Press includes button type (#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.
Nicolas Gallagher committed
Jul 10, 2019 at 17:52 UTC
2073a7144e9982cc07cf7c19813e50b02c8bcd1b
2 files changed
+76
-6
packages/react-events/src/dom/Press.js
+13
-4
@@ -89,6 +89,7 @@ type PressEventType =
89
| 'contextmenu';
90
91
type PressEvent = {|
92
+ button: 'primary' | 'auxillary',
93
defaultPrevented: boolean,
94
target: Element | Document,
95
type: PressEventType,
@@ -165,6 +166,7 @@ function createPressEvent(
166
defaultPrevented: boolean,
167
): PressEvent {
168
const timeStamp = context.getTimeStamp();
169
+ let button = 'primary';
170
let clientX = null;
171
let clientY = null;
172
let pageX = null;
@@ -186,8 +188,12 @@ function createPressEvent(
188
if (eventObject) {
189
({clientX, clientY, pageX, pageY, screenX, screenY} = eventObject);
190
}
191
+ if (nativeEvent.button === 1) {
192
+ button = 'auxillary';
193
+ }
194
}
195
return {
196
+ button,
197
defaultPrevented,
198
target,
199
type,
@@ -706,11 +712,11 @@ const PressResponder: ReactDOMEventResponder = {
712
state.activePointerId = touchEvent.identifier;
713
}
714
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
717
// acts like right-click and opens the contextmenu.
718
if (
713
- nativeEvent.button > 0 ||
719
+ nativeEvent.button > 1 ||
720
(isMac && isMouseEvent && nativeEvent.ctrlKey)
721
) {
722
return;
@@ -962,7 +968,10 @@ const PressResponder: ReactDOMEventResponder = {
968
state,
969
);
970
}
965
- if (state.isPressWithinResponderRegion) {
971
+ if (
972
+ state.isPressWithinResponderRegion &&
973
+ nativeEvent.button !== 1
974
+ ) {
975
if (
976
!(
977
wasLongPressed &&
packages/react-events/src/dom/__tests__/Press-test.internal.js
+63
-2
@@ -136,6 +136,20 @@ describe('Event responder: Press', () => {
136
);
137
});
138
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
+
153
it('ignores browser emulated events', () => {
154
ref.current.dispatchEvent(createEvent('pointerdown'));
155
ref.current.dispatchEvent(createEvent('touchstart'));
@@ -143,8 +157,7 @@ describe('Event responder: Press', () => {
157
expect(onPressStart).toHaveBeenCalledTimes(1);
158
});
159
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', () => {
161
ref.current.dispatchEvent(createEvent('pointerdown', {button: 5}));
162
ref.current.dispatchEvent(createEvent('mousedown', {button: 2}));
163
expect(onPressStart).toHaveBeenCalledTimes(0);
@@ -330,6 +343,23 @@ describe('Event responder: Press', () => {
343
);
344
});
345
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
+
363
it('ignores browser emulated events', () => {
364
ref.current.dispatchEvent(
365
createEvent('pointerdown', {pointerType: 'touch'}),
@@ -664,6 +694,21 @@ describe('Event responder: Press', () => {
694
);
695
});
696
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
+
712
it('is called after valid "keyup" event', () => {
713
ref.current.dispatchEvent(createKeyboardEvent('keydown', {key: 'Enter'}));
714
ref.current.dispatchEvent(createKeyboardEvent('keyup', {key: 'Enter'}));
@@ -709,6 +754,22 @@ describe('Event responder: Press', () => {
754
expect(onPress).toHaveBeenCalledTimes(1);
755
});
756
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
+
773
// No PointerEvent fallbacks
774
// TODO: jsdom missing APIs
775
// it('is called after "touchend" event', () => {