@kitnai/chat 0.6.0 → 0.8.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 (211) hide show
  1. package/README.md +9 -9
  2. package/dist/custom-elements.json +1676 -881
  3. package/dist/kitn-chat.es.js +36 -36
  4. package/dist/llms/llms-full.txt +316 -155
  5. package/dist/llms/llms.txt +18 -18
  6. package/dist/schemas/card-envelope.schema.json +14 -0
  7. package/dist/schemas/card-event.schema.json +12 -0
  8. package/dist/schemas/confirm.schema.json +65 -0
  9. package/dist/schemas/embed.schema.json +65 -0
  10. package/dist/schemas/form.result.schema.json +7 -0
  11. package/dist/schemas/form.schema.json +33 -0
  12. package/dist/schemas/link.schema.json +56 -0
  13. package/dist/schemas/task-list.result.schema.json +16 -0
  14. package/dist/schemas/task-list.schema.json +78 -0
  15. package/dist/theme.tokens.css +65 -65
  16. package/dist/tsx-B8rCNbgL.js +1 -0
  17. package/dist/typescript-RycA9KXf.js +1 -0
  18. package/frameworks/react/index.tsx +382 -193
  19. package/frameworks/react/runtime.tsx +2 -2
  20. package/llms-full.txt +316 -155
  21. package/llms.txt +18 -18
  22. package/package.json +5 -2
  23. package/src/components/artifact.stories.tsx +138 -0
  24. package/src/components/artifact.tsx +581 -0
  25. package/src/components/attachments.stories.tsx +7 -8
  26. package/src/components/attachments.tsx +2 -2
  27. package/src/components/card.tsx +110 -0
  28. package/src/components/chain-of-thought.stories.tsx +7 -8
  29. package/src/components/chat-container.stories.tsx +7 -8
  30. package/src/components/chat-container.tsx +4 -0
  31. package/src/components/checkpoint.stories.tsx +7 -8
  32. package/src/components/code-block.stories.tsx +8 -9
  33. package/src/components/component-meta.json +3411 -0
  34. package/src/components/confirm-card.stories.tsx +74 -0
  35. package/src/components/confirm-card.tsx +299 -0
  36. package/src/components/context.stories.tsx +7 -8
  37. package/src/components/conversation-item.stories.tsx +7 -8
  38. package/src/components/conversation-item.tsx +2 -2
  39. package/src/components/conversation-list.stories.tsx +7 -8
  40. package/src/components/conversation-list.tsx +1 -1
  41. package/src/components/embed.tsx +196 -0
  42. package/src/components/empty.stories.tsx +8 -9
  43. package/src/components/feedback-bar.stories.tsx +7 -8
  44. package/src/components/file-tree.stories.tsx +73 -0
  45. package/src/components/file-tree.tsx +383 -0
  46. package/src/components/file-upload.stories.tsx +7 -8
  47. package/src/components/form-widgets.tsx +461 -0
  48. package/src/components/form.tsx +796 -0
  49. package/src/components/image.stories.tsx +7 -8
  50. package/src/components/link-card.tsx +194 -0
  51. package/src/components/loader.stories.tsx +7 -8
  52. package/src/components/markdown.stories.tsx +7 -8
  53. package/src/components/message-narrow.stories.tsx +12 -13
  54. package/src/components/message-skills.stories.tsx +16 -17
  55. package/src/components/message.stories.tsx +17 -18
  56. package/src/components/model-switcher.stories.tsx +7 -8
  57. package/src/components/prompt-input.stories.tsx +8 -9
  58. package/src/components/prompt-suggestion.stories.tsx +7 -8
  59. package/src/components/prompt-suggestion.tsx +3 -3
  60. package/src/components/reasoning.stories.tsx +7 -8
  61. package/src/components/scroll-button.stories.tsx +7 -8
  62. package/src/components/slash-command.stories.tsx +8 -9
  63. package/src/components/slash-command.tsx +2 -2
  64. package/src/components/source.stories.tsx +7 -8
  65. package/src/components/source.tsx +1 -1
  66. package/src/components/task-list-card.stories.tsx +78 -0
  67. package/src/components/task-list-card.tsx +388 -0
  68. package/src/components/text-shimmer.stories.tsx +7 -8
  69. package/src/components/thinking-bar.stories.tsx +7 -8
  70. package/src/components/tool.stories.tsx +7 -8
  71. package/src/components/tool.tsx +2 -2
  72. package/src/components/voice-input.stories.tsx +7 -8
  73. package/src/elements/artifact.stories.tsx +291 -0
  74. package/src/elements/artifact.tsx +72 -0
  75. package/src/elements/{kitn-attachments.stories.tsx → attachments.stories.tsx} +11 -11
  76. package/src/elements/attachments.tsx +4 -4
  77. package/src/elements/card.stories.tsx +118 -0
  78. package/src/elements/card.tsx +40 -0
  79. package/src/elements/catalog.stories.tsx +491 -0
  80. package/src/elements/{kitn-chain-of-thought.stories.tsx → chain-of-thought.stories.tsx} +13 -13
  81. package/src/elements/chain-of-thought.tsx +3 -3
  82. package/src/elements/{kitn-chat-scope-picker.stories.tsx → chat-scope-picker.stories.tsx} +10 -10
  83. package/src/elements/chat-scope-picker.tsx +4 -4
  84. package/src/elements/{kitn-chat-workspace.stories.tsx → chat-workspace.stories.tsx} +71 -29
  85. package/src/elements/chat-workspace.tsx +29 -3
  86. package/src/elements/{kitn-chat.stories.tsx → chat.stories.tsx} +61 -16
  87. package/src/elements/chat.tsx +23 -2
  88. package/src/elements/{kitn-checkpoint.stories.tsx → checkpoint.stories.tsx} +11 -11
  89. package/src/elements/checkpoint.tsx +4 -4
  90. package/src/elements/{kitn-code-block.stories.tsx → code-block.stories.tsx} +10 -10
  91. package/src/elements/code-block.tsx +3 -3
  92. package/src/elements/compiled.css +1 -1
  93. package/src/elements/composed-shell.stories.tsx +316 -0
  94. package/src/elements/confirm-card.stories.tsx +186 -0
  95. package/src/elements/confirm-card.tsx +45 -0
  96. package/src/elements/{kitn-context-meter.stories.tsx → context-meter.stories.tsx} +10 -10
  97. package/src/elements/context-meter.tsx +3 -3
  98. package/src/elements/{kitn-conversation-list.stories.tsx → conversation-list.stories.tsx} +35 -22
  99. package/src/elements/conversation-list.tsx +11 -2
  100. package/src/elements/css.ts +1 -1
  101. package/src/elements/define.tsx +10 -10
  102. package/src/elements/element-meta.json +2649 -0
  103. package/src/elements/element-types.d.ts +251 -125
  104. package/src/elements/embed.stories.tsx +197 -0
  105. package/src/elements/embed.tsx +35 -0
  106. package/src/elements/{kitn-empty.stories.tsx → empty.stories.tsx} +12 -12
  107. package/src/elements/empty.tsx +3 -3
  108. package/src/elements/{kitn-feedback-bar.stories.tsx → feedback-bar.stories.tsx} +11 -11
  109. package/src/elements/feedback-bar.tsx +4 -4
  110. package/src/elements/file-tree.stories.tsx +133 -0
  111. package/src/elements/file-tree.tsx +52 -0
  112. package/src/elements/{kitn-file-upload.stories.tsx → file-upload.stories.tsx} +12 -12
  113. package/src/elements/file-upload.tsx +4 -4
  114. package/src/elements/form.stories.tsx +204 -0
  115. package/src/elements/form.tsx +37 -0
  116. package/src/elements/{kitn-image.stories.tsx → image.stories.tsx} +10 -10
  117. package/src/elements/image.tsx +3 -3
  118. package/src/elements/link-card.stories.tsx +193 -0
  119. package/src/elements/link-card.tsx +34 -0
  120. package/src/elements/{kitn-loader.stories.tsx → loader.stories.tsx} +11 -11
  121. package/src/elements/loader.tsx +3 -3
  122. package/src/elements/{kitn-markdown.stories.tsx → markdown.stories.tsx} +10 -10
  123. package/src/elements/markdown.tsx +3 -3
  124. package/src/elements/{kitn-message-skills.stories.tsx → message-skills.stories.tsx} +10 -10
  125. package/src/elements/message-skills.tsx +3 -3
  126. package/src/elements/{kitn-message.stories.tsx → message.stories.tsx} +12 -12
  127. package/src/elements/message.tsx +5 -5
  128. package/src/elements/{kitn-model-switcher.stories.tsx → model-switcher.stories.tsx} +10 -10
  129. package/src/elements/model-switcher.tsx +5 -5
  130. package/src/elements/{kitn-prompt-input.stories.tsx → prompt-input.stories.tsx} +41 -19
  131. package/src/elements/prompt-input.tsx +5 -5
  132. package/src/elements/{kitn-prompt-suggestions.stories.tsx → prompt-suggestions.stories.tsx} +13 -13
  133. package/src/elements/prompt-suggestions.tsx +4 -4
  134. package/src/elements/{kitn-reasoning.stories.tsx → reasoning.stories.tsx} +10 -10
  135. package/src/elements/reasoning.tsx +4 -4
  136. package/src/elements/register.ts +11 -1
  137. package/src/elements/resizable.stories.tsx +200 -0
  138. package/src/elements/resizable.tsx +264 -0
  139. package/src/elements/{kitn-response-stream.stories.tsx → response-stream.stories.tsx} +10 -10
  140. package/src/elements/response-stream.tsx +4 -4
  141. package/src/elements/{kitn-source-list.stories.tsx → source-list.stories.tsx} +11 -11
  142. package/src/elements/{kitn-source.stories.tsx → source.stories.tsx} +12 -12
  143. package/src/elements/source.tsx +5 -5
  144. package/src/elements/styles.css +140 -1
  145. package/src/elements/task-list-card.stories.tsx +194 -0
  146. package/src/elements/task-list-card.tsx +40 -0
  147. package/src/elements/{kitn-text-shimmer.stories.tsx → text-shimmer.stories.tsx} +10 -10
  148. package/src/elements/text-shimmer.tsx +3 -3
  149. package/src/elements/{kitn-thinking-bar.stories.tsx → thinking-bar.stories.tsx} +11 -11
  150. package/src/elements/thinking-bar.tsx +5 -5
  151. package/src/elements/{kitn-tool.stories.tsx → tool.stories.tsx} +10 -10
  152. package/src/elements/tool.tsx +3 -3
  153. package/src/elements/{kitn-voice-input.stories.tsx → voice-input.stories.tsx} +10 -10
  154. package/src/elements/voice-input.tsx +4 -4
  155. package/src/index.ts +94 -2
  156. package/src/primitives/card-contract.ts +60 -0
  157. package/src/primitives/card-host.tsx +35 -0
  158. package/src/primitives/card-routing.ts +79 -0
  159. package/src/primitives/card-schemas/card-envelope.schema.json +14 -0
  160. package/src/primitives/card-schemas/card-event.schema.json +12 -0
  161. package/src/primitives/card-schemas/confirm.schema.json +65 -0
  162. package/src/primitives/card-schemas/embed.schema.json +65 -0
  163. package/src/primitives/card-schemas/form.result.schema.json +7 -0
  164. package/src/primitives/card-schemas/form.schema.json +33 -0
  165. package/src/primitives/card-schemas/link.schema.json +56 -0
  166. package/src/primitives/card-schemas/task-list.result.schema.json +16 -0
  167. package/src/primitives/card-schemas/task-list.schema.json +78 -0
  168. package/src/primitives/card-validate.ts +95 -0
  169. package/src/primitives/embed-providers.ts +254 -0
  170. package/src/primitives/highlighter.ts +4 -0
  171. package/src/primitives/link-preview.ts +87 -0
  172. package/src/primitives/pdf-preview.ts +121 -0
  173. package/src/stories/chat-panel-layout.stories.tsx +2 -1
  174. package/src/stories/chat-scene.tsx +22 -21
  175. package/src/stories/checkpoint-restore.stories.tsx +10 -10
  176. package/src/stories/conversation-with-reasoning.stories.tsx +4 -4
  177. package/src/stories/conversation-with-sources.stories.tsx +7 -7
  178. package/src/stories/docs/Accessibility.mdx +2 -2
  179. package/src/stories/docs/ForAIAgents.mdx +3 -3
  180. package/src/stories/docs/GettingStarted.mdx +2 -2
  181. package/src/stories/docs/Installation.mdx +2 -2
  182. package/src/stories/docs/Integrations.mdx +29 -29
  183. package/src/stories/docs/Introduction.mdx +3 -3
  184. package/src/stories/docs/Theming.mdx +2 -2
  185. package/src/stories/docs/element-controls.ts +60 -0
  186. package/src/stories/docs/theme-editor/theme-editor.tsx +1 -0
  187. package/src/stories/examples/ChoosingComponents.mdx +94 -0
  188. package/src/stories/examples/sample-data.ts +79 -0
  189. package/src/stories/message-actions.stories.tsx +13 -13
  190. package/src/stories/pattern-centered-conversation.stories.tsx +3 -3
  191. package/src/stories/pattern-docked-widget.stories.tsx +1 -1
  192. package/src/stories/pattern-empty-state.stories.tsx +3 -3
  193. package/src/stories/prompt-input-variants.stories.tsx +13 -13
  194. package/src/stories/streaming-response.stories.tsx +3 -3
  195. package/src/stories/typography.stories.tsx +4 -4
  196. package/src/ui/avatar.stories.tsx +7 -8
  197. package/src/ui/badge.stories.tsx +7 -8
  198. package/src/ui/button.stories.tsx +8 -9
  199. package/src/ui/button.tsx +1 -0
  200. package/src/ui/collapsible.stories.tsx +6 -7
  201. package/src/ui/dropdown.stories.tsx +6 -7
  202. package/src/ui/hover-card.stories.tsx +6 -7
  203. package/src/ui/resizable.stories.tsx +74 -9
  204. package/src/ui/resizable.tsx +351 -71
  205. package/src/ui/scroll-area.stories.tsx +6 -7
  206. package/src/ui/scroll-area.tsx +3 -1
  207. package/src/ui/separator.stories.tsx +7 -8
  208. package/src/ui/skeleton.stories.tsx +7 -8
  209. package/src/ui/textarea.stories.tsx +6 -7
  210. package/src/ui/tooltip.stories.tsx +8 -9
  211. package/theme.css +65 -65
