@kitnai/chat 0.7.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 (212) hide show
  1. package/README.md +9 -9
  2. package/dist/custom-elements.json +1626 -883
  3. package/dist/kitn-chat.es.js +36 -36
  4. package/dist/llms/llms-full.txt +303 -142
  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 +356 -189
  19. package/frameworks/react/runtime.tsx +2 -2
  20. package/llms-full.txt +303 -142
  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 -20
  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 -22
  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 -19
  83. package/src/elements/chat-scope-picker.tsx +4 -4
  84. package/src/elements/{kitn-chat-workspace.stories.tsx → chat-workspace.stories.tsx} +15 -23
  85. package/src/elements/chat-workspace.tsx +2 -2
  86. package/src/elements/{kitn-chat.stories.tsx → chat.stories.tsx} +12 -20
  87. package/src/elements/chat.tsx +2 -2
  88. package/src/elements/{kitn-checkpoint.stories.tsx → checkpoint.stories.tsx} +11 -20
  89. package/src/elements/checkpoint.tsx +4 -4
  90. package/src/elements/{kitn-code-block.stories.tsx → code-block.stories.tsx} +10 -19
  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 -19
  97. package/src/elements/context-meter.tsx +3 -3
  98. package/src/elements/{kitn-conversation-list.stories.tsx → conversation-list.stories.tsx} +12 -20
  99. package/src/elements/conversation-list.tsx +2 -2
  100. package/src/elements/css.ts +1 -1
  101. package/src/elements/define.tsx +10 -10
  102. package/src/elements/element-meta.json +1379 -733
  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 -21
  107. package/src/elements/empty.tsx +3 -3
  108. package/src/elements/{kitn-feedback-bar.stories.tsx → feedback-bar.stories.tsx} +11 -20
  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 -21
  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 -19
  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 -20
  121. package/src/elements/loader.tsx +3 -3
  122. package/src/elements/{kitn-markdown.stories.tsx → markdown.stories.tsx} +10 -19
  123. package/src/elements/markdown.tsx +3 -3
  124. package/src/elements/{kitn-message-skills.stories.tsx → message-skills.stories.tsx} +10 -19
  125. package/src/elements/message-skills.tsx +3 -3
  126. package/src/elements/{kitn-message.stories.tsx → message.stories.tsx} +12 -21
  127. package/src/elements/message.tsx +5 -5
  128. package/src/elements/{kitn-model-switcher.stories.tsx → model-switcher.stories.tsx} +10 -19
  129. package/src/elements/model-switcher.tsx +5 -5
  130. package/src/elements/{kitn-prompt-input.stories.tsx → prompt-input.stories.tsx} +14 -22
  131. package/src/elements/prompt-input.tsx +3 -3
  132. package/src/elements/{kitn-prompt-suggestions.stories.tsx → prompt-suggestions.stories.tsx} +13 -22
  133. package/src/elements/prompt-suggestions.tsx +4 -4
  134. package/src/elements/{kitn-reasoning.stories.tsx → reasoning.stories.tsx} +10 -19
  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 -19
  140. package/src/elements/response-stream.tsx +4 -4
  141. package/src/elements/{kitn-source-list.stories.tsx → source-list.stories.tsx} +11 -20
  142. package/src/elements/{kitn-source.stories.tsx → source.stories.tsx} +12 -21
  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 -19
  148. package/src/elements/text-shimmer.tsx +3 -3
  149. package/src/elements/{kitn-thinking-bar.stories.tsx → thinking-bar.stories.tsx} +11 -20
  150. package/src/elements/thinking-bar.tsx +5 -5
  151. package/src/elements/{kitn-tool.stories.tsx → tool.stories.tsx} +10 -19
  152. package/src/elements/tool.tsx +3 -3
  153. package/src/elements/{kitn-voice-input.stories.tsx → voice-input.stories.tsx} +10 -19
  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 +32 -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
  212. package/src/stories/docs/element-spec.tsx +0 -86
