'use client'; import { motion } from 'framer-motion'; import { useMemo, useState, useEffect } from 'react'; interface InkDropProps { size?: number; opacity?: number; color?: string; blur?: number; delay?: number; duration?: number; className?: string; } export function InkDrop({ size = 20, opacity = 0.15, color = '#1C1C1C', blur = 0, delay = 0, duration: _duration = 8, className = '' }: InkDropProps) { return ( 0 ? `blur(${blur}px)` : 'none', }} initial={{ scale: 0, opacity: 0 }} animate={{ scale: [0.8, 1.2, 1], opacity: [0, opacity, opacity], }} transition={{ duration: 1.5, delay, ease: [0.16, 1, 0.3, 1], }} /> ); } interface InkSplashProps { size?: number; color?: string; opacity?: number; delay?: number; className?: string; } export function InkSplash({ size = 60, color = '#C41E3A', opacity = 0.2, delay = 0, className = '' }: InkSplashProps) { return ( ); } interface SealStampProps { size?: number; color?: string; opacity?: number; delay?: number; className?: string; } export function SealStamp({ size = 40, color = '#C41E3A', opacity = 0.15, delay = 0, className = '' }: SealStampProps) { return ( ); } interface InkStainProps { size?: number; color?: string; opacity?: number; blur?: number; delay?: number; className?: string; } export function InkStain({ size = 100, color = '#1C1C1C', opacity = 0.05, blur = 20, delay = 0, className = '' }: InkStainProps) { return ( ); } interface InkLineProps { width?: number; height?: number; color?: string; opacity?: number; delay?: number; className?: string; } export function InkLine({ width = 200, height = 2, color = '#1C1C1C', opacity = 0.1, delay = 0, className = '' }: InkLineProps) { return ( ); } interface BrushStrokeProps { width?: number; height?: number; color?: string; opacity?: number; delay?: number; className?: string; } export function BrushStroke({ width = 150, height = 30, color = '#C41E3A', opacity = 0.12, delay = 0, className = '' }: BrushStrokeProps) { return ( ); } interface FloatingInkProps { count?: number; className?: string; } export function FloatingInk({ count = 15, className = '' }: FloatingInkProps) { const [isMounted, setIsMounted] = useState(false); useEffect(() => { setIsMounted(true); }, []); const elements = useMemo(() => { if (!isMounted) {return [];} const items = []; for (let i = 0; i < count; i++) { const type = i % 5; const baseDelay = i * 0.15; items.push({ id: i, type, delay: baseDelay, props: { left: `${10 + Math.random() * 80}%`, top: `${10 + Math.random() * 80}%`, }, animX: Math.random() * 10 - 5, animDuration: 6 + Math.random() * 4, size: type === 0 ? 8 + Math.random() * 16 : type === 1 ? 4 + Math.random() * 8 : type === 2 ? 20 + Math.random() * 30 : type === 3 ? 60 + Math.random() * 80 : 80 + Math.random() * 100, opacity: type === 0 ? 0.08 + Math.random() * 0.1 : type === 1 ? 0.1 + Math.random() * 0.15 : type === 2 ? 0.08 + Math.random() * 0.08 : type === 3 ? 0.03 + Math.random() * 0.04 : 0.06 + Math.random() * 0.08, blur: type === 0 ? Math.random() * 2 : 0, height: type === 4 ? 15 + Math.random() * 20 : undefined, }); } return items; }, [count, isMounted]); return (
{elements.map((el) => ( {el.type === 0 && ( )} {el.type === 1 && ( )} {el.type === 2 && ( )} {el.type === 3 && ( )} {el.type === 4 && ( )} ))}
); } interface InkDecorationProps { variant?: 'minimal' | 'balanced' | 'rich'; className?: string; } interface DropPosition { left: string; top: string; size: number; opacity: number; blur: number; isRed: boolean; duration: number; } interface SplashPosition { left: string; top: string; size: number; duration: number; } interface SealPosition { left: string; top: string; size: number; duration: number; } interface StainPosition { left: string; top: string; size: number; duration: number; } interface StrokePosition { left: string; top: string; width: number; duration: number; } export function InkDecoration({ variant = 'balanced', className = '' }: InkDecorationProps) { const [dropPositions, setDropPositions] = useState([]); const [splashPositions, setSplashPositions] = useState([]); const [sealPositions, setSealPositions] = useState([]); const [stainPositions, setStainPositions] = useState([]); const [strokePositions, setStrokePositions] = useState([]); const config = { minimal: { drops: 3, splashes: 1, seals: 1, stains: 1, strokes: 1 }, balanced: { drops: 5, splashes: 2, seals: 2, stains: 2, strokes: 2 }, rich: { drops: 8, splashes: 3, seals: 3, stains: 3, strokes: 3 }, }; const { drops, splashes, seals, stains, strokes } = config[variant]; useEffect(() => { setDropPositions(Array.from({ length: drops }, (_, i) => ({ left: `${15 + (i * 70 / drops)}%`, top: `${20 + Math.random() * 60}%`, size: 6 + Math.random() * 14, opacity: 0.06 + Math.random() * 0.1, blur: Math.random() * 3, isRed: i % 3 === 0, duration: 5 + Math.random() * 3, }))); setSplashPositions(Array.from({ length: splashes }, (_, i) => ({ left: `${20 + (i * 60 / splashes)}%`, top: `${15 + Math.random() * 70}%`, size: 40 + Math.random() * 40, duration: 7 + Math.random() * 3, }))); setSealPositions(Array.from({ length: seals }, (_, i) => ({ left: `${25 + (i * 50 / seals)}%`, top: `${25 + Math.random() * 50}%`, size: 25 + Math.random() * 25, duration: 6 + Math.random() * 2, }))); setStainPositions(Array.from({ length: stains }, (_, i) => ({ left: `${10 + (i * 80 / stains)}%`, top: `${30 + Math.random() * 40}%`, size: 80 + Math.random() * 60, duration: 8 + Math.random() * 4, }))); setStrokePositions(Array.from({ length: strokes }, (_, i) => ({ left: `${15 + (i * 70 / strokes)}%`, top: `${40 + Math.random() * 30}%`, width: 100 + Math.random() * 100, duration: 6 + Math.random() * 3, }))); }, [drops, splashes, seals, stains, strokes]); return (
{dropPositions.map((pos, i) => ( ))} {splashPositions.map((pos, i) => ( ))} {sealPositions.map((pos, i) => ( ))} {stainPositions.map((pos, i) => ( ))} {strokePositions.map((pos, i) => ( ))}
); } export function InkBackground() { return (
); }