/** * Mobile key toolbar for the web terminal — ticket #69, lot 3. * * A phone's virtual keyboard has no Esc, Tab, Ctrl or arrow keys, so on a * touch device a CLI agent is effectively undrivable: you can type a prompt but * you cannot interrupt it (Ctrl-C), complete a path (Tab), leave an editor * (Esc) or recall history (↑). This bar renders those keys as tappable chips. * * Two details carry the whole design: * * - **Focus must not move.** Tapping a chip would normally blur xterm's hidden * textarea, which collapses the virtual keyboard — so every tap would cost * the user their keyboard. Each chip therefore cancels the default * pointer-down focus shift and re-focuses the terminal, keeping the keyboard * up across taps. * - **Keys are injected, not written.** `send` goes through * {@link TerminalInputApi.send} (xterm's `input()`), the same path a typed * key takes, so the PTY relay and the agent write-portal behave identically * to real typing. * * It is web-only presentation: it holds no transport, and is rendered by * {@link WebAgentCell} below the terminal. */ import type { TerminalInputApi } from "@/features/terminals"; import { Button, cn } from "@/shared"; interface TerminalKeyBarProps { /** Input API of the mounted terminal; `null` until xterm reports ready. */ api: TerminalInputApi | null; className?: string; } /** A key chip: what the user reads, and the bytes a real keyboard would emit. */ interface KeyChip { label: string; /** Accessible name, when the glyph alone is not speakable (arrows). */ aria?: string; /** The exact sequence a physical key sends (xterm consumes it verbatim). */ data: string; } const KEYS: readonly KeyChip[] = [ { label: "Esc", data: "\x1b" }, { label: "Tab", data: "\t" }, { label: "Ctrl-C", aria: "Ctrl-C (interrompre)", data: "\x03" }, { label: "Ctrl-D", aria: "Ctrl-D (fin de saisie)", data: "\x04" }, { label: "↑", aria: "Flèche haut", data: "\x1b[A" }, { label: "↓", aria: "Flèche bas", data: "\x1b[B" }, { label: "←", aria: "Flèche gauche", data: "\x1b[D" }, { label: "→", aria: "Flèche droite", data: "\x1b[C" }, ]; export function TerminalKeyBar({ api, className }: TerminalKeyBarProps) { return (