'use client'; // AUTO-GENERATED by scripts/gen-element-api.mjs — do not edit by hand. // Typed React wrappers for every kitn custom element. Usage: // import { Message } from '@kitn.ai/ui/react'; // …} /> // Each wrapper lazy-registers ITS element on first client mount (a dynamic import // of '@kitn.ai/ui/elements/'), so a consumer ships only the elements they use // — not the register-all bundle. SSR-safe: registration fires only in a client effect. // For eager all-registration call registerAll() or import '@kitn.ai/ui/elements'. import { createWebComponent, registerAll, type WebComponentProps } from './runtime'; export { registerAll }; export { useKaiChat } from './use-kai-chat'; export type { UseKaiChatOptions, KaiChatController, ChatMessage } from './use-kai-chat'; export interface AgentCardProps extends WebComponentProps { /** The agent's name — the primary label. Attribute: `name`. */ name?: string; /** Selected / focused state: highlighted border + surface. Attribute: `active`. */ active?: boolean; /** Raise a prominent "Needs you" pill plus a glowing amber edge — the attention-routing signal that pulls focus to this agent. Attribute: `needs-attention`. */ needsAttention?: boolean; /** Run status — a JS PROPERTY (object), not an attribute. Shape: `{ tone, label?, pulse? }`, where `tone` is one of `working` | `idle` | `done` | `error` | `blocked` (maps to the kit's tool hues), `label` is an optional short string beside the dot, and `pulse` animates the dot. Set it with `el.status = { tone: 'working', label: 'Working', pulse: true }`. */ status?: { tone: "working" | "idle" | "done" | "error" | "blocked"; label?: string; pulse?: boolean }; /** The card was activated — clicked, or Enter / Space while focused. Promote this agent back to focus. */ onActivate?: (event: CustomEvent) => void; /** The trailing "..." kebab was clicked. The consumer opens its own menu; the card only surfaces the affordance (the click does not also activate the card). */ onMenu?: (event: CustomEvent) => void; } export const AgentCard = /*#__PURE__*/ createWebComponent( 'kai-agent-card', ["theme","name","active","needsAttention","status"], { onActivate: 'kai-activate', onMenu: 'kai-menu' }, () => import('@kitn.ai/ui/elements/agent-card'), ); export interface ArtifactProps extends WebComponentProps { /** 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"; additions?: undefined | number; deletions?: undefined | number; status?: undefined | "added" | "modified" | "deleted" | "renamed" | "untracked" }[]; /** Controlled active tab: `preview` or `code`. When set, the artifact follows it (re-asserted on change). Leave unset for an uncontrolled tab (see `defaultTab`). */ tab?: "preview" | "code"; /** Uncontrolled INITIAL tab (used only when `tab` is unset). Default `preview`. Seeds the starting tab; the user can then switch freely without the consumer re-asserting a controlled `tab`. */ defaultTab?: "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; /** Friendly address shown in the path field instead of the real current url (read-only, non-navigable). Use when the framed url is not consumer-facing (e.g. a `data:` blob) so a clean address shows instead of leaking it. Scalar string: set as the `display-url` attribute or the `displayUrl` property. */ displayUrl?: string; /** Fired when a file is selected. `detail.path`. */ onFileSelect?: (event: CustomEvent<{ path: string }>) => void; /** Artifact's own maximize button toggled (consumer-observable; non-bubbling). */ onMaximizeChange?: (event: CustomEvent<{ maximized: boolean }>) => void; /** Fired when the preview navigates. `detail.url` = the new location. */ onNavigate?: (event: CustomEvent<{ url: string }>) => void; /** Fired when the Preview|Code tab changes. `detail.tab`. */ onTabChange?: (event: CustomEvent<{ tab: "preview" | "code" }>) => void; } export const Artifact = /*#__PURE__*/ createWebComponent( 'kai-artifact', ["theme","src","files","tab","defaultTab","activeFile","sandbox","iframeTitle","maximized","expandable","openInTab","noNav","noReload","noHome","noPathField","noTabs","standalone","readonlyPath","displayUrl"], { onFileSelect: 'kai-file-select', onMaximizeChange: 'kai-maximize-change', onNavigate: 'kai-navigate', onTabChange: 'kai-tab-change' }, () => import('@kitn.ai/ui/elements/artifact'), ); export interface AttachmentsProps extends WebComponentProps { /** 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 `kai-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; /** A remove button was clicked. */ onRemove?: (event: CustomEvent<{ id: string }>) => void; } export const Attachments = /*#__PURE__*/ createWebComponent( 'kai-attachments', ["theme","items","variant","hoverCard","removable","showMediaType","emptyText"], { onRemove: 'kai-remove' }, () => import('@kitn.ai/ui/elements/attachments'), ); export interface AvatarProps extends WebComponentProps { /** Image URL/data-URI. When absent, the `fallback` initials show instead. */ src?: string; /** Alt text for the image. Defaults to `fallback`. */ alt?: string; /** Short text shown when there's no image — usually initials (e.g. "JD", "AI"). */ fallback?: string; /** Size token: `sm` | `md` (default) | `lg`. */ size?: "sm" | "md" | "lg"; } export const Avatar = /*#__PURE__*/ createWebComponent( 'kai-avatar', ["theme","src","alt","fallback","size"], { }, () => import('@kitn.ai/ui/elements/avatar'), ); export interface BadgeProps extends WebComponentProps { /** `default` (muted pill) · `count` (compact number badge) · `citation` (filled primary, for inline citation markers). Defaults to `default`. */ variant?: "default" | "count" | "citation"; } export const Badge = /*#__PURE__*/ createWebComponent( 'kai-badge', ["theme","variant"], { }, () => import('@kitn.ai/ui/elements/badge'), ); export interface ButtonProps extends WebComponentProps { /** Visual style. `default` (filled), `subtle` (muted text, hover tint — the toolbar icon look), `ghost` (transparent, hover fill), `outline`, or `destructive`. Defaults to `default`. */ variant?: "default" | "subtle" | "ghost" | "outline" | "destructive"; /** Size token. `icon` / `icon-sm` are square (for icon-only buttons); `sm` / `md` / `lg` size text buttons. Defaults to `md`. */ size?: "sm" | "md" | "lg" | "icon" | "icon-sm"; /** Leading icon: a named icon (e.g. `"mic"`, `"plus"`), an image URL/data-URI, or plain text. Renders before any slotted label. */ icon?: string; /** Trailing icon, after the label (e.g. `"chevron-down"` for a menu affordance). */ iconTrailing?: string; /** Accessible name. REQUIRED for icon-only buttons (no visible text); ignored when you slot visible text, which already names the button. */ label?: string; /** Disable the button (non-interactive, dimmed). */ disabled?: boolean; /** Stretch the button to the full width of its container (a block button) — e.g. a card CTA or a stacked action. Attribute: `full`. */ full?: boolean; /** Justify the button's content: `start`, `center` (default), or `end`. Combine with `full` for a full-width, left-aligned button. */ align?: "start" | "center" | "end"; /** Native button `type`. Defaults to `button` (so it never submits a form). */ type?: "button" | "submit" | "reset"; /** The button was activated (pointer or keyboard). Carries no detail. The native `click` also bubbles (composed) for consumers who prefer it. */ onClick?: (event: CustomEvent) => void; } export const Button = /*#__PURE__*/ createWebComponent( 'kai-button', ["theme","variant","size","icon","iconTrailing","label","disabled","full","align","type"], { onClick: 'kai-click' }, () => import('@kitn.ai/ui/elements/button'), ); export interface CardProps extends WebComponentProps { /** Surface treatment: `outlined` (default) | `filled` | `plain` | `accent`. Attribute: `appearance`. */ appearance?: "outlined" | "filled" | "plain" | "accent"; /** `vertical` (default, media on top) | `horizontal` (media at the start) | `responsive` (horizontal when the card's container is wide enough, else vertical — a container query on the card's own width). Attribute: `orientation`. */ orientation?: "vertical" | "horizontal" | "responsive"; /** The card width below which a `responsive` card collapses to vertical and the footer actions stack. A CSS length; default `28rem`. Attribute: `collapse`. */ collapse?: string; /** Tighter spacing for dense lists. Attribute: `dense`. */ dense?: boolean; /** Show a close (×) that hides the card and emits `kai-dismiss`. Attribute: `dismissible`. Off by default. */ dismissible?: boolean; /** Render the whole card as a link. Attribute: `href`. Wins over `clickable`. */ href?: string; /** `target` for the `href` anchor. Attribute: `target`. */ target?: string; /** `rel` for the `href` anchor. Attribute: `rel`. */ rel?: string; /** Make the whole card a button (`role="button"`, Enter/Space, hover affordance) that emits `kai-card-click`. Attribute: `clickable`. Ignored when `href` is set. */ clickable?: boolean; /** A `clickable`/`href` card was activated (click, or Enter/Space). */ onCardClick?: (event: CustomEvent) => void; /** The card was dismissed via its × (it also hides itself). */ onDismiss?: (event: CustomEvent) => void; } export const Card = /*#__PURE__*/ createWebComponent( 'kai-card', ["theme","appearance","orientation","collapse","dense","dismissible","href","target","rel","clickable"], { onCardClick: 'kai-card-click', onDismiss: 'kai-dismiss' }, () => import('@kitn.ai/ui/elements/card'), ); export interface CardsProps extends WebComponentProps { /** 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 } | { kind: "dismissed"; at?: string } | { kind: "expired"; reason?: string; 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; /** 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; onReopen?: (cardId: string) => void; onError?: (cardId: string, message: string) => void; maxSendPromptMode?: "compose" | "send" }; /** A child card transitioned to a resolved/deferred state (an action was chosen, a form/tasks submission landed, or it was dismissed) — re-emitted off the host as a non-bubbling convenience event so a consumer can observe resolution centrally without diffing the cards array. `detail` = `{ cardId, resolution }`. (A `reopen` un-resolves a card and has no `CardResolution`, so it does NOT fire this — observe reopen via the underlying bubbling `kai-card` event.) */ onCardResolved?: (event: CustomEvent<{ cardId: string; resolution: { kind: "action"; action: string; payload?: unknown; at?: undefined | string } | { kind: "submit"; data: unknown; at?: undefined | string } | { kind: "dismissed"; at?: undefined | string } | { kind: "expired"; reason?: undefined | string; at?: undefined | string } }>) => void; } export const Cards = /*#__PURE__*/ createWebComponent( 'kai-cards', ["theme","cards","types","policy"], { onCardResolved: 'kai-card-resolved' }, () => import('@kitn.ai/ui/elements/cards'), ); export interface ChainOfThoughtProps extends WebComponentProps { /** The reasoning steps. Set as a JS property. Compound sub-parts collapse to this one data model (Route 1). Each `{ label, content?, id? }`. */ steps: { label: string; content?: undefined | string; id?: undefined | string }[]; /** Open mode: `'multiple'` (default — any number of steps open at once) or `'single'` (at most one open; opening a step closes the others). */ type?: "single" | "multiple"; /** Controlled open step key(s). When set, it WINS over user interaction (the consumer owns the open set). String in `single` mode, string[] in `multiple` mode. Set as a JS property. */ value?: string | string[]; /** Uncontrolled INITIAL open step key(s) — seeds which steps render expanded. Ignored once `value` is provided. Set as a JS property. */ defaultValue?: string | string[]; /** The open set changed — by user click OR an expand()/collapse()/toggle() call. `value` is a string in `single` mode, a string[] in `multiple` mode. (Maps Radix Accordion's onValueChange.) */ onValueChange?: (event: CustomEvent<{ value: string | string[] }>) => void; } export const ChainOfThought = /*#__PURE__*/ createWebComponent( 'kai-chain-of-thought', ["theme","steps","type","value","defaultValue"], { onValueChange: 'kai-value-change' }, () => import('@kitn.ai/ui/elements/chain-of-thought'), ); export interface ChatProps extends WebComponentProps { /** 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; output?: undefined | Record; 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 }; feedback?: undefined | "like" | "dislike" }[]; /** Value of the input. A **string** is controlled (the host owns the text and updates it on `kai-value-change`). A **ComposerDoc** is a one-time seed that pre-populates pills; the user then edits freely. Leave unset for uncontrolled. */ value?: string | ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: string; promptText?: string; data?: Record } })[]; /** 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?: "sm" | "lg" | "xs" | "base"; /** 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 `
` 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 `kai-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 `` 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;
  /** REPLACE — full custom header in place of the built-in title/model/context bar. */
  headerFull?: boolean;
  /** INJECT — left sidebar column (e.g. a conversation list / your own nav). */
  sidebar?: boolean;
  /** REPLACE — custom zero-state rendered in the message area while the thread is empty (replaces the empty message list only; the composer and its suggestions still render). */
  empty?: boolean;
  /** REPLACE — full custom composer in place of the built-in prompt input. The projected content wires its own submit (the data-flow boundary). */
  composer?: boolean;
  /** INJECT — accessory row just above the composer (e.g. extra actions). */
  composerActions?: boolean;
  /** INJECT — footer row below the composer (disclaimers, token meter, …). */
  footer?: 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;
  /** Rich entity triggers — each `{ char, kind, items }` opens a caret-anchored menu that inserts an atomic pill (`/` skills, `@` agents/plugins). Set as a JS property; forwarded to the input. */
  triggers?: { char: string; kind: string; items?: { id: string; label: string; icon?: string; description?: string; group?: string; kind?: string; promptText?: string; data?: Record }[] }[];
  /** Default icon per entity kind (kind → image src) for pills/menu items. */
  kindIcons?: Record;
  /** Whether each message's action bar is always visible (`'always'`, default) or only revealed on hover of that message row (`'hover'`). */
  actionsReveal?: "always" | "hover";
  /** The staged attachments changed (file added or removed). Carries the full current list so a consumer can react in real time. */
  onAttachmentsChange?: (event: CustomEvent<{ attachments: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }>) => void;
  /** An action button on a message was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
  onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
  /** The header model switcher changed. */
  onModelChange?: (event: CustomEvent<{ modelId: string }>) => void;
  /** The Search button was clicked. */
  onSearch?: (event: CustomEvent>) => void;
  /** User submitted a message. */
  onSubmit?: (event: CustomEvent<{ value: string; attachments: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }>) => void;
  /** A suggestion chip was clicked (only in `suggestion-mode="fill"`). */
  onSuggestionClick?: (event: CustomEvent<{ value: string }>) => void;
  /** Fired on every input change. */
  onValueChange?: (event: CustomEvent<{ value: string }>) => void;
  /** The Mic / voice button was clicked. */
  onVoice?: (event: CustomEvent>) => void;
}

