'use client'; import { useEffect, useRef, useState } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'; import { Play, Pause, RotateCcw, Square, Circle, Type } from 'lucide-react'; import { buildCSS } from '@/lib/animate/cssBuilder'; import type { AnimationConfig, PreviewElement } from '@/types/animate'; interface Props { config: AnimationConfig; element: PreviewElement; onElementChange: (e: PreviewElement) => void; } type AnimState = 'playing' | 'paused' | 'ended'; const SPEEDS: { label: string; value: string }[] = [ { label: '0.25×', value: '0.25' }, { label: '0.5×', value: '0.5' }, { label: '1×', value: '1' }, { label: '2×', value: '2' }, ]; export function AnimationPreview({ config, element, onElementChange }: Props) { const styleRef = useRef(null); const [restartKey, setRestartKey] = useState(0); const [animState, setAnimState] = useState('playing'); const [speed, setSpeed] = useState('1'); // Inject @keyframes CSS into document head useEffect(() => { if (!styleRef.current) { styleRef.current = document.createElement('style'); styleRef.current.id = 'kit-animate-preview'; document.head.appendChild(styleRef.current); } styleRef.current.textContent = buildCSS(config); // Restart preview whenever config changes so changes are immediately visible setAnimState('playing'); setRestartKey((k) => k + 1); }, [config]); // Cleanup on unmount useEffect(() => { return () => { styleRef.current?.remove(); }; }, []); const restart = () => { setAnimState('playing'); setRestartKey((k) => k + 1); }; const handlePlay = () => { if (animState === 'ended') { // Animation finished — restart it restart(); } else { setAnimState('playing'); } }; const scaledDuration = Math.round(config.duration / Number(speed)); const isInfinite = config.iterationCount === 'infinite'; return ( Preview v && setSpeed(v)} variant="outline" size="sm"> {SPEEDS.map((s) => ( {s.label} ))} {/* Preview canvas */}
{/* Grid overlay */}
{/* Animated element */}
!isInfinite && setAnimState('ended')} > {element === 'box' && (
)} {element === 'circle' && (
)} {element === 'text' && ( Hello )}
{/* Controls */}
v && onElementChange(v as PreviewElement)} variant="outline" size="sm">
); }