PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.6
Booking for Appointments and Events Calendar – Amelia v2.4.6
2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / v3 / src / views / common / SbsFormConstruction / MenuSlideDialog / MenuSlideDialog.vue
ameliabooking / v3 / src / views / common / SbsFormConstruction / MenuSlideDialog Last commit date
MenuSlideDialog.vue 4 weeks ago
MenuSlideDialog.vue
345 lines
1 <template>
2 <AmSlidePopup
3 :visibility="visibility"
4 :position="position"
5 custom-class="am-msd"
6 :close-outside="true"
7 :custom-css="{ ...customCss, ...cssVars }"
8 @update:visibility="emits('update:visibility', false)"
9 >
10 <div class="am-msd__item-wrapper">
11 <div class="am-msd__item" @click="closeMenu">
12 <div class="am-msd__item-inner">
13 <transition name="fade">
14 <p class="am-msd__item-heading" :class="{ 'am-rtl': isRtl }">
15 {{ displayLabels('menu_title') }}
16 </p>
17 </transition>
18 <transition name="fade">
19 <div class="am-msd__item-icon">
20 <span class="am-icon-close"></span>
21 </div>
22 </transition>
23 </div>
24 </div>
25 <template v-for="(step, index) in menuItems" :key="step.key">
26 <div
27 v-if="step.key !== 'packages' || store.getters['entities/getPackages'].length"
28 class="am-msd__item"
29 :class="{ selected: monitor === step.key }"
30 @click="menuSelection(step, index)"
31 >
32 <div class="am-msd__item-inner">
33 <div class="am-msd__item-icon">
34 <span :class="`am-icon-${step.icon}`"></span>
35 </div>
36 <transition name="fade">
37 <p class="am-msd__item-heading" :class="{ 'am-rtl': isRtl }">
38 {{ step.label }}
39 </p>
40 </transition>
41 <transition name="fade">
42 <div class="am-msd__item-indicator" :class="{ 'am-rtl': isRtl }">
43 <span :class="isRtl ? 'am-icon-arrow-big-left' : 'am-icon-arrow-big-right'"></span>
44 </div>
45 </transition>
46 </div>
47 </div>
48 <div v-if="index === 0" class="am-msd__item-divider"></div>
49 </template>
50 </div>
51
52 <template #footer>
53 <div class="am-msd__item" @click="() => emits('logout')">
54 <div class="am-msd__item-inner">
55 <div class="am-msd__item-icon">
56 <span class="am-icon-logout"></span>
57 </div>
58 <p class="am-msd__item-heading">
59 {{ displayLabels('log_out') }}
60 </p>
61 </div>
62 </div>
63 </template>
64 </AmSlidePopup>
65 </template>
66
67 <script setup>
68 // * _components
69 import AmSlidePopup from '../../../_components/slide-popup/AmSlidePopup.vue'
70
71 // * Import from Vue
72 import { computed, inject } from 'vue'
73
74 import { useStore } from 'vuex'
75
76 // * Components Props
77 let props = defineProps({
78 visibility: {
79 type: Boolean,
80 required: true,
81 },
82 customizedLabels: {
83 type: Object,
84 default: () => {
85 return {}
86 },
87 },
88 monitor: {
89 type: String,
90 required: true,
91 },
92 menuItems: {
93 type: Array,
94 required: true,
95 },
96 customCss: {
97 type: Object,
98 default: () => {},
99 },
100 width: {
101 type: Number,
102 default: 300,
103 },
104 position: {
105 type: String,
106 default: 'right',
107 validator(value) {
108 return ['right', 'left', 'top', 'bottom'].includes(value)
109 },
110 },
111 })
112
113 // * Components Emits
114 let emits = defineEmits(['click', 'update:visibility', 'logout'])
115
116 let amLabels = inject('labels')
117
118 const store = useStore()
119
120 // * Component text orientation
121 let isRtl = computed(() => {
122 if (document) {
123 return document.documentElement.dir === 'rtl'
124 }
125
126 return false
127 })
128
129 function menuSelection(step, index) {
130 let obj = { step, index }
131 emits('click', obj)
132 emits('update:visibility', false)
133 }
134
135 function closeMenu() {
136 emits('update:visibility', false)
137 }
138
139 function displayLabels(label) {
140 return Object.keys(props.customizedLabels).length && props.customizedLabels[label]
141 ? props.customizedLabels[label]
142 : amLabels[label]
143 }
144
145 let cssVars = computed(() => {
146 return {
147 '--am-mw-msd': `${props.width}px`,
148 }
149 })
150 </script>
151
152 <style lang="scss">
153 @mixin menu-slide-dialog {
154 // am -- amelia
155 // msd -- menu slide dialog
156 .am-msd {
157 flex-direction: column;
158 justify-content: space-between;
159 font-size: 16px;
160 color: var(--am-c-msd-text);
161 transition: width 0.3s ease-in-out;
162
163 &.am-slide-popup__block-inner {
164 display: flex;
165 border-radius: 0.5rem 0 0 0.5rem;
166 background-color: var(--am-c-msd-bgr);
167 padding: 16px 8px 16px 16px;
168
169 &.am-position-right,
170 &.am-position-left {
171 max-width: var(--am-mw-msd);
172 width: 100%;
173 }
174
175 &.am-position-top {
176 border-radius: 8px 8px 0 0;
177 }
178
179 &.am-position-right {
180 border-radius: 0 8px 8px 0;
181 }
182
183 &.am-position-left {
184 border-radius: 8px 0 0 8px;
185 }
186
187 &.am-position-bottom {
188 border-radius: 0 0 8px 8px;
189 }
190 }
191
192 * {
193 box-sizing: border-box;
194 font-family: var(--am-font-family);
195 }
196
197 // Sidebar Step
198 &__item {
199 width: 100%;
200 display: flex;
201 align-items: center;
202 justify-content: space-between;
203 border-radius: 4px;
204 padding: 8px;
205 margin-bottom: 8px;
206
207 $count: 100;
208 @for $i from 0 through $count {
209 &:nth-child(#{$i + 1}) {
210 animation: 400ms cubic-bezier(0.45, 1, 0.4, 1.2) #{$i * 70}ms am-animation-slide-right;
211 animation-fill-mode: both;
212 }
213 }
214
215 &.selected {
216 background-color: var(--am-c-msd-text-op10);
217
218 .am-msd__item-indicator {
219 display: flex;
220 }
221 }
222
223 // Sidebar Step Wrapper
224 &-wrapper {
225 padding: 0 8px 0 0;
226 overflow-x: hidden;
227
228 // Main Scroll styles
229 &::-webkit-scrollbar {
230 width: 6px;
231 }
232
233 &::-webkit-scrollbar-thumb {
234 border-radius: 6px;
235 background: var(--am-c-scroll-op30);
236 }
237
238 &::-webkit-scrollbar-track {
239 border-radius: 6px;
240 background: var(--am-c-scroll-op10);
241 }
242
243 .el-skeleton {
244 .el-skeleton__text {
245 --el-skeleton-color: var(--am-c-skeleton-sb-op20);
246 --el-skeleton-to-color: var(--am-c-skeleton-sb-op60);
247 }
248 padding: 0;
249 }
250 }
251
252 // Sidebar Step Inner
253 &-inner {
254 width: 100%;
255 display: flex;
256 align-items: center;
257 justify-content: space-between;
258 }
259
260 // Sidebar Step Icon
261 &-icon {
262 position: relative;
263 width: 24px;
264 height: 20px;
265 font-size: 24px;
266
267 span {
268 display: block;
269 position: absolute;
270 top: 50%;
271 left: 50%;
272 transform: translate(-50%, -50%);
273 }
274 }
275
276 // Sidebar Step Heading
277 &-heading {
278 font-family: var(--am-font-family);
279 font-size: 14px;
280 font-weight: 500;
281 line-height: 1.43;
282 margin: 0 auto 0 6px;
283
284 &.am-rtl {
285 margin: 0 6px 0 auto;
286 }
287
288 &.fade-enter-active {
289 animation: sidebar-step-selection 1s;
290 }
291
292 &.fade-leave-active {
293 animation: sidebar-step-selection 1s reverse;
294 }
295 }
296
297 // Sidebar Item Indicator
298 &-indicator {
299 display: none;
300 align-items: center;
301 justify-content: center;
302 font-size: 24px;
303 line-height: 20px;
304 margin-left: auto;
305
306 &.am-rtl {
307 margin-left: 0;
308 margin-right: auto;
309 }
310 }
311
312 // Sidebar Item Divider
313 &-divider {
314 border-top: 1px solid var(--am-c-msd-text-op60);
315 margin: 16px 0;
316 }
317 }
318 }
319 }
320
321 @keyframes sidebar-step-selection {
322 0% {
323 opacity: 0;
324 transform: translateX(-100%);
325 }
326 50% {
327 transform: translateX(10%);
328 }
329 100% {
330 opacity: 1;
331 transform: translateX(0);
332 }
333 }
334
335 // Public
336 .amelia-v2-booking #amelia-container {
337 @include menu-slide-dialog;
338 }
339
340 // Admin
341 #amelia-app-backend-new {
342 @include menu-slide-dialog;
343 }
344 </style>
345