@@ -22,6 +22,7 @@ type FocusProps = {
2222
2323type FocusState = {
2424 isFocused : boolean ,
25+ focusTarget : null | Element | Document ,
2526} ;
2627
2728type FocusEventType = 'focus' | 'blur' | 'focuschange' ;
@@ -47,54 +48,87 @@ function createFocusEvent(
4748}
4849
4950function dispatchFocusInEvents (
50- event : ReactResponderEvent ,
51+ event : null | ReactResponderEvent ,
5152 context : ReactResponderContext ,
5253 props : FocusProps ,
54+ state : FocusState ,
5355) {
54- const { nativeEvent, target} = event ;
55- if ( context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget ) ) {
56- return ;
56+ if ( event != null ) {
57+ const { nativeEvent} = event ;
58+ if (
59+ context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget )
60+ ) {
61+ return ;
62+ }
5763 }
5864 if ( props . onFocus ) {
59- const syntheticEvent = createFocusEvent ( 'focus' , target ) ;
65+ const syntheticEvent = createFocusEvent (
66+ 'focus' ,
67+ ( ( state . focusTarget : any ) : Element | Document ) ,
68+ ) ;
6069 context . dispatchEvent ( syntheticEvent , props . onFocus , { discrete : true } ) ;
6170 }
6271 if ( props . onFocusChange ) {
6372 const listener = ( ) => {
6473 props . onFocusChange ( true ) ;
6574 } ;
66- const syntheticEvent = createFocusEvent ( 'focuschange' , target ) ;
75+ const syntheticEvent = createFocusEvent (
76+ 'focuschange' ,
77+ ( ( state . focusTarget : any ) : Element | Document ) ,
78+ ) ;
6779 context . dispatchEvent ( syntheticEvent , listener , { discrete : true } ) ;
6880 }
6981}
7082
7183function dispatchFocusOutEvents (
72- event : ReactResponderEvent ,
84+ event : null | ReactResponderEvent ,
7385 context : ReactResponderContext ,
7486 props : FocusProps ,
87+ state : FocusState ,
7588) {
76- const { nativeEvent , target } = event ;
77- if ( context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget ) ) {
78- return ;
89+ if ( event != null ) {
90+ const { nativeEvent } = event ;
91+ if (
92+ context . isTargetWithinEventComponent ( ( nativeEvent : any ) . relatedTarget )
93+ ) {
94+ return ;
95+ }
7996 }
8097 if ( props . onBlur ) {
81- const syntheticEvent = createFocusEvent ( 'blur' , target ) ;
98+ const syntheticEvent = createFocusEvent (
99+ 'blur' ,
100+ ( ( state . focusTarget : any ) : Element | Document ) ,
101+ ) ;
82102 context . dispatchEvent ( syntheticEvent , props . onBlur , { discrete : true } ) ;
83103 }
84104 if ( props . onFocusChange ) {
85105 const listener = ( ) = > {
86106 props . onFocusChange ( false ) ;
87107 } ;
88- const syntheticEvent = createFocusEvent ( 'focuschange' , target ) ;
108+ const syntheticEvent = createFocusEvent (
109+ 'focuschange' ,
110+ ( ( state . focusTarget : any ) : Element | Document ) ,
111+ ) ;
89112 context . dispatchEvent ( syntheticEvent , listener , { discrete : true } ) ;
90113 }
91114}
92115
116+ function unmountResponder (
117+ context : ReactResponderContext ,
118+ props : FocusProps ,
119+ state : FocusState ,
120+ ) : void {
121+ if ( state . isFocused ) {
122+ dispatchFocusOutEvents ( null , context , props , state ) ;
123+ }
124+ }
125+
93126const FocusResponder = {
94127 targetEventTypes ,
95128 createInitialState ( ) : FocusState {
96129 return {
97130 isFocused : false ,
131+ focusTarget : null ,
98132 } ;
99133 } ,
100134 onEvent (
@@ -103,25 +137,41 @@ const FocusResponder = {
103137 props : Object ,
104138 state : FocusState ,
105139 ) : void {
106- const { type } = event ;
140+ const { type , target } = event ;
107141
108142 switch ( type ) {
109143 case 'focus ': {
110144 if ( ! state . isFocused && ! context . hasOwnership ( ) ) {
111- dispatchFocusInEvents ( event , context , props ) ;
145+ state . focusTarget = target ;
146+ dispatchFocusInEvents ( event , context , props , state ) ;
112147 state . isFocused = true ;
113148 }
114149 break ;
115150 }
116151 case 'blur' : {
117152 if ( state . isFocused ) {
118- dispatchFocusOutEvents ( event , context , props ) ;
153+ dispatchFocusOutEvents ( event , context , props , state ) ;
119154 state . isFocused = false ;
155+ state . focusTarget = null ;
120156 }
121157 break ;
122158 }
123159 }
124160 } ,
161+ onUnmount (
162+ context : ReactResponderContext ,
163+ props : FocusProps ,
164+ state : FocusState ,
165+ ) {
166+ unmountResponder ( context , props , state ) ;
167+ } ,
168+ onOwnershipChange (
169+ context : ReactResponderContext ,
170+ props : FocusProps ,
171+ state : FocusState ,
172+ ) {
173+ unmountResponder ( context , props , state ) ;
174+ } ,
125175} ;
126176
127177export default {
0 commit comments