diff --git a/packages/react-events/src/Focus.js b/packages/react-events/src/Focus.js index a5532a0667165..b45a0459afac4 100644 --- a/packages/react-events/src/Focus.js +++ b/packages/react-events/src/Focus.js @@ -116,10 +116,20 @@ const FocusResponder = { const shouldStopPropagation = props.stopPropagation === undefined ? true : props.stopPropagation; + if (props.disabled) { + if (state.isFocused) { + dispatchFocusOutEvents(context, props, state); + state.isFocused = false; + state.focusTarget = null; + } + return false; + } + // Focus doesn't handle capture target events at this point if (phase === CAPTURE_PHASE) { return false; } + switch (type) { case 'focus': { if (!state.isFocused) { diff --git a/packages/react-events/src/Hover.js b/packages/react-events/src/Hover.js index 4893adfd5319d..b8144a9ec288b 100644 --- a/packages/react-events/src/Hover.js +++ b/packages/react-events/src/Hover.js @@ -253,6 +253,17 @@ const HoverResponder = { ): boolean { const {type} = event; + if (props.disabled) { + if (state.isHovered) { + dispatchHoverEndEvents(event, context, props, state); + state.ignoreEmulatedMouseEvents = false; + } + if (state.isTouched) { + state.isTouched = false; + } + return false; + } + // Hover doesn't handle capture target events at this point if (event.phase === CAPTURE_PHASE) { return false; diff --git a/packages/react-events/src/Press.js b/packages/react-events/src/Press.js index 457d92e0840ed..eb83f6fb68023 100644 --- a/packages/react-events/src/Press.js +++ b/packages/react-events/src/Press.js @@ -408,6 +408,13 @@ const PressResponder = { ): boolean { const {phase, target, type} = event; + if (props.disabled) { + dispatchPressEndEvents(context, props, state); + context.removeRootEventTypes(rootEventTypes); + state.ignoreEmulatedMouseEvents = false; + return false; + } + // Press doesn't handle capture target events at this point if (phase === CAPTURE_PHASE) { return false; diff --git a/packages/react-events/src/__tests__/Focus-test.internal.js b/packages/react-events/src/__tests__/Focus-test.internal.js index 9e7131f7b6b2b..6c575e1add49f 100644 --- a/packages/react-events/src/__tests__/Focus-test.internal.js +++ b/packages/react-events/src/__tests__/Focus-test.internal.js @@ -40,6 +40,29 @@ describe('Focus event responder', () => { container = null; }); + describe('disabled', () => { + let onBlur, onFocus, ref; + + beforeEach(() => { + onBlur = jest.fn(); + onFocus = jest.fn(); + ref = React.createRef(); + const element = ( + +
+ + ); + ReactDOM.render(element, container); + }); + + it('prevents custom events being dispatched', () => { + ref.current.dispatchEvent(createFocusEvent('focus')); + ref.current.dispatchEvent(createFocusEvent('blur')); + expect(onFocus).not.toBeCalled(); + expect(onBlur).not.toBeCalled(); + }); + }); + describe('onBlur', () => { let onBlur, ref; diff --git a/packages/react-events/src/__tests__/Hover-test.internal.js b/packages/react-events/src/__tests__/Hover-test.internal.js index 6076807575bd6..dc29723b65917 100644 --- a/packages/react-events/src/__tests__/Hover-test.internal.js +++ b/packages/react-events/src/__tests__/Hover-test.internal.js @@ -45,6 +45,32 @@ describe('Hover event responder', () => { container = null; }); + describe('disabled', () => { + let onHoverStart, onHoverEnd, ref; + + beforeEach(() => { + onHoverStart = jest.fn(); + onHoverEnd = jest.fn(); + ref = React.createRef(); + const element = ( + +
+ + ); + ReactDOM.render(element, container); + }); + + it('prevents custom events being dispatched', () => { + ref.current.dispatchEvent(createPointerEvent('pointerover')); + ref.current.dispatchEvent(createPointerEvent('pointerout')); + expect(onHoverStart).not.toBeCalled(); + expect(onHoverEnd).not.toBeCalled(); + }); + }); + describe('onHoverStart', () => { let onHoverStart, ref; diff --git a/packages/react-events/src/__tests__/Press-test.internal.js b/packages/react-events/src/__tests__/Press-test.internal.js index 5f1684ad33adc..550ad95eee0fe 100644 --- a/packages/react-events/src/__tests__/Press-test.internal.js +++ b/packages/react-events/src/__tests__/Press-test.internal.js @@ -55,6 +55,35 @@ describe('Event responder: Press', () => { container = null; }); + describe('disabled', () => { + let onPressStart, onPress, onPressEnd, ref; + + beforeEach(() => { + onPressStart = jest.fn(); + onPress = jest.fn(); + onPressEnd = jest.fn(); + ref = React.createRef(); + const element = ( + +
+ + ); + ReactDOM.render(element, container); + }); + + it('prevents custom events being dispatched', () => { + ref.current.dispatchEvent(createPointerEvent('pointerdown')); + ref.current.dispatchEvent(createPointerEvent('pointerup')); + expect(onPressStart).not.toBeCalled(); + expect(onPress).not.toBeCalled(); + expect(onPressEnd).not.toBeCalled(); + }); + }); + describe('onPressStart', () => { let onPressStart, ref;