|
2 | 2 | import { onMount } from 'svelte'; |
3 | 3 | import type { HeroSliderList } from '../../../contract/HeroSliderList'; |
4 | 4 |
|
5 | | - let currentSlide = 0; |
6 | | - const totalSlides = 3; |
| 5 | + let { isStatic = false, intervalTime = 5000 } = $props(); |
| 6 | +
|
| 7 | + let currentSlide = $state(0); |
| 8 | + const totalSlides = $state(3); |
| 9 | + let interval = $state<NodeJS.Timeout | null>(null); |
7 | 10 | let sliderItem: HeroSliderList[] = [ |
8 | 11 | { |
9 | 12 | id: 1, |
|
32 | 35 | ]; |
33 | 36 |
|
34 | 37 | onMount(() => { |
35 | | - const interval = setInterval(() => { |
36 | | - currentSlide = (currentSlide + 1) % totalSlides; |
37 | | - }, 5000); |
| 38 | + setNewInterval(); |
| 39 | + return () => interval && clearInterval(interval); |
| 40 | + }); |
38 | 41 |
|
39 | | - return () => clearInterval(interval); |
| 42 | + $effect(() => { |
| 43 | + if (isStatic && interval) { |
| 44 | + clearInterval(interval); |
| 45 | + interval = null; |
| 46 | + return; |
| 47 | + } else { |
| 48 | + setTimeout(() => { |
| 49 | + setNewInterval(); |
| 50 | + }, 0); |
| 51 | + } |
40 | 52 | }); |
41 | 53 |
|
| 54 | + function setNewInterval() { |
| 55 | + if (isStatic) return; |
| 56 | + if (interval) clearInterval(interval); |
| 57 | + interval = setInterval(() => { |
| 58 | + currentSlide = (currentSlide + 1) % totalSlides; |
| 59 | + }, intervalTime); |
| 60 | + } |
| 61 | +
|
42 | 62 | function goToSlide(index: number) { |
| 63 | + setNewInterval(); |
43 | 64 | currentSlide = index; |
44 | 65 | } |
45 | 66 |
|
46 | 67 | function nextSlide() { |
| 68 | + setNewInterval(); |
47 | 69 | currentSlide = (currentSlide + 1) % totalSlides; |
48 | 70 | } |
49 | 71 |
|
50 | 72 | function prevSlide() { |
| 73 | + setNewInterval(); |
51 | 74 | currentSlide = (currentSlide - 1 + totalSlides) % totalSlides; |
52 | 75 | } |
53 | 76 | </script> |
|
82 | 105 | </div> |
83 | 106 | {/each} |
84 | 107 |
|
85 | | - <button |
86 | | - aria-label="indicator previous slide" |
87 | | - on:click={prevSlide} |
88 | | - class="absolute top-1/2 left-4 z-10 flex h-12 w-12 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-white/80 transition-all hover:bg-white sm:left-8" |
89 | | - > |
90 | | - <svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
91 | | - <polyline points="15 18 9 12 15 6"></polyline> |
92 | | - </svg> |
93 | | - </button> |
94 | | - <button |
95 | | - aria-label="indicator next slide" |
96 | | - on:click={nextSlide} |
97 | | - class="absolute top-1/2 right-4 z-10 flex h-12 w-12 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-white/80 transition-all hover:bg-white sm:right-8" |
98 | | - > |
99 | | - <svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
100 | | - <polyline points="9 18 15 12 9 6"></polyline> |
101 | | - </svg> |
102 | | - </button> |
103 | | - |
104 | | - <div class="absolute bottom-8 left-1/2 z-10 flex -translate-x-1/2 gap-4"> |
105 | | - {#each sliderItem as slider, i (slider.id)} |
106 | | - <button |
107 | | - aria-label="dot-{slider.id}" |
108 | | - on:click={() => goToSlide(i)} |
109 | | - class="h-3 cursor-pointer rounded-full transition-all {currentSlide === i |
110 | | - ? 'w-8' |
111 | | - : 'w-3'} {currentSlide === i ? 'bg-white' : 'bg-white/50'}" |
112 | | - > |
113 | | - </button> |
114 | | - {/each} |
115 | | - </div> |
| 108 | + {#if !isStatic} |
| 109 | + <button |
| 110 | + aria-label="indicator previous slide" |
| 111 | + onclick={prevSlide} |
| 112 | + class="absolute top-1/2 left-4 z-10 flex h-12 w-12 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-white/80 transition-all hover:bg-white sm:left-8" |
| 113 | + > |
| 114 | + <svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 115 | + <polyline points="15 18 9 12 15 6"></polyline> |
| 116 | + </svg> |
| 117 | + </button> |
| 118 | + <button |
| 119 | + aria-label="indicator next slide" |
| 120 | + onclick={nextSlide} |
| 121 | + class="absolute top-1/2 right-4 z-10 flex h-12 w-12 -translate-y-1/2 cursor-pointer items-center justify-center rounded-full bg-white/80 transition-all hover:bg-white sm:right-8" |
| 122 | + > |
| 123 | + <svg class="h-6 w-6" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> |
| 124 | + <polyline points="9 18 15 12 9 6"></polyline> |
| 125 | + </svg> |
| 126 | + </button> |
| 127 | + <div class="absolute bottom-8 left-1/2 z-10 flex -translate-x-1/2 gap-4"> |
| 128 | + {#each sliderItem as slider, i (slider.id)} |
| 129 | + <button |
| 130 | + aria-label="dot-{slider.id}" |
| 131 | + onclick={() => goToSlide(i)} |
| 132 | + class="h-3 cursor-pointer rounded-full transition-all {currentSlide === i |
| 133 | + ? 'w-8' |
| 134 | + : 'w-3'} {currentSlide === i ? 'bg-white' : 'bg-white/50'}" |
| 135 | + > |
| 136 | + </button> |
| 137 | + {/each} |
| 138 | + </div> |
| 139 | + {/if} |
116 | 140 | </div> |
117 | 141 | </section> |
0 commit comments