@samitouri / QOS-React / commits / a29a273c17

[react-interactions] Ensure blur to window disengages press (#18125)

Dominic Gannaway committed Feb 25, 2020 at 14:14 UTC a29a273c17d069f3bc89c8a71dc90da4dafe544e
2 files changed +40
packages/react-interactions/events/src/dom/PressLegacy.js
+17
@@ -126,6 +126,7 @@ const rootEventTypes = hasPointerEvents
126 'click',
127 'keyup',
128 'scroll',
129 + 'blur',
130 ]
131 : [
132 'click',
@@ -138,6 +139,7 @@ const rootEventTypes = hasPointerEvents
139 'dragstart',
140 'mouseup_active',
141 'touchend',
142 + 'blur',
143 ];
144
145 function isFunction(obj): boolean {
@@ -881,6 +883,21 @@ const pressResponderImpl = {
883 case 'touchcancel':
884 case 'dragstart': {
885 dispatchCancel(event, context, props, state);
886 + break;
887 + }
888 + case 'blur': {
889 + // If we encounter a blur event that moves focus to
890 + // the window, then the relatedTarget will be null.
891 + // In this case, we should cancel the active press.
892 + // Alternatively, if the blur target matches the
893 + // current pressed target, we should also cancel
894 + // the active press.
895 + if (
896 + isPressed &&
897 + (nativeEvent.relatedTarget === null || target === state.pressTarget)
898 + ) {
899 + dispatchCancel(event, context, props, state);
900 + }
901 }
902 }
903 },
packages/react-interactions/events/src/dom/__tests__/PressLegacy-test.internal.js
+23
@@ -1167,4 +1167,27 @@ describe.each(environmentTable)('Press responder', hasPointerEvents => {
1167 expect(onPressStart).toBeCalled();
1168 expect(onPressEnd).toBeCalled();
1169 });
1170 +
1171 + it('focus moving to the window should stop the press', () => {
1172 + const onPress = jest.fn(e => e.preventDefault());
1173 + const onPressStart = jest.fn(e => e.preventDefault());
1174 + const onPressEnd = jest.fn(e => e.preventDefault());
1175 + const buttonRef = React.createRef();
1176 +
1177 + const Component = () => {
1178 + const listener = usePress({onPress, onPressStart, onPressEnd});
1179 + return <button ref={buttonRef} DEPRECATED_flareListeners={listener} />;
1180 + };
1181 + ReactDOM.render(<Component />, container);
1182 +
1183 + const target = createEventTarget(buttonRef.current);
1184 + target.pointerdown();
1185 + const secondTarget = createEventTarget(document);
1186 + // relatedTarget is null when moving focus to window
1187 + expect(onPressStart).toBeCalled();
1188 + secondTarget.blur({relatedTarget: null});
1189 + expect(onPressEnd).toBeCalled();
1190 + target.pointerup();
1191 + expect(onPress).not.toBeCalled();
1192 + });
1193 });