import { File, Hash } from "lucide-react"; import type { FileSearchItem, TaskSearchItem } from "../hooks/useFileMention"; import { getDisplayDirname } from "../utils/pathDisplay"; import "./FileMentionPopup.css"; import type { ReactNode } from "react"; export interface FileMentionPopupProps { visible: boolean; position: { top: number; left: number }; tasks: TaskSearchItem[]; files: FileSearchItem[]; selectedIndex: number; onSelectTask: (task: TaskSearchItem) => void; onSelectFile: (file: FileSearchItem) => void; loading: boolean; } function getTaskRowIndex(taskIndex: number): number { return taskIndex; } function getFileRowIndex(taskCount: number, fileIndex: number): number { return taskCount + fileIndex; } /** * Shared hash-mention popup for chat composers. * Renders grouped task and file matches for the active `#` query. */ export function FileMentionPopup({ visible, position, tasks, files, selectedIndex, onSelectTask, onSelectFile, loading, }: FileMentionPopupProps): ReactNode | null { if (!visible) { return null; } const hasTasks = tasks.length > 0; const hasFiles = files.length > 0; return (
{ e.preventDefault(); }} > {loading && (
)} {!loading && !hasTasks && !hasFiles && (
No tasks or files found
)} {!loading && (hasTasks || hasFiles) && (
{hasTasks && (
Tasks
    {tasks.map((task, index) => { const rowIndex = getTaskRowIndex(index); return (
  • onSelectTask(task)} role="option" aria-selected={rowIndex === selectedIndex} data-testid={`task-mention-item-${rowIndex}`} >
    {task.id} {task.column}
    {task.title}
  • ); })}
)} {hasFiles && (
Files
    {files.map((file, index) => { const rowIndex = getFileRowIndex(tasks.length, index); const dirPath = getDisplayDirname(file.path); return (
  • onSelectFile(file)} role="option" aria-selected={rowIndex === selectedIndex} data-testid={`file-mention-item-${rowIndex}`} >
    {file.name} {dirPath && ( {dirPath} )}
  • ); })}
)}
)}
); }