diff --git a/packages/react-dom/src/events/DOMEventResponderSystem.js b/packages/react-dom/src/events/DOMEventResponderSystem.js index f68a682d3227..a318f90ab2ce 100644 --- a/packages/react-dom/src/events/DOMEventResponderSystem.js +++ b/packages/react-dom/src/events/DOMEventResponderSystem.js @@ -234,10 +234,11 @@ const eventResponderContext: ReactDOMResponderContext = { validateResponderContext(); const childFiber = getClosestInstanceFromNode(childTarget); const parentFiber = getClosestInstanceFromNode(parentTarget); + const parentAlternateFiber = parentFiber.alternate; let node = childFiber; while (node !== null) { - if (node === parentFiber) { + if (node === parentFiber || node === parentAlternateFiber) { return true; } node = node.return; diff --git a/packages/react-events/src/dom/Press.js b/packages/react-events/src/dom/Press.js index f92b926c88d9..dcffeaa7e1ec 100644 --- a/packages/react-events/src/dom/Press.js +++ b/packages/react-events/src/dom/Press.js @@ -837,20 +837,22 @@ const PressResponder: ReactDOMEventResponder = { } const pressTarget = state.pressTarget; - if ( - pressTarget !== null && - !targetIsDocument(pressTarget) && - (pointerType !== 'mouse' || - !context.isTargetWithinNode(target, pressTarget)) - ) { - // Calculate the responder region we use for deactivation, as the - // element dimensions may have changed since activation. - updateIsPressWithinResponderRegion( - touchEvent || nativeEvent, - context, - props, - state, - ); + if (pressTarget !== null && !targetIsDocument(pressTarget)) { + if ( + pointerType === 'mouse' && + context.isTargetWithinNode(target, pressTarget) + ) { + state.isPressWithinResponderRegion = true; + } else { + // Calculate the responder region we use for deactivation, as the + // element dimensions may have changed since activation. + updateIsPressWithinResponderRegion( + touchEvent || nativeEvent, + context, + props, + state, + ); + } } if (state.isPressWithinResponderRegion) { @@ -958,19 +960,24 @@ const PressResponder: ReactDOMEventResponder = { if ( !isKeyboardEvent && pressTarget !== null && - !targetIsDocument(pressTarget) && - (pointerType !== 'mouse' || - !context.isTargetWithinNode(target, pressTarget)) + !targetIsDocument(pressTarget) ) { - // If the event target isn't within the press target, check if we're still - // within the responder region. The region may have changed if the - // element's layout was modified after activation. - updateIsPressWithinResponderRegion( - touchEvent || nativeEvent, - context, - props, - state, - ); + if ( + pointerType === 'mouse' && + context.isTargetWithinNode(target, pressTarget) + ) { + state.isPressWithinResponderRegion = true; + } else { + // If the event target isn't within the press target, check if we're still + // within the responder region. The region may have changed if the + // element's layout was modified after activation. + updateIsPressWithinResponderRegion( + touchEvent || nativeEvent, + context, + props, + state, + ); + } } if (state.isPressWithinResponderRegion && button !== 1) { if ( diff --git a/packages/react-events/src/dom/__tests__/Press-test.internal.js b/packages/react-events/src/dom/__tests__/Press-test.internal.js index f5f2f7db4f31..91020fa96fb9 100644 --- a/packages/react-events/src/dom/__tests__/Press-test.internal.js +++ b/packages/react-events/src/dom/__tests__/Press-test.internal.js @@ -812,6 +812,32 @@ describe('Event responder: Press', () => { ); }); + it('is called if target rect is not right but the target is (for mouse events)', () => { + const buttonRef = React.createRef(); + const divRef = React.createRef(); + const element = ( + +
+
+
+ ); + ReactDOM.render(element, container); + divRef.current.getBoundingClientRect = () => ({ + left: 0, + right: 0, + bottom: 0, + top: 0, + }); + buttonRef.current.dispatchEvent( + createEvent('pointerdown', {pointerType: 'mouse'}), + ); + buttonRef.current.dispatchEvent( + createEvent('pointerup', {pointerType: 'mouse'}), + ); + expect(onPress).toBeCalled(); + }); + // No PointerEvent fallbacks // TODO: jsdom missing APIs // it('is called after "touchend" event', () => {