/** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type Role = "user" | "assistant" | "system"; /** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type MessageStatus = "sending" | "sent" | "error"; /** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type ChatState = "closed" | "open" | "hidden"; /** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type Trigger = "user" | "api"; /** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type Device = "pc" | "mobile"; /** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type Effect = "fade" | "scale" | "slide" | "none"; /** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type Position = "bottom-right" | "bottom-left" | "top-right" | "top-left"; /** * Public types for Chit UI. This module has no runtime value; it exists so that * every other file can `@import` from one place and so `tsc` can emit .d.ts. */ export type BubbleTail = "none" | "top" | "bottom"; export type MessageBase = { /** * Unique within the array; used as the diffing key. */ id: string; role: Role; time?: string | Date | undefined; /** * Overrides the theme's speaker name; null hides it. */ name?: string | null | undefined; /** * Overrides the theme's speaker image; null hides it. */ avatar?: string | null | undefined; status?: MessageStatus | undefined; streaming?: boolean | undefined; /** * Never touched by the library. */ meta?: unknown; }; export type TextMessage = MessageBase & { text: string; }; export type HtmlMessage = MessageBase & { html: string; }; export type TemplateMessage = MessageBase & { template: import("lit").TemplateResult; }; export type ElementMessage = MessageBase & { element: HTMLElement; }; export type ComponentMessage = MessageBase & { component: (new () => HTMLElement) | string; props?: Record; }; export type Message = TextMessage | HtmlMessage | TemplateMessage | ElementMessage | ComponentMessage; export type Animation = { enter?: Effect | undefined; exit?: Effect | undefined; /** * ms */ duration?: number | undefined; }; export type Offset = { x?: number | undefined; y?: number | undefined; }; export type ClosedTheme = { /** * Launcher edge length in px, or 'auto' to let its content decide. */ size?: number | "auto" | undefined; position?: Position | undefined; offset?: Offset | undefined; radius?: number | undefined; /** * Icon image URL; null clears the default. */ image?: string | null | undefined; label?: string | null | undefined; /** * Let the reader move it around the viewport. */ draggable?: boolean | undefined; /** * A component that draws the whole launcher. */ component?: string | (new () => HTMLElement) | null | undefined; /** * Properties written to that component. */ props?: Record | undefined; colors?: { background?: string; text?: string; shadow?: string; } | undefined; animation?: (Animation & { idle?: "none" | "pulse" | "bounce"; }) | undefined; }; /** * The wait between sending and the answer arriving. */ export type LoadingStyle = "dots" | "spinner" | "text"; /** * The wait between sending and the answer arriving. */ export type LoadingTheme = { /** * Show it from `chat-submit` until the next message from the other side. */ auto?: boolean | undefined; /** * What it looks like. */ style?: LoadingStyle | undefined; /** * Wording beside the animation, or on its own for `'text'`. */ text?: string | null | undefined; /** * ms after which it gives up on its own; 0 leaves it to the consumer. */ timeout?: number | undefined; }; /** * Who is talking, as the theme describes them. A message that carries its own * `name` or `avatar` wins; `null` on the message hides what the theme set. */ export type SpeakerTheme = { /** * Shown above the bubble. */ name?: string | null | undefined; /** * Image URL for the speaker's icon. */ avatar?: string | null | undefined; }; export type OpenColors = { background?: string | undefined; text?: string | undefined; accent?: string | undefined; border?: string | undefined; shadow?: string | undefined; headerBackground?: string | undefined; headerText?: string | undefined; userBubble?: string | undefined; userText?: string | undefined; assistantBubble?: string | undefined; assistantText?: string | undefined; systemText?: string | undefined; inputBackground?: string | undefined; inputText?: string | undefined; inputPlaceholder?: string | undefined; }; export type OpenTheme = { /** * Ignored on mobile (always full screen). */ width?: number | undefined; /** * Ignored on mobile (always full screen). */ height?: number | undefined; position?: Position | undefined; offset?: Offset | undefined; radius?: number | undefined; /** * Keep the launcher visible while open. */ launcher?: "hidden" | "visible" | undefined; /** * Let the reader move the panel by its title bar. */ draggable?: boolean | undefined; /** * The title bar: whether it is there at all, its text, its image, and whether it offers a way back to the start. */ header?: { visible?: boolean; title?: string | null; logo?: string | null; home?: boolean; } | undefined; background?: { image?: string | null; } | undefined; colors?: OpenColors | undefined; /** * Bubble corner radius, and where the tail points from. */ bubble?: { radius?: number; tail?: BubbleTail; } | undefined; /** * Default name and icon per side. */ speaker?: { assistant?: SpeakerTheme; user?: SpeakerTheme; } | undefined; /** * The wait for an answer. */ loading?: LoadingTheme | undefined; animation?: (Animation & { scroll?: "smooth" | "instant"; }) | undefined; /** * Composer: rows, placeholder, and the attach button. */ input?: { maxRows?: number; placeholder?: string | null; attach?: boolean; accept?: string; multiple?: boolean; } | undefined; }; export type Theme = { /** * Widths below this are treated as mobile. */ breakpoint?: number | undefined; zIndex?: number | undefined; font?: { family?: string; size?: number; } | undefined; closed?: ClosedTheme | { pc?: ClosedTheme; mobile?: ClosedTheme; } | undefined; open?: OpenTheme | undefined; hidden?: { animation?: { exit?: Effect; duration?: number; }; } | undefined; }; /** * A theme with every gap filled in and `closed` narrowed to the device in use. * This is what the render functions and the CSS generator read. */ export type ResolvedClosed = { size: number | "auto"; position: Position; offset: { x: number; y: number; }; radius: number; draggable: boolean; image: string | null; label: string | null; component: (new () => HTMLElement) | string | null; props: Record; colors: { background: string; text: string; shadow: string; }; animation: { enter: Effect; exit: Effect; duration: number; idle: "none" | "pulse" | "bounce"; }; }; /** * A theme with every gap filled in and `closed` narrowed to the device in use. * This is what the render functions and the CSS generator read. */ export type ResolvedOpen = { width: number; height: number; position: Position; offset: { x: number; y: number; }; radius: number; launcher: "hidden" | "visible"; draggable: boolean; header: { visible: boolean; title: string | null; logo: string | null; home: boolean; }; background: { image: string | null; }; colors: Required; bubble: { radius: number; tail: BubbleTail; }; speaker: { assistant: Required; user: Required; }; loading: Required; animation: { enter: Effect; exit: Effect; duration: number; scroll: "smooth" | "instant"; }; input: { maxRows: number; placeholder: string | null; attach: boolean; accept: string; multiple: boolean; }; }; /** * A theme with every gap filled in and `closed` narrowed to the device in use. * This is what the render functions and the CSS generator read. */ export type ResolvedTheme = { breakpoint: number; zIndex: number; font: { family: string; size: number; }; closed: ResolvedClosed; open: ResolvedOpen; hidden: { animation: { exit: Effect; duration: number; }; }; /** * Which bucket `closed` was narrowed to. */ device: Device; };