export const Chat = /*#__PURE__*/ createWebComponent(
  'kai-chat',
  ["theme","messages","value","placeholder","loading","suggestions","suggestionMode","persistSuggestions","proseSize","codeTheme","codeHighlight","chatTitle","models","currentModel","context","scrollButton","headerStart","headerEnd","headerFull","sidebar","empty","composer","composerActions","footer","search","voice","triggers","kindIcons","actionsReveal"],
  { onAttachmentsChange: 'kai-attachments-change', onMessageAction: 'kai-message-action', onModelChange: 'kai-model-change', onSearch: 'kai-search', onSubmit: 'kai-submit', onSuggestionClick: 'kai-suggestion-click', onValueChange: 'kai-value-change', onVoice: 'kai-voice' },
  () => import('@kitn.ai/ui/elements/chat'),
);

export interface CheckpointProps extends WebComponentProps {
  /** Optional text beside the icon. */
  label?: string;
  /** Tooltip on hover. */
  tooltip?: string;
  /** Visual button style. */
  variant?: "default" | "ghost" | "outline";
  /** Button size (use an `icon*` size for an icon-only checkpoint). */
  size?: "sm" | "md" | "lg" | "icon" | "icon-sm";
  /** The checkpoint was clicked. */
  onSelect?: (event: CustomEvent) => void;
}

