reachat 2.1.0-alpha.20 → 2.1.0-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/{CSVFileRenderer-B7eSDub6.js → CSVFileRenderer-DC2ZhtNx.js} +2 -2
  2. package/dist/{CSVFileRenderer-B7eSDub6.js.map → CSVFileRenderer-DC2ZhtNx.js.map} +1 -1
  3. package/dist/ChatInput/ChatInput.d.ts +9 -1
  4. package/dist/ChatInput/FileDropzone.d.ts +33 -0
  5. package/dist/ChatInput/FileInput.d.ts +0 -4
  6. package/dist/ChatInput/index.d.ts +1 -0
  7. package/dist/ChatSuggestions/ChatSuggestion.d.ts +9 -0
  8. package/dist/ChatSuggestions/ChatSuggestions.d.ts +22 -0
  9. package/dist/ChatSuggestions/index.d.ts +2 -0
  10. package/dist/{DefaultFileRenderer-CszY8p_0.js → DefaultFileRenderer-3oHDLIk4.js} +2 -2
  11. package/dist/{DefaultFileRenderer-CszY8p_0.js.map → DefaultFileRenderer-3oHDLIk4.js.map} +1 -1
  12. package/dist/MessageStatus/MessageStatus.d.ts +44 -0
  13. package/dist/MessageStatus/MessageStatusItem.d.ts +9 -0
  14. package/dist/MessageStatus/StatusIcon.d.ts +17 -0
  15. package/dist/MessageStatus/index.d.ts +3 -0
  16. package/dist/SessionMessages/SessionMessages.d.ts +4 -0
  17. package/dist/docs.json +555 -16
  18. package/dist/{index-DNefh8rs.js → index-CWCW-OiG.js} +477 -124
  19. package/dist/index-CWCW-OiG.js.map +1 -0
  20. package/dist/index.css +186 -55
  21. package/dist/index.d.ts +2 -0
  22. package/dist/index.js +30 -24
  23. package/dist/index.umd.cjs +450 -99
  24. package/dist/index.umd.cjs.map +1 -1
  25. package/dist/stories/ChatSuggestions.stories.tsx +542 -0
  26. package/dist/stories/Console.stories.tsx +101 -623
  27. package/dist/stories/Files.stories.tsx +348 -0
  28. package/dist/stories/Markdown.stories.tsx +108 -1
  29. package/dist/stories/MessageStatus.stories.tsx +326 -0
  30. package/dist/stories/SessionsList.stories.tsx +276 -0
  31. package/dist/stories/assets/sparkles.svg +7 -0
  32. package/dist/stories/examples.ts +34 -0
  33. package/dist/theme.d.ts +46 -0
  34. package/dist/types.d.ts +10 -0
  35. package/package.json +7 -4
  36. package/dist/index-DNefh8rs.js.map +0 -1
