@kitn.ai/ui 0.18.2 → 0.19.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 (201) hide show
  1. package/dist/components/thread.d.ts +54 -0
  2. package/dist/custom-elements.json +195 -0
  3. package/dist/elements/agent-card.js +1 -1
  4. package/dist/elements/artifact.js +1 -1
  5. package/dist/elements/attachments.js +1 -1
  6. package/dist/elements/autoloader.js +1 -1
  7. package/dist/elements/avatar.js +1 -1
  8. package/dist/elements/badge.js +1 -1
  9. package/dist/elements/button.js +1 -1
  10. package/dist/elements/card.js +1 -1
  11. package/dist/elements/cards.js +1 -1
  12. package/dist/elements/chain-of-thought.js +1 -1
  13. package/dist/elements/chat-scope-picker.js +1 -1
  14. package/dist/elements/chat-workspace.js +1 -1
  15. package/dist/elements/chat.js +1 -1
  16. package/dist/elements/checkpoint.js +1 -1
  17. package/dist/elements/choice.js +1 -1
  18. package/dist/elements/chunks/{Icon-C2LTALdM.js → Icon-11SRdjJ4.js} +1 -1
  19. package/dist/elements/chunks/action-icons-CtRg17uX.js +1 -0
  20. package/dist/elements/chunks/arrow-left-CifsGq8x.js +1 -0
  21. package/dist/elements/chunks/{attachments-DLJcWCDV.js → attachments-CBqQRh60.js} +1 -1
  22. package/dist/elements/chunks/{badge-BTNZTODL.js → badge-CxklEXQm.js} +1 -1
  23. package/dist/elements/chunks/{button-DBDZebGr.js → button-BD7lUvVB.js} +1 -1
  24. package/dist/elements/chunks/{card-YfCyI4fH.js → card-B-PRGXdj.js} +1 -1
  25. package/dist/elements/chunks/chat-thread-DIZbRIKG.js +1 -0
  26. package/dist/elements/chunks/check-CUKS495w.js +1 -0
  27. package/dist/elements/chunks/chevron-down-AELmYT1j.js +1 -0
  28. package/dist/elements/chunks/chevron-right-C8g26oKh.js +1 -0
  29. package/dist/elements/chunks/circle-DGcI8Cft.js +1 -0
  30. package/dist/elements/chunks/circle-check-DuU0IcBQ.js +1 -0
  31. package/dist/elements/chunks/{circle-x-pDtzlghQ.js → circle-x-mtjCO_Ok.js} +1 -1
  32. package/dist/elements/chunks/{code-block-DZ6mz6vs.js → code-block-BeWVttmU.js} +1 -1
  33. package/dist/elements/chunks/{collapsible-CWUAShMC.js → collapsible-DGjADCN6.js} +1 -1
  34. package/dist/elements/chunks/{composer-BZyPU6gD.js → composer-CavJww3d.js} +7 -3
  35. package/dist/elements/chunks/{context-Cx6eQA_G.js → context-CnlsNJSJ.js} +1 -1
  36. package/dist/elements/chunks/{conversation-list-C4xTQSpT.js → conversation-list-5O_KdI_I.js} +1 -1
  37. package/dist/elements/chunks/{default-input-BZcwyKcP.js → default-input-CB46cJJ1.js} +1 -1
  38. package/dist/elements/chunks/{define-CNSKFZCd.js → define-DfTe4zwZ.js} +1 -1
  39. package/dist/elements/chunks/{disclosure-BcBs--Jf.js → disclosure-BtFK3a-M.js} +1 -1
  40. package/dist/elements/chunks/{download-BDQwcFav.js → download-qJv1dS3M.js} +1 -1
  41. package/dist/elements/chunks/{dropdown-wgs8xCJZ.js → dropdown-UhtAueYR.js} +1 -1
  42. package/dist/elements/chunks/{ellipsis-CUiEJ6R1.js → ellipsis-B1sOOqiJ.js} +1 -1
  43. package/dist/elements/chunks/{external-link-DJUmC7g2.js → external-link-DToP_VKE.js} +1 -1
  44. package/dist/elements/chunks/{file-text-DOYfYvrh.js → file-text-BwUs_Pj4.js} +1 -1
  45. package/dist/elements/chunks/{file-tree-DQzNQrbr.js → file-tree-C6RhmSnX.js} +1 -1
  46. package/dist/elements/chunks/{folder-DBDUBANz.js → folder-H_Xp0GYP.js} +1 -1
  47. package/dist/elements/chunks/hover-card-Dn3yrk1l.js +1 -0
  48. package/dist/elements/chunks/icon-BrxJQXzC.js +1 -0
  49. package/dist/elements/chunks/{info-DBQl-m6e.js → info-11eT2q5H.js} +1 -1
  50. package/dist/elements/chunks/{input-DZD67EvW.js → input-B9oZKDfb.js} +1 -1
  51. package/dist/elements/chunks/{kbd-DbyVrlnU.js → kbd-D2fx3rWh.js} +1 -1
  52. package/dist/elements/chunks/{link-vko7AttA.js → link-B-RNYWNw.js} +1 -1
  53. package/dist/elements/chunks/{loader-Cg6rO8tQ.js → loader-BJh_aRlp.js} +1 -1
  54. package/dist/elements/chunks/{markdown-n3Xbj3PR.js → markdown-BIpjrDFv.js} +1 -1
  55. package/dist/elements/chunks/{message-CgKytiSB.js → message-CPfqj8Gi.js} +1 -1
  56. package/dist/elements/chunks/{message-feedback-Ds3-US0e.js → message-feedback-8uj0aVYh.js} +1 -1
  57. package/dist/elements/chunks/message-square-CCSQ4M9g.js +1 -0
  58. package/dist/elements/chunks/{minimize-2-3kCdE0q3.js → minimize-2-C9qkiTJg.js} +1 -1
  59. package/dist/elements/chunks/{model-switcher-BMtXGwLU.js → model-switcher-DRrMcRXH.js} +1 -1
  60. package/dist/elements/chunks/{overlay-B1-MBI6h.js → overlay-C8_FUL8q.js} +1 -1
  61. package/dist/elements/chunks/{paperclip-DDEfmkHc.js → paperclip-MA9hxLhW.js} +1 -1
  62. package/dist/elements/chunks/{progress-bar-Dwbiyv3s.js → progress-bar-y5G6HDjg.js} +1 -1
  63. package/dist/elements/chunks/{prompt-suggestion-9lvgFcEa.js → prompt-suggestion-LalWvCJy.js} +1 -1
  64. package/dist/elements/chunks/reasoning-CW3SDdb4.js +1 -0
  65. package/dist/elements/chunks/resizable-xhYF5lCQ.js +1 -0
  66. package/dist/elements/chunks/{rotate-cw-jpisOdOV.js → rotate-cw-2ndEXjgS.js} +1 -1
  67. package/dist/elements/chunks/{scroll-area-g5Ze3K6f.js → scroll-area-BzOPDXrZ.js} +1 -1
  68. package/dist/elements/chunks/scroll-button-B1x4cYqM.js +1 -0
  69. package/dist/elements/chunks/{separator-Bmjc5XyX.js → separator-CPvL5Xdl.js} +1 -1
  70. package/dist/elements/chunks/{settings-group-9imY3kRA.js → settings-group-BiIym17O.js} +1 -1
  71. package/dist/elements/chunks/{settings-Cz1bMJP9.js → settings-hmzIuNXD.js} +1 -1
  72. package/dist/elements/chunks/{share-BdenF0wQ.js → share-BbziTAzn.js} +1 -1
  73. package/dist/elements/chunks/skeleton-Bxhs1thL.js +1 -0
  74. package/dist/elements/chunks/{slots-DkZ-Cmha.js → slots--V19HwUb.js} +1 -1
  75. package/dist/elements/chunks/{star-DY6z1UUH.js → star-BHL3Va5p.js} +1 -1
  76. package/dist/elements/chunks/{store-th4VyJXM.js → store-tpnnWlxY.js} +1 -1
  77. package/dist/elements/chunks/{text-shimmer-CEi-tlXr.js → text-shimmer-1DCKivKx.js} +1 -1
  78. package/dist/elements/chunks/textarea-Czaowo9F.js +1 -0
  79. package/dist/elements/chunks/{thumbs-up-BR33KLfA.js → thumbs-up-CdLqA13R.js} +1 -1
  80. package/dist/elements/chunks/{toast-store-BEMda0fv.js → toast-store-BvBquUFA.js} +1 -1
  81. package/dist/elements/chunks/{tool-TMued3WO.js → tool-4P_ne8Go.js} +1 -1
  82. package/dist/elements/chunks/{tooltip-Cft_Rxiw.js → tooltip-CBeFqJKk.js} +1 -1
  83. package/dist/elements/chunks/{triangle-alert-B07fX3Q8.js → triangle-alert-BllqxXq8.js} +1 -1
  84. package/dist/elements/chunks/{use-card-resolution-M36zVciB.js → use-card-resolution-73xiddIW.js} +1 -1
  85. package/dist/elements/chunks/{video-MKp3LmNT.js → video-O9rA6k7S.js} +1 -1
  86. package/dist/elements/chunks/x-DeS3rQhx.js +1 -0
  87. package/dist/elements/coachmark.js +1 -1
  88. package/dist/elements/code-block.js +1 -1
  89. package/dist/elements/command.js +1 -1
  90. package/dist/elements/compare.js +1 -1
  91. package/dist/elements/composer.js +1 -1
  92. package/dist/elements/confirm-card.js +1 -1
  93. package/dist/elements/context-meter.js +1 -1
  94. package/dist/elements/conversation-list.js +1 -1
  95. package/dist/elements/dialog.js +1 -1
  96. package/dist/elements/editable-label.js +1 -1
  97. package/dist/elements/embed.js +1 -1
  98. package/dist/elements/empty.js +1 -1
  99. package/dist/elements/feedback-bar.js +1 -1
  100. package/dist/elements/file-tree.js +1 -1
  101. package/dist/elements/file-upload.js +1 -1
  102. package/dist/elements/form.js +1 -1
  103. package/dist/elements/hover-card.js +1 -1
  104. package/dist/elements/icon.js +1 -1
  105. package/dist/elements/image.js +1 -1
  106. package/dist/elements/input.js +1 -1
  107. package/dist/elements/kbd.js +1 -1
  108. package/dist/elements/link-preview.js +1 -1
  109. package/dist/elements/loader.js +1 -1
  110. package/dist/elements/markdown.js +1 -1
  111. package/dist/elements/menu.js +1 -1
  112. package/dist/elements/message-skills.js +1 -1
  113. package/dist/elements/message.js +1 -1
  114. package/dist/elements/model-switcher.js +1 -1
  115. package/dist/elements/nav.js +1 -1
  116. package/dist/elements/notice.js +1 -1
  117. package/dist/elements/pane-group.js +1 -1
  118. package/dist/elements/pane.js +1 -1
  119. package/dist/elements/popover.js +1 -1
  120. package/dist/elements/progress-bar.js +1 -1
  121. package/dist/elements/prompt-dock.js +1 -1
  122. package/dist/elements/prompt-input.js +1 -1
  123. package/dist/elements/prompt-suggestions.js +1 -1
  124. package/dist/elements/reasoning.js +1 -1
  125. package/dist/elements/remote.js +1 -1
  126. package/dist/elements/resizable.js +1 -1
  127. package/dist/elements/response-stream.js +1 -1
  128. package/dist/elements/screen.js +1 -1
  129. package/dist/elements/scroll-area.js +1 -1
  130. package/dist/elements/scroll-button.js +1 -1
  131. package/dist/elements/search.js +1 -1
  132. package/dist/elements/segmented.js +1 -1
  133. package/dist/elements/separator.js +1 -1
  134. package/dist/elements/setting-item.js +1 -1
  135. package/dist/elements/settings-group.js +1 -1
  136. package/dist/elements/skeleton.js +1 -1
  137. package/dist/elements/slots.d.ts +3 -0
  138. package/dist/elements/source.js +1 -1
  139. package/dist/elements/status.js +1 -1
  140. package/dist/elements/switch.js +1 -1
  141. package/dist/elements/tabs.js +1 -1
  142. package/dist/elements/tasks.js +1 -1
  143. package/dist/elements/text-shimmer.js +1 -1
  144. package/dist/elements/thinking-bar.js +1 -1
  145. package/dist/elements/thread.d.ts +1 -0
  146. package/dist/elements/thread.js +1 -0
  147. package/dist/elements/toast.js +1 -1
  148. package/dist/elements/tool.js +1 -1
  149. package/dist/elements/tooltip.js +1 -1
  150. package/dist/elements/voice-input.js +1 -1
  151. package/dist/elements/voice-output.js +1 -1
  152. package/dist/elements.d.ts +24 -0
  153. package/dist/index.js +3393 -3311
  154. package/dist/kai.es.js +1 -1
  155. package/dist/llms/llms-full.txt +34 -4
  156. package/dist/llms/llms.txt +3 -3
  157. package/dist/react/index.d.ts +64 -0
  158. package/dist/react/use-voice-input.d.ts +15 -0
  159. package/dist/react.js +263 -240
  160. package/dist/register-impl-CaaHJcea.js +145 -0
  161. package/dist/ui/resizable.d.ts +9 -3
  162. package/frameworks/react/index.tsx +32 -1
  163. package/frameworks/react/use-voice-input.tsx +59 -0
  164. package/llms-full.txt +34 -4
  165. package/llms.txt +3 -3
  166. package/package.json +27 -5
  167. package/src/components/component-meta.json +30 -28
  168. package/src/components/composer.tsx +5 -0
  169. package/src/components/thread.tsx +177 -0
  170. package/src/elements/chat-workspace.tsx +1 -1
  171. package/src/elements/compiled.css +1 -1
  172. package/src/elements/element-manifest.json +4 -0
  173. package/src/elements/element-meta.json +117 -0
  174. package/src/elements/element-types.d.ts +24 -0
  175. package/src/elements/icon-names.json +2 -0
  176. package/src/elements/menu.tsx +7 -4
  177. package/src/elements/register-impl.ts +2 -0
  178. package/src/elements/resizable.tsx +78 -2
  179. package/src/elements/slots.ts +7 -0
  180. package/src/elements/thread.tsx +105 -0
  181. package/src/ui/action-icons.ts +2 -1
  182. package/src/ui/icon.tsx +4 -0
  183. package/src/ui/overlay.tsx +8 -1
  184. package/src/ui/resizable.tsx +47 -9
  185. package/dist/elements/chunks/action-icons-Dtl8Ox5D.js +0 -1
  186. package/dist/elements/chunks/arrow-left-GbBceGBE.js +0 -1
  187. package/dist/elements/chunks/chat-thread-Dz2qbzvI.js +0 -1
  188. package/dist/elements/chunks/check-fhmRksq_.js +0 -1
  189. package/dist/elements/chunks/chevron-down-DcRg1aRU.js +0 -1
  190. package/dist/elements/chunks/chevron-right-ChzBcNJ-.js +0 -1
  191. package/dist/elements/chunks/circle-B4fTe9v6.js +0 -1
  192. package/dist/elements/chunks/circle-check-CJV-3Rem.js +0 -1
  193. package/dist/elements/chunks/hover-card-BQGdGAQ3.js +0 -1
  194. package/dist/elements/chunks/icon-CAyRqVrg.js +0 -1
  195. package/dist/elements/chunks/message-square-MmRkvc-M.js +0 -1
  196. package/dist/elements/chunks/reasoning-DzHWsdAJ.js +0 -1
  197. package/dist/elements/chunks/resizable-Bq_eHxUm.js +0 -1
  198. package/dist/elements/chunks/skeleton-Pjc5jiaY.js +0 -1
  199. package/dist/elements/chunks/textarea-CboigarR.js +0 -1
  200. package/dist/elements/chunks/x-Ckwicf6g.js +0 -1
  201. package/dist/register-impl-DcjZDELj.js +0 -141
