75 lines
2.2 KiB
TypeScript
75 lines
2.2 KiB
TypeScript
import { useRef, useState } from 'react';
|
|
import AppImage from '@dukang/shared-ui/AppImage';
|
|
|
|
type Props = {
|
|
images: string[];
|
|
alt: string;
|
|
variant?: 'home' | 'detail' | 'store';
|
|
};
|
|
|
|
export default function ProductCarousel({ images, alt, variant = 'home' }: Props) {
|
|
const scrollRef = useRef<HTMLDivElement>(null);
|
|
const [activeIndex, setActiveIndex] = useState(0);
|
|
const slides = images.length > 0 ? images : [''];
|
|
|
|
function onScroll() {
|
|
const el = scrollRef.current;
|
|
if (!el || el.offsetWidth === 0) return;
|
|
setActiveIndex(Math.round(el.scrollLeft / el.offsetWidth));
|
|
}
|
|
|
|
const wrapClass =
|
|
variant === 'store'
|
|
? 'store-detail-carousel-wrap'
|
|
: variant === 'detail'
|
|
? 'detail-carousel-wrap'
|
|
: 'home-carousel-wrap';
|
|
const trackClass =
|
|
variant === 'store'
|
|
? 'store-detail-carousel'
|
|
: variant === 'detail'
|
|
? 'detail-carousel'
|
|
: 'home-carousel';
|
|
const dotClass =
|
|
variant === 'store'
|
|
? 'store-detail-carousel-dot'
|
|
: variant === 'detail'
|
|
? 'detail-carousel-dot'
|
|
: 'home-carousel-dot';
|
|
const itemClass =
|
|
variant === 'store'
|
|
? 'store-detail-carousel-item'
|
|
: variant === 'detail'
|
|
? 'detail-carousel-item'
|
|
: 'home-carousel-item';
|
|
const placeholderClass =
|
|
variant === 'store'
|
|
? 'store-detail-carousel-placeholder'
|
|
: variant === 'detail'
|
|
? 'detail-carousel-placeholder'
|
|
: 'home-carousel-placeholder';
|
|
|
|
return (
|
|
<div className={wrapClass}>
|
|
<div className={trackClass} ref={scrollRef} onScroll={onScroll}>
|
|
{slides.map((src, i) => (
|
|
<div key={i} className={itemClass}>
|
|
{src ? (
|
|
<AppImage src={src} alt={alt} wrapperClassName="app-image--fill" />
|
|
) : (
|
|
<div className={placeholderClass} />
|
|
)}
|
|
</div>
|
|
))}
|
|
</div>
|
|
{slides.length > 1 && (
|
|
<div className={variant === 'store' ? 'store-detail-carousel-dots' : variant === 'detail' ? 'detail-carousel-dots' : 'home-carousel-dots'}>
|
|
{slides.map((_, i) => (
|
|
<span key={i} className={`${dotClass}${i === activeIndex ? ' active' : ''}`} />
|
|
))}
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|