'use client'; /** * NOVA CMS - APPLE-STYLE SEARCH BAR COMPONENT * ========================================== * * Barra de búsqueda estilo macOS/iOS reutilizable con: * - Diseño glassmorphic * - Shortcuts de teclado (⌘K) * - Animaciones suaves * - Iconografía estilo Apple */ import { useState, useEffect, useRef } from 'react'; import { Search, Command, X } from 'lucide-react'; import { Input } from '@/components/ui/input'; import { cn } from '@/lib/utils'; interface AppleSearchBarProps { placeholder?: string; value?: string; onChange?: (value: string) => void; className?: string; showShortcut?: boolean; size?: 'sm' | 'md' | 'lg'; variant?: 'default' | 'glass' | 'solid'; } export function AppleSearchBar({ placeholder = "Buscar...", value = "", onChange, className = "", showShortcut = true, size = 'md', variant = 'glass' }: AppleSearchBarProps) { const [isFocused, setIsFocused] = useState(false); const [internalValue, setInternalValue] = useState(value); const inputRef = useRef(null); // Manejo de atajos de teclado useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if ((e.metaKey || e.ctrlKey) && e.key === 'k') { e.preventDefault(); inputRef.current?.focus(); } if (e.key === 'Escape' && isFocused) { inputRef.current?.blur(); } }; document.addEventListener('keydown', handleKeyDown); return () => document.removeEventListener('keydown', handleKeyDown); }, [isFocused]); // Sincronizar valor externo useEffect(() => { setInternalValue(value); }, [value]); const handleValueChange = (newValue: string) => { setInternalValue(newValue); onChange?.(newValue); }; const handleClear = () => { setInternalValue(""); onChange?.(""); inputRef.current?.focus(); }; // Estilos dinámicos basados en props const sizeClasses = { sm: 'px-4 py-2 text-sm', md: 'px-6 py-3 text-base', lg: 'px-8 py-4 text-lg' }; const iconSizes = { sm: 'h-4 w-4', md: 'h-5 w-5', lg: 'h-6 w-6' }; const variantClasses = { default: 'bg-white border-gray-200 hover:border-gray-300 focus-within:border-blue-400', glass: 'bg-white/90 backdrop-blur-sm border-white/50 hover:bg-white/95 focus-within:bg-white focus-within:border-blue-300 shadow-lg hover:shadow-xl', solid: 'bg-gray-50 border-gray-300 hover:bg-gray-100 focus-within:bg-white focus-within:border-blue-400' }; return (
{/* Icono de búsqueda */}
{/* Input principal */} handleValueChange(e.target.value)} onFocus={() => setIsFocused(true)} onBlur={() => setIsFocused(false)} className="flex-1 border-0 bg-transparent p-0 focus-visible:ring-0 focus-visible:ring-offset-0 placeholder:text-gray-400" /> {/* Área de acciones (shortcut/clear) */}
{/* Botón de limpiar (aparece cuando hay texto) */} {internalValue && ( )} {/* Shortcut indicator */} {showShortcut && !internalValue && (
K
)}
{/* Indicador de focus sutil */}
); }