@kitnai/chat 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. package/README.md +11 -0
  2. package/dist/custom-elements.json +2494 -0
  3. package/dist/kitn-chat.es.js +52 -39
  4. package/dist/llms/llms-full.txt +667 -0
  5. package/dist/llms/llms.txt +104 -0
  6. package/dist/theme.tokens.css +133 -0
  7. package/frameworks/react/index.tsx +530 -0
  8. package/frameworks/react/runtime.tsx +94 -0
  9. package/llms-full.txt +667 -0
  10. package/llms.txt +104 -0
  11. package/package.json +34 -5
  12. package/src/components/attachments.tsx +4 -2
  13. package/src/components/chain-of-thought.tsx +1 -1
  14. package/src/components/chat-scope-picker.tsx +2 -2
  15. package/src/components/checkpoint.tsx +7 -3
  16. package/src/components/context.tsx +14 -18
  17. package/src/components/conversation-item.tsx +1 -1
  18. package/src/components/conversation-list.tsx +5 -4
  19. package/src/components/message-skills.tsx +1 -1
  20. package/src/components/message.tsx +1 -0
  21. package/src/components/model-switcher.tsx +3 -3
  22. package/src/components/prompt-input.tsx +15 -2
  23. package/src/components/reasoning.tsx +2 -2
  24. package/src/components/scroll-button.tsx +1 -0
  25. package/src/components/slash-command.tsx +17 -8
  26. package/src/components/source.tsx +2 -2
  27. package/src/components/thinking-bar.tsx +2 -2
  28. package/src/components/tool.tsx +17 -6
  29. package/src/components/voice-input.tsx +5 -1
  30. package/src/elements/attachments.tsx +132 -0
  31. package/src/elements/chain-of-thought.tsx +45 -0
  32. package/src/elements/chat-scope-picker.tsx +36 -0
  33. package/src/elements/chat.tsx +51 -7
  34. package/src/elements/checkpoint.tsx +43 -0
  35. package/src/elements/code-block.tsx +42 -0
  36. package/src/elements/compiled.css +1 -1
  37. package/src/elements/context-meter.tsx +71 -0
  38. package/src/elements/conversation-list.tsx +6 -0
  39. package/src/elements/default-input.tsx +22 -1
  40. package/src/elements/define.tsx +102 -13
  41. package/src/elements/element-types.d.ts +404 -0
  42. package/src/elements/empty.tsx +29 -0
  43. package/src/elements/feedback-bar.tsx +33 -0
  44. package/src/elements/file-upload.tsx +44 -0
  45. package/src/elements/image.tsx +32 -0
  46. package/src/elements/kitn-attachments.stories.tsx +181 -0
  47. package/src/elements/kitn-chain-of-thought.stories.tsx +75 -0
  48. package/src/elements/kitn-chat-scope-picker.stories.tsx +72 -0
  49. package/src/elements/kitn-checkpoint.stories.tsx +71 -0
  50. package/src/elements/kitn-code-block.stories.tsx +82 -0
  51. package/src/elements/kitn-context-meter.stories.tsx +85 -0
  52. package/src/elements/kitn-empty.stories.tsx +110 -0
  53. package/src/elements/kitn-feedback-bar.stories.tsx +73 -0
  54. package/src/elements/kitn-file-upload.stories.tsx +81 -0
  55. package/src/elements/kitn-image.stories.tsx +70 -0
  56. package/src/elements/kitn-loader.stories.tsx +87 -0
  57. package/src/elements/kitn-markdown.stories.tsx +75 -0
  58. package/src/elements/kitn-message-skills.stories.tsx +74 -0
  59. package/src/elements/kitn-message.stories.tsx +105 -0
  60. package/src/elements/kitn-model-switcher.stories.tsx +80 -0
  61. package/src/elements/kitn-prompt-input.stories.tsx +74 -16
  62. package/src/elements/kitn-prompt-suggestions.stories.tsx +157 -0
  63. package/src/elements/kitn-reasoning.stories.tsx +76 -0
  64. package/src/elements/kitn-response-stream.stories.tsx +79 -0
  65. package/src/elements/kitn-source-list.stories.tsx +77 -0
  66. package/src/elements/kitn-source.stories.tsx +87 -0
  67. package/src/elements/kitn-text-shimmer.stories.tsx +63 -0
  68. package/src/elements/kitn-thinking-bar.stories.tsx +72 -0
  69. package/src/elements/kitn-tool.stories.tsx +88 -0
  70. package/src/elements/kitn-voice-input.stories.tsx +87 -0
  71. package/src/elements/loader.tsx +25 -0
  72. package/src/elements/markdown.tsx +38 -0
  73. package/src/elements/message-skills.tsx +22 -0
  74. package/src/elements/message.tsx +125 -0
  75. package/src/elements/model-switcher.tsx +35 -0
  76. package/src/elements/prompt-input.tsx +83 -7
  77. package/src/elements/prompt-suggestions.tsx +58 -0
  78. package/src/elements/reasoning.tsx +50 -0
  79. package/src/elements/register.ts +31 -0
  80. package/src/elements/response-stream.tsx +40 -0
  81. package/src/elements/source.tsx +67 -0
  82. package/src/elements/text-shimmer.tsx +28 -0
  83. package/src/elements/thinking-bar.tsx +34 -0
  84. package/src/elements/tool.tsx +23 -0
  85. package/src/elements/voice-input.tsx +41 -0
  86. package/src/index.ts +0 -1
  87. package/src/primitives/chat-config.tsx +2 -2
  88. package/src/stories/docs/Accessibility.mdx +119 -0
  89. package/src/stories/docs/ForAIAgents.mdx +93 -0
  90. package/src/stories/docs/GettingStarted.mdx +2 -2
  91. package/src/stories/docs/Installation.mdx +2 -2
  92. package/src/stories/docs/Integrations.mdx +415 -15
  93. package/src/stories/docs/Introduction.mdx +5 -5
  94. package/src/stories/docs/Theming.mdx +1 -1
  95. package/src/stories/typography.stories.tsx +78 -0
  96. package/src/ui/button.tsx +1 -1
  97. package/src/ui/collapsible.tsx +119 -8
  98. package/src/ui/dropdown.tsx +177 -12
  99. package/src/ui/hover-card.tsx +147 -26
  100. package/src/ui/overlay.tsx +151 -0
  101. package/src/ui/textarea.tsx +1 -1
  102. package/src/ui/tooltip.stories.tsx +1 -1
  103. package/src/ui/tooltip.tsx +59 -13
  104. package/src/utils/cn.ts +19 -1
  105. package/theme.css +72 -43
  106. package/src/ui/dialog.tsx +0 -21
