Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6286039

Browse files
committed
refactor(CDropdown): rebuild the component, and improve the syntax
1 parentf5f92ef commit6286039

File tree

3 files changed

+106
-113
lines changed

3 files changed

+106
-113
lines changed

‎packages/coreui-vue/src/components/dropdown/CDropdown.ts‎

Lines changed: 99 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,53 @@
1-
import{defineComponent,h,ref,provide,watch,PropType,onMounted}from'vue'
2-
import{createPopper,Placement}from'@popperjs/core'
1+
import{defineComponent,h,ref,provide,watch,PropType}from'vue'
2+
importtype{Placement}from'@popperjs/core'
33

4-
import{Triggers}from'../../types'
4+
import{usePopper}from'../../composables'
5+
importtype{Placements,Triggers}from'../../types'
56
import{isRTL}from'../../utils'
67

8+
exporttypeDirections='start'|'end'
9+
10+
exporttypeBreakpoints=
11+
|{xs:Directions}
12+
|{sm:Directions}
13+
|{md:Directions}
14+
|{lg:Directions}
15+
|{xl:Directions}
16+
|{xxl:Directions}
17+
18+
exporttypeAlignments=Directions|Breakpoints
19+
20+
constgetPlacement=(
21+
placement:Placement,
22+
direction:string|undefined,
23+
alignment:Alignments|string|undefined,
24+
isRTL:boolean,
25+
):Placements=>{
26+
let_placement=placement
27+
28+
if(direction==='dropup'){
29+
_placement=isRTL ?'top-end' :'top-start'
30+
}
31+
32+
if(direction==='dropup-center'){
33+
_placement='top'
34+
}
35+
36+
if(direction==='dropend'){
37+
_placement=isRTL ?'left-start' :'right-start'
38+
}
39+
40+
if(direction==='dropstart'){
41+
_placement=isRTL ?'right-start' :'left-start'
42+
}
43+
44+
if(alignment==='end'){
45+
_placement=isRTL ?'bottom-start' :'bottom-end'
46+
}
47+
48+
return_placement
49+
}
50+
751
constCDropdown=defineComponent({
852
name:'CDropdown',
953
props:{
@@ -13,7 +57,7 @@ const CDropdown = defineComponent({
1357
*@values { 'start' | 'end' | { xs: 'start' | 'end' } | { sm: 'start' | 'end' } | { md: 'start' | 'end' } | { lg: 'start' | 'end' } | { xl: 'start' | 'end'} | { xxl: 'start' | 'end'}}
1458
*/
1559
alignment:{
16-
type:[String,Object],
60+
type:[String,Object]asPropType<string|Alignments>,
1761
// eslint-disable-next-line @typescript-eslint/no-explicit-any
1862
validator:(value:string|any)=>{
1963
if(value==='start'||value==='end'){
@@ -127,19 +171,43 @@ const CDropdown = defineComponent({
127171
setup(props,{ slots, emit}){
128172
constdropdownToggleRef=ref()
129173
constdropdownMenuRef=ref()
130-
constplacement=ref(props.placement)
131-
constpopper=ref()
174+
constpopper=ref(typeofprops.alignment==='object' ?false :props.popper)
132175
constvisible=ref(props.visible)
133176

177+
const{ initPopper, destroyPopper}=usePopper()
178+
179+
constpopperConfig={
180+
placement:getPlacement(
181+
props.placement,
182+
props.direction,
183+
props.alignment,
184+
isRTL(dropdownMenuRef.value),
185+
)asPlacement,
186+
}
187+
134188
watch(
135189
()=>props.visible,
136190
()=>{
137191
visible.value=props.visible
138192
},
139193
)
140194

195+
watch(visible,()=>{
196+
if(visible.value&&dropdownToggleRef.value&&dropdownMenuRef.value){
197+
popper.value&&initPopper(dropdownToggleRef.value,dropdownMenuRef.value,popperConfig)
198+
window.addEventListener('mouseup',handleMouseUp)
199+
window.addEventListener('keyup',handleKeyup)
200+
emit('show')
201+
return
202+
}
203+
204+
popper.value&&destroyPopper()
205+
window.removeEventListener('mouseup',handleMouseUp)
206+
window.removeEventListener('keyup',handleKeyup)
207+
emit('hide')
208+
})
209+
141210
provide('config',{
142-
autoClose:props.autoClose,
143211
alignment:props.alignment,
144212
dark:props.dark,
145213
popper:props.popper,
@@ -150,27 +218,38 @@ const CDropdown = defineComponent({
150218
provide('dropdownToggleRef',dropdownToggleRef)
151219
provide('dropdownMenuRef',dropdownMenuRef)
152220

153-
constinitPopper=()=>{
154-
// Disable popper if responsive aligment is set.
155-
if(typeofprops.alignment==='object'){
221+
consthandleKeyup=(event:KeyboardEvent)=>{
222+
if(props.autoClose===false){
156223
return
157224
}
158225

159-
if(dropdownToggleRef.value){
160-
popper.value=createPopper(dropdownToggleRef.value,dropdownMenuRef.value,{
161-
placement:placement.value,
162-
})
226+
if(event.key==='Escape'){
227+
setVisible(false)
163228
}
164229
}
165230

166-
constdestroyPopper=()=>{
167-
if(popper.value){
168-
popper.value.destroy()
231+
consthandleMouseUp=(event:Event)=>{
232+
if(!dropdownToggleRef.value||!dropdownMenuRef.value){
233+
return
234+
}
235+
236+
if(dropdownToggleRef.value.contains(event.targetasHTMLElement)){
237+
return
238+
}
239+
240+
if(
241+
props.autoClose===true||
242+
(props.autoClose==='inside'&&
243+
dropdownMenuRef.value.contains(event.targetasHTMLElement))||
244+
(props.autoClose==='outside'&&
245+
!dropdownMenuRef.value.contains(event.targetasHTMLElement))
246+
){
247+
setVisible(false)
248+
return
169249
}
170-
popper.value=undefined
171250
}
172251

173-
consttoggleMenu=(_visible?:boolean)=>{
252+
constsetVisible=(_visible?:boolean)=>{
174253
if(props.disabled){
175254
return
176255
}
@@ -188,48 +267,7 @@ const CDropdown = defineComponent({
188267
visible.value=true
189268
}
190269

191-
provide('toggleMenu',toggleMenu)
192-
193-
consthideMenu=()=>{
194-
if(props.disabled){
195-
return
196-
}
197-
198-
visible.value=false
199-
}
200-
201-
provide('hideMenu',hideMenu)
202-
203-
watch(visible,()=>{
204-
props.popper&&(visible.value ?initPopper() :destroyPopper())
205-
visible.value ?emit('show') :emit('hide')
206-
})
207-
208-
onMounted(()=>{
209-
if(props.direction==='center'){
210-
placement.value='bottom'
211-
}
212-
213-
if(props.direction==='dropup'){
214-
placement.value=isRTL(dropdownMenuRef.value) ?'top-end' :'top-start'
215-
}
216-
217-
if(props.direction==='dropup-center'){
218-
placement.value='top'
219-
}
220-
221-
if(props.direction==='dropend'){
222-
placement.value=isRTL(dropdownMenuRef.value) ?'left-start' :'right-start'
223-
}
224-
225-
if(props.direction==='dropstart'){
226-
placement.value=isRTL(dropdownMenuRef.value) ?'right-start' :'left-start'
227-
}
228-
229-
if(props.alignment==='end'){
230-
placement.value=isRTL(dropdownMenuRef.value) ?'bottom-start' :'bottom-end'
231-
}
232-
})
270+
provide('setVisible',setVisible)
233271

234272
return()=>
235273
props.variant==='input-group'

‎packages/coreui-vue/src/components/dropdown/CDropdownMenu.ts‎

Lines changed: 2 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import{defineComponent,h,inject,onUnmounted,onUpdated,Ref}from'vue'
1+
import{defineComponent,h,inject,Ref}from'vue'
22

33
constCDropdownMenu=defineComponent({
44
name:'CDropdownMenu',
@@ -14,13 +14,11 @@ const CDropdownMenu = defineComponent({
1414
},
1515
},
1616
setup(props,{ slots}){
17-
constdropdownToggleRef=inject('dropdownToggleRef')asRef<HTMLElement>
1817
constdropdownMenuRef=inject('dropdownMenuRef')asRef<HTMLElement>
1918
constconfig=inject('config')asany// eslint-disable-line @typescript-eslint/no-explicit-any
20-
consthideMenu=inject('hideMenu')as()=>void
2119
constvisible=inject('visible')asRef<boolean>
2220

23-
const{autoClose,alignment, dark, popper}=config
21+
const{ alignment, dark, popper}=config
2422

2523
// eslint-disable-next-line @typescript-eslint/ban-types, unicorn/consistent-function-scoping
2624
constalignmentClassNames=(alignment:object|string)=>{
@@ -36,49 +34,6 @@ const CDropdownMenu = defineComponent({
3634
returnclassNames
3735
}
3836

39-
consthandleKeyup=(event:KeyboardEvent)=>{
40-
if(autoClose===false){
41-
return
42-
}
43-
44-
if(event.key==='Escape'){
45-
hideMenu()
46-
}
47-
}
48-
49-
consthandleMouseUp=(event:Event)=>{
50-
if(dropdownToggleRef.value?.contains(event.targetasHTMLElement)){
51-
return
52-
}
53-
54-
if(autoClose===true){
55-
hideMenu()
56-
return
57-
}
58-
59-
if(autoClose==='inside'&&dropdownMenuRef.value?.contains(event.targetasHTMLElement)){
60-
hideMenu()
61-
return
62-
}
63-
64-
if(
65-
autoClose==='outside'&&
66-
!dropdownMenuRef.value?.contains(event.targetasHTMLElement)
67-
){
68-
hideMenu()
69-
}
70-
}
71-
72-
onUpdated(()=>{
73-
visible.value&&window.addEventListener('mouseup',handleMouseUp)
74-
visible.value&&window.addEventListener('keyup',handleKeyup)
75-
})
76-
77-
onUnmounted(()=>{
78-
window.removeEventListener('mouseup',handleMouseUp)
79-
window.removeEventListener('keyup',handleKeyup)
80-
})
81-
8237
return()=>
8338
h(
8439
props.component,

‎packages/coreui-vue/src/components/dropdown/CDropdownToggle.ts‎

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { cloneVNode, defineComponent, h, inject, onMounted, PropType, Ref, ref }
33
import{CButton}from'../button'
44

55
import{Color,Shape}from'../../props'
6-
import{Triggers}from'../../types'
6+
importtype{Triggers}from'../../types'
77

88
constCDropdownToggle=defineComponent({
99
name:'CDropdownToggle',
@@ -85,7 +85,7 @@ const CDropdownToggle = defineComponent({
8585
constdropdownToggleRef=inject('dropdownToggleRef')asRef<HTMLElement>
8686
constdropdownVariant=inject('variant')asstring
8787
constvisible=inject('visible')asRef<boolean>
88-
consttoggleMenu=inject('toggleMenu')as(_visible?:boolean)=>void
88+
constsetVisible=inject('setVisible')as(_visible?:boolean)=>void
8989

9090
constclassName=[
9191
{
@@ -103,7 +103,7 @@ const CDropdownToggle = defineComponent({
103103
return
104104
}
105105

106-
toggleMenu()
106+
setVisible()
107107
},
108108
}),
109109
...((props.trigger==='focus'||props.trigger.includes('focus'))&&{
@@ -112,13 +112,13 @@ const CDropdownToggle = defineComponent({
112112
return
113113
}
114114

115-
toggleMenu(true)
115+
setVisible(true)
116116
},
117117
onblur:()=>{
118118
if(props.disabled){
119119
return
120120
}
121-
toggleMenu(false)
121+
setVisible(false)
122122
},
123123
}),
124124
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp