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 / _components / dialog / AmDialog.vue
ameliabooking / v3 / src / views / _components / dialog Last commit date
AmDialog.vue 3 weeks ago
AmDialog.vue
327 lines
1 <template>
2 <el-dialog
3 ref="amDialogRef"
4 v-model="model"
5 :modal-class="`am-dialog-popup ${props.modalClass}`"
6 :class="[props.customClass, { 'am-dialog--with-header': hasHeaderContent }]"
7 :title="props.title"
8 :width="props.width"
9 :fullscreen="props.fullscreen"
10 :top="props.top"
11 :modal="props.modal"
12 :append-to-body="props.appendToBody"
13 :append-to="props.appendTo"
14 :lock-scroll="props.lockScroll"
15 :open-delay="props.openDelay"
16 :close-delay="props.closeDelay"
17 :close-on-click-modal="props.closeOnClickModal"
18 :close-on-press-escape="props.closeOnPressEscape"
19 :show-close="props.showClose"
20 :before-close="props.beforeClose"
21 :center="props.center"
22 :align-center="props.alignCenter"
23 :destroy-on-close="props.destroyOnClose"
24 :close-icon="props.closeIcon"
25 :draggable="props.draggable"
26 :overflow="props.overflow"
27 :z-index="props.zIndex"
28 :header-class="props.headerClass"
29 :body-class="props.bodyClass"
30 :footer-class="props.footerClass"
31 :style="props.customStyles"
32 @close="emits('close')"
33 @open="emits('open')"
34 @closed="emits('closed')"
35 @opened="emits('opened')"
36 @open-auto-focus="emits('open-auto-focus', $event)"
37 @close-auto-focus="emits('close-auto-focus', $event)"
38 >
39 <template #header="{ titleId, titleClass }">
40 <slot name="header" />
41 <span v-if="title" :id="titleId" :class="[titleClass, 'am-dialog__title']">{{ title }}</span>
42 <span v-else :id="titleId" :class="titleClass">
43 <slot name="title" />
44 </span>
45 </template>
46
47 <slot />
48
49 <template v-if="$slots.footer" #footer>
50 <slot name="footer" />
51 </template>
52 </el-dialog>
53 </template>
54
55 <script setup>
56 import AmeliaIconClose from '../icons/IconClose.vue'
57
58 // * Import from Vue
59 import { toRefs, computed, ref, onMounted, useSlots } from 'vue'
60
61 /**
62 * Component Props
63 */
64 const props = defineProps({
65 modelValue: {
66 type: [String, Array, Object, Number, Boolean],
67 },
68 modalClass: {
69 type: String,
70 default: '',
71 },
72 title: {
73 type: String,
74 default: '',
75 },
76 width: {
77 type: [String, Number],
78 default: '50%',
79 },
80 fullscreen: {
81 type: Boolean,
82 default: false,
83 },
84 top: {
85 type: String,
86 default: '15vh',
87 },
88 modal: {
89 type: Boolean,
90 default: true,
91 },
92 appendToBody: {
93 type: Boolean,
94 default: false,
95 },
96 appendTo: {
97 type: [String, Object],
98 default: undefined,
99 },
100 alignCenter: {
101 type: Boolean,
102 default: true,
103 },
104 lockScroll: {
105 type: Boolean,
106 default: true,
107 },
108 customClass: {
109 type: String,
110 default: '',
111 },
112 openDelay: {
113 type: Number,
114 default: 0,
115 },
116 closeDelay: {
117 type: Number,
118 default: 0,
119 },
120 closeOnClickModal: {
121 type: Boolean,
122 default: true,
123 },
124 closeOnPressEscape: {
125 type: Boolean,
126 default: true,
127 },
128 showClose: {
129 type: Boolean,
130 default: true,
131 },
132 beforeClose: {
133 type: Function,
134 },
135 center: {
136 type: Boolean,
137 default: false,
138 },
139 destroyOnClose: {
140 type: Boolean,
141 default: false,
142 },
143 closeIcon: {
144 type: [Object, Function],
145 default: AmeliaIconClose,
146 },
147 draggable: {
148 type: Boolean,
149 default: false,
150 },
151 overflow: {
152 type: Boolean,
153 default: false,
154 },
155 zIndex: {
156 type: Number,
157 default: undefined,
158 },
159 headerClass: {
160 type: String,
161 default: '',
162 },
163 bodyClass: {
164 type: String,
165 default: '',
166 },
167 footerClass: {
168 type: String,
169 default: '',
170 },
171 customStyles: {
172 type: Object,
173 },
174 usedForShortcode: {
175 type: Boolean,
176 default: false,
177 },
178 })
179
180 const amDialogRef = ref(null)
181 const slots = useSlots()
182
183 const hasHeaderContent = computed(() => {
184 return Boolean(props.title || slots.header || slots.title)
185 })
186
187 onMounted(() => {
188 if (props.usedForShortcode) {
189 amDialogRef.value.rendered = true
190 }
191 })
192
193 /**
194 * Component Emits
195 * */
196 const emits = defineEmits([
197 'close',
198 'open',
199 'closed',
200 'opened',
201 'open-auto-focus',
202 'close-auto-focus',
203 'update:modelValue',
204 ])
205
206 /**
207 * Component model
208 */
209 let { modelValue } = toRefs(props)
210
211 let model = computed({
212 get: () => modelValue.value,
213 set: (val) => {
214 emits('update:modelValue', val)
215 },
216 })
217 </script>
218
219 <script>
220 export default {
221 inheritAttrs: false,
222 }
223 </script>
224
225 <style lang="scss">
226 .am-dialog-popup {
227 .el-overlay-dialog {
228 overflow: hidden;
229 }
230
231 @media only screen and (max-width: 768px) {
232 .el-overlay-dialog {
233 display: flex !important;
234 align-items: stretch !important;
235 height: 100%;
236 }
237 }
238
239 .el-dialog {
240 max-width: var(--el-dialog-width, 50%);
241 width: 100%;
242 padding: 0;
243 border-radius: 8px;
244 overflow: hidden;
245 background-color: var(--am-c-main-bgr);
246 display: flex;
247 flex-direction: column;
248 max-height: calc(var(--am-dvh, 100dvh) - 80px);
249
250 &__header {
251 padding: 0 24px;
252 min-height: 60px;
253 display: flex;
254 align-items: center;
255 flex-shrink: 0;
256 position: sticky;
257 top: 0;
258 z-index: 2;
259 background-color: var(--am-c-main-bgr);
260 border-radius: 8px 8px 0 0;
261 box-shadow: 0 2px 3px var(--am-c-main-text-op15, rgba(26, 44, 55, 0.15));
262 }
263
264 &.am-dialog--with-header .el-dialog__header {
265 height: 60px;
266 }
267
268 &__headerbtn {
269 top: 16px;
270 right: 16px;
271 width: 24px;
272 height: 24px;
273 background: transparent !important;
274 padding: 0;
275 z-index: 3;
276
277 &:focus {
278 outline: 1px solid var(--am-c-main-text);
279 }
280
281 &:active {
282 position: absolute;
283 border: none;
284 outline: 0;
285 }
286 }
287
288 &__close {
289 .am-icon-close:before {
290 color: var(--am-c-main-text);
291 }
292 }
293
294 &__body {
295 flex: 1 1 auto;
296 min-height: 0;
297 overflow-x: hidden;
298 overflow-y: auto;
299 -webkit-overflow-scrolling: touch;
300 padding: 16px 24px 24px;
301 }
302
303 &__footer {
304 flex-shrink: 0;
305 position: sticky;
306 bottom: 0;
307 z-index: 2;
308 padding: 16px;
309 background-color: var(--am-c-main-bgr);
310 box-shadow: 0 -2px 3px var(--am-c-main-text-op15, rgba(26, 44, 55, 0.15));
311 }
312
313 @media only screen and (max-width: 768px) {
314 height: var(--am-dvh, 100dvh);
315 max-height: var(--am-dvh, 100dvh);
316 margin: 0 !important;
317 max-width: 100% !important;
318 border-radius: 0;
319
320 &.is-align-center {
321 margin: 0 !important;
322 }
323 }
324 }
325 }
326 </style>
327