@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
  type Item = string | { label: string; value?: string };
6
7
 
@@ -9,7 +10,7 @@ declare module 'solid-js' {
9
10
  // eslint-disable-next-line @typescript-eslint/no-namespace
10
11
  namespace JSX {
11
12
  interface IntrinsicElements {
12
- 'kitn-prompt-suggestions': JSX.HTMLAttributes<HTMLElement> & {
13
+ 'kc-suggestions': JSX.HTMLAttributes<HTMLElement> & {
13
14
  variant?: string;
14
15
  size?: string;
15
16
  block?: boolean | string;
@@ -25,7 +26,7 @@ const suggestions: Item[] = [
25
26
  "What's deferred?",
26
27
  ];
27
28
 
28
- /** Render `<kitn-prompt-suggestions>` with `suggestions` set as a property. */
29
+ /** Render `<kc-suggestions>` with `suggestions` set as a property. */
29
30
  function SuggestionsElement(props: { suggestions: Item[]; variant?: string; size?: string; block?: boolean; highlight?: string }) {
30
31
  let el: (HTMLElement & { suggestions?: Item[] }) | undefined;
31
32
  onMount(() => {
@@ -37,7 +38,7 @@ function SuggestionsElement(props: { suggestions: Item[]; variant?: string; size
37
38
  });
38
39
  });
39
40
  return (
40
- <kitn-prompt-suggestions
41
+ <kc-suggestions
41
42
  ref={(e) => (el = e as HTMLElement)}
42
43
  variant={props.variant}
43
44
  size={props.size}
@@ -49,7 +50,7 @@ function SuggestionsElement(props: { suggestions: Item[]; variant?: string; size
49
50
  }
50
51
 
51
52
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
52
- <kitn-prompt-suggestions id="suggs" variant="outline"></kitn-prompt-suggestions>
53
+ <kc-suggestions id="suggs" variant="outline"></kc-suggestions>
53
54
 
54
55
  <script type="module">
55
56
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -60,19 +61,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
60
61
  </script>`;
61
62
 
62
63
  const meta = {
63
- title: 'Web Components/kitn-prompt-suggestions',
64
+ title: 'Web Components/kc-suggestions',
64
65
  tags: ['autodocs'],
66
+ argTypes: argTypesFor('kc-suggestions'),
65
67
  parameters: {
66
68
  layout: 'fullscreen',
67
69
  docs: {
68
- description: {
69
- component: [
70
- '`<kitn-prompt-suggestions>` is the framework-agnostic **web component** for a row (or list) of clickable suggestion chips — starter prompts or follow-ups — isolated in **Shadow DOM**.',
70
+ description: specDescription('kc-suggestions', [
71
+ '`<kc-suggestions>` is the framework-agnostic **web component** for a row (or list) of clickable suggestion chips — starter prompts or follow-ups — isolated in **Shadow DOM**.',
71
72
  '**When to use:** offering the user quick prompts to click instead of type, usually above an input. In SolidJS, use the `PromptSuggestion` primitive.',
72
73
  "**How to use:** register once with `import '@kitnai/chat/elements'`, set the `suggestions` **property** (strings, or `{ label, value }` when the displayed text differs from the emitted value), choose a `variant` and `size` (`sm` | `md` | `lg`; pills default to `lg`), optionally add the `block` flag for full-width rows or a `highlight` substring to emphasize, and listen for the `select` **CustomEvent**.",
73
74
  'See the **Code** tab for HTML usage.',
74
- ].join('\n\n'),
75
- },
75
+ ]),
76
76
  },
77
77
  },
78
78
  } satisfies Meta;
@@ -112,7 +112,7 @@ export const WithHighlightedSearch: Story = {
112
112
  parameters: {
113
113
  docs: {
114
114
  source: {
115
- code: `<kitn-prompt-suggestions id="suggs" highlight="Solid"></kitn-prompt-suggestions>
115
+ code: `<kc-suggestions id="suggs" highlight="Solid"></kc-suggestions>
116
116
 
117
117
  <script type="module">
118
118
  import '@kitnai/chat/elements';
@@ -147,9 +147,9 @@ export const Sizes: Story = {
147
147
  docs: {
148
148
  source: {
149
149
  code: `<!-- default pill -->
150
- <kitn-prompt-suggestions variant="outline"></kitn-prompt-suggestions>
150
+ <kc-suggestions variant="outline"></kc-suggestions>
151
151
  <!-- smaller pill -->
152
- <kitn-prompt-suggestions variant="outline" size="sm"></kitn-prompt-suggestions>`,
152
+ <kc-suggestions variant="outline" size="sm"></kc-suggestions>`,
153
153
  language: 'html',
154
154
  },
155
155
  },
@@ -1,5 +1,5 @@
1
1
  import { For } from 'solid-js';
2
- import { defineKitnElement } from './define';
2
+ import { defineWebComponent } from './define';
3
3
  import { PromptSuggestion } from '../components/prompt-suggestion';
4
4
 
5
5
  type Item = string | { label: string; value?: string };
@@ -19,7 +19,7 @@ interface Props extends Record<string, unknown> {
19
19
  highlight?: string;
20
20
  }
21
21
 
22
- /** Events fired by `<kitn-prompt-suggestions>`. */
22
+ /** Events fired by `<kc-suggestions>`. */
23
23
  interface Events {
24
24
  /** A suggestion was clicked. */
25
25
  select: { value: string };
@@ -29,11 +29,11 @@ const labelOf = (s: Item) => (typeof s === 'string' ? s : s.label);
29
29
  const valueOf = (s: Item) => (typeof s === 'string' ? s : s.value ?? s.label);
30
30
 
31
31
  /**
32
- * `<kitn-prompt-suggestions>` — a row/list of suggestion chips. Data via the
32
+ * `<kc-suggestions>` — a row/list of suggestion chips. Data via the
33
33
  * `suggestions` property; `variant`/`block`/`highlight` attributes; emits
34
34
  * `select`.
35
35
  */
36
- defineKitnElement<Props, Events>('kitn-prompt-suggestions', {
36
+ defineWebComponent<Props, Events>('kc-suggestions', {
37
37
  suggestions: [],
38
38
  variant: 'outline',
39
39
  size: undefined,
@@ -1,13 +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 { 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-reasoning': JSX.HTMLAttributes<HTMLElement>;
11
+ 'kc-reasoning': JSX.HTMLAttributes<HTMLElement>;
11
12
  }
12
13
  }
13
14
  }
@@ -15,7 +16,7 @@ declare module 'solid-js' {
15
16
  const sampleText =
16
17
  'First I parse the request, then I plan the steps, then I execute and verify each one before responding.';
17
18
 
18
- /** Render the actual `<kitn-reasoning>` custom element with a `text` property. */
19
+ /** Render the actual `<kc-reasoning>` custom element with a `text` property. */
19
20
  function ReasoningElement(props: { text: string; streaming?: boolean }) {
20
21
  let el: (HTMLElement & { text?: string; streaming?: boolean }) | undefined;
21
22
  onMount(() => {
@@ -25,12 +26,12 @@ function ReasoningElement(props: { text: string; streaming?: boolean }) {
25
26
  }
26
27
  });
27
28
  return (
28
- <kitn-reasoning ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px', 'max-width': '720px' }} />
29
+ <kc-reasoning ref={(e) => (el = e as HTMLElement)} style={{ display: 'block', padding: '16px', 'max-width': '720px' }} />
29
30
  );
30
31
  }
31
32
 
32
33
  const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
33
- <kitn-reasoning id="reason" label="Reasoning"></kitn-reasoning>
34
+ <kc-reasoning id="reason" label="Reasoning"></kc-reasoning>
34
35
 
35
36
  <script type="module">
36
37
  import '@kitnai/chat/elements'; // registers the custom elements
@@ -44,19 +45,18 @@ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
44
45
  </script>`;
45
46
 
46
47
  const meta = {
47
- title: 'Web Components/kitn-reasoning',
48
+ title: 'Web Components/kc-reasoning',
48
49
  tags: ['autodocs'],
50
+ argTypes: argTypesFor('kc-reasoning'),
49
51
  parameters: {
50
52
  layout: 'fullscreen',
51
53
  docs: {
52
- description: {
53
- component: [
54
- '`<kitn-reasoning>` is the framework-agnostic **web component** for a collapsible reasoning/thinking block that auto-expands while a thought is `streaming`, isolated in **Shadow DOM**.',
54
+ description: specDescription('kc-reasoning', [
55
+ '`<kc-reasoning>` is the framework-agnostic **web component** for a collapsible reasoning/thinking block that auto-expands while a thought is `streaming`, isolated in **Shadow DOM**.',
55
56
  '**When to use:** surfacing model chain-of-thought in a non-Solid app. In SolidJS, compose the `Reasoning` primitives directly.',
56
57
  "**How to use:** register once with `import '@kitnai/chat/elements'`, set the body via the `text` **property**, set the `streaming` flag while it streams in, optionally drive the controlled `open` property, and listen for the `openchange` **CustomEvent**.",
57
58
  'See the **Code** tab for HTML usage.',
58
- ].join('\n\n'),
59
- },
59
+ ]),
60
60
  },
61
61
  },
62
62
  } satisfies Meta;
@@ -1,4 +1,4 @@
1
- import { defineKitnElement } from './define';
1
+ import { defineWebComponent } from './define';
2
2
  import { Reasoning, ReasoningTrigger, ReasoningContent } from '../components/reasoning';
3
3
  import { ChatConfig, useChatConfig } from '../primitives/chat-config';
4
4
 
@@ -16,18 +16,18 @@ interface Props extends Record<string, unknown> {
16
16
  markdown?: boolean;
17
17
  }
18
18
 
19
- /** Events fired by `<kitn-reasoning>`. */
19
+ /** Events fired by `<kc-reasoning>`. */
20
20
  interface Events {
21
21
  /** Open state changed (via the trigger or streaming auto-open). */
22
22
  openchange: { open: boolean };
23
23
  }
24
24
 
25
25
  /**
26
- * `<kitn-reasoning>` — a collapsible reasoning/thinking block that auto-expands
26
+ * `<kc-reasoning>` — a collapsible reasoning/thinking block that auto-expands
27
27
  * while `streaming`. Text via the `text` property; `markdown`/`streaming` flags;
28
28
  * `open` is a controlled property; emits `openchange`.
29
29
  */
30
- defineKitnElement<Props, Events>('kitn-reasoning', {
30
+ defineWebComponent<Props, Events>('kc-reasoning', {
31
31
  text: '',
32
32
  label: 'Reasoning',
33
33
  open: undefined,
@@ -21,7 +21,7 @@ import './chat-scope-picker';
21
21
  // Phase 3 — input ecosystem
22
22
  // (NB: SlashCommand is context-bound to PromptInput — it observes the input
23
23
  // value via usePromptInput() — so it is NOT a standalone element. It will fold
24
- // into <kitn-prompt-input> as a `slash-commands` property in a later pass.)
24
+ // into <kc-prompt-input> as a `slash-commands` property in a later pass.)
25
25
  import './prompt-suggestions';
26
26
  import './file-upload';
27
27
  import './voice-input';
@@ -35,6 +35,16 @@ import './source';
35
35
  import './response-stream';
36
36
  import './empty';
37
37
  import './chain-of-thought';
38
+ import './resizable';
39
+ import './file-tree';
40
+ import './artifact';
41
+ // Generative-UI cards (Card Contract)
42
+ import './card';
43
+ import './form';
44
+ import './link-card';
45
+ import './embed';
46
+ import './confirm-card';
47
+ import './task-list-card';
38
48
 
39
49
  export type { ChatMessage, ChatMessageAction } from './chat-types';
40
50
  export { configureCodeHighlighting, isCodeHighlightingEnabled } from '../primitives/highlighter';
@@ -0,0 +1,200 @@
1
+ import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
+ import { createSignal, type JSX } from 'solid-js';
3
+ import './register'; // side effect: registers the custom elements
4
+ import { argTypesFor, specDescription } from '../stories/docs/element-controls';
5
+
6
+ // The web components are custom DOM elements, so declare the tags for JSX.
7
+ declare module 'solid-js' {
8
+ // eslint-disable-next-line @typescript-eslint/no-namespace
9
+ namespace JSX {
10
+ interface IntrinsicElements {
11
+ 'kc-resizable': JSX.HTMLAttributes<HTMLElement> & { orientation?: string };
12
+ 'kc-resizable-item': JSX.HTMLAttributes<HTMLElement> & {
13
+ size?: string; min?: string; max?: string; locked?: boolean | string; hidden?: boolean | string;
14
+ };
15
+ }
16
+ }
17
+ }
18
+
19
+ /** A labelled placeholder pane so the layout is visible in stories. */
20
+ function Pane(props: { label: string; tone?: 'muted' | 'plain' }) {
21
+ return (
22
+ <div
23
+ style={{
24
+ height: '100%',
25
+ display: 'flex',
26
+ 'align-items': 'center',
27
+ 'justify-content': 'center',
28
+ padding: '16px',
29
+ background: props.tone === 'plain' ? 'transparent' : 'var(--color-muted, #f4f4f5)',
30
+ color: 'var(--color-muted-foreground, #71717a)',
31
+ 'font-size': '13px',
32
+ }}
33
+ >
34
+ {props.label}
35
+ </div>
36
+ );
37
+ }
38
+
39
+ /** A bordered, sized frame the group fills. */
40
+ function Frame(props: { children: JSX.Element; tall?: boolean }) {
41
+ return (
42
+ <div
43
+ style={{
44
+ height: props.tall ? '384px' : '256px',
45
+ width: '100%',
46
+ 'max-width': '768px',
47
+ border: '1px solid var(--color-border, #e4e4e7)',
48
+ 'border-radius': '8px',
49
+ overflow: 'hidden',
50
+ }}
51
+ >
52
+ {props.children}
53
+ </div>
54
+ );
55
+ }
56
+
57
+ const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
58
+ <kc-resizable orientation="horizontal" style="display:block;height:400px">
59
+ <kc-resizable-item size="25%" min="160px"> ...list... </kc-resizable-item>
60
+ <kc-resizable-item> ...chat... </kc-resizable-item>
61
+ <kc-resizable-item size="30%"> ...preview... </kc-resizable-item>
62
+ </kc-resizable>
63
+
64
+ <script type="module">
65
+ import '@kitnai/chat/elements'; // registers the custom elements
66
+ document.querySelector('kc-resizable')
67
+ .addEventListener('change', (e) => console.log(e.detail.sizes));
68
+ </script>`;
69
+
70
+ const meta = {
71
+ title: 'Web Components/kc-resizable',
72
+ tags: ['autodocs'],
73
+ argTypes: argTypesFor('kc-resizable'),
74
+ parameters: {
75
+ layout: 'padded',
76
+ docs: {
77
+ description: specDescription('kc-resizable', [
78
+ '`<kc-resizable>` is the framework-agnostic **web component** for a composable, resizable multi-panel layout (up to **3** `<kc-resizable-item>` panels) with **auto-inserted draggable dividers** — isolated in **Shadow DOM**.',
79
+ '**When to use:** to compose an app shell out of slotted regions without hand-wiring panels and handles — e.g. `list | chat | preview`. In SolidJS, use the `Resizable` convenience (UI/Resizable) directly.',
80
+ "**How to use:** register once with `import '@kitnai/chat/elements'`, set `orientation` (`horizontal` row / `vertical` column), and put a `<kc-resizable-item>` per panel. Each item carries `size` (px or %, e.g. `\"280px\"` or `\"25%\"`), `min`/`max`, `locked` (fixed size + non-draggable neighbour), and `hidden` (drops the panel + its divider). Listen for the **`change`** event (`detail.sizes`, percent).",
81
+ '**Placement:** the layout spine for compose-your-own-chat shells — sidebar + conversation, conversation + inspector, or a three-up list/chat/preview.',
82
+ 'See the **Code** tab for HTML usage.',
83
+ ]),
84
+ },
85
+ },
86
+ args: { orientation: 'horizontal' },
87
+ } satisfies Meta;
88
+
89
+ export default meta;
90
+ type Story = StoryObj;
91
+
92
+ /** Interactive playground — flip orientation, then drag the dividers. */
93
+ export const Playground: Story = {
94
+ render: (args: { orientation?: string }) => (
95
+ <Frame>
96
+ <kc-resizable orientation={args.orientation ?? 'horizontal'}>
97
+ <kc-resizable-item size="25%" min="120px"><Pane label="List" /></kc-resizable-item>
98
+ <kc-resizable-item><Pane label="Chat" tone="plain" /></kc-resizable-item>
99
+ </kc-resizable>
100
+ </Frame>
101
+ ),
102
+ parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
103
+ };
104
+
105
+ /** Two panels: a sized list beside a flexible chat. */
106
+ export const ListChat: Story = {
107
+ name: 'Sidebar + chat',
108
+ render: () => (
109
+ <Frame>
110
+ <kc-resizable orientation="horizontal">
111
+ <kc-resizable-item size="28%" min="140px" max="50%"><Pane label="List" /></kc-resizable-item>
112
+ <kc-resizable-item><Pane label="Chat" tone="plain" /></kc-resizable-item>
113
+ </kc-resizable>
114
+ </Frame>
115
+ ),
116
+ };
117
+
118
+ /** Three panels, two draggable dividers. */
119
+ export const ListChatPreview: Story = {
120
+ name: 'List + chat + preview',
121
+ render: () => (
122
+ <Frame>
123
+ <kc-resizable orientation="horizontal">
124
+ <kc-resizable-item size="22%" min="120px"><Pane label="List" /></kc-resizable-item>
125
+ <kc-resizable-item><Pane label="Chat" tone="plain" /></kc-resizable-item>
126
+ <kc-resizable-item size="30%" min="160px"><Pane label="Preview" /></kc-resizable-item>
127
+ </kc-resizable>
128
+ </Frame>
129
+ ),
130
+ };
131
+
132
+ /** A locked, fixed-px sidebar — its divider is a static (non-draggable) separator. */
133
+ export const LockedSidebar: Story = {
134
+ name: 'Locked sidebar',
135
+ render: () => (
136
+ <Frame>
137
+ <kc-resizable orientation="horizontal">
138
+ <kc-resizable-item size="240px" locked><Pane label="Locked sidebar (240px)" /></kc-resizable-item>
139
+ <kc-resizable-item><Pane label="Chat" tone="plain" /></kc-resizable-item>
140
+ </kc-resizable>
141
+ </Frame>
142
+ ),
143
+ };
144
+
145
+ /** Stacked top/bottom split. */
146
+ export const Vertical: Story = {
147
+ name: 'Vertical split',
148
+ render: () => (
149
+ <Frame tall>
150
+ <kc-resizable orientation="vertical">
151
+ <kc-resizable-item size="40%" min="80px"><Pane label="Top" /></kc-resizable-item>
152
+ <kc-resizable-item><Pane label="Bottom" tone="plain" /></kc-resizable-item>
153
+ </kc-resizable>
154
+ </Frame>
155
+ ),
156
+ };
157
+
158
+ /** Toggle the preview panel — its divider drops and the rest reflow. */
159
+ export const HiddenToggle: Story = {
160
+ name: 'Show / hide a panel',
161
+ render: () => {
162
+ const [showPreview, setShowPreview] = createSignal(true);
163
+ let previewItem: HTMLElement | undefined;
164
+ const toggle = () => {
165
+ setShowPreview((v) => !v);
166
+ // Drive the boolean attribute directly so the group's MutationObserver
167
+ // re-lays out (Solid sets the `hidden` IDL property, which doesn't reflect
168
+ // to the attribute on a custom element).
169
+ if (previewItem) {
170
+ if (showPreview()) previewItem.removeAttribute('hidden');
171
+ else previewItem.setAttribute('hidden', '');
172
+ }
173
+ };
174
+ return (
175
+ <div style={{ display: 'flex', 'flex-direction': 'column', gap: '8px' }}>
176
+ <button
177
+ type="button"
178
+ onClick={toggle}
179
+ style={{
180
+ 'align-self': 'flex-start',
181
+ padding: '4px 12px',
182
+ 'font-size': '13px',
183
+ border: '1px solid var(--color-border, #e4e4e7)',
184
+ 'border-radius': '6px',
185
+ cursor: 'pointer',
186
+ }}
187
+ >
188
+ {showPreview() ? 'Hide preview' : 'Show preview'}
189
+ </button>
190
+ <Frame>
191
+ <kc-resizable orientation="horizontal">
192
+ <kc-resizable-item size="24%" min="120px"><Pane label="List" /></kc-resizable-item>
193
+ <kc-resizable-item><Pane label="Chat" tone="plain" /></kc-resizable-item>
194
+ <kc-resizable-item ref={(e) => (previewItem = e as HTMLElement)} size="30%"><Pane label="Preview" /></kc-resizable-item>
195
+ </kc-resizable>
196
+ </Frame>
197
+ </div>
198
+ );
199
+ },
200
+ };