@kitn.ai/ui 0.14.1 → 0.15.1
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/dist/kitn-chat.es.js +1 -1
- package/package.json +6 -1
- package/src/components/component-meta.json +10 -10
- package/src/elements/compiled.css +1 -1
- package/src/remote/host-embed.ts +1 -1
- package/src/components/artifact.stories.tsx +0 -138
- package/src/components/attachments.stories.tsx +0 -303
- package/src/components/attachments.test.tsx +0 -64
- package/src/components/chain-of-thought.stories.tsx +0 -211
- package/src/components/chat-container.stories.tsx +0 -187
- package/src/components/chat-thread.test.tsx +0 -58
- package/src/components/checkpoint.stories.tsx +0 -102
- package/src/components/code-block.stories.tsx +0 -150
- package/src/components/confirm-card.stories.tsx +0 -74
- package/src/components/context.stories.tsx +0 -229
- package/src/components/context.test.tsx +0 -133
- package/src/components/conversation-item.stories.tsx +0 -125
- package/src/components/conversation-list.stories.tsx +0 -133
- package/src/components/default-input.test.tsx +0 -111
- package/src/components/empty.stories.tsx +0 -434
- package/src/components/feedback-bar.stories.tsx +0 -138
- package/src/components/feedback-bar.test.tsx +0 -103
- package/src/components/file-tree.stories.tsx +0 -73
- package/src/components/file-upload.stories.tsx +0 -156
- package/src/components/image.stories.tsx +0 -89
- package/src/components/loader.stories.tsx +0 -181
- package/src/components/markdown.stories.tsx +0 -180
- package/src/components/message-action-bar.test.tsx +0 -128
- package/src/components/message-narrow.stories.tsx +0 -329
- package/src/components/message-skills.stories.tsx +0 -211
- package/src/components/message.stories.tsx +0 -281
- package/src/components/model-switcher.stories.tsx +0 -123
- package/src/components/model-switcher.test.tsx +0 -65
- package/src/components/prompt-input.stories.tsx +0 -222
- package/src/components/prompt-suggestion.stories.tsx +0 -142
- package/src/components/reasoning.stories.tsx +0 -140
- package/src/components/resizable.test.tsx +0 -226
- package/src/components/scroll-button.stories.tsx +0 -100
- package/src/components/slash-command.stories.tsx +0 -163
- package/src/components/source-list.test.tsx +0 -152
- package/src/components/source.stories.tsx +0 -124
- package/src/components/tasks-card.stories.tsx +0 -78
- package/src/components/text-shimmer.stories.tsx +0 -87
- package/src/components/thinking-bar.stories.tsx +0 -87
- package/src/components/tool.stories.tsx +0 -153
- package/src/components/voice-input.stories.tsx +0 -83
- package/src/elements/artifact.stories.tsx +0 -506
- package/src/elements/attachments.stories.tsx +0 -190
- package/src/elements/card.stories.tsx +0 -113
- package/src/elements/cards.stories.tsx +0 -59
- package/src/elements/catalog.stories.tsx +0 -491
- package/src/elements/chain-of-thought.declarative.test.tsx +0 -153
- package/src/elements/chain-of-thought.stories.tsx +0 -113
- package/src/elements/chat-scope-picker.stories.tsx +0 -73
- package/src/elements/chat-workspace.stories.tsx +0 -288
- package/src/elements/chat.stories.tsx +0 -151
- package/src/elements/checkpoint.stories.tsx +0 -72
- package/src/elements/choice.stories.tsx +0 -240
- package/src/elements/code-block.stories.tsx +0 -83
- package/src/elements/composed-shell.stories.tsx +0 -316
- package/src/elements/confirm-card.stories.tsx +0 -227
- package/src/elements/context-meter.stories.tsx +0 -151
- package/src/elements/conversation-list.declarative.test.tsx +0 -137
- package/src/elements/conversation-list.stories.tsx +0 -243
- package/src/elements/embed.stories.tsx +0 -213
- package/src/elements/empty.stories.tsx +0 -111
- package/src/elements/feedback-bar.stories.tsx +0 -114
- package/src/elements/file-tree.stories.tsx +0 -134
- package/src/elements/file-upload.stories.tsx +0 -82
- package/src/elements/form.stories.tsx +0 -248
- package/src/elements/image.stories.tsx +0 -71
- package/src/elements/link-preview.stories.tsx +0 -209
- package/src/elements/loader.stories.tsx +0 -88
- package/src/elements/markdown.stories.tsx +0 -76
- package/src/elements/message-skills.declarative.test.tsx +0 -104
- package/src/elements/message-skills.stories.tsx +0 -114
- package/src/elements/message.stories.tsx +0 -218
- package/src/elements/model-switcher.declarative.test.tsx +0 -130
- package/src/elements/model-switcher.stories.tsx +0 -198
- package/src/elements/popover.stories.tsx +0 -80
- package/src/elements/prompt-input-slash-command.test.tsx +0 -128
- package/src/elements/prompt-input-stoppable.test.tsx +0 -88
- package/src/elements/prompt-input-toolbar-actions.test.tsx +0 -120
- package/src/elements/prompt-input.stories.tsx +0 -331
- package/src/elements/prompt-suggestions.declarative.test.tsx +0 -164
- package/src/elements/prompt-suggestions.stories.tsx +0 -213
- package/src/elements/reasoning.stories.tsx +0 -77
- package/src/elements/remote.stories.tsx +0 -314
- package/src/elements/resizable.stories.tsx +0 -426
- package/src/elements/response-stream.stories.tsx +0 -79
- package/src/elements/scroll-button.stories.tsx +0 -202
- package/src/elements/scroll-button.test.tsx +0 -148
- package/src/elements/source-list.stories.tsx +0 -143
- package/src/elements/source.stories.tsx +0 -88
- package/src/elements/switch.stories.tsx +0 -56
- package/src/elements/tasks.stories.tsx +0 -237
- package/src/elements/text-shimmer.stories.tsx +0 -64
- package/src/elements/thinking-bar.stories.tsx +0 -72
- package/src/elements/tool.stories.tsx +0 -89
- package/src/elements/voice-input.stories.tsx +0 -88
- package/src/primitives/controllable.test.ts +0 -47
- package/src/stories/chat-panel-layout.stories.tsx +0 -145
- package/src/stories/chat-scene.tsx +0 -571
- package/src/stories/checkpoint-restore.stories.tsx +0 -256
- package/src/stories/context-usage.stories.tsx +0 -212
- package/src/stories/conversation-with-reasoning.stories.tsx +0 -182
- package/src/stories/conversation-with-sources.stories.tsx +0 -471
- package/src/stories/docs/Accessibility.mdx +0 -119
- package/src/stories/docs/ChildElements.mdx +0 -269
- package/src/stories/docs/ForAIAgents.mdx +0 -162
- package/src/stories/docs/GettingStarted.mdx +0 -65
- package/src/stories/docs/Installation.mdx +0 -83
- package/src/stories/docs/Introduction.mdx +0 -50
- package/src/stories/docs/SolidJsAdvanced.mdx +0 -17
- package/src/stories/docs/Theming.mdx +0 -85
- package/src/stories/docs/element-controls.ts +0 -121
- package/src/stories/docs/frameworks/Angular.mdx +0 -245
- package/src/stories/docs/frameworks/Html.mdx +0 -227
- package/src/stories/docs/frameworks/Overview.mdx +0 -47
- package/src/stories/docs/frameworks/React.mdx +0 -227
- package/src/stories/docs/frameworks/Solid.mdx +0 -173
- package/src/stories/docs/frameworks/Svelte.mdx +0 -194
- package/src/stories/docs/frameworks/Vue.mdx +0 -238
- package/src/stories/docs/generative-ui-overview.mdx +0 -186
- package/src/stories/docs/recipes/SpeechToText.mdx +0 -7
- package/src/stories/docs/recipes/Streaming.mdx +0 -68
- package/src/stories/docs/recipes/TextToSpeech.mdx +0 -35
- package/src/stories/docs/theme-editor/canvas.tsx +0 -32
- package/src/stories/docs/theme-editor/inspector.tsx +0 -66
- package/src/stories/docs/theme-editor/presets.test.ts +0 -32
- package/src/stories/docs/theme-editor/presets.ts +0 -64
- package/src/stories/docs/theme-editor/theme-css.test.ts +0 -19
- package/src/stories/docs/theme-editor/theme-css.ts +0 -15
- package/src/stories/docs/theme-editor/theme-editor.tsx +0 -146
- package/src/stories/docs/theme-tokens.tsx +0 -174
- package/src/stories/examples/ChoosingComponents.mdx +0 -106
- package/src/stories/examples/sample-data.ts +0 -79
- package/src/stories/examples/usage/checkpoint-restore.ts +0 -156
- package/src/stories/examples/usage/context-usage.ts +0 -591
- package/src/stories/examples/usage/conversation-with-reasoning.ts +0 -224
- package/src/stories/examples/usage/conversation-with-sources.ts +0 -589
- package/src/stories/examples/usage/empty-state.ts +0 -144
- package/src/stories/examples/usage/full-chat-app.ts +0 -277
- package/src/stories/examples/usage/index.ts +0 -63
- package/src/stories/examples/usage/message-actions.ts +0 -704
- package/src/stories/examples/usage/pattern-centered-conversation.ts +0 -446
- package/src/stories/examples/usage/pattern-chat-panel-layout.ts +0 -442
- package/src/stories/examples/usage/pattern-docked-widget.ts +0 -479
- package/src/stories/examples/usage/prompt-input-variants.ts +0 -1356
- package/src/stories/examples/usage/streaming-response.ts +0 -687
- package/src/stories/examples/usage/types.ts +0 -33
- package/src/stories/full-chat.stories.tsx +0 -18
- package/src/stories/message-actions.stories.tsx +0 -230
- package/src/stories/pattern-centered-conversation.stories.tsx +0 -93
- package/src/stories/pattern-docked-widget.stories.tsx +0 -93
- package/src/stories/pattern-empty-state.stories.tsx +0 -76
- package/src/stories/prompt-input-variants.stories.tsx +0 -456
- package/src/stories/streaming-response.stories.tsx +0 -438
- package/src/stories/theme-editor.stories.tsx +0 -16
- package/src/stories/token-reference.stories.tsx +0 -18
- package/src/stories/typography.stories.tsx +0 -78
- package/src/ui/avatar.stories.tsx +0 -103
- package/src/ui/badge.stories.tsx +0 -86
- package/src/ui/button.stories.tsx +0 -145
- package/src/ui/collapsible.stories.tsx +0 -69
- package/src/ui/dropdown.stories.tsx +0 -59
- package/src/ui/hover-card.stories.tsx +0 -77
- package/src/ui/hover-card.test.tsx +0 -30
- package/src/ui/overlay.stories.tsx +0 -115
- package/src/ui/popover.stories.tsx +0 -81
- package/src/ui/popover.test.tsx +0 -99
- package/src/ui/resizable.stories.tsx +0 -236
- package/src/ui/scroll-area.stories.tsx +0 -50
- package/src/ui/separator.stories.tsx +0 -81
- package/src/ui/skeleton.stories.tsx +0 -337
- package/src/ui/switch.stories.tsx +0 -51
- package/src/ui/switch.test.tsx +0 -59
- package/src/ui/textarea.stories.tsx +0 -76
- package/src/ui/tooltip.stories.tsx +0 -74
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from 'storybook-solidjs-vite';
|
|
2
|
-
import { fn } from 'storybook/test';
|
|
3
|
-
import { ConversationItem } from './conversation-item';
|
|
4
|
-
import { componentDescription } from '../stories/docs/element-controls';
|
|
5
|
-
|
|
6
|
-
const baseConversation = {
|
|
7
|
-
id: '1',
|
|
8
|
-
title: 'How to use SolidJS signals',
|
|
9
|
-
messageCount: 8,
|
|
10
|
-
lastMessageAt: '2026-04-10T12:00:00Z',
|
|
11
|
-
updatedAt: '2026-04-10T12:00:00Z',
|
|
12
|
-
scope: { type: 'document' as const },
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* A single selectable row in a conversation/chat list: title plus a message
|
|
17
|
-
* count, with an active (selected) state.
|
|
18
|
-
*/
|
|
19
|
-
const meta = {
|
|
20
|
-
title: 'Solid (Advanced)/Elements/ConversationItem',
|
|
21
|
-
component: ConversationItem,
|
|
22
|
-
tags: ['autodocs'],
|
|
23
|
-
parameters: {
|
|
24
|
-
layout: 'padded',
|
|
25
|
-
docs: {
|
|
26
|
-
description: componentDescription([
|
|
27
|
-
'A single conversation row — shows the title and message count, truncating long titles, with a highlighted active state.',
|
|
28
|
-
'**When to use:** as the leaf item inside a chat history sidebar. Usually rendered for you by `ConversationList`; use it directly to build a custom list.',
|
|
29
|
-
'**How to use:** pass a `conversation` summary, an `isActive` flag, and an `onSelect(id)` handler fired when the row is clicked.',
|
|
30
|
-
'**Placement:** inside a conversation/chat history sidebar list.',
|
|
31
|
-
]),
|
|
32
|
-
controls: { exclude: ['use:eventListener'] },
|
|
33
|
-
},
|
|
34
|
-
},
|
|
35
|
-
argTypes: {
|
|
36
|
-
conversation: {
|
|
37
|
-
control: 'object',
|
|
38
|
-
description: 'The conversation summary (id, title, messageCount, scope, timestamps).',
|
|
39
|
-
},
|
|
40
|
-
isActive: {
|
|
41
|
-
control: 'boolean',
|
|
42
|
-
description: 'Whether this row is the currently selected conversation.',
|
|
43
|
-
},
|
|
44
|
-
onSelect: {
|
|
45
|
-
action: 'select',
|
|
46
|
-
description: 'Fired with the conversation id when the row is clicked.',
|
|
47
|
-
table: { category: 'Events' },
|
|
48
|
-
},
|
|
49
|
-
},
|
|
50
|
-
args: {
|
|
51
|
-
conversation: baseConversation,
|
|
52
|
-
isActive: false,
|
|
53
|
-
onSelect: fn(),
|
|
54
|
-
},
|
|
55
|
-
render: (args) => (
|
|
56
|
-
<div class="w-64">
|
|
57
|
-
<ConversationItem {...args} />
|
|
58
|
-
</div>
|
|
59
|
-
),
|
|
60
|
-
} satisfies Meta<typeof ConversationItem>;
|
|
61
|
-
|
|
62
|
-
export default meta;
|
|
63
|
-
type Story = StoryObj<typeof meta>;
|
|
64
|
-
|
|
65
|
-
const IMPORT = `import { ConversationItem } from '@kitn.ai/ui';`;
|
|
66
|
-
const src = (code: string) => ({
|
|
67
|
-
parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } },
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
/** Interactive playground — toggle `isActive` and edit the conversation object. */
|
|
71
|
-
export const Playground: Story = {
|
|
72
|
-
...src(`<ConversationItem conversation={conversation} isActive={false} onSelect={(id) => {}} />`),
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
export const Active: Story = {
|
|
76
|
-
args: { isActive: true },
|
|
77
|
-
...src(`<ConversationItem conversation={conversation} isActive onSelect={(id) => {}} />`),
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export const Inactive: Story = {
|
|
81
|
-
args: { isActive: false },
|
|
82
|
-
...src(`<ConversationItem conversation={conversation} isActive={false} onSelect={(id) => {}} />`),
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
export const LongTitle: Story = {
|
|
86
|
-
args: {
|
|
87
|
-
conversation: {
|
|
88
|
-
...baseConversation,
|
|
89
|
-
title: 'This is a very long conversation title that should be truncated with an ellipsis',
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
...src(`<ConversationItem
|
|
93
|
-
conversation={{ ...conversation, title: 'A very long title…' }}
|
|
94
|
-
isActive={false}
|
|
95
|
-
onSelect={(id) => {}}
|
|
96
|
-
/>`),
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
/** Several items stacked, one active — showcase. */
|
|
100
|
-
export const MultipleItems: Story = {
|
|
101
|
-
render: (args: { onSelect: (id: string) => void }) => (
|
|
102
|
-
<div class="w-64 space-y-0.5">
|
|
103
|
-
<ConversationItem
|
|
104
|
-
conversation={{ ...baseConversation, id: '1', title: 'SolidJS reactive primitives' }}
|
|
105
|
-
isActive={true}
|
|
106
|
-
onSelect={args.onSelect}
|
|
107
|
-
/>
|
|
108
|
-
<ConversationItem
|
|
109
|
-
conversation={{ ...baseConversation, id: '2', title: 'TypeScript generics guide', messageCount: 12 }}
|
|
110
|
-
isActive={false}
|
|
111
|
-
onSelect={args.onSelect}
|
|
112
|
-
/>
|
|
113
|
-
<ConversationItem
|
|
114
|
-
conversation={{ ...baseConversation, id: '3', title: 'Tailwind CSS tips and tricks', messageCount: 3 }}
|
|
115
|
-
isActive={false}
|
|
116
|
-
onSelect={args.onSelect}
|
|
117
|
-
/>
|
|
118
|
-
</div>
|
|
119
|
-
),
|
|
120
|
-
...src(`<div class="space-y-0.5">
|
|
121
|
-
<ConversationItem conversation={c1} isActive onSelect={onSelect} />
|
|
122
|
-
<ConversationItem conversation={c2} isActive={false} onSelect={onSelect} />
|
|
123
|
-
<ConversationItem conversation={c3} isActive={false} onSelect={onSelect} />
|
|
124
|
-
</div>`),
|
|
125
|
-
};
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import type { Meta, StoryObj } from 'storybook-solidjs-vite';
|
|
2
|
-
import { fn } from 'storybook/test';
|
|
3
|
-
import { ConversationList, type ConversationListProps } from './conversation-list';
|
|
4
|
-
import type { ConversationSummary, ConversationGroup } from '../types';
|
|
5
|
-
import { componentDescription } from '../stories/docs/element-controls';
|
|
6
|
-
|
|
7
|
-
const scope = { type: 'document' as const };
|
|
8
|
-
|
|
9
|
-
const groups: ConversationGroup[] = [
|
|
10
|
-
{ id: 'today', name: 'Today', sortOrder: 0, createdAt: '2026-04-10' },
|
|
11
|
-
{ id: 'yesterday', name: 'Yesterday', sortOrder: 1, createdAt: '2026-04-09' },
|
|
12
|
-
{ id: 'week', name: 'This Week', sortOrder: 2, createdAt: '2026-04-07' },
|
|
13
|
-
];
|
|
14
|
-
|
|
15
|
-
const conversations: ConversationSummary[] = [
|
|
16
|
-
{ id: '1', title: 'SolidJS signals explained', groupId: 'today', scope, messageCount: 5, lastMessageAt: '2026-04-10T14:00:00Z', updatedAt: '2026-04-10T14:00:00Z' },
|
|
17
|
-
{ id: '2', title: 'TypeScript generics deep dive', groupId: 'today', scope, messageCount: 12, lastMessageAt: '2026-04-10T10:00:00Z', updatedAt: '2026-04-10T10:00:00Z' },
|
|
18
|
-
{ id: '3', title: 'CSS Grid vs Flexbox', groupId: 'yesterday', scope, messageCount: 8, lastMessageAt: '2026-04-09T16:00:00Z', updatedAt: '2026-04-09T16:00:00Z' },
|
|
19
|
-
{ id: '4', title: 'Setting up Storybook', groupId: 'yesterday', scope, messageCount: 3, lastMessageAt: '2026-04-09T11:00:00Z', updatedAt: '2026-04-09T11:00:00Z' },
|
|
20
|
-
{ id: '5', title: 'Vite configuration tips', groupId: 'week', scope, messageCount: 7, lastMessageAt: '2026-04-08T09:00:00Z', updatedAt: '2026-04-08T09:00:00Z' },
|
|
21
|
-
{ id: '6', title: 'Chrome extension manifest v3', groupId: 'week', scope, messageCount: 15, lastMessageAt: '2026-04-07T14:00:00Z', updatedAt: '2026-04-07T14:00:00Z' },
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* The conversation/chat history sidebar: a header with new-chat action, a search
|
|
26
|
-
* box, and grouped, collapsible lists of `ConversationItem`s.
|
|
27
|
-
*/
|
|
28
|
-
const meta = {
|
|
29
|
-
title: 'Solid (Advanced)/Elements/ConversationList',
|
|
30
|
-
component: ConversationList,
|
|
31
|
-
tags: ['autodocs'],
|
|
32
|
-
parameters: {
|
|
33
|
-
layout: 'padded',
|
|
34
|
-
docs: {
|
|
35
|
-
description: componentDescription([
|
|
36
|
-
'A full chat-history sidebar: header (sidebar toggle + new chat), a built-in search box that filters by title, and conversations bucketed into collapsible, count-badged groups.',
|
|
37
|
-
'**When to use:** as the left-hand navigation for a chat app — browsing, searching, and switching between past conversations.',
|
|
38
|
-
'**How to use:** pass `groups` and `conversations` arrays, the `activeId`, and handlers `onSelect(id)` / `onNewChat()` (plus optional `onToggleSidebar()`). Give it a sized, overflow-hidden container.',
|
|
39
|
-
'**Placement:** the persistent left sidebar of a chat layout.',
|
|
40
|
-
]),
|
|
41
|
-
controls: { exclude: ['use:eventListener'] },
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
argTypes: {
|
|
45
|
-
groups: {
|
|
46
|
-
control: 'object',
|
|
47
|
-
description: 'Conversation groups (buckets) to render as collapsible sections.',
|
|
48
|
-
},
|
|
49
|
-
conversations: {
|
|
50
|
-
control: 'object',
|
|
51
|
-
description: 'Conversation summaries; placed into groups by their `groupId`.',
|
|
52
|
-
},
|
|
53
|
-
activeId: {
|
|
54
|
-
control: 'text',
|
|
55
|
-
description: 'Id of the currently selected conversation.',
|
|
56
|
-
},
|
|
57
|
-
onSelect: {
|
|
58
|
-
action: 'select',
|
|
59
|
-
description: 'Fired with the conversation id when a row is clicked.',
|
|
60
|
-
table: { category: 'Events' },
|
|
61
|
-
},
|
|
62
|
-
onNewChat: {
|
|
63
|
-
action: 'newChat',
|
|
64
|
-
description: 'Fired when the new-chat (+) button is clicked.',
|
|
65
|
-
table: { category: 'Events' },
|
|
66
|
-
},
|
|
67
|
-
onToggleSidebar: {
|
|
68
|
-
action: 'toggleSidebar',
|
|
69
|
-
description: 'Fired when the sidebar-toggle (menu) button is clicked.',
|
|
70
|
-
table: { category: 'Events' },
|
|
71
|
-
},
|
|
72
|
-
},
|
|
73
|
-
args: {
|
|
74
|
-
groups,
|
|
75
|
-
conversations,
|
|
76
|
-
activeId: '1',
|
|
77
|
-
onSelect: fn(),
|
|
78
|
-
onNewChat: fn(),
|
|
79
|
-
onToggleSidebar: fn(),
|
|
80
|
-
},
|
|
81
|
-
render: (args) => (
|
|
82
|
-
<div class="h-[500px] w-72 border border-border rounded-lg overflow-hidden">
|
|
83
|
-
<ConversationList {...args} />
|
|
84
|
-
</div>
|
|
85
|
-
),
|
|
86
|
-
} satisfies Meta<typeof ConversationList>;
|
|
87
|
-
|
|
88
|
-
export default meta;
|
|
89
|
-
type Story = StoryObj<typeof meta>;
|
|
90
|
-
|
|
91
|
-
const IMPORT = `import { ConversationList } from '@kitn.ai/ui';`;
|
|
92
|
-
const src = (code: string) => ({
|
|
93
|
-
parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } },
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
const usage = `<ConversationList
|
|
97
|
-
groups={groups}
|
|
98
|
-
conversations={conversations}
|
|
99
|
-
activeId={activeId()}
|
|
100
|
-
onSelect={setActiveId}
|
|
101
|
-
onNewChat={() => {}}
|
|
102
|
-
/>`;
|
|
103
|
-
|
|
104
|
-
/** Interactive playground — edit the groups/conversations arrays and active id via controls. */
|
|
105
|
-
export const Playground: Story = {
|
|
106
|
-
...src(usage),
|
|
107
|
-
};
|
|
108
|
-
|
|
109
|
-
/** Conversations bucketed into Today / Yesterday / This Week. */
|
|
110
|
-
export const WithGroups: Story = {
|
|
111
|
-
...src(usage),
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
/** No conversations — the list renders just its header and search box. */
|
|
115
|
-
export const EmptyState: Story = {
|
|
116
|
-
args: { groups: [], conversations: [], activeId: undefined },
|
|
117
|
-
render: (args: ConversationListProps) => (
|
|
118
|
-
<div class="h-[400px] w-72 border border-border rounded-lg overflow-hidden">
|
|
119
|
-
<ConversationList {...args} />
|
|
120
|
-
</div>
|
|
121
|
-
),
|
|
122
|
-
...src(`<ConversationList
|
|
123
|
-
groups={[]}
|
|
124
|
-
conversations={[]}
|
|
125
|
-
onSelect={() => {}}
|
|
126
|
-
onNewChat={() => {}}
|
|
127
|
-
/>`),
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
/** Type in the built-in search box to filter conversations by title. */
|
|
131
|
-
export const WithSearch: Story = {
|
|
132
|
-
...src(usage),
|
|
133
|
-
};
|
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, afterEach, vi } from 'vitest';
|
|
2
|
-
import '@testing-library/jest-dom/vitest';
|
|
3
|
-
import { render, cleanup, fireEvent } from '@solidjs/testing-library';
|
|
4
|
-
import { createSignal } from 'solid-js';
|
|
5
|
-
import { DefaultPromptInput } from '../elements/default-input';
|
|
6
|
-
|
|
7
|
-
// jsdom doesn't implement Element.scrollTo; some inner controls may call it.
|
|
8
|
-
if (!Element.prototype.scrollTo) (Element.prototype as unknown as { scrollTo: () => void }).scrollTo = () => {};
|
|
9
|
-
|
|
10
|
-
afterEach(cleanup);
|
|
11
|
-
|
|
12
|
-
const noop = () => {};
|
|
13
|
-
|
|
14
|
-
describe('DefaultPromptInput disabled state', () => {
|
|
15
|
-
it('renders the textarea and send button as disabled', () => {
|
|
16
|
-
const { container } = render(() => (
|
|
17
|
-
<DefaultPromptInput
|
|
18
|
-
value="hello"
|
|
19
|
-
disabled
|
|
20
|
-
onValueChange={noop}
|
|
21
|
-
onSubmit={noop}
|
|
22
|
-
onSuggestionClick={noop}
|
|
23
|
-
/>
|
|
24
|
-
));
|
|
25
|
-
const textarea = container.querySelector('textarea');
|
|
26
|
-
const send = container.querySelector('[data-testid="send"]');
|
|
27
|
-
expect(textarea).toBeDisabled();
|
|
28
|
-
expect(send).toBeDisabled();
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('does not call onSubmit when the send button is clicked while disabled', () => {
|
|
32
|
-
const onSubmit = vi.fn();
|
|
33
|
-
const { container } = render(() => (
|
|
34
|
-
<DefaultPromptInput
|
|
35
|
-
value="hello"
|
|
36
|
-
disabled
|
|
37
|
-
onValueChange={noop}
|
|
38
|
-
onSubmit={onSubmit}
|
|
39
|
-
onSuggestionClick={noop}
|
|
40
|
-
/>
|
|
41
|
-
));
|
|
42
|
-
const send = container.querySelector('[data-testid="send"]') as HTMLButtonElement;
|
|
43
|
-
fireEvent.click(send);
|
|
44
|
-
expect(onSubmit).not.toHaveBeenCalled();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('does not call onSubmit when Enter is pressed while disabled', () => {
|
|
48
|
-
const onSubmit = vi.fn();
|
|
49
|
-
const { container } = render(() => (
|
|
50
|
-
<DefaultPromptInput
|
|
51
|
-
value="hello"
|
|
52
|
-
disabled
|
|
53
|
-
onValueChange={noop}
|
|
54
|
-
onSubmit={onSubmit}
|
|
55
|
-
onSuggestionClick={noop}
|
|
56
|
-
/>
|
|
57
|
-
));
|
|
58
|
-
const textarea = container.querySelector('textarea') as HTMLTextAreaElement;
|
|
59
|
-
fireEvent.keyDown(textarea, { key: 'Enter' });
|
|
60
|
-
expect(onSubmit).not.toHaveBeenCalled();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('reactively disables/enables the textarea when `disabled` changes after mount', () => {
|
|
64
|
-
const [disabled, setDisabled] = createSignal(false);
|
|
65
|
-
const { container } = render(() => (
|
|
66
|
-
<DefaultPromptInput
|
|
67
|
-
value="hi"
|
|
68
|
-
disabled={disabled()}
|
|
69
|
-
onValueChange={noop}
|
|
70
|
-
onSubmit={noop}
|
|
71
|
-
onSuggestionClick={noop}
|
|
72
|
-
/>
|
|
73
|
-
));
|
|
74
|
-
const textarea = container.querySelector('textarea') as HTMLTextAreaElement;
|
|
75
|
-
expect(textarea).not.toBeDisabled();
|
|
76
|
-
setDisabled(true);
|
|
77
|
-
expect(textarea).toBeDisabled(); // fails if PromptInput context captures `disabled` statically
|
|
78
|
-
setDisabled(false);
|
|
79
|
-
expect(textarea).not.toBeDisabled();
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it('still submits via Enter when not disabled (sanity)', () => {
|
|
83
|
-
const onSubmit = vi.fn();
|
|
84
|
-
const { container } = render(() => (
|
|
85
|
-
<DefaultPromptInput
|
|
86
|
-
value="hello"
|
|
87
|
-
onValueChange={noop}
|
|
88
|
-
onSubmit={onSubmit}
|
|
89
|
-
onSuggestionClick={noop}
|
|
90
|
-
/>
|
|
91
|
-
));
|
|
92
|
-
const textarea = container.querySelector('textarea') as HTMLTextAreaElement;
|
|
93
|
-
fireEvent.keyDown(textarea, { key: 'Enter' });
|
|
94
|
-
expect(onSubmit).toHaveBeenCalledTimes(1);
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
describe('DefaultPromptInput leading/trailing slots', () => {
|
|
99
|
-
it('renders a leading and trailing named slot', () => {
|
|
100
|
-
const { container } = render(() => (
|
|
101
|
-
<DefaultPromptInput
|
|
102
|
-
value=""
|
|
103
|
-
onValueChange={noop}
|
|
104
|
-
onSubmit={noop}
|
|
105
|
-
onSuggestionClick={noop}
|
|
106
|
-
/>
|
|
107
|
-
));
|
|
108
|
-
expect(container.querySelector('slot[name="leading"]')).toBeTruthy();
|
|
109
|
-
expect(container.querySelector('slot[name="trailing"]')).toBeTruthy();
|
|
110
|
-
});
|
|
111
|
-
});
|