@samitouri / QOS-React-2 / commits / 2073a7144e

[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', () => {