import type { ChatStore } from './store.js'; export interface WidgetConfig { subject?: { title?: string; subtitle?: string; tags?: string[]; status?: string; ownerLabel?: string; }; quickReplies?: string[]; accent?: string; /** Secondary accent — the guest's OWN bubble + send button. Defaults to the * design blue; if omitted while `accent` is set, follows `accent` so a single * accent override re-themes cohesively. */ accent2?: string; /** Colour scheme. Default 'light'. 'auto' follows the OS (prefers-color-scheme); * 'dark'/'light' force it. Dark is never auto-applied unless the host opts in. */ theme?: 'auto' | 'light' | 'dark'; /** Load the brand webfonts (Baloo 2 + Nunito). Default true; set false for * strict-CSP / privacy-sensitive hosts (falls back to the system stack). */ webfont?: boolean; /** Identified user info — shown as the guest avatar/name in the widget header. */ userInfo?: { name?: string; avatar?: string; }; /** i18n string overrides */ i18n?: { placeholder?: string; send?: string; offline?: string; poweredBy?: string; online?: string; away?: string; aiAssistant?: string; resolved?: string; reopen?: string; sources?: string; helpful?: string; notHelpful?: string; translate?: string; original?: string; showOriginal?: string; translateUnavailable?: string; back?: string; sendMessage?: string; conversation?: string; typing?: string; }; } export interface RendererHandlers { onSend(text: string): void; onAttach?(file: File): void; onInvoke(actionId: string, inputs?: Record): void; onTyping(isTyping: boolean, preview?: string): void; onReadUpTo(seq: number): void; onReact?(messageId: string, emoji: string, remove: boolean): void; onCsat?(score: number): void; onLoadMore?(): void; onEdit?(messageId: string, newText: string): void; onDelete?(messageId: string): void; /** Pre-chat qualification submitted (values keyed by field; topic/callback included). */ onPreChat?(values: { name?: string; email?: string; phone?: string; topic?: string; callback?: boolean; }): void; /** KB deflection: the guest is typing their FIRST message — look up articles. */ onDeflectQuery?(q: string): void; /** Translate a message's text for display. Return null if unavailable — * the renderer shows a brief "unavailable" hint and leaves the original. */ onTranslate?(text: string): Promise; /** Stack navigation (chat-app surfaces): when set, the header shows a back * chevron on the left that calls this — tap a conversation → chatroom → * back → list, like a native messaging app. Omit for a standalone widget, * which has nothing to go "back" to. */ onBack?(): void; } /** Renders a ChatStore into a host element in the Image-1 layout: header → * subject card → action chips → chat → quick replies → input. Self-injects its * stylesheet so it looks right wherever it mounts. Accent comes from the * dashboard-authored profile theme (via the manifest), falling back to config. */ export declare class Renderer { private readonly root; private readonly me; private readonly h; private readonly cfg; private readonly scroll; private readonly chips; private readonly typing; private readonly quick; private suggestedKey; private readonly formHost; private readonly csatPanel; private readonly awayNotice; private readonly headStatus; private readonly reopenBtn; private readonly preChatPanel; private readonly deflectPanel; private preChatBuilt; private preChatDone; private readonly footer; private readonly input; private readonly subjectCard; private readonly e2eBadge; private readonly statusBadge; private readonly headerName; private readonly connStatus; private typingTimer; private csatSubmitted; private readonly sendBtn; /** Container-driven responsive sizing — toggles .ocw-compact (see CSS note). */ private compactObserver; private storeRef; private readonly cfgAccent2; private scrollCleanup; /** Returns the scroll container so history.ts can attach scroll listeners. */ getScrollEl(): HTMLElement | null; /** Registers a cleanup fn removed on destroy() to prevent listener leaks. */ setScrollCleanup(fn: () => void): void; private readonly translationCache; private readonly showingTranslation; private readonly autoTranslated; /** Last seq the guest has seen per conversationId — used to compute unread badges. */ constructor(root: HTMLElement, me: string, h: RendererHandlers, cfg?: WidgetConfig); /** Call when the widget is unmounted. Disconnects scroll listeners and clears timers. */ destroy(): void; private flushSend; /** Grow the composer with its content (up to the CSS max-height), collapse * when cleared. scrollHeight is 0 in non-layout environments (jsdom) — * skip there so tests and SSR-ish mounts are unaffected. */ private autoGrowInput; private signalTyping; /** A3.3 — per-chatroom bot identity from the manifest; relabels bot bubbles. */ setBotName(name: string): void; /** (Re)build the strip of tappable prompts above the composer. Each tap sends * the prompt as the guest's message and hides the strip. */ private buildQuick; render(store: ChatStore): void; setConnStatus(status: 'connecting' | 'open' | 'reconnecting' | 'error', message?: string): void; private buildPreChatPanel; /** Mark pre-chat complete (submitted now or in a previous session). */ completePreChat(): void; /** KB deflection results ("was this your question?") above the composer. */ showDeflection(articles: { id: string; title: string; answer: string; }[]): void; hideDeflection(): void; private buildCsatPanel; /** Whether the subject card (server Subject entity, mount config fallback) * has been built — built once when data first arrives. */ private subjectBuilt; private buildSubjectCard; private chipEl; /** In-widget confirmation modal (replaces window.confirm). */ private confirm; /** Inline form for a form-effect action: typed inputs (date picker, number, * text) rendered above the composer — no browser prompts. `prefill` seeds * field values (search pre-fill) — deterministic parse, correctable before * submit. */ private openForm; private messageEl; }