"use client"; import { motion } from "framer-motion"; import clsx from "clsx"; import { useState, useEffect } from "react"; interface BackgroundCirclesProps { title?: string; description?: string; className?: string; variant?: keyof typeof COLOR_VARIANTS; audioLevel?: number; isActive?: boolean; } const COLOR_VARIANTS = { primary: { border: [ "border-emerald-500/60", "border-cyan-400/50", "border-slate-600/30", ], gradient: "from-emerald-500/30", }, secondary: { border: [ "border-violet-500/60", "border-fuchsia-400/50", "border-slate-600/30", ], gradient: "from-violet-500/30", }, tertiary: { border: [ "border-orange-500/60", "border-yellow-400/50", "border-slate-600/30", ], gradient: "from-orange-500/30", }, quaternary: { border: [ "border-purple-500/60", "border-pink-400/50", "border-slate-600/30", ], gradient: "from-purple-500/30", }, quinary: { border: [ "border-red-500/60", "border-rose-400/50", "border-slate-600/30", ], gradient: "from-red-500/30", }, // red senary: { border: [ "border-blue-500/60", "border-sky-400/50", "border-slate-600/30", ], gradient: "from-blue-500/30", }, // blue septenary: { border: [ "border-gray-500/60", "border-gray-400/50", "border-slate-600/30", ], gradient: "from-gray-500/30", }, octonary: { border: [ "border-red-500/60", "border-rose-400/50", "border-slate-600/30", ], gradient: "from-red-500/30", }, } as const; const AnimatedGrid = () => (
); export function BackgroundCircles({ title = "", description = "", className, variant = "octonary", audioLevel = 0, isActive = false, }: BackgroundCirclesProps) { const variantStyles = COLOR_VARIANTS[variant]; const [animationParams, setAnimationParams] = useState({ scale: 1, duration: 5, intensity: 0 }); const [isLoaded, setIsLoaded] = useState(false); // Initial page load animation useEffect(() => { // Small delay to ensure the black screen is visible first const timer = setTimeout(() => { setIsLoaded(true); }, 300); return () => clearTimeout(timer); }, []); // Update animation based on audio level useEffect(() => { if (isActive && audioLevel > 0) { // Simple enhancement of audio level for more dramatic effect const enhancedLevel = Math.min(1, audioLevel * 1.5); setAnimationParams({ scale: 1 + enhancedLevel * 0.3, duration: Math.max(2, 5 - enhancedLevel * 3), intensity: enhancedLevel }); } else if (animationParams.intensity > 0) { // Only reset if we need to (prevents unnecessary updates) const timer = setTimeout(() => { setAnimationParams({ scale: 1, duration: 5, intensity: 0 }); }, 300); return () => clearTimeout(timer); } }, [audioLevel, isActive, animationParams.intensity]); return ( <> {/* Initial black overlay that fades out */}
{[0, 1, 2].map((i) => (
))}
{/* Additional glow that appears only during high audio levels */} {isActive && animationParams.intensity > 0.4 && ( )}
); } export function DemoCircles() { const [currentVariant, setCurrentVariant] = useState("octonary"); const variants = Object.keys( COLOR_VARIANTS ) as (keyof typeof COLOR_VARIANTS)[]; function getNextVariant() { const currentIndex = variants.indexOf(currentVariant); const nextVariant = variants[(currentIndex + 1) % variants.length]; return nextVariant; } return ( <>
); }