export const Checkpoint = /*#__PURE__*/ createWebComponent(
  'kai-checkpoint',
  ["theme","label","tooltip","variant","size"],
  { onSelect: 'kai-select' },
  () => import('@kitn.ai/ui/elements/checkpoint'),
);

export interface ChoiceProps extends WebComponentProps {
  /** The choice definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { prompt, options:[…], allowOther?, submitLabel? }`. Import `ChoiceCardData` from `@kitn.ai/ui` for the full shape. */
  data?: Record;
  /** 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;
  /** Controlled selection — the selected option id. When set, the consumer owns the current pick (RadioGroup `value`). Attribute: `value`. */
  value?: string;
  /** Option id to pre-select on mount (uncontrolled seed). Attribute: `default-value`. */
  defaultValue?: string;
  /** Disable the whole radiogroup + Submit (e.g. while the agent is busy). Attribute: `disabled`. */
  disabled?: boolean;
  /** The selection changed BEFORE submit (a row click or the `select()` method). Distinct from the terminal `action` verb on the `kai-card` contract event. */
  onValueChange?: (event: CustomEvent<{ value: string }>) => void;
}

export const Choice = /*#__PURE__*/ createWebComponent(
  'kai-choice',
  ["theme","data","cardId","heading","resolution","value","defaultValue","disabled"],
  { onValueChange: 'kai-value-change' },
  () => import('@kitn.ai/ui/elements/choice'),
);

export interface CoachmarkProps extends WebComponentProps {
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute; the element still self-manages). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** The bold title. Named `headline` because `title` collides with the global `HTMLElement.title` attribute (it throws at registration). */
  headline?: string;
  /** A small badge pill beside the headline (e.g. "New"). */
  badge?: string;
  /** Floating placement relative to the anchor (default `bottom`). */
  placement?: string;
  /** Color tone: `primary` (default, theme accent), `info` (blue), `success` (green), `warning` (amber), or `error` (red) — reusing the kit's tool hues. */
  tone?: "error" | "primary" | "info" | "success" | "warning";
  /** Render the arrow that points at the anchor (default `true`). Set `arrow="false"` for a plain bubble with no pointer. */
  arrow?: boolean;
  /** The × dismiss button was pressed. The consumer records that this hint was seen so it won't show again. */
  onDismiss?: (event: CustomEvent>) => void;
  /** The coachmark opened or closed (a method, the ×, or a driven `open`). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
}

export const Coachmark = /*#__PURE__*/ createWebComponent(
  'kai-coachmark',
  ["theme","open","defaultOpen","headline","badge","placement","tone","arrow"],
  { onDismiss: 'kai-dismiss', onOpenChange: 'kai-open-change' },
  () => import('@kitn.ai/ui/elements/coachmark'),
);

export interface CodeBlockProps extends WebComponentProps {
  /** 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?: "sm" | "lg" | "xs" | "base";
}

export const CodeBlock = /*#__PURE__*/ createWebComponent(
  'kai-code-block',
  ["theme","code","language","codeTheme","codeHighlight","proseSize"],
  {  },
  () => import('@kitn.ai/ui/elements/code-block'),
);

export interface CommandProps extends WebComponentProps {
  /** Flat list of items. Set as a JS property — not an HTML attribute. */
  items?: { id: string; label: string; icon?: string; description?: string; shortcut?: string; group?: string }[];
  /** Placeholder text for the search input. */
  placeholder?: string;
  /** Label shown when no items match the current query. */
  emptyLabel?: string;
  /** Fired when the highlighted/active item changes — via Arrow keys or when filtering re-clamps the active row. `id` is the newly active item's id, or `undefined` when no item is active (e.g. the filtered list is empty). Lets a host preview the active item without committing a selection. */
  onActiveChange?: (event: CustomEvent<{ id: undefined | string }>) => void;
  /** Fired on every keystroke in the search input. */
  onQueryChange?: (event: CustomEvent<{ value: string }>) => void;
  /** Fired when the user selects an item (click or Enter). */
  onSelect?: (event: CustomEvent<{ id: string }>) => void;
}

export const Command = /*#__PURE__*/ createWebComponent(
  'kai-command',
  ["theme","items","placeholder","emptyLabel"],
  { onActiveChange: 'kai-active-change', onQueryChange: 'kai-query-change', onSelect: 'kai-select' },
  () => import('@kitn.ai/ui/elements/command'),
);

export interface CompareProps extends WebComponentProps {
  /** The compare definition (prompt + the two candidates). Set as a JS PROPERTY: `el.data = { prompt, candidates: [A, B], collapse? }`. Import `ResponseCompareData` from `@kitn.ai/ui` for the full shape. */
  data?: Record;
  /** Stable id correlating every emitted event. Attribute: `compare-id`. */
  compareId?: string;
  /** Re-hydrate / control the user's pick. Set as a JS PROPERTY: `el.selection = { chosenId, rejectedIds }`. Renders the collapsed winner. */
  selection?: Record;
  /** Layout: `'auto'` (default — columns when wide, tabs when narrow, by CONTAINER width) | `'columns'` (side-by-side) | `'tabs'` (pills to switch). Attribute: `layout`. */
  layout?: "auto" | "columns" | "tabs";
  /** Prose/text size for the rendered candidates. Attribute: `prose-size`. */
  proseSize?: "sm" | "lg" | "xs" | "base";
  /** Shiki theme for code blocks in the candidates. Attribute: `code-theme`. */
  codeTheme?: string;
  /** Whether code blocks are syntax-highlighted. Attribute: `code-highlight`. */
  codeHighlight?: boolean;
  /** The user committed a pick. `detail` = `{ chosenId, rejectedIds, at }`. */
  onCompareSelect?: (event: CustomEvent<{ chosenId: string; rejectedIds: string[]; at?: undefined | number }>) => void;
  /** The definition was unusable. */
  onError?: (event: CustomEvent<{ compareId: string; message: string }>) => void;
  /** Both candidates have settled and the pick is live. */
  onReady?: (event: CustomEvent<{ compareId: string }>) => void;
}

export const Compare = /*#__PURE__*/ createWebComponent(
  'kai-compare',
  ["theme","data","compareId","selection","layout","proseSize","codeTheme","codeHighlight"],
  { onCompareSelect: 'kai-compare-select', onError: 'kai-error', onReady: 'kai-ready' },
  () => import('@kitn.ai/ui/elements/compare'),
);

export interface ComposerProps extends WebComponentProps {
  /** Controlled value — string or a full ComposerDoc (set as JS property). */
  value?: string | ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: string; promptText?: string; data?: Record } })[];
  /** Placeholder text shown when the composer is empty. */
  placeholder?: string;
  /** Disable the composer entirely (non-interactive). */
  disabled?: boolean;
  /** Show a loading/streaming state and block submit. */
  loading?: boolean;
  /** Maximum height in px before the content scrolls. Default 240. */
  maxHeight?: string | number;
  /** Whether pressing Enter (without Shift) submits. Default true. */
  submitOnEnter?: boolean;
  /** Trigger definitions — set as a JS property. */
  triggers?: { char: string; kind: string; items?: { id: string; label: string; icon?: string; description?: string; group?: string; kind?: string; promptText?: string; data?: Record }[] }[];
  /** Keyword highlight rules — set as a JS property. */
  highlights?: (string | { pattern: string; flags?: string; class?: string })[];
  /** Default icon per entity kind (kind → image URL/data-URI) for items without their own `icon`. Overrides the built-in agent/plugin glyphs. JS property. */
  kindIcons?: Record;
  /** The composer lost focus. */
  onBlur?: (event: CustomEvent<{ originalEvent: FocusEvent }>) => void;
  /** An entity pill was inserted into the composer. */
  onEntityAdd?: (event: CustomEvent<{ entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record } }>) => void;
  /** An entity pill was deleted from the composer. */
  onEntityRemove?: (event: CustomEvent<{ entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record } }>) => void;
  /** The composer gained focus. `focus`/`blur` are NOT composed natively, so they don't escape the shadow root — these re-expose them on the host. (For `keydown`/`paste`/`focusin`/`focusout`, listen NATIVELY on ``: they're composed and already cross the shadow boundary.) */
  onFocus?: (event: CustomEvent<{ originalEvent: FocusEvent }>) => void;
  /** The user submitted the composer (Enter or programmatic submit). */
  onSubmit?: (event: CustomEvent<{ doc: ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record } })[]; text: string; entities: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record }[] }>) => void;
  /** A trigger character was detected at the caret (e.g. `/` or `@`). */
  onTrigger?: (event: CustomEvent<{ char: string; query: string; rect: DOMRect }>) => void;
  /** The active trigger was dismissed (Escape, space, or outside click). */
  onTriggerClose?: (event: CustomEvent>) => void;
  /** The content changed (fires on every input event). */
  onValueChange?: (event: CustomEvent<{ doc: ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record } })[]; text: string; entities: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record }[] }>) => void;
}

