7
7
* @flow
8
8
*/
9
9
10
+ import type { TopLevelType } from 'legacy-events/TopLevelEventTypes' ;
10
11
import type { RootType } from './ReactDOMRoot' ;
11
12
12
13
import {
@@ -84,6 +85,7 @@ import {
84
85
attachTargetEventListener ,
85
86
} from '../events/DOMModernPluginEventSystem' ;
86
87
import { getListenerMapForElement } from '../events/DOMEventListenerMap' ;
88
+ import { TOP_BEFORE_BLUR , TOP_AFTER_BLUR } from '../events/DOMTopLevelEventTypes' ;
87
89
88
90
export type ReactListenerEvent = ReactDOMListenerEvent ;
89
91
export type ReactListenerMap = ReactDOMListenerMap ;
@@ -238,11 +240,11 @@ export function resetAfterCommit(containerInfo: Container): void {
238
240
restoreSelection ( selectionInformation ) ;
239
241
ReactBrowserEventEmitterSetEnabled ( eventsEnabled ) ;
240
242
eventsEnabled = null ;
241
- if ( enableDeprecatedFlareAPI ) {
243
+ if ( enableDeprecatedFlareAPI || enableUseEventAPI ) {
242
244
const activeElementDetached = ( selectionInformation : any )
243
245
. activeElementDetached ;
244
246
if ( activeElementDetached !== null ) {
245
- dispatchDetachedBlur ( activeElementDetached ) ;
247
+ dispatchAfterDetachedBlur ( activeElementDetached ) ;
246
248
}
247
249
}
248
250
selectionInformation = null ;
@@ -490,34 +492,66 @@ export function insertInContainerBefore(
490
492
}
491
493
}
492
494
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
+
493
501
function dispatchBeforeDetachedBlur ( target : HTMLElement ) : void {
494
502
const targetInstance = getClosestInstanceFromNode ( target ) ;
495
503
( ( selectionInformation : any ) : SelectionInformation ) . activeElementDetached = target ;
496
504
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 ) ,
501
513
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
+ }
507
531
}
508
532
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 ) ,
515
543
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
+ }
521
555
}
522
556
523
557
// This is a specific event for the React Flare
@@ -528,7 +562,7 @@ export function beforeRemoveInstance(
528
562
instance : Instance | TextInstance | SuspenseInstance ,
529
563
) : void {
530
564
if (
531
- enableDeprecatedFlareAPI &&
565
+ ( enableDeprecatedFlareAPI || enableUseEventAPI ) &&
532
566
selectionInformation &&
533
567
instance === selectionInformation . focusedElem
534
568
) {
@@ -639,7 +673,7 @@ export function hideInstance(instance: Instance): void {
639
673
// is ether the instance of a child or the instance. We need
640
674
// to traverse the Fiber tree here rather than use node.contains()
641
675
// as the child node might be inside a Portal.
642
- if ( enableDeprecatedFlareAPI && selectionInformation ) {
676
+ if ( ( enableDeprecatedFlareAPI || enableUseEventAPI ) && selectionInformation ) {
643
677
const focusedElem = selectionInformation . focusedElem ;
644
678
if ( focusedElem !== null && instanceContainsElem ( instance , focusedElem ) ) {
645
679
dispatchBeforeDetachedBlur ( ( ( focusedElem : any ) : HTMLElement ) ) ;
0 commit comments