reachat 2.1.0-alpha.9 → 2.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.
Files changed (82) hide show
  1. package/README.md +4 -2
  2. package/dist/AppBar/AppBar.d.ts +1 -1
  3. package/dist/{CSVFileRenderer-CkRKGiCl.js → CSVFileRenderer-D2mDdCjs.js} +14 -15
  4. package/dist/CSVFileRenderer-D2mDdCjs.js.map +1 -0
  5. package/dist/Chat.d.ts +9 -3
  6. package/dist/ChatBubble/ChatBubble.d.ts +1 -1
  7. package/dist/ChatContext.d.ts +4 -2
  8. package/dist/ChatInput/ChatInput.d.ts +23 -13
  9. package/dist/ChatInput/FileInput.d.ts +1 -1
  10. package/dist/ChatInput/MentionList.d.ts +32 -0
  11. package/dist/ChatInput/RichTextInput.d.ts +55 -0
  12. package/dist/ChatInput/index.d.ts +3 -0
  13. package/dist/ChatInput/types.d.ts +104 -0
  14. package/dist/ChatSuggestions/ChatSuggestion.d.ts +9 -0
  15. package/dist/ChatSuggestions/ChatSuggestions.d.ts +22 -0
  16. package/dist/ChatSuggestions/index.d.ts +2 -0
  17. package/dist/{DefaultFileRenderer-C1qZ57tG.js → DefaultFileRenderer-BLV8PtJk.js} +2 -2
  18. package/dist/DefaultFileRenderer-BLV8PtJk.js.map +1 -0
  19. package/dist/ImageFileRenderer-C8tVW3I8.js.map +1 -1
  20. package/dist/Markdown/Markdown.d.ts +4 -3
  21. package/dist/Markdown/Table.d.ts +1 -1
  22. package/dist/Markdown/charts/ChartError.d.ts +21 -0
  23. package/dist/Markdown/charts/ChartPre.d.ts +6 -0
  24. package/dist/Markdown/charts/ChartRenderer.d.ts +13 -0
  25. package/dist/Markdown/charts/chartHelpers.d.ts +40 -0
  26. package/dist/Markdown/charts/chartHelpers.spec.d.ts +1 -0
  27. package/dist/Markdown/charts/index.d.ts +7 -0
  28. package/dist/Markdown/index.d.ts +3 -2
  29. package/dist/Markdown/plugins/index.d.ts +1 -0
  30. package/dist/Markdown/plugins/remarkChart.d.ts +59 -0
  31. package/dist/Markdown/plugins/remarkCve.d.ts +1 -1
  32. package/dist/MessageStatus/MessageStatus.d.ts +44 -0
  33. package/dist/MessageStatus/MessageStatusItem.d.ts +9 -0
  34. package/dist/MessageStatus/StatusIcon.d.ts +17 -0
  35. package/dist/MessageStatus/index.d.ts +3 -0
  36. package/dist/PDFFileRenderer-DQdFS2l6.js +9 -0
  37. package/dist/PDFFileRenderer-DQdFS2l6.js.map +1 -0
  38. package/dist/SessionMessages/SessionEmpty.d.ts +4 -1
  39. package/dist/SessionMessages/SessionMessage/MessageFile/renderers/index.d.ts +1 -1
  40. package/dist/SessionMessages/SessionMessage/MessageFiles.d.ts +1 -1
  41. package/dist/SessionMessages/SessionMessage/MessageSources.d.ts +1 -1
  42. package/dist/SessionMessages/SessionMessage/SessionMessage.d.ts +0 -4
  43. package/dist/SessionMessages/SessionMessage/index.d.ts +2 -2
  44. package/dist/SessionMessages/SessionMessages.d.ts +3 -7
  45. package/dist/SessionMessages/index.d.ts +2 -2
  46. package/dist/SessionsList/index.d.ts +2 -2
  47. package/dist/docs.json +1037 -183
  48. package/dist/index-B3dZT-5c.js +4369 -0
  49. package/dist/index-B3dZT-5c.js.map +1 -0
  50. package/dist/index.css +2129 -6532
  51. package/dist/index.d.ts +8 -7
  52. package/dist/index.js +49 -34
  53. package/dist/index.umd.cjs +3414 -1320
  54. package/dist/index.umd.cjs.map +1 -1
  55. package/dist/stories/Changelog.mdx +1 -1
  56. package/dist/stories/ChartError.stories.tsx +85 -0
  57. package/dist/stories/Charts.stories.tsx +371 -0
  58. package/dist/stories/Chat.stories.tsx +5 -5
  59. package/dist/stories/ChatBubble.stories.tsx +3 -3
  60. package/dist/stories/ChatSuggestions.stories.tsx +541 -0
  61. package/dist/stories/Companion.stories.tsx +6 -6
  62. package/dist/stories/Console.stories.tsx +165 -25
  63. package/dist/stories/EnhancedInput.stories.tsx +322 -0
  64. package/dist/stories/Integration.stories.tsx +2 -2
  65. package/dist/stories/Intro.mdx +1 -1
  66. package/dist/stories/MessageStatus.stories.tsx +314 -0
  67. package/dist/stories/RichTextInput.stories.tsx +198 -0
  68. package/dist/stories/assets/logo.svg +19 -38
  69. package/dist/stories/assets/paperclip.svg +1 -4
  70. package/dist/stories/assets/search.svg +1 -5
  71. package/dist/stories/assets/sparkles.svg +7 -0
  72. package/dist/stories/examples.ts +47 -20
  73. package/dist/theme.d.ts +76 -13
  74. package/dist/types.d.ts +10 -0
  75. package/package.json +69 -66
  76. package/dist/CSVFileRenderer-CkRKGiCl.js.map +0 -1
  77. package/dist/DefaultFileRenderer-C1qZ57tG.js.map +0 -1
  78. package/dist/PDFFileRenderer-BBn2EVrV.js +0 -16
  79. package/dist/PDFFileRenderer-BBn2EVrV.js.map +0 -1
  80. package/dist/index-6CsqxEMx.js +0 -2257
  81. package/dist/index-6CsqxEMx.js.map +0 -1
  82. package/dist/utils/index.d.ts +0 -1
