PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 1.2.20
Booking for Appointments and Events Calendar – Amelia v1.2.20
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 / _components / collapse / AmCollapseItem.vue
ameliabooking / v3 / src / views / _components / collapse Last commit date
AmCollapse.vue 3 years ago AmCollapseItem.vue 2 years ago
AmCollapseItem.vue
371 lines
1 <template>
2 <div
3 class="am-collapse-item"
4 :class="[
5 {'am-collapse-item-no-button': !partsVisibility || props.side},
6 {'am-collapse-item-no-border': props.borderless},
7 {'am-collapse-item__arrow' : props.side && partsVisibility},
8 {'am-collapse-item__open': contentVisibility}
9 ]"
10 :style="cssVars"
11 >
12 <div
13 class="am-collapse-item__heading"
14 :class="[
15 {'am-collapse-item__heading-active' : contentVisibility},
16 {'am-collapse-item__heading-side' : contentVisibility && props.side},
17 props.headingClass
18 ]"
19 @click="toggleContentHeading"
20 >
21 <slot name="heading"></slot>
22 <div v-if="props.side && partsVisibility" class="am-collapse-item__trigger am-collapse-item__trigger-side">
23 <slot name="icon-start" class="am-collapse-item__trigger-start"></slot>
24 <span class="am-icon-arrow-down" :class="{'am-rotate-180': contentVisibility}"></span>
25 <slot name="icon-end"></slot>
26 </div>
27 <slot name="icon-below"></slot>
28 </div>
29
30 <template v-if="partsVisibility">
31 <div
32 ref="collapseContent"
33 class="am-collapse-item__content"
34 :class="[
35 {'am-collapse-item__content-no-border' : !props.side},
36 contentVisibility ? 'am-collapse-item__content-open' : 'am-collapse-item__content-close',
37 contentClosing ? 'am-collapse-item__content-closing' : ''
38 ]"
39 >
40 <slot></slot>
41 </div>
42 </template>
43 <div v-if="partsVisibility && !props.side" class="am-collapse-item__trigger" @click="toggleContentButton">
44 <span class="am-collapse-item__trigger-label">
45 <slot v-if="!contentVisibility && !props.buttonClosed.length" name="button-closed"></slot>
46 <template v-if="!contentVisibility && props.buttonClosed.length">
47 {{ props.buttonClosed }}
48 </template>
49 <slot v-if="contentVisibility && !props.buttonOpened.length" name="button-opened"></slot>
50 <template v-if="contentVisibility && props.buttonOpened.length">
51 {{ props.buttonOpened }}
52 </template>
53 </span>
54 <span class="am-icon-arrow-down" :class="{'am-rotate-180': contentVisibility}"></span>
55 </div>
56 </div>
57 </template>
58
59 <script setup>
60 // * Import from Vue
61 import {
62 inject,
63 ref,
64 reactive,
65 computed,
66 useSlots
67 } from 'vue';
68
69 // * Composables
70 import { useColorTransparency } from "../../../assets/js/common/colorManipulation";
71
72 /**
73 * Component Props
74 */
75 let props = defineProps({
76 buttonOpened: {
77 type: String,
78 default: ''
79 },
80 buttonClosed: {
81 type: String,
82 default: ''
83 },
84 side: {
85 type: Boolean,
86 default: false
87 },
88 borderless: {
89 type: Boolean,
90 default: false
91 },
92 type: {
93 type: String,
94 default: ''
95 },
96 delay: {
97 type: Number,
98 default: 500
99 },
100 headingClass: {
101 type: String,
102 default: ''
103 }
104 })
105
106 /**
107 * Component Emits
108 * @type {EmitFn<(string)[]>}
109 */
110 const emits = defineEmits(['collapseOpen', 'collapseClose', 'collapseClicked'])
111
112 // * Template slots
113 let slots = useSlots()
114
115 let partsVisibility = computed(() => {
116 return slots.default().length && slots.default()[0].props !== null
117 })
118
119 // * Card Expand variable
120 let contentVisibility = ref(false)
121 let contentClosing = ref(false)
122 let collapseContent = ref(null)
123 let collapseHeight = reactive({
124 h: '0px'
125 })
126
127 function closingCollapse () {
128 contentClosing.value = true
129 setTimeout(() => {
130 contentClosing.value = false
131 }, 480)
132 }
133
134 function toggleContentHeading () {
135 if (props.side) {
136 toggleContent()
137 }
138 }
139
140 // * Card Expand Function
141 function toggleContentButton () {
142 if (collapseContent.value) {
143 toggleContent()
144 }
145 }
146
147 // * Card Expand Function
148 function toggleContent () {
149 emits('collapseClicked')
150 if (partsVisibility.value) {
151 setTimeout(() => {
152 if (collapseContent.value) {
153 collapseHeight.h = `${collapseContent.value.offsetHeight}px`
154 }
155 if (contentVisibility.value) closingCollapse()
156 contentVisibility.value = !contentVisibility.value
157 if (contentVisibility.value) emits('collapseOpen')
158 if (!contentVisibility.value) emits('collapseClose')
159 }, props.delay)
160 }
161 }
162
163 function closingFromParent () {
164 if (contentVisibility.value) closingCollapse()
165 contentVisibility.value = false
166 }
167
168 function openingFromParent () {
169 contentVisibility.value = true
170 }
171
172
173 defineExpose({
174 closingFromParent,
175 openingFromParent,
176 contentVisibility
177 })
178
179 // * Colors
180 let amColors = inject('amColors', ref({
181 colorPrimary: '#1246D6',
182 colorSuccess: '#019719',
183 colorError: '#B4190F',
184 colorWarning: '#CCA20C',
185 colorMainBgr: '#FFFFFF',
186 colorMainHeadingText: '#33434C',
187 colorMainText: '#1A2C37',
188 colorSbBgr: '#17295A',
189 colorSbText: '#FFFFFF',
190 colorInpBgr: '#FFFFFF',
191 colorInpBorder: '#D1D5D7',
192 colorInpText: '#1A2C37',
193 colorInpPlaceHolder: '#1A2C37',
194 colorDropBgr: '#FFFFFF',
195 colorDropBorder: '#D1D5D7',
196 colorDropText: '#0E1920',
197 colorBtnPrim: '#265CF2',
198 colorBtnPrimText: '#FFFFFF',
199 colorBtnSec: '#1A2C37',
200 colorBtnSecText: '#FFFFFF',
201 }))
202 let cssVars = computed(() => {
203 return {
204 '--am-c-collapse-text-op80': useColorTransparency(amColors.value.colorMainText, 0.8),
205 '--am-delay-collapse': `${props.delay}ms`,
206 }
207 })
208 </script>
209
210 <style lang="scss">
211 $collapseContentHeight: v-bind('collapseHeight.h');
212
213 @keyframes am-animation-collapse-open {
214 0%{height: 0;}
215 100%{height: $collapseContentHeight;}
216 }
217
218 @keyframes am-animation-collapse-close {
219 0%{height: $collapseContentHeight;}
220 100%{height: 0;}
221 }
222
223 @mixin am-collapse-item-block {
224 // Collapse card
225 // am -- amelia
226 // c - color
227 // v - visible
228 .am-collapse-item {
229 --am-c-collapse-border: var(--am-c-inp-border);
230 --am-c-collapse-text: var(--am-c-main-text);
231 --am-combo-collapse-border: 1px solid var(--am-c-inp-border);
232 --am-pointer-collapse: unset;
233 position: relative;
234 margin: 8px 0;
235 overflow: hidden;
236
237 &-no-button {
238 .am-collapse-item__heading {
239 border-radius: 8px;
240 &-side {
241 border-radius: 8px 8px 0 0;
242 border-bottom: 0;
243 }
244 }
245 }
246
247 &-no-border {
248 --am-combo-collapse-border: none;
249 }
250
251 &__arrow {
252 --am-pointer-collapse: pointer;
253 }
254
255 * {
256 font-family: var(--am-font-family);
257 box-sizing: border-box;
258 }
259
260 // Collapse header
261 &__heading {
262 display: flex;
263 justify-content: space-between;
264 align-items: center;
265 border-radius: 8px 8px 0 0;
266 padding: 16px;
267 border: var(--am-combo-collapse-border);
268 cursor: var(--am-pointer-collapse);
269 transition-delay: var(--am-delay-collapse);
270
271 &-side {
272 transition-delay: 0ms;
273 }
274 }
275
276 // Collapse card content
277 &__content {
278 display: flex;
279 font-size: 14px;
280 font-weight: 400;
281 line-height: 1.4285;
282 color: var(--am-c-collapse-text-op80);
283 border: var(--am-combo-collapse-border);
284 border-radius: 0 0 8px 8px;
285 overflow: hidden;
286 position: absolute;
287 opacity: 0;
288 z-index: -1;
289
290 & > * {
291 padding: 16px;
292 }
293
294 &-no-border {
295 border-radius: 0;
296 border-top: 0;
297 border-bottom: 0;
298 }
299
300 &-open {
301 position: relative;
302 opacity: 1;
303 z-index: 100;
304 animation: 500ms ease-in-out am-animation-collapse-open;
305 }
306
307 &-closing {
308 position: relative;
309 opacity: 1;
310 z-index: 100;
311 }
312
313 &-close {
314 animation: 500ms ease-in-out am-animation-collapse-close;
315 }
316 }
317
318 // Collapse trigger button
319 &__trigger {
320 display: flex;
321 align-items: center;
322 justify-content: center;
323 font-size: 13px;
324 line-height: 1.5385;
325 color: var(--am-c-collapse-text);
326 padding: 8px 16px;
327 border: var(--am-combo-collapse-border);
328 border-top: none;
329 border-radius: 0 0 8px 8px;
330 cursor: pointer;
331
332 &-side {
333 border: none
334 }
335
336 &-label {
337 font-size: 13px;
338 line-height: 1.5385;
339 color: var(--am-c-collapse-text);
340 }
341
342 .am-icon-arrow-down {
343 font-size: 16px;
344 line-height: 1.4;
345 color: var(--am-c-collapse-text);
346 transition: all 0.3s ease-in-out;
347
348 &.am-rotate-180 {
349 transform: rotate(180deg);
350 }
351 }
352 }
353 }
354 }
355
356 // public
357 .amelia-v2-booking #amelia-container {
358 @include am-collapse-item-block;
359 }
360
361 // admin
362 #amelia-app-backend-new {
363 @include am-collapse-item-block;
364 }
365
366 // modal popup
367 .am-dialog-popup {
368 @include am-collapse-item-block;
369 }
370 </style>
371