diff --git a/packages/react-dom/src/client/ReactDOMHostConfig.js b/packages/react-dom/src/client/ReactDOMHostConfig.js index f3c83a7ffcb14..2d4d9ba109d3e 100644 --- a/packages/react-dom/src/client/ReactDOMHostConfig.js +++ b/packages/react-dom/src/client/ReactDOMHostConfig.js @@ -465,16 +465,17 @@ export function insertInContainerBefore( } } -function dispatchCustomFlareEvent( - type: string, +function dispatchFlareDetachedBlurEvent( + elementDetached: boolean, targetInstance: null | Object, target: Element | Document, ): void { // Simlulate the custom event to the React Flare responder system. dispatchEventForResponderEventSystem( - type, + 'blur', targetInstance, ({ + elementDetached, target, timeStamp: Date.now(), }: any), @@ -486,17 +487,13 @@ function dispatchCustomFlareEvent( function dispatchBeforeActiveElementBlur(element: HTMLElement): void { const targtInstance = getClosestInstanceFromNode(element); ((selectionInformation: any): SelectionInformation).blurredActiveElement = element; - dispatchCustomFlareEvent('beforeactiveelementblur', targtInstance, element); + dispatchFlareDetachedBlurEvent(false, targtInstance, element); } function dispatchActiveElementBlur( node: Instance | TextInstance | SuspenseInstance, ): void { - dispatchCustomFlareEvent( - 'activeelementblur', - null, - ((node: any): HTMLElement), - ); + dispatchFlareDetachedBlurEvent(true, null, ((node: any): HTMLElement)); } // This is a specific event for the React Flare diff --git a/packages/react-interactions/events/src/dom/Focus.js b/packages/react-interactions/events/src/dom/Focus.js index cc0da6e953029..9886011c66bf1 100644 --- a/packages/react-interactions/events/src/dom/Focus.js +++ b/packages/react-interactions/events/src/dom/Focus.js @@ -45,13 +45,7 @@ type FocusProps = { onFocusVisibleChange: boolean => void, }; -type FocusEventType = - | 'focus' - | 'blur' - | 'focuschange' - | 'focusvisiblechange' - | 'beforeactiveelementblur' - | 'activeelementblur'; +type FocusEventType = 'focus' | 'blur' | 'focuschange' | 'focusvisiblechange'; type FocusWithinProps = { disabled?: boolean, @@ -59,8 +53,8 @@ type FocusWithinProps = { onBlurWithin?: (e: FocusEvent) => void, onFocusWithinChange?: boolean => void, onFocusWithinVisibleChange?: boolean => void, - onBeforeActiveElementBlur?: (e: FocusEvent) => void, - onActiveElementBlur?: (e: FocusEvent) => void, + onBeforeFocusedElementDetached?: (e: FocusEvent) => void, + onFocusedElementDetached?: (e: FocusEvent) => void, }; type FocusWithinEventType = @@ -68,8 +62,8 @@ type FocusWithinEventType = | 'focuswithinchange' | 'blurwithin' | 'focuswithin' - | 'beforeactiveelementblur' - | 'activeelementblur'; + | 'focusedelementdetached' + | 'beforefocusedelementdetached'; /** * Shared between Focus and FocusWithin @@ -82,20 +76,13 @@ const isMac = ? /^Mac/.test(window.navigator.platform) : false; -const targetEventTypes = ['focus', 'blur', 'beforeactiveelementblur']; +const targetEventTypes = ['focus', 'blur']; const hasPointerEvents = typeof window !== 'undefined' && window.PointerEvent != null; const rootEventTypes = hasPointerEvents - ? [ - 'keydown', - 'keyup', - 'pointermove', - 'pointerdown', - 'pointerup', - 'activeelementblur', - ] + ? ['keydown', 'keyup', 'pointermove', 'pointerdown', 'pointerup', 'blur'] : [ 'keydown', 'keyup', @@ -103,7 +90,7 @@ const rootEventTypes = hasPointerEvents 'touchmove', 'touchstart', 'touchend', - 'activeelementblur', + 'blur', ]; function isFunction(obj): boolean { @@ -522,6 +509,23 @@ const focusWithinResponderImpl = { break; } case 'blur': { + if ((nativeEvent: any).elementDetached === false) { + const onBeforeFocusedElementDetached = (props.onBeforeFocusedElementDetached: any); + if (isFunction(onBeforeFocusedElementDetached)) { + const syntheticEvent = createFocusEvent( + context, + 'beforefocusedelementdetached', + event.target, + state.pointerType, + ); + context.dispatchEvent( + syntheticEvent, + onBeforeFocusedElementDetached, + DiscreteEvent, + ); + } + return; + } if ( state.isFocused && !context.isTargetWithinResponder(relatedTarget) @@ -532,22 +536,6 @@ const focusWithinResponderImpl = { } break; } - case 'beforeactiveelementblur': { - const onBeforeActiveElementBlur = (props.onBeforeActiveElementBlur: any); - if (isFunction(onBeforeActiveElementBlur)) { - const syntheticEvent = createFocusEvent( - context, - 'beforeactiveelementblur', - event.target, - state.pointerType, - ); - context.dispatchEvent( - syntheticEvent, - onBeforeActiveElementBlur, - DiscreteEvent, - ); - } - } } }, onRootEvent( @@ -556,18 +544,18 @@ const focusWithinResponderImpl = { props: FocusWithinProps, state: FocusState, ): void { - if (event.type === 'activeelementblur') { - const onActiveElementBlur = (props.onActiveElementBlur: any); - if (isFunction(onActiveElementBlur)) { + if ((event.nativeEvent: any).elementDetached === true) { + const onFocusedElementDetached = (props.onFocusedElementDetached: any); + if (isFunction(onFocusedElementDetached)) { const syntheticEvent = createFocusEvent( context, - 'activeelementblur', + 'focusedelementdetached', event.target, state.pointerType, ); context.dispatchEvent( syntheticEvent, - onActiveElementBlur, + onFocusedElementDetached, DiscreteEvent, ); } diff --git a/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js b/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js index 70aac0f36bad4..388bce20f2b27 100644 --- a/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js +++ b/packages/react-interactions/events/src/dom/__tests__/FocusWithin-test.internal.js @@ -262,16 +262,16 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => { }); }); - describe('onBeforeActiveElementBlur/onActiveElementBlur', () => { - let onBeforeActiveElementBlur, - onActiveElementBlur, + describe('onBeforeFocusedElementDetached/onFocusedElementDetached', () => { + let onBeforeFocusedElementDetached, + onFocusedElementDetached, ref, innerRef, innerRef2; beforeEach(() => { - onBeforeActiveElementBlur = jest.fn(); - onActiveElementBlur = jest.fn(); + onBeforeFocusedElementDetached = jest.fn(); + onFocusedElementDetached = jest.fn(); ref = React.createRef(); innerRef = React.createRef(); innerRef2 = React.createRef(); @@ -280,8 +280,8 @@ describe.each(table)('FocusWithin responder', hasPointerEvents => { it('is called after a focused element is unmounted', () => { const Component = ({show}) => { const listener = useFocusWithin({ - onBeforeActiveElementBlur, - onActiveElementBlur, + onBeforeFocusedElementDetached, + onFocusedElementDetached, }); return (