import { ElementRef, OnDestroy, QueryList, AfterViewInit, TemplateRef } from '@angular/core'; import { Observable } from 'rxjs'; import type { AparteMessage, AparteSegment, AparteSendEventDetail, AparteConfig, AparteActionEventDetail, AparteChatImperativeApi } from '@aparte/core'; import { isAwaitingReply } from '@aparte/core'; import * as i0 from "@angular/core"; /** * AparteChatComponent — Angular 19 Wrapper * * Standalone component wrapping aparté Web Components with Angular Signals. * The streaming / branch-navigation / host-method orchestration (orphan-stream * guard, lifecycle tracking, conversation lifecycle, bubble reconciliation) * lives in the framework-agnostic `AparteChatHost` from `@aparte/core`; this * component only owns the Angular-idiomatic surface (signals, template, DI) and * binds the host over its `messages` signal. */ export declare class AparteChatComponent implements AfterViewInit, OnDestroy, AparteChatImperativeApi { constructor(); private elementRef; /** * Template bridge to core's shared `isAwaitingReply` (an Angular template can't * call an imported function). One rule for the four wrappers and core itself, * so "is this bubble in flight" can't drift between them. */ readonly awaitingReply: typeof isAwaitingReply; /** Messages to display */ set messagesInput(val: AparteMessage[]); readonly messages: import("@angular/core").WritableSignal; /** Input placeholder text */ set placeholderInput(val: string); readonly placeholder: import("@angular/core").WritableSignal; /** Whether the input is disabled */ set disabledInput(val: boolean); readonly disabled: import("@angular/core").WritableSignal; /** When false, Shift+Enter submits and a bare Enter inserts a newline. */ set submitOnEnterInput(val: boolean); readonly submitOnEnter: import("@angular/core").WritableSignal; /** * Opt in to the "centered composer when empty" layout: the composer sits * vertically centered with the `[slot='empty-state']` content above it while * the list is empty, then slides to the bottom on the first message (~0.3s). * Off by default — additive (adds the `--auto-center` modifier + a * `data-aparte-empty` attribute the shipped `aparte.css` recipe keys off). */ set centerWhenEmptyInput(val: boolean); readonly centerWhenEmpty: import("@angular/core").WritableSignal; /** * The conversation is on its way: the viewport draws two skeleton turns, the empty * state stays off and the composer is disabled until it lands. The conversation * controller sets this itself while it fetches through your adapter's `loadFull()`; * the input is for a wait of your own. Off by default. */ set loadingInput(val: boolean); readonly loading: import("@angular/core").WritableSignal; /** The controller's wait (a conversation fetched through the adapter). */ readonly hostLoading: import("@angular/core").WritableSignal; readonly waiting: import("@angular/core").Signal; get loadingText(): string; /** * Class(es) merged onto the INNER `.aparte-chat-container`, not onto this * component's own `` host. * * The other three wrappers have no such host: their root IS the container, so a * consumer's `className` / `class` lands on the div that carries * `.aparte-chat-container`, `[overlay-composer]` and `[data-aparte-empty]` — the * three selectors core's shell recipe keys on. Here a class written on the tag * lands one level above them, so overriding the shell needed a descendant * selector on Angular alone. This input is that parity. Additive: the recipe's * own classes stay. */ set containerClassInput(val: string); readonly containerClass: import("@angular/core").WritableSignal; /** Inline style for the same div — a string or a `{ prop: value }` map. */ set containerStyleInput(val: string | Record | null); readonly containerStyle: import("@angular/core").WritableSignal>; /** * Overlay the composer on the transcript (the ChatGPT anatomy): the scroll * surface spans the whole column, the scrollbar runs edge to edge, and the * composer floats over it. Bound on the INNER `.aparte-chat-container` — that * div is this wrapper's shell (the viewport is its child, not the host's), and * core's recipe and the viewport's measurement both key on the attribute * there. Read when the viewport mounts. */ set overlayComposerInput(val: boolean); readonly overlayComposer: import("@angular/core").WritableSignal; /** * Add the file picker + chips strip to the default composer shell. **Off by * default**, because the capability needs a host that consumes the files: an * `AparteClient` inlines them per its `rawFileInject` option, but if you drive * your own loop you must read `event.files` on `(messageSent)` — otherwise the * file the user deliberately attached is dropped in silence. No effect when you * project a `[slot='composer']` (drop `` and * `` in it yourself). */ set attachmentsInput(val: boolean); readonly attachments: import("@angular/core").WritableSignal; /** * Render the `` presenter inside the host — on by default, as * it is in ``: the built-in approval gate and `requestUserInput()` * ask through it, and it renders nothing until something asks. Set it to `false` * when you mount a presenter of your own (`setElicitationPresenter`) or place the * element yourself. */ set elicitationInput(val: boolean); readonly elicitation: import("@angular/core").WritableSignal; /** Whether the assistant is currently typing/streaming */ set isTypingInput(val: boolean); readonly isTyping: import("@angular/core").WritableSignal; /** Text to show in the typing status */ set typingTextInput(val: string); readonly typingText: import("@angular/core").WritableSignal; /** Duration in ms to freeze spacer recalculation after a conversation swap. */ layoutTransitionMs: number; /** * Active conversation id. When provided, the host attaches an * `AparteConversationController` that loads/persists messages via the * `AparteConversationManager` registered in `aparteGlobalConfig`. Setting a different id * mid-stream aborts the previous request; `null` deselects. */ set conversationIdInput(val: string | null | undefined); private _conversationId; /** * Instance {@link AparteConfig} for this chat. When set, aparté components * inside resolve THIS config instead of `aparteGlobalConfig`, so * several independently-configured chats can coexist on one page. Omit for the * global config. Read once in `ngAfterViewInit` when the host is created. */ config?: AparteConfig; /** * Render your OWN element per message in place of ``. * Opt-in — provide a `` and pass its ref. Driven by * the reactive `messages()` signal, so it updates live during streaming. * The built-in action bar (retry/edit/branch) belongs to the native bubble; * a custom bubble owns whatever it wires. * @example * * {{ message.content }} */ bubbleTemplate?: TemplateRef<{ $implicit: AparteMessage; }>; /** * User submitted a message from the composer. It is **appended to the thread * automatically** (optimistic UI) before this fires — do NOT add it again in * the handler (uncontrolled → duplicates; controlled → mirror it into your * own `[messages]`). For side-effects: scroll, analytics, send. */ readonly messageSent: import("@angular/core").OutputEmitterRef; /** * Emitted when a custom bubble action (registered via * `aparteGlobalConfig.registerAction` with `zones: ['bubble']`) is clicked — a typed * wrapper over the bubbling `aparte-action` DOM event. Switch on `$event.actionId`. */ readonly action: import("@angular/core").OutputEmitterRef; /** Emitted when messages are updated internally (e.g. by AparteClient) */ readonly messagesChange: import("@angular/core").OutputEmitterRef; /** Emitted when a message is added internally (e.g. by appendMessage) */ readonly messageAppended: import("@angular/core").OutputEmitterRef; /** The typing/"thinking" indicator toggled (the host flips it off on the first streamed token). */ readonly typingChange: import("@angular/core").OutputEmitterRef; /** Emitted when the controller lazily creates a conversation on first send. */ readonly conversationCreated: import("@angular/core").OutputEmitterRef; viewportRef?: ElementRef; inputRef?: ElementRef; bubbleRefs: QueryList>; /** Mirror of the host's streaming target id (drives `isStreaming`). */ private readonly _streamingId; /** Computed: is currently streaming */ readonly isStreaming: import("@angular/core").Signal; /** rAF id used to coalesce rapid signal updates during streaming */ private _syncRafId; /** The framework-agnostic chat-host orchestrator (created in ngAfterViewInit). */ private _host?; private _unbindHost?; /** QueryList.changes subscription — released in ngOnDestroy so SPA route * churn doesn't leak a live subscription per mount. */ private _bubbleRefsSub?; ngAfterViewInit(): void; private readonly _onAction; ngOnDestroy(): void; /** Append a message optimistically — `{ historical: true }` for one restored from your own store. */ appendMessage(message: AparteMessage, options?: { historical?: boolean; }): void; /** Atomic update for a message. */ updateMessage(messageId: string, updates: Partial): void; /** Update the last message content (streaming text). */ updateLastMessage(content: string, options?: { append?: boolean; }): void; /** Add a segment to the last message. */ addSegment(segment: AparteSegment): void; /** Update a segment in the last message. */ updateSegment(segmentId: string, updates: Partial): void; /** Remove a transient segment. */ removeSegment(segmentId: string): void; /** Append content to a segment in the last message. */ appendToSegment(segmentId: string, content: string): void; /** Read the current message list. */ getMessages(): AparteMessage[]; /** * Clear all messages + reset state. `{ revokeAttachments: false }` keeps the * attachments' object URLs alive — pass it when the same messages are going back. */ clearMessages(options?: { revokeAttachments?: boolean; }): void; /** Scroll the viewport to the latest message. */ scrollToBottom(): void; /** * The `` element — for custom scroll handling, an * IntersectionObserver, etc. Same `getViewport()` accessor on all four * wrappers. */ getViewport(): HTMLElement | null; /** Focus the composer input. */ focusInput(): void; /** Create a new branch from a message (returns the new sibling index). */ addBranch(messageId: string): number; /** Add a sibling of an existing message (returns the new id). */ addSiblingOf(existingId: string, newMessage: AparteMessage): string | null; /** Remove a message and all descendants (edit flow). */ truncateFrom(messageId: string): void; /** Keep up to and including a user message, drop later responses (retry). */ truncateResponsesAfter(userMessageId: string): void; /** * Inject a token stream for LLM streaming. Takes the cross-wrapper * `AsyncIterable` contract (the exact call that works on * React/Vue/Svelte) — or an Angular-idiomatic RxJS `Observable`, * adapted into the host's agnostic `streamTokens(AsyncIterable)` so the * orphan-stream guard + id tracking stay in one place (the host). */ injectTokenStream(messageId: string, stream: Observable | AsyncIterable): Promise; /** Stop any active token stream. */ stopTokenStream(): void; /** * Set the active conversation id imperatively — parity with the other * wrappers' handles (the `conversationId` `@Input` remains the declarative * path). Delegates to the host, which loads/persists via the registered * `AparteConversationManager`. */ setConversationId(id: string | null): Promise; private _observableToAsyncIterable; /** Handle aparte-send event from the composer Web Component. */ onAparteSend(event: Event): void; static ɵfac: i0.ɵɵFactoryDeclaration; static ɵcmp: i0.ɵɵComponentDeclaration; static ngAcceptInputType_disabledInput: unknown; static ngAcceptInputType_submitOnEnterInput: unknown; static ngAcceptInputType_centerWhenEmptyInput: unknown; static ngAcceptInputType_loadingInput: unknown; static ngAcceptInputType_overlayComposerInput: unknown; static ngAcceptInputType_attachmentsInput: unknown; static ngAcceptInputType_elicitationInput: unknown; static ngAcceptInputType_isTypingInput: unknown; static ngAcceptInputType_layoutTransitionMs: unknown; }