1- import { defineComponent , h , ref , provide , watch , PropType } from 'vue'
1+ import { defineComponent , h , ref , provide , watch , PropType , onUnmounted , nextTick } from 'vue'
22import type { Placement } from '@popperjs/core'
33
44import { usePopper } from '../../composables'
@@ -158,6 +158,7 @@ const CDropdown = defineComponent({
158158setup ( props , { slots, emit} ) {
159159const dropdownToggleRef = ref ( )
160160const dropdownMenuRef = ref ( )
161+ const pendingKeyDownEventRef = ref < KeyboardEvent | null > ( null )
161162const popper = ref ( typeof props . alignment === 'object' ?false :props . popper )
162163const visible = ref ( props . visible )
163164
@@ -176,35 +177,50 @@ const CDropdown = defineComponent({
176177props . placement ,
177178props . direction ,
178179props . alignment ,
179- isRTL ( dropdownMenuRef . value ) ,
180+ isRTL ( dropdownMenuRef . value )
180181) as Placement ,
181182}
182183
183184watch (
184185( ) => props . visible ,
185186( ) => {
186187visible . value = props . visible
187- } ,
188+ }
188189)
189190
190191watch ( visible , ( ) => {
191192if ( visible . value && dropdownToggleRef . value && dropdownMenuRef . value ) {
192- popper . value && initPopper ( dropdownToggleRef . value , dropdownMenuRef . value , popperConfig )
193+ if ( popper . value ) {
194+ initPopper ( dropdownToggleRef . value , dropdownMenuRef . value , popperConfig )
195+ }
196+
193197window . addEventListener ( 'mouseup' , handleMouseUp )
194198window . addEventListener ( 'keyup' , handleKeyup )
195199dropdownToggleRef . value . addEventListener ( 'keydown' , handleKeydown )
196200dropdownMenuRef . value . addEventListener ( 'keydown' , handleKeydown )
201+
202+ if ( pendingKeyDownEventRef . value ) {
203+ nextTick ( ( ) => {
204+ handleKeydown ( pendingKeyDownEventRef . value as KeyboardEvent )
205+ pendingKeyDownEventRef . value = null
206+ } )
207+ }
208+
197209emit ( 'show' )
198210return
199211}
200212
201213popper . value && destroyPopper ( )
202214window . removeEventListener ( 'mouseup' , handleMouseUp )
203215window . removeEventListener ( 'keyup' , handleKeyup )
216+ dropdownMenuRef . value && dropdownMenuRef . value . removeEventListener ( 'keydown' , handleKeydown )
217+ emit ( 'hide' )
218+ } )
219+
220+ onUnmounted ( ( ) => {
204221dropdownToggleRef . value &&
205222dropdownToggleRef . value . removeEventListener ( 'keydown' , handleKeydown )
206223dropdownMenuRef . value && dropdownMenuRef . value . removeEventListener ( 'keydown' , handleKeydown )
207- emit ( 'hide' )
208224} )
209225
210226provide ( 'config' , {
@@ -219,18 +235,14 @@ const CDropdown = defineComponent({
219235provide ( 'visible' , visible )
220236provide ( 'dropdownToggleRef' , dropdownToggleRef )
221237provide ( 'dropdownMenuRef' , dropdownMenuRef )
238+ provide ( 'pendingKeyDownEventRef' , pendingKeyDownEventRef )
222239
223240const handleKeydown = ( event :KeyboardEvent ) => {
224- if (
225- visible . value &&
226- dropdownMenuRef . value &&
227- ( event . key === 'ArrowDown' || event . key === 'ArrowUp' )
228- ) {
241+ if ( dropdownMenuRef . value && ( event . key === 'ArrowDown' || event . key === 'ArrowUp' ) ) {
229242event . preventDefault ( )
230243const target = event . target as HTMLElement
231- // eslint-disable-next-line unicorn/prefer-spread
232244const items :HTMLElement [ ] = Array . from (
233- dropdownMenuRef . value . querySelectorAll ( '.dropdown-item:not(.disabled):not(:disabled)' ) ,
245+ dropdownMenuRef . value . querySelectorAll ( '.dropdown-item:not(.disabled):not(:disabled)' )
234246)
235247getNextActiveElement ( items , target , event . key === 'ArrowDown' , true ) . focus ( )
236248}
@@ -243,6 +255,7 @@ const CDropdown = defineComponent({
243255
244256if ( event . key === 'Escape' ) {
245257setVisible ( false )
258+ dropdownToggleRef . value ?. focus ( )
246259}
247260}
248261
@@ -267,22 +280,20 @@ const CDropdown = defineComponent({
267280}
268281}
269282
270- const setVisible = ( _visible ?:boolean ) => {
283+ const setVisible = ( _visible ?:boolean , event ?: KeyboardEvent ) => {
271284if ( props . disabled ) {
272285return
273286}
274287
275- if ( typeof _visible == 'boolean' ) {
288+ if ( typeof _visible === 'boolean' ) {
289+ if ( event ) {
290+ pendingKeyDownEventRef . value = event || null
291+ }
292+
276293visible . value = _visible
277- return
278- }
279294
280- if ( visible . value === true ) {
281- visible . value = false
282295return
283296}
284-
285- visible . value = true
286297}
287298
288299provide ( 'setVisible' , setVisible )
@@ -298,11 +309,11 @@ const CDropdown = defineComponent({
298309props . direction === 'center'
299310 ?'dropdown-center'
300311 :props . direction === 'dropup-center'
301- ?'dropup dropup-center'
302- :props . direction ,
312+ ?'dropup dropup-center'
313+ :props . direction ,
303314] ,
304315} ,
305- slots . default && slots . default ( ) ,
316+ slots . default && slots . default ( )
306317)
307318} ,
308319} )