/** * CompletionsDropdown — autocomplete popover for journal command input. */ import { Component, For, Show, createEffect, onMount, onCleanup } from "solid-js"; import type { CompletionItem } from "./command-parser"; import type { CompletionsState } from "./completions"; export interface CompletionsDropdownProps { show: boolean; items: CompletionItem[]; selectedIdx: number; onSelect: (item: CompletionItem) => void; onHover: (idx: number) => void; onClose: () => void; state: CompletionsState; } export const CompletionsDropdown: Component = ( props, ) => { let containerRef!: HTMLDivElement; // Scroll selected into view createEffect(() => { const idx = props.selectedIdx; if (!props.show || !containerRef) return; const el = containerRef.querySelector(`[data-comp-idx="${idx}"]`); if (el) el.scrollIntoView({ block: "nearest" }); }); // Click outside onMount(() => { const handler = (e: MouseEvent) => { if (containerRef && !containerRef.contains(e.target as Node)) { props.onClose(); } }; document.addEventListener("mousedown", handler); onCleanup(() => document.removeEventListener("mousedown", handler)); }); return ( {(props.state as any).message || "无法加载补全数据"} } >
正在加载补全数据…
} > 0}>
{(item, idx) => (
props.onSelect(item)} onMouseEnter={() => item.kind !== "no-results" && props.onHover(idx()) } > — } > {item.kind === "command" ? "cmd" : "val"} {item.label}
)}
); };