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.
@@ -0,0 +1,8 @@
1
+ import { Meta, Markdown } from '@storybook/addon-docs';
2
+ import Readme from "../CHANGELOG.md?raw";
3
+
4
+ <Meta title="Docs/Changelog" />
5
+
6
+ # Changelog
7
+
8
+ <Markdown>{Readme}</Markdown>
@@ -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
+ };