1
1
import Vue from '../../utils/vue'
2
2
import { arrayIncludes } from '../../utils/array'
3
- import { stripTags } from '../../utils/html'
4
3
import { getComponentConfig } from '../../utils/config'
5
- import idMixin from '../../mixins/id '
4
+ import { htmlOrText } from '../../utils/html '
6
5
import dropdownMixin from '../../mixins/dropdown'
6
+ import idMixin from '../../mixins/id'
7
7
import normalizeSlotMixin from '../../mixins/normalize-slot'
8
8
import { BButton } from '../button/button'
9
9
10
+ // --- Constants ---
11
+
10
12
const NAME = 'BDropdown'
11
13
14
+ // --- Props ---
15
+
12
16
export const props = {
13
17
text : {
14
18
// Button label
@@ -20,14 +24,14 @@ export const props = {
20
24
type : String
21
25
// default: undefined
22
26
} ,
23
- size : {
24
- type : String ,
25
- default : ( ) => getComponentConfig ( NAME , 'size' )
26
- } ,
27
27
variant : {
28
28
type : String ,
29
29
default : ( ) => getComponentConfig ( NAME , 'variant' )
30
30
} ,
31
+ size : {
32
+ type : String ,
33
+ default : ( ) => getComponentConfig ( NAME , 'size' )
34
+ } ,
31
35
block : {
32
36
type : Boolean ,
33
37
default : false
@@ -89,28 +93,30 @@ export const props = {
89
93
}
90
94
}
91
95
96
+ // --- Main component ---
92
97
// @vue /component
93
98
export const BDropdown = /*#__PURE__*/ Vue . extend ( {
94
99
name : NAME ,
95
100
mixins : [ idMixin , dropdownMixin , normalizeSlotMixin ] ,
96
101
props,
97
102
computed : {
98
103
dropdownClasses ( ) {
104
+ const { block, split, boundary } = this
99
105
return [
100
106
this . directionClass ,
101
107
{
102
108
show : this . visible ,
103
109
// The 'btn-group' class is required in `split` mode for button alignment
104
110
// It needs also to be applied when `block` is disabled to allow multiple
105
111
// dropdowns to be aligned one line
106
- 'btn-group' : this . split || ! this . block ,
112
+ 'btn-group' : split || ! block ,
107
113
// When `block` is enabled and we are in `split` mode the 'd-flex' class
108
114
// needs to be applied to allow the buttons to stretch to full width
109
- 'd-flex' : this . block && this . split ,
115
+ 'd-flex' : block && split ,
110
116
// Position `static` is needed to allow menu to "breakout" of the `scrollParent`
111
117
// boundaries when boundary is anything other than `scrollParent`
112
118
// See: https://github.com/twbs/bootstrap/issues/24251#issuecomment-341413786
113
- 'position-static' : this . boundary !== 'scrollParent' || ! this . boundary
119
+ 'position-static' : boundary !== 'scrollParent' || ! boundary
114
120
}
115
121
]
116
122
} ,
@@ -124,100 +130,107 @@ export const BDropdown = /*#__PURE__*/ Vue.extend({
124
130
]
125
131
} ,
126
132
toggleClasses ( ) {
133
+ const { split } = this
127
134
return [
128
135
this . toggleClass ,
129
136
{
130
- 'dropdown-toggle-split' : this . split ,
131
- 'dropdown-toggle-no-caret' : this . noCaret && ! this . split
137
+ 'dropdown-toggle-split' : split ,
138
+ 'dropdown-toggle-no-caret' : this . noCaret && ! split
132
139
}
133
140
]
134
141
}
135
142
} ,
136
143
render ( h ) {
137
- let split = h ( )
138
- const buttonContent = this . normalizeSlot ( 'button-content' ) || this . html || stripTags ( this . text )
139
- if ( this . split ) {
144
+ const { variant, size, block, disabled, split, role } = this
145
+ const commonProps = { variant, size, block, disabled }
146
+
147
+ const $buttonContent = this . normalizeSlot ( 'button-content' )
148
+ const buttonContentProps = this . hasNormalizedSlot ( 'button-content' )
149
+ ? { }
150
+ : htmlOrText ( this . html , this . text )
151
+
152
+ let $split = h ( )
153
+ if ( split ) {
154
+ const { splitTo, splitHref, splitButtonType } = this
140
155
const btnProps = {
141
- variant : this . splitVariant || this . variant ,
142
- size : this . size ,
143
- block : this . block ,
144
- disabled : this . disabled
156
+ ...commonProps ,
157
+ variant : this . splitVariant || this . variant
145
158
}
146
- // We add these as needed due to router-link issues with defined property with undefined/null values
147
- if ( this . splitTo ) {
148
- btnProps . to = this . splitTo
149
- } else if ( this . splitHref ) {
150
- btnProps . href = this . splitHref
151
- } else if ( this . splitButtonType ) {
152
- btnProps . type = this . splitButtonType
159
+ // We add these as needed due to <router-link> issues with
160
+ // defined property with `undefined`/`null` values
161
+ if ( splitTo ) {
162
+ btnProps . to = splitTo
163
+ } else if ( splitHref ) {
164
+ btnProps . href = splitHref
165
+ } else if ( splitButtonType ) {
166
+ btnProps . type = splitButtonType
153
167
}
154
- split = h (
168
+ $ split = h (
155
169
BButton ,
156
170
{
157
- ref : 'button' ,
158
- props : btnProps ,
159
171
class : this . splitClass ,
160
- attrs : {
161
- id : this . safeId ( '_BV_button_' )
162
- } ,
163
- on : {
164
- click : this . onSplitClick
165
- }
172
+ attrs : { id : this . safeId ( '_BV_button_' ) } ,
173
+ props : btnProps ,
174
+ domProps : buttonContentProps ,
175
+ on : { click : this . onSplitClick } ,
176
+ ref : 'button'
166
177
} ,
167
- [ buttonContent ]
178
+ [ $ buttonContent]
168
179
)
169
180
}
170
- const toggle = h (
181
+
182
+ const $toggle = h (
171
183
BButton ,
172
184
{
173
- ref : 'toggle' ,
174
185
staticClass : 'dropdown-toggle' ,
175
186
class : this . toggleClasses ,
176
- props : {
177
- tag : this . toggleTag ,
178
- variant : this . variant ,
179
- size : this . size ,
180
- block : this . block && ! this . split ,
181
- disabled : this . disabled
182
- } ,
183
187
attrs : {
184
188
id : this . safeId ( '_BV_toggle_' ) ,
185
189
'aria-haspopup' : 'true' ,
186
190
'aria-expanded' : this . visible ? 'true' : 'false'
187
191
} ,
192
+ props : {
193
+ ...commonProps ,
194
+ tag : this . toggleTag ,
195
+ block : block && ! split
196
+ } ,
197
+ domProps : split ? { } : buttonContentProps ,
188
198
on : {
189
199
mousedown : this . onMousedown ,
190
200
click : this . toggle ,
191
201
keydown : this . toggle // Handle ENTER, SPACE and DOWN
192
- }
202
+ } ,
203
+ ref : 'toggle'
193
204
} ,
194
- [ this . split ? h ( 'span' , { class : [ 'sr-only' ] } , [ this . toggleText ] ) : buttonContent ]
205
+ [ split ? h ( 'span' , { class : [ 'sr-only' ] } , [ this . toggleText ] ) : $ buttonContent]
195
206
)
196
- const menu = h (
207
+
208
+ const $menu = h (
197
209
'ul' ,
198
210
{
199
- ref : 'menu' ,
200
211
staticClass : 'dropdown-menu' ,
201
212
class : this . menuClasses ,
202
213
attrs : {
203
- role : this . role ,
214
+ role,
204
215
tabindex : '-1' ,
205
- 'aria-labelledby' : this . safeId ( this . split ? '_BV_button_' : '_BV_toggle_' )
216
+ 'aria-labelledby' : this . safeId ( split ? '_BV_button_' : '_BV_toggle_' )
206
217
} ,
207
218
on : {
208
219
keydown : this . onKeydown // Handle UP, DOWN and ESC
209
- }
220
+ } ,
221
+ ref : 'menu'
210
222
} ,
211
223
! this . lazy || this . visible ? this . normalizeSlot ( 'default' , { hide : this . hide } ) : [ h ( ) ]
212
224
)
225
+
213
226
return h (
214
227
'div' ,
215
228
{
216
229
staticClass : 'dropdown b-dropdown' ,
217
230
class : this . dropdownClasses ,
218
231
attrs : { id : this . safeId ( ) }
219
232
} ,
220
- [ split , toggle , menu ]
233
+ [ $ split, $ toggle, $ menu]
221
234
)
222
235
}
223
236
} )
0 commit comments