import { useState, useEffect, useRef } from 'react' const COMMANDS = [ { id: 'summarize', label: 'Summarize', description: 'Summarize the entire conversation', // icon: '📄', }, { id: 'deepThink', label: 'Deep Think', description: 'Research thoroughly from multiple sources', // icon: '🔍', }, ] /** * Detect if the input value is a slash command. * Returns the matched command and any text after the command name. */ export function parseSlashCommand(input) { if (!input || !input.startsWith('/')) return null const trimmed = input.slice(1).trim() // remove leading / if (!trimmed) { // Just "/" typed, showing all commands return { partial: '', matched: null, fullText: '' } } // Split on first space to get command and args const spaceIdx = trimmed.indexOf(' ') const cmdPart = spaceIdx >= 0 ? trimmed.slice(0, spaceIdx) : trimmed const argsPart = spaceIdx >= 0 ? trimmed.slice(spaceIdx + 1) : '' // Find exact match const exact = COMMANDS.find((c) => c.id === cmdPart) if (exact) return { partial: cmdPart, matched: exact, fullText: argsPart } // Find partial matches for filtering return { partial: cmdPart, matched: null, fullText: '' } } export default function SlashCommandsDropdown({ inputValue, onSelect, onClose }) { const [selectedIndex, setSelectedIndex] = useState(0) const dropdownRef = useRef(null) const parsed = parseSlashCommand(inputValue) // Filter commands based on partial input const filtered = parsed ? COMMANDS.filter( (c) => !parsed.partial || c.id.startsWith(parsed.partial.toLowerCase()), ) : [] const visible = parsed !== null && filtered.length > 0 useEffect(() => { setSelectedIndex(0) }, [inputValue]) useEffect(() => { if (!visible) return const handleKeyDown = (e) => { if (e.key === 'ArrowDown') { e.preventDefault() setSelectedIndex((prev) => (prev + 1) % filtered.length) } else if (e.key === 'ArrowUp') { e.preventDefault() setSelectedIndex((prev) => (prev - 1 + filtered.length) % filtered.length) } else if (e.key === 'Enter' || e.key === 'Tab') { if (filtered[selectedIndex]) { e.preventDefault() onSelect(filtered[selectedIndex]) } } else if (e.key === 'Escape') { e.preventDefault() onClose?.() } } document.addEventListener('keydown', handleKeyDown) return () => document.removeEventListener('keydown', handleKeyDown) }, [visible, filtered, selectedIndex, onSelect, onClose]) if (!visible) return null return ( <> {/* Backdrop to detect clicks outside */}
Commands
{filtered.map((cmd, idx) => ( ))}
) }