1- import React , { useCallback , useEffect , useMemo , useState } from 'react' ;
1+ import React , { useCallback , useEffect , useMemo , useRef , useState } from 'react' ;
22import ImagePreLoader from './ImageSliderPreLoader' ;
33import styles from './ImageSliderStyle' ;
44import ImageSliderNavigation , { ImageSliderNavDirection , ImageSliderNavStyle } from './ImageSliderNavigation' ;
55import ImageSliderBullets from './ImageSliderBullets' ;
6+ import useSlideIndex from './hooks/useSlideIndex' ;
67
78export type SimpleImageSliderProps = {
89 width : number | string ;
@@ -11,6 +12,9 @@ export type SimpleImageSliderProps = {
1112 style ?: React . CSSProperties ;
1213 showNavs : boolean ;
1314 showBullets : boolean ;
15+ loop ?: boolean ;
16+ autoPlay ?: boolean ;
17+ autoPlayDelay ?: number ;
1418 startIndex ?: number ;
1519 slideDuration ?: number ;
1620 bgColor ?: string ;
@@ -31,6 +35,9 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
3135 images,
3236 showNavs,
3337 showBullets,
38+ loop = true ,
39+ autoPlay = false ,
40+ autoPlayDelay = 2.0 ,
3441 startIndex = 0 ,
3542 style = undefined ,
3643 slideDuration = 0.5 ,
@@ -46,11 +53,15 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
4653 onCompleteSlide = undefined
4754} : SimpleImageSliderProps ) => {
4855 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+ } ) ;
5262 const [ currentSliderStyle , setCurrentSlideStyle ] = useState ( styles . getImageSlide ( images [ 0 ] . url , slideDuration , 0 , useGPURender ) ) ;
5363 const [ nextSliderStyle , setNextSliderStyle ] = useState ( styles . getImageSlide ( images [ 1 ] ?. url , slideDuration , 1 , useGPURender ) ) ;
64+ const isSlidingRef = useRef ( false ) ;
5465
5566 const handleClick = useCallback (
5667 ( event : React . SyntheticEvent ) => {
@@ -61,64 +72,54 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
6172
6273 const handleClickNav = useCallback (
6374 ( direction : ImageSliderNavDirection ) => ( ) => {
64- if ( isSliding ) {
75+ if ( isSlidingRef . current ) {
6576 return ;
6677 }
6778 const isRight : boolean = direction === ImageSliderNavDirection . RIGHT ;
6879
6980 onClickNav ?.( isRight ) ;
70- slide ( isRight ? slideIdx + 1 : slideIdx - 1 ) ;
81+ updateSlideIdx ( isRight ? slideIdx + 1 : slideIdx - 1 ) ;
7182 } ,
72- [ slideIdx , isSliding ]
83+ [ onClickNav , slideIdx , updateSlideIdx ]
7384 ) ;
7485
7586 const handleClickBullets = useCallback (
7687 ( idx : number ) => {
77- if ( idx === slideIdx || isSliding ) {
88+ if ( idx === slideIdx || isSlidingRef . current ) {
7889 return ;
7990 }
8091
8192 onClickBullets ?.( idx ) ;
82- slide ( idx ) ;
93+ updateSlideIdx ( idx ) ;
8394 } ,
84- [ slideIdx , isSliding ]
95+ [ onClickBullets , slideIdx , updateSlideIdx ]
8596 ) ;
8697
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-
10398 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 ;
114101 }
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 ] ) ;
116116
117117 const handleSlideEnd = useCallback ( ( ) => {
118+ isSlidingRef . current = false ;
119+ ImagePreLoader . load ( images [ slideIdx + 2 ] ?. url ) ;
118120 setCurrentSlideStyle ( styles . getImageSlide ( images [ slideIdx ] . url , 0 , 0 , useGPURender ) ) ;
119- setIsSliding ( false ) ;
120121 onCompleteSlide ?.( slideIdx + 1 , images . length ) ;
121- } , [ slideIdx ] ) ;
122+ } , [ onCompleteSlide , slideIdx ] ) ;
122123
123124 return (
124125 < div style = { { ...rootStyle , ...style } } >
@@ -130,27 +131,28 @@ const SimpleImageSlider: React.FC<SimpleImageSliderProps> = ({
130131 </ div >
131132
132133 { /* Render Navigation */ }
133- { showNavs && images . length > 0 && slideIdx > 0 && (
134+ { ( loop || slideIdx > 0 ) && (
134135 < ImageSliderNavigation
135136 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 }
139141 onClickNav = { handleClickNav }
140142 />
141143 ) }
142- { showNavs && images . length > 0 && slideIdx < images . length - 1 && (
144+ { ( loop || slideIdx < images . length - 1 ) && (
143145 < ImageSliderNavigation
144146 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 }
148151 onClickNav = { handleClickNav }
149152 />
150153 ) }
151154
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 } />
154156 </ div >
155157 </ div >
156158 ) ;
0 commit comments