'use client'; import { useState, useCallback } from 'react'; import { AnimationSettings } from './AnimationSettings'; import { AnimationPreview } from './AnimationPreview'; import { KeyframeTimeline } from './KeyframeTimeline'; import { KeyframeProperties } from './KeyframeProperties'; import { PresetLibrary } from './PresetLibrary'; import { ExportPanel } from './ExportPanel'; import { DEFAULT_CONFIG, newKeyframe } from '@/lib/animate/defaults'; import { cn } from '@/lib/utils/cn'; import type { AnimationConfig, KeyframeProperties as KFProps, PreviewElement } from '@/types/animate'; type MobileTab = 'edit' | 'preview'; type RightTab = 'keyframes' | 'export' | 'presets'; export function AnimationEditor() { const [config, setConfig] = useState(DEFAULT_CONFIG); const [selectedId, setSelectedId] = useState( DEFAULT_CONFIG.keyframes[DEFAULT_CONFIG.keyframes.length - 1].id ); const [previewElement, setPreviewElement] = useState('box'); const [mobileTab, setMobileTab] = useState('edit'); const [rightTab, setRightTab] = useState('export'); const selectedKeyframe = config.keyframes.find((k) => k.id === selectedId) ?? null; const updateKeyframeProps = useCallback((id: string, props: KFProps) => { setConfig((c) => ({ ...c, keyframes: c.keyframes.map((k) => k.id === id ? { ...k, properties: props } : k), })); }, []); const addKeyframe = useCallback((offset: number) => { const kf = newKeyframe(offset); setConfig((c) => ({ ...c, keyframes: [...c.keyframes, kf] })); setSelectedId(kf.id); }, []); const deleteKeyframe = useCallback((id: string) => { setConfig((c) => { if (c.keyframes.length <= 2) return c; return { ...c, keyframes: c.keyframes.filter((k) => k.id !== id) }; }); setSelectedId((prev) => { if (prev !== id) return prev; const remaining = config.keyframes.filter((k) => k.id !== id); return remaining[remaining.length - 1]?.id ?? null; }); }, [config.keyframes]); const moveKeyframe = useCallback((id: string, newOffset: number) => { const clamped = Math.min(100, Math.max(0, Math.round(newOffset))); setConfig((c) => ({ ...c, keyframes: c.keyframes.map((k) => k.id === id ? { ...k, offset: clamped } : k), })); }, []); const loadPreset = useCallback((presetConfig: AnimationConfig) => { setConfig(presetConfig); setSelectedId(presetConfig.keyframes[presetConfig.keyframes.length - 1].id); }, []); const timelineProps = { keyframes: config.keyframes, selectedId, onSelect: setSelectedId, onAdd: addKeyframe, onDelete: deleteKeyframe, onMove: moveKeyframe, }; return (
{/* ── Mobile tab switcher ─────────────────────────────── */}
{(['edit', 'preview'] as MobileTab[]).map((t) => ( ))}
{/* ── Main layout ─────────────────────────────────────── */}
{/* Left: Settings + Properties */}
{/* Right: Preview + tabbed panel */}
{/* Preview canvas */} {/* Keyframes / Export / Presets tab panel */}
{/* Tab switcher */}
{(['export', 'presets'] as RightTab[]).map((t) => ( ))}
{/* Content */} {rightTab === 'export' && } {rightTab === 'presets' && }
); }