import { type ComponentType, type ReactNode, type RefAttributes } from "react"; import { type TextInput as RNTextInput } from "react-native"; import { type LayoutStyle } from "../../style/index.js"; import { type ButtonProps } from "../../atoms/button/button.js"; import { type TextareaProps } from "../../atoms/textarea/textarea.js"; import { type SpinnerProps } from "../../atoms/spinner/spinner.js"; import { type ChipProps } from "../../atoms/chip/chip.js"; import { type RadioProps, type RadioGroupProps } from "../../atoms/radio/radio.js"; import { type CheckboxProps } from "../../atoms/checkbox/checkbox.js"; import { type FormSectionProps } from "../../molecules/form/form.js"; import { type SwitchProps } from "../../atoms/switch/switch.js"; import { type CardProps } from "../../molecules/card/card.js"; import { type MarkdownParts } from "./markdown.shared.js"; import * as s from "./chat.styles.js"; /** Application-owned file metadata. Picking, uploading, and opening files belong to the app. */ export interface ChatAttachmentData { id: string; name: string; uploading?: boolean; error?: boolean; notice?: string; } /** One application-owned question, single-choice unless multiple is set. Reserve the option id `__custom` for freeform answers. */ export interface ChatQuestionData { id: string; title: string; /** Allow any nonempty set of choices, including a custom answer alongside other options. */ multiple?: boolean; options: readonly { id: string; label: string; description?: string; }[]; } /** A controlled answer. `__custom` requires nonempty customText, limited to 1000 characters. */ export interface ChatQuestionAnswerData { questionId: string; optionId?: string; /** Multi-select answers use optionIds instead of optionId. */ optionIds?: string[]; /** Human-selected multi-answer mode for a question originally supplied as single-choice. */ multiple?: boolean; customText?: string; } interface MessageActionCallbacks { /** The app owns action handling, persistence, and removing resolved actions. */ onAction?: (messageId: string | number, actionId: string) => void; } interface QuestionCallbacks { /** Update the message's controlled questionAnswers; the app owns saving the draft. */ onQuestionAnswerChange?: (messageId: string | number, answers: ChatQuestionAnswerData[]) => void; /** Submit the final complete answer set; the app owns transport and setting questionsSubmitted. */ onSubmitQuestionAnswers?: (messageId: string | number, answers: ChatQuestionAnswerData[]) => void; /** Save the zero-based current question index; omit questionIndex for local navigation state. */ onQuestionIndexChange?: (messageId: string | number, index: number) => void; /** Disable question forms while other application work is in progress. */ disabled?: boolean; pending?: boolean; } /** Application-owned message data. Update content under the same id while streaming. */ export interface ChatMessageData { id: string | number; role: "user" | "assistant" | "system"; content: string; author?: string; provider?: string; /** Application-supplied provider mark; give the image/icon an accessible provider name. */ providerIcon?: ReactNode; attachments?: readonly ChatAttachmentData[]; /** Application-owned choices beneath the message; omit once the choice is resolved. */ actions?: readonly { id: string; label: string; primary?: boolean; }[]; streaming?: boolean; /** Optional structured question form beneath assistant content. */ questions?: readonly ChatQuestionData[]; /** Controlled answers, one entry per question. */ questionAnswers?: readonly ChatQuestionAnswerData[]; /** Controlled zero-based position within questions; the counter always uses the actual question count. */ questionIndex?: number; /** Saved answers are shown read-only with an Answers sent receipt. */ questionsSubmitted?: boolean; /** Show every original question and option read-only for an earlier or inactive batch. */ questionsDisabled?: boolean; /** Marks a failed reply with an explicit error label as well as error ink. */ error?: boolean; /** Persisted delivery, fallback, or other supplementary information. */ notice?: string; /** * Work the assistant did rather than said (a command, a tool call, a process log): one muted * line, `author` then `notice`, that expands to its markdown `content`, the way a desktop * assistant folds its tool use between replies. */ activity?: boolean; } export interface ChatMessageProps extends QuestionCallbacks, MessageActionCallbacks { message: ChatMessageData; onOpenAttachment?: (attachment: ChatAttachmentData) => void; /** Render assistant markdown punctuation literally. User messages are always plain text. */ plain?: boolean; /** Flat, compact monospace terminal transcript. */ terminal?: boolean; /** * Lay the conversation out like a desktop assistant's window (the Claude desktop window, * reference claude-desktop-chat): one centered reading column, plain 15 / 21 replies, a * neutral user bubble, a wider rhythm between turns, and a raised 44 px composer with a * quiet send control and the `meta` line. Without it, Chat draws the v4 hand-off's look. */ assistant?: boolean; testID?: string; } export interface ChatThreadProps extends QuestionCallbacks, MessageActionCallbacks { messages: readonly ChatMessageData[]; onOpenAttachment?: (attachment: ChatAttachmentData) => void; /** A reply is being prepared; no artificial message is added to the data. */ pending?: boolean; pendingLabel?: string; /** Application-supplied provider mark for a reply that has not started streaming. */ pendingIcon?: ReactNode; label?: string; emptyState?: ReactNode; plain?: boolean; /** Flat, compact monospace terminal transcript. */ terminal?: boolean; /** Draw no frame: the conversation sits on its host's fill, as a desktop assistant's window does. */ flush?: boolean; /** * Lay the conversation out like a desktop assistant's window (the Claude desktop window, * reference claude-desktop-chat): one centered reading column, plain 15 / 21 replies, a * neutral user bubble, a wider rhythm between turns, and a raised 44 px composer with a * quiet send control and the `meta` line. Without it, Chat draws the v4 hand-off's look. */ assistant?: boolean; testID?: string; /** Parent composition only. Supply a bounded height, or a bounded flex parent. */ style?: LayoutStyle; } export interface ChatComposerProps { /** Bare terminal prompt; hardware Enter sends and Shift+Enter inserts a newline. */ terminal?: boolean; /** Focus the message input on mount. */ autoFocus?: boolean; value: string; onChangeText: (value: string) => void; /** Receives the trimmed draft. The app owns clearing the draft and starting transport. */ onSend: (value: string) => void; placeholder?: string; composerLabel?: string; sendLabel?: string; /** Block only sending, keeping the draft, attachments, and message choices interactive. */ sendDisabled?: boolean; /** Optional application input limit; enforced by the native text field. */ maxLength?: number; /** Prevent sending while a reply is pending; the draft remains editable. */ pending?: boolean; disabled?: boolean; /** Show an attachment control; the app owns its file picker and upload service. */ onAttach?: () => void; attachments?: readonly ChatAttachmentData[]; onRemoveAttachment?: (id: string) => void; /** File selection or upload is in progress; prevents attaching or sending again. */ attaching?: boolean; /** Anchored actions or help below the composer, outside the scrolling thread. */ footer?: ReactNode; /** With `assistant`, a short muted line at the composer's end below it, naming the model or mode that will answer. */ meta?: string; /** * Lay the conversation out like a desktop assistant's window (the Claude desktop window, * reference claude-desktop-chat): one centered reading column, plain 15 / 21 replies, a * neutral user bubble, a wider rhythm between turns, and a raised 44 px composer with a * quiet send control and the `meta` line. Without it, Chat draws the v4 hand-off's look. */ assistant?: boolean; testID?: string; } export interface ChatProps extends ChatThreadProps, ChatComposerProps { } interface ChatParts extends MarkdownParts { Button: ComponentType; Textarea: ComponentType>; Spinner: ComponentType; Chip: ComponentType; Radio: ComponentType; RadioGroup: ComponentType; Checkbox: ComponentType; FormSection: ComponentType; Switch: ComponentType; Card: ComponentType; } export declare function createChat(skin: s.ChatSkin, { Button, Textarea, Spinner, Chip, Radio, RadioGroup, Checkbox, FormSection, Switch, Card, DataTable, Divider }?: Partial): { Chat: (props: ChatProps) => import("react").JSX.Element; ChatThread: (props: ChatThreadProps) => import("react").JSX.Element; ChatMessage: (props: ChatMessageProps) => import("react").JSX.Element; ChatComposer: (props: ChatComposerProps & { flush?: boolean; }) => import("react").JSX.Element; }; export {}; //# sourceMappingURL=chat.shared.d.ts.map