@ozdao/martyrs 0.2.424 → 0.2.426
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builder.js +2 -12
- package/dist/builder.mjs +2 -12
- package/dist/martyrs/src/components/Block/Block.vue.cjs +1 -1
- package/dist/martyrs/src/components/Block/Block.vue.js +1 -1
- package/dist/martyrs/src/components/PhotoViewer/PhotoViewer.vue.cjs +87 -5
- package/dist/martyrs/src/components/PhotoViewer/PhotoViewer.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/PhotoViewer/PhotoViewer.vue.js +88 -6
- package/dist/martyrs/src/components/PhotoViewer/PhotoViewer.vue.js.map +1 -1
- package/dist/martyrs/src/components/Tooltip/{Tooltip.vue.cjs → Tooltip.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Tooltip/Tooltip.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Tooltip/{Tooltip.vue.js → Tooltip.vue2.js} +2 -2
- package/dist/martyrs/src/components/Tooltip/{Tooltip.vue.cjs.map → Tooltip.vue2.js.map} +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/CardHeader.vue.cjs +1 -1
- package/dist/martyrs/src/modules/globals/views/components/blocks/CardHeader.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.cjs +1 -1
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.cjs +1 -1
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/ImagesThumbnails.vue.cjs +52 -14
- package/dist/martyrs/src/modules/products/components/blocks/ImagesThumbnails.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/blocks/ImagesThumbnails.vue.js +53 -15
- package/dist/martyrs/src/modules/products/components/blocks/ImagesThumbnails.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs +37 -65
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +38 -66
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js.map +1 -1
- package/dist/style.css +39 -61
- package/package.json +1 -1
- package/src/builder/modes/spa.dev.js +3 -1
- package/src/builder/modes/spa.prod.js +1 -1
- package/src/builder/modes/ssr.dev.js +10 -10
- package/src/components/PhotoViewer/PhotoViewer.vue +140 -12
- package/src/modules/products/components/blocks/ImagesThumbnails.vue +46 -37
- package/src/modules/products/components/pages/Product.vue +5 -28
- package/dist/martyrs/src/components/Tooltip/Tooltip.vue.js.map +0 -1
|
@@ -3,47 +3,119 @@
|
|
|
3
3
|
<img loading="lazy" :src="photoUrl" :style="imgStyle" ref="image" @load="initialize" />
|
|
4
4
|
</div>
|
|
5
5
|
</template>
|
|
6
|
-
|
|
7
6
|
<script setup>
|
|
8
|
-
import { ref, reactive, computed } from 'vue';
|
|
9
|
-
|
|
7
|
+
import { ref, reactive, computed, onMounted, watch } from 'vue';
|
|
10
8
|
const props = defineProps({
|
|
11
9
|
photoUrl: String,
|
|
12
10
|
show: Boolean,
|
|
13
11
|
});
|
|
14
|
-
|
|
15
12
|
const scale = ref(1);
|
|
16
13
|
const position = reactive({ x: 0, y: 0 });
|
|
17
14
|
const dragging = ref(false);
|
|
18
15
|
const startPosition = reactive({ x: 0, y: 0 });
|
|
19
16
|
const startScale = ref(1);
|
|
20
17
|
const startDistance = ref(0);
|
|
18
|
+
const image = ref(null);
|
|
19
|
+
const container = ref(null);
|
|
21
20
|
|
|
22
21
|
const imgStyle = computed(() => ({
|
|
23
22
|
transform: `scale(${scale.value}) translate(${position.x}px, ${position.y}px)`,
|
|
24
23
|
}));
|
|
25
24
|
|
|
25
|
+
// Наблюдаем за изменением масштаба, чтобы ограничивать позицию
|
|
26
|
+
watch(scale, () => {
|
|
27
|
+
constrainPosition();
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const getImageDimensions = () => {
|
|
31
|
+
if (!image.value) return { width: 0, height: 0 };
|
|
32
|
+
|
|
33
|
+
// Используем естественные размеры изображения
|
|
34
|
+
const imgWidth = image.value.naturalWidth;
|
|
35
|
+
const imgHeight = image.value.naturalHeight;
|
|
36
|
+
|
|
37
|
+
// Получаем размеры контейнера
|
|
38
|
+
const containerRect = image.value.parentElement?.getBoundingClientRect();
|
|
39
|
+
if (!containerRect) return { width: 0, height: 0 };
|
|
40
|
+
|
|
41
|
+
const containerWidth = containerRect.width;
|
|
42
|
+
const containerHeight = containerRect.height;
|
|
43
|
+
|
|
44
|
+
// Определяем, как изображение вписывается в контейнер (с учетом object-fit: scale-down)
|
|
45
|
+
let renderedWidth, renderedHeight;
|
|
46
|
+
|
|
47
|
+
if (imgWidth > containerWidth || imgHeight > containerHeight) {
|
|
48
|
+
const ratioX = containerWidth / imgWidth;
|
|
49
|
+
const ratioY = containerHeight / imgHeight;
|
|
50
|
+
const ratio = Math.min(ratioX, ratioY);
|
|
51
|
+
|
|
52
|
+
renderedWidth = imgWidth * ratio;
|
|
53
|
+
renderedHeight = imgHeight * ratio;
|
|
54
|
+
} else {
|
|
55
|
+
renderedWidth = imgWidth;
|
|
56
|
+
renderedHeight = imgHeight;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
renderedWidth,
|
|
61
|
+
renderedHeight,
|
|
62
|
+
containerWidth,
|
|
63
|
+
containerHeight
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
26
67
|
const handleWheel = (event) => {
|
|
27
68
|
event.preventDefault();
|
|
69
|
+
|
|
28
70
|
const delta = event.deltaY > 0 ? -0.1 : 0.1;
|
|
29
|
-
|
|
71
|
+
const newScale = Math.min(Math.max(1, scale.value + delta), 3);
|
|
72
|
+
|
|
73
|
+
// Рассчитываем позицию курсора относительно центра изображения
|
|
74
|
+
const rect = image.value.getBoundingClientRect();
|
|
75
|
+
const mouseX = event.clientX - rect.left - rect.width / 2;
|
|
76
|
+
const mouseY = event.clientY - rect.top - rect.height / 2;
|
|
77
|
+
|
|
78
|
+
// Сохраняем соотношение позиции курсора к изображению при масштабировании
|
|
79
|
+
const scaleChange = newScale / scale.value;
|
|
80
|
+
|
|
81
|
+
// Обновляем позицию так, чтобы точка под курсором оставалась на месте
|
|
82
|
+
position.x = position.x - (mouseX / scale.value) * (scaleChange - 1);
|
|
83
|
+
position.y = position.y - (mouseY / scale.value) * (scaleChange - 1);
|
|
84
|
+
|
|
85
|
+
// Обновляем масштаб
|
|
86
|
+
scale.value = newScale;
|
|
87
|
+
|
|
88
|
+
// Ограничиваем позицию после обновления масштаба
|
|
89
|
+
constrainPosition();
|
|
30
90
|
};
|
|
31
91
|
|
|
32
92
|
const startDrag = (event) => {
|
|
33
93
|
event.preventDefault();
|
|
94
|
+
if (scale.value <= 1) return; // Не позволяем перетаскивать при масштабе 1
|
|
95
|
+
|
|
34
96
|
dragging.value = true;
|
|
35
97
|
startPosition.x = event.type === 'mousedown' ? event.clientX : event.touches[0].clientX;
|
|
36
98
|
startPosition.y = event.type === 'mousedown' ? event.clientY : event.touches[0].clientY;
|
|
99
|
+
|
|
37
100
|
const move = (moveEvent) => {
|
|
38
101
|
if (dragging.value) {
|
|
39
102
|
const currentX = moveEvent.type === 'mousemove' ? moveEvent.clientX : moveEvent.touches[0].clientX;
|
|
40
103
|
const currentY = moveEvent.type === 'mousemove' ? moveEvent.clientY : moveEvent.touches[0].clientY;
|
|
41
|
-
|
|
42
|
-
|
|
104
|
+
|
|
105
|
+
const deltaX = (currentX - startPosition.x) / scale.value;
|
|
106
|
+
const deltaY = (currentY - startPosition.y) / scale.value;
|
|
107
|
+
|
|
108
|
+
position.x += deltaX;
|
|
109
|
+
position.y += deltaY;
|
|
110
|
+
|
|
111
|
+
// Ограничиваем позицию после перемещения
|
|
112
|
+
constrainPosition();
|
|
113
|
+
|
|
43
114
|
startPosition.x = currentX;
|
|
44
115
|
startPosition.y = currentY;
|
|
45
116
|
}
|
|
46
117
|
};
|
|
118
|
+
|
|
47
119
|
const endDrag = () => {
|
|
48
120
|
dragging.value = false;
|
|
49
121
|
document.removeEventListener('mousemove', move);
|
|
@@ -51,6 +123,7 @@ const startDrag = (event) => {
|
|
|
51
123
|
document.removeEventListener('touchmove', move);
|
|
52
124
|
document.removeEventListener('touchend', endDrag);
|
|
53
125
|
};
|
|
126
|
+
|
|
54
127
|
document.addEventListener('mousemove', move);
|
|
55
128
|
document.addEventListener('mouseup', endDrag);
|
|
56
129
|
document.addEventListener('touchmove', move);
|
|
@@ -79,7 +152,25 @@ const handleTouchMove = (event) => {
|
|
|
79
152
|
const distanceY = Math.abs(touch1.clientY - touch2.clientY);
|
|
80
153
|
const newDistance = Math.sqrt(distanceX ** 2 + distanceY ** 2);
|
|
81
154
|
const scaleFactor = newDistance / startDistance.value;
|
|
82
|
-
|
|
155
|
+
|
|
156
|
+
// Получаем центр между двумя касаниями
|
|
157
|
+
const centerX = (touch1.clientX + touch2.clientX) / 2;
|
|
158
|
+
const centerY = (touch1.clientY + touch2.clientY) / 2;
|
|
159
|
+
|
|
160
|
+
// Получаем координаты центра касания относительно изображения
|
|
161
|
+
const rect = image.value.getBoundingClientRect();
|
|
162
|
+
const touchCenterX = centerX - rect.left - rect.width / 2;
|
|
163
|
+
const touchCenterY = centerY - rect.top - rect.height / 2;
|
|
164
|
+
|
|
165
|
+
const newScale = Math.min(Math.max(1, startScale.value * scaleFactor), 3);
|
|
166
|
+
const scaleChange = newScale / scale.value;
|
|
167
|
+
|
|
168
|
+
// Обновляем позицию, чтобы центр касания оставался на месте
|
|
169
|
+
position.x = position.x - (touchCenterX / scale.value) * (scaleChange - 1);
|
|
170
|
+
position.y = position.y - (touchCenterY / scale.value) * (scaleChange - 1);
|
|
171
|
+
|
|
172
|
+
scale.value = newScale;
|
|
173
|
+
constrainPosition();
|
|
83
174
|
}
|
|
84
175
|
};
|
|
85
176
|
|
|
@@ -94,8 +185,45 @@ const initialize = () => {
|
|
|
94
185
|
position.x = 0;
|
|
95
186
|
position.y = 0;
|
|
96
187
|
};
|
|
97
|
-
</script>
|
|
98
188
|
|
|
189
|
+
const constrainPosition = () => {
|
|
190
|
+
// Если масштаб 1, сбрасываем позицию в центр
|
|
191
|
+
if (scale.value <= 1) {
|
|
192
|
+
position.x = 0;
|
|
193
|
+
position.y = 0;
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const { renderedWidth, renderedHeight, containerWidth, containerHeight } = getImageDimensions();
|
|
198
|
+
|
|
199
|
+
// Вычисляем максимальное смещение
|
|
200
|
+
const scaledWidth = renderedWidth * scale.value;
|
|
201
|
+
const scaledHeight = renderedHeight * scale.value;
|
|
202
|
+
|
|
203
|
+
// Отступ от края изображения до края контейнера при текущем масштабе
|
|
204
|
+
const horizontalOffset = (scaledWidth - containerWidth) / 2 / scale.value;
|
|
205
|
+
const verticalOffset = (scaledHeight - containerHeight) / 2 / scale.value;
|
|
206
|
+
|
|
207
|
+
// Ограничиваем смещение, чтобы изображение не выходило за пределы контейнера
|
|
208
|
+
if (horizontalOffset > 0) {
|
|
209
|
+
position.x = Math.max(-horizontalOffset, Math.min(horizontalOffset, position.x));
|
|
210
|
+
} else {
|
|
211
|
+
position.x = 0;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (verticalOffset > 0) {
|
|
215
|
+
position.y = Math.max(-verticalOffset, Math.min(verticalOffset, position.y));
|
|
216
|
+
} else {
|
|
217
|
+
position.y = 0;
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
onMounted(() => {
|
|
222
|
+
window.addEventListener('resize', () => {
|
|
223
|
+
constrainPosition();
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
</script>
|
|
99
227
|
<style>
|
|
100
228
|
.photo-container {
|
|
101
229
|
width: 100%;
|
|
@@ -105,11 +233,11 @@ const initialize = () => {
|
|
|
105
233
|
position: relative;
|
|
106
234
|
cursor: grab;
|
|
107
235
|
}
|
|
108
|
-
|
|
109
236
|
.photo-container img {
|
|
110
237
|
width: 100%;
|
|
111
238
|
height: 100%;
|
|
112
239
|
object-fit: scale-down;
|
|
113
|
-
transition: transform 0.
|
|
240
|
+
transition: transform 0.05s;
|
|
241
|
+
transform-origin: center center;
|
|
114
242
|
}
|
|
115
|
-
</style>
|
|
243
|
+
</style>
|
|
@@ -1,14 +1,41 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="o-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
2
|
+
<div class="w-100 o-hidden bg-light radius-big flex-nowrap flex-column flex pos-relative">
|
|
3
|
+
<!-- Main image container -->
|
|
4
|
+
<div class="pd-semi w-100 bg-light radius-semi o-hidden" @click="openPopup(images[0])">
|
|
5
|
+
<Images360
|
|
6
|
+
v-if="product && product.image3d"
|
|
7
|
+
class="h-100 w-100"
|
|
8
|
+
:imagePath="`/assets/images/products/${product.image3d}`"
|
|
9
|
+
:imageCount="36"
|
|
10
10
|
/>
|
|
11
|
+
<img
|
|
12
|
+
loading="lazy"
|
|
13
|
+
v-if="images[0] && !product?.image3d"
|
|
14
|
+
class="h-max h-max-15r bg-white radius-semi w-100"
|
|
15
|
+
style="object-fit: contain;"
|
|
16
|
+
:src="(FILE_SERVER_URL || '') + images[0]"
|
|
17
|
+
/>
|
|
18
|
+
<PlaceholderImage
|
|
19
|
+
v-if="!images[0] && !product?.image3d"
|
|
20
|
+
class="h-max-20r h-100 w-100"
|
|
21
|
+
style="object-fit: cover;"
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<!-- Thumbnails -->
|
|
26
|
+
<div v-if="images.length > 1" class="o-scroll w-100 pd-semi pd-t-zero">
|
|
27
|
+
<div class="no-responsive w-max flex flex-nowrap gap-thin">
|
|
28
|
+
<img loading="lazy"
|
|
29
|
+
v-for="(image, index) in images"
|
|
30
|
+
:key="index"
|
|
31
|
+
:src="(FILE_SERVER_URL || '') + image"
|
|
32
|
+
@click="openPopup(image)"
|
|
33
|
+
class="flex-child flex-child-grow-1 aspect-1x1 radius-semi bg-white o-hidden thumbnail"
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
11
36
|
</div>
|
|
37
|
+
|
|
38
|
+
<!-- Popup with photo viewer -->
|
|
12
39
|
<Popup @close-popup="closePopup" :isPopupOpen="isPopupVisible" class="radius-medium o-hidden">
|
|
13
40
|
<PhotoViewer
|
|
14
41
|
:photoUrl="(FILE_SERVER_URL || '') + selectedImage"
|
|
@@ -20,20 +47,28 @@
|
|
|
20
47
|
<script setup>
|
|
21
48
|
import { ref } from "vue";
|
|
22
49
|
|
|
23
|
-
import Popup from '@martyrs/src/components/Popup/Popup.vue'
|
|
24
|
-
import PhotoViewer from '@martyrs/src/components/PhotoViewer/PhotoViewer.vue'
|
|
50
|
+
import Popup from '@martyrs/src/components/Popup/Popup.vue';
|
|
51
|
+
import PhotoViewer from '@martyrs/src/components/PhotoViewer/PhotoViewer.vue';
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
import Images360 from '@martyrs/src/modules/products/components/blocks/Images360.vue'
|
|
25
55
|
|
|
26
56
|
const props = defineProps({
|
|
27
57
|
images: {
|
|
28
58
|
type: Array,
|
|
29
59
|
required: true,
|
|
30
|
-
}
|
|
60
|
+
},
|
|
61
|
+
product: {
|
|
62
|
+
type: Object,
|
|
63
|
+
default: () => ({})
|
|
64
|
+
},
|
|
31
65
|
});
|
|
32
66
|
|
|
33
67
|
const isPopupVisible = ref(false);
|
|
34
68
|
const selectedImage = ref(null);
|
|
35
69
|
|
|
36
70
|
const openPopup = (image) => {
|
|
71
|
+
if (!image) return;
|
|
37
72
|
selectedImage.value = image;
|
|
38
73
|
isPopupVisible.value = true;
|
|
39
74
|
};
|
|
@@ -44,14 +79,6 @@ const closePopup = () => {
|
|
|
44
79
|
</script>
|
|
45
80
|
|
|
46
81
|
<style scoped>
|
|
47
|
-
.magnifier {
|
|
48
|
-
max-width: 32rem;
|
|
49
|
-
}
|
|
50
|
-
.product-images {
|
|
51
|
-
display: flex;
|
|
52
|
-
flex-direction: column;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
82
|
.thumbnail {
|
|
56
83
|
width: 100%;
|
|
57
84
|
max-width: 6rem;
|
|
@@ -59,22 +86,4 @@ const closePopup = () => {
|
|
|
59
86
|
object-fit: cover;
|
|
60
87
|
cursor: pointer;
|
|
61
88
|
}
|
|
62
|
-
|
|
63
|
-
.popup {
|
|
64
|
-
position: fixed;
|
|
65
|
-
top: 0;
|
|
66
|
-
left: 0;
|
|
67
|
-
width: 100vw;
|
|
68
|
-
height: 100vh;
|
|
69
|
-
background-color: rgba(0, 0, 0, 0.8);
|
|
70
|
-
display: flex;
|
|
71
|
-
justify-content: center;
|
|
72
|
-
align-items: center;
|
|
73
|
-
cursor: zoom-out;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
.popup-image {
|
|
77
|
-
max-width: 90%;
|
|
78
|
-
max-height: 90%;
|
|
79
|
-
}
|
|
80
89
|
</style>
|
|
@@ -1,33 +1,11 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div v-if="products.state.current._id" class="h-100 w-100 mobile:pd-thin pd-big bg-white">
|
|
3
3
|
<div class="cols-2-1_2 w-100 gap-medium">
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
:imagePath="`/assets/images/products/${product.image3d}`"
|
|
10
|
-
:imageCount="36"
|
|
11
|
-
/>
|
|
12
|
-
<img
|
|
13
|
-
loading="lazy"
|
|
14
|
-
v-if="images[0] && !product.image3d"
|
|
15
|
-
class="h-max h-max-15r bg-white radius-semi w-100"
|
|
16
|
-
style="object-fit: contain;"
|
|
17
|
-
:src="(FILE_SERVER_URL || '') + images[0]"
|
|
18
|
-
/>
|
|
19
|
-
<PlaceholderImage
|
|
20
|
-
v-if="!images[0] && !product.image3d"
|
|
21
|
-
class="h-max-20r h-100 w-100"
|
|
22
|
-
style="object-fit: cover;"
|
|
23
|
-
/>
|
|
24
|
-
</div>
|
|
25
|
-
<ImagesThumbnails
|
|
26
|
-
v-if="images.length > 1"
|
|
27
|
-
:images="images"
|
|
28
|
-
class="pd-semi pd-t-zero"
|
|
29
|
-
/>
|
|
30
|
-
</div>
|
|
4
|
+
|
|
5
|
+
<ImagesThumbnails
|
|
6
|
+
:images="images"
|
|
7
|
+
:product="product"
|
|
8
|
+
/>
|
|
31
9
|
|
|
32
10
|
<div class="pos-relative w-100 h-100 flex-column flex-h-center flex">
|
|
33
11
|
<IconEdit
|
|
@@ -138,7 +116,6 @@ import PopupDateSelector from '@martyrs/src/modules/globals/views/components/blo
|
|
|
138
116
|
import IconEdit from '@martyrs/src/modules/icons/navigation/IconEdit.vue'
|
|
139
117
|
import IconShopcartAdd from '@martyrs/src/modules/icons/actions/IconShopcartAdd.vue'
|
|
140
118
|
import PlaceholderImage from '@martyrs/src/modules/icons/placeholders/PlaceholderImage.vue'
|
|
141
|
-
import Images360 from '@martyrs/src/modules/products/components/blocks/Images360.vue'
|
|
142
119
|
import ImagesThumbnails from '@martyrs/src/modules/products/components/blocks/ImagesThumbnails.vue'
|
|
143
120
|
import Price from '@martyrs/src/modules/products/components/elements/Price.vue'
|
|
144
121
|
import PopularProducts from '@martyrs/src/modules/products/components/sections/PopularProducts.vue'
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Tooltip.vue.js","sources":["../../../../../src/components/Tooltip/Tooltip.vue"],"sourcesContent":["<template>\n <div class=\"cursor-pointer tooltip-container\" @mouseover=\"showTooltip\" @mouseleave=\"hideTooltip\">\n <slot></slot>\n <div class=\"tooltip-content\" :style=\"tooltipStyle\">\n {{ text }}\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, reactive } from 'vue';\n\nconst props = defineProps({\n text: {\n type: String,\n required: true\n }\n});\n\nconst visible = ref(false);\n\nconst tooltipStyle = reactive({\n position: 'absolute',\n width: 'max-content',\n zIndex: 1000,\n background: '#333',\n color: '#fff',\n padding: '5px 10px',\n borderRadius: '3px',\n fontSize: '14px',\n display: 'none',\n});\n\nfunction showTooltip(event) {\n visible.value = true;\n tooltipStyle.left = `${(event.clientX / 100) + 10 }px`;\n tooltipStyle.top = `${(event.clientY / 100) + 10 }px`;\n tooltipStyle.display = 'block';\n}\n\nfunction hideTooltip() {\n visible.value = false;\n tooltipStyle.display = 'none';\n}\n</script>\n\n<style >\n.tooltip-container {\n position: relative;\n display: inline-block;\n}\n\n.tooltip-content {\n pointer-events: none;\n}\n</style>"],"names":[],"mappings":";;;;;;;;;;;AAmBA,UAAM,UAAU,IAAI,KAAK;AAEzB,UAAM,eAAe,SAAS;AAAA,MAC5B,UAAU;AAAA,MACV,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd,UAAU;AAAA,MACV,SAAS;AAAA,IACX,CAAC;AAED,aAAS,YAAY,OAAO;AAC1B,cAAQ,QAAQ;AAChB,mBAAa,OAAO,GAAI,MAAM,UAAU,MAAO,EAAE;AACjD,mBAAa,MAAM,GAAI,MAAM,UAAU,MAAO,EAAE;AAChD,mBAAa,UAAU;AAAA,IACzB;AAEA,aAAS,cAAc;AACrB,cAAQ,QAAQ;AAChB,mBAAa,UAAU;AAAA,IACzB;;;;;;;;;;;;;;;;"}
|