@@ -0,0 +1,348 @@
1
+ import type { Meta } from '@storybook/react';
2
+ import { subHours } from 'date-fns';
3
+ import { cn } from 'reablocks';
4
+ import { useState } from 'react';
5
+
6
+ import type { Session } from 'reachat';
7
+ import {
8
+ Chat,
9
+ ChatInput,
10
+ NewSessionButton,
11
+ SessionGroups,
12
+ SessionMessagePanel,
13
+ SessionMessages,
14
+ SessionMessagesHeader,
15
+ SessionsList
16
+ } from 'reachat';
17
+ import UploadIcon from 'reachat';
18
+ import AttachIcon from './assets/paperclip.svg?react';
19
+ import { sessionsWithFiles, sessionWithCSVFiles } from './examples';
20
+
21
+ export default {
22
+ title: 'Demos/Files',
23
+ component: Chat
24
+ } as Meta;
25
+
26
+ export const FileUploads = () => {
27
+ const [sessions, setSessions] = useState(sessionsWithFiles);
28
+ const [selectedFile, setSelectedFile] = useState<File | null>(null);
29
+
30
+ return (
31
+ <div
32
+ className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
33
+ style={{
34
+ position: 'absolute',
35
+ top: 0,
36
+ left: 0,
37
+ right: 0,
38
+ bottom: 0,
39
+ padding: 20,
40
+ margin: 20,
41
+ borderRadius: 5
42
+ }}
43
+ >
44
+ <Chat
45
+ viewType="console"
46
+ sessions={sessions}
47
+ activeSessionId="session-files"
48
+ onSendMessage={message =>
49
+ setSessions(sessions => {
50
+ const session = sessions[0];
51
+
52
+ setSelectedFile(null);
53
+
54
+ return [
55
+ {
56
+ ...session,
57
+ conversations: [
58
+ ...session.conversations,
59
+ {
60
+ id: (Math.random() * 100).toString(),
61
+ createdAt: new Date(),
62
+ question: message,
63
+ ...(selectedFile
64
+ ? {
65
+ files: [
66
+ {
67
+ name: selectedFile.name,
68
+ size: selectedFile.size,
69
+ type: selectedFile.type
70
+ }
71
+ ]
72
+ }
73
+ : [])
74
+ }
75
+ ]
76
+ }
77
+ ];
78
+ })
79
+ }
80
+ onFileUpload={setSelectedFile}
81
+ onDeleteSession={() => alert('delete!')}
82
+ >
83
+ <SessionsList>
84
+ <NewSessionButton />
85
+ <SessionGroups />
86
+ </SessionsList>
87
+ <SessionMessagePanel>
88
+ <SessionMessagesHeader />
89
+ <SessionMessages />
90
+ <ChatInput
91
+ attachIcon={
92
+ <AttachIcon className={cn({ 'text-green-500': selectedFile })} />
93
+ }
94
+ allowedFiles={['.pdf', '.docx']}
95
+ />
96
+ </SessionMessagePanel>
97
+ </Chat>
98
+ </div>
99
+ );
100
+ };
101
+
102
+ export const DragAndDrop = () => {
103
+ const [sessions, setSessions] = useState<Session[]>([
104
+ {
105
+ id: 'session-dragdrop',
106
+ title: 'Drag and Drop Demo',
107
+ createdAt: subHours(new Date(), 1),
108
+ updatedAt: new Date(),
109
+ conversations: [
110
+ {
111
+ id: 'conv-1',
112
+ question: 'Try dragging and dropping files onto the input below!',
113
+ response:
114
+ 'You can drag and drop files directly onto the chat input. When you start dragging a file over the input area, you will see a visual indicator showing where to drop. This works with any file type that is allowed by the chat input configuration.',
115
+ createdAt: new Date()
116
+ }
117
+ ]
118
+ }
119
+ ]);
120
+ const [uploadedFiles, setUploadedFiles] = useState<File[]>([]);
121
+
122
+ const handleFileUpload = (file: File) => {
123
+ setUploadedFiles(prev => [...prev, file]);
124
+ };
125
+
126
+ return (
127
+ <div
128
+ className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
129
+ style={{
130
+ position: 'absolute',
131
+ top: 0,
132
+ left: 0,
133
+ right: 0,
134
+ bottom: 0,
135
+ padding: 20,
136
+ margin: 20,
137
+ borderRadius: 5
138
+ }}
139
+ >
140
+ <Chat
141
+ viewType="console"
142
+ sessions={sessions}
143
+ activeSessionId="session-dragdrop"
144
+ onSendMessage={message =>
145
+ setSessions(sessions => {
146
+ const session = sessions[0];
147
+ const files = uploadedFiles.map(f => ({
148
+ name: f.name,
149
+ size: f.size,
150
+ type: f.type
151
+ }));
152
+ setUploadedFiles([]);
153
+
154
+ return [
155
+ {
156
+ ...session,
157
+ conversations: [
158
+ ...session.conversations,
159
+ {
160
+ id: (Math.random() * 100).toString(),
161
+ createdAt: new Date(),
162
+ question: message,
163
+ response: files.length
164
+ ? `Received ${files.length} file(s): ${files.map(f => f.name).join(', ')}`
165
+ : 'Message received!',
166
+ ...(files.length > 0 ? { files } : {})
167
+ }
168
+ ]
169
+ }
170
+ ];
171
+ })
172
+ }
173
+ onFileUpload={handleFileUpload}
174
+ onDeleteSession={() => alert('delete!')}
175
+ >
176
+ <SessionsList>
177
+ <NewSessionButton />
178
+ <SessionGroups />
179
+ </SessionsList>
180
+ <SessionMessagePanel>
181
+ <SessionMessagesHeader />
182
+ <SessionMessages />
183
+ <div className="flex flex-col gap-2">
184
+ {uploadedFiles.length > 0 && (
185
+ <div className="flex flex-wrap gap-2 px-2">
186
+ {uploadedFiles.map((file, idx) => (
187
+ <div
188
+ key={idx}
189
+ className="flex items-center gap-2 bg-gray-100 dark:bg-gray-800 px-3 py-1 rounded-full text-sm"
190
+ >
191
+ <span>{file.name}</span>
192
+ <button
193
+ onClick={() =>
194
+ setUploadedFiles(prev =>
195
+ prev.filter((_, i) => i !== idx)
196
+ )
197
+ }
198
+ className="text-gray-500 hover:text-gray-700 dark:hover:text-gray-300"
199
+ >
200
+ ×
201
+ </button>
202
+ </div>
203
+ ))}
204
+ </div>
205
+ )}
206
+ <ChatInput
207
+ allowedFiles={[
208
+ '.pdf',
209
+ '.docx',
210
+ '.txt',
211
+ '.csv',
212
+ '.jpg',
213
+ '.jpeg',
214
+ '.png',
215
+ '.gif'
216
+ ]}
217
+ allowMultipleFiles
218
+ dropIcon={<UploadIcon className="w-8 h-8" />}
219
+ dropText="Drop your files here"
220
+ placeholder="Type a message or drag files here..."
221
+ />
222
+ </div>
223
+ </SessionMessagePanel>
224
+ </Chat>
225
+ </div>
226
+ );
227
+ };
228
+
229
+ export const CSVPreview = () => {
230
+ return (
231
+ <div
232
+ className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
233
+ style={{
234
+ position: 'absolute',
235
+ inset: 0,
236
+ padding: 20,
237
+ margin: 20,
238
+ borderRadius: 5
239
+ }}
240
+ >
241
+ <Chat
242
+ sessions={sessionWithCSVFiles}
243
+ activeSessionId="1"
244
+ onDeleteSession={() => alert('delete!')}
245
+ >
246
+ <SessionsList>
247
+ <NewSessionButton />
248
+ <SessionGroups />
249
+ </SessionsList>
250
+
251
+ <SessionMessagePanel>
252
+ <SessionMessagesHeader />
253
+ <SessionMessages />
254
+ <ChatInput allowedFiles={['.pdf', '.docx', '.csv']} />
255
+ </SessionMessagePanel>
256
+ </Chat>
257
+ </div>
258
+ );
259
+ };
260
+
261
+ export const ImageFiles = () => {
262
+ const staticImageFiles = [
263
+ {
264
+ id: '1',
265
+ name: 'landscape.jpg',
266
+ type: 'image/jpeg',
267
+ url: 'https://picsum.photos/200?random=1'
268
+ },
269
+ {
270
+ id: '2',
271
+ name: 'portrait.jpg',
272
+ type: 'image/jpeg',
273
+ url: 'https://picsum.photos/200?random=2'
274
+ },
275
+ {
276
+ id: '3',
277
+ name: 'abstract.png',
278
+ type: 'image/jpg',
279
+ url: 'https://picsum.photos/200?random=3'
280
+ },
281
+ {
282
+ id: '4',
283
+ name: 'nature.jpg',
284
+ type: 'image/jpeg',
285
+ url: 'https://picsum.photos/200?random=4'
286
+ }
287
+ ];
288
+
289
+ const sessionWithImages: Session[] = [
290
+ {
291
+ id: 'session-images',
292
+ title: 'Multiple Image Files Showcase',
293
+ createdAt: subHours(new Date(), 1),
294
+ updatedAt: new Date(),
295
+ conversations: [
296
+ {
297
+ id: 'conversation-1',
298
+ question: 'Analyze these images and describe what you see.',
299
+ response:
300
+ "I'm sorry, but as an AI language model, I cannot actually see or analyze images. I can only process and respond to text input. If you'd like me to describe or analyze images, you would need to provide detailed textual descriptions of the images.",
301
+ createdAt: new Date(),
302
+ files: staticImageFiles
303
+ },
304
+ {
305
+ id: 'conversation-2',
306
+ question: 'Analyze these images and describe what you see.',
307
+ response:
308
+ "I'm sorry, but as an AI language model, I cannot actually see or analyze images. I can only process and respond to text input. If you'd like me to describe or analyze images, you would need to provide detailed textual descriptions of the images.",
309
+ createdAt: new Date(),
310
+ files: [staticImageFiles[0]]
311
+ }
312
+ ]
313
+ }
314
+ ];
315
+
316
+ return (
317
+ <div
318
+ className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
319
+ style={{
320
+ position: 'absolute',
321
+ top: 0,
322
+ left: 0,
323
+ right: 0,
324
+ bottom: 0,
325
+ padding: 20,
326
+ margin: 20,
327
+ borderRadius: 5
328
+ }}
329
+ >
330
+ <Chat
331
+ viewType="console"
332
+ sessions={sessionWithImages}
333
+ activeSessionId="session-images"
334
+ >
335
+ <SessionsList>
336
+ <NewSessionButton />
337
+ <SessionGroups />
338
+ </SessionsList>
339
+
340
+ <SessionMessagePanel>
341
+ <SessionMessagesHeader />
342
+ <SessionMessages />
343
+ <ChatInput />
344
+ </SessionMessagePanel>
345
+ </Chat>
346
+ </div>
347
+ );
348
+ };
@@ -34,7 +34,7 @@ This risk table uses Dragos ransomware intelligence trends along with Acme Contr
34
34
 
