1
- import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
1
+ import React , { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
2
2
import ImagePreLoader from './ImageSliderPreLoader' ;
3
3
import styles from './ImageSliderStyle' ;
4
4
import ImageSliderNavigation , { ImageSliderNavDirection , ImageSliderNavStyle } from './ImageSliderNavigation' ;
5
5
import ImageSliderBullets from './ImageSliderBullets' ;
6
+ import useSlideIndex from './hooks/useSlideIndex' ;
6
7
7
8
export type SimpleImageSliderProps = {
8
9
width : number | string ;
@@ -11,6 +12,9 @@ export type SimpleImageSliderProps = {
11
12
style ?: React . CSSProperties ;
12
13
showNavs : boolean ;
13
14
showBullets : boolean ;
15
+ loop ?: boolean ;
16
+ autoPlay ?: boolean ;
17
+ autoPlayDelay ?: number ;
14
18
startIndex ?: number ;
15
19
slideDuration ?: number ;
16
20
bgColor ?: string ;
@@ -31,6 +35,9 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
31
35
images,
32
36
showNavs,
33
37
showBullets,
38
+ loop = true ,
39
+ autoPlay = false ,
40
+ autoPlayDelay = 2.0 ,
34
41
startIndex = 0 ,
35
42
style = undefined ,
36
43
slideDuration = 0.5 ,
@@ -46,11 +53,15 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
46
53
onCompleteSlide = undefined
47
54
} : SimpleImageSliderProps ) => {
48
55
const rootStyle : React . CSSProperties = useMemo ( ( ) => styles . getRootContainer ( width , height , bgColor ) , [ width , height , bgColor ] ) ;
49
- const [ slideIdx , setSlideIdx ] = useState ( startIndex < images . length ? startIndex : 0 ) ;
50
- const [ slideDirection , setSlideDirection ] = useState ( ImageSliderNavDirection . RIGHT ) ;
51
- const [ isSliding , setIsSliding ] = useState ( false ) ;
56
+ const { slideIdx, updateSlideIdx, isRightDirection, getNextLoopingIdx, previousSlideIdx } = useSlideIndex ( {
57
+ imageCount : images . length ,
58
+ startIndex,
59
+ autoPlay,
60
+ autoPlayDelay : autoPlayDelay + slideDuration
61
+ } ) ;
52
62
const [ currentSliderStyle , setCurrentSlideStyle ] = useState ( styles . getImageSlide ( images [ 0 ] . url , slideDuration , 0 , useGPURender ) ) ;
53
63
const [ nextSliderStyle , setNextSliderStyle ] = useState ( styles . getImageSlide ( images [ 1 ] ?. url , slideDuration , 1 , useGPURender ) ) ;
64
+ const isSlidingRef = useRef ( false ) ;
54
65
55
66
const handleClick = useCallback (
56
67
( event : React . SyntheticEvent ) => {
@@ -61,64 +72,54 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
61
72
62
73
const handleClickNav = useCallback (
63
74
( direction : ImageSliderNavDirection ) => ( ) => {
64
- if ( isSliding ) {
75
+ if ( isSlidingRef . current ) {
65
76
return ;
66
77
}
67
78
const isRight : boolean = direction === ImageSliderNavDirection . RIGHT ;
68
79
69
80
onClickNav ?.( isRight ) ;
70
- slide ( isRight ? slideIdx + 1 : slideIdx - 1 ) ;
81
+ updateSlideIdx ( isRight ? slideIdx + 1 : slideIdx - 1 ) ;
71
82
} ,
72
- [ slideIdx , isSliding ]
83
+ [ onClickNav , slideIdx , updateSlideIdx ]
73
84
) ;
74
85
75
86
const handleClickBullets = useCallback (
76
87
( idx : number ) => {
77
- if ( idx === slideIdx || isSliding ) {
88
+ if ( idx === slideIdx || isSlidingRef . current ) {
78
89
return ;
79
90
}
80
91
81
92
onClickBullets ?.( idx ) ;
82
- slide ( idx ) ;
93
+ updateSlideIdx ( idx ) ;
83
94
} ,
84
- [ slideIdx , isSliding ]
95
+ [ onClickBullets , slideIdx , updateSlideIdx ]
85
96
) ;
86
97
87
- const slide = ( idx : number ) => {
88
- const toNext : boolean = idx > slideIdx ;
89
- const currentUrl : string = images [ slideIdx ] . url ;
90
- const nextUrl : string = images [ idx ] . url ;
91
- const nextReadyX : 1 | - 1 = toNext ? 1 : - 1 ;
92
-
93
- setSlideIdx ( idx ) ;
94
- setSlideDirection ( idx > slideIdx ? ImageSliderNavDirection . RIGHT : ImageSliderNavDirection . LEFT ) ;
95
- setCurrentSlideStyle ( styles . getImageSlide ( currentUrl , 0 , 0 , useGPURender ) ) ;
96
- setNextSliderStyle ( styles . getImageSlide ( nextUrl , 0 , nextReadyX , useGPURender ) ) ;
97
- setIsSliding ( true ) ;
98
-
99
- onStartSlide ?.( idx + 1 , images . length ) ;
100
- idx + 2 < images . length && ImagePreLoader . load ( images [ idx + 2 ] . url ) ;
101
- } ;
102
-
103
98
useEffect ( ( ) => {
104
- if ( isSliding ) {
105
- setTimeout ( ( ) => {
106
- const toRight : boolean = slideDirection === ImageSliderNavDirection . RIGHT ;
107
- const currentUrl : string = images [ toRight ? slideIdx - 1 : slideIdx + 1 ] . url ;
108
- const nextUrl : string = images [ slideIdx ] . url ;
109
- const currentOffsetX : 1 | - 1 = toRight ? - 1 : 1 ;
110
-
111
- setCurrentSlideStyle ( styles . getImageSlide ( currentUrl , slideDuration , currentOffsetX , useGPURender ) ) ;
112
- setNextSliderStyle ( styles . getImageSlide ( nextUrl , slideDuration , 0 , useGPURender ) ) ;
113
- } , 50 ) ;
99
+ if ( slideIdx === previousSlideIdx ) {
100
+ return ;
114
101
}
115
- } , [ slideIdx , isSliding ] ) ;
102
+
103
+ const currentUrl : string = images [ getNextLoopingIdx ( isRightDirection ? slideIdx - 1 : slideIdx + 1 ) ] . url ;
104
+ const nextUrl : string = images [ slideIdx ] . url ;
105
+ const currentOffsetX : 1 | - 1 = isRightDirection ? - 1 : 1 ;
106
+ const nextReadyOffsetX : 1 | - 1 = isRightDirection ? 1 : - 1 ;
107
+
108
+ onStartSlide ?.( slideIdx + 1 , images . length ) ;
109
+ setNextSliderStyle ( styles . getImageSlide ( nextUrl , 0 , nextReadyOffsetX , useGPURender ) ) ;
110
+ setTimeout ( ( ) => {
111
+ isSlidingRef . current = true ;
112
+ setCurrentSlideStyle ( styles . getImageSlide ( currentUrl , slideDuration , currentOffsetX , useGPURender ) ) ;
113
+ setNextSliderStyle ( styles . getImageSlide ( nextUrl , slideDuration , 0 , useGPURender ) ) ;
114
+ } , 50 ) ;
115
+ } , [ onStartSlide , slideIdx , isRightDirection ] ) ;
116
116
117
117
const handleSlideEnd = useCallback ( ( ) => {
118
+ isSlidingRef . current = false ;
119
+ ImagePreLoader . load ( images [ slideIdx + 2 ] ?. url ) ;
118
120
setCurrentSlideStyle ( styles . getImageSlide ( images [ slideIdx ] . url , 0 , 0 , useGPURender ) ) ;
119
- setIsSliding ( false ) ;
120
121
onCompleteSlide ?.( slideIdx + 1 , images . length ) ;
121
- } , [ slideIdx ] ) ;
122
+ } , [ onCompleteSlide , slideIdx ] ) ;
122
123
123
124
return (
124
125
< div style = { { ...rootStyle , ...style } } >
@@ -130,27 +131,28 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
130
131
</ div >
131
132
132
133
{ /* Render Navigation */ }
133
- { showNavs && images . length > 0 && slideIdx > 0 && (
134
+ { ( loop || slideIdx > 0 ) && (
134
135
< ImageSliderNavigation
135
136
direction = { ImageSliderNavDirection . LEFT }
136
- navStyle = { navStyle }
137
- navSize = { navSize }
138
- navMargin = { navMargin }
137
+ visible = { showNavs && images . length > 0 }
138
+ type = { navStyle }
139
+ size = { navSize }
140
+ margin = { navMargin }
139
141
onClickNav = { handleClickNav }
140
142
/>
141
143
) }
142
- { showNavs && images . length > 0 && slideIdx < images . length - 1 && (
144
+ { ( loop || slideIdx < images . length - 1 ) && (
143
145
< ImageSliderNavigation
144
146
direction = { ImageSliderNavDirection . RIGHT }
145
- navStyle = { navStyle }
146
- navSize = { navSize }
147
- navMargin = { navMargin }
147
+ visible = { showNavs && images . length > 0 }
148
+ type = { navStyle }
149
+ size = { navSize }
150
+ margin = { navMargin }
148
151
onClickNav = { handleClickNav }
149
152
/>
150
153
) }
151
154
152
- { /* Render Bullets */ }
153
- { showBullets && images . length > 0 && < ImageSliderBullets length = { images . length } currentIdx = { slideIdx } onClickBullets = { handleClickBullets } /> }
155
+ < ImageSliderBullets visible = { showBullets } length = { images . length } currentIdx = { slideIdx } onClickBullets = { handleClickBullets } />
154
156
</ div >
155
157
</ div >
156
158
) ;
0 commit comments