@@ -17,7 +17,7 @@ const ROOT_DROPDOWN_SHOWN = `${ROOT_DROPDOWN_PREFIX}shown`
1717const ROOT_DROPDOWN_HIDDEN = `${ ROOT_DROPDOWN_PREFIX } hidden`
1818
1919// Delay when loosing focus before closing menu (in ms)
20- const FOCUSOUT_DELAY = 100
20+ const FOCUSOUT_DELAY = 150
2121
2222// Dropdown item CSS selectors
2323const Selector = {
@@ -174,17 +174,19 @@ export default {
174174 created ( ) {
175175 // Create non-reactive property
176176 this . $_popper = null
177+ this . $_hideTimeout = null
177178 } ,
178179 deactivated ( ) /* istanbul ignore next: not easy to test */ {
179180 // In case we are inside a `<keep-alive>`
180181 this . visible = false
181182 this . whileOpenListen ( false )
182- this . removePopper ( )
183+ this . destroyPopper ( )
183184 } ,
184185 beforeDestroy ( ) {
185186 this . visible = false
186187 this . whileOpenListen ( false )
187- this . removePopper ( )
188+ this . destroyPopper ( )
189+ this . clearHideTimeout ( )
188190 } ,
189191 methods : {
190192 // Event emitter
@@ -237,19 +239,25 @@ export default {
237239 this . whileOpenListen ( false )
238240 this . $root . $emit ( ROOT_DROPDOWN_HIDDEN , this )
239241 this . $emit ( 'hidden' )
240- this . removePopper ( )
242+ this . destroyPopper ( )
241243 } ,
242244 createPopper ( element ) {
243- this . removePopper ( )
245+ this . destroyPopper ( )
244246 this . $_popper = new Popper ( element , this . $refs . menu , this . getPopperConfig ( ) )
245247 } ,
246- removePopper ( ) {
248+ destroyPopper ( ) {
247249 if ( this . $_popper ) {
248250 // Ensure popper event listeners are removed cleanly
249251 this . $_popper . destroy ( )
250252 }
251253 this . $_popper = null
252254 } ,
255+ clearHideTimeout ( ) {
256+ if ( this . $_hideTimeout ) {
257+ clearTimeout ( this . $_hideTimeout )
258+ this . $_hideTimeout = null
259+ }
260+ } ,
253261 getPopperConfig ( ) {
254262 let placement = AttachmentMap . BOTTOM
255263 if ( this . dropup ) {
@@ -273,9 +281,6 @@ export default {
273281 }
274282 return { ...popperConfig , ...( this . popperOpts || { } ) }
275283 } ,
276- isDropdownElement ( el ) {
277- return contains ( this . $refs . menu , el ) || contains ( this . toggler , el )
278- } ,
279284 // Turn listeners on/off while open
280285 whileOpenListen ( isOpen ) {
281286 // Hide the dropdown when clicked outside
@@ -380,7 +385,11 @@ export default {
380385 } ,
381386 // Document click out listener
382387 clickOutHandler ( evt ) {
383- if ( this . visible && ! this . isDropdownElement ( evt . target ) ) {
388+ const target = evt . target
389+ if ( this . visible && ! contains ( this . $refs . menu , target ) && ! contains ( this . toggler , target ) ) {
390+ // Clear hide timeout anyway
391+ this . clearHideTimeout ( )
392+ // Create temp hide function to reuse in belows logic
384393 const doHide = ( ) => {
385394 this . visible = false
386395 }
@@ -393,10 +402,9 @@ export default {
393402 }
394403 } ,
395404 // Document focusin listener
396- focusInHandler ( evt ) {
397- if ( this . visible && ! this . isDropdownElement ( evt . target ) ) {
398- this . visible = false
399- }
405+ focusInHandler ( ...args ) {
406+ // Shared logic with click out
407+ this . clickOutHandler ( ...args )
400408 } ,
401409 // Keyboard nav
402410 focusNext ( evt , up ) {
0 commit comments