@@ -1,6 +1,7 @@
1
1
  import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
2
  import { onMount } from 'solid-js';
3
3
  import './register'; // side effect: registers the custom elements
4
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
4
5
 
5
6
  interface Step {
6
7
  label: string;
@@ -12,7 +13,7 @@ declare module 'solid-js' {
12
13
  // eslint-disable-next-line @typescript-eslint/no-namespace
13
14
  namespace JSX {
14
15
  interface IntrinsicElements {
15
- 'kitn-chain-of-thought': JSX.HTMLAttributes<HTMLElement>;
16
+ 'kc-chain-of-thought': JSX.HTMLAttributes<HTMLElement>;
16
17
  }
17
18
  }
18
19
  }
@@ -23,19 +24,19 @@ const steps: Step[] = [
23
24
  { label: 'Build & verify' },
24
25
  ];
25
26
 
26
- /** Render `<kitn-chain-of-thought>` with the `steps` set as a JS property. */
27
+ /** Render `<kc-chain-of-thought>` with the `steps` set as a JS property. */
27
28
  function CotElement(props: { steps: Step[] }) {
28
29
  let el: (HTMLElement & { steps?: Step[] }) | undefined;
29
30
  onMount(() => {
30
31
  if (el) el.steps = props.steps;
31
32
  });
32
33
  return (
33
- <kitn-chain-of-thought ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '24px', 'max-width': '560px' }} />
34
+ <kc-chain-of-thought ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '24px', 'max-width': '560px' }} />
34
35
  );
