import type { VendoTheme } from "../../core/apps/index.js"; import { type ComponentType, type ReactNode } from "react"; import { type VendoDiscoverability, type VendoGreeting } from "./discoverability.js"; import { type VendoThreadProps } from "./thread/index.js"; /** F12 (ENG-388) — the launcher's viewport corners. */ export type VendoLauncherPosition = "bottom-right" | "bottom-left" | "top-right" | "top-left"; export interface VendoOverlayProps { /** Controlled open state — pair with `onOpenChange`. Omit for uncontrolled. */ open?: boolean; /** Initial state in uncontrolled mode (default `false`). */ defaultOpen?: boolean; /** Fires for every open/close request: launcher click, close button, Escape, scrim click, or programmatic toggles. */ onOpenChange?(open: boolean): void; /** * Built-in launcher placement and content. The default is `"none"`: a bare * `` renders NO pill, and the panel opens programmatically * — `open`/`onOpenChange`, the `useVendoOverlay` hook, `VendoTrigger`, the * palette, or a slot. * * Opt the pill in with a corner string or the object form. `launcher={{}}` * is the plain pill: a fixed pill in the corner carrying the accent-circle * mark and a WHITE-LABEL text — "AI agent", never a product name. * `position` picks the corner (default `"bottom-right"`), `label` accepts * any host string (`null` collapses the pill to a blob-only orb), `icon` * swaps the blob for a host element, and `offset` nudges the whole launcher * cluster (pill, whisper, toast) inward from its corner when the host's own * UI already lives there (F12, ENG-388). */ launcher?: VendoLauncherPosition | "none" | { position?: VendoLauncherPosition; /** Pill text. Default "AI agent"; `null` renders the blob-only orb. */ label?: string | null; /** Replaces the circle mark (a host logo, custom glyph, …). */ icon?: ReactNode; /** Extra pixels pushed inward from the anchored corner: `x` from the * anchored side, `y` from the anchored edge. Safe-area insets still * apply on top. */ offset?: { x?: number; y?: number; }; }; /** * Change to discard the current conversation and start a fresh thread * (ENG-221). `useVendoOverlay().newConversation()` drives this for you; * hosts managing their own state can bump any number/string. The panel's * built-in new-conversation button works with or without this prop. */ conversationKey?: string | number; /** * The one sanctioned component-injection point: a thread component the panel * renders in place of the built-in `VendoThread`. The overlay stays the * positioning shell — portal, scrim, focus, mobile sheet — while a custom * thread supplies the conversation pixels. It receives `VendoThreadProps` * (all optional), so a plain zero-prop component works too. */ thread?: ComponentType; /** * The discoverability dial (ui-usage-dx §6), overriding the provider's. * `"default"` keeps the fire-once whisper on the launcher pill (and the * thread's greeting-as-tutorial); `"quiet"` turns both off. Nothing here * ever fires twice for the same user — the whisper marks itself seen the * moment it first renders. */ discoverability?: VendoDiscoverability; /** * Greeting-as-tutorial content for the thread's one-time first message * (intro + prompt chips — the `.vendo/greeting.json` shape), overriding the * provider's `greeting`. */ greeting?: VendoGreeting; /** * This surface's own brand tokens, merged group by group over the provider's * resolved theme — the same merge `VendoProvider` does over * `defaultVendoTheme`, so with no provider above this merges over the * defaults. The panel portals to `` and the approval modal portals * again from inside it; both carry these tokens. * * FRAME ONLY: it styles Vendo's own chrome — launcher, panel, thread, * composer. A generated view mounted in the conversation keeps the PROVIDER * theme, whether it is iframe-served (themed over the app transport) or * rendered natively: the tree surface restates the provider tokens on its * own root, so the local ones do not cascade in. */ theme?: Partial; /** * Where the panel sits while open. * * `"center"` (the default) is the centered modal box: scrim, body * scroll-lock, inert background and focus trap. It stays the default so * upgrading never changes an existing host's behavior. * * `"dock"` is the opt-in DevTools posture: a full-height side panel against * the right edge, with the host page REFLOWED beside it. It is deliberately * NON-modal — none of those four containments — because the page is the * thing being reshaped and has to stay visible and clickable while the panel * is open. Below the mobile breakpoint both collapse to the full-bleed * takeover, which owns small screens either way. */ placement?: "dock" | "center"; /** Docked panel width in CSS px (default 420) — also the amount the host * page reflows by, so the two can never disagree. */ dockWidth?: number; /** * The one line the panel shows a visitor the wire refused for missing * identity (H2-E / #1372) — host-brandable, defaulting to * "Sign in to use the agent." The launcher still renders (nothing about * wire health hides it); only the panel content changes, and the server's * developer-facing resolver message never reaches this surface. The panel * returns to the conversation on `vendo:identity-changed` or the first * successful wire read. */ signedOutNotice?: string; } /** 08-ui §4 — floating modal launcher with focus containment and restoration. * Supported entry API (ENG-220): opt-in positioned launcher, controlled + * uncontrolled programmatic open/close, panel portaled to document.body with * body scroll-lock and an inert background while open. */ export declare function VendoOverlay({ open: openProp, defaultOpen, onOpenChange, launcher, conversationKey, thread: Thread, discoverability, greeting, theme: themeOverride, placement, dockWidth, signedOutNotice, }?: VendoOverlayProps): import("react").JSX.Element;