import { useEffect, useRef } from "react"; import { cn } from "@/lib/utils"; import type { SlashCommandInfo } from "shared/legacy-sdk"; interface SlashCommandMenuProps { commands: SlashCommandInfo[]; query: string; selectedIndex: number; onSelect: (name: string) => void; onHover: (index: number) => void; } function highlightMatch(text: string, query: string): React.ReactNode { if (!query) { return text; } const lowerText = text.toLowerCase(); const lowerQuery = query.toLowerCase(); const parts: React.ReactNode[] = []; let lastIdx = 0; let qi = 0; for (let i = 0; i < text.length && qi < lowerQuery.length; i++) { if (lowerText[i] === lowerQuery[qi]) { if (i > lastIdx) { parts.push(text.slice(lastIdx, i)); } parts.push( {text[i]} , ); lastIdx = i + 1; qi++; } } if (lastIdx < text.length) { parts.push(text.slice(lastIdx)); } return parts.length > 0 ? parts : text; } export function SlashCommandMenu({ commands, query, selectedIndex, onSelect, onHover }: SlashCommandMenuProps) { const selectedRef = useRef(null); const hoverSelectionRef = useRef(null); useEffect(() => { if (hoverSelectionRef.current === selectedIndex) { hoverSelectionRef.current = null; return; } hoverSelectionRef.current = null; selectedRef.current?.scrollIntoView({ block: "nearest" }); }, [selectedIndex]); const handleHover = (index: number) => { hoverSelectionRef.current = index; onHover(index); }; if (commands.length === 0) { return
No commands found
; } return (
{commands.map((cmd, idx) => ( ))}
); }