blixify-ui-web-mcp 0.1.3 → 0.1.18
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/lib/components/action/button/README.md +12 -11
- package/lib/components/action/button/button.stories.tsx +4 -10
- package/lib/components/action/buttonGroup/buttonGroup.stories.tsx +4 -10
- package/lib/components/action/iconButton/iconButton.stories.tsx +4 -10
- package/lib/components/action/radioList/radioList.stories.tsx +4 -10
- package/lib/components/action/slider/slider.stories.tsx +4 -10
- package/lib/components/action/textButton/textButton.stories.tsx +4 -10
- package/lib/components/action/toggle/toggle.stories.tsx +4 -10
- package/lib/components/advanced/collapse/collapse.stories.tsx +4 -10
- package/lib/components/advanced/infoWindow/infoWindow.stories.tsx +4 -10
- package/lib/components/advanced/popUp/README.md +21 -7
- package/lib/components/advanced/popUp/popUp.stories.tsx +4 -10
- package/lib/components/auth/bareSignIn/bareSignIn.stories.tsx +30 -10
- package/lib/components/auth/bareSignUp/bareSignUp.stories.tsx +4 -10
- package/lib/components/auth/signIn/signIn.stories.tsx +4 -10
- package/lib/components/auth/signUp/signUp.stories.tsx +4 -10
- package/lib/components/chart/areaChart/areaChart.stories.tsx +7 -13
- package/lib/components/chart/barChart/barChart.stories.tsx +7 -13
- package/lib/components/chart/boxPlotChart/boxPlotChart.stories.tsx +8 -14
- package/lib/components/chart/bubbleChart/bubbleChart.stories.tsx +8 -14
- package/lib/components/chart/card/card.stories.tsx +4 -10
- package/lib/components/chart/ganttChart/ganttChart.stories.tsx +4 -10
- package/lib/components/chart/heatmapChart/heatmapChart.stories.tsx +4 -10
- package/lib/components/chart/lineChart/lineChart.stories.tsx +4 -10
- package/lib/components/chart/pieChart/pieChart.stories.tsx +4 -10
- package/lib/components/chart/polarAreaChart/polarAreaChart.stories.tsx +8 -14
- package/lib/components/chart/radarChart/radarChart.stories.tsx +4 -10
- package/lib/components/chart/radialBar/radialChart.stories.tsx +4 -10
- package/lib/components/chart/rangeBarChart/rangeBarChart.stories.tsx +4 -10
- package/lib/components/chart/statsCard/statsCard.stories.tsx +4 -10
- package/lib/components/chart/treemapChart/treemapChart.stories.tsx +8 -14
- package/lib/components/chat/chatAnchor/chatAnchor.stories.tsx +13 -19
- package/lib/components/chat/chatBase/README.md +103 -22
- package/lib/components/chat/chatBase/chatBase.stories.tsx +652 -52
- package/lib/components/chat/chatDashboard/README.md +17 -15
- package/lib/components/chat/chatDashboard/chatDashboard.stories.tsx +356 -44
- package/lib/components/data/dataGraph/dataGraph.stories.tsx +4 -10
- package/lib/components/data/dataReference/dataReference.stories.tsx +4 -10
- package/lib/components/data/dataTemplate/README.md +88 -61
- package/lib/components/data/dataTemplate/dataModule.stories.tsx +4 -10
- package/lib/components/data/dataTemplate/dataTemplate.stories.tsx +4 -10
- package/lib/components/data/dataWrapper/README.md +46 -45
- package/lib/components/data/dataWrapper/dataWrapper.stories.tsx +258 -489
- package/lib/components/data/queryForm/queryForm.stories.tsx +4 -10
- package/lib/components/data/readQuery/readQuery.stories.tsx +4 -9
- package/lib/components/data/readQueryHoc/readQueryHoc.stories.tsx +4 -10
- package/lib/components/data/writeQuery/writeQuery.stories.tsx +4 -8
- package/lib/components/design/actionSection/actionSection.stories.tsx +6 -10
- package/lib/components/design/banner/banner.stories.tsx +4 -10
- package/lib/components/design/bannerAction/bannerAction.stories.tsx +4 -10
- package/lib/components/design/blogSection/blogSection.stories.tsx +4 -10
- package/lib/components/design/carouselSection/carouselSection.stories.tsx +4 -10
- package/lib/components/design/designList/designList.stories.tsx +4 -10
- package/lib/components/design/faq/faq.stories.tsx +4 -10
- package/lib/components/design/fileGrid/fileGrid.stories.tsx +4 -10
- package/lib/components/design/fileViewer/fileViewer.stories.tsx +4 -10
- package/lib/components/design/footerSection/footerSection.stories.tsx +4 -10
- package/lib/components/design/googleReview/googleReview.stories.tsx +4 -10
- package/lib/components/design/heroSection/heroSection.stories.tsx +4 -10
- package/lib/components/design/iconList/iconList.stories.tsx +4 -10
- package/lib/components/design/imageGallery/imageGallery.stories.tsx +4 -10
- package/lib/components/design/imageZoom/imageZoom.stories.tsx +4 -10
- package/lib/components/design/leftContent/leftContent.stories.tsx +4 -10
- package/lib/components/design/logoCloud/logoCloud.stories.tsx +4 -10
- package/lib/components/design/onboarding/onboarding.stories.tsx +4 -10
- package/lib/components/design/pricing/pricing.stories.tsx +4 -10
- package/lib/components/design/rightContent/rightContent.stories.tsx +4 -10
- package/lib/components/design/sectionList/sectionList.stories.tsx +4 -10
- package/lib/components/design/teams/teams.stories.tsx +4 -10
- package/lib/components/display/alert/alert.stories.tsx +4 -10
- package/lib/components/display/calendar/README.md +49 -0
- package/lib/components/display/calendar/calendar.stories.tsx +71 -28
- package/lib/components/display/clipboard/clipboard.stories.tsx +4 -10
- package/lib/components/display/detailList/detailList.stories.tsx +5 -10
- package/lib/components/display/drawer/drawer.stories.tsx +5 -10
- package/lib/components/display/emptyState/emptyState.stories.tsx +4 -10
- package/lib/components/display/feeds/feeds.stories.tsx +4 -10
- package/lib/components/display/flexTable/README.md +11 -7
- package/lib/components/display/flexTable/flexTable.stories.tsx +114 -11
- package/lib/components/display/grid/README.md +28 -27
- package/lib/components/display/grid/grid.stories.tsx +4 -10
- package/lib/components/display/kanban/kanban.stories.tsx +14 -20
- package/lib/components/display/list/README.md +30 -29
- package/lib/components/display/list/list.stories.tsx +4 -10
- package/lib/components/display/loading/loading.stories.tsx +5 -10
- package/lib/components/display/mapView/mapView.stories.tsx +4 -10
- package/lib/components/display/modal/modal.stories.tsx +4 -11
- package/lib/components/display/notification/notification.stories.tsx +4 -10
- package/lib/components/display/progress/progress.stories.tsx +5 -10
- package/lib/components/display/stepper/stepper.stories.tsx +5 -10
- package/lib/components/display/table/README.md +38 -37
- package/lib/components/display/table/table.stories.tsx +8 -14
- package/lib/components/display/tag/tag.stories.tsx +4 -10
- package/lib/components/input/address/address.stories.tsx +4 -10
- package/lib/components/input/canvas/canvas.stories.tsx +4 -10
- package/lib/components/input/checkbox/checkbox.stories.tsx +4 -10
- package/lib/components/input/datePicker/datePicker.stories.tsx +4 -10
- package/lib/components/input/form/form.stories.tsx +4 -10
- package/lib/components/input/markdown/markdown.stories.tsx +5 -10
- package/lib/components/input/monthYearPicker/monthYearPicker.stories.tsx +4 -10
- package/lib/components/input/netPromoterScore/netPromoterScore.stories.tsx +4 -10
- package/lib/components/input/rating/rating.stories.tsx +4 -10
- package/lib/components/input/select/README.md +30 -29
- package/lib/components/input/select/select.stories.tsx +4 -10
- package/lib/components/input/signature/signature.stories.tsx +4 -10
- package/lib/components/input/textArea/textArea.stories.tsx +4 -10
- package/lib/components/input/textInput/textinput.stories.tsx +4 -10
- package/lib/components/input/uploadInput/uploadInput.stories.tsx +135 -11
- package/lib/components/navigation/bars/bars.stories.tsx +4 -10
- package/lib/components/navigation/bottomTab/bottomTab.stories.tsx +5 -10
- package/lib/components/navigation/breadcrumb/breadcrumb.stories.tsx +4 -10
- package/lib/components/navigation/header/header.stories.tsx +24 -12
- package/lib/components/navigation/leftNav/leftNav.stories.tsx +4 -10
- package/lib/components/navigation/tabs/tabs.stories.tsx +4 -10
- package/lib/components/structure/column/column.stories.tsx +5 -10
- package/lib/components/structure/container/container.stories.tsx +5 -10
- package/lib/components/structure/link/link.stories.tsx +4 -10
- package/lib/components/structure/text/text.stories.tsx +5 -10
- package/lib/components/template/authPage/authPage.stories.tsx +6 -5
- package/lib/components/template/landingPage/landingPage.stories.tsx +8 -6
- package/lib/components/template/productListing/productListing.stories.tsx +7 -13
- package/lib/components/template/productOverview/productOverview.stories.tsx +5 -11
- package/lib/components/template/shoppingCart/shoppingCart.stories.tsx +6 -12
- package/lib/components/template/userHomePage/userHomePage.stories.tsx +7 -6
- package/lib/components/template/userRankingDashboard/userRankingDashboard.stories.tsx +5 -11
- package/package.json +1 -1
|
@@ -1,21 +1,16 @@
|
|
|
1
1
|
import { TrashIcon } from "@heroicons/react/24/outline";
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
2
|
+
import { MicrophoneIcon, CameraIcon } from "@heroicons/react/24/outline";
|
|
3
|
+
import { DocumentIcon, XMarkIcon } from "@heroicons/react/24/solid";
|
|
4
|
+
import dayjs from "../../dayjs";
|
|
4
5
|
import React, { useState } from "react";
|
|
5
|
-
import {
|
|
6
|
-
import { ChatBase, ChatBaseAction, Conversation } from ".";
|
|
6
|
+
import { ChatBase, ChatBaseAction, Conversation, Message, ToolCall } from ".";
|
|
7
7
|
import Logo from "../../../assets/logo.png";
|
|
8
8
|
import { StorySection } from "../../storyUtils";
|
|
9
9
|
import { TextButton } from "../../action/textButton";
|
|
10
|
-
import
|
|
10
|
+
import { IconButton } from "../../action/iconButton";
|
|
11
11
|
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
stories.addParameters({
|
|
15
|
-
readme: {
|
|
16
|
-
content: README,
|
|
17
|
-
},
|
|
18
|
-
});
|
|
12
|
+
const meta = { title: "Chat/Chat Base" };
|
|
13
|
+
export default meta;
|
|
19
14
|
|
|
20
15
|
const botUser = {
|
|
21
16
|
id: "bot",
|
|
@@ -25,37 +20,190 @@ const botUser = {
|
|
|
25
20
|
};
|
|
26
21
|
const currentUser = { id: "me", name: "You" };
|
|
27
22
|
|
|
28
|
-
const seedMessages = [
|
|
23
|
+
const seedMessages: Message[] = [
|
|
29
24
|
{
|
|
30
25
|
sender: botUser,
|
|
31
26
|
messageBody: "Hi! How can I help you? 🤖",
|
|
32
|
-
createdAt:
|
|
27
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
33
28
|
},
|
|
34
29
|
{
|
|
35
30
|
sender: currentUser,
|
|
36
31
|
messageBody: "My computer keeps crashing.",
|
|
37
|
-
createdAt:
|
|
32
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
38
33
|
},
|
|
39
34
|
{
|
|
40
35
|
sender: botUser,
|
|
41
36
|
messageBody:
|
|
42
37
|
"**Quick Tips**\n1. Restart your machine.\n2. Check for updates.\n3. Free up disk space.",
|
|
43
|
-
createdAt:
|
|
38
|
+
createdAt: dayjs("2023-11-03 12:02").toDate(),
|
|
44
39
|
},
|
|
45
40
|
{
|
|
46
41
|
sender: currentUser,
|
|
47
42
|
messageBody: "Thanks, I'll try that!",
|
|
48
|
-
createdAt:
|
|
43
|
+
createdAt: dayjs("2023-11-03 12:03").toDate(),
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
sender: botUser,
|
|
47
|
+
messageBody:
|
|
48
|
+
"You can also check the [official troubleshooting guide](https://google.com) or visit [our FAQ page](https://google.com) for more help.",
|
|
49
|
+
createdAt: dayjs("2023-11-03 12:04").toDate(),
|
|
49
50
|
},
|
|
50
51
|
];
|
|
51
52
|
|
|
52
|
-
const makeConversation = (
|
|
53
|
+
const makeConversation = (
|
|
54
|
+
messages: Message[] = seedMessages
|
|
55
|
+
): Conversation => ({
|
|
53
56
|
id: "1",
|
|
54
57
|
members: [currentUser, botUser],
|
|
55
58
|
messageList: messages,
|
|
56
59
|
});
|
|
57
60
|
|
|
58
|
-
|
|
61
|
+
const toolCallSequence: {
|
|
62
|
+
content: string;
|
|
63
|
+
request: string;
|
|
64
|
+
delayMs: number;
|
|
65
|
+
}[] = [
|
|
66
|
+
{
|
|
67
|
+
content: "search_knowledge_base",
|
|
68
|
+
request: "query: order status #4821",
|
|
69
|
+
delayMs: 800,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
content: "fetch_user_context",
|
|
73
|
+
request: "userId: current_user",
|
|
74
|
+
delayMs: 1400,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
content: "generate_summary",
|
|
78
|
+
request: "summarize order + delivery info",
|
|
79
|
+
delayMs: 2200,
|
|
80
|
+
},
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
const seedToolMessages: Message[] = [
|
|
84
|
+
{
|
|
85
|
+
sender: botUser,
|
|
86
|
+
messageBody:
|
|
87
|
+
"Hi! I'm an AI assistant. Ask me anything and I'll show you which tools I use to answer.",
|
|
88
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
sender: { id: "me", name: "You" },
|
|
92
|
+
messageBody: "What's the status of my latest order?",
|
|
93
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
sender: botUser,
|
|
97
|
+
messageBody:
|
|
98
|
+
"Your latest order #4821 is currently **out for delivery** and should arrive today by 6 PM.",
|
|
99
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
100
|
+
toolReport: {
|
|
101
|
+
model: "gemini-3-flash-preview",
|
|
102
|
+
tools: [
|
|
103
|
+
{
|
|
104
|
+
content: "search_orders",
|
|
105
|
+
request: "query: latest order for user",
|
|
106
|
+
response: { success: true, output: "Order #4821 found" },
|
|
107
|
+
status: "done",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
content: "fetch_delivery_status",
|
|
111
|
+
request: "orderId: 4821",
|
|
112
|
+
response: { success: true, output: "Out for delivery, ETA 6 PM" },
|
|
113
|
+
status: "done",
|
|
114
|
+
},
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
sender: { id: "me", name: "You" },
|
|
120
|
+
messageBody: "Can you summarise my account activity?",
|
|
121
|
+
createdAt: dayjs("2023-11-03 12:02").toDate(),
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
sender: botUser,
|
|
125
|
+
messageBody:
|
|
126
|
+
"Sorry, I couldn't retrieve your account activity right now. Please try again later.",
|
|
127
|
+
createdAt: dayjs("2023-11-03 12:02").toDate(),
|
|
128
|
+
toolReport: {
|
|
129
|
+
model: "gemini-3-flash-preview",
|
|
130
|
+
tools: [
|
|
131
|
+
{
|
|
132
|
+
content: "fetch_account_activity",
|
|
133
|
+
request: "userId: current_user",
|
|
134
|
+
response: { success: false, output: "Service unavailable" },
|
|
135
|
+
status: "error",
|
|
136
|
+
},
|
|
137
|
+
],
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
];
|
|
141
|
+
|
|
142
|
+
const toolCallConversation: Conversation = {
|
|
143
|
+
id: "tool-call-demo",
|
|
144
|
+
members: [currentUser, botUser],
|
|
145
|
+
messageList: [
|
|
146
|
+
{
|
|
147
|
+
sender: currentUser,
|
|
148
|
+
messageBody: "What's my policy renewal date?",
|
|
149
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
sender: botUser,
|
|
153
|
+
messageBody: "lookup_policy_by_user",
|
|
154
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
155
|
+
isToolCall: true,
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
sender: botUser,
|
|
159
|
+
messageBody: "fetch_renewal_schedule",
|
|
160
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
161
|
+
isToolCall: true,
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
sender: botUser,
|
|
165
|
+
messageBody:
|
|
166
|
+
"Your policy **POL-00421** is due for renewal on **15 Jan 2025**. Would you like me to send a reminder?",
|
|
167
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
sender: currentUser,
|
|
171
|
+
messageBody:
|
|
172
|
+
"Yes please, and also check if there are any pending claims.",
|
|
173
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
sender: botUser,
|
|
177
|
+
messageBody: "schedule_renewal_reminder",
|
|
178
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
179
|
+
isToolCall: true,
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
sender: botUser,
|
|
183
|
+
messageBody: "fetch_claims_by_policy",
|
|
184
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
185
|
+
isToolCall: true,
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
sender: botUser,
|
|
189
|
+
messageBody:
|
|
190
|
+
"Done! Reminder set for 8 Jan 2025. You have **1 pending claim** (REF-8821) currently under review.",
|
|
191
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
// INFO: generates older messages for scroll-up pagination demo
|
|
197
|
+
const generateOlderMessages = (page: number): Message[] =>
|
|
198
|
+
Array.from({ length: 10 }, (_, i) => ({
|
|
199
|
+
sender: i % 2 === 0 ? botUser : currentUser,
|
|
200
|
+
messageBody: `Older message ${i + 1} from page ${page}`,
|
|
201
|
+
createdAt: dayjs("2023-11-03 12:00")
|
|
202
|
+
.subtract(page * 10 + (10 - i), "minutes")
|
|
203
|
+
.toDate(),
|
|
204
|
+
}));
|
|
205
|
+
|
|
206
|
+
export const ChatBaseStory = () => {
|
|
59
207
|
// --- Default ---
|
|
60
208
|
const [msg1, setMsg1] = useState("");
|
|
61
209
|
const [conv1, setConv1] = useState(makeConversation());
|
|
@@ -73,14 +221,140 @@ stories.add("Chat Base", () => {
|
|
|
73
221
|
|
|
74
222
|
// --- File upload ---
|
|
75
223
|
const [msg4, setMsg4] = useState("");
|
|
76
|
-
const [conv4, setConv4] = useState(
|
|
77
|
-
|
|
224
|
+
const [conv4, setConv4] = useState(
|
|
225
|
+
makeConversation([
|
|
226
|
+
{
|
|
227
|
+
sender: botUser,
|
|
228
|
+
messageBody: {
|
|
229
|
+
fileName:
|
|
230
|
+
"https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=400",
|
|
231
|
+
token: "sample-image.jpg",
|
|
232
|
+
type: "image/jpeg",
|
|
233
|
+
} as any,
|
|
234
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
sender: botUser,
|
|
238
|
+
messageBody: {
|
|
239
|
+
fileName:
|
|
240
|
+
"https://firebasestorage.googleapis.com/v0/b/verdant-solar-dev.appspot.com/o/preCheckList%2F0184b7ee-8bb0-4a48-992c-ac8d37f8e833%2FPre-Checklist.pdf?alt=media&token=1de8eafb-27c4-4ff7-91a3-e640e4ef07cf",
|
|
241
|
+
token: "sample-document.pdf",
|
|
242
|
+
type: "application/pdf",
|
|
243
|
+
} as any,
|
|
244
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
sender: botUser,
|
|
248
|
+
messageBody: {
|
|
249
|
+
fileName:
|
|
250
|
+
"https://docs.google.com/document/d/18eW31QU-UY_Tw2zJBzwaWTiijbuRKR7x/edit?usp=drive_link&ouid=106313527006787712257&rtpof=true&sd=true",
|
|
251
|
+
token: "sample-report.docx",
|
|
252
|
+
type: "",
|
|
253
|
+
} as any,
|
|
254
|
+
createdAt: dayjs("2023-11-03 12:02").toDate(),
|
|
255
|
+
},
|
|
256
|
+
])
|
|
257
|
+
);
|
|
258
|
+
const [files4, setFiles4] = useState<File[]>([]);
|
|
259
|
+
|
|
260
|
+
// --- Multi-line input ---
|
|
261
|
+
const [msg11, setMsg11] = useState("");
|
|
262
|
+
const [conv11, setConv11] = useState(makeConversation());
|
|
263
|
+
|
|
264
|
+
// --- Media rendering (audio / attachments[]) ---
|
|
265
|
+
const [msg12, setMsg12] = useState("");
|
|
266
|
+
const [conv12, setConv12] = useState(
|
|
267
|
+
makeConversation([
|
|
268
|
+
{
|
|
269
|
+
sender: currentUser,
|
|
270
|
+
messageBody: "Here are the photos from the site visit.",
|
|
271
|
+
attachments: [
|
|
272
|
+
{
|
|
273
|
+
fileName:
|
|
274
|
+
"https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?w=400",
|
|
275
|
+
token: "site-photo-1.jpg",
|
|
276
|
+
type: "image/jpeg",
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
fileName:
|
|
280
|
+
"https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?w=400",
|
|
281
|
+
token: "site-photo-2.jpg",
|
|
282
|
+
type: "image/jpeg",
|
|
283
|
+
},
|
|
284
|
+
] as any,
|
|
285
|
+
createdAt: dayjs("2023-11-03 12:00").toDate(),
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
sender: botUser,
|
|
289
|
+
messageBody:
|
|
290
|
+
"Got them, thanks! I've also attached the inspection report and a voice note summary.",
|
|
291
|
+
attachments: [
|
|
292
|
+
{
|
|
293
|
+
fileName:
|
|
294
|
+
"https://www.soundhelix.com/examples/mp3/SoundHelix-Song-1.mp3",
|
|
295
|
+
token: "voice-summary.mp3",
|
|
296
|
+
type: "audio/mpeg",
|
|
297
|
+
},
|
|
298
|
+
] as any,
|
|
299
|
+
createdAt: dayjs("2023-11-03 12:01").toDate(),
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
sender: currentUser,
|
|
303
|
+
messageBody: "Perfect. Can you also send the diagram?",
|
|
304
|
+
attachments: [
|
|
305
|
+
{
|
|
306
|
+
fileName:
|
|
307
|
+
"https://images.unsplash.com/photo-1519389950473-47ba0277781c?w=400",
|
|
308
|
+
token: "diagram.jpg",
|
|
309
|
+
type: "image/jpeg",
|
|
310
|
+
},
|
|
311
|
+
] as any,
|
|
312
|
+
createdAt: dayjs("2023-11-03 12:02").toDate(),
|
|
313
|
+
},
|
|
314
|
+
])
|
|
315
|
+
);
|
|
78
316
|
|
|
79
317
|
// --- Loading reply ---
|
|
80
|
-
const [msg5, setMsg5] = useState("");
|
|
318
|
+
const [msg5, setMsg5] = useState("Hello, any updates?");
|
|
81
319
|
const [conv5, setConv5] = useState(makeConversation());
|
|
82
320
|
const [isLoading, setIsLoading] = useState(false);
|
|
83
321
|
|
|
322
|
+
// --- Tool report ---
|
|
323
|
+
const [msg6, setMsg6] = useState("");
|
|
324
|
+
const [isLoading6, setIsLoading6] = useState(false);
|
|
325
|
+
const [conv6, setConv6] = useState<Conversation>({
|
|
326
|
+
id: "tool-demo",
|
|
327
|
+
members: [currentUser, botUser],
|
|
328
|
+
messageList: seedToolMessages,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
// --- Scroll-up pagination ---
|
|
332
|
+
const [msg7, setMsg7] = useState("");
|
|
333
|
+
const [msgPage, setMsgPage] = useState(1);
|
|
334
|
+
const [loadingOlder, setLoadingOlder] = useState(false);
|
|
335
|
+
const [conv7, setConv7] = useState<Conversation>(
|
|
336
|
+
makeConversation(generateOlderMessages(0))
|
|
337
|
+
);
|
|
338
|
+
|
|
339
|
+
// --- Quick replies (footerElement) ---
|
|
340
|
+
const quickReplies = [
|
|
341
|
+
"Track my order",
|
|
342
|
+
"Speak to an agent",
|
|
343
|
+
"View FAQs",
|
|
344
|
+
"Reset password",
|
|
345
|
+
];
|
|
346
|
+
const [msg8, setMsg8] = useState("");
|
|
347
|
+
const [conv8, setConv8] = useState(makeConversation());
|
|
348
|
+
|
|
349
|
+
// --- Input actions ---
|
|
350
|
+
const [msg9, setMsg9] = useState("");
|
|
351
|
+
const [conv9, setConv9] = useState(makeConversation());
|
|
352
|
+
|
|
353
|
+
// --- File attach with URI footer ---
|
|
354
|
+
const [msg10, setMsg10] = useState("");
|
|
355
|
+
const [conv10, setConv10] = useState(makeConversation());
|
|
356
|
+
const [files10, setFiles10] = useState<File[]>([]);
|
|
357
|
+
|
|
84
358
|
const sendMessage =
|
|
85
359
|
(
|
|
86
360
|
conv: Conversation,
|
|
@@ -108,6 +382,67 @@ stories.add("Chat Base", () => {
|
|
|
108
382
|
}
|
|
109
383
|
};
|
|
110
384
|
|
|
385
|
+
const handleSendToolReport = (updated: Conversation) => {
|
|
386
|
+
setMsg6("");
|
|
387
|
+
setIsLoading6(true);
|
|
388
|
+
|
|
389
|
+
const pendingTools: ToolCall[] = toolCallSequence.map((t) => ({
|
|
390
|
+
content: t.content,
|
|
391
|
+
request: t.request,
|
|
392
|
+
response: null,
|
|
393
|
+
status: "pending" as const,
|
|
394
|
+
}));
|
|
395
|
+
|
|
396
|
+
const placeholderMsg: Message = {
|
|
397
|
+
sender: botUser,
|
|
398
|
+
messageBody: "",
|
|
399
|
+
createdAt: dayjs().toDate(),
|
|
400
|
+
toolReport: { model: "gemini-3-flash-preview", tools: pendingTools },
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
setConv6({
|
|
404
|
+
...updated,
|
|
405
|
+
messageList: [...updated.messageList, placeholderMsg],
|
|
406
|
+
});
|
|
407
|
+
|
|
408
|
+
toolCallSequence.forEach(({ content, delayMs }) => {
|
|
409
|
+
setTimeout(() => {
|
|
410
|
+
setConv6((prev) => {
|
|
411
|
+
const msgs = [...prev.messageList];
|
|
412
|
+
const last = { ...msgs[msgs.length - 1] };
|
|
413
|
+
last.toolReport = {
|
|
414
|
+
...last.toolReport!,
|
|
415
|
+
tools: last.toolReport!.tools.map((t) =>
|
|
416
|
+
t.content === content
|
|
417
|
+
? {
|
|
418
|
+
...t,
|
|
419
|
+
status: "done" as const,
|
|
420
|
+
response: { success: true, output: "OK" },
|
|
421
|
+
}
|
|
422
|
+
: t
|
|
423
|
+
),
|
|
424
|
+
};
|
|
425
|
+
msgs[msgs.length - 1] = last;
|
|
426
|
+
return { ...prev, messageList: msgs };
|
|
427
|
+
});
|
|
428
|
+
}, delayMs);
|
|
429
|
+
});
|
|
430
|
+
|
|
431
|
+
const totalDelay =
|
|
432
|
+
toolCallSequence[toolCallSequence.length - 1].delayMs + 400;
|
|
433
|
+
setTimeout(() => {
|
|
434
|
+
setConv6((prev) => {
|
|
435
|
+
const msgs = [...prev.messageList];
|
|
436
|
+
const last = { ...msgs[msgs.length - 1] };
|
|
437
|
+
last.messageBody =
|
|
438
|
+
"I've checked across all relevant sources. Here's a summary based on your query — everything looks good on our end!";
|
|
439
|
+
msgs[msgs.length - 1] = last;
|
|
440
|
+
return { ...prev, messageList: msgs };
|
|
441
|
+
});
|
|
442
|
+
setIsLoading6(false);
|
|
443
|
+
}, totalDelay);
|
|
444
|
+
};
|
|
445
|
+
|
|
111
446
|
const handleSendWithReply = (updated: Conversation) => {
|
|
112
447
|
setConv5(updated);
|
|
113
448
|
setMsg5("");
|
|
@@ -120,7 +455,7 @@ stories.add("Chat Base", () => {
|
|
|
120
455
|
{
|
|
121
456
|
sender: botUser,
|
|
122
457
|
messageBody: "Got it! Let me look into that for you.",
|
|
123
|
-
createdAt:
|
|
458
|
+
createdAt: dayjs().toDate(),
|
|
124
459
|
},
|
|
125
460
|
],
|
|
126
461
|
}));
|
|
@@ -128,6 +463,20 @@ stories.add("Chat Base", () => {
|
|
|
128
463
|
}, 2000);
|
|
129
464
|
};
|
|
130
465
|
|
|
466
|
+
// INFO: scroll-up handler — prepends older messages after a simulated delay
|
|
467
|
+
const handleLoadOlderMessages = () => {
|
|
468
|
+
setLoadingOlder(true);
|
|
469
|
+
const nextPage = msgPage + 1;
|
|
470
|
+
setTimeout(() => {
|
|
471
|
+
setConv7((prev) => ({
|
|
472
|
+
...prev,
|
|
473
|
+
messageList: [...generateOlderMessages(nextPage), ...prev.messageList],
|
|
474
|
+
}));
|
|
475
|
+
setMsgPage(nextPage);
|
|
476
|
+
setLoadingOlder(false);
|
|
477
|
+
}, 1000);
|
|
478
|
+
};
|
|
479
|
+
|
|
131
480
|
const clearAction = (
|
|
132
481
|
setConv: (c: Conversation) => void
|
|
133
482
|
): ChatBaseAction[] => [
|
|
@@ -218,7 +567,7 @@ stories.add("Chat Base", () => {
|
|
|
218
567
|
|
|
219
568
|
<StorySection
|
|
220
569
|
title="File Upload"
|
|
221
|
-
description="fileUpload.allowFileUpload=true shows a paperclip button.
|
|
570
|
+
description="fileUpload.allowFileUpload=true shows a paperclip button. Selected files appear as chips in footerElement. onSendMessage fires for both text and file sends — the consumer handles upload logic there."
|
|
222
571
|
>
|
|
223
572
|
<ChatBase
|
|
224
573
|
open
|
|
@@ -227,37 +576,58 @@ stories.add("Chat Base", () => {
|
|
|
227
576
|
conversation={conv4}
|
|
228
577
|
fileUpload={{
|
|
229
578
|
allowFileUpload: true,
|
|
230
|
-
|
|
231
|
-
|
|
579
|
+
hasFiles: files4.length > 0,
|
|
580
|
+
multiple: true,
|
|
581
|
+
acceptFileType: ".jpg,.jpeg,.png,.mp4,.webm,.pdf,.docx",
|
|
232
582
|
onChangeUpload: (e) => {
|
|
233
|
-
if (e?.target?.files?.length > 0)
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const fileUrl = URL.createObjectURL(file);
|
|
239
|
-
setConv4({
|
|
240
|
-
...conversation,
|
|
241
|
-
messageList: [
|
|
242
|
-
...conversation.messageList,
|
|
243
|
-
{
|
|
244
|
-
sender: currentUser,
|
|
245
|
-
messageBody: {
|
|
246
|
-
fileName: fileUrl,
|
|
247
|
-
token: uuidv4(),
|
|
248
|
-
type: file.type,
|
|
249
|
-
},
|
|
250
|
-
createdAt: moment().toDate(),
|
|
251
|
-
},
|
|
252
|
-
],
|
|
253
|
-
});
|
|
254
|
-
setFile(undefined);
|
|
255
|
-
setMsg4("");
|
|
256
|
-
}
|
|
583
|
+
if (e?.target?.files?.length > 0)
|
|
584
|
+
setFiles4((prev) => [
|
|
585
|
+
...prev,
|
|
586
|
+
...Array.from(e.target.files as FileList),
|
|
587
|
+
]);
|
|
257
588
|
},
|
|
258
589
|
}}
|
|
259
|
-
onSendMessage={
|
|
590
|
+
onSendMessage={(updated) => {
|
|
591
|
+
const newMessages = files4.map((f) => ({
|
|
592
|
+
sender: currentUser,
|
|
593
|
+
messageBody: {
|
|
594
|
+
fileName: URL.createObjectURL(f),
|
|
595
|
+
token: f.name,
|
|
596
|
+
type: f.type,
|
|
597
|
+
},
|
|
598
|
+
createdAt: dayjs().toDate(),
|
|
599
|
+
}));
|
|
600
|
+
setConv4({
|
|
601
|
+
...updated,
|
|
602
|
+
messageList: [...updated.messageList, ...newMessages],
|
|
603
|
+
});
|
|
604
|
+
setFiles4([]);
|
|
605
|
+
setMsg4("");
|
|
606
|
+
}}
|
|
260
607
|
onChangeMessage={(e) => setMsg4(e.target.value)}
|
|
608
|
+
footerElement={
|
|
609
|
+
files4.length > 0 ? (
|
|
610
|
+
<div className="flex flex-wrap gap-2 px-2 pb-1 pt-1">
|
|
611
|
+
{files4.map((f, i) => (
|
|
612
|
+
<span
|
|
613
|
+
key={i}
|
|
614
|
+
className="inline-flex items-center gap-1.5 rounded-full border border-primary-300 bg-primary-50 py-1 pl-2.5 pr-1.5 text-xs text-primary-700"
|
|
615
|
+
>
|
|
616
|
+
<DocumentIcon className="h-3.5 w-3.5 flex-shrink-0 text-primary-500" />
|
|
617
|
+
<span className="max-w-[140px] truncate">{f.name}</span>
|
|
618
|
+
<button
|
|
619
|
+
onClick={() =>
|
|
620
|
+
setFiles4((prev) => prev.filter((_, idx) => idx !== i))
|
|
621
|
+
}
|
|
622
|
+
className="ml-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full hover:bg-primary-200 transition-colors"
|
|
623
|
+
>
|
|
624
|
+
<XMarkIcon className="h-3 w-3 text-primary-500" />
|
|
625
|
+
</button>
|
|
626
|
+
</span>
|
|
627
|
+
))}
|
|
628
|
+
</div>
|
|
629
|
+
) : undefined
|
|
630
|
+
}
|
|
261
631
|
sizeClassName="h-[500px] w-96"
|
|
262
632
|
disableMobileResize
|
|
263
633
|
/>
|
|
@@ -279,6 +649,236 @@ stories.add("Chat Base", () => {
|
|
|
279
649
|
disableMobileResize
|
|
280
650
|
/>
|
|
281
651
|
</StorySection>
|
|
652
|
+
|
|
653
|
+
<StorySection
|
|
654
|
+
title="Tool Report"
|
|
655
|
+
description="When a message has a toolReport, a compact log panel is shown above the message body. It displays the model used and each tool call with a status dot: yellow (pending), green (done), red (error). Send a message to see the simulated tool-call flow."
|
|
656
|
+
>
|
|
657
|
+
<ChatBase
|
|
658
|
+
open
|
|
659
|
+
value={msg6}
|
|
660
|
+
currentUser={currentUser}
|
|
661
|
+
conversation={conv6}
|
|
662
|
+
isLoadingReply={isLoading6}
|
|
663
|
+
onSendMessage={handleSendToolReport}
|
|
664
|
+
onChangeMessage={(e) => setMsg6(e.target.value)}
|
|
665
|
+
sizeClassName="h-[500px] w-96"
|
|
666
|
+
disableMobileResize
|
|
667
|
+
/>
|
|
668
|
+
</StorySection>
|
|
669
|
+
|
|
670
|
+
<StorySection
|
|
671
|
+
title="Tool Call Messages"
|
|
672
|
+
description="Messages with isToolCall=true are rendered as centered inline chips instead of chat bubbles. This is used when the chat history includes tool invocation records (e.g. author: 'tool' from an AI pipeline). They sit between user and assistant messages to show what happened behind the scenes."
|
|
673
|
+
>
|
|
674
|
+
<ChatBase
|
|
675
|
+
open
|
|
676
|
+
value=""
|
|
677
|
+
currentUser={currentUser}
|
|
678
|
+
conversation={toolCallConversation}
|
|
679
|
+
sizeClassName="h-[500px] w-96"
|
|
680
|
+
disableMobileResize
|
|
681
|
+
hideAdditionalAction
|
|
682
|
+
/>
|
|
683
|
+
</StorySection>
|
|
684
|
+
|
|
685
|
+
<StorySection
|
|
686
|
+
title="Scroll-Up Pagination"
|
|
687
|
+
description="onMessageListScrollTop fires when scrolled near the top. isLoadingMessages shows a spinner at the top while older messages are being fetched. Scroll up to see the effect."
|
|
688
|
+
>
|
|
689
|
+
<ChatBase
|
|
690
|
+
open
|
|
691
|
+
value={msg7}
|
|
692
|
+
currentUser={currentUser}
|
|
693
|
+
conversation={conv7}
|
|
694
|
+
isLoadingMessages={loadingOlder}
|
|
695
|
+
onMessageListScrollTop={handleLoadOlderMessages}
|
|
696
|
+
onSendMessage={(updated) => {
|
|
697
|
+
setConv7(updated);
|
|
698
|
+
setMsg7("");
|
|
699
|
+
}}
|
|
700
|
+
onChangeMessage={(e) => setMsg7(e.target.value)}
|
|
701
|
+
sizeClassName="h-[500px] w-96"
|
|
702
|
+
disableMobileResize
|
|
703
|
+
/>
|
|
704
|
+
</StorySection>
|
|
705
|
+
|
|
706
|
+
<StorySection
|
|
707
|
+
title="Quick Replies (footerElement)"
|
|
708
|
+
description="footerElement renders above the message input. Pass quick-reply chips here so users can tap a preset prompt instead of typing. Clicking a chip fills the input — the user still hits send."
|
|
709
|
+
>
|
|
710
|
+
<ChatBase
|
|
711
|
+
open
|
|
712
|
+
value={msg8}
|
|
713
|
+
currentUser={currentUser}
|
|
714
|
+
conversation={conv8}
|
|
715
|
+
onSendMessage={(updated) => {
|
|
716
|
+
setConv8(updated);
|
|
717
|
+
setMsg8("");
|
|
718
|
+
}}
|
|
719
|
+
onChangeMessage={(e) => setMsg8(e.target.value)}
|
|
720
|
+
footerElement={
|
|
721
|
+
<div className="flex flex-wrap gap-2 px-2 pb-1 pt-1">
|
|
722
|
+
{quickReplies.map((reply) => (
|
|
723
|
+
<button
|
|
724
|
+
key={reply}
|
|
725
|
+
onClick={() => setMsg8(reply)}
|
|
726
|
+
className="text-xs px-3 py-1 rounded-full border border-primary-300 text-primary-600 bg-primary-50 hover:bg-primary-100 transition-colors"
|
|
727
|
+
>
|
|
728
|
+
{reply}
|
|
729
|
+
</button>
|
|
730
|
+
))}
|
|
731
|
+
</div>
|
|
732
|
+
}
|
|
733
|
+
sizeClassName="h-[500px] w-96"
|
|
734
|
+
disableMobileResize
|
|
735
|
+
/>
|
|
736
|
+
</StorySection>
|
|
737
|
+
|
|
738
|
+
<StorySection
|
|
739
|
+
title="File Attach with Chips Footer"
|
|
740
|
+
description="Attach multiple files via the paperclip. Each file appears as a dismissible chip in footerElement — click × to remove individually. onSendMessage handles both text and files together."
|
|
741
|
+
>
|
|
742
|
+
<ChatBase
|
|
743
|
+
open
|
|
744
|
+
value={msg10}
|
|
745
|
+
currentUser={currentUser}
|
|
746
|
+
conversation={conv10}
|
|
747
|
+
fileUpload={{
|
|
748
|
+
allowFileUpload: true,
|
|
749
|
+
hasFiles: files10.length > 0,
|
|
750
|
+
multiple: true,
|
|
751
|
+
acceptFileType: ".jpg,.jpeg,.png,.mp4,.webm,.pdf,.docx",
|
|
752
|
+
onChangeUpload: (e) => {
|
|
753
|
+
if (e?.target?.files?.length > 0)
|
|
754
|
+
setFiles10((prev) => [
|
|
755
|
+
...prev,
|
|
756
|
+
...Array.from(e.target.files as FileList),
|
|
757
|
+
]);
|
|
758
|
+
},
|
|
759
|
+
}}
|
|
760
|
+
onSendMessage={(updated) => {
|
|
761
|
+
const newMessages = files10.map((f) => ({
|
|
762
|
+
sender: currentUser,
|
|
763
|
+
messageBody: {
|
|
764
|
+
fileName: URL.createObjectURL(f),
|
|
765
|
+
token: f.name,
|
|
766
|
+
type: f.type,
|
|
767
|
+
},
|
|
768
|
+
createdAt: dayjs().toDate(),
|
|
769
|
+
}));
|
|
770
|
+
setConv10({
|
|
771
|
+
...updated,
|
|
772
|
+
messageList: [...updated.messageList, ...newMessages],
|
|
773
|
+
});
|
|
774
|
+
setFiles10([]);
|
|
775
|
+
setMsg10("");
|
|
776
|
+
}}
|
|
777
|
+
onChangeMessage={(e) => setMsg10(e.target.value)}
|
|
778
|
+
footerElement={
|
|
779
|
+
files10.length > 0 ? (
|
|
780
|
+
<div className="flex flex-wrap gap-2 px-2 pb-1 pt-1">
|
|
781
|
+
{files10.map((f, i) => (
|
|
782
|
+
<span
|
|
783
|
+
key={i}
|
|
784
|
+
className="inline-flex items-center gap-1.5 rounded-full border border-primary-300 bg-primary-50 py-1 pl-2.5 pr-1.5 text-xs text-primary-700"
|
|
785
|
+
>
|
|
786
|
+
<DocumentIcon className="h-3.5 w-3.5 flex-shrink-0 text-primary-500" />
|
|
787
|
+
<span className="max-w-[180px] truncate">{f.name}</span>
|
|
788
|
+
<button
|
|
789
|
+
onClick={() =>
|
|
790
|
+
setFiles10((prev) => prev.filter((_, idx) => idx !== i))
|
|
791
|
+
}
|
|
792
|
+
className="ml-0.5 flex h-4 w-4 flex-shrink-0 items-center justify-center rounded-full hover:bg-primary-200 transition-colors"
|
|
793
|
+
>
|
|
794
|
+
<XMarkIcon className="h-3 w-3 text-primary-500" />
|
|
795
|
+
</button>
|
|
796
|
+
</span>
|
|
797
|
+
))}
|
|
798
|
+
</div>
|
|
799
|
+
) : undefined
|
|
800
|
+
}
|
|
801
|
+
sizeClassName="h-[500px] w-96"
|
|
802
|
+
disableMobileResize
|
|
803
|
+
/>
|
|
804
|
+
</StorySection>
|
|
805
|
+
|
|
806
|
+
<StorySection
|
|
807
|
+
title="Custom Input Actions (inputActions)"
|
|
808
|
+
description="inputActions renders extra icon buttons in the input row between the paperclip and the send button. Useful for voice input, camera, or any custom LLM action."
|
|
809
|
+
>
|
|
810
|
+
<ChatBase
|
|
811
|
+
open
|
|
812
|
+
value={msg9}
|
|
813
|
+
currentUser={currentUser}
|
|
814
|
+
conversation={conv9}
|
|
815
|
+
onSendMessage={(updated) => {
|
|
816
|
+
setConv9(updated);
|
|
817
|
+
setMsg9("");
|
|
818
|
+
}}
|
|
819
|
+
onChangeMessage={(e) => setMsg9(e.target.value)}
|
|
820
|
+
fileUpload={{
|
|
821
|
+
allowFileUpload: true,
|
|
822
|
+
hasFiles: false,
|
|
823
|
+
onChangeUpload: () => {},
|
|
824
|
+
}}
|
|
825
|
+
inputActions={[
|
|
826
|
+
<IconButton
|
|
827
|
+
key="mic"
|
|
828
|
+
onClick={() => alert("Voice input triggered")}
|
|
829
|
+
className="focus:ring-transparent flex flex-col justify-center"
|
|
830
|
+
icon={<MicrophoneIcon className="w-5 h-5 text-primary-500" />}
|
|
831
|
+
/>,
|
|
832
|
+
<IconButton
|
|
833
|
+
key="camera"
|
|
834
|
+
onClick={() => alert("Camera triggered")}
|
|
835
|
+
className="focus:ring-transparent flex flex-col justify-center"
|
|
836
|
+
icon={<CameraIcon className="w-5 h-5 text-primary-500" />}
|
|
837
|
+
/>,
|
|
838
|
+
]}
|
|
839
|
+
sizeClassName="h-[500px] w-96"
|
|
840
|
+
disableMobileResize
|
|
841
|
+
/>
|
|
842
|
+
</StorySection>
|
|
843
|
+
|
|
844
|
+
<StorySection
|
|
845
|
+
title="Multi-line Input (Email Composer)"
|
|
846
|
+
description="multiLine=true expands the textarea to 5 rows and moves action buttons to a bottom-right row. Enter adds a new line instead of sending — use the send button to submit. Ideal for composing emails."
|
|
847
|
+
>
|
|
848
|
+
<ChatBase
|
|
849
|
+
open
|
|
850
|
+
value={msg11}
|
|
851
|
+
currentUser={currentUser}
|
|
852
|
+
conversation={conv11}
|
|
853
|
+
multiLine={5}
|
|
854
|
+
onSendMessage={(updated) => {
|
|
855
|
+
setConv11(updated);
|
|
856
|
+
setMsg11("");
|
|
857
|
+
}}
|
|
858
|
+
onChangeMessage={(e) => setMsg11(e.target.value)}
|
|
859
|
+
sizeClassName="h-[500px] w-96"
|
|
860
|
+
disableMobileResize
|
|
861
|
+
/>
|
|
862
|
+
</StorySection>
|
|
863
|
+
|
|
864
|
+
<StorySection
|
|
865
|
+
title="Media Rendering (Text + Attachments)"
|
|
866
|
+
description="Messages with both a text messageBody and an attachments[] array — images, PDFs, and audio files rendered inline beneath the message text. Simulates real-world scenarios like sending a caption with photos or a bot reply with supporting files."
|
|
867
|
+
>
|
|
868
|
+
<ChatBase
|
|
869
|
+
open
|
|
870
|
+
value={msg12}
|
|
871
|
+
currentUser={currentUser}
|
|
872
|
+
conversation={conv12}
|
|
873
|
+
onSendMessage={(updated) => {
|
|
874
|
+
setConv12(updated);
|
|
875
|
+
setMsg12("");
|
|
876
|
+
}}
|
|
877
|
+
onChangeMessage={(e) => setMsg12(e.target.value)}
|
|
878
|
+
sizeClassName="h-[500px] w-96"
|
|
879
|
+
disableMobileResize
|
|
880
|
+
/>
|
|
881
|
+
</StorySection>
|
|
282
882
|
</>
|
|
283
883
|
);
|
|
284
|
-
}
|
|
884
|
+
};
|