export const Composer = /*#__PURE__*/ createWebComponent(
  'kai-composer',
  ["theme","value","placeholder","disabled","loading","maxHeight","submitOnEnter","triggers","highlights","kindIcons"],
  { onBlur: 'kai-blur', onEntityAdd: 'kai-entity-add', onEntityRemove: 'kai-entity-remove', onFocus: 'kai-focus', onSubmit: 'kai-submit', onTrigger: 'kai-trigger', onTriggerClose: 'kai-trigger-close', onValueChange: 'kai-value-change' },
  () => import('@kitn.ai/ui/elements/composer'),
);

export interface ConfirmProps extends WebComponentProps {
  /** The confirm definition (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { body, tone, actions:[…] }`. Import `ConfirmCardData` from `@kitn.ai/ui` for the full shape. */
  data?: Record;
  /** 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;
}

export const Confirm = /*#__PURE__*/ createWebComponent(
  'kai-confirm',
  ["theme","data","cardId","heading","autofocus","resolution"],
  {  },
  () => import('@kitn.ai/ui/elements/confirm-card'),
);

export interface ContextProps extends WebComponentProps {
  /** 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;
  /** Fires when the computed severity level changes (ok → warn → danger or back). `detail.level` is `'ok'`, `'warn'`, or `'danger'`. */
  onThresholdChange?: (event: CustomEvent<{ level: "ok" | "warn" | "danger" }>) => void;
}

export const Context = /*#__PURE__*/ createWebComponent(
  'kai-context',
  ["theme","context","warnThreshold","dangerThreshold"],
  { onThresholdChange: 'kai-threshold-change' },
  () => import('@kitn.ai/ui/elements/context-meter'),
);

export interface ConversationsProps extends WebComponentProps {
  /** 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; trailing?: undefined | string }[];
  /** The id of the currently-open conversation, highlighted in the list. */
  activeId?: string;
  /** Controlled collapsed state. Set as a JS property (`el.collapsed = true`) to drive the rail from your app, updating it in response to `kai-collapse-toggle`. Omit for uncontrolled (the element manages it). Collapsed shrinks the rail to a floating reopen button. */
  collapsed?: boolean;
  /** Initial collapsed state when uncontrolled (default false). Use the `default-collapsed` attribute to start collapsed in plain HTML. */
  defaultCollapsed?: boolean;
  /** The rail was collapsed or expanded (via the toggle, the reopen button, or a `collapse()`/`expand()`/`toggle()` call). */
  onCollapseToggle?: (event: CustomEvent<{ collapsed: boolean }>) => void;
  /** A conversation was selected. */
  onConversationSelect?: (event: CustomEvent<{ id: string }>) => void;
  /** The "New chat" button was clicked. */
  onNewChat?: (event: CustomEvent>) => void;
  /** The built-in search box query changed (typing, or a programmatic `clear()` which fires it with `''`). Lets a consumer mirror or server-side the filter. */
  onSearch?: (event: CustomEvent<{ query: string }>) => void;
  /** The sidebar toggle was clicked. */
  onToggleSidebar?: (event: CustomEvent>) => void;
}

export const Conversations = /*#__PURE__*/ createWebComponent(
  'kai-conversations',
  ["theme","groups","conversations","activeId","collapsed","defaultCollapsed"],
  { onCollapseToggle: 'kai-collapse-toggle', onConversationSelect: 'kai-conversation-select', onNewChat: 'kai-new-chat', onSearch: 'kai-search', onToggleSidebar: 'kai-toggle-sidebar' },
  () => import('@kitn.ai/ui/elements/conversation-list'),
);

export interface DialogProps extends WebComponentProps {
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute; the element still self-manages on Escape/backdrop). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** The dialog opened or closed (Escape, backdrop click, a driven `open`, or a method). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
}

export const Dialog = /*#__PURE__*/ createWebComponent(
  'kai-dialog',
  ["theme","open","defaultOpen"],
  { onOpenChange: 'kai-open-change' },
  () => import('@kitn.ai/ui/elements/dialog'),
);

export interface EditableLabelProps extends WebComponentProps {
  /** The label text — settable and reflected to the `value` attribute. Read `el.value` for live state. */
  value?: string;
  /** Controlled edit state. `el.editing = true` opens the field; reflected to the `editing` attribute. */
  editing?: boolean;
  /** Placeholder shown while editing / when the value is empty. */
  placeholder?: string;
  /** Disable entering edit mode. */
  disabled?: boolean;
  /** Edit was cancelled (Esc); the text is restored. */
  onCancel?: (event: CustomEvent>) => void;
  /** Committed a changed value (Enter / blur). */
  onRename?: (event: CustomEvent<{ value: string }>) => void;
}

export const EditableLabel = /*#__PURE__*/ createWebComponent(
  'kai-editable-label',
  ["theme","value","editing","placeholder","disabled"],
  { onCancel: 'kai-cancel', onRename: 'kai-rename' },
  () => import('@kitn.ai/ui/elements/editable-label'),
);

