fix: render TUI pickers as overlays
This commit is contained in:
60
src/tui/tui-overlays.test.ts
Normal file
60
src/tui/tui-overlays.test.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import type { Component } from "@mariozechner/pi-tui";
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
import { createOverlayHandlers } from "./tui-overlays.js";
|
||||
|
||||
class DummyComponent implements Component {
|
||||
render() {
|
||||
return ["dummy"];
|
||||
}
|
||||
|
||||
invalidate() {}
|
||||
}
|
||||
|
||||
describe("createOverlayHandlers", () => {
|
||||
it("routes overlays through the TUI overlay stack", () => {
|
||||
const showOverlay = vi.fn();
|
||||
const hideOverlay = vi.fn();
|
||||
const setFocus = vi.fn();
|
||||
let open = false;
|
||||
|
||||
const host = {
|
||||
showOverlay: (component: Component) => {
|
||||
open = true;
|
||||
showOverlay(component);
|
||||
},
|
||||
hideOverlay: () => {
|
||||
open = false;
|
||||
hideOverlay();
|
||||
},
|
||||
hasOverlay: () => open,
|
||||
setFocus,
|
||||
};
|
||||
|
||||
const { openOverlay, closeOverlay } = createOverlayHandlers(host, new DummyComponent());
|
||||
const overlay = new DummyComponent();
|
||||
|
||||
openOverlay(overlay);
|
||||
expect(showOverlay).toHaveBeenCalledWith(overlay);
|
||||
|
||||
closeOverlay();
|
||||
expect(hideOverlay).toHaveBeenCalledTimes(1);
|
||||
expect(setFocus).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("restores focus when closing without an overlay", () => {
|
||||
const setFocus = vi.fn();
|
||||
const host = {
|
||||
showOverlay: vi.fn(),
|
||||
hideOverlay: vi.fn(),
|
||||
hasOverlay: () => false,
|
||||
setFocus,
|
||||
};
|
||||
const fallback = new DummyComponent();
|
||||
|
||||
const { closeOverlay } = createOverlayHandlers(host, fallback);
|
||||
closeOverlay();
|
||||
|
||||
expect(setFocus).toHaveBeenCalledWith(fallback);
|
||||
});
|
||||
});
|
||||
19
src/tui/tui-overlays.ts
Normal file
19
src/tui/tui-overlays.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import type { Component, TUI } from "@mariozechner/pi-tui";
|
||||
|
||||
type OverlayHost = Pick<TUI, "showOverlay" | "hideOverlay" | "hasOverlay" | "setFocus">;
|
||||
|
||||
export function createOverlayHandlers(host: OverlayHost, fallbackFocus: Component) {
|
||||
const openOverlay = (component: Component) => {
|
||||
host.showOverlay(component);
|
||||
};
|
||||
|
||||
const closeOverlay = () => {
|
||||
if (host.hasOverlay()) {
|
||||
host.hideOverlay();
|
||||
return;
|
||||
}
|
||||
host.setFocus(fallbackFocus);
|
||||
};
|
||||
|
||||
return { openOverlay, closeOverlay };
|
||||
}
|
||||
@@ -1,11 +1,4 @@
|
||||
import {
|
||||
CombinedAutocompleteProvider,
|
||||
type Component,
|
||||
Container,
|
||||
ProcessTerminal,
|
||||
Text,
|
||||
TUI,
|
||||
} from "@mariozechner/pi-tui";
|
||||
import { CombinedAutocompleteProvider, Container, ProcessTerminal, Text, TUI } from "@mariozechner/pi-tui";
|
||||
import { resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import {
|
||||
@@ -22,6 +15,7 @@ import { editorTheme, theme } from "./theme/theme.js";
|
||||
import { createCommandHandlers } from "./tui-command-handlers.js";
|
||||
import { createEventHandlers } from "./tui-event-handlers.js";
|
||||
import { formatTokens } from "./tui-formatters.js";
|
||||
import { createOverlayHandlers } from "./tui-overlays.js";
|
||||
import { createSessionActions } from "./tui-session-actions.js";
|
||||
import type {
|
||||
AgentSummary,
|
||||
@@ -188,10 +182,8 @@ export async function runTui(opts: TuiOptions) {
|
||||
const footer = new Text("", 1, 0);
|
||||
const chatLog = new ChatLog();
|
||||
const editor = new CustomEditor(editorTheme);
|
||||
const overlay = new Container();
|
||||
const root = new Container();
|
||||
root.addChild(header);
|
||||
root.addChild(overlay);
|
||||
root.addChild(chatLog);
|
||||
root.addChild(status);
|
||||
root.addChild(footer);
|
||||
@@ -300,16 +292,7 @@ export async function runTui(opts: TuiOptions) {
|
||||
);
|
||||
};
|
||||
|
||||
const closeOverlay = () => {
|
||||
overlay.clear();
|
||||
tui.setFocus(editor);
|
||||
};
|
||||
|
||||
const openOverlay = (component: Component) => {
|
||||
overlay.clear();
|
||||
overlay.addChild(component);
|
||||
tui.setFocus(component);
|
||||
};
|
||||
const { openOverlay, closeOverlay } = createOverlayHandlers(tui, editor);
|
||||
|
||||
const initialSessionAgentId = (() => {
|
||||
if (!initialSessionInput) return null;
|
||||
|
||||
Reference in New Issue
Block a user