srcdev-nuxt-components 2.2.0 → 2.2.1
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="slider-gallery" ref="sliderGalleryWrapper">
|
|
2
|
+
<div class="slider-gallery" :class="elementClasses" ref="sliderGalleryWrapper">
|
|
3
3
|
<div class="list" ref="sliderGalleryImagesList">
|
|
4
|
-
<div v-for="item in galleryData" class="item">
|
|
4
|
+
<div v-for="(item, index) in galleryData" :key="index" class="item">
|
|
5
5
|
<img :src="item.src" />
|
|
6
6
|
<div class="content">
|
|
7
7
|
<div class="author">{{ item.stylist }}</div>
|
|
@@ -16,11 +16,11 @@
|
|
|
16
16
|
</div>
|
|
17
17
|
|
|
18
18
|
<div class="thumbnail" ref="sliderGalleryThumbnailsList">
|
|
19
|
-
<div v-for="item in galleryData" class="item">
|
|
19
|
+
<div v-for="(item, index) in galleryData" :key="index" class="item">
|
|
20
20
|
<img :src="item.src" />
|
|
21
21
|
<div class="content">
|
|
22
|
-
<div class="title">
|
|
23
|
-
<div class="description">
|
|
22
|
+
<div class="title" v-show="item.thumbnail?.title !== ''">{{ item.thumbnail?.title }}</div>
|
|
23
|
+
<div class="description" v-show="item.thumbnail?.description !== ''">{{ item.thumbnail?.description }}</div>
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
26
|
</div>
|
|
@@ -30,12 +30,24 @@
|
|
|
30
30
|
<button id="next" ref="nextDom" @click.prevent="doNext()">></button>
|
|
31
31
|
</div>
|
|
32
32
|
|
|
33
|
-
<div class="time"
|
|
33
|
+
<div class="time"></div>
|
|
34
34
|
</div>
|
|
35
35
|
</template>
|
|
36
36
|
|
|
37
37
|
<script setup lang="ts">
|
|
38
38
|
const props = defineProps({
|
|
39
|
+
autoRun: {
|
|
40
|
+
type: Boolean,
|
|
41
|
+
default: true,
|
|
42
|
+
},
|
|
43
|
+
autoRunInterval: {
|
|
44
|
+
type: Number,
|
|
45
|
+
default: 7000,
|
|
46
|
+
},
|
|
47
|
+
animationDuration: {
|
|
48
|
+
type: Number,
|
|
49
|
+
default: 3000,
|
|
50
|
+
},
|
|
39
51
|
styleClassPassthrough: {
|
|
40
52
|
type: Array as PropType<string[]>,
|
|
41
53
|
default: () => [],
|
|
@@ -49,6 +61,10 @@ interface IGalleryData {
|
|
|
49
61
|
title?: string;
|
|
50
62
|
category?: string;
|
|
51
63
|
description?: string;
|
|
64
|
+
thumbnail?: {
|
|
65
|
+
title: string;
|
|
66
|
+
description: string;
|
|
67
|
+
};
|
|
52
68
|
}
|
|
53
69
|
|
|
54
70
|
const { elementClasses, resetElementClasses } = useStyleClassPassthrough(props.styleClassPassthrough);
|
|
@@ -57,10 +73,9 @@ const galleryData = defineModel<IGalleryData[]>('galleryData');
|
|
|
57
73
|
const sliderGalleryWrapper = useTemplateRef('sliderGalleryWrapper');
|
|
58
74
|
const sliderGalleryImagesList = useTemplateRef('sliderGalleryImagesList');
|
|
59
75
|
const sliderGalleryThumbnailsList = useTemplateRef('sliderGalleryThumbnailsList');
|
|
60
|
-
const timeDom = useTemplateRef('timeDom');
|
|
61
76
|
|
|
62
|
-
const
|
|
63
|
-
const
|
|
77
|
+
// const animationDuration = 3000;
|
|
78
|
+
const autoRunInterval = 7000;
|
|
64
79
|
|
|
65
80
|
const doNext = () => {
|
|
66
81
|
showSlider('next');
|
|
@@ -72,16 +87,15 @@ const doPrevious = () => {
|
|
|
72
87
|
|
|
73
88
|
let runTimeOut: any;
|
|
74
89
|
let runNextAuto = setTimeout(() => {
|
|
90
|
+
if (!props.autoRun) return;
|
|
75
91
|
doNext();
|
|
76
|
-
},
|
|
92
|
+
}, autoRunInterval);
|
|
77
93
|
|
|
78
94
|
function showSlider(type: string) {
|
|
79
|
-
// Get fresh references to all items by querying the DOM directly
|
|
80
95
|
const currentSliderItems = Array.from(sliderGalleryImagesList.value?.children || []);
|
|
81
96
|
const currentThumbnailItems = Array.from(sliderGalleryThumbnailsList.value?.children || []);
|
|
82
97
|
|
|
83
98
|
if (type === 'next') {
|
|
84
|
-
// Move the first item to the end
|
|
85
99
|
if (currentSliderItems.length) {
|
|
86
100
|
const firstItem = currentSliderItems[0];
|
|
87
101
|
sliderGalleryImagesList.value?.appendChild(firstItem);
|
|
@@ -94,17 +108,28 @@ function showSlider(type: string) {
|
|
|
94
108
|
|
|
95
109
|
sliderGalleryWrapper.value?.classList.add('next');
|
|
96
110
|
} else {
|
|
97
|
-
//
|
|
111
|
+
// For prev animation:
|
|
112
|
+
// 1. First modify the DOM (prepend the items)
|
|
98
113
|
if (currentSliderItems.length) {
|
|
99
114
|
const lastItem = currentSliderItems[currentSliderItems.length - 1];
|
|
115
|
+
// Set initial state before prepending (if needed)
|
|
116
|
+
lastItem.classList.add('prepend-item');
|
|
100
117
|
sliderGalleryImagesList.value?.prepend(lastItem);
|
|
101
118
|
}
|
|
102
119
|
|
|
103
120
|
if (currentThumbnailItems.length) {
|
|
104
121
|
const lastThumb = currentThumbnailItems[currentThumbnailItems.length - 1];
|
|
122
|
+
// Set initial state before prepending (if needed)
|
|
123
|
+
lastThumb.classList.add('prepend-item');
|
|
105
124
|
sliderGalleryThumbnailsList.value?.prepend(lastThumb);
|
|
106
125
|
}
|
|
107
126
|
|
|
127
|
+
// 2. Force reflow to ensure the DOM changes are applied
|
|
128
|
+
// This is a standard technique to ensure CSS transitions work properly
|
|
129
|
+
// when you need to apply styles immediately after DOM changes
|
|
130
|
+
sliderGalleryWrapper.value?.offsetWidth;
|
|
131
|
+
|
|
132
|
+
// 3. Add the class for animation
|
|
108
133
|
sliderGalleryWrapper.value?.classList.add('prev');
|
|
109
134
|
}
|
|
110
135
|
|
|
@@ -113,13 +138,21 @@ function showSlider(type: string) {
|
|
|
113
138
|
if (sliderGalleryWrapper.value) {
|
|
114
139
|
sliderGalleryWrapper.value.classList.remove('next');
|
|
115
140
|
sliderGalleryWrapper.value.classList.remove('prev');
|
|
141
|
+
|
|
142
|
+
// Remove any helper classes we added
|
|
143
|
+
const items = sliderGalleryImagesList.value?.querySelectorAll('.prepend-item');
|
|
144
|
+
items?.forEach((item) => item.classList.remove('prepend-item'));
|
|
145
|
+
|
|
146
|
+
const thumbs = sliderGalleryThumbnailsList.value?.querySelectorAll('.prepend-item');
|
|
147
|
+
thumbs?.forEach((thumb) => thumb.classList.remove('prepend-item'));
|
|
116
148
|
}
|
|
117
|
-
},
|
|
149
|
+
}, props.animationDuration);
|
|
118
150
|
|
|
119
151
|
clearTimeout(runNextAuto);
|
|
120
152
|
runNextAuto = setTimeout(() => {
|
|
153
|
+
if (!props.autoRun) return;
|
|
121
154
|
doNext();
|
|
122
|
-
},
|
|
155
|
+
}, autoRunInterval);
|
|
123
156
|
}
|
|
124
157
|
|
|
125
158
|
watch(
|
|
@@ -133,6 +166,10 @@ watch(
|
|
|
133
166
|
<style lang="css">
|
|
134
167
|
/* slider-gallery */
|
|
135
168
|
.slider-gallery {
|
|
169
|
+
--_animationDuration: v-bind(animationDuration + 'ms');
|
|
170
|
+
|
|
171
|
+
--_thembnailAspectRatio: 150 /220;
|
|
172
|
+
|
|
136
173
|
height: 100svh;
|
|
137
174
|
/* margin-top: -50px; */
|
|
138
175
|
width: 100vw;
|
|
@@ -246,6 +283,10 @@ watch(
|
|
|
246
283
|
flex-shrink: 0;
|
|
247
284
|
position: relative;
|
|
248
285
|
|
|
286
|
+
border: var(--_thumbnailBorder, 1px solid transparent);
|
|
287
|
+
outline: var(--_thumbnailOutline, 1px solid transparent);
|
|
288
|
+
border-radius: var(--_thumbnailBorderRadius, 20px);
|
|
289
|
+
|
|
249
290
|
img {
|
|
250
291
|
width: 100%;
|
|
251
292
|
height: 100%;
|
|
@@ -347,7 +388,7 @@ watch(
|
|
|
347
388
|
}
|
|
348
389
|
|
|
349
390
|
.time {
|
|
350
|
-
animation: runningTime
|
|
391
|
+
animation: runningTime var(--_animationDuration) linear 1 forwards;
|
|
351
392
|
}
|
|
352
393
|
}
|
|
353
394
|
|
|
@@ -378,6 +419,11 @@ watch(
|
|
|
378
419
|
z-index: 100;
|
|
379
420
|
}
|
|
380
421
|
}
|
|
422
|
+
|
|
423
|
+
.item.prepend-item {
|
|
424
|
+
z-index: 1; /* Ensure it's visible */
|
|
425
|
+
/* Any initial styles needed */
|
|
426
|
+
}
|
|
381
427
|
}
|
|
382
428
|
|
|
383
429
|
.arrows {
|
|
@@ -387,16 +433,24 @@ watch(
|
|
|
387
433
|
}
|
|
388
434
|
|
|
389
435
|
.thumbnail {
|
|
436
|
+
/* Add a transform to the entire thumbnail container */
|
|
437
|
+
animation: effectPrev 0.5s linear 1 forwards;
|
|
438
|
+
|
|
390
439
|
.item {
|
|
391
440
|
&:nth-child(1) {
|
|
392
441
|
overflow: hidden;
|
|
393
|
-
|
|
394
|
-
animation: showThumbnail 0.5s linear 1 forwards;
|
|
442
|
+
animation: showThumbnailPrev 0.5s linear 1 forwards;
|
|
395
443
|
}
|
|
396
444
|
}
|
|
445
|
+
|
|
446
|
+
.item.prepend-item {
|
|
447
|
+
opacity: 0;
|
|
448
|
+
transform: translateX(-20px);
|
|
449
|
+
/* Initial state for thumbnail animation */
|
|
450
|
+
}
|
|
397
451
|
}
|
|
398
452
|
.time {
|
|
399
|
-
animation: runningTime
|
|
453
|
+
animation: runningTime var(--_animationDuration) linear 1 forwards;
|
|
400
454
|
}
|
|
401
455
|
}
|
|
402
456
|
}
|
|
@@ -458,6 +512,27 @@ watch(
|
|
|
458
512
|
opacity: 0;
|
|
459
513
|
}
|
|
460
514
|
}
|
|
515
|
+
|
|
516
|
+
@keyframes effectPrev {
|
|
517
|
+
from {
|
|
518
|
+
transform: translateX(-150px);
|
|
519
|
+
}
|
|
520
|
+
to {
|
|
521
|
+
transform: translateX(0);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
@keyframes showThumbnailPrev {
|
|
526
|
+
from {
|
|
527
|
+
opacity: 0;
|
|
528
|
+
transform: translateX(-20px);
|
|
529
|
+
}
|
|
530
|
+
to {
|
|
531
|
+
opacity: 1;
|
|
532
|
+
transform: translateX(0);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
|
|
461
536
|
@media screen and (max-width: 678px) {
|
|
462
537
|
.slider-gallery .list .item .content {
|
|
463
538
|
padding-right: 0;
|
package/package.json
CHANGED