@@ -0,0 +1,34 @@
1
+ import { defineWebComponent } from './define';
2
+ import { LinkCard } from '../components/link-card';
3
+ import type { LinkCardData } from '../primitives/link-preview';
4
+ import { emitCardEvent } from '../primitives/card-routing';
5
+
6
+ interface Props extends Record<string, unknown> {
7
+ /** Stable card id correlating every emitted event. Set as an attribute or property. */
8
+ cardId?: string;
9
+ /** The link payload (OG metadata). Set as a JS **property** (object). */
10
+ data?: LinkCardData;
11
+ }
12
+
13
+ /**
14
+ * `<kc-link-card>` — a themed, accessible rich link / Open-Graph preview card. It
15
+ * renders from the supplied `data` (it never fetches; an app may register a
16
+ * `configureLinkPreview` fetcher for the bare-`{ url }` path). Activating the card
17
+ * dispatches the bubbling, composed **`kc-card`** CustomEvent with the contract
18
+ * `open` verb (`{ kind:'open', url, target:'tab' }`) so a host-level listener
19
+ * routes it through CardPolicy. Set `data` as a JS property; `card-id` via attribute.
20
+ */
21
+ defineWebComponent<Props>(
22
+ 'kc-link-card',
23
+ {
24
+ cardId: undefined,
25
+ data: undefined,
26
+ },
27
+ (props, { element }) => (
28
+ <LinkCard
29
+ cardId={props.cardId ?? ''}
30
+ data={props.data ?? ({ url: '' } as LinkCardData)}
31
+ onEmit={(event) => emitCardEvent(element, event)}
32
+ />
33
+ ),
34
+ );
@@ -1,14 +1,13 @@
1
1
  import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
2
  import './register'; // side effect: registers the custom elements
3
- import { ElementSpec } from '../stories/docs/element-spec';
4
- import { argTypesFor } from '../stories/docs/element-controls';
3
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
5
4
 
6
5
  // The web components are custom DOM elements, so declare the tags for JSX.
