From 2b23c17abb097f6fcbc750def33e5cb2735faf56 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 24 Apr 2019 00:50:16 +0100 Subject: [PATCH 1/5] Experimental event API: adds context.isTargetDirectlyWithinEventComponent --- .../src/events/DOMEventResponderSystem.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/react-dom/src/events/DOMEventResponderSystem.js b/packages/react-dom/src/events/DOMEventResponderSystem.js index 2e3da99145f..c7d8d84a79f 100644 --- a/packages/react-dom/src/events/DOMEventResponderSystem.js +++ b/packages/react-dom/src/events/DOMEventResponderSystem.js @@ -170,6 +170,22 @@ const eventResponderContext: ReactResponderContext = { } return false; }, + isTargetDirectlyWithinEventComponent(target: Element | Document): boolean { + validateResponderContext(); + if (target != null) { + let fiber = getClosestInstanceFromNode(target); + while (fiber !== null) { + if (fiber.stateNode === currentInstance) { + return true; + } + if (fiber.tag === EventComponent) { + return false; + } + fiber = fiber.return; + } + } + return false; + }, isTargetWithinElement( childTarget: Element | Document, parentTarget: Element | Document, From 6724f33a33e870d5809a87ec6c3436bd342f942a Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Tue, 23 Apr 2019 19:08:25 -0700 Subject: [PATCH 2/5] Unit test context.isTargetDirectlyWithinEventComponent --- .../DOMEventResponderSystem-test.internal.js | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js b/packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js index 8d476b4568c..f1555339573 100644 --- a/packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js +++ b/packages/react-dom/src/events/__tests__/DOMEventResponderSystem-test.internal.js @@ -917,4 +917,52 @@ describe('DOMEventResponderSystem', () => { }, ]); }); + + it('isTargetDirectlyWithinEventComponent works', () => { + const buttonRef = React.createRef(); + const divRef = React.createRef(); + const log = []; + + const EventComponent = createReactEventComponent( + ['pointerout'], + undefined, + undefined, + (event, context) => { + const isWithin = context.isTargetDirectlyWithinEventComponent( + event.nativeEvent.relatedTarget, + ); + log.push(isWithin); + }, + ); + + const Test = () => ( + +
+ + + + + ); + ReactDOM.render(, container); + + const createEvent = (type, data) => { + const event = document.createEvent('CustomEvent'); + event.initCustomEvent(type, true, true); + if (data != null) { + Object.entries(data).forEach(([key, value]) => { + event[key] = value; + }); + } + return event; + }; + + buttonRef.current.dispatchEvent( + createEvent('pointerout', {relatedTarget: divRef.current}), + ); + divRef.current.dispatchEvent( + createEvent('pointerout', {relatedTarget: buttonRef.current}), + ); + + expect(log).toEqual([false, true, false]); + }); }); From fedd285bbd56796db43ca848222bfad0e503f435 Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Tue, 23 Apr 2019 19:31:54 -0700 Subject: [PATCH 3/5] Fix expected behaviour of nested Hover responders --- packages/react-events/src/Hover.js | 4 ++-- .../react-events/src/__tests__/Hover-test.internal.js | 9 ++++----- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/react-events/src/Hover.js b/packages/react-events/src/Hover.js index 90b5a00883c..0f450a36a0a 100644 --- a/packages/react-events/src/Hover.js +++ b/packages/react-events/src/Hover.js @@ -99,7 +99,7 @@ function dispatchHoverStartEvents( if (event !== null) { const {nativeEvent} = event; if ( - context.isTargetWithinEventComponent((nativeEvent: any).relatedTarget) + context.isTargetDirectlyWithinEventComponent((nativeEvent: any).relatedTarget) ) { return; } @@ -156,7 +156,7 @@ function dispatchHoverEndEvents( if (event !== null) { const {nativeEvent} = event; if ( - context.isTargetWithinEventComponent((nativeEvent: any).relatedTarget) + context.isTargetDirectlyWithinEventComponent((nativeEvent: any).relatedTarget) ) { return; } diff --git a/packages/react-events/src/__tests__/Hover-test.internal.js b/packages/react-events/src/__tests__/Hover-test.internal.js index dc29723b659..b4f2303008c 100644 --- a/packages/react-events/src/__tests__/Hover-test.internal.js +++ b/packages/react-events/src/__tests__/Hover-test.internal.js @@ -443,18 +443,17 @@ describe('Hover event responder', () => { createPointerEvent('pointerover', {relatedTarget: innerRef.current}), ); outerRef.current.dispatchEvent(createPointerEvent('pointerout')); - // TODO: correct result should include commented events expect(events).toEqual([ 'outer: onHoverStart', 'outer: onHoverChange', - // 'outer: onHoverEnd', - // 'outer: onHoverChange', + 'outer: onHoverEnd', + 'outer: onHoverChange', 'inner: onHoverStart', 'inner: onHoverChange', 'inner: onHoverEnd', 'inner: onHoverChange', - // 'outer: onHoverStart', - // 'outer: onHoverChange', + 'outer: onHoverStart', + 'outer: onHoverChange', 'outer: onHoverEnd', 'outer: onHoverChange', ]); From 49a5291c477819c9dadd51827f9a8556eef9025e Mon Sep 17 00:00:00 2001 From: Nicolas Gallagher Date: Tue, 23 Apr 2019 19:41:16 -0700 Subject: [PATCH 4/5] Prettier --- packages/react-events/src/Hover.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/react-events/src/Hover.js b/packages/react-events/src/Hover.js index 0f450a36a0a..b18dc3610b3 100644 --- a/packages/react-events/src/Hover.js +++ b/packages/react-events/src/Hover.js @@ -99,7 +99,9 @@ function dispatchHoverStartEvents( if (event !== null) { const {nativeEvent} = event; if ( - context.isTargetDirectlyWithinEventComponent((nativeEvent: any).relatedTarget) + context.isTargetDirectlyWithinEventComponent( + (nativeEvent: any).relatedTarget, + ) ) { return; } @@ -156,7 +158,9 @@ function dispatchHoverEndEvents( if (event !== null) { const {nativeEvent} = event; if ( - context.isTargetDirectlyWithinEventComponent((nativeEvent: any).relatedTarget) + context.isTargetDirectlyWithinEventComponent( + (nativeEvent: any).relatedTarget, + ) ) { return; } From ccf27901edcfb48ea3376ff5e3078067513fb347 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Wed, 24 Apr 2019 10:42:51 +0100 Subject: [PATCH 5/5] Fix flow --- packages/shared/ReactTypes.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/shared/ReactTypes.js b/packages/shared/ReactTypes.js index d625733dfd3..8f1cd7c76e0 100644 --- a/packages/shared/ReactTypes.js +++ b/packages/shared/ReactTypes.js @@ -167,6 +167,7 @@ export type ReactResponderContext = { parentTarget: Element | Document, ) => boolean, isTargetWithinEventComponent: (Element | Document) => boolean, + isTargetDirectlyWithinEventComponent: (Element | Document) => boolean, isPositionWithinTouchHitTarget: ( doc: Document, x: number,