@@ -1,4 +1,4 @@
1
- import { useState, useRef, FC, useContext } from 'react';
1
+ import { useState, useRef, FC, useContext, useEffect } from 'react';
2
2
  import AttachIcon from './assets/paperclip.svg?react';
3
3
  import { Meta } from '@storybook/react';
4
4
  import {
@@ -17,6 +17,9 @@ import {
17
17
  SessionMessagesHeader,
18
18
  ChatContext,
19
19
  SessionMessage,
20
+ MessageStatus,
21
+ MessageStatusStep,
22
+ MessageStatusState
20
23
  } from 'reachat';
21
24
  import {
22
25
  Card,
@@ -55,7 +58,7 @@ export default {
55
58
  export const Basic = () => {
56
59
  return (
57
60
  <div
58
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
61
+ className="dark:bg-gray-950 bg-white"
59
62
  style={{
60
63
  position: 'absolute',
61
64
  top: 0,
@@ -89,7 +92,7 @@ export const Basic = () => {
89
92
  export const Embeds = () => {
90
93
  return (
91
94
  <div
92
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
95
+ className="dark:bg-gray-950 bg-white"
93
96
  style={{
94
97
  position: 'absolute',
95
98
  top: 0,
@@ -123,7 +126,7 @@ export const Embeds = () => {
123
126
  export const DefaultSession = () => {
124
127
  return (
125
128
  <div
126
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
129
+ className="dark:bg-gray-950 bg-white"
127
130
  style={{
128
131
  position: 'absolute',
129
132
  top: 0,
@@ -159,7 +162,7 @@ export const DefaultSession = () => {
159
162
  export const Loading = () => {
160
163
  return (
161
164
  <div
162
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
165
+ className="dark:bg-gray-950 bg-white"
163
166
  style={{
164
167
  position: 'absolute',
165
168
  top: 0,
@@ -199,7 +202,7 @@ export const FileUploads = () => {
199
202
 
200
203
  return (
201
204
  <div
202
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
205
+ className="dark:bg-gray-950 bg-white"
203
206
  style={{
204
207
  position: 'absolute',
205
208
  top: 0,
@@ -257,7 +260,7 @@ export const FileUploads = () => {
257
260
  export const DefaultInputValue = () => {
258
261
  return (
259
262
  <div
260
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
263
+ className="dark:bg-gray-950 bg-white"
261
264
  style={{
262
265
  position: 'absolute',
263
266
  top: 0,
@@ -293,7 +296,7 @@ export const DefaultInputValue = () => {
293
296
  export const UndeleteableSessions = () => {
294
297
  return (
295
298
  <div
296
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
299
+ className="dark:bg-gray-950 bg-white"
297
300
  style={{
298
301
  position: 'absolute',
299
302
  top: 0,
@@ -367,7 +370,7 @@ export const SessionGrouping = () => {
367
370
 
368
371
  return (
369
372
  <div
370
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
373
+ className="dark:bg-gray-950 bg-white"
371
374
  style={{
372
375
  position: 'absolute',
373
376
  top: 0,
@@ -423,7 +426,7 @@ export const HundredSessions = () => {
423
426
 
424
427
  return (
425
428
  <div
426
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
429
+ className="dark:bg-gray-950 bg-white"
427
430
  style={{
428
431
  position: 'absolute',
429
432
  top: 0,
@@ -474,7 +477,7 @@ export const HundredConversations = () => {
474
477
 
475
478
  return (
476
479
  <div
477
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
480
+ className="dark:bg-gray-950 bg-white"
478
481
  style={{
479
482
  position: 'absolute',
480
483
  top: 0,
@@ -498,7 +501,7 @@ export const HundredConversations = () => {
498
501
 
499
502
  <SessionMessagePanel>
500
503
  <SessionMessagesHeader />
501
- <SessionMessages />
504
+ <SessionMessages showScrollBottomButton />
502
505
  <ChatInput />
503
506
  </SessionMessagePanel>
504
507
  </Chat>
@@ -531,7 +534,7 @@ export const LongSessionNames = () => {
531
534
 
532
535
  return (
533
536
  <div
534
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
537
+ className="dark:bg-gray-950 bg-white"
535
538
  style={{
536
539
  position: 'absolute',
537
540
  top: 0,
@@ -648,7 +651,7 @@ export const MarkdownShowcase = () => {
648
651
 
649
652
  return (
650
653
  <div
651
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
654
+ className="dark:bg-gray-950 bg-white"
652
655
  style={{
653
656
  position: 'absolute',
654
657
  top: 0,
@@ -695,7 +698,7 @@ export const CVEExample = () => {
695
698
  The listed CVEs are critical vulnerabilities that need immediate attention.
696
699
 
697
700
  - CVE-2021-34527
698
- - [CVE-2021-44228](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-44228) < Has link
701
+ - CVE-2021-44228
699
702
  - CVE-2021-45046
700
703
  `;
701
704
 
@@ -718,7 +721,7 @@ export const CVEExample = () => {
718
721
 
719
722
  return (
720
723
  <div
721
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
724
+ className="dark:bg-gray-950 bg-white"
722
725
  style={{
723
726
  position: 'absolute',
724
727
  top: 0,
@@ -754,7 +757,7 @@ export const CVEExample = () => {
754
757
  export const Empty = () => {
755
758
  return (
756
759
  <div
757
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
760
+ className="dark:bg-gray-950 bg-white"
758
761
  style={{
759
762
  position: 'absolute',
760
763
  top: 0,
@@ -817,7 +820,7 @@ export const Empty = () => {
817
820
  export const ConversationSources = () => {
818
821
  return (
819
822
  <div
820
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
823
+ className="dark:bg-gray-950 bg-white"
821
824
  style={{
822
825
  position: 'absolute',
823
826
  top: 0,
@@ -954,7 +957,7 @@ const CustomSessionListItem: FC<SessionListItemProps> = ({
954
957
  export const CustomComponents = () => {
955
958
  return (
956
959
  <div
957
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
960
+ className="dark:bg-gray-950 bg-white"
958
961
  style={{
959
962
  position: 'absolute',
960
963
  top: 0,
@@ -1038,25 +1041,25 @@ export const ImageFiles = () => {
1038
1041
  id: '1',
1039
1042
  name: 'landscape.jpg',
1040
1043
  type: 'image/jpeg',
1041
- url: 'https://picsum.photos/200?random=1'
1044
+ url: 'https://www.goodcode.us/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Faustin.1ee6ee64.jpg&w=640&q=75'
1042
1045
  },
1043
1046
  {
1044
1047
  id: '2',
1045
1048
  name: 'portrait.jpg',
1046
1049
  type: 'image/jpeg',
1047
- url: 'https://picsum.photos/200?random=2'
1050
+ url: 'https://www.goodcode.us/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fandrew.50c21037.jpeg&w=640&q=75'
1048
1051
  },
1049
1052
  {
1050
1053
  id: '3',
1051
1054
  name: 'abstract.png',
1052
1055
  type: 'image/jpg',
1053
- url: 'https://picsum.photos/200?random=3'
1056
+ url: 'https://www.goodcode.us/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fkyle.52befaed.jpg&w=640&q=75'
1054
1057
  },
1055
1058
  {
1056
1059
  id: '4',
1057
1060
  name: 'nature.jpg',
1058
1061
  type: 'image/jpeg',
1059
- url: 'https://picsum.photos/200?random=4'
1062
+ url: 'https://www.goodcode.us/_next/image?url=%2F_next%2Fstatic%2Fmedia%2Fsteph.8a52b5d2.jpg&w=640&q=75'
1060
1063
  }
1061
1064
  ];
1062
1065
 
@@ -1089,7 +1092,7 @@ export const ImageFiles = () => {
1089
1092
 
1090
1093
  return (
1091
1094
  <div
1092
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
1095
+ className="dark:bg-gray-950 bg-white"
1093
1096
  style={{
1094
1097
  position: 'absolute',
1095
1098
  top: 0,
@@ -1124,7 +1127,7 @@ export const ImageFiles = () => {
1124
1127
  export const CSVPreview = () => {
1125
1128
  return (
1126
1129
  <div
1127
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
1130
+ className="dark:bg-gray-950 bg-white"
1128
1131
  style={{
1129
1132
  position: 'absolute',
1130
1133
  inset: 0,
@@ -1152,3 +1155,140 @@ export const CSVPreview = () => {
1152
1155
  </div>
1153
1156
  );
1154
1157
  };
1158
+
1159
+ export const WithToolStatus = () => {
1160
+ const [status, setStatus] = useState<MessageStatusState>('loading');
1161
+ const [steps, setSteps] = useState<MessageStatusStep[]>([
1162
+ { id: '1', text: 'Reading src/index.ts', status: 'loading' }
1163
+ ]);
1164
+
1165
+ useEffect(() => {
1166
+ const timeline = [
1167
+ {
1168
+ delay: 1500,
1169
+ action: () => {
1170
+ setSteps(prev =>
1171
+ prev.map(s => (s.id === '1' ? { ...s, status: 'complete' as const } : s))
1172
+ );
1173
+ }
1174
+ },
1175
+ {
1176
+ delay: 2000,
1177
+ action: () => {
1178
+ setSteps(prev => [
1179
+ ...prev,
1180
+ { id: '2', text: 'Searching for dependencies', status: 'loading' as const }
1181
+ ]);
1182
+ }
1183
+ },
1184
+ {
1185
+ delay: 3500,
1186
+ action: () => {
1187
+ setSteps(prev =>
1188
+ prev.map(s => (s.id === '2' ? { ...s, status: 'complete' as const } : s))
1189
+ );
1190
+ }
1191
+ },
1192
+ {
1193
+ delay: 4000,
1194
+ action: () => {
1195
+ setSteps(prev => [
1196
+ ...prev,
1197
+ { id: '3', text: 'Analyzing code patterns', status: 'loading' as const }
1198
+ ]);
1199
+ }
1200
+ },
1201
+ {
1202
+ delay: 6000,
1203
+ action: () => {
1204
+ setSteps(prev =>
1205
+ prev.map(s => (s.id === '3' ? { ...s, status: 'complete' as const } : s))
1206
+ );
1207
+ setStatus('complete');
1208
+ }
1209
+ }
1210
+ ];
1211
+
1212
+ const timeouts = timeline.map(item => setTimeout(item.action, item.delay));
1213
+ return () => timeouts.forEach(clearTimeout);
1214
+ }, []);
1215
+
1216
+ const sessionWithToolStatus: Session[] = [
1217
+ {
1218
+ id: 'session-tool-status',
1219
+ title: 'Tool Status Demo',
1220
+ createdAt: subHours(new Date(), 1),
1221
+ updatedAt: new Date(),
1222
+ conversations: [
1223
+ {
1224
+ id: 'conversation-1',
1225
+ question: 'Can you analyze my codebase and find any issues?',
1226
+ response:
1227
+ 'I\'ll analyze your codebase now. Let me read through the files and check for any potential issues.',
1228
+ createdAt: new Date()
1229
+ }
1230
+ ]
1231
+ }
1232
+ ];
1233
+
1234
+ return (
1235
+ <div
1236
+ className="dark:bg-gray-950 bg-white"
1237
+ style={{
1238
+ position: 'absolute',
1239
+ top: 0,
1240
+ left: 0,
1241
+ right: 0,
1242
+ bottom: 0,
1243
+ padding: 20,
1244
+ margin: 20,
1245
+ borderRadius: 5
1246
+ }}
1247
+ >
1248
+ <Chat
1249
+ viewType="console"
1250
+ sessions={sessionWithToolStatus}
1251
+ activeSessionId="session-tool-status"
1252
+ isLoading={status === 'loading'}
1253
+ >
1254
+ <SessionsList>
1255
+ <NewSessionButton />
1256
+ <SessionGroups />
1257
+ </SessionsList>
1258
+
1259
+ <SessionMessagePanel>
1260
+ <SessionMessagesHeader />
1261
+ <SessionMessages>
1262
+ {conversations =>
1263
+ conversations.map((conversation, index) => (
1264
+ <SessionMessage
1265
+ conversation={conversation}
1266
+ isLast={index === conversations.length - 1}
1267
+ key={conversation.id}
1268
+ >
1269
+ <MessageQuestion
1270
+ question={conversation.question}
1271
+ files={conversation.files}
1272
+ />
1273
+ <MessageResponse response={conversation.response} />
1274
+ <div className="mt-4">
1275
+ <MessageStatus
1276
+ status={status}
1277
+ text={status === 'complete' ? 'Analysis complete' : 'Analyzing codebase...'}
1278
+ steps={steps}
1279
+ />
1280
+ </div>
1281
+ <MessageActions
1282
+ question={conversation.question}
1283
+ response={conversation.response}
1284
+ />
1285
+ </SessionMessage>
1286
+ ))
1287
+ }
1288
+ </SessionMessages>
1289
+ <ChatInput />
1290
+ </SessionMessagePanel>
1291
+ </Chat>
1292
+ </div>
1293
+ );
1294
+ };
@@ -0,0 +1,322 @@
1
+ import { Meta, StoryFn } from '@storybook/react';
2
+ import { useState, useCallback } from 'react';
3
+ import {
4
+ Chat,
5
+ SessionMessages,
6
+ ChatInput,
7
+ SessionMessagePanel,
8
+ Session,
9
+ MentionItem,
10
+ SlashCommandItem
11
+ } from 'reachat';
12
+ import { fakeSessions } from './examples';
13
+
14
+ const UserIcon = () => (
15
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-full h-full">
16
+ <path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
17
+ <circle cx="12" cy="7" r="4" />
18
+ </svg>
19
+ );
20
+
21
+ const CommandIcon = () => (
22
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-full h-full">
23
+ <path d="M18 3a3 3 0 0 0-3 3v12a3 3 0 0 0 3 3 3 3 0 0 0 3-3 3 3 0 0 0-3-3H6a3 3 0 0 0-3 3 3 3 0 0 0 3 3 3 3 0 0 0 3-3V6a3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3h12a3 3 0 0 0 3-3 3 3 0 0 0-3-3z" />
24
+ </svg>
25
+ );
26
+
27
+ const HelpIcon = () => (
28
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-full h-full">
29
+ <circle cx="12" cy="12" r="10" />
30
+ <path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" />
31
+ <line x1="12" y1="17" x2="12.01" y2="17" />
32
+ </svg>
33
+ );
34
+
35
+ const ClearIcon = () => (
36
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-full h-full">
37
+ <path d="M21 4H8l-7 8 7 8h13a2 2 0 0 0 2-2V6a2 2 0 0 0-2-2z" />
38
+ <line x1="18" y1="9" x2="12" y2="15" />
39
+ <line x1="12" y1="9" x2="18" y2="15" />
40
+ </svg>
41
+ );
42
+
43
+ const ImageIcon = () => (
44
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" className="w-full h-full">
45
+ <rect x="3" y="3" width="18" height="18" rx="2" ry="2" />
46
+ <circle cx="8.5" cy="8.5" r="1.5" />
47
+ <polyline points="21 15 16 10 5 21" />
48
+ </svg>
49
+ );
50
+
51
+ export default {
52
+ title: 'Demos/Enhanced Input',
53
+ component: ChatInput
54
+ } as Meta;
55
+
56
+ const sampleUsers: MentionItem[] = [
57
+ { id: '1', label: 'John Doe', description: 'Engineering', icon: <UserIcon /> },
58
+ { id: '2', label: 'Jane Smith', description: 'Design', icon: <UserIcon /> },
59
+ { id: '3', label: 'Bob Wilson', description: 'Product', icon: <UserIcon /> },
60
+ { id: '4', label: 'Alice Brown', description: 'Marketing', icon: <UserIcon /> },
61
+ { id: '5', label: 'Charlie Davis', description: 'Sales', icon: <UserIcon /> }
62
+ ];
63
+
64
+ const sampleCommands: SlashCommandItem[] = [
65
+ {
66
+ id: 'help',
67
+ label: 'help',
68
+ description: 'Show available commands',
69
+ icon: <HelpIcon />,
70
+ shortcut: '?'
71
+ },
72
+ {
73
+ id: 'clear',
74
+ label: 'clear',
75
+ description: 'Clear the conversation',
76
+ icon: <ClearIcon />
77
+ },
78
+ {
79
+ id: 'image',
80
+ label: 'image',
81
+ description: 'Generate an image',
82
+ icon: <ImageIcon />,
83
+ type: 'action'
84
+ },
85
+ {
86
+ id: 'code',
87
+ label: 'code',
88
+ description: 'Insert a code block',
89
+ icon: <CommandIcon />,
90
+ type: 'insert',
91
+ value: '```\n\n```'
92
+ },
93
+ {
94
+ id: 'summarize',
95
+ label: 'summarize',
96
+ description: 'Summarize the conversation',
97
+ icon: <CommandIcon />
98
+ }
99
+ ];
100
+
101
+ export const WithMentions: StoryFn = () => {
102
+ const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
103
+ const [sessions, setSessions] = useState<Session[]>(fakeSessions);
104
+
105
+ return (
106
+ <div
107
+ className="dark:bg-gray-950 bg-white"
108
+ style={{ width: 500, height: 400, padding: 20, borderRadius: 5 }}
109
+ >
110
+ <Chat
111
+ viewType="chat"
112
+ sessions={sessions}
113
+ activeSessionId={activeId}
114
+ onSelectSession={setActiveId}
115
+ >
116
+ <SessionMessagePanel>
117
+ <SessionMessages />
118
+ <ChatInput
119
+ placeholder="Type @ to mention someone..."
120
+ mentions={{
121
+ items: sampleUsers,
122
+ }}
123
+ />
124
+ </SessionMessagePanel>
125
+ </Chat>
126
+ </div>
127
+ );
128
+ };
129
+
130
+ export const WithSlashCommands: StoryFn = () => {
131
+ const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
132
+ const [sessions, setSessions] = useState<Session[]>(fakeSessions);
133
+
134
+ const handleCommandSelect = useCallback(
135
+ (item: SlashCommandItem, insertText: (text: string) => void) => {
136
+ if (item.type === 'action') {
137
+ console.log('Executing action:', item.label);
138
+ insertText('');
139
+ } else if (item.value) {
140
+ insertText(item.value);
141
+ }
142
+ },
143
+ []
144
+ );
145
+
146
+ return (
147
+ <div
148
+ className="dark:bg-gray-950 bg-white"
149
+ style={{ width: 500, height: 400, padding: 20, borderRadius: 5 }}
150
+ >
151
+ <Chat
152
+ viewType="chat"
153
+ sessions={sessions}
154
+ activeSessionId={activeId}
155
+ onSelectSession={setActiveId}
156
+ >
157
+ <SessionMessagePanel>
158
+ <SessionMessages />
159
+ <ChatInput
160
+ placeholder="Type / for commands..."
161
+ commands={{
162
+ items: sampleCommands,
163
+ onSelect: handleCommandSelect,
164
+ }}
165
+ />
166
+ </SessionMessagePanel>
167
+ </Chat>
168
+ </div>
169
+ );
170
+ };
171
+
172
+ export const WithAllFeatures: StoryFn = () => {
173
+ const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
174
+ const [sessions, setSessions] = useState<Session[]>(fakeSessions);
175
+
176
+ const handleCommandSelect = useCallback(
177
+ (item: SlashCommandItem, insertText: (text: string) => void) => {
178
+ if (item.type === 'action') {
179
+ console.log('Executing action:', item.label);
180
+ insertText('');
181
+ } else if (item.value) {
182
+ insertText(item.value);
183
+ }
184
+ },
185
+ []
186
+ );
187
+
188
+ return (
189
+ <div
190
+ className="dark:bg-gray-950 bg-white"
191
+ style={{ width: 600, height: 500, padding: 20, borderRadius: 5 }}
192
+ >
193
+ <Chat
194
+ viewType="chat"
195
+ sessions={sessions}
196
+ activeSessionId={activeId}
197
+ onSelectSession={setActiveId}
198
+ >
199
+ <SessionMessagePanel>
200
+ <SessionMessages />
201
+ <ChatInput
202
+ placeholder="Type @ for mentions, / for commands..."
203
+ mentions={{
204
+ items: sampleUsers,
205
+ }}
206
+ commands={{
207
+ items: sampleCommands,
208
+ onSelect: handleCommandSelect,
209
+ }}
210
+ />
211
+ </SessionMessagePanel>
212
+ </Chat>
213
+ </div>
214
+ );
215
+ };
216
+
217
+ export const WithAsyncSearch: StoryFn = () => {
218
+ const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
219
+ const [sessions, setSessions] = useState<Session[]>(fakeSessions);
220
+
221
+ const searchUsers = useCallback(async (query: string): Promise<MentionItem[]> => {
222
+ await new Promise(resolve => setTimeout(resolve, 500));
223
+
224
+ const filtered = sampleUsers.filter(
225
+ user =>
226
+ user.label.toLowerCase().includes(query.toLowerCase()) ||
227
+ user.description?.toLowerCase().includes(query.toLowerCase())
228
+ );
229
+
230
+ return filtered;
231
+ }, []);
232
+
233
+ return (
234
+ <div
235
+ className="dark:bg-gray-950 bg-white"
236
+ style={{ width: 500, height: 400, padding: 20, borderRadius: 5 }}
237
+ >
238
+ <Chat
239
+ viewType="chat"
240
+ sessions={sessions}
241
+ activeSessionId={activeId}
242
+ onSelectSession={setActiveId}
243
+ >
244
+ <SessionMessagePanel>
245
+ <SessionMessages />
246
+ <ChatInput
247
+ placeholder="Type @ to search team members (async)..."
248
+ mentions={{
249
+ items: sampleUsers,
250
+ onSearch: searchUsers,
251
+ renderEmpty: query => <span>No users found matching "{query}"</span>
252
+ }}
253
+ />
254
+ </SessionMessagePanel>
255
+ </Chat>
256
+ </div>
257
+ );
258
+ };
259
+
260
+ export const MultiLineEmpty: StoryFn = () => {
261
+ const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
262
+ const [sessions, setSessions] = useState<Session[]>(fakeSessions);
263
+
264
+ return (
265
+ <div
266
+ className="dark:bg-gray-950 bg-white"
267
+ style={{ width: 500, height: 400, padding: 20, borderRadius: 5 }}
268
+ >
269
+ <Chat
270
+ viewType="chat"
271
+ sessions={sessions}
272
+ activeSessionId={activeId}
273
+ onSelectSession={setActiveId}
274
+ >
275
+ <SessionMessagePanel>
276
+ <SessionMessages />
277
+ <ChatInput
278
+ placeholder="Type a multi-line message (max 4 lines visible)..."
279
+ minHeight={88}
280
+ maxHeight={88}
281
+ />
282
+ </SessionMessagePanel>
283
+ </Chat>
284
+ </div>
285
+ );
286
+ };
287
+
288
+ export const MultiLineWithContent: StoryFn = () => {
289
+ const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
290
+ const [sessions, setSessions] = useState<Session[]>(fakeSessions);
291
+
292
+ const defaultMultiLineText = `This is line one of the input.
293
+ This is line two of the input.
294
+ This is line three of the input.
295
+ This is line four of the input.
296
+ This is line five - you should scroll to see this.
297
+ This is line six - still scrolling!`;
298
+
299
+ return (
300
+ <div
301
+ className="dark:bg-gray-950 bg-white"
302
+ style={{ width: 500, height: 400, padding: 20, borderRadius: 5 }}
303
+ >
304
+ <Chat
305
+ viewType="chat"
306
+ sessions={sessions}
307
+ activeSessionId={activeId}
308
+ onSelectSession={setActiveId}
309
+ >
310
+ <SessionMessagePanel>
311
+ <SessionMessages />
312
+ <ChatInput
313
+ placeholder="Type a multi-line message..."
314
+ defaultValue={defaultMultiLineText}
315
+ minHeight={88}
316
+ maxHeight={88}
317
+ />
318
+ </SessionMessagePanel>
319
+ </Chat>
320
+ </div>
321
+ );
322
+ };
@@ -126,7 +126,7 @@ export const _OpenAI = () => {
126
126
  onChange={e => setApiKey(e.target.value)}
127
127
  />
128
128
  <div
129
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
129
+ className="dark:bg-gray-950 bg-white"
130
130
  style={{
131
131
  position: 'absolute',
132
132
  top: 50,
@@ -273,7 +273,7 @@ export const VercelAI = () => {
273
273
  onChange={e => setApiKey(e.target.value)}
274
274
  />
275
275
  <div
276
- className="dark:bg-(--color-background-basic-black) bg-(--color-background-basic-white)"
276
+ className="dark:bg-gray-950 bg-white"
277
277
  style={{
278
278
  position: 'absolute',
279
279
  top: 50,