@kitn.ai/chat
Version:
Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.
711 lines (663 loc) • 39.1 kB
TypeScript
// AUTO-GENERATED by scripts/gen-element-api.mjs — do not edit by hand.
// Typed custom-element interfaces + HTMLElementTagNameMap augmentation, so
// `document.querySelector('kc-message')` is typed and gets prop autocomplete.
// Re-exports for `import { … } from '@kitn.ai/chat/elements'`.
export type { ChatMessage, ChatMessageAction } from './chat-types';
export { configureCodeHighlighting, isCodeHighlightingEnabled } from '../primitives/highlighter';
export type { CodeHighlightingOptions } from '../primitives/highlighter';
export interface KcArtifactElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** URL the preview iframe frames. Consumer-controlled. */
src?: string;
/** Files for the Code tab tree + each file's preview `url`. Set as a JS property (array). */
files: { path: string; url?: undefined | string; code?: undefined | string; language?: undefined | string; type?: undefined | "html" | "pdf" | "image" | "other" }[];
/** Active tab: `preview` (default) or `code`. */
tab?: "preview" | "code";
/** Selected file path — syncs the tree highlight, Code source, and preview. */
activeFile?: string;
/** iframe `sandbox` override. Secure default `allow-scripts allow-forms` (NOT `allow-same-origin`). */
sandbox?: string;
/** Accessible title for the preview iframe. */
iframeTitle?: string;
/** Reflects the artifact's own maximized view-state (usually driven by the protocol). */
maximized?: boolean;
/** Show the expand-to-fill button (OPT-IN). */
expandable?: boolean;
/** Show the open-in-new-tab button (OPT-IN). */
openInTab?: boolean;
/** Hide back/forward. */
noNav?: boolean;
/** Hide reload. */
noReload?: boolean;
/** Hide home. */
noHome?: boolean;
/** Hide the address field. */
noPathField?: boolean;
/** Hide the Preview|Code toggle. */
noTabs?: boolean;
/** Standalone chrome: rounded corners + border (else square, borderless in-panel). */
standalone?: boolean;
/** Show the address but make it read-only (visible, nav-tracking, non-editable). */
readonlyPath?: boolean;
}
export interface KcAttachmentsElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The attachments to render. Set as a JS property (array). */
items: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[];
/** Layout: `grid` = visual tiles, `inline` = icon + label chips, `list` = rows. */
variant?: "grid" | "inline" | "list";
/** Wrap each item in a hover card that previews its details. */
hoverCard?: boolean;
/** Show a remove button per item; clicking it fires a `kc-remove` event. */
removable?: boolean;
/** Also show the media type beneath the filename (non-grid variants). */
showMediaType?: boolean;
/** Text shown when `items` is empty. */
emptyText?: string;
}
export interface KcCardElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
heading?: string;
/** Supporting text under the heading. Attribute: `description`. */
description?: string;
/** When set, the card renders its inline error state instead of the body. Attribute: `error-message`. */
errorMessage?: string;
/** Compact spacing for dense lists. Attribute: `dense`. */
dense?: boolean;
}
export interface KcCardsElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The stream of card envelopes to render. Set as a JS PROPERTY: `el.cards = [...]`. */
cards?: { type: string; id: string; data: unknown; title?: string; resolution?: { kind: "action"; action: string; payload?: unknown; at?: string } | { kind: "submit"; data: unknown; at?: string } }[];
/** Optional type→tag overrides/additions (merged over the built-ins). Property: `el.types`. Typed as a plain string map (not the `CardTagMap` alias) so the generated React wrapper inlines it instead of emitting an unresolved named type. */
types?: Record<string, string>;
/** Optional CardPolicy handling child events. Property: `el.policy`. */
policy?: { onSubmit?: (cardId: string, data: unknown) => void; onAction?: (cardId: string, action: string, payload?: unknown) => void; onSendPrompt?: (text: string, opts: { mode: "compose" | "send"; context?: unknown; }) => void; onOpen?: (url: string, target: "tab" | "artifact") => void; onState?: (cardId: string, patch: unknown) => void; onDismiss?: (cardId: string) => void; onError?: (cardId: string, message: string) => void; maxSendPromptMode?: "compose" | "send" };
}
export interface KcChainOfThoughtElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The reasoning steps. Set as a JS property. Compound sub-parts collapse to this one data model (Route 1). */
steps: { label: string; content?: undefined | string }[];
}
export interface KcChatElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions. Set as a JS property (`el.messages = [...]`). */
messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string } }[];
/** Controlled value of the input. When set, the host owns the input text and must update it on `kc-value-change`; leave unset for uncontrolled behavior. */
value?: string;
/** Placeholder text shown in the empty input. */
placeholder?: string;
/** When true, shows the loading/streaming state and disables submit (use while awaiting the assistant's reply). */
loading?: boolean;
/** Starter prompts shown above the input when the thread is empty. Clicking one follows `suggestionMode`. Set as a JS property. */
suggestions?: string[];
/** What clicking a suggestion does: `'submit'` (default) sends it immediately as if typed and submitted; `'fill'` just places it in the input. */
suggestionMode?: "submit" | "fill";
/** Keep suggestions visible after the conversation starts. By default suggestions are conversation starters and hide once `messages` is non-empty; set this to keep them always shown. Default false. */
persistSuggestions?: boolean;
/** Body/prose font scale for rendered markdown (`'xs' | 'sm' | 'base' | 'lg'`). Defaults to `'sm'`. */
proseSize?: "xs" | "sm" | "base" | "lg";
/** Shiki theme name for syntax-highlighted code blocks (e.g. `'github-dark-dimmed'`). */
codeTheme?: string;
/** Enable Shiki syntax highlighting in code blocks. Turn off to render plain `<pre>` blocks (lighter, no highlighter load). Default true. */
codeHighlight?: boolean;
/** Optional header title shown on the left of the header. */
chatTitle?: string;
/** Optional model list. When set (>1 model) a ModelSwitcher is shown in the header and a `kc-model-change` event fires on selection. */
models?: { id: string; name: string; provider?: string; description?: string; group?: string }[];
/** The currently selected model id (pairs with `models`). */
currentModel?: string;
/** Optional context-window token usage. When set, a Context token meter is shown in the header. */
context?: { usedTokens: number; maxTokens: number; inputTokens?: number; outputTokens?: number; estimatedCost?: number };
/** Show the scroll-to-bottom button inside the scroll area. Default true. */
scrollButton?: boolean;
/** Whether the host has `slot="header-start"` content (left of the title) — set by the `<kc-chat>` facade so a custom control forces the header open. */
headerStart?: boolean;
/** Whether the host has `slot="header-end"` content (right of the controls). */
headerEnd?: boolean;
/** Show a Search (Globe) button in the input toolbar; fires a `search` event. */
search?: boolean;
/** Show a Voice (Mic) button in the input toolbar; fires a `voice` event. */
voice?: boolean;
/** Slash commands — when set, typing `/` in the input opens the command palette and fires `kc-slash-select`. Set as a JS property. */
slashCommands?: { id: string; label: string; description?: string; category?: string }[];
/** Command ids to highlight as active in the palette. */
slashActiveIds?: string[];
/** Single-line palette rows. */
slashCompact?: boolean;
/** Whether each message's action bar is always visible (`'always'`, default) or only revealed on hover of that message row (`'hover'`). */
actionsReveal?: "always" | "hover";
}
export interface KcCheckpointElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Optional text beside the icon. */
label?: string;
/** Tooltip on hover. */
tooltip?: string;
/** Visual button style. */
variant?: "ghost" | "default" | "outline";
/** Button size (use an `icon*` size for an icon-only checkpoint). */
size?: "sm" | "lg" | "md" | "icon" | "icon-sm";
}
export interface KcChoiceElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The choice definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { prompt, options:[…], allowOther?, submitLabel? }`. Import `ChoiceCardData` from `@kitn.ai/chat` for the full shape. */
data?: Record<string, unknown>;
/** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
cardId?: string;
/** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
heading?: string;
/** Set when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'action', action:'…' }`. */
resolution?: Record<string, unknown>;
}
export interface KcCodeBlockElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The source code to render. */
code: string;
/** Language grammar (e.g. `js`, `python`). Defaults to `tsx`. */
language?: string;
/** Shiki theme name. */
codeTheme?: string;
/** Disable syntax highlighting (renders plain text, no Shiki). */
codeHighlight?: boolean;
/** Code text sizing. */
proseSize?: "xs" | "sm" | "base" | "lg";
}
export interface KcConfirmElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The confirm definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { body, tone, actions:[…] }`. Import `ConfirmCardData` from `@kitn.ai/chat` for the full shape. */
data?: Record<string, unknown>;
/** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
cardId?: string;
/** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
heading?: string;
/** Focus the default action on mount (off by default — no focus-stealing). Attribute: `autofocus`. */
autofocus?: boolean;
/** Set when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'action', action:'…' }`. */
resolution?: Record<string, unknown>;
}
export interface KcContextElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Token-usage data. Set as a JS property. */
context?: { usedTokens: number; maxTokens: number; inputTokens?: number; outputTokens?: number; reasoningTokens?: number; cacheTokens?: number; estimatedCost?: number };
/** Fraction (0–1) above which the meter turns yellow. Defaults to `0.7` (70%). */
warnThreshold?: number;
/** Fraction (0–1) above which the meter turns red. Defaults to `0.9` (90%). */
dangerThreshold?: number;
}
export interface KcConversationsElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Pre-bucketed conversation groups (e.g. "Today", "Yesterday"), each with its own conversations. Use this when you want to control the grouping/headers yourself; otherwise pass a flat `conversations` array. Set as a JS property. */
groups: { id: string; userId?: undefined | string; teamId?: undefined | string; name: string; sortOrder: number; createdAt: string }[];
/** A flat list of conversation summaries; the component buckets them by recency for you. Ignored when `groups` is provided. Set as a JS property. */
conversations: { id: string; title: string; groupId?: undefined | string; scope: { type: "document" | "collection"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | "transcript" | "markdown"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string }[];
/** The id of the currently-open conversation, highlighted in the list. */
activeId?: string;
}
export interface KcEmbedElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Stable card id correlating every emitted event. Set as an attribute or property. */
cardId?: string;
/** The embed payload (provider + id/url + options). Set as a JS **property** (object). */
data?: { provider: "youtube" | "vimeo" | "generic"; id?: string; url?: string; title?: string; poster?: string; start?: number; aspectRatio?: "16:9" | "4:3" | "1:1" | "9:16" };
}
export interface KcEmptyElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Title text. Attribute: `empty-title` (`title` is a global HTML attribute). */
emptyTitle?: string;
/** Description text. */
description?: string;
}
export interface KcFeedbackBarElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The banner label (e.g. "Was this helpful?"). Attribute: `bar-title` (`title` is avoided — it's a global HTML attribute). */
barTitle?: string;
/** When set, a not-helpful vote opens an optional detail form before the thank-you confirmation. Attribute: `collect-detail`. */
collectDetail?: boolean;
/** Optional category chips for the detail form. Set as a JS property (array). */
categories?: string[];
/** Heading for the detail form. Attribute: `detail-title`. */
detailTitle?: string;
/** Placeholder for the detail comment box. Attribute: `detail-placeholder`. */
detailPlaceholder?: string;
/** Submit button label in the detail form. Attribute: `submit-label`. */
submitLabel?: string;
/** Confirmation copy shown after a vote/submit. Attribute: `thanks-message`. */
thanksMessage?: string;
}
export interface KcFileTreeElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The files to render. Set as a JS property (array of `{ path, url?, code?, language?, type? }`). */
files: { path: string; url?: undefined | string; code?: undefined | string; language?: undefined | string; type?: undefined | "html" | "pdf" | "image" | "other" }[];
/** Selected file path — highlighted in the tree. */
activeFile?: string;
/** Folder paths expanded initially. Omit to start with all folders open. */
defaultExpanded?: string[];
}
export interface KcFileUploadElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Allow selecting multiple files (default true). */
multiple?: boolean;
/** `accept` attribute for the file picker (e.g. `image/*`). */
accept?: string;
/** Disable the dropzone — no clicking, no drag-and-drop. */
disabled?: boolean;
/** Default dropzone label (overridable via the default slot). */
label?: string;
}
export interface KcFormElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The form definition — a JSON Schema (`type:'object'`) + `x-kc-*` UI hints (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { type:'object', properties:{…} }`. Import the `FormDefinition` type from `@kitn.ai/chat` for the full shape (it is self-referential, so the element types it loosely). */
data?: Record<string, unknown>;
/** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
cardId?: string;
/** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
heading?: string;
/** Set when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'submit', data:{…} }`. */
resolution?: Record<string, unknown>;
}
export interface KcImageElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Base64-encoded image data (pair with `media-type`). */
base64?: string;
/** Raw image bytes (set as a JS property). */
bytes?: Uint8Array;
/** Alt text. */
alt?: string;
/** MIME type (default `image/png`). */
mediaType?: string;
}
export interface KcLinkPreviewElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Stable card id correlating every emitted event. Set as an attribute or property. */
cardId?: string;
/** The link payload (OG metadata). Set as a JS **property** (object). */
data?: { url: string; title?: string; description?: string; image?: string; imageAlt?: string; favicon?: string; domain?: string; siteName?: string };
}
export interface KcLoaderElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The animation style: `'circular' | 'classic' | 'pulse' | 'pulse-dot' | 'dots' | 'typing' | 'wave' | 'bars' | 'terminal' | 'text-blink' | 'text-shimmer' | 'loading-dots'`. Defaults to `'circular'`. */
variant?: "circular" | "classic" | "pulse" | "pulse-dot" | "dots" | "typing" | "wave" | "bars" | "terminal" | "text-blink" | "text-shimmer" | "loading-dots";
/** Loader size: `'sm' | 'md' | 'lg'`. Defaults to `'md'`. */
size?: "sm" | "lg" | "md";
/** Label for the text-based variants. */
text?: string;
}
export interface KcMarkdownElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The markdown source to render. */
content: string;
/** Text/markdown sizing. */
proseSize?: "xs" | "sm" | "base" | "lg";
/** Shiki theme for fenced code blocks. */
codeTheme?: string;
/** Disable syntax highlighting (no Shiki loads). */
codeHighlight?: boolean;
}
export interface KcMessageElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The full message object. Set as a JS property. */
message?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string } };
/** Convenience for simple cases when not passing a `message` object. */
role?: "user" | "assistant";
/** Convenience content (used when `message` is not set). */
content?: string;
/** Force markdown on/off. Defaults to on for assistant, off for user. */
markdown?: boolean;
/** Text/markdown sizing for the message body. */
proseSize?: "xs" | "sm" | "base" | "lg";
/** Shiki theme name used for fenced code blocks in the content. */
codeTheme?: string;
/** Disable syntax highlighting for code blocks (no Shiki loads). */
codeHighlight?: boolean;
/** Whether the action bar is always visible (`'always'`, default) or only revealed on hover of the message row (`'hover'`). */
actionsReveal?: "always" | "hover";
/** Convenience avatar image URL (used when `message.avatar` is not set). */
avatarSrc?: string;
/** Convenience avatar fallback text (used when `message.avatar` is not set). */
avatarFallback?: string;
}
export interface KcModelSwitcherElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The selectable models. Set as a JS property (array). */
models: { id: string; name: string; provider?: undefined | string; description?: undefined | string; group?: undefined | string }[];
/** The currently-selected model id. Defaults to the first model. */
currentModel?: string;
}
export interface KcPopoverElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Floating placement relative to the trigger (floating-ui placement). */
placement?: "top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "right-start" | "right-end" | "bottom-start" | "bottom-end" | "left-start" | "left-end";
/** Gap in px between the trigger and the panel. */
gutter?: number;
/** Controlled open state. Set as a JS property (`el.open = true`) to drive the popover from your app; omit for the default click-to-toggle behaviour. */
open?: boolean;
}
export interface KcPromptInputElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Controlled value of the input. When set, the host owns the text and must update it on `kc-value-change`; leave unset for uncontrolled behavior. */
value?: string;
/** Placeholder text shown in the empty input. */
placeholder?: string;
/** Disable the input and submit button entirely (non-interactive). */
disabled?: boolean;
/** Show the loading/streaming state and block submit (use while awaiting a reply). */
loading?: boolean;
/** Starter prompts shown above the input. Clicking one follows `suggestionMode`. Set as a JS property. */
suggestions?: string[];
/** What clicking a suggestion does: `'submit'` (default) sends it immediately as if typed and submitted; `'fill'` just places it in the input. */
suggestionMode?: "submit" | "fill";
/** Slash commands — when set, typing `/` opens the command palette. Set as a JS property. */
slashCommands?: { id: string; label: string; description?: string; category?: string }[];
/** Command ids to highlight as active. */
slashActiveIds?: string[];
/** Single-line palette rows. */
slashCompact?: boolean;
/** Show a Search (Globe) button in the left toolbar; clicking it fires a `search` event. */
search?: boolean;
/** Show a Voice (Mic) button in the left toolbar; clicking it fires a `voice` event. */
voice?: boolean;
/** When set and `loading` is true, the send button is replaced by a Stop button (square icon, "Stop" aria-label). Clicking it fires `kc-stop`. */
stoppable?: boolean;
/** Attachments to seed the input with (so a consumer can pre-populate staged files without an upload). Set as a JS property; the element then manages its own attachment state from there (add via the paperclip, remove per chip). */
attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[];
}
export interface KcReasoningElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The reasoning text to display. */
text: string;
/** Trigger label. */
label?: string;
/** Controlled open state — set as a property (`el.open = true`). Omit for uncontrolled (the trigger toggles it). */
open?: boolean;
/** While true, auto-expands (and re-collapses when it flips false). */
streaming?: boolean;
/** Render `text` as markdown. */
markdown?: boolean;
}
export interface KcRemoteElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The remote card URL. Attribute: `src`. */
src?: string;
/** Exact provider origin (https: or http://localhost for dev). Attribute: `provider-origin`. */
providerOrigin?: string;
/** The card envelope to render. JS property only. */
envelope?: Record<string, unknown>;
/** Optional routing policy. JS property only. */
policy?: Record<string, unknown>;
}
export interface KcResizableElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Layout axis: `horizontal` (row, default) or `vertical` (column). */
orientation?: "horizontal" | "vertical";
/** Which item index is maximized (null = none). Declarative source of truth. */
maximizedIndex?: null | number;
}
export interface KcResizableItemElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Initial main-axis size: `"280px"` (fixed) or `"25%"`/`25` (percent). Omitted → flexible. */
size?: string;
/** Minimum size during resize (px or %). */
min?: string;
/** Maximum size during resize (px or %). */
max?: string;
/** Fix this panel's size; adjacent dividers become non-draggable. */
locked?: boolean;
/** Hide this panel; its divider is dropped and the rest reflow. */
hidden?: boolean;
}
export interface KcResponseStreamElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Text to stream. A string, or an `AsyncIterable<string>` (set as a JS property — async iterables can't be HTML attributes). */
text?: string | AsyncIterable<string>;
/** Reveal animation. */
mode?: "typewriter" | "fade";
/** Characters/segments per tick. */
speed?: number;
/** Element tag to render as. */
as?: string;
}
export interface KcScopePickerElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Authors to offer as scope filters. Set as a JS property. */
availableAuthors: string[];
/** Tags to offer as scope filters. Set as a JS property. */
availableTags: string[];
/** The label shown on the trigger for the active scope. */
currentLabel?: string;
}
export interface KcScrollButtonElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** CSS id of the scroll container to control. When omitted the element walks up the DOM (outside its own shadow root) to find the nearest scrollable ancestor. Mirrors the `for` convention of `<label for="...">`. */
for?: string;
/** Button visual variant: `'outline' | 'ghost' | 'default'`. Defaults to `'outline'`. */
variant?: "ghost" | "default" | "outline";
/** Button size token. Defaults to `'icon'` (square). */
size?: "sm" | "lg" | "md" | "icon" | "icon-sm";
}
export interface KcSkillsElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The active skills to badge. Set as a JS property. */
skills: { id: string; name: string }[];
}
export interface KcSourceElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The URL this citation links to (the domain also seeds the default label/favicon). */
href?: string;
/** Trigger label (defaults to the domain). */
label?: string;
/** Hover-card headline. Attribute: `headline` (`title` is avoided — it's a global HTML attribute that reflects in a CE constructor and breaks it). */
headline?: string;
/** Hover-card body text describing the source. */
description?: string;
/** Show the source's favicon next to the trigger label. */
showFavicon?: boolean;
}
export interface KcSourcesElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The sources to render. Set as a JS property. */
sources: { href: string; title?: undefined | string; description?: undefined | string; label?: undefined | string; showFavicon?: undefined | boolean }[];
/** Show favicons on all items (per-item `showFavicon` overrides). */
showFavicon?: boolean;
/** When true, each citation chip is labelled with its 1-based index in the merged (prop + declarative-children) list (`[1]`, `[2]`, …) instead of the per-item `label` or domain fallback. HTML attribute: `numbered` (boolean — bare attribute or `numbered="true"`). JS property: `el.numbered = true`. */
numbered?: boolean;
}
export interface KcSuggestionsElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The suggestions. Strings, or `{ label, value }` when the displayed text and the emitted value differ. Set as a JS property. */
suggestions: (string | { label: string; value?: undefined | string })[];
/** Chip style: `'outline'` (default), `'ghost'`, or `'default'` (filled). */
variant?: "ghost" | "default" | "outline";
/** Size preset for each chip. Defaults to the pill default (`'lg'`); pass `'sm'` for smaller pills (or `'md'`). */
size?: "sm" | "lg" | "md" | "icon" | "icon-sm";
/** Full-width left-aligned rows instead of pills. */
block?: boolean;
/** Substring to highlight within each suggestion. */
highlight?: string;
}
export interface KcSwitchElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Initial checked state. Bare attribute (`<kc-switch checked>`) turns it on. */
checked?: boolean;
/** Disable interaction. */
disabled?: boolean;
/** Accessible label. */
label?: string;
}
export interface KcTasksElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The tasks definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { tasks:[…], selectAll, confirmLabel, … }`. Import `TasksCardData` from `@kitn.ai/chat` for the full shape. */
data?: Record<string, unknown>;
/** Stable card id correlating every emitted CardEvent. Attribute: `card-id`. */
cardId?: string;
/** Heading rendered in the card chrome (= CardEnvelope.title). Attribute: `heading`. */
heading?: string;
/** Set when the user resolved this card; renders the read-only view. Property: `el.resolution = { kind:'submit', data:{ selected:[…] } }`. */
resolution?: Record<string, unknown>;
}
export interface KcTextShimmerElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The text to shimmer. */
text?: string;
/** Element tag to render as (default `span`). */
as?: string;
/** Animation duration in seconds. */
duration?: number;
/** Gradient spread (5–45). */
spread?: number;
}
export interface KcThinkingBarElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The shimmering label, e.g. "Thinking…". */
text?: string;
/** When true, show a "stop" affordance that fires a `stop` event. */
stoppable?: boolean;
/** Label for the stop affordance. */
stopLabel?: string;
}
export interface KcToolElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** The tool-call to display. Set as a JS property. */
tool?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string };
/** Start expanded. */
open?: boolean;
}
export interface KcVoiceInputElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Transcriber the host supplies — records audio, returns the text. This is a **function-valued property** (`el.transcribe = async blob => '...'`) because a value-returning callback can't be modelled as a fire-and-forget event. */
transcribe?: (audio: Blob) => Promise<string>;
/** Disable the mic button (non-interactive). */
disabled?: boolean;
}
export interface KcWorkspaceElement extends HTMLElement {
/** Color mode (`auto` follows prefers-color-scheme). */
theme?: 'light' | 'dark' | 'auto';
/** Pre-bucketed conversation groups for the sidebar. Set as a JS property. */
groups: { id: string; userId?: undefined | string; teamId?: undefined | string; name: string; sortOrder: number; createdAt: string }[];
/** Flat conversation list (auto-bucketed if `groups` is empty). Set as a JS property. */
conversations: { id: string; title: string; groupId?: undefined | string; scope: { type: "document" | "collection"; documentId?: undefined | string; filters?: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | "transcript" | "markdown"; dateRange?: undefined | { from: string; to: string } } }; messageCount: number; lastMessageAt: string; updatedAt: string }[];
/** Id of the open conversation, highlighted in the sidebar. */
activeId?: string;
/** The active conversation's message thread, newest last. Set as a JS property. */
messages: { id: string; role: "user" | "assistant"; content: string; reasoning?: undefined | { text: string; label?: undefined | string }; tools?: undefined | { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: undefined | Record<string, unknown>; output?: undefined | Record<string, unknown>; toolCallId?: undefined | string; errorText?: undefined | string }[]; attachments?: undefined | { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[]; actions?: undefined | ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: undefined | string; tooltip?: undefined | string })[]; avatar?: undefined | { src?: undefined | string; fallback?: undefined | string; alt?: undefined | string } }[];
value?: string;
placeholder?: string;
loading?: boolean;
suggestions?: string[];
suggestionMode?: "submit" | "fill";
proseSize?: "xs" | "sm" | "base" | "lg";
codeTheme?: string;
codeHighlight?: boolean;
chatTitle?: string;
models?: { id: string; name: string; provider?: string; description?: string; group?: string }[];
currentModel?: string;
context?: { usedTokens: number; maxTokens: number; inputTokens?: number; outputTokens?: number; estimatedCost?: number };
scrollButton?: boolean;
search?: boolean;
voice?: boolean;
slashCommands?: { id: string; label: string; description?: string; category?: string }[];
slashActiveIds?: string[];
slashCompact?: boolean;
/** Sidebar default width as a percent of the workspace (default 22). */
sidebarWidth?: number;
/** Sidebar min width in px (default 200). */
sidebarMinWidth?: number;
/** Sidebar max width in px (default 420). */
sidebarMaxWidth?: number;
/** Controlled collapsed state. Set this as a JS property (`el.sidebarCollapsed = true`) to drive the sidebar from your app, updating it in response to the `kc-sidebar-toggle` event. Omit for uncontrolled (the element manages it). */
sidebarCollapsed?: boolean;
/** Initial collapsed state when uncontrolled (default false). Use the `default-sidebar-collapsed` attribute to start collapsed in plain HTML. */
defaultSidebarCollapsed?: boolean;
}
declare global {
interface HTMLElementTagNameMap {
'kc-artifact': KcArtifactElement;
'kc-attachments': KcAttachmentsElement;
'kc-card': KcCardElement;
'kc-cards': KcCardsElement;
'kc-chain-of-thought': KcChainOfThoughtElement;
'kc-chat': KcChatElement;
'kc-checkpoint': KcCheckpointElement;
'kc-choice': KcChoiceElement;
'kc-code-block': KcCodeBlockElement;
'kc-confirm': KcConfirmElement;
'kc-context': KcContextElement;
'kc-conversations': KcConversationsElement;
'kc-embed': KcEmbedElement;
'kc-empty': KcEmptyElement;
'kc-feedback-bar': KcFeedbackBarElement;
'kc-file-tree': KcFileTreeElement;
'kc-file-upload': KcFileUploadElement;
'kc-form': KcFormElement;
'kc-image': KcImageElement;
'kc-link-preview': KcLinkPreviewElement;
'kc-loader': KcLoaderElement;
'kc-markdown': KcMarkdownElement;
'kc-message': KcMessageElement;
'kc-model-switcher': KcModelSwitcherElement;
'kc-popover': KcPopoverElement;
'kc-prompt-input': KcPromptInputElement;
'kc-reasoning': KcReasoningElement;
'kc-remote': KcRemoteElement;
'kc-resizable': KcResizableElement;
'kc-resizable-item': KcResizableItemElement;
'kc-response-stream': KcResponseStreamElement;
'kc-scope-picker': KcScopePickerElement;
'kc-scroll-button': KcScrollButtonElement;
'kc-skills': KcSkillsElement;
'kc-source': KcSourceElement;
'kc-sources': KcSourcesElement;
'kc-suggestions': KcSuggestionsElement;
'kc-switch': KcSwitchElement;
'kc-tasks': KcTasksElement;
'kc-text-shimmer': KcTextShimmerElement;
'kc-thinking-bar': KcThinkingBarElement;
'kc-tool': KcToolElement;
'kc-voice-input': KcVoiceInputElement;
'kc-workspace': KcWorkspaceElement;
}
}