import { DynamicBorder } from "@mariozechner/pi-coding-agent"; import { Container, Key, matchesKey, type SelectItem, SelectList, Text, } from "@mariozechner/pi-tui"; type CustomUiContext = { ui: { custom: ( render: ( tui: { requestRender: () => void }, theme: { fg: (tone: string, text: string) => string; bold: (text: string) => string; }, kb: unknown, done: () => void, ) => { render: (width: number) => string; invalidate: () => void; handleInput: (data: string) => void; }, ) => Promise; }; }; export async function showPagedSelectList(params: { ctx: CustomUiContext; title: string; items: SelectItem[]; onSelect: (item: SelectItem) => void; }): Promise { await params.ctx.ui.custom((tui, theme, _kb, done) => { const container = new Container(); container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s))); container.addChild(new Text(theme.fg("accent", theme.bold(params.title)), 0, 0)); const visibleRows = Math.min(params.items.length, 15); let currentIndex = 0; const selectList = new SelectList(params.items, visibleRows, { selectedPrefix: (text) => theme.fg("accent", text), selectedText: (text) => text, description: (text) => theme.fg("muted", text), scrollInfo: (text) => theme.fg("dim", text), noMatch: (text) => theme.fg("warning", text), }); selectList.onSelect = (item) => params.onSelect(item); selectList.onCancel = () => done(); selectList.onSelectionChange = (item) => { currentIndex = params.items.indexOf(item); }; container.addChild(selectList); container.addChild( new Text(theme.fg("dim", " ↑↓ navigate • ←→ page • enter open • esc close"), 0, 0), ); container.addChild(new DynamicBorder((s: string) => theme.fg("accent", s))); return { render: (width) => container.render(width), invalidate: () => container.invalidate(), handleInput: (data) => { if (matchesKey(data, Key.left)) { currentIndex = Math.max(0, currentIndex - visibleRows); selectList.setSelectedIndex(currentIndex); } else if (matchesKey(data, Key.right)) { currentIndex = Math.min(params.items.length - 1, currentIndex + visibleRows); selectList.setSelectedIndex(currentIndex); } else { selectList.handleInput(data); } tui.requestRender(); }, }; }); }