export interface EmbedProps extends WebComponentProps {
  /** 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 const Embed = /*#__PURE__*/ createWebComponent(
  'kai-embed',
  ["theme","cardId","data"],
  {  },
  () => import('@kitn.ai/ui/elements/embed'),
);

export interface EmptyProps extends WebComponentProps {
  /** Title text. Attribute: `empty-title` (`title` is a global HTML attribute). */
  emptyTitle?: string;
  /** Description text. */
  description?: string;
}

export const Empty = /*#__PURE__*/ createWebComponent(
  'kai-empty',
  ["theme","emptyTitle","description"],
  {  },
  () => import('@kitn.ai/ui/elements/empty'),
);

export interface FeedbackBarProps extends WebComponentProps {
  /** 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;
  /** The user dismissed the banner. */
  onClose?: (event: CustomEvent) => void;
  /** The user rated the response. `value` is `'helpful'` or `'not-helpful'`. */
  onFeedback?: (event: CustomEvent<{ value: "helpful" | "not-helpful" }>) => void;
  /** The user submitted the optional detail form (`collect-detail`). */
  onFeedbackDetail?: (event: CustomEvent<{ value: "helpful" | "not-helpful"; category?: undefined | string; comment?: undefined | string }>) => void;
}

export const FeedbackBar = /*#__PURE__*/ createWebComponent(
  'kai-feedback-bar',
  ["theme","barTitle","collectDetail","categories","detailTitle","detailPlaceholder","submitLabel","thanksMessage"],
  { onClose: 'kai-close', onFeedback: 'kai-feedback', onFeedbackDetail: 'kai-feedback-detail' },
  () => import('@kitn.ai/ui/elements/feedback-bar'),
);

export interface FileTreeProps extends WebComponentProps {
  /** The files to render. Set as a JS property (array of `{ path, url?, code?, language?, type?, additions?, deletions?, status? }`). */
  files: { path: string; url?: undefined | string; code?: undefined | string; language?: undefined | string; type?: undefined | "html" | "pdf" | "image" | "other"; additions?: undefined | number; deletions?: undefined | number; status?: undefined | "added" | "modified" | "deleted" | "renamed" | "untracked" }[];
  /** Selected file path — highlighted in the tree. */
  activeFile?: string;
  /** Folder paths expanded initially. Omit to start with all folders open. */
  defaultExpanded?: string[];
  /** Show a changed-files summary header (file count + summed `+/-` + Collapse-all). Attribute: `summary`. Off by default. */
  summary?: boolean;
  /** Fired when a file is selected. `detail.path` = the file's path. */
  onSelect?: (event: CustomEvent<{ path: string }>) => void;
}

export const FileTree = /*#__PURE__*/ createWebComponent(
  'kai-file-tree',
  ["theme","files","activeFile","defaultExpanded","summary"],
  { onSelect: 'kai-select' },
  () => import('@kitn.ai/ui/elements/file-tree'),
);

export interface FileUploadProps extends WebComponentProps {
  /** 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;
  /** Files were picked or dropped. */
  onFilesAdded?: (event: CustomEvent<{ files: File[] }>) => void;
}

export const FileUpload = /*#__PURE__*/ createWebComponent(
  'kai-file-upload',
  ["theme","multiple","accept","disabled","label"],
  { onFilesAdded: 'kai-files-added' },
  () => import('@kitn.ai/ui/elements/file-upload'),
);

export interface FormProps extends WebComponentProps {
  /** The form definition — a JSON Schema (`type:'object'`) + `x-kai-*` UI hints (the CardEnvelope.data). Set as a JS PROPERTY: `el.data = { type:'object', properties:{…} }`. Import the `FormDefinition` type from `@kitn.ai/ui` for the full shape (it is self-referential, so the element types it loosely). */
  data?: Record;
  /** 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;
  /** Controlled field values (JS property). When set, it wins over local edits. */
  values?: Record;
  /** Initial values overlaying the schema defaults (uncontrolled seed; JS property). */
  defaultValues?: Record;
  /** Disable all fields + submit. Attribute: `disabled`. */
  disabled?: boolean;
  /** The form's values changed on input — current coerced values + validity. */
  onValuesChange?: (event: CustomEvent<{ values: Record; valid: boolean }>) => void;
}

export const Form = /*#__PURE__*/ createWebComponent(
  'kai-form',
  ["theme","data","cardId","heading","resolution","values","defaultValues","disabled"],
  { onValuesChange: 'kai-values-change' },
  () => import('@kitn.ai/ui/elements/form'),
);

export interface HoverCardProps extends WebComponentProps {
  /** Delay (ms) before the card opens on hover. Defaults to 0 (focus opens it immediately too). */
  openDelay?: number;
  /** Delay (ms) before it closes after the pointer leaves. Defaults to 300. */
  closeDelay?: number;
  /** Preferred placement: `'top' | 'bottom' | 'left' | 'right'` (+ optional `-start`/`-end`). Defaults to `'bottom'`; flips to stay in view. */
  placement?: string;
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute, the element still self-manages on hover). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** Suppress the hover behavior entirely without unmounting. */
  disabled?: boolean;
  /** The card opened or closed (by hover/focus, outside-click, or a method). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
}

export const HoverCard = /*#__PURE__*/ createWebComponent(
  'kai-hover-card',
  ["theme","openDelay","closeDelay","placement","open","defaultOpen","disabled"],
  { onOpenChange: 'kai-open-change' },
  () => import('@kitn.ai/ui/elements/hover-card'),
);

export interface IconProps extends WebComponentProps {
  /** A curated icon name (e.g. `"mic"`, `"globe"`), an image URL/data-URI, or plain text. */
  name?: string;
  /** Size token: `sm` | `md` (default) | `lg`. */
  size?: "sm" | "md" | "lg";
}

export const Icon = /*#__PURE__*/ createWebComponent(
  'kai-icon',
  ["theme","name","size"],
  {  },
  () => import('@kitn.ai/ui/elements/icon'),
);

export interface ImageProps extends WebComponentProps {
  /** 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 const Image = /*#__PURE__*/ createWebComponent(
  'kai-image',
  ["theme","base64","bytes","alt","mediaType"],
  {  },
  () => import('@kitn.ai/ui/elements/image'),
);

export interface InputProps extends WebComponentProps {
  /** Native input type: `text` (default) · `email` · `url` · `search` · `tel` · `password` · `number`. Single-line only. */
  type?: string;
  /** Controlled value — settable and reflected to the `value` attribute. `el.value = 'hi'` drives it (no event); typing updates it and fires `kai-input`. Read `el.value` for live state. */
  value?: string;
  /** Placeholder shown when empty. */
  placeholder?: string;
  /** Field label, linked to the input. */
  label?: string;
  /** Helper text below the control. */
  hint?: string;
  /** Error text; flips the field invalid (`aria-invalid` + destructive border). */
  error?: string;
  /** Control density: `sm` or `md`. Defaults to `md`. */
  size?: "sm" | "md";
  /** Disable interaction. */
  disabled?: boolean;
  /** Make the input read-only. */
  readonly?: boolean;
  /** Mark the input required. */
  required?: boolean;
  /** Force the invalid state without an `error` string. */
  invalid?: boolean;
  /** Form-control name. */
  name?: string;
  /** Autofill hint forwarded to the inner input (e.g. `email`, `current-password`). */
  autocomplete?: string;
  /** Virtual-keyboard hint forwarded to the inner input (e.g. `numeric`, `email`). */
  inputmode?: string;
  /** The value was committed (blur). */
  onChange?: (event: CustomEvent<{ value: string }>) => void;
  /** The value changed per keystroke. */
  onInput?: (event: CustomEvent<{ value: string }>) => void;
}

export const Input = /*#__PURE__*/ createWebComponent(
  'kai-input',
  ["theme","type","value","placeholder","label","hint","error","size","disabled","readonly","required","invalid","name","autocomplete","inputmode"],
  { onChange: 'kai-change', onInput: 'kai-input' },
  () => import('@kitn.ai/ui/elements/input'),
);

export interface KbdProps extends WebComponentProps {
  /** Shortcut spec — tokens joined by `+` (e.g. `Mod+Shift+K`). Omit it to show default-slot content instead. Display only; the element does not bind keys. */
  keys?: string;
  /** `mac` uses ⌘/⌥, `other` uses Ctrl. `auto` (default) sniffs the OS. */
  platform?: "other" | "auto" | "mac";
  /** Cap size: `sm` or `md`. Defaults to `md`. */
  size?: "sm" | "md";
}

export const Kbd = /*#__PURE__*/ createWebComponent(
  'kai-kbd',
  ["theme","keys","platform","size"],
  {  },
  () => import('@kitn.ai/ui/elements/kbd'),
);

export interface LinkPreviewProps extends WebComponentProps {
  /** 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 const LinkPreview = /*#__PURE__*/ createWebComponent(
  'kai-link-preview',
  ["theme","cardId","data"],
  {  },
  () => import('@kitn.ai/ui/elements/link-preview'),
);

export interface LoaderProps extends WebComponentProps {
  /** 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" | "md" | "lg";
  /** Label for the text-based variants. */
  text?: string;
}

export const Loader = /*#__PURE__*/ createWebComponent(
  'kai-loader',
  ["theme","variant","size","text"],
  {  },
  () => import('@kitn.ai/ui/elements/loader'),
);

export interface MarkdownProps extends WebComponentProps {
  /** The markdown source to render. */
  content: string;
  /** Text/markdown sizing. */
  proseSize?: "sm" | "lg" | "xs" | "base";
  /** Shiki theme for fenced code blocks. */
  codeTheme?: string;
  /** Disable syntax highlighting (no Shiki loads). */
  codeHighlight?: boolean;
}

export const Markdown = /*#__PURE__*/ createWebComponent(
  'kai-markdown',
  ["theme","content","proseSize","codeTheme","codeHighlight"],
  {  },
  () => import('@kitn.ai/ui/elements/markdown'),
);

export interface MenuProps extends WebComponentProps {
  /** Tree of menu items. Set as a JS property — not an HTML attribute. */
  items?: { id?: string; label?: string; icon?: string; shortcut?: string; checked?: boolean; radioGroup?: string; disabled?: boolean; separator?: boolean; heading?: boolean; items?: Record[] }[];
  /** Optional placement hint (unused by the underlying Dropdown which always positions bottom-start, kept for future extension). */
  placement?: string;
  /** Built-in trigger: leading icon (a named icon like `"plus"`, an image URL/data-URI, or text). Use this instead of slotting `slot="trigger"` for the common case — a slotted trigger overrides it. */
  triggerIcon?: string;
  /** Built-in trigger: a text label (e.g. `"High"`). */
  triggerLabel?: string;
  /** Built-in trigger: a trailing icon (e.g. `"chevron-down"` for a select look). */
  triggerIconTrailing?: string;
  /** Accessible name for an icon-only trigger (no visible label). */
  label?: string;
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute, the menu still self-manages on click/keyboard). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** Disable the trigger — click/keyboard and `show()` no longer open the menu. */
  disabled?: boolean;
  /** The menu opened or closed (by click, keyboard, Escape, outside-click, or a method). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
  /** Fired when the user selects a leaf item. - Plain items: `{ id }`. - Checkbox items: `{ id, checked }` where `checked` is the NEW state. - Radio items: `{ id, radioGroup }` — the consumer marks `id` as the selected one in `radioGroup` and clears the others. */
  onSelect?: (event: CustomEvent<{ id: string; checked?: undefined | boolean; radioGroup?: undefined | string }>) => void;
}

export const Menu = /*#__PURE__*/ createWebComponent(
  'kai-menu',
  ["theme","items","placement","triggerIcon","triggerLabel","triggerIconTrailing","label","open","defaultOpen","disabled"],
  { onOpenChange: 'kai-open-change', onSelect: 'kai-select' },
  () => import('@kitn.ai/ui/elements/menu'),
);

export interface MessageProps extends WebComponentProps {
  /** 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; output?: Record; 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 }; feedback?: "like" | "dislike" };
  /** 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?: "sm" | "lg" | "xs" | "base";
  /** 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;
  /** Avatar rail mode. `'none'` omits the avatar rail entirely so the body spans the full row (predictable layout when you never show avatars). Any other value keeps the default behaviour: the built-in avatar when one resolves, or your `slot="avatar"` content when projected (which REPLACES the built-in). */
  avatar?: string;
  /** An action button was clicked. `action` is the built-in name or custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
  onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
}

export const Message = /*#__PURE__*/ createWebComponent(
  'kai-message',
  ["theme","message","role","content","markdown","proseSize","codeTheme","codeHighlight","actionsReveal","avatarSrc","avatarFallback","avatar"],
  { onMessageAction: 'kai-message-action' },
  () => import('@kitn.ai/ui/elements/message'),
);

export interface ModelSwitcherProps extends WebComponentProps {
  /** 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;
  /** Drive/observe the dropdown's open state (Shoelace-style: settable + reflected to the `open` attribute, the dropdown still self-manages on click/keyboard). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** Disable the trigger — click/keyboard and `show()` no longer open the dropdown. */
  disabled?: boolean;
  /** A model was selected. */
  onModelChange?: (event: CustomEvent<{ modelId: string }>) => void;
  /** The model dropdown opened or closed (by click, keyboard, Escape, outside-click, or a method). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
}

export const ModelSwitcher = /*#__PURE__*/ createWebComponent(
  'kai-model-switcher',
  ["theme","models","currentModel","open","defaultOpen","disabled"],
  { onModelChange: 'kai-model-change', onOpenChange: 'kai-open-change' },
  () => import('@kitn.ai/ui/elements/model-switcher'),
);

export interface NavProps extends WebComponentProps {
  /** The nav items. Set as a JS property (array, not an attribute). Each item may carry `children` (a collapsible group), a `status` dot, and trailing `meta` text. */
  items?: { id: string; label?: string; icon?: string; badge?: string; trailing?: string; disabled?: boolean; children?: Record[]; status?: { tone: "error" | "primary" | "info" | "success" | "warning" | "neutral"; label?: string; pulse?: boolean }; meta?: string; action?: { icon: string; label: string }; closable?: boolean }[];
  /** Active item id (controlled). */
  value?: string;
  /** Initial active id when uncontrolled. */
  defaultValue?: string;
  /** Ids of group items collapsed on first render (groups default to expanded). Set as a JS property (array). */
  defaultCollapsed?: string[];
  /** A row's trailing `action` button was activated (not a select). `value` is the item id; `action` echoes the item's `{ icon, label }`. */
  onNavItemAction?: (event: CustomEvent<{ value: string; action?: undefined | { icon: string; label: string } }>) => void;
  /** A `closable` row's trailing close button was activated (not a select). `value` is the item id. */
  onNavItemClose?: (event: CustomEvent<{ value: string }>) => void;
  /** A nav item was activated. */
  onNavSelect?: (event: CustomEvent<{ id: string }>) => void;
}

export const Nav = /*#__PURE__*/ createWebComponent(
  'kai-nav',
  ["theme","items","value","defaultValue","defaultCollapsed"],
  { onNavItemAction: 'kai-nav-item-action', onNavItemClose: 'kai-nav-item-close', onNavSelect: 'kai-nav-select' },
  () => import('@kitn.ai/ui/elements/nav'),
);

export interface NoticeProps extends WebComponentProps {
  /** `neutral` (default) · `info` · `warning` · `error` · `success`. Drives the leading icon's color and the a11y role (`alert` for errors, else `status`). */
  severity?: "error" | "info" | "success" | "warning" | "neutral";
  /** Leading icon: omit for the severity default, `"none"` to hide it, or a named icon to override. */
  icon?: string;
  /** Show a dismiss (×) that hides the notice and emits `kai-dismiss`. */
  dismissible?: boolean;
  /** The notice was dismissed via its × (it also hides itself). */
  onDismiss?: (event: CustomEvent) => void;
}

export const Notice = /*#__PURE__*/ createWebComponent(
  'kai-notice',
  ["theme","severity","icon","dismissible"],
  { onDismiss: 'kai-dismiss' },
  () => import('@kitn.ai/ui/elements/notice'),
);

export interface PaneProps extends WebComponentProps {
  /** The pane title (the agent / window name). Named `headline` because `title` collides with the global `HTMLElement.title` attribute (it throws at registration). Attribute: `headline`. */
  headline?: string;
  /** A role / label shown under the title (e.g. "Reviewer", "claude-sonnet"). Attribute: `subtitle`. */
  subtitle?: string;
  /** Show the restore glyph instead of maximize, and signal the maximized view-state. Drive it yourself in response to `kai-maximize`. Attribute: `maximized`. */
  maximized?: boolean;
  /** Highlight the frame with a ring/border to mark the ACTIVE pane. Attribute: `focused`. */
  focused?: boolean;
  /** Show a split-pane window control that fires `kai-split`. Off by default. Attribute: `show-split`. */
  showSplit?: boolean;
  /** Show a dock-to-side window control that fires `kai-dock`. Off by default. Attribute: `show-dock`. */
  showDock?: boolean;
  /** A tone-colored status dot (+ optional label) in the header. An object `{ tone, label?, pulse? }` set as a JS PROPERTY (not an attribute). */
  status?: { tone: "working" | "idle" | "done" | "error" | "blocked"; label?: string; pulse?: boolean };
  /** The close (×) control was clicked. */
  onClose?: (event: CustomEvent) => void;
  /** The dock control was clicked (only present when `show-dock`). */
  onDock?: (event: CustomEvent) => void;
  /** The maximize/restore control was clicked. `detail.maximized` is the intended NEXT state — drive the `maximized` prop yourself from it. */
  onMaximize?: (event: CustomEvent<{ maximized: boolean }>) => void;
  /** The split control was clicked (only present when `show-split`). */
  onSplit?: (event: CustomEvent) => void;
}

export const Pane = /*#__PURE__*/ createWebComponent(
  'kai-pane',
  ["theme","headline","subtitle","maximized","focused","showSplit","showDock","status"],
  { onClose: 'kai-close', onDock: 'kai-dock', onMaximize: 'kai-maximize', onSplit: 'kai-split' },
  () => import('@kitn.ai/ui/elements/pane'),
);

export interface PaneGroupProps extends WebComponentProps {
  /** The tabs to render. An array of `{ id, name, status?, needsAttention?, number? }` set as a JS PROPERTY (not an HTML attribute). */
  tabs?: { id: string; name: string; status?: { tone: "working" | "idle" | "done" | "error" | "blocked"; label?: string; pulse?: boolean }; needsAttention?: boolean; number?: number }[];
  /** The active tab id (controlled, and reflected to the `active` ATTRIBUTE so `::part`/`[active]` selectors and the per-tab named slot follow it). Set it as the `active` attribute or drive it from `kai-tab-change`; omit for uncontrolled (the first tab). */
  active?: string;
  /** Highlight the frame as the ACTIVE group in a multi-group layout. Attribute: `focused`. */
  focused?: boolean;
  /** A tab was selected (click, Enter/Space, or arrow-key move). `detail.id` is the tab's id. */
  onTabChange?: (event: CustomEvent<{ id: string }>) => void;
  /** A tab's close (×) was clicked. Drop the tab from `tabs` yourself. */
  onTabClose?: (event: CustomEvent<{ id: string }>) => void;
  /** A tab's "…" overflow was clicked. Open your own menu from `detail.id`. */
  onTabMenu?: (event: CustomEvent<{ id: string }>) => void;
}

export const PaneGroup = /*#__PURE__*/ createWebComponent(
  'kai-pane-group',
  ["theme","tabs","active","focused"],
  { onTabChange: 'kai-tab-change', onTabClose: 'kai-tab-close', onTabMenu: 'kai-tab-menu' },
  () => import('@kitn.ai/ui/elements/pane-group'),
);

export interface PopoverProps extends WebComponentProps {
  /** 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;
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute, the element still self-manages on click). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** Turn the popover off while keeping the trigger mounted (clicks and `show()` no longer open it). */
  disabled?: boolean;
  /** The popover opened or closed (click, Escape, outside-click, or a method). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
}

export const Popover = /*#__PURE__*/ createWebComponent(
  'kai-popover',
  ["theme","placement","gutter","open","defaultOpen","disabled"],
  { onOpenChange: 'kai-open-change' },
  () => import('@kitn.ai/ui/elements/popover'),
);

export interface ProgressBarProps extends WebComponentProps {
  /** Current progress value (0..max). Attribute: `value`. */
  value?: number;
  /** The value `value` runs to (default 100). Attribute: `max`. */
  max?: number;
  /** Optional caption above the track. Attribute: `label`. */
  label?: string;
  /** Fill color: `primary` (default), `success`, `warning`, `error`, `info`. Attribute: `tone`. */
  tone?: string;
}

export const ProgressBar = /*#__PURE__*/ createWebComponent(
  'kai-progress-bar',
  ["theme","value","max","label","tone"],
  {  },
  () => import('@kitn.ai/ui/elements/progress-bar'),
);

export interface PromptDockProps extends WebComponentProps {
  /** How the tray frames the input — the SPATIAL inset axis: `inset` (default, the classic recessed frame on every side) | `edge` (top/bottom inset only; the input sits flush left/right so the lips span the full width) | `none` (no inset; the lips attach directly as a plain stack). Attribute: `frame`. */
  frame?: "none" | "inset" | "edge";
  /** How the tray surface looks — the VISUAL axis, orthogonal to `frame`: `soft` (default, sunken surface + border + radius) | `outlined` (transparent + border + radius) | `filled` (sunken, no border, + radius) | `plain` (bare). Attribute: `appearance`. */
  appearance?: "outlined" | "filled" | "plain" | "soft";
}

export const PromptDock = /*#__PURE__*/ createWebComponent(
  'kai-prompt-dock',
  ["theme","frame","appearance"],
  {  },
  () => import('@kitn.ai/ui/elements/prompt-dock'),
);

export interface PromptInputProps extends WebComponentProps {
  /** Value of the input, as a JS property. A **string** is the controlled text mirror (the host owns it and updates on `kai-value-change`). A **ComposerDoc** (array of text/entity segments) is a one-time **seed** that pre-populates pills (skills/agents/plugins); the user then edits freely. Leave unset for uncontrolled behavior. `kai-submit`/`kai-value-change` always emit `value` as the flattened string (back-compat) plus the structured `doc` + `entities`. */
  value?: string | ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: string; promptText?: string; data?: Record } })[];
  /** 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";
  /** 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 `kai-stop`. */
  stoppable?: boolean;
  /** Send-button visibility. `'always'` (default) always shows it; `'auto'` shows it only when there's text/attachments (an empty composer hides it — Enter still submits). To hide it entirely (Enter-only), it's pure CSS: `::part(send){display:none}` — no prop needed. Restyle via `::part(send)`. The Stop button (`stoppable` + `loading`) is unaffected. */
  submit?: "always" | "auto";
  /** When `false`, hides the built-in paperclip attach button even though the element otherwise supports attachments. Use this when a `+` menu in `toolbar-start` already exposes "Add files", to avoid a duplicate control. Defaults to `true`. */
  attach?: 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 }[];
  /** Rich entity triggers — each `{ char, kind, items }` opens a caret-anchored menu that inserts an atomic pill. Convention: `/` → skills, `@` → agents (plugins are the grouping/provenance of those items). Set as a JS property. */
  triggers?: { char: string; kind: string; items?: { id: string; label: string; icon?: string; description?: string; group?: string; kind?: string; promptText?: string; data?: Record }[] }[];
  /** Default icon per entity kind (kind → image URL/data-URI) for pills/menu items without their own `icon`. Overrides the built-in agent/plugin glyphs. JS property. */
  kindIcons?: Record;
  /** The staged attachments changed — a file was added (via the paperclip) or removed (per-chip ×). Carries the full current list so a consumer can react in real time (validate, show upload progress, toggle the send button). */
  onAttachmentsChange?: (event: CustomEvent<{ attachments: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }>) => void;
  /** The Search (Globe) toolbar button was clicked. */
  onSearch?: (event: CustomEvent>) => void;
  /** The Stop button was clicked while `stoppable` and `loading` are both true. */
  onStop?: (event: CustomEvent>) => void;
  /** The user submitted the prompt (Enter or send button). `value` is the flattened text (back-compat); `doc` is the structured document and `entities` the inserted pills (skills/agents) for downstream expansion. */
  onSubmit?: (event: CustomEvent<{ value: string; doc: ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record } })[]; entities: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record }[]; attachments: { id: string; type: "file" | "source-document"; filename?: undefined | string; mediaType?: undefined | string; url?: undefined | string; title?: undefined | string }[] }>) => void;
  /** A suggestion was clicked while `suggestion-mode="fill"`. */
  onSuggestionClick?: (event: CustomEvent<{ value: string }>) => void;
  /** A custom `` toolbar button was clicked. `action` is the `id` of the `` element that was clicked. */
  onToolbarAction?: (event: CustomEvent<{ action: string }>) => void;
  /** The input changed (fires on every edit). Carries the flattened `value` plus the structured `doc` + `entities`. */
  onValueChange?: (event: CustomEvent<{ value: string; doc: ({ type: "text"; text: string } | { type: "entity"; entity: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record } })[]; entities: { kind: string; id: string; label: string; icon?: undefined | string; promptText?: undefined | string; data?: undefined | Record }[] }>) => void;
  /** The Voice (Mic) toolbar button was clicked. */
  onVoice?: (event: CustomEvent>) => void;
}

