@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
|
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
|
-
'
|
|
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 `<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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/
|
|
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
|
-
|
|
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
|
-
]
|
|
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: `<
|
|
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
|
-
<
|
|
150
|
+
<kc-suggestions variant="outline"></kc-suggestions>
|
|
151
151
|
<!-- smaller pill -->
|
|
152
|
-
<
|
|
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 {
|
|
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 `<
|
|
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
|
-
* `<
|
|
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
|
-
|
|
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
|
-
'
|
|
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 `<
|
|
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
|
-
<
|
|
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
|
-
<
|
|
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/
|
|
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
|
-
|
|
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
|
-
]
|
|
59
|
-
},
|
|
59
|
+
]),
|
|
60
60
|
},
|
|
61
61
|
},
|
|
62
62
|
} satisfies Meta;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
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 `<
|
|
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
|
-
* `<
|
|
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
|
-
|
|
30
|
+
defineWebComponent<Props, Events>('kc-reasoning', {
|
|
31
31
|
text: '',
|
|
32
32
|
label: 'Reasoning',
|
|
33
33
|
open: undefined,
|
package/src/elements/register.ts
CHANGED
|
@@ -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 <
|
|
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
|
+
};
|