@@ -52,7 +52,13 @@ export interface ResizablePanelProps extends JSX.HTMLAttributes<HTMLDivElement>
52
52
  }
53
53
  declare function ResizablePanel(props: ResizablePanelProps): JSX.Element;
54
54
  export interface ResizableHandleProps extends JSX.HTMLAttributes<HTMLDivElement> {
55
- withHandle?: boolean;
55
+ /**
56
+ * Divider affordance drawn inside the 8px grab zone:
57
+ * - `line` (default) — a 1px hairline, transparent at rest, tinting on hover/drag.
58
+ * - `grip` — a dotted grip handle.
59
+ * - `none` — no visible divider (invisible hit-area only).
60
+ */
61
+ handle?: 'line' | 'grip' | 'none';
56
62
  onPanelResize?: (delta: number) => void;
57
63
  /** Keyboard nudge step in pixels (default 16). Home/End jump to min/max. */
58
64
  keyboardStep?: number;
@@ -67,8 +73,8 @@ export interface ResizableProps {
67
73
  orientation?: Orientation;
68
74
  /** Fired on drag-end / keyboard resize / visibility change with the current panel sizes (percent). */
69
75
  onChange?: (sizes: number[]) => void;
70
- /** Show a visible grip on each interactive handle. */
71
- withHandle?: boolean;
76
+ /** Divider affordance on each interactive handle: `line` (default), `grip`, or `none`. */
77
+ handle?: 'line' | 'grip' | 'none';
72
78
  class?: string;
73
79
  /** Which panel index is maximized (null = none). Hides the others. */
74
80
  maximizedIndex?: number | null;
@@ -11,6 +11,7 @@ import { createWebComponent, registerAll, type WebComponentProps } from './runti
11
11
  export { registerAll };
12
12
  export { useKaiChat } from './use-kai-chat';
13
13
  export type { UseKaiChatOptions, KaiChatController, ChatMessage } from './use-kai-chat';
14
+ export { useVoiceInput } from './use-voice-input';
14
15
 
15
16
 
16
17
  export interface AgentCardProps extends WebComponentProps {
@@ -1250,6 +1251,8 @@ export interface ResizableProps extends WebComponentProps {
1250
1251
  orientation?: "vertical" | "horizontal";
1251
1252
  /** Which item index is maximized (null = none). Declarative source of truth. */
1252
1253
  maximizedIndex?: null | number;
1254
+ /** Divider affordance drawn inside each draggable handle's 8px grab zone: - `line` (default) — a 1px hairline, transparent at rest, tinting on hover/drag. - `grip` — a dotted grip handle. - `none` — no visible divider, just the invisible hit-area. The full grab zone and keyboard/ARIA behavior are identical for all three. */
1255
+ handle?: "none" | "line" | "grip";
1253
1256
  /** Fired on drag-end / keyboard resize / visibility change. `detail.sizes` = panel sizes in percent. */
1254
1257
  onChange?: (event: CustomEvent<{ sizes: number[] }>) => void;
1255
1258
  /** Observe layout maximize state. */
@@ -1258,7 +1261,7 @@ export interface ResizableProps extends WebComponentProps {
1258
1261
 
1259
1262
  export const Resizable = /*#__PURE__*/ createWebComponent<ResizableProps>(
1260
1263
  'kai-resizable',
1261
- ["theme","orientation","maximizedIndex"],
1264
+ ["theme","orientation","maximizedIndex","handle"],
1262
1265
  { onChange: 'kai-change', onMaximizeChange: 'kai-maximize-change' },
1263
1266
  () => import('@kitn.ai/ui/elements/resizable'),
1264
1267
  );
@@ -1693,6 +1696,34 @@ export const ThinkingBar = /*#__PURE__*/ createWebComponent<ThinkingBarProps>(
1693
1696
  () => import('@kitn.ai/ui/elements/thinking-bar'),
1694
1697
  );
1695
1698
 
1699
+ export interface ThreadProps extends WebComponentProps {
1700
+ /** The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions/avatar. Set as a JS property (`el.messages = [...]`); a NEW array reference per streaming chunk re-renders (mutating in place does not). */
1701
+ messages?: { id: string; role: "user" | "assistant"; content: string; reasoning?: { text: string; label?: string }; tools?: { type: string; state: "input-streaming" | "input-available" | "output-available" | "output-error"; input?: Record<string, unknown>; output?: Record<string, unknown>; toolCallId?: string; errorText?: string }[]; attachments?: { id: string; type: "file" | "source-document"; filename?: string; mediaType?: string; url?: string; title?: string }[]; actions?: ("copy" | "like" | "dislike" | "regenerate" | "edit" | { id: string; label: string; icon?: string; tooltip?: string })[]; avatar?: { src?: string; fallback?: string; alt?: string }; feedback?: "like" | "dislike" }[];
1702
+ /** Show a typing indicator on the pending assistant turn — set while awaiting the assistant's reply. */
1703
+ loading?: boolean;
1704
+ /** Body/prose font scale for rendered markdown (`'xs' | 'sm' | 'base' | 'lg'`). Defaults to `'sm'`. */
1705
+ proseSize?: "sm" | "lg" | "xs" | "base";
1706
+ /** Shiki theme name for syntax-highlighted code blocks (e.g. `'github-dark-dimmed'`). */
1707
+ codeTheme?: string;
1708
+ /** Enable Shiki syntax highlighting in code blocks. Turn off to render plain `<pre>` blocks (lighter, no highlighter load). Default true. */
1709
+ codeHighlight?: boolean;
1710
+ /** Whether each message's action bar is always visible (`'always'`, default) or only revealed on hover of that message row (`'hover'`). */
1711
+ actionsReveal?: "always" | "hover";
1712
+ /** Show the scroll-to-bottom button inside the scroll area. Default true. */
1713
+ scrollButton?: boolean;
1714
+ /** Extra classes applied to the thread's inner root. */
1715
+ class?: string;
1716
+ /** A message's action button was clicked. `action` is the built-in name (`copy` / `like` / `dislike` / `regenerate` / `edit`) or a custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. */
1717
+ onMessageAction?: (event: CustomEvent<{ messageId: string; action: string; state?: undefined | "on" | "off" }>) => void;
1718
+ }
1719
+
1720
+ export const Thread = /*#__PURE__*/ createWebComponent<ThreadProps>(
1721
+ 'kai-thread',
1722
+ ["theme","messages","loading","proseSize","codeTheme","codeHighlight","actionsReveal","scrollButton","class"],
1723
+ { onMessageAction: 'kai-message-action' },
1724
+ () => import('@kitn.ai/ui/elements/thread'),
1725
+ );
1726
+
1696
1727
  export interface ToastRegionProps extends WebComponentProps {
1697
1728
  /** The toasts to render. Newest is shown on top. Set as a JS property (array); pass a new array reference to update. */
1698
1729
  toasts: { id: string; message: string; variant?: undefined | "error" | "info" | "success" | "warning" | "neutral"; appearance?: undefined | "pill" | "card"; inverse?: undefined | boolean; description?: undefined | string; action?: undefined | { label: string; onAction: () => void | false }; duration?: undefined | number; dismissible?: undefined | boolean; target?: undefined | HTMLElement }[];
@@ -0,0 +1,59 @@
1
+ import { useCallback, useRef } from 'react';
2
+
3
+ /** Minimal shape of a Web Speech recognition result event — enough to read the
4
+ * first transcript. The full SpeechRecognition API isn't in TS's lib.dom yet. */
5
+ interface SpeechResultEvent {
6
+ results: ArrayLike<ArrayLike<{ transcript: string }>>;
7
+ }
8
+ interface SpeechRecognitionLike {
9
+ lang: string;
10
+ interimResults: boolean;
11
+ onresult: ((event: SpeechResultEvent) => void) | null;
12
+ start(): void;
13
+ }
14
+ type SpeechRecognitionCtor = new () => SpeechRecognitionLike;
15
+
16
+ /** Resolve the Chromium (`webkitSpeechRecognition`) or standard constructor, if any. */
17
+ function getSpeechRecognition(): SpeechRecognitionCtor | undefined {
18
+ if (typeof window === 'undefined') return undefined;
19
+ const w = window as unknown as {
20
+ SpeechRecognition?: SpeechRecognitionCtor;
21
+ webkitSpeechRecognition?: SpeechRecognitionCtor;
22
+ };
23
+ return w.SpeechRecognition ?? w.webkitSpeechRecognition;
24
+ }
25
+
26
+ /**
27
+ * Web Speech mic → one-shot transcript. Chromium-only (`webkitSpeechRecognition`);
28
+ * `supported` is false elsewhere so the caller can degrade gracefully. This hook is
29
+ * deliberately ONLY about speech recognition: it hands the raw transcript to
30
+ * `onTranscript` and lets the caller decide what to do with it (e.g. a composer mic
31
+ * button appends it to the live text). No composer or DOM knowledge.
32
+ *
33
+ * @param onTranscript called with the final recognized transcript.
34
+ * @returns `supported` (Chromium-only availability) and a referentially stable,
35
+ * one-shot `start` (a no-op when unsupported).
36
+ */
37
+ export function useVoiceInput(onTranscript: (transcript: string) => void): {
38
+ supported: boolean;
39
+ start: () => void;
40
+ } {
41
+ // Latest-callback ref: keeps `start` stable while always calling the current
42
+ // `onTranscript` (no stale closure, no re-created handler each render).
43
+ const cbRef = useRef(onTranscript);
44
+ cbRef.current = onTranscript;
45
+
46
+ const supported = getSpeechRecognition() !== undefined;
47
+
48
+ const start = useCallback(() => {
49
+ const Recognition = getSpeechRecognition();
50
+ if (!Recognition) return;
51
+ const rec = new Recognition();
52
+ rec.lang = 'en-US';
53
+ rec.interimResults = false;
54
+ rec.onresult = (event) => cbRef.current(event.results[0][0].transcript);
55
+ rec.start();
56
+ }, []);
57
+
58
+ return { supported, start };
59
+ }
package/llms-full.txt CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  # @kitn.ai/ui
5
5
 
6
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 78 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
6
+ > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 79 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
7
7
 
8
8
  ## Install
9
9
 
@@ -37,7 +37,7 @@ Drop an element into any framework (React, Vue, plain HTML). Data in via JS prop
37
37
  - `<kai-prompt-input>` — standalone composer with send button.
38
38
 
39
39
  **Layer 2 — composable primitives** (`import { … } from '@kitn.ai/ui'`):
40
- All 78 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
40
+ All 79 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
41
41
 
42
42
  ## Key rules for the web components
43
43
 
@@ -99,7 +99,7 @@ For Tailwind builds: `@import "@kitn.ai/ui/theme.css"` in your CSS.
99
99
 
100
100
  ## Docs
101
101
 
102
- - Full element reference (all 78 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
102
+ - Full element reference (all 79 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
103
103
  - Machine-readable Custom Elements Manifest: https://unpkg.com/@kitn.ai/ui/dist/custom-elements.json
104
104
  - Working examples: https://github.com/kitn-ai/ui/tree/main/examples
105
105
  - Storybook: https://storybook.kitn.dev
@@ -173,7 +173,7 @@ The same rule applies to every array/object property (`models`, `context`, `sugg
173
173
 
174
174
  ---
175
175
 
176
- ## Element reference (78 elements, generated from custom-elements.json)
176
+ ## Element reference (79 elements, generated from custom-elements.json)
177
177
 
178
178
  Every element also accepts the `theme` attribute. Array/object properties are marked with a `—` attribute: they must be set as JS properties.
179
179
 
@@ -1487,6 +1487,7 @@ _No events._
1487
1487
  |---|---|---|---|
1488
1488
  | `orientation` | `orientation` | `undefined \| "vertical" \| "horizontal"` | Layout axis: `horizontal` (row, default) or `vertical` (column). |
1489
1489
  | `maximizedIndex` | — | `undefined \| null \| number` | Which item index is maximized (null = none). Declarative source of truth. |
1490
+ | `handle` | `handle` | `undefined \| "none" \| "line" \| "grip"` | Divider affordance drawn inside each draggable handle's 8px grab zone: - `line` (default) — a 1px hairline, transparent at rest, tinting on hover/drag. - `grip` — a dotted grip handle. - `none` — no visible divider, just the invisible hit-area. The full grab zone and keyboard/ARIA behavior are identical for all three. |
1490
1491
 
1491
1492
  **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
1492
1493
 
@@ -1963,6 +1964,35 @@ _No events._
1963
1964
 
1964
1965
  ---
1965
1966
 
1967
+ ### `kai-thread` / `Thread`
1968
+
1969
+ **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
1970
+
1971
+ | Property | Attribute | Type | Description |
1972
+ |---|---|---|---|
1973
+ | `messages` | — | `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" \| { 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" }[]` | The full message thread to render, newest last. Each entry carries its role, content, and optional reasoning/tools/attachments/actions/avatar. Set as a JS property (`el.messages = [...]`); a NEW array reference per streaming chunk re-renders (mutating in place does not). |
1974
+ | `loading` | `loading` | `undefined \| false \| true` | Show a typing indicator on the pending assistant turn — set while awaiting the assistant's reply. |
1975
+ | `proseSize` | `prose-size` | `undefined \| "sm" \| "lg" \| "xs" \| "base"` | Body/prose font scale for rendered markdown (`'xs' \| 'sm' \| 'base' \| 'lg'`). Defaults to `'sm'`. |
1976
+ | `codeTheme` | `code-theme` | `undefined \| string` | Shiki theme name for syntax-highlighted code blocks (e.g. `'github-dark-dimmed'`). |
1977
+ | `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. |
1978
+ | `actionsReveal` | `actions-reveal` | `undefined \| "always" \| "hover"` | Whether each message's action bar is always visible (`'always'`, default) or only revealed on hover of that message row (`'hover'`). |
1979
+ | `scrollButton` | `scroll-button` | `undefined \| false \| true` | Show the scroll-to-bottom button inside the scroll area. Default true. |
1980
+ | `class` | `class` | `undefined \| string` | Extra classes applied to the thread's inner root. |
1981
+
1982
+ **Events** (non-bubbling `CustomEvent`s — listen directly on the element):
1983
+
1984
+ | Event | `detail` type | Description |
1985
+ |---|---|---|
1986
+ | `kai-message-action` | `CustomEvent<{ messageId: string; action: string; state?: undefined \| "on" \| "off" }>` | A message's action button was clicked. `action` is the built-in name (`copy` / `like` / `dislike` / `regenerate` / `edit`) or a custom id. `state` is present only for the toggleable feedback votes: `'on'` when a like/dislike is set, `'off'` when re-tapped to clear. |
1987
+
1988
+ **Slots** (project your own markup via `slot="name"` on a light-DOM child):
1989
+
1990
+ | Slot | Mode | Description |
1991
+ |---|---|---|
1992
+ | `empty` | replace | Custom zero-state rendered in the message area while the thread is empty; replaces the built-in default. |
1993
+
1994
+ ---
1995
+
1966
1996
  ### `kai-toast-region` / `ToastRegion`
1967
1997
 
1968
1998
  **Properties** (every element also accepts `theme="light|dark|auto"`; only scalar props work as HTML attributes):
package/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  <!-- AUTO-GENERATED by scripts/gen-llms.mjs — do not edit by hand. Run `npm run build`. -->
2
2
  # @kitn.ai/ui
3
3
 
4
- > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 78 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
4
+ > Framework-agnostic, Shadow-DOM web components for building AI chat interfaces — works in React, Vue, Angular, Svelte, or plain HTML. 79 custom elements, every one prefixed `kai-` (e.g. `<kai-chat>`, `<kai-artifact>`): streaming responses, markdown + code rendering, reasoning/tool panels, attachments, conversation sidebar, voice input. Zero framework dependency for consumers; the SolidJS runtime it is authored in is bundled in, so the host needs nothing.
5
5
 
6
6
  ## Install
7
7
 
@@ -35,7 +35,7 @@ Drop an element into any framework (React, Vue, plain HTML). Data in via JS prop
35
35
  - `<kai-prompt-input>` — standalone composer with send button.
36
36
 
37
37
  **Layer 2 — composable primitives** (`import { … } from '@kitn.ai/ui'`):
38
- All 78 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
38
+ All 79 elements are also exported individually. Use them for custom layouts or features `<kai-chat>` does not expose (ChainOfThought, FeedbackBar, ThinkingBar, VoiceInput, …). Your bundler tree-shakes the rest.
39
39
 
40
40
  ## Key rules for the web components
41
41
 
@@ -97,7 +97,7 @@ For Tailwind builds: `@import "@kitn.ai/ui/theme.css"` in your CSS.
97
97
 
98
98
  ## Docs
99
99
 
100
- - Full element reference (all 78 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
100
+ - Full element reference (all 79 elements, every prop/event): ./llms-full.txt — https://kitn.dev/llms-full.txt
101
101
  - Machine-readable Custom Elements Manifest: https://unpkg.com/@kitn.ai/ui/dist/custom-elements.json
102
102
  - Working examples: https://github.com/kitn-ai/ui/tree/main/examples
103
103
  - Storybook: https://storybook.kitn.dev
package/package.json CHANGED
@@ -1,8 +1,30 @@
1
1
  {
2
2
  "name": "@kitn.ai/ui",
3
- "version": "0.18.2",
3
+ "version": "0.19.0",
4
4
  "nx": {
5
- "name": "ui"
5
+ "name": "ui",
6
+ "targets": {
7
+ "build-storybook": {
8
+ "dependsOn": [
9
+ "build"
10
+ ]
11
+ },
12
+ "dev": {
13
+ "dependsOn": [
14
+ "build"
15
+ ]
16
+ },
17
+ "test:storybook": {
18
+ "dependsOn": [
19
+ "build"
20
+ ]
21
+ },
22
+ "test:storybook:ci": {
23
+ "dependsOn": [
24
+ "build"
25
+ ]
26
+ }
27
+ }
6
28
  },
7
29
  "type": "module",
8
30
  "sideEffects": [
@@ -112,14 +134,14 @@
112
134
  "test:storybook:ci": "node scripts/run-storybook-tests.mjs",
113
135
  "test:watch": "vitest",
114
136
  "typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.react.json && tsc --noEmit -p tsconfig.react.test.json && tsc --noEmit -p tsconfig.mcp.json",
115
- "examples": "echo 'Serving repo root on http://localhost:8000 — open http://localhost:8000/examples/composable/index.html' && python3 -m http.server 8000",
137
+ "examples": "echo 'Serving repo root on http://localhost:8000 — open http://localhost:8000/examples/demos/composable/index.html' && python3 -m http.server 8000",
116
138
  "dev": "npm run build:css && storybook dev -p 6006",
117
139
  "storybook": "npm run build:css && storybook dev -p 6006",
118
140
  "build-storybook": "npm run build:css && storybook build",
119
141
  "build:css": "tailwindcss -i src/elements/styles.css -o src/elements/compiled.css --minify",
120
142
  "build:css:watch": "tailwindcss -i src/elements/styles.css -o src/elements/compiled.css --watch",
121
- "dev:provider": "vite ../../examples/remote-provider --port 6007 --strictPort",
122
- "dev:host": "vite ../../examples/remote-host --port 6006 --strictPort",
143
+ "dev:provider": "vite ../../examples/internal/remote-provider --port 6007 --strictPort",
144
+ "dev:host": "vite ../../examples/internal/remote-host --port 6006 --strictPort",
123
145
  "test:e2e": "playwright test",
124
146
  "test:composer-ivp": "playwright test --config playwright.composer.config.ts",
125
147
  "test:slots-ivp": "playwright test --config playwright.slots.config.ts",