1- <template >
2- <li :class =" computedDropdownClasses" >
3- <a href =" #"
4- aria-haspopup =" true"
5- :aria-expanded =" visible"
6- :class =" computedToggleClasses"
7- @click =" click($event)"
8- ref =" toggle"
9- >
10- <slot name =" button" >
11- <button class =" btn btn-outline-primary dropdown-toggle" >{{text}}</button >
12- </slot >
13- </a >
14- <div :class =" computedMenuClasses" ref =" menu" v-on-clickaway =" hide" >
15- <slot ></slot >
16- </div >
17- </li >
18- </template >
191<script >
2+ import CLink from ' ../Link/CLink'
203import Popper from ' popper.js'
214import { mixin as clickaway } from ' vue-clickaway'
5+ import { deepObjectsMerge } from ' @coreui/coreui/dist/js/coreui-utilities'
226
237export default {
248 name: ' CDropdown' ,
@@ -33,20 +17,34 @@ export default {
3317 this .createPopper
3418 },
3519 props: {
36- text : {
20+ buttonContent : {
3721 type: String ,
3822 default: ' Dropdown'
3923 },
4024 show: Boolean ,
4125 dropup: Boolean ,
4226 disabled: Boolean ,
43- right: Boolean ,
44- menuClasses: String ,
45- toggleClasses: String ,
46- popperConfig: Object
27+ addMenuClasses: String ,
28+ addButtonClasses: String ,
29+ nav: Boolean ,
30+ noCaret: Boolean ,
31+ variant: {
32+ type: String ,
33+ default: ' secondary'
34+ },
35+ size: {
36+ type: String ,
37+ validator : val => [' sm' , ' lg' ].includes (val)
38+ },
39+ split: Boolean ,
40+ offset: Number ,
41+ placement: String ,
42+ noFlip: Boolean ,
43+ popperConfig: Object ,
44+ noPopper: Boolean ,
4745 },
4846 mounted () {
49- this .checkForPopper ()
47+ this .menagePopper ()
5048 },
5149 methods: {
5250 hide () {
@@ -57,14 +55,16 @@ export default {
5755 e .preventDefault ()
5856 this .toggle (! this .visible )
5957 },
60- toggle (visible ) {
58+ toggle (value ) {
6159 if (this .disabled )
6260 return
63- this .visible = visible
64- this .checkForPopper ()
61+ setTimeout (() => {
62+ this .visible = value
63+ this .menagePopper ()
64+ }, 0 )
6565 },
66- checkForPopper () {
67- if (this .popperConfig )
66+ menagePopper () {
67+ if (! this .noPopper )
6868 setTimeout (() => this .visible ? this .createPopper () : this .removePopper (), 0 )
6969 },
7070 removePopper () {
@@ -73,37 +73,102 @@ export default {
7373 }
7474 this ._popper = null
7575 },
76- createPopper (element ) {
76+ createPopper () {
7777 this .removePopper ()
78- this ._popper = new Popper (this .$refs .toggle , this .$refs .menu , this .popperConfig )
78+ this ._popper = new Popper (this .$refs .toggle , this .$refs .menu , this .computedPopperConfig )
7979 }
8080 },
8181 computed: {
82+ generatedPopperConfig () {
83+ return {
84+ placement: this .placement ? this .placement : this .dropup ? ' top-start' : ' bottom-start' ,
85+ modifiers: {
86+ offset: { offset: this .offset || 0 },
87+ flip: { enabled: ! this .noFlip }
88+ }
89+ }
90+ },
91+ computedPopperConfig () {
92+ return deepObjectsMerge (this .generatedPopperConfig , this .popperConfig || {})
93+ },
8294 computedDropdownClasses () {
8395 return [
84- ' dropdown' ,
96+ ! this . dropup ? ' dropdown' : ' dropup ' ,
8597 {
86- ' dropup' : this .dropup ,
87- ' show' : this .visible
98+ ' show' : this .visible ,
99+ ' nav-item' : this .nav ,
100+ ' btn-group' : this .haveButtonClasses
88101 }
89102 ]
90103 },
91- computedToggleClasses () {
104+ buttonTag () {
105+ return this .nav ? CLink : ' button'
106+ },
107+ haveButtonClasses () {
108+ return this .nav && ! this .split ? Boolean (this .$options .propsData .variant ) : true
109+ },
110+ computedButtonClasses () {
92111 return [
93- this .toggleClasses ,
112+ this .addButtonClasses ,
113+ this .haveButtonClasses ? ` btn btn-${ this .variant } ` : ' nav-link' ,
94114 {
95- ' disabled' : this .disabled
115+ ' dropdown-toggle' : ! this .noCaret && ! this .split ,
116+ [` btn-${ this .size } ` ]: this .size ,
117+ ' disabled' : this .disabled ,
96118 }
97119 ]
98120 },
99121 computedMenuClasses () {
100122 return [
101- this .menuClasses ,
123+ this .addMenuClasses ,
102124 ' dropdown-menu' ,
103- this .right ? ' dropdown-menu-right' : ' dropdown-menu-left' ,
104125 { ' show' : this .visible }
105126 ]
106- }
127+ },
107128 },
129+ render (h ) {
130+ const toggle = this .$slots .button || h (
131+ this .buttonTag ,
132+ {
133+ style: { cursor: ' pointer' },
134+ attrs: {
135+ ' aria-haspopup' : true ,
136+ ' aria-expanded' : this .visible ,
137+ },
138+ on: {
139+ click: this .split ? ' ' : this .click
140+ },
141+ ref: ' toggle' ,
142+ class: this .computedButtonClasses ,
143+ domProps: ! this .$slots .buttonContent ?
144+ { innerHTML: this .buttonContent } :
145+ null
146+ }, this .$slots .buttonContent )
147+ let splitButton = h (false )
148+ if (this .split ) {
149+ splitButton = h (
150+ this .buttonTag ,
151+ {
152+ class: [ this .computedButtonClasses , ' dropdown-toggle dropdown-toggle-split' ],
153+ on: { click: this .click }
154+ })
155+ }
156+
157+
158+ const content = h (
159+ ' div' ,
160+ {
161+ class: this .computedMenuClasses ,
162+ ref: ' menu' ,
163+ directives: [{ name: ' on-clickaway' , value: this .hide }],
164+ },
165+ this .$slots .default
166+ )
167+ return h (
168+ this .nav ? ' li' : ' div' ,
169+ { class: this .computedDropdownClasses },
170+ [ toggle, splitButton, content ]
171+ )
172+ }
108173}
109174 </script >
0 commit comments