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 / tabs / AmTabs.vue
ameliabooking / v3 / src / views / _components / tabs Last commit date
AmTabs.vue 3 weeks ago AmTabsItem.vue 3 weeks ago
AmTabs.vue
191 lines
1 <template>
2 <el-tabs
3 :id="id"
4 ref="tabsRef"
5 v-model="model"
6 :type="type"
7 :closable="closable"
8 :addable="addable"
9 :editable="editable"
10 :tab-position="tabPosition"
11 :before-leave="beforeLeave"
12 :stretch="stretch"
13 @tab-click="(...args) => emits('tab-click', ...args)"
14 @tab-change="(...args) => emits('tab-change', ...args)"
15 @tab-remove="(...args) => emits('tab-remove', ...args)"
16 @tab-add="(...args) => emits('tab-add', ...args)"
17 @edit="(...args) => emits('edit', ...args)"
18 >
19 <slot></slot>
20
21 <template v-if="$slots['add-icon']" #add-icon>
22 <slot name="add-icon"></slot>
23 </template>
24 </el-tabs>
25 </template>
26
27 <script setup>
28 import { computed, nextTick, onBeforeUnmount, onMounted, onUpdated, ref, toRefs } from 'vue'
29
30 /**
31 * Component Props
32 */
33 const props = defineProps({
34 id: {
35 type: String,
36 },
37 modelValue: {
38 type: [String, Number],
39 },
40 type: {
41 type: String,
42 default: '',
43 validator: (value) => ['', 'card', 'border-card'].includes(value),
44 },
45 closable: {
46 type: Boolean,
47 default: false,
48 },
49 addable: {
50 type: Boolean,
51 default: false,
52 },
53 editable: {
54 type: Boolean,
55 default: false,
56 },
57 tabPosition: {
58 type: String,
59 default: 'top',
60 validator: (value) => ['top', 'right', 'bottom', 'left'].includes(value),
61 },
62 beforeLeave: {
63 type: Function,
64 default: () => true,
65 },
66 stretch: {
67 type: Boolean,
68 default: false,
69 },
70 tabsArray: {
71 type: Array,
72 },
73 })
74
75 /**
76 * Component Emits
77 * */
78 const emits = defineEmits([
79 'tab-click',
80 'tab-change',
81 'tab-remove',
82 'tab-add',
83 'edit',
84 'update:modelValue',
85 ])
86
87 const tabsRef = ref(null)
88
89 /**
90 * Component model
91 */
92 let { modelValue } = toRefs(props)
93 let model = computed({
94 get: () => modelValue.value,
95 set: (val) => {
96 emits('update:modelValue', val)
97 },
98 })
99
100 defineExpose({
101 currentName: computed(() => tabsRef.value?.currentName),
102 })
103
104 let tabsObserver = null
105 let observedTabsElement = null
106
107 function getTabsElement() {
108 return tabsRef.value && tabsRef.value.$el ? tabsRef.value.$el : tabsRef.value
109 }
110
111 function getDirectTabsChild(tabsElement, className) {
112 return Array.from(tabsElement.children).find((child) => child.classList.contains(className))
113 }
114
115 function moveTabsHeaderBeforeContent() {
116 const tabsElement = getTabsElement()
117
118 if (!tabsElement) {
119 return
120 }
121
122 const headerElement = getDirectTabsChild(tabsElement, 'el-tabs__header')
123 const contentElement = getDirectTabsChild(tabsElement, 'el-tabs__content')
124
125 if (headerElement && contentElement && contentElement.previousElementSibling !== headerElement) {
126 tabsElement.insertBefore(headerElement, contentElement)
127 }
128 }
129
130 function observeTabsDom() {
131 const tabsElement = getTabsElement()
132
133 if (
134 !tabsElement ||
135 observedTabsElement === tabsElement ||
136 typeof MutationObserver === 'undefined'
137 ) {
138 return
139 }
140
141 if (tabsObserver) {
142 tabsObserver.disconnect()
143 }
144
145 observedTabsElement = tabsElement
146 tabsObserver = new MutationObserver(updateTabsDomOrder)
147 tabsObserver.observe(tabsElement, { childList: true })
148 }
149
150 function updateTabsDomOrder() {
151 nextTick(() => {
152 moveTabsHeaderBeforeContent()
153 observeTabsDom()
154 })
155 }
156
157 onMounted(updateTabsDomOrder)
158 onUpdated(updateTabsDomOrder)
159
160 onBeforeUnmount(() => {
161 if (tabsObserver) {
162 tabsObserver.disconnect()
163 }
164 })
165 </script>
166
167 <script>
168 export default {
169 name: 'AmTabs',
170 }
171 </script>
172
173 <style lang="scss">
174 @mixin am-tabs {
175 .el-tabs {
176 display: flex;
177 flex-direction: column !important;
178 gap: 16px 0;
179 }
180 }
181 // public
182 .amelia-v2-booking #amelia-container {
183 @include am-tabs;
184 }
185
186 // admin
187 #amelia-app-backend-new {
188 @include am-tabs;
189 }
190 </style>
191