import { useKeyboard } from "@opentui/solid"; import { For, createSignal, onMount, onCleanup } from "solid-js"; import { useKeyboardNav } from "../context/keyboard.js"; import type { KeyEvent } from "@opentui/core"; export interface PersonPickerItem { id: string; name: string; relationship?: string; description?: string; } interface PersonPickerOverlayProps { title: string; people: PersonPickerItem[]; onSelect: (person: PersonPickerItem) => void; onDismiss: () => void; } const truncate = (text: string, maxLen: number): string => { return text.length > maxLen ? text.slice(0, maxLen - 3) + "..." : text; }; export function PersonPickerOverlay(props: PersonPickerOverlayProps) { const { setOverlayActive } = useKeyboardNav(); onMount(() => setOverlayActive(true)); onCleanup(() => setOverlayActive(false)); const [selectedIndex, setSelectedIndex] = createSignal(0); useKeyboard((event: KeyEvent) => { const key = event.name; const listLength = props.people.length; if (key === "j" || key === "down") { event.preventDefault(); setSelectedIndex((prev) => Math.min(prev + 1, listLength - 1)); return; } if (key === "k" || key === "up") { event.preventDefault(); setSelectedIndex((prev) => Math.max(prev - 1, 0)); return; } if (key === "return") { event.preventDefault(); if (listLength > 0) { props.onSelect(props.people[selectedIndex()]); } return; } if (key === "escape") { event.preventDefault(); props.onDismiss(); return; } }); return ( {props.title} {(person, index) => { const isSelected = () => selectedIndex() === index(); const label = () => { let text = person.name; if (person.relationship) { text += ` — ${person.relationship}`; } if (person.description) { text += ` · ${truncate(person.description, 40)}`; } return text; }; return ( {label()} ); }} j/k: navigate | Enter: select | Esc: cancel ); }