1
1
<template >
2
- <div :class =" sidebarClasses" v-on-clickaway = " hideMobile " >
2
+ <div :class =" sidebarClasses" >
3
3
<slot >Sidebar</slot >
4
4
</div >
5
5
</template >
6
- <script >
7
- import { mixin as clickaway } from ' vue-clickaway2'
8
- import { hideMobile } from ' ./hideMobile'
9
6
7
+ <script >
8
+ import elementResizeDetectorMaker from ' element-resize-detector'
9
+ import { getStyle } from ' @coreui/coreui/dist/js/coreui-utilities'
10
10
export default {
11
11
name: ' CSidebar' ,
12
- mixins: [clickaway, hideMobile],
13
12
props: {
14
13
fixed: Boolean ,
15
14
minimize: Boolean ,
16
- display: {
17
- type: [Boolean , String ],
15
+ show: {
16
+ type: Boolean ,
17
+ default: true
18
+ },
19
+ mobileShow: Boolean ,
20
+ noHideOnMobileClick: Boolean ,
21
+ breakpoint: {
22
+ type: [String , Boolean ],
18
23
default: ' lg' ,
19
- validator : val => [true , false , ' sm' , ' md' , ' lg' , ' xl' ].includes (val)
24
+ validator : val => [false , ' sm' , ' md' , ' lg' , ' xl' ].includes (val)
20
25
},
21
- mobile: Boolean ,
22
26
aside: Boolean ,
23
27
light: Boolean
24
28
},
@@ -31,36 +35,110 @@ export default {
31
35
},
32
36
data () {
33
37
return {
34
- displayed: this .display ,
35
- minimized: this .minimize
38
+ open: this .show ,
39
+ mobileOpen: this .mobileShow ,
40
+ minimized: this .initialMinimize ,
41
+ erd: elementResizeDetectorMaker (),
42
+ bodyWidth: undefined ,
36
43
}
37
44
},
38
45
mounted () {
46
+ this .erd .listenTo (document .body , (el ) => this .bodyWidth = el .clientWidth )
47
+
39
48
this .$root .$on (` c-${ this .mode } -toggle-minimize` , () => {
40
- this .minimized = ! this . minimized
49
+ this .switchState ( ' minimized' )
41
50
})
42
51
this .$root .$on (` c-${ this .mode } -toggle` , () => {
43
- this .displayed = this .displayed ? false : this .display || true
52
+ if (this .isOnMobile ) {
53
+ this .switchState (' mobileOpen' )
54
+ } else {
55
+ this .switchState (' open' )
56
+ }
44
57
})
45
58
},
59
+ watch: {
60
+ show (val , oldVal ) {
61
+ if (val !== oldVal && val !== this .open ) {
62
+ this .switchState (' open' )
63
+ }
64
+ },
65
+ mobileShow (val , oldVal ) {
66
+ if (val !== oldVal && val !== this .mobileOpen ) {
67
+ this .switchState (' mobileOpen' )
68
+ }
69
+ },
70
+ minimize (val , oldVal ) {
71
+ if (val !== oldVal && val !== this .minimized ) {
72
+ this .switchState (' minimized' )
73
+ }
74
+ },
75
+ isOnMobile: {
76
+ immediate: true ,
77
+ handler (val , oldVal ) {
78
+ if (val === true && val !== oldVal) {
79
+ document .body .addEventListener (' click' , this .mobileClick )
80
+ } else if (oldVal === true ) {
81
+ document .body .removeEventListener (' click' , this .mobileClick )
82
+ }
83
+ }
84
+ }
85
+ },
46
86
computed: {
47
87
mode () {
48
88
return this .aside ? ' aside' : ' sidebar'
49
89
},
50
- breakpoint () {
51
- return this .displayed === true || this .mobile ? ' ' : ' -' + this .display
90
+ isVisible () {
91
+ if (this .bodyWidth ) {
92
+ return this .isOnMobile ? this .mobileOpen : this .open
93
+ }
94
+ return false
52
95
},
53
96
sidebarClasses () {
54
97
return [
55
- ' c-sidebar' ,
56
- ` c-sidebar-${ this .light ? ' light' : ' dark' } ` ,
57
- {
58
- [` c-sidebar${ this .breakpoint } -show` ]: this .displayed ,
59
- ' c-sidebar-fixed' : this .fixed ,
60
- ' c-sidebar-minimized' : this .minimized ,
61
- ' c-sidebar-right' : this .aside
62
- }
63
- ]
98
+ this .displayClass ,
99
+ ' c-sidebar' ,
100
+ ` c-sidebar-${ this .light ? ' light' : ' dark' } ` ,
101
+ {
102
+ ' c-sidebar-show' : this .isOnMobile && this .mobileOpen ,
103
+ [` c-sidebar-${ this .breakpoint } -show` ]: this .open ,
104
+ ' c-sidebar-fixed' : this .fixed ,
105
+ ' c-sidebar-minimized' : this .minimized ,
106
+ ' c-sidebar-right' : this .aside
107
+ }
108
+ ]
109
+ },
110
+ breakpoints () {
111
+ return {
112
+ ' sm' : getStyle (' --breakpoint-sm' ) || ' 576px' ,
113
+ ' md' : getStyle (' --breakpoint-md' ) || ' 768px' ,
114
+ ' lg' : getStyle (' --breakpoint-lg' ) || ' 992px' ,
115
+ ' xl' : getStyle (' --breakpoint-xl' ) || ' 1200px'
116
+ }
117
+ },
118
+ isOnMobile () {
119
+ const mobileWidth = parseFloat (this .breakpoints [this .breakpoint ]) || 0
120
+ return this .bodyWidth && (this .bodyWidth < mobileWidth)
121
+ }
122
+ },
123
+ methods: {
124
+ mobileClick (event ) {
125
+ if (! this .mobileOpen || this .noHideOnMobileClick ) {
126
+ return
127
+ }
128
+ const classList = Array .from (event .target .classList ).join ()
129
+ const clickedOutsideSidebar = ! this .$el .contains (event .target )
130
+ if (
131
+ (clickedOutsideSidebar && ! classList .includes (' c-header-toggler' )) || (! clickedOutsideSidebar && event .target .tagName === ' A' )
132
+ ) {
133
+ this .switchState (' mobileOpen' )
134
+ }
135
+ },
136
+ switchState (variable ) {
137
+ const propNames = {
138
+ open: ' show' , minimized: ' minimize' , mobileOpen: ' mobileShow'
139
+ }
140
+ this .$emit (` update:${ propNames[variable]} ` , ! this [variable])
141
+ this [variable] = ! this [variable]
64
142
}
65
143
}
66
144
}
0 commit comments