"use client";
import React, { useState, useRef, useEffect, useCallback } from "react";
import { cn } from "@/lib/utils";
import gsap from "gsap";
import { ChevronRight, ChevronLeft } from "lucide-react";
interface CarouselItem {
id: string;
title: string;
description: string;
image: string;
icon: React.ReactNode;
}
export interface KineticCarouselProps {
items: CarouselItem[];
navType?: "icons" | "arrows";
autoPlay?: boolean;
interval?: number;
className?: string;
}
export function KineticCarousel({
items,
navType = "icons",
autoPlay = false,
interval = 5000,
className
}: KineticCarouselProps) {
const [activeIndex, setActiveIndex] = useState(0);
const containerRef = useRef<HTMLDivElement>(null);
const contentRef = useRef<HTMLDivElement>(null);
const imageRef = useRef<HTMLDivElement>(null);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const nextSlide = useCallback(() => {
setActiveIndex((prev) => (prev + 1) % items.length);
}, [items.length]);
const prevSlide = useCallback(() => {
setActiveIndex((prev) => (prev - 1 + items.length) % items.length);
}, [items.length]);
useEffect(() => {
if (autoPlay) {
intervalRef.current = setInterval(nextSlide, interval);
}
return () => {
if (intervalRef.current) clearInterval(intervalRef.current);
};
}, [autoPlay, interval, nextSlide]);
useEffect(() => {
if (!contentRef.current || !imageRef.current) return;
const tl = gsap.timeline();
tl.set(imageRef.current, {
scale: 0.2,
opacity: 0,
transformOrigin: "bottom right",
filter: "blur(10px)"
});
tl.set(contentRef.current.children, {
y: 20,
opacity: 0
});
tl.to(imageRef.current, {
scale: 1,
opacity: 1,
filter: "blur(0px)",
duration: 0.8,
ease: "power4.out"
})
.to(contentRef.current.children, {
y: 0,
opacity: 1,
duration: 0.5,
stagger: 0.1,
ease: "back.out(1.7)"
}, "-=0.4");
}, [activeIndex]);
return (
<div
className={cn(
"relative w-full aspect-[16/9] rounded-[3rem] bg-zinc-950 border border-white/5 overflow-hidden group shadow-2xl",
className
)}
ref={containerRef}
>
{/* Active Slide Image */}
<div
key={items[activeIndex].id}
ref={imageRef}
className="absolute inset-0 z-0 bg-cover bg-center"
style={{ backgroundImage: `url('${items[activeIndex].image}')` }}
>
<div className="absolute inset-0 bg-gradient-to-t from-zinc-950 via-zinc-950/40 to-transparent" />
</div>
{/* Content */}
<div
ref={contentRef}
className="absolute bottom-12 left-12 z-10 max-w-xl space-y-4"
>
<h2 className="text-5xl font-black tracking-tighter text-white uppercase italic">
{items[activeIndex].title}
</h2>
<p className="text-xl text-zinc-400 font-medium leading-relaxed">
{items[activeIndex].description}
</p>
</div>
{/* Navigation Layer */}
{navType === "icons" ? (
<div className="absolute bottom-12 right-12 z-20 flex gap-3 p-3 bg-black/40 backdrop-blur-xl rounded-[2.5rem] border border-white/10">
{items.map((item, index) => (
<button
key={item.id}
onClick={() => {
setActiveIndex(index);
if (intervalRef.current) clearInterval(intervalRef.current);
}}
className={cn(
"w-12 h-12 flex items-center justify-center rounded-2xl transition-all duration-500",
activeIndex === index
? "bg-primary-1 text-white scale-110 shadow-[0_0_20px_rgba(var(--primary-1-rgb),0.4)]"
: "text-zinc-500 hover:text-zinc-200 hover:bg-white/5"
)}
>
{item.icon}
</button>
))}
</div>
) : (
<div className="absolute bottom-12 right-12 z-20 flex gap-4">
<button
onClick={prevSlide}
className="w-14 h-14 flex items-center justify-center rounded-2xl bg-black/40 backdrop-blur-xl border border-white/10 text-white hover:bg-primary-1 transition-all"
>
<ChevronLeft className="h-6 w-6" />
</button>
<button
onClick={nextSlide}
className="w-14 h-14 flex items-center justify-center rounded-2xl bg-black/40 backdrop-blur-xl border border-white/10 text-white hover:bg-primary-1 transition-all"
>
<ChevronRight className="h-6 w-6" />
</button>
</div>
)}
{/* Auto-play Progress Bar */}
{autoPlay && (
<div className="absolute bottom-0 left-0 h-1 bg-primary-1/30 w-full z-30">
<div
key={activeIndex}
className="h-full bg-primary-1 transition-all linear"
style={{
width: '100%',
animation: `carousel-progress ${interval}ms linear forwards`
}}
/>
</div>
)}
<style jsx>{`
@keyframes carousel-progress {
from { width: 0%; }
to { width: 100%; }
}
`}</style>
</div>
);
}