[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
});