/** * What the launcher pill says while the user is somewhere else. * * Closing the panel is leaving, not stopping. So the pill has three jobs * beyond opening the panel: narrate a run that is still going (humanized beat * label + ring), announce the finished result once (a toast whose View returns * to the conversation — the thread IS the record), and carry the two standing * signals: a numbered badge for asks waiting on the user, a quiet dot for * results they haven't seen. Nothing here ever opens or folds a surface on its * own; every path needs a click. */ import { type CSSProperties, type ReactNode } from "react"; import { type RunResult } from "./run-activity.js"; export interface LauncherStatus { /** A run is live and the panel is closed — the pill is the progress. */ working: boolean; /** Humanized label of the live step ("Working" between steps). */ label: string; /** Determinate ring input; absent = the quiet indeterminate ring. */ progress?: { done: number; total: number; }; /** Asks waiting on the user (the numbered badge). */ askCount: number; /** Something the user hasn't looked at (the quiet dot): a finished run, or an * app that has never rendered for them. */ unseenResults: boolean; /** The completion toast currently showing, if any. */ toast?: RunResult; /** View → mark seen and open the panel to the record. */ view(): void; dismissToast(): void; } /** * The pill's state. `threadId` is the conversation the panel currently holds * (reported by the thread): a result belonging to some OTHER surface's thread * is not this launcher's to announce. */ export declare function useLauncherStatus({ open, threadId, onOpen }: { open: boolean; threadId?: string; onOpen(): void; }): LauncherStatus; /** * Everything inside the pill: the mark (morph blob, host icon, or the run's * ring), the text (host label, or the live beat), the signal, and the spoken * line. The button itself — placement, open/close, focus — stays in * VendoOverlay; only its face lives here. */ export declare function LauncherFace({ status, label, icon }: { status: LauncherStatus; /** The host's pill text; `null` is the blob-only orb (no text at all). */ label: string | null; icon?: ReactNode; }): import("react").JSX.Element; /** The completion toast: one headline, one way back. Rides beside the pill it came from (above it in bottom corners, below it in top corners), so the answer lands where the user was already looking. `style` carries the F12 launcher-offset CSS variables so the toast moves with the pill. */ export declare function LauncherToast({ result, position, style, onView, onDismiss }: { result: RunResult; position: "bottom-right" | "bottom-left" | "top-right" | "top-left"; style?: CSSProperties; onView(): void; onDismiss(): void; }): import("react").JSX.Element;