package/llms-full.txt ADDED
@@ -0,0 +1,667 @@
1
+ <!-- AUTO-GENERATED by scripts/gen-llms.mjs — do not edit by hand. Run `npm run build`. -->
2
+ # @kitnai/chat — Full Reference
3
+
4
+ # @kitnai/chat
5
+
6
+ > SolidJS + Shadow-DOM web component kit for building AI chat interfaces. 27 `kitn-*` custom elements: streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; SolidJS is bundled in.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @kitnai/chat
12
+ # SolidJS consumers also need the peer dep:
13
+ npm install solid-js
14
+ ```
15
+
16
+ ## #1 rule: array/object data goes on JS PROPERTIES, not HTML attributes
17
+
18
+ This is the single most common mistake. Arrays and objects (`messages`, `models`, `context`, `suggestions`, `slashCommands`, …) MUST be assigned as JavaScript properties on the element. They CANNOT be passed as HTML attributes — an HTML attribute is always a string and will be ignored or mis-parsed.
19
+
20
+ ```js
21
+ const chat = document.querySelector('kitn-chat');
22
+ chat.messages = [{ id: '1', role: 'assistant', content: 'Hi!' }]; // ✅ property
23
+ ```
24
+ ```html
25
+ <kitn-chat messages="[...]"></kitn-chat> <!-- ❌ never works -->
26
+ ```
27
+
28
+ Only scalar values (string/number/boolean) work as attributes (e.g. `placeholder`, `loading`, `theme`).
29
+
30
+ ## Two layers
31
+
32
+ **Layer 1 — batteries-included web components** (`import '@kitnai/chat/elements'`):
33
+ Drop an element into any framework (React, Vue, plain HTML). Data in via JS properties; interactions out via non-bubbling CustomEvents.
34
+
35
+ - `<kitn-chat>` — full chat UI (message list + prompt input). The primary starting point.
36
+ - `<kitn-conversation-list>` — sidebar conversation browser with group support.
37
+ - `<kitn-prompt-input>` — standalone composer with send button.
38
+
39
+ **Layer 2 — composable primitives** (`import { … } from '@kitnai/chat'`):
40
+ All 27 elements are also exported individually. Use them for custom layouts or features `<kitn-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
41
+
42
+ ## Key rules for the web components
43
+
44
+ 1. **Array/object data = JS properties** (see above). Scalars may be attributes.
45
+ 2. **Events are non-bubbling `CustomEvent`s** — listen directly on the element:
46
+ `chat.addEventListener('submit', (e) => console.log(e.detail.value))`
47
+ 3. **`theme` attribute** (`'light' | 'dark' | 'auto'`) works on every element. Default `auto` follows `prefers-color-scheme`.
48
+ 4. **Theming via CSS custom properties** — override `--kitn-color-*` tokens on `:root`; they pierce Shadow DOM.
49
+
50
+ ## ChatMessage schema (required for `<kitn-chat>`)
51
+
52
+ ```ts
53
+ interface ChatMessage {
54
+ id: string;
55
+ role: 'user' | 'assistant';
56
+ content: string;
57
+ reasoning?: { text: string; label?: string };
58
+ tools?: ToolPart[];
59
+ attachments?: AttachmentData[];
60
+ actions?: ('copy' | 'like' | 'dislike' | 'regenerate' | 'edit')[];
61
+ }
62
+ ```
63
+
64
+ ## Framework wiring
65
+
66
+ **Plain HTML / CDN**
67
+ ```html
68
+ <script type="module" src="https://unpkg.com/@kitnai/chat/elements"></script>
69
+ <kitn-chat style="display:block;height:100vh"></kitn-chat>
70
+ <script type="module">
71
+ const chat = document.querySelector('kitn-chat');
72
+ chat.messages = [];
73
+ </script>
74
+ ```
75
+
76
+ **React** — typed wrappers auto-set properties and expose `on<Event>` props:
77
+ ```tsx
78
+ import { KitnChat } from '@kitnai/chat/react';
79
+ <KitnChat messages={messages} onSubmit={(e) => send(e.detail.value)} />
80
+ ```
81
+
82
+ **Vue** — use the element directly; pass arrays via `.prop`:
83
+ ```vue
84
+ <kitn-chat :messages.prop="messages" @submit="send" />
85
+ ```
86
+
87
+ ## Theming
88
+
89
+ ```css
90
+ :root {
91
+ --kitn-color-background: #0f0f0f;
92
+ --kitn-color-primary: #7c3aed;
93
+ --kitn-color-muted: #1e1e1e;
94
+ }
95
+ ```
96
+
97
+ For plain HTML/CDN: `<link rel="stylesheet" href="…/@kitnai/chat/theme.tokens.css">`.
98
+ For Tailwind builds: `@import "@kitnai/chat/theme.css"` in your CSS.
99
+
100
+ ## Docs
101
+
102
+ - Full element reference (all 27 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
103
+ - Machine-readable Custom Elements Manifest: https://unpkg.com/@kitnai/chat/dist/custom-elements.json
104
+ - Working examples: https://github.com/kitn-ai/chat/tree/main/examples
105
+ - Storybook: https://storybook.kitn.dev
106
+ - Repository: https://github.com/kitn-ai/chat
107
+
108
+ ---
109
+
110
+ ## How to build a chat app in 5 steps
111
+
112
+ ### 1 — Install
113
+ ```bash
114
+ npm install @kitnai/chat
115
+ ```
116
+
117
+ ### 2 — Pick your layer
118
+ Drop-in: use `<kitn-chat>` for a full chat UI in one tag (`import '@kitnai/chat/elements'`).
119
+ Composable: combine `<kitn-message>`, `<kitn-prompt-input>`, `<kitn-reasoning>`, … in your own markup.
120
+
121
+ ### 3 — Handle `submit` and stream
122
+ ```js
123
+ import '@kitnai/chat/elements';
124
+ const chat = document.querySelector('kitn-chat');
125
+ chat.messages = [];
126
+
127
+ chat.addEventListener('submit', async (e) => {
128
+ const userText = e.detail.value;
129
+
130
+ // Append the user message (new array — see streaming note)
131
+ const history = [...chat.messages, { id: crypto.randomUUID(), role: 'user', content: userText }];
132
+ chat.messages = history;
133
+ chat.loading = true;
134
+
135
+ // Add an empty assistant placeholder to stream into
136
+ const aid = crypto.randomUUID();
137
+ chat.messages = [...history, { id: aid, role: 'assistant', content: '' }];
138
+
139
+ let answer = '';
140
+ for await (const token of streamFromYourAPI(history)) {
141
+ answer += token;
142
+ chat.messages = chat.messages.map((m) => (m.id === aid ? { ...m, content: answer } : m));
143
+ }
144
+ chat.loading = false;
145
+ });
146
+ ```
147
+
148
+ ### 4 — Wire optional features
149
+ - Reasoning: add `reasoning: { text: '…' }` to an assistant message.
150
+ - Tool calls: add `tools: [{ type: 'search', state: 'output-available', input: {…}, output: {…} }]`.
151
+ - Model switcher: `chat.models = [{ id: 'gpt-4o', name: 'GPT-4o' }]; chat.currentModel = 'gpt-4o';` — listen for `modelchange`.
152
+ - Token meter: `chat.context = { usedTokens: 1200, maxTokens: 128000 };`.
153
+ - History sidebar: add `<kitn-conversation-list>`; listen for `select` and `newchat`.
154
+
155
+ ### 5 — Theme
156
+ Override `--kitn-color-*` tokens on `:root` (they pierce Shadow DOM).
157
+
158
+ ---
159
+
160
+ ## Streaming recipe (critical)
161
+
162
+ To update messages while streaming, **reassign a NEW array containing a NEW message object** on every chunk. Mutating an existing message object in place will NOT trigger a re-render:
163
+
164
+ ```js
165
+ // ✅ re-renders
166
+ chat.messages = chat.messages.map((m) => (m.id === id ? { ...m, content: next } : m));
167
+
168
+ // ❌ does NOT re-render
169
+ chat.messages[i].content = next;
170
+ ```
171
+
172
+ The same rule applies to every array/object property (`models`, `context`, `suggestions`, …): replace, don't mutate.
173
+
174
+ ---
175
+
176
+ ## Element reference (27 elements, generated from custom-elements.json)
177
+
178
+ Every element also accepts the `theme` attribute. Array/object properties are marked with a `—` attribute: they must be set as JS properties.
179
+
180
+ ### `kitn-attachments` / `KitnAttachments`
181
+
182
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
183
+
184
+ | Property | Attribute | Type | Description |
185
+ |---|---|---|---|
186
+ | `items` | — | `{ id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]` | The attachments to render. Set as a JS property (array). |
187
+ | `variant` | `variant` | `undefined \| "grid" \| "inline" \| "list"` | Layout: `grid` = visual tiles, `inline` = icon + label chips, `list` = rows. |
188
+ | `hoverCard` | `hover-card` | `undefined \| false \| true` | Wrap each item in a hover card that previews its details. |
189
+ | `removable` | `removable` | `undefined \| false \| true` | Show a remove button per item; clicking it fires a `remove` event. |
190
+ | `showMediaType` | `show-media-type` | `undefined \| false \| true` | Also show the media type beneath the filename (non-grid variants). |
191
+ | `emptyText` | `empty-text` | `undefined \| string` | Text shown when `items` is empty. |
192
+
193
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
194
+
195
+ | Event | `detail` type | Description |
196
+ |---|---|---|
197
+ | `remove` | `CustomEvent<{ id: string }>` | A remove button was clicked. |
198
+
199
+ ---
200
+
201
+ ### `kitn-chain-of-thought` / `KitnChainOfThought`
202
+
203
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
204
+
205
+ | Property | Attribute | Type | Description |
206
+ |---|---|---|---|
207
+ | `steps` | — | `{ label: string; content?: undefined \| string }[]` | The reasoning steps. Set as a JS property. Compound sub-parts collapse to this one data model (Route 1). |
208
+
209
+ _No events._
210
+
211
+ ---
212
+
213
+ ### `kitn-chat` / `KitnChat`
214
+
215
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
216
+
217
+ | Property | Attribute | Type | Description |
218
+ |---|---|---|---|
219
+ | `messages` | — | `{ id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit")[] }[]` | 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 = [...]`). |
220
+ | `value` | `value` | `undefined \| string` | Controlled value of the input. When set, the host owns the input text and must update it on `valuechange`; leave unset for uncontrolled behavior. |
221
+ | `placeholder` | `placeholder` | `undefined \| string` | Placeholder text shown in the empty input. |
222
+ | `loading` | `loading` | `undefined \| false \| true` | When true, shows the loading/streaming state and disables submit (use while awaiting the assistant's reply). |
223
+ | `suggestions` | — | `undefined \| string[]` | Starter prompts shown above the input when the thread is empty. Clicking one follows `suggestionMode`. Set as a JS property. |
224
+ | `suggestionMode` | `suggestion-mode` | `undefined \| "submit" \| "fill"` | What clicking a suggestion does: `'submit'` (default) sends it immediately as if typed and submitted; `'fill'` just places it in the input. |
225
+ | `proseSize` | `prose-size` | `undefined \| "xs" \| "sm" \| "base" \| "lg"` | Body/prose font scale for rendered markdown (`'xs' \| 'sm' \| 'base' \| 'lg'`). Defaults to `'sm'`. |
226
+ | `codeTheme` | `code-theme` | `undefined \| string` | Shiki theme name for syntax-highlighted code blocks (e.g. `'github-dark-dimmed'`). |
227
+ | `codeHighlight` | `code-highlight` | `undefined \| false \| true` | Enable Shiki syntax highlighting in code blocks. Turn off to render plain `<pre>` blocks (lighter, no highlighter load). Default true. |
228
+ | `chatTitle` | `chat-title` | `undefined \| string` | Optional header title shown on the left of the header. |
229
+ | `models` | — | `undefined \| { id: string; name: string; provider?: undefined \| string }[]` | Optional model list. When set (>1 model) a ModelSwitcher is shown in the header and a `modelchange` event fires on selection. |
230
+ | `currentModel` | `current-model` | `undefined \| string` | The currently selected model id (pairs with `models`). |
231
+ | `context` | — | `undefined \| { usedTokens: number; maxTokens: number; inputTokens?: undefined \| number; outputTokens?: undefined \| number; estimatedCost?: undefined \| number }` | Optional context-window token usage. When set, a Context token meter is shown in the header. |
232
+ | `scrollButton` | `scroll-button` | `undefined \| false \| true` | Show the scroll-to-bottom button inside the scroll area. Default true. |
233
+ | `search` | `search` | `undefined \| false \| true` | Show a Search (Globe) button in the input toolbar; fires a `search` event. |
234
+ | `voice` | `voice` | `undefined \| false \| true` | Show a Voice (Mic) button in the input toolbar; fires a `voice` event. |
235
+ | `slashCommands` | — | `undefined \| { id: string; label: string; description?: undefined \| string; category?: undefined \| string }[]` | Slash commands — when set, typing `/` in the input opens the command palette and fires `slashselect`. Set as a JS property. |
236
+ | `slashActiveIds` | — | `undefined \| string[]` | Command ids to highlight as active in the palette. |
237
+ | `slashCompact` | `slash-compact` | `undefined \| false \| true` | Single-line palette rows. |
238
+
239
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
240
+
241
+ | Event | `detail` type | Description |
242
+ |---|---|---|
243
+ | `messageaction` | `CustomEvent<unknown>` | |
244
+ | `modelchange` | `CustomEvent<unknown>` | |
245
+ | `search` | `CustomEvent<unknown>` | |
246
+ | `slashselect` | `CustomEvent<unknown>` | |
247
+ | `submit` | `CustomEvent<unknown>` | |
248
+ | `suggestionclick` | `CustomEvent<unknown>` | |
249
+ | `valuechange` | `CustomEvent<unknown>` | |
250
+ | `voice` | `CustomEvent<unknown>` | |
251
+
252
+ ---
253
+
254
+ ### `kitn-chat-scope-picker` / `KitnChatScopePicker`
255
+
256
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
257
+
258
+ | Property | Attribute | Type | Description |
259
+ |---|---|---|---|
260
+ | `availableAuthors` | — | `string[]` | Authors to offer as scope filters. Set as a JS property. |
261
+ | `availableTags` | — | `string[]` | Tags to offer as scope filters. Set as a JS property. |
262
+ | `currentLabel` | `current-label` | `undefined \| string` | The label shown on the trigger for the active scope. |
263
+
264
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
265
+
266
+ | Event | `detail` type | Description |
267
+ |---|---|---|
268
+ | `scopechange` | `CustomEvent<{ filters: undefined \| { tags?: undefined \| string[]; authors?: undefined \| string[]; contentType?: undefined \| "transcript" \| "markdown"; dateRange?: undefined \| { from: string; to: string } } }>` | A scope was chosen (`undefined` filters = "All Content"). |
269
+
270
+ ---
271
+
272
+ ### `kitn-checkpoint` / `KitnCheckpoint`
273
+
274
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
275
+
276
+ | Property | Attribute | Type | Description |
277
+ |---|---|---|---|
278
+ | `label` | `label` | `undefined \| string` | Optional text beside the icon. |
279
+ | `tooltip` | `tooltip` | `undefined \| string` | Tooltip on hover. |
280
+ | `variant` | `variant` | `undefined \| "ghost" \| "default" \| "outline"` | Visual button style. |
281
+ | `size` | `size` | `undefined \| "sm" \| "lg" \| "md" \| "icon" \| "icon-sm"` | Button size (use an `icon*` size for an icon-only checkpoint). |
282
+
283
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
284
+
285
+ | Event | `detail` type | Description |
286
+ |---|---|---|
287
+ | `select` | `CustomEvent` | The checkpoint was clicked. |
288
+
289
+ ---
290
+
291
+ ### `kitn-code-block` / `KitnCodeBlock`
292
+
293
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
294
+
295
+ | Property | Attribute | Type | Description |
296
+ |---|---|---|---|
297
+ | `code` | `code` | `string` | The source code to render. |
298
+ | `language` | `language` | `undefined \| string` | Language grammar (e.g. `js`, `python`). Defaults to `tsx`. |
299
+ | `codeTheme` | `code-theme` | `undefined \| string` | Shiki theme name. |
300
+ | `codeHighlight` | `code-highlight` | `undefined \| false \| true` | Disable syntax highlighting (renders plain text, no Shiki). |
301
+ | `proseSize` | `prose-size` | `undefined \| "xs" \| "sm" \| "base" \| "lg"` | Code text sizing. |
302
+
303
+ _No events._
304
+
305
+ ---
306
+
307
+ ### `kitn-context-meter` / `KitnContextMeter`
308
+
309
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
310
+
311
+ | Property | Attribute | Type | Description |
312
+ |---|---|---|---|
313
+ | `context` | — | `undefined \| { usedTokens: number; maxTokens: number; inputTokens?: undefined \| number; outputTokens?: undefined \| number; reasoningTokens?: undefined \| number; cacheTokens?: undefined \| number; estimatedCost?: undefined \| number }` | Token-usage data. Set as a JS property. |
314
+
315
+ _No events._
316
+
317
+ ---
318
+
319
+ ### `kitn-conversation-list` / `KitnConversationList`
320
+
321
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
322
+
323
+ | Property | Attribute | Type | Description |
324
+ |---|---|---|---|
325
+ | `groups` | — | `{ id: string; userId?: undefined \| string; teamId?: undefined \| string; name: string; sortOrder: number; createdAt: string }[]` | 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. |
326
+ | `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 }[]` | A flat list of conversation summaries; the component buckets them by recency for you. Ignored when `groups` is provided. Set as a JS property. |
327
+ | `activeId` | `active-id` | `undefined \| string` | The id of the currently-open conversation, highlighted in the list. |
328
+
329
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
330
+
331
+ | Event | `detail` type | Description |
332
+ |---|---|---|
333
+ | `newchat` | `CustomEvent<unknown>` | |
334
+ | `select` | `CustomEvent<unknown>` | |
335
+ | `togglesidebar` | `CustomEvent<unknown>` | |
336
+
337
+ ---
338
+
339
+ ### `kitn-empty` / `KitnEmpty`
340
+
341
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
342
+
343
+ | Property | Attribute | Type | Description |
344
+ |---|---|---|---|
345
+ | `emptyTitle` | `empty-title` | `undefined \| string` | Title text. Attribute: `empty-title` (`title` is a global HTML attribute). |
346
+ | `description` | `description` | `undefined \| string` | Description text. |
347
+
348
+ _No events._
349
+
350
+ ---
351
+
352
+ ### `kitn-feedback-bar` / `KitnFeedbackBar`
353
+
354
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
355
+
356
+ | Property | Attribute | Type | Description |
357
+ |---|---|---|---|
358
+ | `barTitle` | `bar-title` | `undefined \| string` | The banner label (e.g. "Was this helpful?"). Attribute: `bar-title` (`title` is avoided — it's a global HTML attribute). |
359
+
360
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
361
+
362
+ | Event | `detail` type | Description |
363
+ |---|---|---|
364
+ | `close` | `CustomEvent` | The user dismissed the banner. |
365
+ | `helpful` | `CustomEvent` | The user clicked thumbs-up. |
366
+ | `nothelpful` | `CustomEvent` | The user clicked thumbs-down. |
367
+
368
+ ---
369
+
370
+ ### `kitn-file-upload` / `KitnFileUpload`
371
+
372
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
373
+
374
+ | Property | Attribute | Type | Description |
375
+ |---|---|---|---|
376
+ | `multiple` | `multiple` | `undefined \| false \| true` | Allow selecting multiple files (default true). |
377
+ | `accept` | `accept` | `undefined \| string` | `accept` attribute for the file picker (e.g. `image/*`). |
378
+ | `disabled` | `disabled` | `undefined \| false \| true` | Disable the dropzone — no clicking, no drag-and-drop. |
379
+ | `label` | `label` | `undefined \| string` | Default dropzone label (overridable via the default slot). |
380
+
381
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
382
+
383
+ | Event | `detail` type | Description |
384
+ |---|---|---|
385
+ | `filesadded` | `CustomEvent<{ files: File[] }>` | Files were picked or dropped. |
386
+
387
+ ---
388
+
389
+ ### `kitn-image` / `KitnImage`
390
+
391
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
392
+
393
+ | Property | Attribute | Type | Description |
394
+ |---|---|---|---|
395
+ | `base64` | `base64` | `undefined \| string` | Base64-encoded image data (pair with `media-type`). |
396
+ | `bytes` | — | `undefined \| Uint8Array<ArrayBufferLike>` | Raw image bytes (set as a JS property). |
397
+ | `alt` | `alt` | `undefined \| string` | Alt text. |
398
+ | `mediaType` | `media-type` | `undefined \| string` | MIME type (default `image/png`). |
399
+
400
+ _No events._
401
+
402
+ ---
403
+
404
+ ### `kitn-loader` / `KitnLoader`
405
+
406
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
407
+
408
+ | Property | Attribute | Type | Description |
409
+ |---|---|---|---|
410
+ | `variant` | `variant` | `undefined \| "circular" \| "classic" \| "pulse" \| "pulse-dot" \| "dots" \| "typing" \| "wave" \| "bars" \| "terminal" \| "text-blink" \| "text-shimmer" \| "loading-dots"` | The animation style: `'circular' \| 'classic' \| 'pulse' \| 'pulse-dot' \| 'dots' \| 'typing' \| 'wave' \| 'bars' \| 'terminal' \| 'text-blink' \| 'text-shimmer' \| 'loading-dots'`. Defaults to `'circular'`. |
411
+ | `size` | `size` | `undefined \| "sm" \| "lg" \| "md"` | Loader size: `'sm' \| 'md' \| 'lg'`. Defaults to `'md'`. |
412
+ | `text` | `text` | `undefined \| string` | Label for the text-based variants. |
413
+
414
+ _No events._
415
+
416
+ ---
417
+
418
+ ### `kitn-markdown` / `KitnMarkdown`
419
+
420
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
421
+
422
+ | Property | Attribute | Type | Description |
423
+ |---|---|---|---|
424
+ | `content` | `content` | `string` | The markdown source to render. |
425
+ | `proseSize` | `prose-size` | `undefined \| "xs" \| "sm" \| "base" \| "lg"` | Text/markdown sizing. |
426
+ | `codeTheme` | `code-theme` | `undefined \| string` | Shiki theme for fenced code blocks. |
427
+ | `codeHighlight` | `code-highlight` | `undefined \| false \| true` | Disable syntax highlighting (no Shiki loads). |
428
+
429
+ _No events._
430
+
431
+ ---
432
+
433
+ ### `kitn-message` / `KitnMessage`
434
+
435
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
436
+
437
+ | Property | Attribute | Type | Description |
438
+ |---|---|---|---|
439
+ | `message` | — | `undefined \| { id: string; role: "user" \| "assistant"; content: string; reasoning?: undefined \| { text: string; label?: undefined \| string }; tools?: undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }[]; attachments?: undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]; actions?: undefined \| ("copy" \| "like" \| "dislike" \| "regenerate" \| "edit")[] }` | The full message object. Set as a JS property. |
440
+ | `role` | `role` | `undefined \| "user" \| "assistant"` | Convenience for simple cases when not passing a `message` object. |
441
+ | `content` | `content` | `undefined \| string` | Convenience content (used when `message` is not set). |
442
+ | `markdown` | `markdown` | `undefined \| false \| true` | Force markdown on/off. Defaults to on for assistant, off for user. |
443
+ | `proseSize` | `prose-size` | `undefined \| "xs" \| "sm" \| "base" \| "lg"` | Text/markdown sizing for the message body. |
444
+ | `codeTheme` | `code-theme` | `undefined \| string` | Shiki theme name used for fenced code blocks in the content. |
445
+ | `codeHighlight` | `code-highlight` | `undefined \| false \| true` | Disable syntax highlighting for code blocks (no Shiki loads). |
446
+
447
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
448
+
449
+ | Event | `detail` type | Description |
450
+ |---|---|---|
451
+ | `messageaction` | `CustomEvent<{ messageId: string; action: "copy" \| "like" \| "dislike" \| "regenerate" \| "edit" }>` | An action button was clicked. |
452
+
453
+ ---
454
+
455
+ ### `kitn-message-skills` / `KitnMessageSkills`
456
+
457
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
458
+
459
+ | Property | Attribute | Type | Description |
460
+ |---|---|---|---|
461
+ | `skills` | — | `{ id: string; name: string }[]` | The active skills to badge. Set as a JS property. |
462
+
463
+ _No events._
464
+
465
+ ---
466
+
467
+ ### `kitn-model-switcher` / `KitnModelSwitcher`
468
+
469
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
470
+
471
+ | Property | Attribute | Type | Description |
472
+ |---|---|---|---|
473
+ | `models` | — | `{ id: string; name: string; provider?: undefined \| string }[]` | The selectable models. Set as a JS property (array). |
474
+ | `currentModel` | `current-model` | `undefined \| string` | The currently-selected model id. Defaults to the first model. |
475
+
476
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
477
+
478
+ | Event | `detail` type | Description |
479
+ |---|---|---|
480
+ | `modelchange` | `CustomEvent<{ modelId: string }>` | A model was selected. |
481
+
482
+ ---
483
+
484
+ ### `kitn-prompt-input` / `KitnPromptInput`
485
+
486
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
487
+
488
+ | Property | Attribute | Type | Description |
489
+ |---|---|---|---|
490
+ | `value` | `value` | `undefined \| string` | Controlled value of the input. When set, the host owns the text and must update it on `valuechange`; leave unset for uncontrolled behavior. |
491
+ | `placeholder` | `placeholder` | `undefined \| string` | Placeholder text shown in the empty input. |
492
+ | `disabled` | `disabled` | `undefined \| false \| true` | Disable the input and submit button entirely (non-interactive). |
493
+ | `loading` | `loading` | `undefined \| false \| true` | Show the loading/streaming state and block submit (use while awaiting a reply). |
494
+ | `suggestions` | — | `undefined \| string[]` | Starter prompts shown above the input. Clicking one follows `suggestionMode`. Set as a JS property. |
495
+ | `suggestionMode` | `suggestion-mode` | `undefined \| "submit" \| "fill"` | What clicking a suggestion does: `'submit'` (default) sends it immediately as if typed and submitted; `'fill'` just places it in the input. |
496
+ | `slashCommands` | — | `undefined \| { id: string; label: string; description?: undefined \| string; category?: undefined \| string }[]` | Slash commands — when set, typing `/` opens the command palette. Set as a JS property. |
497
+ | `slashActiveIds` | — | `undefined \| string[]` | Command ids to highlight as active. |
498
+ | `slashCompact` | `slash-compact` | `undefined \| false \| true` | Single-line palette rows. |
499
+ | `search` | `search` | `undefined \| false \| true` | Show a Search (Globe) button in the left toolbar; clicking it fires a `search` event. |
500
+ | `voice` | `voice` | `undefined \| false \| true` | Show a Voice (Mic) button in the left toolbar; clicking it fires a `voice` event. |
501
+ | `attachments` | — | `undefined \| { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[]` | 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). |
502
+
503
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
504
+
505
+ | Event | `detail` type | Description |
506
+ |---|---|---|
507
+ | `search` | `CustomEvent<undefined>` | The Search (Globe) toolbar button was clicked. |
508
+ | `slashselect` | `CustomEvent<{ command: { id: string; label: string; description?: undefined \| string; category?: undefined \| string } }>` | A slash command was chosen from the palette. |
509
+ | `submit` | `CustomEvent<{ value: string; attachments: { id: string; type: "file" \| "source-document"; filename?: undefined \| string; mediaType?: undefined \| string; url?: undefined \| string; title?: undefined \| string }[] }>` | The user submitted the prompt (Enter or send button) with its attachments. |
510
+ | `suggestionclick` | `CustomEvent<{ value: string }>` | A suggestion was clicked while `suggestion-mode="fill"`. |
511
+ | `valuechange` | `CustomEvent<{ value: string }>` | The input text changed (fires on every keystroke). |
512
+ | `voice` | `CustomEvent<undefined>` | The Voice (Mic) toolbar button was clicked. |
513
+
514
+ ---
515
+
516
+ ### `kitn-prompt-suggestions` / `KitnPromptSuggestions`
517
+
518
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
519
+
520
+ | Property | Attribute | Type | Description |
521
+ |---|---|---|---|
522
+ | `suggestions` | — | `(string \| { label: string; value?: undefined \| string })[]` | The suggestions. Strings, or `{ label, value }` when the displayed text and the emitted value differ. Set as a JS property. |
523
+ | `variant` | `variant` | `undefined \| "ghost" \| "default" \| "outline"` | Chip style: `'outline'` (default), `'ghost'`, or `'default'` (filled). |
524
+ | `size` | `size` | `undefined \| "sm" \| "lg" \| "md" \| "icon" \| "icon-sm"` | Size preset for each chip. Defaults to the pill default (`'lg'`); pass `'sm'` for smaller pills (or `'md'`). |
525
+ | `block` | `block` | `undefined \| false \| true` | Full-width left-aligned rows instead of pills. |
526
+ | `highlight` | `highlight` | `undefined \| string` | Substring to highlight within each suggestion. |
527
+
528
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
529
+
530
+ | Event | `detail` type | Description |
531
+ |---|---|---|
532
+ | `select` | `CustomEvent<{ value: string }>` | A suggestion was clicked. |
533
+
534
+ ---
535
+
536
+ ### `kitn-reasoning` / `KitnReasoning`
537
+
538
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
539
+
540
+ | Property | Attribute | Type | Description |
541
+ |---|---|---|---|
542
+ | `text` | `text` | `string` | The reasoning text to display. |
543
+ | `label` | `label` | `undefined \| string` | Trigger label. |
544
+ | `open` | `open` | `undefined \| false \| true` | Controlled open state — set as a property (`el.open = true`). Omit for uncontrolled (the trigger toggles it). |
545
+ | `streaming` | `streaming` | `undefined \| false \| true` | While true, auto-expands (and re-collapses when it flips false). |
546
+ | `markdown` | `markdown` | `undefined \| false \| true` | Render `text` as markdown. |
547
+
548
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
549
+
550
+ | Event | `detail` type | Description |
551
+ |---|---|---|
552
+ | `openchange` | `CustomEvent<{ open: false \| true }>` | Open state changed (via the trigger or streaming auto-open). |
553
+
554
+ ---
555
+
556
+ ### `kitn-response-stream` / `KitnResponseStream`
557
+
558
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
559
+
560
+ | Property | Attribute | Type | Description |
561
+ |---|---|---|---|
562
+ | `text` | — | `undefined \| string \| AsyncIterable<string>` | Text to stream. A string, or an `AsyncIterable<string>` (set as a JS property — async iterables can't be HTML attributes). |
563
+ | `mode` | `mode` | `undefined \| "typewriter" \| "fade"` | Reveal animation. |
564
+ | `speed` | `speed` | `undefined \| number` | Characters/segments per tick. |
565
+ | `as` | `as` | `undefined \| string` | Element tag to render as. |
566
+
567
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
568
+
569
+ | Event | `detail` type | Description |
570
+ |---|---|---|
571
+ | `complete` | `CustomEvent` | Streaming finished. |
572
+
573
+ ---
574
+
575
+ ### `kitn-source` / `KitnSource`
576
+
577
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
578
+
579
+ | Property | Attribute | Type | Description |
580
+ |---|---|---|---|
581
+ | `href` | `href` | `undefined \| string` | The URL this citation links to (the domain also seeds the default label/favicon). |
582
+ | `label` | `label` | `undefined \| string` | Trigger label (defaults to the domain). |
583
+ | `headline` | `headline` | `undefined \| string` | Hover-card headline. Attribute: `headline` (`title` is avoided — it's a global HTML attribute that reflects in a CE constructor and breaks it). |
584
+ | `description` | `description` | `undefined \| string` | Hover-card body text describing the source. |
585
+ | `showFavicon` | `show-favicon` | `undefined \| false \| true` | Show the source's favicon next to the trigger label. |
586
+
587
+ _No events._
588
+
589
+ ---
590
+
591
+ ### `kitn-source-list` / `KitnSourceList`
592
+
593
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
594
+
595
+ | Property | Attribute | Type | Description |
596
+ |---|---|---|---|
597
+ | `sources` | — | `{ href: string; title?: undefined \| string; description?: undefined \| string; label?: undefined \| string; showFavicon?: undefined \| false \| true }[]` | The sources to render. Set as a JS property. |
598
+ | `showFavicon` | `show-favicon` | `undefined \| false \| true` | Show favicons on all items (per-item `showFavicon` overrides). |
599
+
600
+ _No events._
601
+
602
+ ---
603
+
604
+ ### `kitn-text-shimmer` / `KitnTextShimmer`
605
+
606
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
607
+
608
+ | Property | Attribute | Type | Description |
609
+ |---|---|---|---|
610
+ | `text` | `text` | `undefined \| string` | The text to shimmer. |
611
+ | `as` | `as` | `undefined \| string` | Element tag to render as (default `span`). |
612
+ | `duration` | `duration` | `undefined \| number` | Animation duration in seconds. |
613
+ | `spread` | `spread` | `undefined \| number` | Gradient spread (5–45). |
614
+
615
+ _No events._
616
+
617
+ ---
618
+
619
+ ### `kitn-thinking-bar` / `KitnThinkingBar`
620
+
621
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
622
+
623
+ | Property | Attribute | Type | Description |
624
+ |---|---|---|---|
625
+ | `text` | `text` | `undefined \| string` | The shimmering label, e.g. "Thinking…". |
626
+ | `stoppable` | `stoppable` | `undefined \| false \| true` | When true, show a "stop" affordance that fires a `stop` event. |
627
+ | `stopLabel` | `stop-label` | `undefined \| string` | Label for the stop affordance. |
628
+
629
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
630
+
631
+ | Event | `detail` type | Description |
632
+ |---|---|---|
633
+ | `stop` | `CustomEvent` | The "stop / answer now" affordance was clicked. |
634
+
635
+ ---
636
+
637
+ ### `kitn-tool` / `KitnTool`
638
+
639
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
640
+
641
+ | Property | Attribute | Type | Description |
642
+ |---|---|---|---|
643
+ | `tool` | — | `undefined \| { type: string; state: "input-streaming" \| "input-available" \| "output-available" \| "output-error"; input?: undefined \| Record<string, unknown>; output?: undefined \| Record<string, unknown>; toolCallId?: undefined \| string; errorText?: undefined \| string }` | The tool-call to display. Set as a JS property. |
644
+ | `open` | `open` | `undefined \| false \| true` | Start expanded. |
645
+
646
+ _No events._
647
+
648
+ ---
649
+
650
+ ### `kitn-voice-input` / `KitnVoiceInput`
651
+
652
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
653
+
654
+ | Property | Attribute | Type | Description |
655
+ |---|---|---|---|
656
+ | `transcribe` | — | `undefined \| (audio: Blob) => Promise<string>` | Transcriber the host supplies — records audio, returns the text. This is a **function-valued property** (`el.transcribe = async blob => '...'`) because a value-returning callback can't be modelled as a fire-and-forget event. |
657
+ | `disabled` | `disabled` | `undefined \| false \| true` | Disable the mic button (non-interactive). |
658
+
659
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
660
+
661
+ | Event | `detail` type | Description |
662
+ |---|---|---|
663
+ | `audiocaptured` | `CustomEvent<{ blob: Blob }>` | Raw audio captured (before transcription) — for hosts that prefer to handle transcription themselves instead of via the `transcribe` property. |
664
+ | `transcription` | `CustomEvent<{ text: string }>` | Transcription completed (the `transcribe` property resolved). |
665
+
666
+ ---
667
+