35
36
  }
36
37
 
37
38
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
38
- <kitn-chain-of-thought id="cot"></kitn-chain-of-thought>
39
+ <kc-chain-of-thought id="cot"></kc-chain-of-thought>
39
40
 
40
41
  <script type="module">
41
42
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -48,19 +49,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
48
49
  </script>`;
49
50
 
50
51
  const meta = {
51
- title: 'Web Components/kitn-chain-of-thought',
52
+ title: 'Web Components/kc-chain-of-thought',
52
53
  tags: ['autodocs'],
54
+ argTypes: argTypesFor('kc-chain-of-thought'),
53
55
  parameters: {
54
56
  layout: 'fullscreen',
55
57
  docs: {
56
- description: {
57
- component: [
58
- '`<kitn-chain-of-thought>` is the framework-agnostic **web component** for step-by-step reasoning a connected list of steps, each with optional collapsible detail — isolated in **Shadow DOM**. The compound primitive collapses to a single `steps` data model (Route 1).',
59
- '**When to use:** surfacing an agent\'s plan or reasoning trace in a non-Solid app. In SolidJS, compose the `ChainOfThought` primitives for finer control.',
60
- "**How to use:** register once with `import '@kitnai/chat/elements'`, then set the `steps` **property** an array of `{ label, content? }`. Steps with `content` become expandable.",
61
- 'See the **Code** tab for HTML usage.',
62
- ].join('\n\n'),
63
- },
58
+ description: specDescription('kc-chain-of-thought', [
59
+ '`<kc-chain-of-thought>` is the framework-agnostic **web component** for step-by-step reasoning — a connected list of steps, each with optional collapsible detail — isolated in **Shadow DOM**. The compound primitive collapses to a single `steps` data model (Route 1).',
60
+ '**When to use:** surfacing an agent\'s plan or reasoning trace in a non-Solid app. In SolidJS, compose the `ChainOfThought` primitives for finer control.',
61
+ "**How to use:** register once with `import '@kitnai/chat/elements'`, then set the `steps` **property** an array of `{ label, content? }`. Steps with `content` become expandable.",
62
+ 'See the **Code** tab for HTML usage.',
63
+ ]),
64
64
  },
65
65
  },
66
66
  } satisfies Meta;
@@ -1,5 +1,5 @@
1
1
  import { For, Show } from 'solid-js';
2
- import { defineKitnElement } from './define';
2
+ import { defineWebComponent } from './define';
3
3
  import {
4
4
  ChainOfThought,
5
5
  ChainOfThoughtStep,
@@ -22,10 +22,10 @@ interface Props extends Record<string, unknown> {
22
22
  }
23
23
 
24
24
  /**
25
- * `<kitn-chain-of-thought>` — step-by-step reasoning with connectors and
25
+ * `<kc-chain-of-thought>` — step-by-step reasoning with connectors and
26
26
  * per-step collapsible detail. Data via the `steps` property.
27
27
  */
28
- defineKitnElement<Props>('kitn-chain-of-thought', {
28
+ defineWebComponent<Props>('kc-chain-of-thought', {
29
29
  steps: [],
30
30
  }, (props) => (
31
31
  <ChainOfThought>
@@ -1,20 +1,21 @@
1
1
  import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
2
  import { onMount } from 'solid-js';
3
3
  import './register'; // side effect: registers the custom elements
4
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
4
5
 
5
6
  // The web components are custom DOM elements, so declare the tags for JSX.
6
7
  declare module 'solid-js' {
7
8
  // eslint-disable-next-line @typescript-eslint/no-namespace
8
9
  namespace JSX {
9
10
  interface IntrinsicElements {
10
- 'kitn-chat-scope-picker': JSX.HTMLAttributes<HTMLElement> & {
11
+ 'kc-scope-picker': JSX.HTMLAttributes<HTMLElement> & {
11
12
  'current-label'?: string;
12
13
  };
13
14
  }
14
15
  }
15
16
  }
16
17
 
17
- /** Render `<kitn-chat-scope-picker>` with author/tag options set as properties. */
18
+ /** Render `<kc-scope-picker>` with author/tag options set as properties. */
18
19
  function ScopePickerElement(props: { authors: string[]; tags: string[] }) {
19
20
  let el: (HTMLElement & { availableAuthors?: string[]; availableTags?: string[] }) | undefined;
20
21
  onMount(() => {
@@ -27,12 +28,12 @@ function ScopePickerElement(props: { authors: string[]; tags: string[] }) {
27
28
  });
28
29
  });
29
30
  return (
30
- <kitn-chat-scope-picker ref={(e) => (el = e as HTMLElement)} style={{ display: 'inline-block', padding: '40px' }} />
31
+ <kc-scope-picker ref={(e) => (el = e as HTMLElement)} style={{ display: 'inline-block', padding: '40px' }} />
31
32
  );
32
33
  }
33
34
 
34
35
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
35
- <kitn-chat-scope-picker id="scope"></kitn-chat-scope-picker>
36
+ <kc-scope-picker id="scope"></kc-scope-picker>
36
37
 
37
38
  <script type="module">
38
39
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -45,19 +46,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
45
46
  </script>`;
