77 * @flow
88 */
99
10+ import type { TopLevelType } from 'legacy-events/TopLevelEventTypes' ;
1011import type { RootType } from './ReactDOMRoot' ;
1112
1213import {
@@ -84,6 +85,7 @@ import {
8485 attachTargetEventListener ,
8586} from '../events/DOMModernPluginEventSystem' ;
8687import { getListenerMapForElement } from '../events/DOMEventListenerMap' ;
88+ import { TOP_BEFORE_BLUR , TOP_AFTER_BLUR } from '../events/DOMTopLevelEventTypes' ;
8789
8890export type ReactListenerEvent = ReactDOMListenerEvent ;
8991export type ReactListenerMap = ReactDOMListenerMap ;
@@ -238,11 +240,11 @@ export function resetAfterCommit(containerInfo: Container): void {
238240 restoreSelection ( selectionInformation ) ;
239241 ReactBrowserEventEmitterSetEnabled ( eventsEnabled ) ;
240242 eventsEnabled = null ;
241- if ( enableDeprecatedFlareAPI ) {
243+ if ( enableDeprecatedFlareAPI || enableUseEventAPI ) {
242244 const activeElementDetached = ( selectionInformation : any )
243245 . activeElementDetached ;
244246 if ( activeElementDetached !== null ) {
245- dispatchDetachedBlur ( activeElementDetached ) ;
247+ dispatchAfterDetachedBlur ( activeElementDetached ) ;
246248 }
247249 }
248250 selectionInformation = null ;
@@ -490,34 +492,66 @@ export function insertInContainerBefore(
490492 }
491493}
492494
495+ function createEvent ( type : TopLevelType ) : Event {
496+ const event = document . createEvent ( 'Event' ) ;
497+ event . initEvent ( ( ( type : any ) : string ) , false , false ) ;
498+ return event ;
499+ }
500+
493501function dispatchBeforeDetachedBlur ( target : HTMLElement ) : void {
494502 const targetInstance = getClosestInstanceFromNode ( target ) ;
495503 ( ( selectionInformation : any ) : SelectionInformation ) . activeElementDetached = target ;
496504
497- DEPRECATED_dispatchEventForResponderEventSystem (
498- 'beforeblur' ,
499- targetInstance ,
500- ( {
505+ if ( enableDeprecatedFlareAPI ) {
506+ DEPRECATED_dispatchEventForResponderEventSystem (
507+ 'beforeblur' ,
508+ targetInstance ,
509+ ( {
510+ target,
511+ timeStamp : Date . now ( ) ,
512+ } : any ) ,
501513 target ,
502- timeStamp : Date . now ( ) ,
503- } : any ) ,
504- target ,
505- RESPONDER_EVENT_SYSTEM | IS_PASSIVE ,
506- ) ;
514+ RESPONDER_EVENT_SYSTEM | IS_PASSIVE ,
515+ ) ;
516+ }
517+ if ( enableUseEventAPI ) {
518+ try {
519+ // We need to temporarily enable the event system
520+ // to dispatch the "beforeblur" event.
521+ ReactBrowserEventEmitterSetEnabled ( true ) ;
522+ const event = createEvent ( TOP_BEFORE_BLUR ) ;
523+ // Dispatch "beforeblur" directly on the target,
524+ // so it gets picked up by the event system and
525+ // can propagate through the React internal tree.
526+ target . dispatchEvent ( event ) ;
527+ } finally {
528+ ReactBrowserEventEmitterSetEnabled ( false ) ;
529+ }
530+ }
507531}
508532
509- function dispatchDetachedBlur ( target : HTMLElement ) : void {
510- DEPRECATED_dispatchEventForResponderEventSystem (
511- 'blur ',
512- null ,
513- ( {
514- isTargetAttached : false ,
533+ function dispatchAfterDetachedBlur ( target : HTMLElement ) : void {
534+ if ( enableDeprecatedFlareAPI ) {
535+ DEPRECATED_dispatchEventForResponderEventSystem (
536+ 'blur' ,
537+ null ,
538+ ( {
539+ isTargetAttached : false ,
540+ target,
541+ timeStamp : Date . now ( ) ,
542+ } : any ) ,
515543 target ,
516- timeStamp : Date . now ( ) ,
517- } : any ) ,
518- target ,
519- RESPONDER_EVENT_SYSTEM | IS_PASSIVE ,
520- ) ;
544+ RESPONDER_EVENT_SYSTEM | IS_PASSIVE ,
545+ ) ;
546+ }
547+ if ( enableUseEventAPI ) {
548+ const event = createEvent ( TOP_AFTER_BLUR ) ;
549+ // So we know what was detached, make the relatedTarget the
550+ // detached target on the "afterblur" event.
551+ ( event : any ) . relatedTarget = target ;
552+ // Dispatch the event on the document.
553+ document . dispatchEvent ( event ) ;
554+ }
521555}
522556
523557// This is a specific event for the React Flare
@@ -528,7 +562,7 @@ export function beforeRemoveInstance(
528562 instance : Instance | TextInstance | SuspenseInstance ,
529563) : void {
530564 if (
531- enableDeprecatedFlareAPI &&
565+ ( enableDeprecatedFlareAPI || enableUseEventAPI ) &&
532566 selectionInformation &&
533567 instance === selectionInformation . focusedElem
534568 ) {
@@ -639,7 +673,7 @@ export function hideInstance(instance: Instance): void {
639673 // is ether the instance of a child or the instance. We need
640674 // to traverse the Fiber tree here rather than use node.contains()
641675 // as the child node might be inside a Portal.
642- if ( enableDeprecatedFlareAPI && selectionInformation ) {
676+ if ( ( enableDeprecatedFlareAPI || enableUseEventAPI ) && selectionInformation ) {
643677 const focusedElem = selectionInformation . focusedElem ;
644678 if ( focusedElem !== null && instanceContainsElem ( instance , focusedElem ) ) {
645679 dispatchBeforeDetachedBlur ( ( ( focusedElem : any ) : HTMLElement ) ) ;
0 commit comments