export const PromptInput = /*#__PURE__*/ createWebComponent(
  'kai-prompt-input',
  ["theme","value","placeholder","disabled","loading","suggestions","suggestionMode","search","voice","stoppable","submit","attach","attachments","triggers","kindIcons"],
  { onAttachmentsChange: 'kai-attachments-change', onSearch: 'kai-search', onStop: 'kai-stop', onSubmit: 'kai-submit', onSuggestionClick: 'kai-suggestion-click', onToolbarAction: 'kai-toolbar-action', onValueChange: 'kai-value-change', onVoice: 'kai-voice' },
  () => import('@kitn.ai/ui/elements/prompt-input'),
);

export interface ReasoningProps extends WebComponentProps {
  /** The reasoning text to display. */
  text: string;
  /** Trigger label. */
  label?: string;
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute; the element still self-manages on trigger click + while streaming). Set `el.open = true`; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** While true, auto-expands (and re-collapses when it flips false). */
  streaming?: boolean;
  /** Render `text` as markdown. */
  markdown?: boolean;
  /** Gate the disclosure trigger — programmatic `show()/hide()/toggle()` still work, but the trigger click no longer toggles. */
  disabled?: boolean;
  /** The reasoning block expanded or collapsed (via the trigger, streaming auto-open, or a method). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
}

export const Reasoning = /*#__PURE__*/ createWebComponent(
  'kai-reasoning',
  ["theme","text","label","open","defaultOpen","streaming","markdown","disabled"],
  { onOpenChange: 'kai-open-change' },
  () => import('@kitn.ai/ui/elements/reasoning'),
);