46
47
 
47
48
  const meta = {
48
- title: 'Web Components/kitn-chat-scope-picker',
49
+ title: 'Web Components/kc-scope-picker',
49
50
  tags: ['autodocs'],
51
+ argTypes: argTypesFor('kc-scope-picker'),
50
52
  parameters: {
51
53
  layout: 'fullscreen',
52
54
  docs: {
53
- description: {
54
- component: [
55
- '`<kitn-chat-scope-picker>` is the framework-agnostic **web component** for scoping a chat by author or tag — a dropdown that emits the chosen filters — isolated in **Shadow DOM**.',
55
+ description: specDescription('kc-scope-picker', [
56
+ '`<kc-scope-picker>` is the framework-agnostic **web component** for scoping a chat by author or tag — a dropdown that emits the chosen filters — isolated in **Shadow DOM**.',
56
57
  '**When to use:** letting users narrow a conversation/search to a subset of content. In SolidJS, use the `ChatScopePicker` primitive.',
57
58
  "**How to use:** register once with `import '@kitnai/chat/elements'`, set the `availableAuthors` / `availableTags` **properties** (and optionally `current-label`), and listen for the `scopechange` **CustomEvent** (`undefined` filters = \"All Content\").",
58
59
  'See the **Code** tab for HTML usage.',
59
- ].join('\n\n'),
60
- },
60
+ ]),
61
61
  },
62
62
  },
63
63
  } satisfies Meta;
@@ -1,4 +1,4 @@
1
- import { defineKitnElement } from './define';
1
+ import { defineWebComponent } from './define';
2
2
  import { ChatScopePicker } from '../components/chat-scope-picker';
