'use client'; import { useState, useEffect, useMemo, useRef } from 'react'; import { Command, Hash, Star, Moon, Sun } from 'lucide-react'; import { useTheme } from '@/components/providers/ThemeProvider'; import { getAllMeasures, formatMeasureName, getCategoryColor, getCategoryColorHex, type Measure, } from '@/lib/units/units'; import { getFavorites } from '@/lib/units/storage'; import { cn } from '@/lib/utils'; interface CommandPaletteProps { onSelectMeasure: (measure: Measure) => void; onSelectUnit: (unit: string, measure: Measure) => void; } export default function CommandPalette({ onSelectMeasure, onSelectUnit, }: CommandPaletteProps) { const [isOpen, setIsOpen] = useState(false); const [query, setQuery] = useState(''); const [selectedIndex, setSelectedIndex] = useState(0); const { theme, setTheme } = useTheme(); const inputRef = useRef(null); // Commands const commands: Array<{ id: string; label: string; icon: any; action: () => void; keywords: string[]; color?: string; }> = [ { id: 'theme-light', label: 'Switch to Light Mode', icon: Sun, action: () => setTheme('light'), keywords: ['theme', 'light', 'mode'], }, { id: 'theme-dark', label: 'Switch to Dark Mode', icon: Moon, action: () => setTheme('dark'), keywords: ['theme', 'dark', 'mode'], }, { id: 'theme-system', label: 'Use System Theme', icon: Command, action: () => setTheme('system'), keywords: ['theme', 'system', 'auto'], }, ]; // Add measure commands const measures = getAllMeasures(); const measureCommands = measures.map(measure => ({ id: `measure-${measure}`, label: `Convert ${formatMeasureName(measure)}`, icon: Hash, action: () => onSelectMeasure(measure), keywords: ['convert', measure, formatMeasureName(measure).toLowerCase()], color: getCategoryColorHex(measure), })); const allCommands = [...commands, ...measureCommands]; // Filter commands const filteredCommands = query ? allCommands.filter(cmd => cmd.keywords.some(kw => kw.toLowerCase().includes(query.toLowerCase())) || cmd.label.toLowerCase().includes(query.toLowerCase()) ) : allCommands; // Focus input when opened useEffect(() => { if (isOpen) { inputRef.current?.focus(); setQuery(''); setSelectedIndex(0); } }, [isOpen]); // Reset selected index when query changes useEffect(() => { setSelectedIndex(0); }, [query]); if (!isOpen) return null; return ( <> {/* Backdrop */}
setIsOpen(false)} /> {/* Command Palette */}
{/* Search Input */}
setQuery(e.target.value)} className="flex-1 bg-transparent py-4 px-4 outline-none placeholder:text-muted-foreground" />
{/* Commands List */}
{filteredCommands.length === 0 ? (
No commands found
) : ( filteredCommands.map((command, index) => { const Icon = command.icon; return ( ); }) )}
{/* Footer */}
Navigate with arrows Select with Enter Close with click outside
); }