@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.
- package/README.md +9 -9
- package/dist/custom-elements.json +1676 -881
- package/dist/kitn-chat.es.js +36 -36
- package/dist/llms/llms-full.txt +316 -155
- package/dist/llms/llms.txt +18 -18
- package/dist/schemas/card-envelope.schema.json +14 -0
- package/dist/schemas/card-event.schema.json +12 -0
- package/dist/schemas/confirm.schema.json +65 -0
- package/dist/schemas/embed.schema.json +65 -0
- package/dist/schemas/form.result.schema.json +7 -0
- package/dist/schemas/form.schema.json +33 -0
- package/dist/schemas/link.schema.json +56 -0
- package/dist/schemas/task-list.result.schema.json +16 -0
- package/dist/schemas/task-list.schema.json +78 -0
- package/dist/theme.tokens.css +65 -65
- package/dist/tsx-B8rCNbgL.js +1 -0
- package/dist/typescript-RycA9KXf.js +1 -0
- package/frameworks/react/index.tsx +382 -193
- package/frameworks/react/runtime.tsx +2 -2
- package/llms-full.txt +316 -155
- package/llms.txt +18 -18
- package/package.json +5 -2
- package/src/components/artifact.stories.tsx +138 -0
- package/src/components/artifact.tsx +581 -0
- package/src/components/attachments.stories.tsx +7 -8
- package/src/components/attachments.tsx +2 -2
- package/src/components/card.tsx +110 -0
- package/src/components/chain-of-thought.stories.tsx +7 -8
- package/src/components/chat-container.stories.tsx +7 -8
- package/src/components/chat-container.tsx +4 -0
- package/src/components/checkpoint.stories.tsx +7 -8
- package/src/components/code-block.stories.tsx +8 -9
- package/src/components/component-meta.json +3411 -0
- package/src/components/confirm-card.stories.tsx +74 -0
- package/src/components/confirm-card.tsx +299 -0
- package/src/components/context.stories.tsx +7 -8
- package/src/components/conversation-item.stories.tsx +7 -8
- package/src/components/conversation-item.tsx +2 -2
- package/src/components/conversation-list.stories.tsx +7 -8
- package/src/components/conversation-list.tsx +1 -1
- package/src/components/embed.tsx +196 -0
- package/src/components/empty.stories.tsx +8 -9
- package/src/components/feedback-bar.stories.tsx +7 -8
- package/src/components/file-tree.stories.tsx +73 -0
- package/src/components/file-tree.tsx +383 -0
- package/src/components/file-upload.stories.tsx +7 -8
- package/src/components/form-widgets.tsx +461 -0
- package/src/components/form.tsx +796 -0
- package/src/components/image.stories.tsx +7 -8
- package/src/components/link-card.tsx +194 -0
- package/src/components/loader.stories.tsx +7 -8
- package/src/components/markdown.stories.tsx +7 -8
- package/src/components/message-narrow.stories.tsx +12 -13
- package/src/components/message-skills.stories.tsx +16 -17
- package/src/components/message.stories.tsx +17 -18
- package/src/components/model-switcher.stories.tsx +7 -8
- package/src/components/prompt-input.stories.tsx +8 -9
- package/src/components/prompt-suggestion.stories.tsx +7 -8
- package/src/components/prompt-suggestion.tsx +3 -3
- package/src/components/reasoning.stories.tsx +7 -8
- package/src/components/scroll-button.stories.tsx +7 -8
- package/src/components/slash-command.stories.tsx +8 -9
- package/src/components/slash-command.tsx +2 -2
- package/src/components/source.stories.tsx +7 -8
- package/src/components/source.tsx +1 -1
- package/src/components/task-list-card.stories.tsx +78 -0
- package/src/components/task-list-card.tsx +388 -0
- package/src/components/text-shimmer.stories.tsx +7 -8
- package/src/components/thinking-bar.stories.tsx +7 -8
- package/src/components/tool.stories.tsx +7 -8
- package/src/components/tool.tsx +2 -2
- package/src/components/voice-input.stories.tsx +7 -8
- package/src/elements/artifact.stories.tsx +291 -0
- package/src/elements/artifact.tsx +72 -0
- package/src/elements/{kitn-attachments.stories.tsx → attachments.stories.tsx} +11 -11
- package/src/elements/attachments.tsx +4 -4
- package/src/elements/card.stories.tsx +118 -0
- package/src/elements/card.tsx +40 -0
- package/src/elements/catalog.stories.tsx +491 -0
- package/src/elements/{kitn-chain-of-thought.stories.tsx → chain-of-thought.stories.tsx} +13 -13
- package/src/elements/chain-of-thought.tsx +3 -3
- package/src/elements/{kitn-chat-scope-picker.stories.tsx → chat-scope-picker.stories.tsx} +10 -10
- package/src/elements/chat-scope-picker.tsx +4 -4
- package/src/elements/{kitn-chat-workspace.stories.tsx → chat-workspace.stories.tsx} +71 -29
- package/src/elements/chat-workspace.tsx +29 -3
- package/src/elements/{kitn-chat.stories.tsx → chat.stories.tsx} +61 -16
- package/src/elements/chat.tsx +23 -2
- package/src/elements/{kitn-checkpoint.stories.tsx → checkpoint.stories.tsx} +11 -11
- package/src/elements/checkpoint.tsx +4 -4
- package/src/elements/{kitn-code-block.stories.tsx → code-block.stories.tsx} +10 -10
- package/src/elements/code-block.tsx +3 -3
- package/src/elements/compiled.css +1 -1
- package/src/elements/composed-shell.stories.tsx +316 -0
- package/src/elements/confirm-card.stories.tsx +186 -0
- package/src/elements/confirm-card.tsx +45 -0
- package/src/elements/{kitn-context-meter.stories.tsx → context-meter.stories.tsx} +10 -10
- package/src/elements/context-meter.tsx +3 -3
- package/src/elements/{kitn-conversation-list.stories.tsx → conversation-list.stories.tsx} +35 -22
- package/src/elements/conversation-list.tsx +11 -2
- package/src/elements/css.ts +1 -1
- package/src/elements/define.tsx +10 -10
- package/src/elements/element-meta.json +2649 -0
- package/src/elements/element-types.d.ts +251 -125
- package/src/elements/embed.stories.tsx +197 -0
- package/src/elements/embed.tsx +35 -0
- package/src/elements/{kitn-empty.stories.tsx → empty.stories.tsx} +12 -12
- package/src/elements/empty.tsx +3 -3
- package/src/elements/{kitn-feedback-bar.stories.tsx → feedback-bar.stories.tsx} +11 -11
- package/src/elements/feedback-bar.tsx +4 -4
- package/src/elements/file-tree.stories.tsx +133 -0
- package/src/elements/file-tree.tsx +52 -0
- package/src/elements/{kitn-file-upload.stories.tsx → file-upload.stories.tsx} +12 -12
- package/src/elements/file-upload.tsx +4 -4
- package/src/elements/form.stories.tsx +204 -0
- package/src/elements/form.tsx +37 -0
- package/src/elements/{kitn-image.stories.tsx → image.stories.tsx} +10 -10
- package/src/elements/image.tsx +3 -3
- package/src/elements/link-card.stories.tsx +193 -0
- package/src/elements/link-card.tsx +34 -0
- package/src/elements/{kitn-loader.stories.tsx → loader.stories.tsx} +11 -11
- package/src/elements/loader.tsx +3 -3
- package/src/elements/{kitn-markdown.stories.tsx → markdown.stories.tsx} +10 -10
- package/src/elements/markdown.tsx +3 -3
- package/src/elements/{kitn-message-skills.stories.tsx → message-skills.stories.tsx} +10 -10
- package/src/elements/message-skills.tsx +3 -3
- package/src/elements/{kitn-message.stories.tsx → message.stories.tsx} +12 -12
- package/src/elements/message.tsx +5 -5
- package/src/elements/{kitn-model-switcher.stories.tsx → model-switcher.stories.tsx} +10 -10
- package/src/elements/model-switcher.tsx +5 -5
- package/src/elements/{kitn-prompt-input.stories.tsx → prompt-input.stories.tsx} +41 -19
- package/src/elements/prompt-input.tsx +5 -5
- package/src/elements/{kitn-prompt-suggestions.stories.tsx → prompt-suggestions.stories.tsx} +13 -13
- package/src/elements/prompt-suggestions.tsx +4 -4
- package/src/elements/{kitn-reasoning.stories.tsx → reasoning.stories.tsx} +10 -10
- package/src/elements/reasoning.tsx +4 -4
- package/src/elements/register.ts +11 -1
- package/src/elements/resizable.stories.tsx +200 -0
- package/src/elements/resizable.tsx +264 -0
- package/src/elements/{kitn-response-stream.stories.tsx → response-stream.stories.tsx} +10 -10
- package/src/elements/response-stream.tsx +4 -4
- package/src/elements/{kitn-source-list.stories.tsx → source-list.stories.tsx} +11 -11
- package/src/elements/{kitn-source.stories.tsx → source.stories.tsx} +12 -12
- package/src/elements/source.tsx +5 -5
- package/src/elements/styles.css +140 -1
- package/src/elements/task-list-card.stories.tsx +194 -0
- package/src/elements/task-list-card.tsx +40 -0
- package/src/elements/{kitn-text-shimmer.stories.tsx → text-shimmer.stories.tsx} +10 -10
- package/src/elements/text-shimmer.tsx +3 -3
- package/src/elements/{kitn-thinking-bar.stories.tsx → thinking-bar.stories.tsx} +11 -11
- package/src/elements/thinking-bar.tsx +5 -5
- package/src/elements/{kitn-tool.stories.tsx → tool.stories.tsx} +10 -10
- package/src/elements/tool.tsx +3 -3
- package/src/elements/{kitn-voice-input.stories.tsx → voice-input.stories.tsx} +10 -10
- package/src/elements/voice-input.tsx +4 -4
- package/src/index.ts +94 -2
- package/src/primitives/card-contract.ts +60 -0
- package/src/primitives/card-host.tsx +35 -0
- package/src/primitives/card-routing.ts +79 -0
- package/src/primitives/card-schemas/card-envelope.schema.json +14 -0
- package/src/primitives/card-schemas/card-event.schema.json +12 -0
- package/src/primitives/card-schemas/confirm.schema.json +65 -0
- package/src/primitives/card-schemas/embed.schema.json +65 -0
- package/src/primitives/card-schemas/form.result.schema.json +7 -0
- package/src/primitives/card-schemas/form.schema.json +33 -0
- package/src/primitives/card-schemas/link.schema.json +56 -0
- package/src/primitives/card-schemas/task-list.result.schema.json +16 -0
- package/src/primitives/card-schemas/task-list.schema.json +78 -0
- package/src/primitives/card-validate.ts +95 -0
- package/src/primitives/embed-providers.ts +254 -0
- package/src/primitives/highlighter.ts +4 -0
- package/src/primitives/link-preview.ts +87 -0
- package/src/primitives/pdf-preview.ts +121 -0
- package/src/stories/chat-panel-layout.stories.tsx +2 -1
- package/src/stories/chat-scene.tsx +22 -21
- package/src/stories/checkpoint-restore.stories.tsx +10 -10
- package/src/stories/conversation-with-reasoning.stories.tsx +4 -4
- package/src/stories/conversation-with-sources.stories.tsx +7 -7
- package/src/stories/docs/Accessibility.mdx +2 -2
- package/src/stories/docs/ForAIAgents.mdx +3 -3
- package/src/stories/docs/GettingStarted.mdx +2 -2
- package/src/stories/docs/Installation.mdx +2 -2
- package/src/stories/docs/Integrations.mdx +29 -29
- package/src/stories/docs/Introduction.mdx +3 -3
- package/src/stories/docs/Theming.mdx +2 -2
- package/src/stories/docs/element-controls.ts +60 -0
- package/src/stories/docs/theme-editor/theme-editor.tsx +1 -0
- package/src/stories/examples/ChoosingComponents.mdx +94 -0
- package/src/stories/examples/sample-data.ts +79 -0
- package/src/stories/message-actions.stories.tsx +13 -13
- package/src/stories/pattern-centered-conversation.stories.tsx +3 -3
- package/src/stories/pattern-docked-widget.stories.tsx +1 -1
- package/src/stories/pattern-empty-state.stories.tsx +3 -3
- package/src/stories/prompt-input-variants.stories.tsx +13 -13
- package/src/stories/streaming-response.stories.tsx +3 -3
- package/src/stories/typography.stories.tsx +4 -4
- package/src/ui/avatar.stories.tsx +7 -8
- package/src/ui/badge.stories.tsx +7 -8
- package/src/ui/button.stories.tsx +8 -9
- package/src/ui/button.tsx +1 -0
- package/src/ui/collapsible.stories.tsx +6 -7
- package/src/ui/dropdown.stories.tsx +6 -7
- package/src/ui/hover-card.stories.tsx +6 -7
- package/src/ui/resizable.stories.tsx +74 -9
- package/src/ui/resizable.tsx +351 -71
- package/src/ui/scroll-area.stories.tsx +6 -7
- package/src/ui/scroll-area.tsx +3 -1
- package/src/ui/separator.stories.tsx +7 -8
- package/src/ui/skeleton.stories.tsx +7 -8
- package/src/ui/textarea.stories.tsx +6 -7
- package/src/ui/tooltip.stories.tsx +8 -9
- 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
|
-
'
|
|
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 `<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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/
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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 {
|
|
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
|
-
* `<
|
|
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
|
-
|
|
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
|
-
'
|
|
11
|
+
'kc-scope-picker': JSX.HTMLAttributes<HTMLElement> & {
|
|
11
12
|
'current-label'?: string;
|
|
12
13
|
};
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
17
|
|
|
17
|
-
/** Render `<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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/
|
|
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
|
-
|
|
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
|
-
]
|
|
60
|
-
},
|
|
60
|
+
]),
|
|
61
61
|
},
|
|
62
62
|
},
|
|
63
63
|
} satisfies Meta;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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 `<
|
|
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
|
-
* `<
|
|
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
|
-
|
|
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 <
|
|
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
|
-
'
|
|
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 `<
|
|
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
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
<
|
|
88
|
-
ref={(e) => (el = e as
|
|
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
|
-
<
|
|
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 <
|
|
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 <
|
|
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
|
-
<
|
|
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/
|
|
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
|
-
|
|
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
|
-
]
|
|
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
|
-
|
|
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 {
|
|
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
|
-
|
|
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 <
|
|
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
|
-
'
|
|
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
|
-
|
|
28
|
-
|
|
29
|
-
|
|
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)
|
|
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 <
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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/
|
|
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
|
-
|
|
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
|
-
]
|
|
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
|
-
|
|
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
|
+
|
package/src/elements/chat.tsx
CHANGED
|
@@ -1,14 +1,35 @@
|
|
|
1
|
-
import {
|
|
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
|
-
|
|
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,
|