3
3
  import type { SearchFilters } from '../types';
4
4
 
@@ -11,18 +11,18 @@ interface Props extends Record<string, unknown> {
11
11
  currentLabel?: string;
12
12
  }
13
13
 
14
- /** Events fired by `<kitn-chat-scope-picker>`. */
14
+ /** Events fired by `<kc-scope-picker>`. */
15
15
  interface Events {
16
16
  /** A scope was chosen (`undefined` filters = "All Content"). */
17
17
  scopechange: { filters: SearchFilters | undefined };
18
18
  }
19
19
 
20
20
  /**
21
- * `<kitn-chat-scope-picker>` — a dropdown to scope a chat by author or tag.
21
+ * `<kc-scope-picker>` — a dropdown to scope a chat by author or tag.
22
22
  * Options via `available-authors`/`available-tags` properties; emits
23
23
  * `scopechange`.
24
24
  */
25
- defineKitnElement<Props, Events>('kitn-chat-scope-picker', {
25
+ defineWebComponent<Props, Events>('kc-scope-picker', {
26
26
  availableAuthors: [],
27
27
  availableTags: [],
28
28
  currentLabel: 'All Content',
@@ -1,15 +1,16 @@
1
1
  import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
2
  import { onMount } from 'solid-js';
3
- import './register'; // side effect: registers all kitn custom elements including <kitn-chat-workspace>
3
+ import './register'; // side effect: registers all kitn custom elements including <kc-workspace>
4
4
  import type { ConversationGroup, ConversationSummary, ModelOption } from '../types';
5
5
  import type { ChatMessage } from './chat-types';
6
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
6
7
 
7
8
  // The web components are custom DOM elements, so declare the tags for JSX.
8
9
  declare module 'solid-js' {
9
10
  // eslint-disable-next-line @typescript-eslint/no-namespace
10
11
  namespace JSX {
11
12
  interface IntrinsicElements {
12
- 'kitn-chat-workspace': JSX.HTMLAttributes<HTMLElement>;
13
+ 'kc-workspace': JSX.HTMLAttributes<HTMLElement>;
13
14
  }
14
15
  }
15
16
  }
@@ -50,26 +51,42 @@ const sampleMessages: ChatMessage[] = [
50
51
  id: 'm2',
51
52
  role: 'assistant',
52
53
  content:
53
- 'Use `<kitn-chat-workspace>` — set `conversations`, `messages`, and `models` as properties and listen for `conversationselect` + `submit`.',
54
+ 'Use `<kc-workspace>` — set `conversations`, `messages`, and `models` as properties and listen for `conversationselect` + `submit`.',
54
55
  actions: ['copy', 'like'],
55
56
  },
56
57
  ];
57
58
 
58
- /** Live demo of the actual `<kitn-chat-workspace>` custom element (Shadow DOM and all). */
59
- function WorkspaceElement() {
60
- let el:
61
- | (HTMLElement & {
62
- groups?: ConversationGroup[];
63
- conversations?: ConversationSummary[];
64
- activeId?: string;
65
- messages?: ChatMessage[];
66
- models?: ModelOption[];
67
- currentModel?: string;
68
- chatTitle?: string;
69
- })
70
- | undefined;
59
+ type WorkspaceEl = HTMLElement & {
60
+ groups?: ConversationGroup[];
61
+ conversations?: ConversationSummary[];
62
+ activeId?: string;
63
+ messages?: ChatMessage[];
64
+ models?: ModelOption[];
65
+ currentModel?: string;
66
+ chatTitle?: string;
67
+ placeholder?: string;
68
+ loading?: boolean;
69
+ suggestionMode?: string;
70
+ proseSize?: string;
71
+ codeTheme?: string;
72
+ codeHighlight?: boolean;
73
+ scrollButton?: boolean;
74
+ search?: boolean;
75
+ voice?: boolean;
76
+ slashCompact?: boolean;
77
+ sidebarWidth?: number;
78
+ sidebarMinWidth?: number;
79
+ sidebarMaxWidth?: number;
80
+ sidebarCollapsed?: boolean;
81
+ value?: string;
82
+ };
83
+
84
+ /** Live demo of the actual `<kc-workspace>` custom element (Shadow DOM and all). */
85
+ function WorkspaceElement(props: { args?: Record<string, unknown> }) {
86
+ let el: WorkspaceEl | undefined;
71
87
  onMount(() => {
72
88
  if (el) {
89
+ // Fixed array/object data
73
90
  el.groups = sampleGroups;
74
91
  el.conversations = sampleConversations;
75
92
  el.activeId = '1';
@@ -77,6 +94,18 @@ function WorkspaceElement() {
77
94
  el.models = sampleModels;
78
95
  el.currentModel = 'claude-4';
79
96
  el.chatTitle = 'Web component architecture';
97
+ // Scalar args from Controls (override defaults above for scalar props)
98
+ const args = props.args;
99
+ if (args) {
100
+ const scalarNames = [
101
+ 'placeholder', 'loading', 'suggestionMode', 'proseSize', 'codeTheme',
102
+ 'codeHighlight', 'scrollButton', 'search', 'voice', 'slashCompact',
103
+ 'sidebarWidth', 'sidebarMinWidth', 'sidebarMaxWidth', 'sidebarCollapsed', 'value',
104
+ ];
105
+ for (const name of scalarNames) {
106
+ if (name in args) (el as unknown as Record<string, unknown>)[name] = args[name];
107
+ }
108
+ }
80
109
  el.addEventListener('conversationselect', (e) => console.log('select', (e as CustomEvent).detail));
81
110
  el.addEventListener('submit', (e) => console.log('submit', (e as unknown as CustomEvent).detail));
82
111
  el.addEventListener('sidebartoggle', (e) => console.log('sidebartoggle', (e as CustomEvent).detail));
@@ -84,8 +113,8 @@ function WorkspaceElement() {
84
113
  });
85
114
  return (
86
115
  <div style={{ height: '720px', width: '100%' }}>
87
- <kitn-chat-workspace
88
- ref={(e) => (el = e as HTMLElement)}
116
+ <kc-workspace
117
+ ref={(e) => (el = e as WorkspaceEl)}
89
118
  style={{ display: 'block', height: '100%' }}
90
119
  />
91
120
  </div>
@@ -93,7 +122,7 @@ function WorkspaceElement() {
93
122
  }
94
123
 
95
124
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
96
- <kitn-chat-workspace id="workspace" style="display:block; height:100vh;"></kitn-chat-workspace>
125
+ <kc-workspace id="workspace" style="display:block; height:100vh;"></kc-workspace>
97
126
 
98
127
  <script type="module">
99
128
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -108,7 +137,7 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
108
137
  ];
109
138
  workspace.messages = [
110
139
  { id: 'm1', role: 'user', content: 'How do I drop the whole chat app in with one tag?' },
111
- { id: 'm2', role: 'assistant', content: 'Use <kitn-chat-workspace> — set conversations, messages, and models as properties.' },
140
+ { id: 'm2', role: 'assistant', content: 'Use <kc-workspace> — set conversations, messages, and models as properties.' },
112
141
  ];
113
142
  workspace.models = [
114
143
  { id: 'claude-4', name: 'Claude 4 Opus', provider: 'Anthropic' },
@@ -141,7 +170,7 @@ function Workspace() {
141
170
  ];
142
171
  const messages: ChatMessage[] = [
143
172
  { id: 'm1', role: 'user', content: 'How do I drop the whole chat app in with one tag?' },
144
- { id: 'm2', role: 'assistant', content: 'Use <kitn-chat-workspace> — set conversations, messages, and models as properties.' },
173
+ { id: 'm2', role: 'assistant', content: 'Use <kc-workspace> — set conversations, messages, and models as properties.' },
145
174
  ];
146
175
  onMount(() => {
147
176
  el.conversations = conversations;
@@ -152,7 +181,7 @@ function Workspace() {
152
181
  el.addEventListener('sidebartoggle', (e) => console.log('sidebar collapsed:', e.detail.collapsed));
153
182
  });
154
183
  return (
155
- <kitn-chat-workspace
184
+ <kc-workspace
156
185
  ref={el}
157
186
  style={{ display: 'block', height: '100vh' }}
158
187
  />
@@ -160,20 +189,19 @@ function Workspace() {
160
189
  }`;
161
190
 
162
191
  const meta = {
163
- title: 'Web Components/kitn-chat-workspace',
192
+ title: 'Web Components/kc-workspace',
164
193
  tags: ['autodocs'],
194
+ argTypes: argTypesFor('kc-workspace'),
165
195
  parameters: {
166
196
  layout: 'fullscreen',
167
197
  docs: {
168
- description: {
169
- component: [
170
- '`<kitn-chat-workspace>` is the full chat shell as a single **web component** — a resizable split layout with a collapsible conversation list on the left and a full message thread on the right, all isolated in **Shadow DOM**. SolidJS is bundled in, so the host needs nothing.',
198
+ description: specDescription('kc-workspace', [
199
+ '`<kc-workspace>` is the full chat shell as a single **web component** — a resizable split layout with a collapsible conversation list on the left and a full message thread on the right, all isolated in **Shadow DOM**. SolidJS is bundled in, so the host needs nothing.',
171
200
  '**When to use:** dropping an entire chat application shell into a non-Solid app (React, Vue, Svelte, plain HTML), or anywhere you want zero style conflicts and a ready-made list+chat layout. If you *are* in SolidJS and want fine-grained control, compose the `ConversationList` and `ChatThread` primitives directly.',
172
201
  '**How to use:** register once with `import \'@kitnai/chat/elements\'`, set rich data as JS **properties** (`el.conversations = [...]`, `el.messages = [...]`, `el.models = [...]`), and listen for **CustomEvents** (`conversationselect`, `submit`, `sidebartoggle`, `newchat`) directly on the element.',
173
202
  '**Placement:** as a full-page surface or large panel. Give it an explicit height (e.g. `height: 100vh`). The sidebar is drag-resizable and can be collapsed via the toggle button in its header.',
174
203
  'See the **Code** tab below for the HTML usage; the *SolidJS* story shows the same element inside a Solid component.',
175
- ].join('\n\n'),
176
- },
204
+ ]),
177
205
  },
178
206
  },
179
207
  } satisfies Meta;
@@ -183,7 +211,20 @@ type Story = StoryObj;
183
211
 
184
212
  /** The element used the plain-HTML / any-framework way. */
185
213
  export const Default: Story = {
186
- render: () => <WorkspaceElement />,
214
+ args: {
215
+ placeholder: 'Send a message...',
216
+ loading: false,
217
+ suggestionMode: 'submit',
218
+ proseSize: 'sm',
219
+ codeTheme: 'github-dark-dimmed',
220
+ codeHighlight: true,
221
+ scrollButton: true,
222
+ search: false,
223
+ voice: false,
224
+ slashCompact: false,
225
+ sidebarCollapsed: false,
226
+ },
227
+ render: (args: Record<string, unknown>) => <WorkspaceElement args={args} />,
187
228
  parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
188
229
  };
189
230
 
@@ -193,3 +234,4 @@ export const InSolidJS: Story = {
193
234
  render: () => <WorkspaceElement />,
194
235
  parameters: { docs: { source: { code: SOLID_SNIPPET, language: 'tsx' } } },
195
236
  };
237
+
@@ -1,12 +1,13 @@
1
1
  import { createSignal, Show } from 'solid-js';
2
- import { defineKitnElement } from './define';
2
+ import { defineWebComponent } from './define';
3
3
  import { ChatThread, type ChatThreadContextUsage } from '../components/chat-thread';
4
4
  import { ConversationList } from '../components/conversation-list';
5
5
  import { ResizablePanelGroup, ResizablePanel, ResizableHandle } from '../ui/resizable';
6
6
  import { Button } from '../ui/button';
7
7
  import { PanelLeftOpen } from 'lucide-solid';
8
+ import type { AttachmentData } from '../components/attachments';
8
9
  import type { SlashCommandItem } from '../components/slash-command';
9
- import type { ChatMessage } from './chat-types';
10
+ import type { ChatMessage, ChatMessageAction } from './chat-types';
10
11
  import type { ProseSize } from '../primitives/chat-config';
11
12
  import type { ModelOption, ConversationGroup, ConversationSummary } from '../types';
12
13
 
@@ -47,7 +48,32 @@ interface Props extends Record<string, unknown> {
47
48
  sidebarCollapsed?: boolean;
48
49
  }
49
50
 
50
- defineKitnElement<Props>('kitn-chat-workspace', {
51
+ interface Events {
52
+ /** A conversation was selected in the sidebar. */
53
+ conversationselect: { id: string };
54
+ /** The "New chat" button was clicked. */
55
+ newchat: Record<string, never>;
56
+ /** The sidebar was collapsed or expanded. */
57
+ sidebartoggle: { collapsed: boolean };
58
+ /** User submitted a message. */
59
+ submit: { value: string; attachments: AttachmentData[] };
60
+ /** Fired on every input change. */
61
+ valuechange: { value: string };
62
+ /** The header model switcher changed. */
63
+ modelchange: { modelId: string };
64
+ /** An action button on a message was clicked. */
65
+ messageaction: { messageId: string; action: ChatMessageAction };
66
+ /** The Search button was clicked. */
67
+ search: Record<string, never>;
68
+ /** The Mic / voice button was clicked. */
69
+ voice: Record<string, never>;
70
+ /** A slash command was chosen from the palette. */
71
+ slashselect: { command: SlashCommandItem };
72
+ /** A suggestion chip was clicked (only in `suggestion-mode="fill"`). */
73
+ suggestionclick: { value: string };
74
+ }
75
+
76
+ defineWebComponent<Props, Events>('kc-workspace', {
51
77
  groups: [], conversations: [], activeId: undefined, messages: [],
52
78
  value: undefined, placeholder: 'Send a message...', loading: false,
53
79
  suggestions: undefined, suggestionMode: 'submit', proseSize: 'sm',
@@ -1,14 +1,15 @@
1
1
  import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
2
  import { onMount } from 'solid-js';
3
- import './register'; // side effect: registers <kitn-chat>, <kitn-conversation-list>, <kitn-prompt-input>
3
+ import './register'; // side effect: registers <kc-chat>, <kc-conversations>, <kc-prompt-input>
4
4
  import type { ChatMessage } from './chat-types';
5
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
5
6
 
6
7
  // The web components are custom DOM elements, so declare the tags for JSX.
7
8
  declare module 'solid-js' {
8
9
  // eslint-disable-next-line @typescript-eslint/no-namespace
9
10
  namespace JSX {
10
11
  interface IntrinsicElements {
11
- 'kitn-chat': JSX.HTMLAttributes<HTMLElement>;
12
+ 'kc-chat': JSX.HTMLAttributes<HTMLElement>;
12
13
  }
13
14
  }
14
15
  }
@@ -24,17 +25,49 @@ const sampleMessages: ChatMessage[] = [
24
25
  },
25
26
  ];
26
27
 
27
- /** Live demo of the actual `<kitn-chat>` custom element (Shadow DOM and all). */
28
- function ChatElement() {
29
- let el: (HTMLElement & { messages?: ChatMessage[] }) | undefined;
28
+ type ChatEl = HTMLElement & {
29
+ messages?: ChatMessage[];
30
+ value?: string;
31
+ placeholder?: string;
32
+ loading?: boolean;
33
+ suggestionMode?: string;
34
+ proseSize?: string;
35
+ codeTheme?: string;
36
+ codeHighlight?: boolean;
37
+ chatTitle?: string;
38
+ currentModel?: string;
39
+ scrollButton?: boolean;
40
+ search?: boolean;
41
+ voice?: boolean;
42
+ slashCompact?: boolean;
43
+ };
44
+
45
+ /** Live demo of the actual `<kc-chat>` custom element (Shadow DOM and all). */
46
+ function ChatElement(props: { args?: Record<string, unknown> }) {
47
+ let el: ChatEl | undefined;
30
48
  onMount(() => {
31
- if (el) el.messages = sampleMessages;
49
+ if (el) {
50
+ // Fixed array data
51
+ el.messages = sampleMessages;
52
+ // Scalar args from Controls
53
+ const args = props.args;
54
+ if (args) {
55
+ const scalarNames = [
56
+ 'value', 'placeholder', 'loading', 'suggestionMode', 'proseSize',
57
+ 'codeTheme', 'codeHighlight', 'chatTitle', 'currentModel',
58
+ 'scrollButton', 'search', 'voice', 'slashCompact',
59
+ ];
60
+ for (const name of scalarNames) {
61
+ if (name in args) (el as unknown as Record<string, unknown>)[name] = args[name];
62
+ }
63
+ }
64
+ }
32
65
  });
33
- return <kitn-chat ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', height: '560px' }} />;
66
+ return <kc-chat ref={(e) => (el = e as ChatEl)} style={{ display: 'block', height: '560px' }} />;
34
67
  }
35
68
 
36
69
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
37
- <kitn-chat id="chat" style="display:block; height:100vh;"></kitn-chat>
70
+ <kc-chat id="chat" style="display:block; height:100vh;"></kc-chat>
38
71
 
39
72
  <script type="module">
40
73
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -61,7 +94,7 @@ function Chat() {
61
94
  ];
62
95
  onMount(() => { el.messages = messages; });
63
96
  return (
64
- <kitn-chat
97
+ <kc-chat
65
98
  ref={el}
66
99
  style={{ display: 'block', height: '100vh' }}
67
100
  on:submit={(e) => console.log('user sent:', e.detail.value)}
@@ -70,20 +103,19 @@ function Chat() {
70
103
  }`;
71
104
 
72
105
  const meta = {
73
- title: 'Web Components/kitn-chat',
106
+ title: 'Web Components/kc-chat',
74
107
  tags: ['autodocs'],
108
+ argTypes: argTypesFor('kc-chat'),
75
109
  parameters: {
76
110
  layout: 'fullscreen',
77
111
  docs: {
78
- description: {
79
- component: [
80
- '`<kitn-chat>` is the framework-agnostic **web component** version of the chat UI — a complete message thread plus prompt input, isolated in **Shadow DOM** so the host page\'s CSS can\'t leak in and the kit\'s styles can\'t leak out. SolidJS is bundled in, so the host needs nothing.',
112
+ description: specDescription('kc-chat', [
113
+ '`<kc-chat>` is the framework-agnostic **web component** version of the chat UI — a complete message thread plus prompt input, isolated in **Shadow DOM** so the host page\'s CSS can\'t leak in and the kit\'s styles can\'t leak out. SolidJS is bundled in, so the host needs nothing.',
81
114
  '**When to use:** dropping a full chat into a non-Solid app (React, Vue, Svelte, plain HTML), or anywhere you want zero style conflicts. If you *are* in SolidJS and want fine-grained control, compose the primitives (`ChatContainer`, `Message`, `PromptInput`) instead.',
82
115
  '**How to use:** register once with `import \'@kitnai/chat/elements\'`, set rich data as JS **properties** (`el.messages = [...]`), and listen for **CustomEvents** (`submit`, `messageaction`, `valuechange`) directly on the element.',
83
116
  '**Placement:** as a top-level panel or full-page surface. Give it an explicit height (e.g. `height: 100vh`).',
84
117
  'See the **Code** tab below for the HTML usage; the *SolidJS* story shows the same element inside a Solid component.',
85
- ].join('\n\n'),
86
- },
118
+ ]),
87
119
  },
88
120
  },
89
121
  } satisfies Meta;
@@ -93,7 +125,19 @@ type Story = StoryObj;
93
125
 
94
126
  /** The element used the plain-HTML / any-framework way. */
95
127
  export const Default: Story = {
96
- render: () => <ChatElement />,
128
+ args: {
129
+ placeholder: 'Send a message...',
130
+ loading: false,
131
+ suggestionMode: 'submit',
132
+ proseSize: 'sm',
133
+ codeTheme: 'github-dark-dimmed',
134
+ codeHighlight: true,
135
+ scrollButton: true,
136
+ search: false,
137
+ voice: false,
138
+ slashCompact: false,
139
+ },
140
+ render: (args: Record<string, unknown>) => <ChatElement args={args} />,
97
141
  parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
98
142
  };
99
143
 
@@ -103,3 +147,4 @@ export const InSolidJS: Story = {
103
147
  render: () => <ChatElement />,
104
148
  parameters: { docs: { source: { code: SOLID_SNIPPET, language: 'tsx' } } },
105
149
  };
150
+
@@ -1,14 +1,35 @@
1
- import { defineKitnElement } from './define';
1
+ import { defineWebComponent } from './define';
2
2
  import { ChatThread, type ChatThreadProps, type ChatThreadContextUsage } from '../components/chat-thread';
3
+ import type { AttachmentData } from '../components/attachments';
3
4
  import type { SlashCommandItem } from '../components/slash-command';
4
5
  import type { ProseSize } from '../primitives/chat-config';
6
+ import type { ChatMessageAction } from './chat-types';
5
7
  import type { ModelOption } from '../types';
6
8
 
7
9
  type Props = Omit<ChatThreadProps,
8
10
  'class' | 'onValueChange' | 'onSubmit' | 'onSuggestionClick' | 'onModelChange'
9
11
  | 'onMessageAction' | 'onSearch' | 'onVoice' | 'onSlashSelect'> & Record<string, unknown>;
10
12
 
11
- defineKitnElement<Props>('kitn-chat', {
13
+ interface Events {
14
+ /** User submitted a message. */
15
+ submit: { value: string; attachments: AttachmentData[] };
16
+ /** Fired on every input change. */
17
+ valuechange: { value: string };
18
+ /** A suggestion chip was clicked (only in `suggestion-mode="fill"`). */
19
+ suggestionclick: { value: string };
20
+ /** An action button on a message was clicked. */
21
+ messageaction: { messageId: string; action: ChatMessageAction };
22
+ /** The header model switcher changed. */
23
+ modelchange: { modelId: string };
24
+ /** A slash command was chosen from the palette. */
25
+ slashselect: { command: SlashCommandItem };
26
+ /** The Search button was clicked. */
27
+ search: Record<string, never>;
28
+ /** The Mic / voice button was clicked. */
29
+ voice: Record<string, never>;
30
+ }
31
+
32
+ defineWebComponent<Props, Events>('kc-chat', {
12
33
  messages: [], value: undefined, placeholder: 'Send a message...', loading: false,
13
34
  suggestions: undefined, suggestionMode: 'submit', proseSize: 'sm',
14
35
  codeTheme: 'github-dark-dimmed', codeHighlight: true, chatTitle: undefined,