export interface RemoteProps extends WebComponentProps {
  /** 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;
  /** Optional routing policy. JS property only. */
  policy?: Record;
}

export const Remote = /*#__PURE__*/ createWebComponent(
  'kai-remote',
  ["theme","src","providerOrigin","envelope","policy"],
  {  },
  () => import('@kitn.ai/ui/elements/remote'),
);

export interface ResizableProps extends WebComponentProps {
  /** Layout axis: `horizontal` (row, default) or `vertical` (column). */
  orientation?: "vertical" | "horizontal";
  /** Which item index is maximized (null = none). Declarative source of truth. */
  maximizedIndex?: null | number;
  /** Fired on drag-end / keyboard resize / visibility change. `detail.sizes` = panel sizes in percent. */
  onChange?: (event: CustomEvent<{ sizes: number[] }>) => void;
  /** Observe layout maximize state. */
  onMaximizeChange?: (event: CustomEvent<{ maximized: boolean; index: null | number }>) => void;
}

export const Resizable = /*#__PURE__*/ createWebComponent(
  'kai-resizable',
  ["theme","orientation","maximizedIndex"],
  { onChange: 'kai-change', onMaximizeChange: 'kai-maximize-change' },
  () => import('@kitn.ai/ui/elements/resizable'),
);

export interface ResizableItemProps extends WebComponentProps {
  /** 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;
  /** Collapse this panel — same layout effect as `hidden` (divider dropped, the rest reflow), but it WORKS as a bare boolean from framework JSX. A plain `` in React/Solid/Vue/Svelte collapses the panel at the first render; `hidden` does not, because a JSX boolean sets neither the `hidden` attribute nor the IDL property on a custom element, so the parent never sees it. The facade reflects `collapsed` to a `collapsed` attribute the parent reads. Prefer this over `hidden` for declarative collapse. */
  collapsed?: boolean;
  onChange?: (event: CustomEvent) => void;
  onMaximizeChange?: (event: CustomEvent) => void;
}