7
6
  declare module 'solid-js' {
8
7
  // eslint-disable-next-line @typescript-eslint/no-namespace
9
8
  namespace JSX {
10
9
  interface IntrinsicElements {
11
- 'kitn-loader': JSX.HTMLAttributes<HTMLElement> & {
10
+ 'kc-loader': JSX.HTMLAttributes<HTMLElement> & {
12
11
  variant?: string;
13
12
  size?: string;
14
13
  text?: string;
@@ -18,27 +17,25 @@ declare module 'solid-js' {
18
17
  }
19
18
 
20
19
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
21
- <kitn-loader variant="dots" size="md"></kitn-loader>
20
+ <kc-loader variant="dots" size="md"></kc-loader>
22
21
 
23
22
  <script type="module">
24
23
  import '@kitnai/chat/elements'; // registers the custom elements
25
24
  </script>`;
26
25
 
27
26
  const meta = {
28
- title: 'Web Components/kitn-loader',
27
+ title: 'Web Components/kc-loader',
29
28
  tags: ['autodocs'],
30
- argTypes: argTypesFor('kitn-loader'),
29
+ argTypes: argTypesFor('kc-loader'),
31
30
  parameters: {
32
31
  layout: 'fullscreen',
33
32
  docs: {
34
- description: {
35
- component: [
36
- '`<kitn-loader>` is the framework-agnostic **web component** for an animated busy indicator — a dozen styles (circular, dots, wave, bars, text-shimmer, …) selected via the `variant` attribute, isolated in **Shadow DOM**.',
33
+ description: specDescription('kc-loader', [
34
+ '`<kc-loader>` is the framework-agnostic **web component** for an animated busy indicator — a dozen styles (circular, dots, wave, bars, text-shimmer, …) selected via the `variant` attribute, isolated in **Shadow DOM**.',
37
35
  '**When to use:** showing a small "working" indicator anywhere outside the chat thread (toolbars, buttons, panels). In SolidJS, use the `Loader` primitive directly.',
38
36
  "**How to use:** register once with `import '@kitnai/chat/elements'`, then set `variant`, `size`, and (for text variants) `text` as plain HTML attributes.",
39
37
  'See the **Code** tab for HTML usage.',
40
- ].join('\n\n'),
41
- },
38
+ ]),
42
39
  },
43
40
  },
44
41
  } satisfies Meta;
@@ -46,12 +43,6 @@ const meta = {
46
43
  export default meta;
47
44
  type Story = StoryObj;
48
45
 
49
- /** Full generated API reference — properties, events, tokens, and composed-from. */
50
- export const API: Story = {
51
- render: () => <ElementSpec tag="kitn-loader" />,
52
- parameters: { layout: 'padded' },
53
- };
54
-
55
46
  const VARIANTS = [
56
47
  'circular', 'classic', 'pulse', 'pulse-dot', 'dots', 'typing',
57
48
  'wave', 'bars', 'terminal', 'text-blink', 'text-shimmer', 'loading-dots',
@@ -61,7 +52,7 @@ const VARIANTS = [
61
52
  export const Default: Story = {
62
53
  render: () => (
63
54
  <div style={{ padding: '24px' }}>
64
- <kitn-loader variant="circular" size="md" />
55
+ <kc-loader variant="circular" size="md" />
65
56
  </div>
66
57
  ),
67
58
  parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
@@ -73,7 +64,7 @@ export const AllVariants: Story = {
73
64
  <div style={{ display: 'flex', 'flex-wrap': 'wrap', gap: '32px', 'align-items': 'center', padding: '24px' }}>
74
65
  {VARIANTS.map((v) => (
75
66
  <div style={{ display: 'flex', 'flex-direction': 'column', 'align-items': 'center', gap: '8px', 'min-width': '90px' }}>
76
- <kitn-loader variant={v} size="md" text="Loading" />
67
+ <kc-loader variant={v} size="md" text="Loading" />
77
68
  <code style={{ 'font-size': '11px', opacity: 0.6 }}>{v}</code>
78
69
  </div>
79
70
  ))}
@@ -87,7 +78,7 @@ export const Sizes: Story = {
87
78
  <div style={{ display: 'flex', gap: '32px', 'align-items': 'center', padding: '24px' }}>
88
79
  {['sm', 'md', 'lg'].map((s) => (
89
80
  <div style={{ display: 'flex', 'flex-direction': 'column', 'align-items': 'center', gap: '8px' }}>
90
- <kitn-loader variant="dots" size={s} />
81
+ <kc-loader variant="dots" size={s} />
91
82
  <code style={{ 'font-size': '11px', opacity: 0.6 }}>{s}</code>
92
83
  </div>
93
84
  ))}
@@ -1,4 +1,4 @@
1
- import { defineKitnElement } from './define';
1
+ import { defineWebComponent } from './define';
2
2
  import { Loader, type LoaderVariant, type LoaderSize } from '../components/loader';
3
3
 
4
4
  interface Props extends Record<string, unknown> {
@@ -13,10 +13,10 @@ interface Props extends Record<string, unknown> {
13
13
  }
14
14
 
15
15
  /**
16
- * `<kitn-loader>` — an animated loader. `variant` selects the style (circular,
16
+ * `<kc-loader>` — an animated loader. `variant` selects the style (circular,
17
17
  * dots, wave, text-shimmer, …); `size` and `text` are attributes.
18
18
  */
19
- defineKitnElement<Props>('kitn-loader', {
19
+ defineWebComponent<Props>('kc-loader', {
20
20
  variant: 'circular',
21
21
  size: 'md',
22
22
  text: undefined,
@@ -1,15 +1,14 @@
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 { ElementSpec } from '../stories/docs/element-spec';
5
- import { argTypesFor } from '../stories/docs/element-controls';
4
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
6
5
 
7
6
  // The web components are custom DOM elements, so declare the tags for JSX.
8
7
  declare module 'solid-js' {
9
8
  // eslint-disable-next-line @typescript-eslint/no-namespace
10
9
  namespace JSX {
11
10
  interface IntrinsicElements {
12
- 'kitn-markdown': JSX.HTMLAttributes<HTMLElement>;
11
+ 'kc-markdown': JSX.HTMLAttributes<HTMLElement>;
13
12
  }
14
13
  }
15
14
  }
@@ -27,19 +26,19 @@ export function add(a: number, b: number): number {
27
26
  }
28
27
  \`\`\``;
29
28
 
30
- /** Render the actual `<kitn-markdown>` custom element with a `content` property. */
29
+ /** Render the actual `<kc-markdown>` custom element with a `content` property. */
31
30
  function MarkdownElement(props: { content: string }) {
32
31
  let el: (HTMLElement & { content?: string }) | undefined;
33
32
  onMount(() => {
34
33
  if (el) el.content = props.content;
35
34
  });
36
35
  return (
37
- <kitn-markdown ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px', 'max-width': '720px' }} />
36
+ <kc-markdown ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px', 'max-width': '720px' }} />
38
37
  );
39
38
  }
40
39
 
41
40
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
42
- <kitn-markdown id="md" code-theme="github-dark-dimmed"></kitn-markdown>
41
+ <kc-markdown id="md" code-theme="github-dark-dimmed"></kc-markdown>
43
42
 
44
43
  <script type="module">
45
44
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -50,20 +49,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
50
49
  </script>`;
51
50
 
52
51
  const meta = {
53
- title: 'Web Components/kitn-markdown',
52
+ title: 'Web Components/kc-markdown',
54
53
  tags: ['autodocs'],
55
- argTypes: argTypesFor('kitn-markdown'),
54
+ argTypes: argTypesFor('kc-markdown'),
56
55
  parameters: {
57
56
  layout: 'fullscreen',
58
57
  docs: {
59
- description: {
60
- component: [
61
- '`<kitn-markdown>` is the framework-agnostic **web component** that renders a markdown string (with fenced-code syntax highlighting via Shiki) as a standalone element, isolated in **Shadow DOM**.',
58
+ description: specDescription('kc-markdown', [
59
+ '`<kc-markdown>` is the framework-agnostic **web component** that renders a markdown string (with fenced-code syntax highlighting via Shiki) as a standalone element, isolated in **Shadow DOM**.',
62
60
  '**When to use:** showing model output or any markdown in a non-Solid app without pulling in a markdown stack. In SolidJS, use the `Markdown` primitive directly.',
63
61
  "**How to use:** register once with `import '@kitnai/chat/elements'`, set the source via the `content` **property** (`el.content = '...'`), and tune rendering with the `prose-size`, `code-theme`, and `code-highlight` attributes.",
64
62
  'See the **Code** tab for HTML usage.',
65
- ].join('\n\n'),
66
- },
63
+ ]),
67
64
  },
68
65
  },
69
66
  } satisfies Meta;
@@ -71,12 +68,6 @@ const meta = {
71
68
  export default meta;
72
69
  type Story = StoryObj;
73
70
 
74
- /** Full generated API reference — properties, events, tokens, and composed-from. */
75
- export const API: Story = {
76
- render: () => <ElementSpec tag="kitn-markdown" />,
77
- parameters: { layout: 'padded' },
78
- };
79
-
80
71
  /** Headings, emphasis, lists, a blockquote, and a highlighted code fence. */
81
72
  export const Default: Story = {
82
73
  render: () => <MarkdownElement content={sampleMarkdown} />,
@@ -1,4 +1,4 @@
1
- import { defineKitnElement } from './define';
1
+ import { defineWebComponent } from './define';
2
2
  import { Markdown } from '../components/markdown';
3
3
  import { ChatConfig, useChatConfig, type ProseSize } from '../primitives/chat-config';
4
4
 
@@ -14,11 +14,11 @@ interface Props extends Record<string, unknown> {
14
14
  }
15
15
 
16
16
  /**
17
- * `<kitn-markdown>` — renders markdown (with fenced-code syntax highlighting) as
17
+ * `<kc-markdown>` — renders markdown (with fenced-code syntax highlighting) as
18
18
  * a standalone element. Content via the `content` property; sizing/highlighting
19
19
  * via attributes.
20
20
  */
21
- defineKitnElement<Props>('kitn-markdown', {
21
+ defineWebComponent<Props>('kc-markdown', {
22
22
  content: '',
23
23
  proseSize: 'sm',
24
24
  codeTheme: 'github-dark-dimmed',
@@ -1,15 +1,14 @@
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 { ElementSpec } from '../stories/docs/element-spec';
5
- import { argTypesFor } from '../stories/docs/element-controls';
4
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
6
5
 
7
6
  // The web components are custom DOM elements, so declare the tags for JSX.
8
7
  declare module 'solid-js' {
9
8
  // eslint-disable-next-line @typescript-eslint/no-namespace
10
9
  namespace JSX {
11
10
  interface IntrinsicElements {
12
- 'kitn-message-skills': JSX.HTMLAttributes<HTMLElement>;
11
+ 'kc-skills': JSX.HTMLAttributes<HTMLElement>;
13
12
  }
14
13
  }
15
14
  }
@@ -24,19 +23,19 @@ const sampleSkills: Skill[] = [
24
23
  { id: 's2', name: 'code' },
25
24
  ];
26
25
 
27
- /** Render the actual `<kitn-message-skills>` custom element with a `skills` property. */
26
+ /** Render the actual `<kc-skills>` custom element with a `skills` property. */
28
27
  function MessageSkillsElement(props: { skills: Skill[] }) {
29
28
  let el: (HTMLElement & { skills?: Skill[] }) | undefined;
30
29
  onMount(() => {
31
30
  if (el) el.skills = props.skills;
32
31
  });
33
32
  return (
34
- <kitn-message-skills ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px' }} />
33
+ <kc-skills ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px' }} />
35
34
  );
36
35
  }
37
36
 
38
37
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
39
- <kitn-message-skills id="skills"></kitn-message-skills>
38
+ <kc-skills id="skills"></kc-skills>
40
39
 
41
40
  <script type="module">
42
41
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -49,20 +48,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
49
48
  </script>`;
50
49
 
51
50
  const meta = {
52
- title: 'Web Components/kitn-message-skills',
51
+ title: 'Web Components/kc-skills',
53
52
  tags: ['autodocs'],
54
- argTypes: argTypesFor('kitn-message-skills'),
53
+ argTypes: argTypesFor('kc-skills'),
55
54
  parameters: {
56
55
  layout: 'fullscreen',
57
56
  docs: {
58
- description: {
59
- component: [
60
- '`<kitn-message-skills>` is the framework-agnostic **web component** that badges which skills were active for a message, isolated in **Shadow DOM**.',
57
+ description: specDescription('kc-skills', [
58
+ '`<kc-skills>` is the framework-agnostic **web component** that badges which skills were active for a message, isolated in **Shadow DOM**.',
61
59
  '**When to use:** annotating a message row with the skills/tools it used, in a non-Solid app. In SolidJS, use the `MessageSkills` primitive directly.',
62
60
  "**How to use:** register once with `import '@kitnai/chat/elements'`, then set the `skills` **property** to an array of `{ id, name }`.",
63
61
  'See the **Code** tab for HTML usage.',
64
- ].join('\n\n'),
65
- },
62
+ ]),
66
63
  },
67
64
  },
68
65
  } satisfies Meta;
@@ -70,12 +67,6 @@ const meta = {
70
67
  export default meta;
71
68
  type Story = StoryObj;
72
69
 
73
- /** Full generated API reference — properties, events, tokens, and composed-from. */
74
- export const API: Story = {
75
- render: () => <ElementSpec tag="kitn-message-skills" />,
76
- parameters: { layout: 'padded' },
77
- };
78
-
79
70
  /** Two active-skill badges. */
80
71
  export const Default: Story = {
81
72
  render: () => <MessageSkillsElement skills={sampleSkills} />,
@@ -1,4 +1,4 @@
1
- import { defineKitnElement } from './define';
1
+ import { defineWebComponent } from './define';
2
2
  import { MessageSkills } from '../components/message-skills';
3
3
 
4
4
  interface Skill {
@@ -14,9 +14,9 @@ interface Props extends Record<string, unknown> {
14
14
  }
15
15
 
16
16
  /**
17
- * `<kitn-message-skills>` — badges showing which skills were active for a
17
+ * `<kc-skills>` — badges showing which skills were active for a
18
18
  * message. Data via the `skills` property.
19
19
  */
20
- defineKitnElement<Props>('kitn-message-skills', {
20
+ defineWebComponent<Props>('kc-skills', {
21
21
  skills: [],
22
22
  }, (props) => <MessageSkills skills={props.skills} />);
@@ -2,15 +2,14 @@ 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
4
  import type { ChatMessage } from './chat-types';
5
- import { ElementSpec } from '../stories/docs/element-spec';
6
- import { argTypesFor } from '../stories/docs/element-controls';
5
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
7
6
 
8
7
  // The web components are custom DOM elements, so declare the tags for JSX.
9
8
  declare module 'solid-js' {
10
9
  // eslint-disable-next-line @typescript-eslint/no-namespace
11
10
  namespace JSX {
12
11
  interface IntrinsicElements {
13
- 'kitn-message': JSX.HTMLAttributes<HTMLElement>;
12
+ 'kc-message': JSX.HTMLAttributes<HTMLElement>;
14
13
  }
15
14
  }
16
15
  }
@@ -19,7 +18,7 @@ const assistantMessage: ChatMessage = {
19
18
  id: 'm-a',
20
19
  role: 'assistant',
21
20
  content:
22
- "Here's the plan, with a quick code sample:\n\n```js\nconst kit = useKitn();\n```\n\nThat wires the kit into your component.",
21
+ "Here's the plan, with a quick code sample:\n\n```js\nconst kit = useChat();\n```\n\nThat wires the kit into your component.",
23
22
  reasoning: { text: 'The user wants X, so I should do Y then Z.', label: 'Reasoning' },
24
23
  tools: [{ type: 'search', state: 'output-available', input: { query: 'kitn docs' }, output: { hits: 3 } }],
25
24
  attachments: [
@@ -44,19 +43,19 @@ const userMessage: ChatMessage = {
44
43
  content: 'How do I compose these myself?',
45
44
  };
46
45
 
47
- /** Render the actual `<kitn-message>` custom element with a `message` property. */
46
+ /** Render the actual `<kc-message>` custom element with a `message` property. */
48
47
  function MessageElement(props: { message: ChatMessage }) {
49
48
  let el: (HTMLElement & { message?: ChatMessage }) | undefined;
50
49
  onMount(() => {
51
50
  if (el) el.message = props.message;
52
51
  });
53
52
  return (
54
- <kitn-message ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px', 'max-width': '720px' }} />
53
+ <kc-message ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px', 'max-width': '720px' }} />
55
54
  );
56
55
  }
57
56
 
58
57
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
59
- <kitn-message id="msg" style="display:block;"></kitn-message>
58
+ <kc-message id="msg" style="display:block;"></kc-message>
60
59
 
61
60
  <script type="module">
62
61
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -64,7 +63,7 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
64
63
  const msg = document.getElementById('msg');
65
64
  msg.message = {
66
65
  id: 'm-a', role: 'assistant',
67
- content: "Here's the plan:\\n\\n\\\`\\\`\\\`js\\nconst kit = useKitn();\\n\\\`\\\`\\\`",
66
+ content: "Here's the plan:\\n\\n\\\`\\\`\\\`js\\nconst kit = useChat();\\n\\\`\\\`\\\`",
68
67
  reasoning: { text: 'The user wants X, so I should do Y.' },
69
68
  tools: [{ type: 'search', state: 'output-available', output: { hits: 3 } }],
70
69
  actions: ['copy', 'like', 'dislike', 'regenerate'],
@@ -75,20 +74,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
75
74
  </script>`;
76
75
 
77
76
  const meta = {
78
- title: 'Web Components/kitn-message',
77
+ title: 'Web Components/kc-message',
79
78
  tags: ['autodocs'],
80
- argTypes: argTypesFor('kitn-message'),
79
+ argTypes: argTypesFor('kc-message'),
81
80
  parameters: {
82
81
  layout: 'fullscreen',
83
82
  docs: {
84
- description: {
85
- component: [
86
- '`<kitn-message>` is the framework-agnostic **web component** for a single message row — markdown/plain content, an optional reasoning block, tool calls, attachments, and action buttons — all rendered from one `message` object (the same shape `<kitn-chat>` uses per message). It is the keystone of the "compose your own message list" pattern, isolated in **Shadow DOM**.',
83
+ description: specDescription('kc-message', [
84
+ '`<kc-message>` is the framework-agnostic **web component** for a single message row — markdown/plain content, an optional reasoning block, tool calls, attachments, and action buttons — all rendered from one `message` object (the same shape `<kc-chat>` uses per message). It is the keystone of the "compose your own message list" pattern, isolated in **Shadow DOM**.',
87
85
  "**When to use:** building a custom message thread in a non-Solid app, or anywhere you want to lay out the list yourself but keep the kit's rich message rendering. In SolidJS, compose the `Message` primitives for finer control.",
88
86
  "**How to use:** register once with `import '@kitnai/chat/elements'`, set the whole row via the `message` **property** (`el.message = {...}`), and listen for the `messageaction` **CustomEvent** for action-button clicks. For simple cases, set `role` + `content` attributes instead of a full object.",
89
87
  'See the **Code** tab for HTML usage.',
90
- ].join('\n\n'),
91
- },
88
+ ]),
92
89
  },
93
90
  },
94
91
  } satisfies Meta;
@@ -96,12 +93,6 @@ const meta = {
96
93
  export default meta;
97
94
  type Story = StoryObj;
98
95
 
99
- /** Full generated API reference — properties, events, tokens, and composed-from. */
100
- export const API: Story = {
101
- render: () => <ElementSpec tag="kitn-message" />,
102
- parameters: { layout: 'padded' },
103
- };
104
-
105
96
  /** A rich assistant message: markdown, reasoning, a tool call, an attachment, and actions. */
106
97
  export const Assistant: Story = {
107
98
  render: () => <MessageElement message={assistantMessage} />,
@@ -1,5 +1,5 @@
1
1
  import { For, Show, type Component } from 'solid-js';
2
- import { defineKitnElement } from './define';
2
+ import { defineWebComponent } from './define';
3
3
  import { ChatConfig, useChatConfig, type ProseSize } from '../primitives/chat-config';
4
4
  import { Message, MessageContent, MessageActions } from '../components/message';
5
5
  import { Reasoning, ReasoningTrigger, ReasoningContent } from '../components/reasoning';
@@ -26,7 +26,7 @@ interface Props extends Record<string, unknown> {
26
26
  codeHighlight?: boolean;
27
27
  }
28
28
 
29
- /** Events fired by `<kitn-message>`. */
29
+ /** Events fired by `<kc-message>`. */
30
30
  interface Events {
31
31
  /** An action button was clicked. */
32
32
  messageaction: { messageId: string; action: ChatMessageAction };
@@ -40,12 +40,12 @@ const ACTION_ICON: Record<ChatMessageAction, Component<{ class?: string }>> = {
40
40
  };
41
41
 
42
42
  /**
43
- * `<kitn-message>` — a single message row: markdown/plain content, reasoning,
43
+ * `<kc-message>` — a single message row: markdown/plain content, reasoning,
44
44
  * tool calls, attachments, and action buttons, rendered from one `message`
45
- * object (the same shape `<kitn-chat>` uses per message). The keystone of the
45
+ * object (the same shape `<kc-chat>` uses per message). The keystone of the
46
46
  * "compose your own message list" pattern. Emits `messageaction`.
47
47
  */
48
- defineKitnElement<Props, Events>('kitn-message', {
48
+ defineWebComponent<Props, Events>('kc-message', {
49
49
  message: undefined,
50
50
  role: 'assistant',
51
51
  content: undefined,
@@ -2,15 +2,14 @@ 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
4
  import type { ModelOption } from '../types';
5
- import { ElementSpec } from '../stories/docs/element-spec';
6
- import { argTypesFor } from '../stories/docs/element-controls';
5
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
7
6
 
8
7
  // The web components are custom DOM elements, so declare the tags for JSX.
9
8
  declare module 'solid-js' {
10
9
  // eslint-disable-next-line @typescript-eslint/no-namespace
11
10
  namespace JSX {
12
11
  interface IntrinsicElements {
13
- 'kitn-model-switcher': JSX.HTMLAttributes<HTMLElement>;
12
+ 'kc-model-switcher': JSX.HTMLAttributes<HTMLElement>;
14
13
  }
15
14
  }
16
15
  }
@@ -21,7 +20,7 @@ const models: ModelOption[] = [
21
20
  { id: 'haiku', name: 'Claude Haiku', provider: 'Anthropic' },
22
21
  ];
23
22
 
24
- /** Render `<kitn-model-switcher>` with `models` set as a property; tracks selection. */
23
+ /** Render `<kc-model-switcher>` with `models` set as a property; tracks selection. */
25
24
  function SwitcherElement(props: { models: ModelOption[]; current?: string }) {
26
25
  let el: (HTMLElement & { models?: ModelOption[]; currentModel?: string }) | undefined;
27
26
  onMount(() => {
@@ -35,12 +34,12 @@ function SwitcherElement(props: { models: ModelOption[]; current?: string }) {
35
34
  });
36
35
  });
37
36
  return (
38
- <kitn-model-switcher ref={(e) => (el = e as HTMLElement)} style={{ display: 'inline-block', padding: '40px' }} />
37
+ <kc-model-switcher ref={(e) => (el = e as HTMLElement)} style={{ display: 'inline-block', padding: '40px' }} />
39
38
  );
40
39
  }
41
40
 
42
41
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
43
- <kitn-model-switcher id="ms"></kitn-model-switcher>
42
+ <kc-model-switcher id="ms"></kc-model-switcher>
44
43
 
45
44
  <script type="module">
46
45
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -55,20 +54,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
55
54
  </script>`;
56
55
 
57
56
  const meta = {
58
- title: 'Web Components/kitn-model-switcher',
57
+ title: 'Web Components/kc-model-switcher',
59
58
  tags: ['autodocs'],
60
- argTypes: argTypesFor('kitn-model-switcher'),
59
+ argTypes: argTypesFor('kc-model-switcher'),
61
60
  parameters: {
62
61
  layout: 'fullscreen',
63
62
  docs: {
64
- description: {
65
- component: [
66
- '`<kitn-model-switcher>` is the framework-agnostic **web component** for picking the active model — a dropdown showing each model\'s name and provider — isolated in **Shadow DOM**. It mirrors the switcher inside `<kitn-chat>` as a standalone, composable piece.',
63
+ description: specDescription('kc-model-switcher', [
64
+ '`<kc-model-switcher>` is the framework-agnostic **web component** for picking the active model — a dropdown showing each model\'s name and provider — isolated in **Shadow DOM**. It mirrors the switcher inside `<kc-chat>` as a standalone, composable piece.',
67
65
  '**When to use:** building your own chat header and want the model picker on its own. In SolidJS, use the `ModelSwitcher` primitive.',
68
66
  "**How to use:** register once with `import '@kitnai/chat/elements'`, set the `models` **property** (and optionally `currentModel`), and listen for the `modelchange` **CustomEvent**. Note: like the underlying primitive, it only renders when more than one model is provided.",
69
67
  'See the **Code** tab for HTML usage.',
70
- ].join('\n\n'),
71
- },
68
+ ]),
72
69
  },
73
70
  },
74
71
  } satisfies Meta;
@@ -76,12 +73,6 @@ const meta = {
76
73
  export default meta;
77
74
  type Story = StoryObj;
78
75
 
79
- /** Full generated API reference — properties, events, tokens, and composed-from. */
80
- export const API: Story = {
81
- render: () => <ElementSpec tag="kitn-model-switcher" />,
82
- parameters: { layout: 'padded' },
83
- };
84
-
85
76
  /** A three-model picker; selecting updates the trigger label. */
86
77
  export const Default: Story = {
87
78
  render: () => <SwitcherElement models={models} current="opus" />,
@@ -1,4 +1,4 @@
1
- import { defineKitnElement } from './define';
1
+ import { defineWebComponent } from './define';
2
2
  import { ModelSwitcher } from '../components/model-switcher';
3
3
  import type { ModelOption } from '../types';
4
4
 
@@ -9,21 +9,21 @@ interface Props extends Record<string, unknown> {
9
9
  currentModel?: string;
10
10
  }
11
11
 
12
- /** Events fired by `<kitn-model-switcher>`. */
12
+ /** Events fired by `<kc-model-switcher>`. */
13
13
  interface Events {
14
14
  /** A model was selected. */
15
15
  modelchange: { modelId: string };
16
16
  }
17
17
 
18
18
  /**
19
- * `<kitn-model-switcher>` — an event-emitting leaf element. Data in via the
19
+ * `<kc-model-switcher>` — an event-emitting leaf element. Data in via the
20
20
  * `models` property, selection out via a `modelchange` event. Mirrors the
21
- * header switcher inside `<kitn-chat>` as a standalone, composable piece.
21
+ * header switcher inside `<kc-chat>` as a standalone, composable piece.
22
22
  *
23
23
  * Note: like the underlying primitive, this only renders when more than one
24
24
  * model is provided.
25
25
  */
26
- defineKitnElement<Props, Events>('kitn-model-switcher', {
26
+ defineWebComponent<Props, Events>('kc-model-switcher', {
27
27
  models: [],
28
28
  currentModel: undefined,
29
29
  }, (props, { dispatch }) => (