1- import React , { useEffect , useState } from 'react'
1+ import React , { useEffect , useMemo , useState } from 'react'
22import { useInterval } from '../hooks/async'
3- import { useAgentMobile } from '../hooks/dom'
43import PerfectImage from '../image/perfect'
4+ import CarouselButton from './button'
5+ import { CarouselStyles , CarouselVariant , CarouselVariants } from './carousel.design'
6+ import { CarouselComponent } from './carousel.types'
57import DotRenderer from './dot-renderer'
68
7- type Props = {
8- images : string [ ]
9- imageAltPrefix : string
10- imageTitlePrefix ?: string
11- imageClassName ?: string
12- imgLoadingClassName ?: string
13- pictureClassName ?: string
14- sizeClassName : string
15- activeIndex ?: number
16- className ?: string
17- onClick ?: ( image : string , idx : number ) => void
18- autoPlay ?: boolean
19- autoPlayInterval ?: number
20- showDots ?: boolean
21- showSubImages ?: boolean
22- }
23-
24- type ButtonProps = {
25- position : 'left' | 'right'
26- onClick : ( ) => void
27- }
28-
29- const CarouselButton : React . FC < ButtonProps > = ( { position, onClick } ) => {
30- const isMobile = useAgentMobile ( )
31- const icon = position === 'left' ? 'bx-chevron-left' : 'bx-chevron-right'
32- const left = position === 'left' ? 'left-2' : 'right-2'
33- return (
34- < button
35- className = { `${
36- ! isMobile ? 'flex' : 'hidden'
37- } invisible absolute top-1/2 opacity-0 transition-all duration-200 group-hover:visible group-hover:opacity-90 group-hover:hover:opacity-100 ${ left } shadow-xs bg-second h-8 w-8 -translate-y-1/2 transform items-center justify-center rounded-full border bg-opacity-95 text-gray-600 dark:bg-opacity-10 dark:text-white`}
38- onClick = { onClick }
39- >
40- < i className = { `bx bx-sm ${ icon } ` } />
41- </ button >
42- )
43- }
44-
45- const Carousel : React . FC < Props > = ( {
9+ const Carousel : CarouselComponent = ( {
4610 images,
4711 imageTitlePrefix,
4812 imageAltPrefix,
49- sizeClassName,
50- imageClassName,
51- pictureClassName,
52- imgLoadingClassName = 'rounded-md' ,
53- className,
13+ variant = CarouselVariant . List ,
5414 onClick,
5515 showDots = true ,
56- showSubImages = false ,
16+ showPreview = false ,
5717 autoPlay = false ,
5818 autoPlayInterval = 5000 ,
5919 activeIndex = 0 ,
6020} ) => {
6121 const [ indexes , setIndexes ] = useState ( [ 0 , 0 , 2 ] )
6222 const [ currentIndex , setCurrentIndex ] = useState ( activeIndex )
6323
24+ const styles = useMemo < CarouselStyles > ( ( ) => CarouselVariants [ variant ] , [ variant ] )
25+
6426 useInterval (
6527 ( ) => {
6628 goToNextSlide ( )
@@ -113,8 +75,8 @@ const Carousel: React.FC<Props> = ({
11375 }
11476
11577 return (
116- < div className = { `group w-full ${ className ? className : '' } ` } onClick = { checkImageClick } >
117- < div className = { `relative ${ sizeClassName } ` } >
78+ < div className = { `group w-full ${ styles . container } ` } onClick = { checkImageClick } >
79+ < div className = { `relative col-span-10 ${ styles . provider } ` } >
11880 { images . map ( ( img , idx ) => (
11981 < PerfectImage
12082 key = { idx }
@@ -124,9 +86,9 @@ const Carousel: React.FC<Props> = ({
12486 isActive = { idx === currentIndex }
12587 className = { `absolute left-0 top-0 h-full w-full object-cover transition-opacity duration-200 ${
12688 idx === currentIndex ? 'opacity-100' : 'cursor-pointer opacity-0'
127- } ${ pictureClassName ? pictureClassName : '' } `}
128- imgClassName = { `rounded-md ${ imageClassName ? imageClassName : '' } ` }
129- loadingClassName = { imgLoadingClassName }
89+ } `}
90+ imgClassName = { `rounded-md ${ styles . item } ` }
91+ loadingClassName = { styles . itemLoading }
13092 onLeftSwipe = { checkLeftSwipe }
13193 onRightSwipe = { checkRightSwipe }
13294 />
@@ -135,31 +97,28 @@ const Carousel: React.FC<Props> = ({
13597 { currentIndex !== 0 && < CarouselButton position = 'left' onClick = { goToPreviousSlide } /> }
13698 { currentIndex !== images . length - 1 && < CarouselButton position = 'right' onClick = { goToNextSlide } /> }
13799 </ div >
138- { showSubImages && (
139- < div className = 'mt-2 flex justify-start gap-1 overflow-x-auto pb-2' >
140- { images . map ( ( img , idx ) => (
141- < div key = { idx } className = 'max-w-12 relative h-12 max-h-12 min-h-[3rem] w-12 min-w-[3rem]' >
142- < PerfectImage
143- src = { img }
144- full = { false }
145- alt = { `` }
146- title = { imageTitlePrefix ? `${ imageTitlePrefix } -${ idx } ` : undefined }
147- imgClassName = 'rounded-md w-full h-full'
148- loadingClassName = 'rounded-md w-full h-full'
149- className = { `max-w-12 h-12 max-h-12 min-h-[3rem] w-12 min-w-[3rem] rounded-md object-cover transition-opacity duration-200 ${
150- idx === currentIndex ? 'opacity-100' : 'cursor-pointer opacity-50'
151- } `}
152- onClick = { ( e ) => {
153- setCurrentIndex ( idx )
154- e . stopPropagation ( )
155- } }
156- />
157- </ div >
158- ) ) }
159- </ div >
100+ { showPreview && styles . Preview && (
101+ < styles . Preview
102+ currentIndex = { currentIndex }
103+ imageTitlePrefix = { imageTitlePrefix }
104+ images = { images }
105+ styles = { styles . preview }
106+ onClick = { onClick }
107+ setCurrentIndex = { ( idx ) => {
108+ setIndexes ( ( [ fromIndex , currentIndex , toIndex ] ) => {
109+ if ( idx === currentIndex ) return [ idx - 1 , idx , idx + 1 ]
110+ if ( idx === fromIndex ) return [ idx - 1 , idx , idx + 1 ]
111+ if ( idx === toIndex ) return [ idx - 1 , idx , idx + 1 ]
112+ return [ idx - 1 , idx , idx + 1 ]
113+ } )
114+ setCurrentIndex ( idx )
115+ } }
116+ />
160117 ) }
161118 </ div >
162119 )
163120}
164121
122+ Carousel . Variants = CarouselVariant
123+
165124export default Carousel
0 commit comments