@@ -64,6 +64,7 @@ class DropdownTreeSelect extends Component {
6464 this . state = {
6565 searchModeOn : false ,
6666 currentFocus : undefined ,
67+ isManagingFocus : false ,
6768 }
6869 this . clientId = props . id || clientIdGenerator . get ( this )
6970 }
@@ -106,40 +107,61 @@ class DropdownTreeSelect extends Component {
106107 }
107108
108109 componentWillUnmount ( ) {
109- document . removeEventListener ( 'click' , this . handleOutsideClick , false )
110+ document . removeEventListener ( 'click' , this . handleDropdownCollapse , false )
110111 }
111112
112113 componentWillReceiveProps ( nextProps ) {
113114 this . initNewProps ( nextProps )
114115 }
115116
117+ onBlur = ( ) => {
118+ console . log ( this . _timeoutID )
119+
120+ // setTimeout runs afterwards in the event.
121+ // If onFocus is triggered immediately in a child component, clearTimeout will stop setTimeout to run.
122+ this . _timeoutID = setTimeout ( ( ) => {
123+ if ( this . state . isManagingFocus ) {
124+ this . props . onBlur ( )
125+ this . setState ( {
126+ isManagingFocus : false ,
127+ } )
128+ }
129+ } , 0 )
130+ }
131+
132+ onFocus = ( ) => {
133+ clearTimeout ( this . _timeoutID )
134+ if ( ! this . state . isManagingFocus ) {
135+ this . props . onFocus ( )
136+ this . setState ( {
137+ isManagingFocus : true ,
138+ } )
139+ }
140+ }
141+
116142 handleClick = ( e , callback ) => {
117143 this . setState ( prevState => {
118144 // keep dropdown active when typing in search box
119145 const showDropdown = this . props . showDropdown === 'always' || this . keepDropdownActive || ! prevState . showDropdown
120146
121- // register event listeners only if there is a state change
122- if ( showDropdown !== prevState . showDropdown ) {
123- if ( showDropdown ) {
124- document . addEventListener ( 'click' , this . handleOutsideClick , false )
125- } else {
126- document . removeEventListener ( 'click' , this . handleOutsideClick , false )
127- }
128- }
147+ const searchStateReset = ! showDropdown ? this . resetSearchState ( ) : { }
129148
130- if ( showDropdown ) this . props . onFocus ( )
131- else this . props . onBlur ( )
149+ if ( this . state . isManagingFocus && this . props . showDropdown !== 'always' ) {
150+ document . addEventListener ( 'click' , this . handleDropdownCollapse , false )
151+ }
132152
133- return ! showDropdown ? { showDropdown, ...this . resetSearchState ( ) } : { showDropdown }
153+ return {
154+ showDropdown,
155+ searchStateReset,
156+ }
134157 } , callback )
135158 }
136159
137- handleOutsideClick = e => {
138- if ( this . props . showDropdown === 'always' || ! isOutsideClick ( e , this . node ) ) {
139- return
140- }
141-
142- this . handleClick ( )
160+ handleDropdownCollapse = e => {
161+ if ( ! isOutsideClick ( e , this . node ) ) return
162+ document . removeEventListener ( 'click' , this . handleDropdownCollapse , false )
163+ const showDropdown = this . props . showDropdown === 'always'
164+ this . setState ( { showDropdown : showDropdown } )
143165 }
144166
145167 onInputChange = value => {
@@ -157,12 +179,15 @@ class DropdownTreeSelect extends Component {
157179 } )
158180 }
159181
160- onTagRemove = ( id , isKeyboardEvent ) => {
182+ onTagRemove = id => {
161183 const { tags : prevTags } = this . state
162184 this . onCheckboxChange ( id , false , tags => {
163- if ( ! isKeyboardEvent ) return
164-
165- keyboardNavigation . getNextFocusAfterTagDelete ( id , prevTags , tags , this . searchInput ) . focus ( )
185+ const nextFocus = keyboardNavigation . getNextFocusAfterTagDelete ( id , prevTags , tags , this . searchInput )
186+ if ( nextFocus ) {
187+ nextFocus . focus ( )
188+ } else {
189+ this . onBlur ( )
190+ }
166191 } )
167192 }
168193
@@ -201,7 +226,7 @@ class DropdownTreeSelect extends Component {
201226 }
202227
203228 if ( isSingleSelect && ! showDropdown ) {
204- document . removeEventListener ( 'click' , this . handleOutsideClick , false )
229+ document . removeEventListener ( 'click' , this . handleDropdownCollapse , false )
205230 }
206231
207232 keyboardNavigation . adjustFocusedProps ( currentFocusNode , node )
@@ -311,6 +336,8 @@ class DropdownTreeSelect extends Component {
311336 return (
312337 < div
313338 id = { this . clientId }
339+ onBlur = { this . onBlur }
340+ onFocus = { this . onFocus }
314341 className = { [ this . props . className && this . props . className , 'react-dropdown-tree-select' ]
315342 . filter ( Boolean )
316343 . join ( ' ' ) }
0 commit comments