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">Name Slider</div>
23
- <div class="description">Description</div>
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" ref="timeDom"></div>
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 timeRunning = 3000;
63
- const timeAutoNext = 7000;
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
- }, timeAutoNext);
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
- // Move the last item to the beginning
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
- }, timeRunning);
149
+ }, props.animationDuration);
118
150
 
119
151
  clearTimeout(runNextAuto);
120
152
  runNextAuto = setTimeout(() => {
153
+ if (!props.autoRun) return;
121
154
  doNext();
122
- }, timeAutoNext);
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 3s linear 1 forwards;
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
- opacity: 0;
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 3s linear 1 forwards;
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "srcdev-nuxt-components",
3
3
  "type": "module",
4
- "version": "2.2.0",
4
+ "version": "2.2.1",
5
5
  "main": "nuxt.config.ts",
6
6
  "scripts": {
7
7
  "clean": "rm -rf .nuxt && rm -rf .output && rm -rf .playground/.nuxt && rm -rf .playground/.output",