@samitouri / QOS-React-2 / commits / 6088a201e1

[Flare] Fix Press scroll cancellation handling (#15983)

Dominic Gannaway committed Jun 25, 2019 at 14:31 UTC 6088a201e12258a6d0e36dbb0d2208a57ec133ba
3 files changed +75 -2
packages/react-dom/src/events/DOMEventResponderSystem.js
+5 -1
@@ -1037,7 +1037,11 @@ export function dispatchEventForResponderEventSystem(
1037 const previouslyInHook = currentlyInHook;
1038 currentTimers = null;
1039 currentEventQueue = createEventQueue();
1040 - currentDocument = (nativeEventTarget: any).ownerDocument;
1040 + // nodeType 9 is DOCUMENT_NODE
1041 + currentDocument =
1042 + (nativeEventTarget: any).nodeType === 9
1043 + ? ((nativeEventTarget: any): Document)
1044 + : (nativeEventTarget: any).ownerDocument;
1045 // We might want to control timeStamp another way here
1046 currentTimeStamp = (nativeEvent: any).timeStamp;
1047 try {
packages/react-events/src/dom/Press.js
+16 -1
@@ -1002,8 +1002,23 @@ const PressResponder: ReactDOMEventResponder = {
1002 }
1003
1004 // CANCEL
1005 + case 'scroll': {
1006 + const pressTarget = state.pressTarget;
1007 + const scrollTarget = nativeEvent.target;
1008 + const doc = context.getActiveDocument();
1009 + // If the scroll target is the document or if the press target
1010 + // is inside the scroll target, then this a scroll that should
1011 + // trigger a cancel.
1012 + if (
1013 + pressTarget !== null &&
1014 + (scrollTarget === doc ||
1015 + context.isTargetWithinElement(pressTarget, scrollTarget))
1016 + ) {
1017 + dispatchCancel(event, context, props, state);
1018 + }
1019 + break;
1020 + }
1021 case 'pointercancel':
1006 - case 'scroll':
1022 case 'touchcancel':
1023 case 'dragstart': {
1024 dispatchCancel(event, context, props, state);
packages/react-events/src/dom/__tests__/Press-test.internal.js
+54
@@ -2458,6 +2458,60 @@ describe('Event responder: Press', () => {
2458 });
2459 });
2460
2461 + it('does end on "scroll" to document', () => {
2462 + const onPressEnd = jest.fn();
2463 + const ref = React.createRef();
2464 + const element = (
2465 + <div>
2466 + <Press onPressEnd={onPressEnd}>
2467 + <a href="#" ref={ref} />
2468 + </Press>
2469 + </div>
2470 + );
2471 + ReactDOM.render(element, container);
2472 +
2473 + ref.current.dispatchEvent(createEvent('pointerdown'));
2474 + document.dispatchEvent(createEvent('scroll'));
2475 + expect(onPressEnd).toHaveBeenCalledTimes(1);
2476 + });
2477 +
2478 + it('does end on "scroll" to a parent container', () => {
2479 + const onPressEnd = jest.fn();
2480 + const ref = React.createRef();
2481 + const containerRef = React.createRef();
2482 + const element = (
2483 + <div ref={containerRef}>
2484 + <Press onPressEnd={onPressEnd}>
2485 + <a href="#" ref={ref} />
2486 + </Press>
2487 + </div>
2488 + );
2489 + ReactDOM.render(element, container);
2490 +
2491 + ref.current.dispatchEvent(createEvent('pointerdown'));
2492 + containerRef.current.dispatchEvent(createEvent('scroll'));
2493 + expect(onPressEnd).toHaveBeenCalledTimes(1);
2494 + });
2495 +
2496 + it('does not end on "scroll" to an element outside', () => {
2497 + const onPressEnd = jest.fn();
2498 + const ref = React.createRef();
2499 + const outsideRef = React.createRef();
2500 + const element = (
2501 + <div>
2502 + <Press onPressEnd={onPressEnd}>
2503 + <a href="#" ref={ref} />
2504 + </Press>
2505 + <span ref={outsideRef} />
2506 + </div>
2507 + );
2508 + ReactDOM.render(element, container);
2509 +
2510 + ref.current.dispatchEvent(createEvent('pointerdown'));
2511 + outsideRef.current.dispatchEvent(createEvent('scroll'));
2512 + expect(onPressEnd).not.toBeCalled();
2513 + });
2514 +
2515 it('expect displayName to show up for event component', () => {
2516 expect(Press.responder.displayName).toBe('Press');
2517 });