import { useState } from 'react' import { Sparkles, X, Search } from 'lucide-react' import { EFFECT_DEFINITIONS } from '../../types/project' import type { EffectType, TimelineClip } from '../../types/project-model' interface EffectsBrowserProps { onClose: () => void selectedClip: TimelineClip | null addEffectToClip: (clipId: string, effectType: EffectType) => void } export function EffectsBrowser({ onClose, selectedClip, addEffectToClip }: EffectsBrowserProps) { const [effectsSearchQuery, setEffectsSearchQuery] = useState('') return (
{/* Header */}
Effects
{/* Search */}
setEffectsSearchQuery(e.target.value)} className="w-full pl-7 pr-2 py-1.5 bg-zinc-800/70 rounded-md text-[11px] text-white placeholder-zinc-600 outline-none border border-zinc-700/40 focus:border-blue-500/50 focus:bg-zinc-800 transition-colors" />
{/* Effect categories */}
{(['filter', 'stylize', 'color-preset'] as const).map(category => { const categoryLabel = category === 'filter' ? 'Filters' : category === 'stylize' ? 'Stylize' : 'Color Presets' const categoryIcon = category === 'filter' ? 'filter' : category === 'stylize' ? 'stylize' : 'color' const effects = (Object.entries(EFFECT_DEFINITIONS) as [EffectType, typeof EFFECT_DEFINITIONS[EffectType]][]) .filter(([_, def]) => def.category === category) .filter(([_, def]) => !effectsSearchQuery || def.name.toLowerCase().includes(effectsSearchQuery.toLowerCase())) if (effects.length === 0) return null return (
{categoryLabel}
{effects.map(([type, def]) => { const lutGradient: Record = { 'lut-cinematic': 'linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%)', 'lut-vintage': 'linear-gradient(135deg, #d4a373 0%, #e6ccb2 50%, #b5838d 100%)', 'lut-bw': 'linear-gradient(135deg, #111 0%, #666 50%, #ccc 100%)', 'lut-cool': 'linear-gradient(135deg, #4cc9f0 0%, #4895ef 50%, #4361ee 100%)', 'lut-warm': 'linear-gradient(135deg, #f77f00 0%, #fcbf49 50%, #eae2b7 100%)', 'lut-muted': 'linear-gradient(135deg, #6b7280 0%, #9ca3af 50%, #d1d5db 100%)', 'lut-vivid': 'linear-gradient(135deg, #ff006e 0%, #fb5607 50%, #ffbe0b 100%)', } const filterIcon: Record = { 'blur': 'B', 'sharpen': 'S', 'glow': 'G', 'vignette': 'V', 'grain': 'N', } const filterColor: Record = { 'blur': 'from-blue-500/20 to-blue-600/10 text-blue-400', 'sharpen': 'from-cyan-500/20 to-cyan-600/10 text-cyan-400', 'glow': 'from-amber-500/20 to-amber-600/10 text-amber-400', 'vignette': 'from-blue-500/20 to-blue-600/10 text-blue-400', 'grain': 'from-stone-500/20 to-stone-600/10 text-stone-400', } return ( ) })}
) })}
{/* Footer hint */}

Drag onto a clip or double-click to apply to selection

) }