"use client"; import React, { useState, useRef, useEffect } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { Search, X, Command } from "lucide-react"; import { cn } from "../lib/utils"; interface ExpandableSearchBarProps { /** Optional placeholder text */ placeholder?: string; /** Optional onChange handler */ onChange?: (value: string) => void; /** Optional onSubmit handler */ onSubmit?: (value: string) => void; /** Additional CSS classes */ className?: string; /** The maximum expanded width (Tailwind class or absolute value like "300px") */ expandedWidth?: string | number; } export function ExpandableSearchBar({ placeholder = "Search...", onChange, onSubmit, className, expandedWidth = "18rem", // 288px (w-72) }: ExpandableSearchBarProps) { const [isExpanded, setIsExpanded] = useState(false); const [value, setValue] = useState(""); const inputRef = useRef(null); const containerRef = useRef(null); // Focus input when expanded useEffect(() => { if (isExpanded && inputRef.current) { inputRef.current.focus(); } }, [isExpanded]); // Handle outside click to collapse if empty useEffect(() => { const handleClickOutside = (e: MouseEvent) => { if ( containerRef.current && !containerRef.current.contains(e.target as Node) && value === "" ) { setIsExpanded(false); } }; document.addEventListener("mousedown", handleClickOutside); return () => document.removeEventListener("mousedown", handleClickOutside); }, [value]); const handleSubmit = (e: React.FormEvent) => { e.preventDefault(); if (onSubmit) onSubmit(value); }; const handleClear = () => { setValue(""); if (onChange) onChange(""); inputRef.current?.focus(); }; return (
!isExpanded && setIsExpanded(true)} > { setValue(e.target.value); if (onChange) onChange(e.target.value); }} placeholder={placeholder} className="h-full w-full border-none bg-transparent pl-10 pr-10 text-sm outline-none placeholder:text-muted-foreground/60 focus:border-transparent focus:outline-none focus:ring-0 focus-visible:ring-0 focus-visible:outline-none focus:ring-offset-0 focus-visible:ring-offset-0" style={{ pointerEvents: isExpanded ? "auto" : "none", opacity: isExpanded ? 1 : 0, boxShadow: "none", }} tabIndex={isExpanded ? 0 : -1} /> {isExpanded && value === "" && (
K
)} {isExpanded && value !== "" && ( )}
); }