1
- import { defineComponent , h , onBeforeUnmount , onMounted , ref } from 'vue'
1
+ import { defineComponent , h , onBeforeUnmount , onMounted , onUpdated , ref , watch } from 'vue'
2
+ import { CBackdrop } from '../backdrop'
2
3
3
4
const CSidebar = defineComponent ( {
4
5
name : 'CSidebar' ,
@@ -66,16 +67,22 @@ const CSidebar = defineComponent({
66
67
/**
67
68
* Toggle the visibility of sidebar component.
68
69
*/
69
- visible : {
70
- type : Boolean ,
71
- default : undefined ,
72
- } ,
70
+ visible : Boolean ,
73
71
} ,
74
72
emits : [ 'visible-change' ] ,
75
- setup ( props , { slots, emit } ) {
73
+ setup ( props , { attrs, slots, emit } ) {
74
+ const mobile = ref ( )
75
+ const inViewport = ref ( )
76
76
const sidebarRef = ref ( )
77
77
const visible = ref ( )
78
78
79
+ const handleClick = ( event : Event ) => {
80
+ const target = event . target as HTMLElement
81
+ target . closest ( 'a.nav-link:not(.nav-group-toggle)' )
82
+ ? ( visible . value = false )
83
+ : ( visible . value = true )
84
+ }
85
+
79
86
const options = {
80
87
rootMargin : '0px' ,
81
88
threshold : 1.0 ,
@@ -86,22 +93,44 @@ const CSidebar = defineComponent({
86
93
onMounted ( ( ) => {
87
94
const callback = ( entries : IntersectionObserverEntry [ ] ) => {
88
95
entries . forEach ( ( entry ) => {
89
- if ( entry . isIntersecting !== props . visible || typeof visible . value === 'undefined' ) {
90
- visible . value = entry . isIntersecting
91
- emit ( 'visible-change' , visible . value )
92
- }
96
+ inViewport . value = entry . isIntersecting
97
+ emit ( 'visible-change' , entry . isIntersecting )
93
98
} )
94
99
}
95
100
96
101
observer = new IntersectionObserver ( callback , options )
97
102
observer . observe ( sidebarRef . value )
103
+
104
+ mobile . value = Boolean ( getComputedStyle ( sidebarRef . value ) . getPropertyValue ( '--cui-is-mobile' ) )
105
+ } )
106
+
107
+ onUpdated ( ( ) => {
108
+ mobile . value = Boolean ( getComputedStyle ( sidebarRef . value ) . getPropertyValue ( '--cui-is-mobile' ) )
109
+
110
+ if ( mobile . value ) {
111
+ window . addEventListener ( 'click' , handleClick )
112
+ } else {
113
+ window . removeEventListener ( 'click' , handleClick )
114
+ }
98
115
} )
99
116
100
117
onBeforeUnmount ( ( ) => {
101
118
observer . disconnect ( )
102
119
} )
103
120
104
- return ( ) =>
121
+ watch (
122
+ ( ) => props . visible ,
123
+ ( ) => {
124
+ if ( props . visible === true && inViewport . value === false ) {
125
+ visible . value = true
126
+ }
127
+ if ( props . visible === false && inViewport . value === true ) {
128
+ visible . value = false
129
+ }
130
+ } ,
131
+ )
132
+
133
+ return ( ) => [
105
134
h (
106
135
'div' ,
107
136
{
@@ -116,14 +145,24 @@ const CSidebar = defineComponent({
116
145
} `] : props . selfHiding ,
117
146
[ `sidebar-${ props . size } ` ] : props . size ,
118
147
'sidebar-narrow-unfoldable' : props . unfoldable ,
119
- show : props . visible === true && visible . value === false ,
120
- hide : props . visible === false && visible . value === true ,
148
+ show : visible . value === true ,
149
+ hide : visible . value === false ,
121
150
} ,
151
+ attrs . class ,
122
152
] ,
123
153
ref : sidebarRef ,
124
154
} ,
125
155
slots . default && slots . default ( ) ,
126
- )
156
+ ) ,
157
+ mobile . value &&
158
+ h ( CBackdrop , {
159
+ class : 'sidebar-backdrop d-none' ,
160
+ visible : props . visible ,
161
+ onClick : ( ) => {
162
+ visible . value = false
163
+ } ,
164
+ } ) ,
165
+ ]
127
166
} ,
128
167
} )
129
168
0 commit comments