export const ResizableItem = /*#__PURE__*/ createWebComponent(
  'kai-resizable-item',
  ["theme","size","min","max","locked","hidden","collapsed"],
  { onChange: 'kai-change', onMaximizeChange: 'kai-maximize-change' },
  () => import('@kitn.ai/ui/elements/resizable'),
);

export interface ResponseStreamProps extends WebComponentProps {
  /** Text to stream. A string, or an `AsyncIterable` (set as a JS property — async iterables can't be HTML attributes). */
  text?: string | AsyncIterable;
  /** Reveal animation. */
  mode?: "typewriter" | "fade";
  /** Characters/segments per tick. */
  speed?: number;
  /** Element tag to render as. */
  as?: string;
  /** Streaming finished. */
  onComplete?: (event: CustomEvent) => void;
}

export const ResponseStream = /*#__PURE__*/ createWebComponent(
  'kai-response-stream',
  ["theme","text","mode","speed","as"],
  { onComplete: 'kai-complete' },
  () => import('@kitn.ai/ui/elements/response-stream'),
);

export interface ScopePickerProps extends WebComponentProps {
  /** 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;
  /** Drive/observe the dropdown's open state (Shoelace-style: settable + reflected to the `open` attribute, the dropdown still self-manages on click/keyboard). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** Disable the trigger — click/keyboard and `show()` no longer open the dropdown. */
  disabled?: boolean;
  /** The scope dropdown opened or closed (by click, keyboard, Escape, outside-click, or a method). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
  /** A scope was chosen (`undefined` filters = "All Content"). */
  onScopeChange?: (event: CustomEvent<{ filters: undefined | { tags?: undefined | string[]; authors?: undefined | string[]; contentType?: undefined | "transcript" | "markdown"; dateRange?: undefined | { from: string; to: string } } }>) => void;
}

export const ScopePicker = /*#__PURE__*/ createWebComponent(
  'kai-scope-picker',
  ["theme","availableAuthors","availableTags","currentLabel","open","defaultOpen","disabled"],
  { onOpenChange: 'kai-open-change', onScopeChange: 'kai-scope-change' },
  () => import('@kitn.ai/ui/elements/chat-scope-picker'),
);

export interface ScreenProps extends WebComponentProps {
  /** Drive/observe open state (Shoelace-style: settable + reflected to the `open` attribute; the element still self-manages). Set `el.open = true`, or ``; listen for `kai-open-change`. */
  open?: boolean;
  /** Initial open state on mount (uncontrolled seed). */
  defaultOpen?: boolean;
  /** Header title text. A projected `title` slot overrides it. (Named `headline` because `title` collides with the global `HTMLElement.title` attribute.) */
  headline?: string;
  /** Show the back button (default true). */
  back?: boolean;
  /** Opt out of marking sibling elements inert/aria-hidden while open (for unusual layouts). */
  noInert?: boolean;
  /** Back navigation intent: the back button or Escape. The consumer flips their own routing in response (the screen knows nothing about the trigger). */
  onBack?: (event: CustomEvent>) => void;
  /** The screen opened or closed (a method, `Escape` close, or driven `open`). */
  onOpenChange?: (event: CustomEvent<{ open: boolean }>) => void;
}

export const Screen = /*#__PURE__*/ createWebComponent(
  'kai-screen',
  ["theme","open","defaultOpen","headline","back","noInert"],
  { onBack: 'kai-back', onOpenChange: 'kai-open-change' },
  () => import('@kitn.ai/ui/elements/screen'),
);

export interface ScrollAreaProps extends WebComponentProps {
  /** Which axis scrolls. `vertical` (default) · `horizontal` · `both`. The cross axis is clamped so content can't overflow it. */
  orientation?: "vertical" | "horizontal" | "both";
}

export const ScrollArea = /*#__PURE__*/ createWebComponent(
  'kai-scroll-area',
  ["theme","orientation"],
  {  },
  () => import('@kitn.ai/ui/elements/scroll-area'),
);

export interface ScrollButtonProps extends WebComponentProps {
  /** 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 `