35
35
  Let me know your next question or if you want me to elaborate on specific risks before we proceed to complete the Strategic Risk Assessment.`;
36
36
 
37
- export const RiskAssessmentTable: Story = {
37
+ export const ComplexTable: Story = {
38
38
  render: args => (
39
39
  <div className="p-8 bg-background-neutral-canvas-base max-w-full overflow-x-auto">
40
40
  <Markdown {...args} remarkPlugins={[remarkGfm, remarkMath, remarkCve]}>
@@ -316,3 +316,110 @@ function greet(name: string): string {
316
316
  </div>
317
317
  )
318
318
  };
319
+
320
+ export const MarkdownShowcase: Story = {
321
+ render: args => (
322
+ <div className="p-8 bg-background-neutral-canvas-base max-w-4xl">
323
+ <Markdown {...args}>
324
+ {`
325
+ **The purpose of life is a philosophical question concerning the significance of life or existence in general.**
326
+
327
+ 1. Burning of fossil fuels (coal, oil, and natural gas)
328
+ 2. Deforestation and land-use changes
329
+ 3. Industrial processes
330
+ 4. Agriculture and livestock farming
331
+
332
+ or
333
+
334
+ - Burning
335
+ - Deforestation
336
+ - Industrial
337
+ - Agriculture
338
+
339
+ Here is a table to illustrate different perspectives:
340
+
341
+ | Perspective | Description |
342
+ |-------------------|-----------------------------------------------------------------------------|
343
+ | Religious | Belief in a higher power or divine purpose. |
344
+ | Philosophical | Various theories including existentialism, nihilism, and absurdism. |
345
+ | Scientific | Understanding life through biology, evolution, and the universe. |
346
+ | Personal | Individual goals, happiness, and fulfillment. |
347
+
348
+ \`\`\`python
349
+ def purpose_of_life():
350
+ return 42
351
+ \`\`\`
352
+
353
+ \`\`\`json
354
+ {
355
+ "perspectives": [
356
+ {
357
+ "type": "Religious",
358
+ "description": "Belief in a higher power or divine purpose."
359
+ },
360
+ {
361
+ "type": "Philosophical",
362
+ "description": "Various theories including existentialism, nihilism, and absurdism."
363
+ },
364
+ {
365
+ "type": "Scientific",
366
+ "description": "Understanding life through biology, evolution, and the universe."
367
+ },
368
+ {
369
+ "type": "Personal",
370
+ "description": "Individual goals, happiness, and fulfillment."
371
+ }
372
+ ]
373
+ }
374
+ \`\`\`
375
+
376
+ The answer to the ultimate question of life, the universe, and everything is **42**.
377
+
378
+ \`\`\`math
379
+ L = \\frac{1}{2} \\rho v^2 S C_L
380
+ \`\`\`
381
+
382
+ [Perspective](https://en.wikipedia.org/wiki/Philosophical_question)
383
+ `}
384
+ </Markdown>
385
+ </div>
386
+ )
387
+ };
388
+
389
+ export const CVEExample: Story = {
390
+ render: args => (
391
+ <div className="p-8 bg-background-neutral-canvas-base max-w-4xl">
392
+ <Markdown {...args} remarkPlugins={[remarkGfm, remarkMath, remarkCve]}>
393
+ {`
394
+ ## Analysis
395
+
396
+ The listed CVEs are critical vulnerabilities that need immediate attention.
397
+
398
+ - CVE-2021-34527
399
+ - [CVE-2021-44228](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228) < Has link
400
+ - CVE-2021-45046
401
+
402
+ The \`remarkCve\` plugin automatically converts CVE identifiers into clickable links.
403
+ `}
404
+ </Markdown>
405
+ </div>
406
+ )
407
+ };
408
+
409
+ export const Embeds: Story = {
410
+ render: args => (
411
+ <div className="p-8 bg-background-neutral-canvas-base max-w-4xl">
412
+ <Markdown {...args}>
413
+ {`
414
+ ## Watch this video
415
+
416
+ https://youtu.be/enTFE2c68FQ
417
+
418
+ https://www.youtube.com/watch?v=enTFE2c68FQ
419
+
420
+ These links showcase a video about React basics. You can click on either link to watch the video.
421
+ `}
422
+ </Markdown>
423
+ </div>
424
+ )
425
+ };