'use client'; /** * `` — the filtered command list shown above the composer * while the slash machine is in `composing` state. * * Keyboard navigation (↑/↓/Enter/Tab/Esc) is owned by * `useSlashCommands` — this component is a pure render of the * `matches` + `highlight` it produces, plus click/hover handlers. * * Empty matches still render (showing a muted "No commands match" line) * — keeps the dropdown anchored while the user fixes a typo instead of * silently disappearing on them. */ import { forwardRef } from 'react'; import { cn } from '@djangocfg/ui-core/lib'; import { DEFAULT_SLASH_LABELS, formatEmptyState, type SlashMenuLabels, } from './labels'; import type { SlashCommand } from './types'; export interface SlashMenuProps { /** Filtered verbs to show (from `useSlashCommands.matches`). */ matches: readonly SlashCommand[]; /** Index of the highlighted row. */ highlight: number; /** Current filter query — only used for the empty-state line. */ query?: string; /** Called when a row is clicked. */ onPick: (command: SlashCommand) => void; /** Optional pointer-move highlight sync. */ onHighlight?: (index: number) => void; /** Localised label overrides for the empty state. */ labels?: Partial; className?: string; } export const SlashMenu = forwardRef( function SlashMenu( { matches, highlight, query = '', onPick, onHighlight, labels, className, }, ref, ) { const L = { ...DEFAULT_SLASH_LABELS, ...labels }; const isEmpty = matches.length === 0; return (
{isEmpty ? (
{formatEmptyState(L.emptyState, query)}
) : ( matches.map((cmd, i) => { const isActive = i === highlight; return ( ); }) )}
); }, );