"use client" import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@/components/ui/command" import { useMediaQuery } from "@/hooks/use-media-query" import { formatIconName, fuzzySearch, filterAndSortIcons } from "@/lib/utils" import { useRouter } from "next/navigation" import { useCallback, useEffect, useState, useMemo } from "react" import type { IconWithName } from "@/types/icons" import { Tag, Search as SearchIcon, Info } from "lucide-react" import { Badge } from "@/components/ui/badge" interface CommandMenuProps { icons: IconWithName[] triggerButtonId?: string open?: boolean onOpenChange?: (open: boolean) => void } export function CommandMenu({ icons, open: externalOpen, onOpenChange: externalOnOpenChange }: CommandMenuProps) { const router = useRouter() const [internalOpen, setInternalOpen] = useState(false) const [query, setQuery] = useState("") const isDesktop = useMediaQuery("(min-width: 768px)") // Use either external or internal state for controlling open state const isOpen = externalOpen !== undefined ? externalOpen : internalOpen // Wrap setIsOpen in useCallback to fix dependency issue const setIsOpen = useCallback( (value: boolean) => { if (externalOnOpenChange) { externalOnOpenChange(value) } else { setInternalOpen(value) } }, [externalOnOpenChange], ) const filteredIcons = useMemo(() => filterAndSortIcons({ icons, query, limit: 20 }), [icons, query] ) const totalIcons = icons.length useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if ( (e.key === "k" && (e.metaKey || e.ctrlKey)) || (e.key === "/" && document.activeElement?.tagName !== "INPUT" && document.activeElement?.tagName !== "TEXTAREA") ) { e.preventDefault() setIsOpen(!isOpen) } } document.addEventListener("keydown", handleKeyDown) return () => document.removeEventListener("keydown", handleKeyDown) }, [isOpen, setIsOpen]) const handleSelect = (name: string) => { setIsOpen(false) router.push(`/icons/${name}`) } const handleBrowseAll = () => { setIsOpen(false) router.push("/icons") } return ( {/* Icon Results */} {filteredIcons.length > 0 && ( filteredIcons.map(({ name, data }) => { const formatedIconName = formatIconName(name) const hasCategories = data.categories && data.categories.length > 0 return ( handleSelect(name)} className="flex items-center gap-2 cursor-pointer py-1.5" >
{name.substring(0, 2).toUpperCase()}
{formatedIconName} {hasCategories && (
{/* First category */} {data.categories[0].replace(/-/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())} {/* "+N" badge if more than one category */} {data.categories.length > 1 && ( +{data.categories.length - 1} )}
)}
) }) )}
{/* Minimal empty state */}
{/* Smaller red icon */} No matching icons found.
{/* Separator and Browse section - Styled div outside CommandList */}
{ if (e.key === 'Enter' || e.key === ' ') handleBrowseAll() }} >
Browse all icons – {totalIcons} available
) }