chore: transfer repo
This commit is contained in:
83
components/ui/Carousel.tsx
Normal file
83
components/ui/Carousel.tsx
Normal file
@@ -0,0 +1,83 @@
|
||||
'use client';
|
||||
|
||||
import { ReactNode, useEffect, useState } from 'react';
|
||||
|
||||
export interface CarouselIndicatorsProps {
|
||||
totalSlides: number;
|
||||
activeIndex: number;
|
||||
onSelect: (index: number) => void;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function CarouselIndicators({ totalSlides, activeIndex, onSelect, className = '' }: CarouselIndicatorsProps) {
|
||||
return (
|
||||
<div className={`flex justify-center gap-2 z-20 ${className}`}>
|
||||
{Array.from({ length: totalSlides }).map((_, index) => (
|
||||
<button
|
||||
key={index}
|
||||
className={`w-2 h-2 rounded-full transition-colors ${
|
||||
index === activeIndex ? "bg-black" : "bg-white"
|
||||
}`}
|
||||
onClick={() => onSelect(index)}
|
||||
aria-label={`Go to slide ${index + 1}`}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export interface CarouselProps {
|
||||
slides: ReactNode[];
|
||||
autoPlay?: boolean;
|
||||
interval?: number;
|
||||
showIndicators?: boolean;
|
||||
indicatorsClassName?: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export function Carousel({
|
||||
slides,
|
||||
autoPlay = true,
|
||||
interval = 5000,
|
||||
showIndicators = true,
|
||||
indicatorsClassName = '',
|
||||
className = ''
|
||||
}: CarouselProps) {
|
||||
const [activeSlide, setActiveSlide] = useState(0);
|
||||
|
||||
// Auto-advance carousel if autoPlay is enabled
|
||||
useEffect(() => {
|
||||
if (!autoPlay) return;
|
||||
|
||||
const timer = setInterval(() => {
|
||||
setActiveSlide((prev) => (prev === slides.length - 1 ? 0 : prev + 1));
|
||||
}, interval);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, [autoPlay, interval, slides.length]);
|
||||
|
||||
return (
|
||||
<div className={`relative w-full h-full ${className}`}>
|
||||
{/* All slides need to be absolutely positioned */}
|
||||
{slides.map((slide, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`absolute inset-0 w-full h-full transition-opacity duration-500 ${
|
||||
index === activeSlide ? "opacity-100 z-10" : "opacity-0 z-0"
|
||||
}`}
|
||||
>
|
||||
{slide}
|
||||
</div>
|
||||
))}
|
||||
|
||||
{showIndicators && slides.length > 1 && (
|
||||
<CarouselIndicators
|
||||
totalSlides={slides.length}
|
||||
activeIndex={activeSlide}
|
||||
onSelect={setActiveSlide}
|
||||
className={indicatorsClassName}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user