import { useState, useEffect, useRef, useCallback } from 'react'; import { useBotStore, type SlashCommand } from '../stores/bot.ts'; interface SlashCommandPopupProps { serverId: string; filter: string; onSelect: (command: SlashCommand) => void; onClose: () => void; position?: { bottom: number; left: number }; } export function SlashCommandPopup({ serverId, filter, onSelect, onClose, position, }: SlashCommandPopupProps) { const fetchServerCommands = useBotStore((s) => s.fetchServerCommands); const [commands, setCommands] = useState([]); const [selectedIndex, setSelectedIndex] = useState(0); const listRef = useRef(null); useEffect(() => { let cancelled = false; fetchServerCommands(serverId).then((cmds) => { if (!cancelled) setCommands(cmds); }); return () => { cancelled = true; }; }, [serverId, fetchServerCommands]); const filtered = commands .filter((c) => c.name.toLowerCase().includes(filter.toLowerCase())) .slice(0, 8); useEffect(() => { setSelectedIndex(0); }, [filter]); const handleSelect = useCallback( (cmd: SlashCommand) => { onSelect(cmd); }, [onSelect] ); useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (filtered.length === 0) return; if (e.key === 'ArrowDown') { e.preventDefault(); setSelectedIndex((prev) => Math.min(prev + 1, filtered.length - 1)); } else if (e.key === 'ArrowUp') { e.preventDefault(); setSelectedIndex((prev) => Math.max(prev - 1, 0)); } else if (e.key === 'Enter' || e.key === 'Tab') { e.preventDefault(); if (filtered[selectedIndex]) { handleSelect(filtered[selectedIndex]); } } else if (e.key === 'Escape') { e.preventDefault(); onClose(); } }; window.addEventListener('keydown', handleKeyDown); return () => window.removeEventListener('keydown', handleKeyDown); }, [filtered, selectedIndex, handleSelect, onClose]); if (filtered.length === 0) return null; return (
SLASH COMMANDS
{filtered.map((cmd, index) => ( ))}
); }