UNPKG

@kitn.ai/ui

Version:

Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. Authored in SolidJS.

177 lines (176 loc) 9.82 kB
/** * Composition slots for `kai-*` elements. A slot is a named region a consumer * fills with their own markup. This registry is the SINGLE SOURCE OF TRUTH: * the facade derives its detection from it (and, later, docs are generated * from it). See docs/superpowers/specs/2026-06-23-kai-chat-composition-seams-design.md. */ /** `inject` = additive (the built-in region still renders, your markup is added * in). `replace` = your markup stands in for the whole region — you own that * region's data + events (a slotted light-DOM node can't read the component's * reactive state). */ export type SlotMode = 'inject' | 'replace'; export interface SlotDef { /** Slot name (kebab-case). Also the `::part` name when `part` is true. */ name: string; mode: SlotMode; /** Expose `::part(name)` on the region wrapper for consumer styling. */ part?: boolean; /** One-line contract: what the consumer projects / owns. Feeds the docs. */ doc: string; } /** Slots of `<kai-chat>`, in render order. */ export declare const CHAT_SLOTS: SlotDef[]; /** Slots of `<kai-prompt-input>` (and the default composer inside `<kai-chat>`). Native * shadow slots — an empty slot renders nothing, so no facade flag-gating is required. * * These are ONLY positions inside the card's shadow boundary — places a consumer * cannot reach from their own DOM. Content ABOVE/BELOW the whole card is the * consumer's own light-DOM layout (a sibling element), so there is intentionally * no outer block slot here. (When the input is nested inside `<kai-chat>`'s shadow, * that surrounding hole belongs to `kai-chat` — see `composer-actions`/`footer`.) */ export declare const PROMPT_INPUT_SLOTS: SlotDef[]; /** Slots of `<kai-conversations>` (also used inside `<kai-chat>`'s `sidebar`). * Names mirror `<kai-chat>`'s so the two compose with one vocabulary. */ export declare const CONVERSATIONS_SLOTS: SlotDef[]; /** Styleable `::part`s of `<kai-conversations>`. */ export declare const CONVERSATIONS_PARTS: PartDef[]; /** Slots of `<kai-message>` — per-message composition seams. `before-body` and * `after-body` are INJECT regions inside the message's body column; `avatar` * REPLACES the built-in avatar rail (pair it with `avatar="none"` to omit the * rail entirely). These are the keystone of compose-your-own message lists. */ export declare const MESSAGE_SLOTS: SlotDef[]; /** Slots of `<kai-notice>`. The message is the default slot; these are the named seams. */ export declare const NOTICE_SLOTS: SlotDef[]; /** Slots of `<kai-button>` (the label is the default slot). */ export declare const BUTTON_SLOTS: SlotDef[]; /** Slots of `<kai-hover-card>` (the trigger is the default slot). */ export declare const HOVER_CARD_SLOTS: SlotDef[]; /** Slots of `<kai-menu>` (the menu items come from the `items` prop). */ export declare const MENU_SLOTS: SlotDef[]; /** A styleable `::part` the kit renders (NOT a slot — you don't project into it; * you restyle it from outside via `::part(name)`). This registry is the source * of truth so the styling surface is discoverable: docs + the `kai` MCP * component reference are generated from it, the same way slots are. The * `recipe` is a copy-pasteable example — including the "just hide it" case that * is pure CSS and therefore intentionally NOT a prop. */ export interface PartDef { /** `::part(name)` exposed for consumer styling. */ name: string; /** One-line contract: what the part is. */ doc: string; /** A copy-pasteable styling example for docs / the MCP reference. */ recipe?: string; } /** Styleable `::part`s of `<kai-chat>` (beyond the slot-backed `header`/`sidebar`/ * `footer` parts). */ export declare const CHAT_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-prompt-input>`. */ export declare const PROMPT_INPUT_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-button>`. */ export declare const BUTTON_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-badge>`. */ export declare const BADGE_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-icon>`. */ export declare const ICON_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-separator>`. */ export declare const SEPARATOR_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-scroll-area>`. */ export declare const SCROLL_AREA_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-skeleton>`. */ export declare const SKELETON_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-message>`. (The `avatar` part is contributed by * the `avatar` slot's `part: true` flag, so it is not repeated here.) */ export declare const MESSAGE_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-attachments>`. */ export declare const ATTACHMENTS_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-status>`. */ export declare const STATUS_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-tabs>`. */ export declare const TABS_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-voice-output>`. */ export declare const VOICE_OUTPUT_PARTS: PartDef[]; /** Slots of `<kai-screen>` (the default slot is the screen body). */ export declare const SCREEN_SLOTS: SlotDef[]; /** Styleable `::part`s of `<kai-screen>`. */ export declare const SCREEN_PARTS: PartDef[]; /** Slots of `<kai-card>` — structural regions only (the title/description are body * or `slot="header"` content you mark up). The body is the default slot. */ export declare const CARD_SLOTS: SlotDef[]; /** Styleable `::part`s of `<kai-card>`. */ export declare const CARD_PARTS: PartDef[]; /** Injection slots of `<kai-workspace>` (the carrier regions the consumer drops * content into: brand/tabs, the upgrade/Design/user-menu cluster, a top banner). */ export declare const WORKSPACE_SLOTS: SlotDef[]; /** Styleable `::part`s of `<kai-workspace>`. */ export declare const WORKSPACE_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-nav>`. */ export declare const NAV_PARTS: PartDef[]; /** Slots of `<kai-coachmark>` (the anchor/trigger is the default slot). */ export declare const COACHMARK_SLOTS: SlotDef[]; /** Styleable `::part`s of `<kai-coachmark>`. */ export declare const COACHMARK_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-progress-bar>`. */ export declare const PROGRESS_BAR_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-file-tree>` — the changed-files / diff bits, shown * only when a file carries diff metadata (or the `summary` attribute is set). */ export declare const FILE_TREE_PARTS: PartDef[]; /** * Per-element composition surface — the SINGLE registry the build extracts * (`scripts/gen-element-api.mjs`) into `element-meta.json`, the Custom Elements * Manifest (`cssParts`/`slots`), `docs/web-components.md`, and the `kai` MCP * `component_reference`. Each entry maps a `kai-*` tag to the slots it projects * and the `::part`s it exposes for styling. Slots flagged `part: true` are ALSO * styleable parts, so they surface in both places. * * Adding a `part="…"` in a facade/component without registering it here fails the * `slots.test.ts` drift guard — keep this in sync with the source. */ export interface ElementComposition { slots?: SlotDef[]; parts?: PartDef[]; } /** Slots + styleable `::part`s of `<kai-prompt-dock>`. */ export declare const PROMPT_DOCK_SLOTS: SlotDef[]; export declare const PROMPT_DOCK_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-segmented>`. */ export declare const SEGMENTED_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-settings-group>`. */ export declare const SETTINGS_GROUP_PARTS: PartDef[]; /** Slots + styleable `::part`s of `<kai-setting-item>`. */ export declare const SETTING_ITEM_SLOTS: SlotDef[]; export declare const SETTING_ITEM_PARTS: PartDef[]; /** Slots + styleable `::part`s of `<kai-pane>` (the editor-group pane frame). */ export declare const PANE_SLOTS: SlotDef[]; export declare const PANE_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-agent-card>`. */ export declare const AGENT_CARD_PARTS: PartDef[]; /** Slots + styleable `::part`s of `<kai-dialog>` (the centered modal). */ export declare const DIALOG_SLOTS: SlotDef[]; export declare const DIALOG_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-pane-group>` (the editor group: a tab strip over * the active tab's pane). The per-tab content slots are NAMED DYNAMICALLY by tab * id (`slot="<tab id>"`) plus a default slot, so they are not enumerable here — * only the styleable parts are registered. */ export declare const PANE_GROUP_PARTS: PartDef[]; /** Affix slots + styleable `::part`s of `<kai-input>` (the field shell). */ export declare const INPUT_SLOTS: SlotDef[]; export declare const INPUT_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-search>` (the debounced filter field; composes the * kai-input field plus a clear button). */ export declare const SEARCH_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-editable-label>` (inline rename; the edit field is the kai-input field). */ export declare const EDITABLE_LABEL_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-kbd>` (the keyboard-shortcut display). */ export declare const KBD_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-command>` (the command palette). */ export declare const COMMAND_PARTS: PartDef[]; /** Styleable `::part`s of `<kai-menu>` (the actions dropdown). */ export declare const MENU_PARTS: PartDef[]; export declare const ELEMENT_COMPOSITION: Record<string, ElementComposition>; /** * Which slots have projected light-DOM content — a DIRECT child of `host` * carrying the matching `slot` attribute. Pure and synchronous; safe in jsdom * and SSR (returns all-false when `host` has no matching children). The facade * calls this on mount and on every childList mutation. */ export declare function readSlots(host: Element, defs?: SlotDef[]): Record<string, boolean>;