@kitnai/chat 0.1.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/LICENSE +21 -0
- package/README.md +314 -0
- package/dist/bash-InADTalH.js +6 -0
- package/dist/core-AYMC6_lb.js +5874 -0
- package/dist/engine-javascript-vq0WuIJl.js +2643 -0
- package/dist/github-dark-dimmed-DUshB20C.js +4 -0
- package/dist/github-light-JYsPkUQd.js +4 -0
- package/dist/javascript-C25yR2R2.js +6 -0
- package/dist/json-DxJze_jm.js +6 -0
- package/dist/kitn-chat.es.js +6632 -0
- package/dist/tsx-B8rCNbgL.js +6 -0
- package/dist/typescript-RycA9KXf.js +6 -0
- package/package.json +80 -0
- package/src/components/attachments.stories.tsx +304 -0
- package/src/components/attachments.tsx +394 -0
- package/src/components/chain-of-thought.stories.tsx +212 -0
- package/src/components/chain-of-thought.tsx +139 -0
- package/src/components/chat-container.stories.tsx +188 -0
- package/src/components/chat-container.tsx +78 -0
- package/src/components/chat-scope-picker.tsx +47 -0
- package/src/components/checkpoint.stories.tsx +103 -0
- package/src/components/checkpoint.tsx +81 -0
- package/src/components/code-block.stories.tsx +151 -0
- package/src/components/code-block.tsx +99 -0
- package/src/components/context.stories.tsx +180 -0
- package/src/components/context.tsx +323 -0
- package/src/components/conversation-item.stories.tsx +126 -0
- package/src/components/conversation-item.tsx +18 -0
- package/src/components/conversation-list.stories.tsx +134 -0
- package/src/components/conversation-list.tsx +100 -0
- package/src/components/empty.stories.tsx +435 -0
- package/src/components/empty.tsx +166 -0
- package/src/components/feedback-bar.stories.tsx +101 -0
- package/src/components/feedback-bar.tsx +58 -0
- package/src/components/file-upload.stories.tsx +157 -0
- package/src/components/file-upload.tsx +161 -0
- package/src/components/image.stories.tsx +90 -0
- package/src/components/image.tsx +67 -0
- package/src/components/loader.stories.tsx +182 -0
- package/src/components/loader.tsx +333 -0
- package/src/components/markdown.stories.tsx +181 -0
- package/src/components/markdown.tsx +81 -0
- package/src/components/message-narrow.stories.tsx +330 -0
- package/src/components/message-skills.stories.tsx +212 -0
- package/src/components/message-skills.tsx +36 -0
- package/src/components/message.stories.tsx +282 -0
- package/src/components/message.tsx +149 -0
- package/src/components/model-switcher.stories.tsx +98 -0
- package/src/components/model-switcher.tsx +36 -0
- package/src/components/prompt-input.stories.tsx +223 -0
- package/src/components/prompt-input.tsx +190 -0
- package/src/components/prompt-suggestion.stories.tsx +143 -0
- package/src/components/prompt-suggestion.tsx +115 -0
- package/src/components/reasoning.stories.tsx +141 -0
- package/src/components/reasoning.tsx +157 -0
- package/src/components/response-stream.tsx +103 -0
- package/src/components/scroll-button.stories.tsx +101 -0
- package/src/components/scroll-button.tsx +33 -0
- package/src/components/slash-command.stories.tsx +164 -0
- package/src/components/slash-command.tsx +223 -0
- package/src/components/source.stories.tsx +125 -0
- package/src/components/source.tsx +129 -0
- package/src/components/text-shimmer.stories.tsx +88 -0
- package/src/components/text-shimmer.tsx +37 -0
- package/src/components/thinking-bar.stories.tsx +88 -0
- package/src/components/thinking-bar.tsx +50 -0
- package/src/components/tool.stories.tsx +154 -0
- package/src/components/tool.tsx +173 -0
- package/src/components/voice-input.stories.tsx +84 -0
- package/src/components/voice-input.tsx +103 -0
- package/src/elements/chat-types.ts +14 -0
- package/src/elements/chat.tsx +111 -0
- package/src/elements/compiled.css +2 -0
- package/src/elements/conversation-list.tsx +26 -0
- package/src/elements/css.ts +5 -0
- package/src/elements/default-input.tsx +53 -0
- package/src/elements/define.tsx +54 -0
- package/src/elements/kitn-chat.stories.tsx +105 -0
- package/src/elements/kitn-conversation-list.stories.tsx +177 -0
- package/src/elements/kitn-prompt-input.stories.tsx +123 -0
- package/src/elements/prompt-input.tsx +39 -0
- package/src/elements/register.ts +9 -0
- package/src/elements/styles.css +12 -0
- package/src/index.ts +128 -0
- package/src/primitives/chat-config.tsx +76 -0
- package/src/primitives/highlighter.ts +150 -0
- package/src/primitives/use-auto-resize.ts +31 -0
- package/src/primitives/use-stick-to-bottom.ts +43 -0
- package/src/primitives/use-text-stream.ts +112 -0
- package/src/primitives/use-voice-recorder.ts +50 -0
- package/src/stories/chat-panel-layout.stories.tsx +144 -0
- package/src/stories/chat-scene.tsx +570 -0
- package/src/stories/checkpoint-restore.stories.tsx +224 -0
- package/src/stories/context-usage.stories.tsx +155 -0
- package/src/stories/conversation-with-reasoning.stories.tsx +151 -0
- package/src/stories/conversation-with-sources.stories.tsx +165 -0
- package/src/stories/docs/GettingStarted.mdx +76 -0
- package/src/stories/docs/Installation.mdx +48 -0
- package/src/stories/docs/Integrations.mdx +110 -0
- package/src/stories/docs/Introduction.mdx +29 -0
- package/src/stories/docs/Theming.mdx +87 -0
- package/src/stories/docs/theme-editor/canvas.tsx +32 -0
- package/src/stories/docs/theme-editor/inspector.tsx +66 -0
- package/src/stories/docs/theme-editor/presets.test.ts +32 -0
- package/src/stories/docs/theme-editor/presets.ts +64 -0
- package/src/stories/docs/theme-editor/theme-css.test.ts +19 -0
- package/src/stories/docs/theme-editor/theme-css.ts +15 -0
- package/src/stories/docs/theme-editor/theme-editor.tsx +145 -0
- package/src/stories/docs/theme-tokens.tsx +174 -0
- package/src/stories/full-chat.stories.tsx +18 -0
- package/src/stories/message-actions.stories.tsx +167 -0
- package/src/stories/prompt-input-variants.stories.tsx +179 -0
- package/src/stories/streaming-response.stories.tsx +234 -0
- package/src/stories/theme-editor.stories.tsx +16 -0
- package/src/stories/token-reference.stories.tsx +18 -0
- package/src/types.ts +41 -0
- package/src/ui/avatar.stories.tsx +104 -0
- package/src/ui/avatar.tsx +23 -0
- package/src/ui/badge.stories.tsx +87 -0
- package/src/ui/badge.tsx +21 -0
- package/src/ui/button.stories.tsx +146 -0
- package/src/ui/button.tsx +37 -0
- package/src/ui/collapsible.tsx +14 -0
- package/src/ui/dialog.tsx +21 -0
- package/src/ui/dropdown.tsx +26 -0
- package/src/ui/hover-card.tsx +48 -0
- package/src/ui/resizable.stories.tsx +171 -0
- package/src/ui/resizable.tsx +219 -0
- package/src/ui/scroll-area.tsx +13 -0
- package/src/ui/separator.stories.tsx +82 -0
- package/src/ui/separator.tsx +10 -0
- package/src/ui/skeleton.stories.tsx +338 -0
- package/src/ui/skeleton.tsx +16 -0
- package/src/ui/textarea.tsx +21 -0
- package/src/ui/tooltip.stories.tsx +75 -0
- package/src/ui/tooltip.tsx +22 -0
- package/src/utils/cn.ts +6 -0
- package/theme.css +115 -0
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kitnai/chat",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "SolidJS + Shadow-DOM web component kit for building AI chat interfaces.",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"homepage": "https://github.com/kitn-ai/chat#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/kitn-ai/chat.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/kitn-ai/chat/issues"
|
|
14
|
+
},
|
|
15
|
+
"main": "src/index.ts",
|
|
16
|
+
"types": "src/index.ts",
|
|
17
|
+
"unpkg": "./dist/kitn-chat.es.js",
|
|
18
|
+
"jsdelivr": "./dist/kitn-chat.es.js",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": "./src/index.ts",
|
|
21
|
+
"./elements": "./dist/kitn-chat.es.js",
|
|
22
|
+
"./theme.css": "./theme.css"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"src",
|
|
27
|
+
"theme.css"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"prepublishOnly": "npm run build",
|
|
31
|
+
"prebuild": "npm run build:css",
|
|
32
|
+
"build": "vite build --config vite.config.ts",
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:watch": "vitest",
|
|
35
|
+
"dev": "npm run build:css && storybook dev -p 6006",
|
|
36
|
+
"storybook": "npm run build:css && storybook dev -p 6006",
|
|
37
|
+
"build-storybook": "npm run build:css && storybook build",
|
|
38
|
+
"build:css": "tailwindcss -i src/elements/styles.css -o src/elements/compiled.css --minify",
|
|
39
|
+
"build:css:watch": "tailwindcss -i src/elements/styles.css -o src/elements/compiled.css --watch"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@kobalte/core": "^0.13.0",
|
|
43
|
+
"@shikijs/langs": "^4.2.0",
|
|
44
|
+
"@shikijs/themes": "^4.2.0",
|
|
45
|
+
"class-variance-authority": "^0.7.0",
|
|
46
|
+
"clsx": "^2.1.0",
|
|
47
|
+
"lucide-solid": "^0.400.0",
|
|
48
|
+
"marked": "^18.0.0",
|
|
49
|
+
"shiki": "^4.0.2",
|
|
50
|
+
"solid-element": "^1.9.1",
|
|
51
|
+
"solid-js": "^1.9.0",
|
|
52
|
+
"tailwind-merge": "^2.5.0"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@solidjs/testing-library": "^0.8.0",
|
|
56
|
+
"@storybook/addon-docs": "^10.3.5",
|
|
57
|
+
"@storybook/addon-themes": "^10.3.5",
|
|
58
|
+
"@storybook/addon-vitest": "^10.3.5",
|
|
59
|
+
"@tailwindcss/cli": "^4.3.0",
|
|
60
|
+
"@tailwindcss/postcss": "^4.2.2",
|
|
61
|
+
"@tailwindcss/typography": "^0.5.19",
|
|
62
|
+
"@testing-library/jest-dom": "^6.0.0",
|
|
63
|
+
"@vitest/browser-playwright": "4.1.2",
|
|
64
|
+
"@vitest/coverage-v8": "4.1.2",
|
|
65
|
+
"jsdom": "^24.0.0",
|
|
66
|
+
"playwright": "^1.59.1",
|
|
67
|
+
"storybook": "^10.3.5",
|
|
68
|
+
"storybook-dark-mode": "^5.0.0",
|
|
69
|
+
"storybook-solidjs-vite": "^10.0.12",
|
|
70
|
+
"tailwindcss": "^4.2.2",
|
|
71
|
+
"tw-animate-css": "^1.4.0",
|
|
72
|
+
"typescript": "^5.5.0",
|
|
73
|
+
"vite": "^6.0.0",
|
|
74
|
+
"vite-plugin-solid": "^2.11.0",
|
|
75
|
+
"vitest": "^4.1.0"
|
|
76
|
+
},
|
|
77
|
+
"peerDependencies": {
|
|
78
|
+
"solid-js": "^1.9.0"
|
|
79
|
+
}
|
|
80
|
+
}
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from 'storybook-solidjs-vite';
|
|
2
|
+
import { createSignal, For } from 'solid-js';
|
|
3
|
+
import {
|
|
4
|
+
Attachments,
|
|
5
|
+
Attachment,
|
|
6
|
+
AttachmentPreview,
|
|
7
|
+
AttachmentInfo,
|
|
8
|
+
AttachmentRemove,
|
|
9
|
+
AttachmentHoverCard,
|
|
10
|
+
AttachmentHoverCardTrigger,
|
|
11
|
+
AttachmentHoverCardContent,
|
|
12
|
+
AttachmentEmpty,
|
|
13
|
+
} from './attachments';
|
|
14
|
+
import type { AttachmentData } from './attachments';
|
|
15
|
+
|
|
16
|
+
const sampleAttachments: AttachmentData[] = [
|
|
17
|
+
{
|
|
18
|
+
id: '1',
|
|
19
|
+
type: 'file',
|
|
20
|
+
filename: 'mountain-landscape.jpg',
|
|
21
|
+
mediaType: 'image/jpeg',
|
|
22
|
+
url: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=400&h=400&fit=crop',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: '2',
|
|
26
|
+
type: 'file',
|
|
27
|
+
filename: 'sunset-beach.png',
|
|
28
|
+
mediaType: 'image/png',
|
|
29
|
+
url: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=400&h=400&fit=crop',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: '3',
|
|
33
|
+
type: 'file',
|
|
34
|
+
filename: 'architecture-report.pdf',
|
|
35
|
+
mediaType: 'application/pdf',
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
id: '4',
|
|
39
|
+
type: 'file',
|
|
40
|
+
filename: 'demo-recording.mp4',
|
|
41
|
+
mediaType: 'video/mp4',
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
id: '5',
|
|
45
|
+
type: 'file',
|
|
46
|
+
filename: 'podcast-episode.mp3',
|
|
47
|
+
mediaType: 'audio/mpeg',
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
id: '6',
|
|
51
|
+
type: 'source-document',
|
|
52
|
+
filename: 'SolidJS Documentation',
|
|
53
|
+
title: 'SolidJS Reactivity Guide',
|
|
54
|
+
url: 'https://solidjs.com/docs',
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
const meta = {
|
|
59
|
+
title: 'Components/Attachments',
|
|
60
|
+
component: Attachments,
|
|
61
|
+
tags: ['autodocs'],
|
|
62
|
+
parameters: {
|
|
63
|
+
layout: 'padded',
|
|
64
|
+
docs: {
|
|
65
|
+
description: {
|
|
66
|
+
component: [
|
|
67
|
+
'A composable container for displaying file and source-document attachments as thumbnails, inline chips, or a vertical list. Built from `Attachments` + per-item `Attachment` with `AttachmentPreview`, `AttachmentInfo`, and `AttachmentRemove` parts.',
|
|
68
|
+
'**When to use:** to show files a user attached to a prompt, or documents/sources referenced by a message. Choose `grid` for thumbnails, `inline` for compact chips, `list` for a detailed rows view.',
|
|
69
|
+
'**How to use:** set `variant` on `Attachments`, then map your data to `Attachment` (passing each item via `data` and an `onRemove` handler) and compose the preview/info/remove parts inside.',
|
|
70
|
+
'**Placement:** prompt input area (pending uploads), message bodies (attached or cited files), and document panels.',
|
|
71
|
+
].join('\n\n'),
|
|
72
|
+
},
|
|
73
|
+
controls: { exclude: ['use:eventListener'] },
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
argTypes: {
|
|
77
|
+
variant: {
|
|
78
|
+
control: 'select',
|
|
79
|
+
options: ['grid', 'inline', 'list'],
|
|
80
|
+
description: 'Layout of the attachment items.',
|
|
81
|
+
table: { defaultValue: { summary: 'grid' } },
|
|
82
|
+
},
|
|
83
|
+
children: {
|
|
84
|
+
control: false,
|
|
85
|
+
description: 'The `Attachment` items to render inside the container.',
|
|
86
|
+
},
|
|
87
|
+
class: {
|
|
88
|
+
control: 'text',
|
|
89
|
+
description: 'Extra classes for the container element.',
|
|
90
|
+
},
|
|
91
|
+
},
|
|
92
|
+
args: {
|
|
93
|
+
variant: 'grid',
|
|
94
|
+
},
|
|
95
|
+
render: (args) => {
|
|
96
|
+
const [items, setItems] = createSignal([...sampleAttachments]);
|
|
97
|
+
const remove = (id: string) => setItems((prev) => prev.filter((a) => a.id !== id));
|
|
98
|
+
return (
|
|
99
|
+
<Attachments {...args}>
|
|
100
|
+
<For each={items()}>
|
|
101
|
+
{(item) => (
|
|
102
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
103
|
+
<AttachmentPreview />
|
|
104
|
+
<AttachmentInfo />
|
|
105
|
+
<AttachmentRemove />
|
|
106
|
+
</Attachment>
|
|
107
|
+
)}
|
|
108
|
+
</For>
|
|
109
|
+
</Attachments>
|
|
110
|
+
);
|
|
111
|
+
},
|
|
112
|
+
} satisfies Meta<typeof Attachments>;
|
|
113
|
+
|
|
114
|
+
export default meta;
|
|
115
|
+
type Story = StoryObj<typeof meta>;
|
|
116
|
+
|
|
117
|
+
const IMPORT = `import {
|
|
118
|
+
Attachments, Attachment, AttachmentPreview, AttachmentInfo, AttachmentRemove,
|
|
119
|
+
} from '@kitnai/chat';`;
|
|
120
|
+
const src = (code: string) => ({
|
|
121
|
+
parameters: { docs: { source: { code: `${IMPORT}\n\n${code}`, language: 'tsx' } } },
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
/** Interactive playground — switch `variant` to compare grid / inline / list. */
|
|
125
|
+
export const Playground: Story = {
|
|
126
|
+
...src(`<Attachments variant="grid">
|
|
127
|
+
<For each={items()}>
|
|
128
|
+
{(item) => (
|
|
129
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
130
|
+
<AttachmentPreview />
|
|
131
|
+
<AttachmentInfo />
|
|
132
|
+
<AttachmentRemove />
|
|
133
|
+
</Attachment>
|
|
134
|
+
)}
|
|
135
|
+
</For>
|
|
136
|
+
</Attachments>`),
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export const Grid: Story = {
|
|
140
|
+
render: () => {
|
|
141
|
+
const [items, setItems] = createSignal([...sampleAttachments]);
|
|
142
|
+
const remove = (id: string) => setItems((prev) => prev.filter((a) => a.id !== id));
|
|
143
|
+
return (
|
|
144
|
+
<div class="space-y-4">
|
|
145
|
+
<Attachments variant="grid">
|
|
146
|
+
<For each={items()}>
|
|
147
|
+
{(item) => (
|
|
148
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
149
|
+
<AttachmentPreview />
|
|
150
|
+
<AttachmentRemove />
|
|
151
|
+
</Attachment>
|
|
152
|
+
)}
|
|
153
|
+
</For>
|
|
154
|
+
</Attachments>
|
|
155
|
+
<button
|
|
156
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
157
|
+
onClick={() => setItems([...sampleAttachments])}
|
|
158
|
+
>
|
|
159
|
+
Reset
|
|
160
|
+
</button>
|
|
161
|
+
</div>
|
|
162
|
+
);
|
|
163
|
+
},
|
|
164
|
+
...src(`<Attachments variant="grid">
|
|
165
|
+
<For each={items()}>
|
|
166
|
+
{(item) => (
|
|
167
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
168
|
+
<AttachmentPreview />
|
|
169
|
+
<AttachmentRemove />
|
|
170
|
+
</Attachment>
|
|
171
|
+
)}
|
|
172
|
+
</For>
|
|
173
|
+
</Attachments>`),
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
export const Inline: Story = {
|
|
177
|
+
render: () => {
|
|
178
|
+
const [items, setItems] = createSignal([...sampleAttachments]);
|
|
179
|
+
const remove = (id: string) => setItems((prev) => prev.filter((a) => a.id !== id));
|
|
180
|
+
return (
|
|
181
|
+
<div class="space-y-4">
|
|
182
|
+
<Attachments variant="inline">
|
|
183
|
+
<For each={items()}>
|
|
184
|
+
{(item) => (
|
|
185
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
186
|
+
<AttachmentPreview />
|
|
187
|
+
<AttachmentInfo />
|
|
188
|
+
<AttachmentRemove />
|
|
189
|
+
</Attachment>
|
|
190
|
+
)}
|
|
191
|
+
</For>
|
|
192
|
+
</Attachments>
|
|
193
|
+
<button
|
|
194
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
195
|
+
onClick={() => setItems([...sampleAttachments])}
|
|
196
|
+
>
|
|
197
|
+
Reset
|
|
198
|
+
</button>
|
|
199
|
+
</div>
|
|
200
|
+
);
|
|
201
|
+
},
|
|
202
|
+
...src(`<Attachments variant="inline">
|
|
203
|
+
<For each={items()}>
|
|
204
|
+
{(item) => (
|
|
205
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
206
|
+
<AttachmentPreview />
|
|
207
|
+
<AttachmentInfo />
|
|
208
|
+
<AttachmentRemove />
|
|
209
|
+
</Attachment>
|
|
210
|
+
)}
|
|
211
|
+
</For>
|
|
212
|
+
</Attachments>`),
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
export const List: Story = {
|
|
216
|
+
render: () => {
|
|
217
|
+
const [items, setItems] = createSignal([...sampleAttachments]);
|
|
218
|
+
const remove = (id: string) => setItems((prev) => prev.filter((a) => a.id !== id));
|
|
219
|
+
return (
|
|
220
|
+
<div class="w-96 space-y-4">
|
|
221
|
+
<Attachments variant="list">
|
|
222
|
+
<For each={items()}>
|
|
223
|
+
{(item) => (
|
|
224
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
225
|
+
<AttachmentPreview />
|
|
226
|
+
<AttachmentInfo showMediaType />
|
|
227
|
+
<AttachmentRemove />
|
|
228
|
+
</Attachment>
|
|
229
|
+
)}
|
|
230
|
+
</For>
|
|
231
|
+
</Attachments>
|
|
232
|
+
<button
|
|
233
|
+
class="text-sm text-muted-foreground hover:text-foreground transition-colors"
|
|
234
|
+
onClick={() => setItems([...sampleAttachments])}
|
|
235
|
+
>
|
|
236
|
+
Reset
|
|
237
|
+
</button>
|
|
238
|
+
</div>
|
|
239
|
+
);
|
|
240
|
+
},
|
|
241
|
+
...src(`<Attachments variant="list">
|
|
242
|
+
<For each={items()}>
|
|
243
|
+
{(item) => (
|
|
244
|
+
<Attachment data={item} onRemove={() => remove(item.id)}>
|
|
245
|
+
<AttachmentPreview />
|
|
246
|
+
<AttachmentInfo showMediaType />
|
|
247
|
+
<AttachmentRemove />
|
|
248
|
+
</Attachment>
|
|
249
|
+
)}
|
|
250
|
+
</For>
|
|
251
|
+
</Attachments>`),
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
export const WithHoverCard: Story = {
|
|
255
|
+
render: () => (
|
|
256
|
+
<Attachments variant="grid">
|
|
257
|
+
<AttachmentHoverCard>
|
|
258
|
+
<AttachmentHoverCardTrigger>
|
|
259
|
+
<Attachment
|
|
260
|
+
data={{
|
|
261
|
+
id: '1',
|
|
262
|
+
type: 'file',
|
|
263
|
+
filename: 'mountain-landscape.jpg',
|
|
264
|
+
mediaType: 'image/jpeg',
|
|
265
|
+
url: 'https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=400&h=400&fit=crop',
|
|
266
|
+
}}
|
|
267
|
+
>
|
|
268
|
+
<AttachmentPreview />
|
|
269
|
+
</Attachment>
|
|
270
|
+
</AttachmentHoverCardTrigger>
|
|
271
|
+
<AttachmentHoverCardContent>
|
|
272
|
+
<img
|
|
273
|
+
src="https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=600&h=400&fit=crop"
|
|
274
|
+
alt="Mountain landscape"
|
|
275
|
+
class="max-w-xs rounded"
|
|
276
|
+
/>
|
|
277
|
+
</AttachmentHoverCardContent>
|
|
278
|
+
</AttachmentHoverCard>
|
|
279
|
+
</Attachments>
|
|
280
|
+
),
|
|
281
|
+
...src(`<Attachments variant="grid">
|
|
282
|
+
<AttachmentHoverCard>
|
|
283
|
+
<AttachmentHoverCardTrigger>
|
|
284
|
+
<Attachment data={item}>
|
|
285
|
+
<AttachmentPreview />
|
|
286
|
+
</Attachment>
|
|
287
|
+
</AttachmentHoverCardTrigger>
|
|
288
|
+
<AttachmentHoverCardContent>
|
|
289
|
+
<img src={item.url} alt={item.filename} class="max-w-xs rounded" />
|
|
290
|
+
</AttachmentHoverCardContent>
|
|
291
|
+
</AttachmentHoverCard>
|
|
292
|
+
</Attachments>`),
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
export const Empty: Story = {
|
|
296
|
+
render: () => (
|
|
297
|
+
<Attachments variant="grid">
|
|
298
|
+
<AttachmentEmpty />
|
|
299
|
+
</Attachments>
|
|
300
|
+
),
|
|
301
|
+
...src(`<Attachments variant="grid">
|
|
302
|
+
<AttachmentEmpty />
|
|
303
|
+
</Attachments>`),
|
|
304
|
+
};
|