reachat 2.0.1 → 2.0.2
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/{CSVFileRenderer-Dy3iLTeu.js → CSVFileRenderer-fklKR5lg.js} +2 -2
- package/dist/{CSVFileRenderer-Dy3iLTeu.js.map → CSVFileRenderer-fklKR5lg.js.map} +1 -1
- package/dist/{DefaultFileRenderer-Dxar9MFe.js → DefaultFileRenderer-BQ9xzbrH.js} +2 -2
- package/dist/{DefaultFileRenderer-Dxar9MFe.js.map → DefaultFileRenderer-BQ9xzbrH.js.map} +1 -1
- package/dist/{index-NuRjkHCl.js → index-D7d92jbn.js} +9 -4
- package/dist/index-D7d92jbn.js.map +1 -0
- package/dist/index.css +3 -0
- package/dist/index.js +1 -1
- package/dist/index.umd.cjs +6 -1
- package/dist/index.umd.cjs.map +1 -1
- package/dist/stories/Changelog.mdx +8 -0
- package/dist/stories/Chat.stories.tsx +265 -0
- package/dist/stories/ChatBubble.stories.tsx +267 -0
- package/dist/stories/Companion.stories.tsx +435 -0
- package/dist/stories/Console.stories.tsx +1154 -0
- package/dist/stories/Integration.stories.tsx +312 -0
- package/dist/stories/Intro.mdx +41 -0
- package/dist/stories/Support.mdx +9 -0
- package/dist/stories/assets/chat-voice-fill.svg +5 -0
- package/dist/stories/assets/close-fill.svg +5 -0
- package/dist/stories/assets/logo.svg +21 -0
- package/dist/stories/assets/menu.svg +1 -0
- package/dist/stories/assets/paperclip.svg +1 -0
- package/dist/stories/assets/placeholder-dark.svg +500 -0
- package/dist/stories/assets/placeholder.svg +258 -0
- package/dist/stories/assets/search.svg +1 -0
- package/dist/stories/examples.ts +267 -0
- package/package.json +7 -3
- package/dist/index-NuRjkHCl.js.map +0 -1
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { Meta } from '@storybook/react';
|
|
2
|
+
import {
|
|
3
|
+
Chat,
|
|
4
|
+
SessionMessages,
|
|
5
|
+
ChatInput,
|
|
6
|
+
SessionMessagePanel,
|
|
7
|
+
SessionMessage,
|
|
8
|
+
Session,
|
|
9
|
+
AppBar
|
|
10
|
+
} from 'reachat';
|
|
11
|
+
import {
|
|
12
|
+
fakeSessions,
|
|
13
|
+
sessionWithSources,
|
|
14
|
+
sessionsWithFiles
|
|
15
|
+
} from './examples';
|
|
16
|
+
import { useState } from 'react';
|
|
17
|
+
import Placeholder from './assets/placeholder.svg?react';
|
|
18
|
+
import PlaceholderDark from './assets/placeholder-dark.svg?react';
|
|
19
|
+
import ReachatLogo from './assets/logo.svg?react';
|
|
20
|
+
import IconSearch from './assets/search.svg?react';
|
|
21
|
+
import IconClose from './assets/close-fill.svg?react';
|
|
22
|
+
import { IconButton } from 'reablocks';
|
|
23
|
+
|
|
24
|
+
export default {
|
|
25
|
+
title: 'Demos/Chat',
|
|
26
|
+
component: Chat
|
|
27
|
+
} as Meta;
|
|
28
|
+
|
|
29
|
+
export const Compact = () => {
|
|
30
|
+
const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
|
|
31
|
+
const [sessions, setSessions] = useState<Session[]>([
|
|
32
|
+
...fakeSessions,
|
|
33
|
+
...sessionsWithFiles,
|
|
34
|
+
...sessionWithSources
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
return (
|
|
38
|
+
<div
|
|
39
|
+
className="dark:bg-gray-950 bg-white"
|
|
40
|
+
style={{
|
|
41
|
+
width: 350,
|
|
42
|
+
height: 500,
|
|
43
|
+
padding: 20,
|
|
44
|
+
borderRadius: 5
|
|
45
|
+
}}
|
|
46
|
+
>
|
|
47
|
+
<Chat
|
|
48
|
+
viewType="chat"
|
|
49
|
+
sessions={sessions}
|
|
50
|
+
activeSessionId={activeId}
|
|
51
|
+
onNewSession={() => {
|
|
52
|
+
const newId = (sessions.length + 1).toLocaleString();
|
|
53
|
+
setSessions([
|
|
54
|
+
...sessions,
|
|
55
|
+
{
|
|
56
|
+
id: newId,
|
|
57
|
+
title: `New Session #${newId}`,
|
|
58
|
+
createdAt: new Date(),
|
|
59
|
+
updatedAt: new Date(),
|
|
60
|
+
conversations: []
|
|
61
|
+
}
|
|
62
|
+
]);
|
|
63
|
+
setActiveId(newId);
|
|
64
|
+
}}
|
|
65
|
+
onSelectSession={setActiveId}
|
|
66
|
+
onDeleteSession={() => alert('delete!')}
|
|
67
|
+
>
|
|
68
|
+
<SessionMessagePanel>
|
|
69
|
+
<SessionMessages />
|
|
70
|
+
<ChatInput />
|
|
71
|
+
</SessionMessagePanel>
|
|
72
|
+
</Chat>
|
|
73
|
+
</div>
|
|
74
|
+
);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const FullScreen = () => {
|
|
78
|
+
const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
|
|
79
|
+
const [sessions, setSessions] = useState<Session[]>([
|
|
80
|
+
...fakeSessions,
|
|
81
|
+
...sessionsWithFiles,
|
|
82
|
+
...sessionWithSources
|
|
83
|
+
]);
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<div
|
|
87
|
+
className="dark:bg-gray-950 bg-white"
|
|
88
|
+
style={{
|
|
89
|
+
position: 'absolute',
|
|
90
|
+
top: 0,
|
|
91
|
+
left: 0,
|
|
92
|
+
right: 0,
|
|
93
|
+
bottom: 0,
|
|
94
|
+
padding: 20,
|
|
95
|
+
margin: 20,
|
|
96
|
+
borderRadius: 5
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
<Chat
|
|
100
|
+
viewType="chat"
|
|
101
|
+
sessions={sessions}
|
|
102
|
+
activeSessionId={activeId}
|
|
103
|
+
onNewSession={() => {
|
|
104
|
+
const newId = (sessions.length + 1).toLocaleString();
|
|
105
|
+
setSessions([
|
|
106
|
+
...sessions,
|
|
107
|
+
{
|
|
108
|
+
id: newId,
|
|
109
|
+
title: `New Session #${newId}`,
|
|
110
|
+
createdAt: new Date(),
|
|
111
|
+
updatedAt: new Date(),
|
|
112
|
+
conversations: []
|
|
113
|
+
}
|
|
114
|
+
]);
|
|
115
|
+
setActiveId(newId);
|
|
116
|
+
}}
|
|
117
|
+
onSelectSession={setActiveId}
|
|
118
|
+
onDeleteSession={() => alert('delete!')}
|
|
119
|
+
>
|
|
120
|
+
<SessionMessagePanel>
|
|
121
|
+
<SessionMessages />
|
|
122
|
+
<ChatInput />
|
|
123
|
+
</SessionMessagePanel>
|
|
124
|
+
</Chat>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export const Empty = () => {
|
|
130
|
+
const [activeId, setActiveId] = useState<string>();
|
|
131
|
+
const [sessions, setSessions] = useState<Session[]>([]);
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<div
|
|
135
|
+
className="dark:bg-gray-950 bg-white"
|
|
136
|
+
style={{
|
|
137
|
+
width: 350,
|
|
138
|
+
height: 500,
|
|
139
|
+
padding: 20,
|
|
140
|
+
borderRadius: 5
|
|
141
|
+
}}
|
|
142
|
+
>
|
|
143
|
+
<Chat
|
|
144
|
+
viewType="chat"
|
|
145
|
+
sessions={sessions}
|
|
146
|
+
activeSessionId={activeId}
|
|
147
|
+
onNewSession={() => {
|
|
148
|
+
const newId = (sessions.length + 1).toLocaleString();
|
|
149
|
+
setSessions([
|
|
150
|
+
...sessions,
|
|
151
|
+
{
|
|
152
|
+
id: newId,
|
|
153
|
+
title: `New Session #${newId}`,
|
|
154
|
+
createdAt: new Date(),
|
|
155
|
+
updatedAt: new Date(),
|
|
156
|
+
conversations: []
|
|
157
|
+
}
|
|
158
|
+
]);
|
|
159
|
+
setActiveId(newId);
|
|
160
|
+
}}
|
|
161
|
+
onSelectSession={setActiveId}
|
|
162
|
+
onDeleteSession={() => alert('delete!')}
|
|
163
|
+
>
|
|
164
|
+
<SessionMessagePanel>
|
|
165
|
+
<SessionMessages
|
|
166
|
+
newSessionContent={
|
|
167
|
+
<div className="flex flex-col gap-2 items-center justify-center h-full">
|
|
168
|
+
<Placeholder className="h-[50%] block dark:hidden max-w-[100%]" />
|
|
169
|
+
<PlaceholderDark className="h-[50%] hidden dark:block max-w-[100%]" />
|
|
170
|
+
<p className="text-gray-500 max-w-[400px] text-center">
|
|
171
|
+
Welcome to Reachat, a UI library for effortlessly building and
|
|
172
|
+
customizing chat experiences with Tailwind.
|
|
173
|
+
</p>
|
|
174
|
+
</div>
|
|
175
|
+
}
|
|
176
|
+
>
|
|
177
|
+
{conversations =>
|
|
178
|
+
conversations.map((conversation, index) => (
|
|
179
|
+
<SessionMessage
|
|
180
|
+
key={conversation.id}
|
|
181
|
+
conversation={conversation}
|
|
182
|
+
isLast={index === conversations.length - 1}
|
|
183
|
+
/>
|
|
184
|
+
))
|
|
185
|
+
}
|
|
186
|
+
</SessionMessages>
|
|
187
|
+
<ChatInput />
|
|
188
|
+
</SessionMessagePanel>
|
|
189
|
+
</Chat>
|
|
190
|
+
</div>
|
|
191
|
+
);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const WithAppBar = () => {
|
|
195
|
+
const [activeId, setActiveId] = useState<string>(fakeSessions[0].id);
|
|
196
|
+
const [sessions, setSessions] = useState<Session[]>([
|
|
197
|
+
...fakeSessions,
|
|
198
|
+
...sessionsWithFiles,
|
|
199
|
+
...sessionWithSources
|
|
200
|
+
]);
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<div
|
|
204
|
+
className="dark:bg-gray-950 bg-white"
|
|
205
|
+
style={{
|
|
206
|
+
width: 800,
|
|
207
|
+
height: 600,
|
|
208
|
+
padding: 20,
|
|
209
|
+
borderRadius: 5
|
|
210
|
+
}}
|
|
211
|
+
>
|
|
212
|
+
<Chat
|
|
213
|
+
viewType="chat"
|
|
214
|
+
sessions={sessions}
|
|
215
|
+
activeSessionId={activeId}
|
|
216
|
+
onNewSession={() => {
|
|
217
|
+
const newId = (sessions.length + 1).toLocaleString();
|
|
218
|
+
setSessions([
|
|
219
|
+
...sessions,
|
|
220
|
+
{
|
|
221
|
+
id: newId,
|
|
222
|
+
title: `New Session #${newId}`,
|
|
223
|
+
createdAt: new Date(),
|
|
224
|
+
updatedAt: new Date(),
|
|
225
|
+
conversations: []
|
|
226
|
+
}
|
|
227
|
+
]);
|
|
228
|
+
setActiveId(newId);
|
|
229
|
+
}}
|
|
230
|
+
onSelectSession={setActiveId}
|
|
231
|
+
onDeleteSession={() => alert('delete!')}
|
|
232
|
+
>
|
|
233
|
+
<div className="flex flex-col h-full">
|
|
234
|
+
<AppBar
|
|
235
|
+
content={
|
|
236
|
+
<div className="flex items-center justify-between w-full">
|
|
237
|
+
<div className="flex-shrink-0">
|
|
238
|
+
<IconButton size="small" variant="outline" className='rounded-full p-3'>
|
|
239
|
+
<IconSearch className='w-4 h-4' />
|
|
240
|
+
</IconButton>
|
|
241
|
+
</div>
|
|
242
|
+
<div className="flex-grow flex justify-center items-center">
|
|
243
|
+
<ReachatLogo className="h-6 w-auto" />
|
|
244
|
+
</div>
|
|
245
|
+
<div className="flex-shrink-0">
|
|
246
|
+
<IconButton
|
|
247
|
+
variant="text"
|
|
248
|
+
size="small"
|
|
249
|
+
className='rounded-full p-3'
|
|
250
|
+
>
|
|
251
|
+
<IconClose className='w-4 h-4' />
|
|
252
|
+
</IconButton>
|
|
253
|
+
</div>
|
|
254
|
+
</div>
|
|
255
|
+
}
|
|
256
|
+
/>
|
|
257
|
+
<SessionMessagePanel>
|
|
258
|
+
<SessionMessages />
|
|
259
|
+
<ChatInput />
|
|
260
|
+
</SessionMessagePanel>
|
|
261
|
+
</div>
|
|
262
|
+
</Chat>
|
|
263
|
+
</div>
|
|
264
|
+
);
|
|
265
|
+
};
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { ChatBubble } from 'reachat';
|
|
3
|
+
import {
|
|
4
|
+
Chat,
|
|
5
|
+
SessionsList,
|
|
6
|
+
NewSessionButton,
|
|
7
|
+
SessionMessages,
|
|
8
|
+
SessionGroups,
|
|
9
|
+
ChatInput,
|
|
10
|
+
SessionMessagePanel,
|
|
11
|
+
SessionMessagesHeader,
|
|
12
|
+
Session
|
|
13
|
+
} from 'reachat';
|
|
14
|
+
import { FC, useState } from 'react';
|
|
15
|
+
import { IconButton } from 'reablocks';
|
|
16
|
+
import IconChat from './assets/chat-voice-fill.svg?react';
|
|
17
|
+
import {
|
|
18
|
+
fakeSessions,
|
|
19
|
+
sessionsWithFiles,
|
|
20
|
+
sessionWithSources
|
|
21
|
+
} from './examples';
|
|
22
|
+
|
|
23
|
+
export default {
|
|
24
|
+
title: 'Demos/ChatBubble',
|
|
25
|
+
component: ChatBubble,
|
|
26
|
+
args: {
|
|
27
|
+
position: 'right-end',
|
|
28
|
+
bubbleContent: (
|
|
29
|
+
<IconButton
|
|
30
|
+
size="medium"
|
|
31
|
+
variant="outline"
|
|
32
|
+
className="rounded-full p-3 hover:scale-110 transition-transform"
|
|
33
|
+
>
|
|
34
|
+
<IconChat />
|
|
35
|
+
</IconButton>
|
|
36
|
+
)
|
|
37
|
+
},
|
|
38
|
+
argTypes: {
|
|
39
|
+
position: {
|
|
40
|
+
control: 'select',
|
|
41
|
+
options: [
|
|
42
|
+
'top',
|
|
43
|
+
'top-start',
|
|
44
|
+
'top-end',
|
|
45
|
+
'right',
|
|
46
|
+
'right-start',
|
|
47
|
+
'right-end',
|
|
48
|
+
'bottom',
|
|
49
|
+
'bottom-start',
|
|
50
|
+
'bottom-end',
|
|
51
|
+
'left',
|
|
52
|
+
'left-start',
|
|
53
|
+
'left-end'
|
|
54
|
+
],
|
|
55
|
+
description: 'The position of the chat bubble'
|
|
56
|
+
},
|
|
57
|
+
className: {
|
|
58
|
+
description: 'Additional CSS classes'
|
|
59
|
+
},
|
|
60
|
+
children: {
|
|
61
|
+
description: 'Main content (chat/companion interface)'
|
|
62
|
+
},
|
|
63
|
+
bubbleContent: {
|
|
64
|
+
description: 'Content to show in the trigger bubble'
|
|
65
|
+
},
|
|
66
|
+
modifiers: {
|
|
67
|
+
description: 'Custom position modifiers'
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
} as Meta<typeof ChatBubble>;
|
|
71
|
+
|
|
72
|
+
type Story = StoryObj<typeof ChatBubble>;
|
|
73
|
+
|
|
74
|
+
const ChatSample: FC = () => {
|
|
75
|
+
const [activeId, setActiveId] = useState<string>();
|
|
76
|
+
const [sessions, setSessions] = useState<Session[]>([
|
|
77
|
+
...fakeSessions,
|
|
78
|
+
...sessionsWithFiles,
|
|
79
|
+
...sessionWithSources
|
|
80
|
+
]);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<div
|
|
84
|
+
className="dark:bg-gray-950 bg-white"
|
|
85
|
+
style={{
|
|
86
|
+
width: 350,
|
|
87
|
+
height: 500,
|
|
88
|
+
padding: 20,
|
|
89
|
+
borderRadius: 5
|
|
90
|
+
}}
|
|
91
|
+
>
|
|
92
|
+
<Chat
|
|
93
|
+
viewType="companion"
|
|
94
|
+
sessions={sessions}
|
|
95
|
+
activeSessionId={activeId}
|
|
96
|
+
onNewSession={() => {
|
|
97
|
+
const newId = (sessions.length + 1).toLocaleString();
|
|
98
|
+
setSessions([
|
|
99
|
+
...sessions,
|
|
100
|
+
{
|
|
101
|
+
id: newId,
|
|
102
|
+
title: `New Session #${newId}`,
|
|
103
|
+
createdAt: new Date(),
|
|
104
|
+
updatedAt: new Date(),
|
|
105
|
+
conversations: []
|
|
106
|
+
}
|
|
107
|
+
]);
|
|
108
|
+
setActiveId(newId);
|
|
109
|
+
}}
|
|
110
|
+
onSelectSession={setActiveId}
|
|
111
|
+
onDeleteSession={() => alert('delete!')}
|
|
112
|
+
>
|
|
113
|
+
<SessionsList>
|
|
114
|
+
<NewSessionButton />
|
|
115
|
+
<SessionGroups />
|
|
116
|
+
</SessionsList>
|
|
117
|
+
<SessionMessagePanel>
|
|
118
|
+
<SessionMessagesHeader />
|
|
119
|
+
<SessionMessages />
|
|
120
|
+
<ChatInput />
|
|
121
|
+
</SessionMessagePanel>
|
|
122
|
+
</Chat>
|
|
123
|
+
</div>
|
|
124
|
+
);
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
export const Basic: Story = {
|
|
128
|
+
render: args => (
|
|
129
|
+
<ChatBubble className="absolute left-5 bottom-5" {...args}>
|
|
130
|
+
<ChatSample />
|
|
131
|
+
</ChatBubble>
|
|
132
|
+
)
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export const PortalExample: Story = {
|
|
136
|
+
render: args => (
|
|
137
|
+
<>
|
|
138
|
+
<div className="relative w-[400px] h-[300px] border-2 border-gray-300 flex justify-center items-center">
|
|
139
|
+
<p className="text-gray-600">The ChatBubble will portal here!</p>
|
|
140
|
+
<ChatBubble className="absolute left-5 bottom-5" {...args}>
|
|
141
|
+
<ChatSample />
|
|
142
|
+
</ChatBubble>
|
|
143
|
+
</div>
|
|
144
|
+
</>
|
|
145
|
+
)
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
export const WithChildren: Story = {
|
|
149
|
+
render: args => {
|
|
150
|
+
const [activeId, setActiveId] = useState<string>();
|
|
151
|
+
const [sessions, setSessions] = useState<Session[]>([
|
|
152
|
+
...fakeSessions,
|
|
153
|
+
...sessionsWithFiles,
|
|
154
|
+
...sessionWithSources
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
return (
|
|
158
|
+
<div className="fixed left-5 bottom-5">
|
|
159
|
+
<ChatBubble {...args}>
|
|
160
|
+
<div
|
|
161
|
+
className="dark:bg-gray-950 bg-white"
|
|
162
|
+
style={{
|
|
163
|
+
width: 350,
|
|
164
|
+
height: 500,
|
|
165
|
+
padding: 20,
|
|
166
|
+
borderRadius: 5
|
|
167
|
+
}}
|
|
168
|
+
>
|
|
169
|
+
<Chat
|
|
170
|
+
viewType="companion"
|
|
171
|
+
sessions={sessions}
|
|
172
|
+
activeSessionId={activeId}
|
|
173
|
+
onNewSession={() => {
|
|
174
|
+
const newId = (sessions.length + 1).toLocaleString();
|
|
175
|
+
setSessions([
|
|
176
|
+
...sessions,
|
|
177
|
+
{
|
|
178
|
+
id: newId,
|
|
179
|
+
title: `New Session #${newId}`,
|
|
180
|
+
createdAt: new Date(),
|
|
181
|
+
updatedAt: new Date(),
|
|
182
|
+
conversations: []
|
|
183
|
+
}
|
|
184
|
+
]);
|
|
185
|
+
setActiveId(newId);
|
|
186
|
+
}}
|
|
187
|
+
onSelectSession={setActiveId}
|
|
188
|
+
onDeleteSession={() => alert('delete!')}
|
|
189
|
+
>
|
|
190
|
+
<SessionsList>
|
|
191
|
+
<NewSessionButton />
|
|
192
|
+
<SessionGroups />
|
|
193
|
+
</SessionsList>
|
|
194
|
+
<SessionMessagePanel>
|
|
195
|
+
<SessionMessagesHeader />
|
|
196
|
+
<SessionMessages />
|
|
197
|
+
<ChatInput />
|
|
198
|
+
</SessionMessagePanel>
|
|
199
|
+
</Chat>
|
|
200
|
+
</div>
|
|
201
|
+
</ChatBubble>
|
|
202
|
+
</div>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
export const WithChildrenPortal: Story = {
|
|
208
|
+
render: args => {
|
|
209
|
+
const [activeId, setActiveId] = useState<string>();
|
|
210
|
+
const [sessions, setSessions] = useState<Session[]>([
|
|
211
|
+
...fakeSessions,
|
|
212
|
+
...sessionsWithFiles,
|
|
213
|
+
...sessionWithSources
|
|
214
|
+
]);
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<>
|
|
218
|
+
<div className="relative w-[400px] h-[300px] border-2 border-gray-300 flex flex-col justify-center items-center">
|
|
219
|
+
<p className="text-gray-600">The ChatBubble will portal here!</p>
|
|
220
|
+
<ChatBubble {...args} className="absolute left-5 bottom-5">
|
|
221
|
+
<div
|
|
222
|
+
className="dark:bg-gray-950 bg-white"
|
|
223
|
+
style={{
|
|
224
|
+
width: 350,
|
|
225
|
+
height: 500,
|
|
226
|
+
padding: 20,
|
|
227
|
+
borderRadius: 5
|
|
228
|
+
}}
|
|
229
|
+
>
|
|
230
|
+
<Chat
|
|
231
|
+
viewType="companion"
|
|
232
|
+
sessions={sessions}
|
|
233
|
+
activeSessionId={activeId}
|
|
234
|
+
onNewSession={() => {
|
|
235
|
+
const newId = (sessions.length + 1).toLocaleString();
|
|
236
|
+
setSessions([
|
|
237
|
+
...sessions,
|
|
238
|
+
{
|
|
239
|
+
id: newId,
|
|
240
|
+
title: `New Session #${newId}`,
|
|
241
|
+
createdAt: new Date(),
|
|
242
|
+
updatedAt: new Date(),
|
|
243
|
+
conversations: []
|
|
244
|
+
}
|
|
245
|
+
]);
|
|
246
|
+
setActiveId(newId);
|
|
247
|
+
}}
|
|
248
|
+
onSelectSession={setActiveId}
|
|
249
|
+
onDeleteSession={() => alert('delete!')}
|
|
250
|
+
>
|
|
251
|
+
<SessionsList>
|
|
252
|
+
<NewSessionButton />
|
|
253
|
+
<SessionGroups />
|
|
254
|
+
</SessionsList>
|
|
255
|
+
<SessionMessagePanel>
|
|
256
|
+
<SessionMessagesHeader />
|
|
257
|
+
<SessionMessages />
|
|
258
|
+
<ChatInput />
|
|
259
|
+
</SessionMessagePanel>
|
|
260
|
+
</Chat>
|
|
261
|
+
</div>
|
|
262
|
+
</ChatBubble>
|
|
263
|
+
</div>
|
|
264
|
+
</>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
};
|