|
@@ -224,18 +224,63 @@ export function PromptHints(props: {
|
|
|
prompts: Prompt[];
|
|
|
onPromptSelect: (prompt: Prompt) => void;
|
|
|
}) {
|
|
|
- if (props.prompts.length === 0) return null;
|
|
|
+ const noPrompts = props.prompts.length === 0;
|
|
|
+ const [selectIndex, setSelectIndex] = useState(0);
|
|
|
+ const selectedRef = useRef<HTMLDivElement>(null);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ setSelectIndex(0);
|
|
|
+ }, [props.prompts.length]);
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ const onKeyDown = (e: KeyboardEvent) => {
|
|
|
+ if (noPrompts) return;
|
|
|
+
|
|
|
+ // arrow up / down to select prompt
|
|
|
+ const changeIndex = (delta: number) => {
|
|
|
+ e.stopPropagation();
|
|
|
+ e.preventDefault();
|
|
|
+ const nextIndex = Math.max(
|
|
|
+ 0,
|
|
|
+ Math.min(props.prompts.length - 1, selectIndex + delta),
|
|
|
+ );
|
|
|
+ setSelectIndex(nextIndex);
|
|
|
+ selectedRef.current?.scrollIntoView({
|
|
|
+ block: "center",
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
+ if (e.key === "ArrowUp") {
|
|
|
+ changeIndex(1);
|
|
|
+ } else if (e.key === "ArrowDown") {
|
|
|
+ changeIndex(-1);
|
|
|
+ } else if (e.key === "Enter") {
|
|
|
+ const selectedPrompt = props.prompts.at(selectIndex);
|
|
|
+ if (selectedPrompt) {
|
|
|
+ props.onPromptSelect(selectedPrompt);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ window.addEventListener("keydown", onKeyDown);
|
|
|
+
|
|
|
+ return () => window.removeEventListener("keydown", onKeyDown);
|
|
|
+ // eslint-disable-next-line react-hooks/exhaustive-deps
|
|
|
+ }, [noPrompts, selectIndex]);
|
|
|
|
|
|
+ if (noPrompts) return null;
|
|
|
return (
|
|
|
<div className={styles["prompt-hints"]}>
|
|
|
{props.prompts.map((prompt, i) => (
|
|
|
<div
|
|
|
- className={styles["prompt-hint"]}
|
|
|
+ ref={i === selectIndex ? selectedRef : null}
|
|
|
+ className={
|
|
|
+ styles["prompt-hint"] +
|
|
|
+ ` ${i === selectIndex ? styles["prompt-hint-selected"] : ""}`
|
|
|
+ }
|
|
|
key={prompt.title + i.toString()}
|
|
|
- onClick={() => {
|
|
|
- console.log("click hint");
|
|
|
- props.onPromptSelect(prompt);
|
|
|
- }}
|
|
|
+ onClick={() => props.onPromptSelect(prompt)}
|
|
|
+ onMouseEnter={() => setSelectIndex(i)}
|
|
|
>
|
|
|
<div className={styles["hint-title"]}>{prompt.title}</div>
|
|
|
<div className={styles["hint-content"]}>{prompt.content}</div>
|