@ibti-tech/chatbot 0.2.0 → 0.5.7
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/README.md +456 -14
- package/dist/index.d.ts +233 -72
- package/dist/index.mjs +1264 -157
- package/package.json +5 -4
- package/dist/index.js +0 -1132
package/dist/index.mjs
CHANGED
|
@@ -17,10 +17,10 @@ var useChatbot = /* @__PURE__ */ __name(() => {
|
|
|
17
17
|
var useChatbot_default = useChatbot;
|
|
18
18
|
|
|
19
19
|
// src/contexts/Chatbot/provider.tsx
|
|
20
|
-
import React3, { useMemo, useRef, useState as useState3 } from "react";
|
|
20
|
+
import React3, { useEffect as useEffect2, useMemo, useRef as useRef2, useState as useState3 } from "react";
|
|
21
21
|
|
|
22
22
|
// src/contexts/Chatbot/useChatbotMessages.ts
|
|
23
|
-
import { useEffect, useState as useState2 } from "react";
|
|
23
|
+
import { useEffect, useState as useState2, useRef } from "react";
|
|
24
24
|
import { v4 as uuidv4 } from "uuid";
|
|
25
25
|
|
|
26
26
|
// src/contexts/Chatbot/useChatbotSuggestedQuestions.ts
|
|
@@ -66,8 +66,10 @@ var en_default = {
|
|
|
66
66
|
ONLINE: "Now online",
|
|
67
67
|
LOADING: "Loading...",
|
|
68
68
|
WRITING: "Writing answer...",
|
|
69
|
-
UNAVAILABLE: "Unavailable"
|
|
69
|
+
UNAVAILABLE: "Unavailable",
|
|
70
|
+
INACTIVE: "Inactive"
|
|
70
71
|
},
|
|
72
|
+
WRITING_MESSAGE: "Writing",
|
|
71
73
|
ERRORS: {
|
|
72
74
|
UNKNOWN: "Sorry. We couldn't provide a response."
|
|
73
75
|
},
|
|
@@ -87,7 +89,13 @@ var en_default = {
|
|
|
87
89
|
SUBMIT_BUTTON: "Send",
|
|
88
90
|
CLOSE_BUTTON: "Close",
|
|
89
91
|
RATE: "Rate assistant"
|
|
90
|
-
}
|
|
92
|
+
},
|
|
93
|
+
MESSAGE_ACTIONS: {
|
|
94
|
+
COPY: "Copy message",
|
|
95
|
+
SHARE: "Share message",
|
|
96
|
+
RESEND: "Resend message"
|
|
97
|
+
},
|
|
98
|
+
USER_LABEL: "Me"
|
|
91
99
|
};
|
|
92
100
|
|
|
93
101
|
// src/i18n/pt_BR.json
|
|
@@ -97,8 +105,10 @@ var pt_BR_default = {
|
|
|
97
105
|
ONLINE: "Ativo agora",
|
|
98
106
|
LOADING: "Carregando...",
|
|
99
107
|
WRITING: "Escrevendo resposta...",
|
|
100
|
-
UNAVAILABLE: "Indispon\xEDvel"
|
|
108
|
+
UNAVAILABLE: "Indispon\xEDvel",
|
|
109
|
+
INACTIVE: "Inativo"
|
|
101
110
|
},
|
|
111
|
+
WRITING_MESSAGE: "Escrevendo",
|
|
102
112
|
ERRORS: {
|
|
103
113
|
UNKNOWN: "Desculpe. N\xE3o conseguimos fornecer uma resposta."
|
|
104
114
|
},
|
|
@@ -118,7 +128,13 @@ var pt_BR_default = {
|
|
|
118
128
|
SUBMIT_BUTTON: "Enviar",
|
|
119
129
|
CLOSE_BUTTON: "Fechar",
|
|
120
130
|
RATE: "Avaliar assistente"
|
|
121
|
-
}
|
|
131
|
+
},
|
|
132
|
+
MESSAGE_ACTIONS: {
|
|
133
|
+
COPY: "Copiar mensagem",
|
|
134
|
+
SHARE: "Compartilhar mensagem",
|
|
135
|
+
RESEND: "Reenviar mensagem"
|
|
136
|
+
},
|
|
137
|
+
USER_LABEL: "Eu"
|
|
122
138
|
};
|
|
123
139
|
|
|
124
140
|
// src/i18n/index.ts
|
|
@@ -184,10 +200,46 @@ var sendUserChatFeedback = /* @__PURE__ */ __name(async ({
|
|
|
184
200
|
message: description
|
|
185
201
|
})
|
|
186
202
|
}), "sendUserChatFeedback");
|
|
203
|
+
var checkApiHealth = /* @__PURE__ */ __name(async (apiUrl, locale = "en") => {
|
|
204
|
+
const controller = new AbortController();
|
|
205
|
+
const timeoutId = setTimeout(() => controller.abort(), 5e3);
|
|
206
|
+
try {
|
|
207
|
+
const req = await fetch(`${apiUrl}/chat/welcome?locale=${locale}`, {
|
|
208
|
+
method: "HEAD",
|
|
209
|
+
// Use HEAD to minimize data transfer
|
|
210
|
+
signal: controller.signal
|
|
211
|
+
});
|
|
212
|
+
clearTimeout(timeoutId);
|
|
213
|
+
return req.ok;
|
|
214
|
+
} catch (err) {
|
|
215
|
+
clearTimeout(timeoutId);
|
|
216
|
+
const fallbackController = new AbortController();
|
|
217
|
+
const fallbackTimeoutId = setTimeout(
|
|
218
|
+
() => fallbackController.abort(),
|
|
219
|
+
5e3
|
|
220
|
+
);
|
|
221
|
+
try {
|
|
222
|
+
const req = await fetch(`${apiUrl}/chat/welcome?locale=${locale}`, {
|
|
223
|
+
method: "GET",
|
|
224
|
+
signal: fallbackController.signal
|
|
225
|
+
});
|
|
226
|
+
clearTimeout(fallbackTimeoutId);
|
|
227
|
+
return req.ok;
|
|
228
|
+
} catch {
|
|
229
|
+
clearTimeout(fallbackTimeoutId);
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}, "checkApiHealth");
|
|
187
234
|
var getWelcomeMessage = /* @__PURE__ */ __name(async (apiUrl, locale = "en") => {
|
|
188
235
|
const req = await fetch(`${apiUrl}/chat/welcome?locale=${locale}`, {
|
|
189
236
|
method: "GET"
|
|
190
237
|
});
|
|
238
|
+
if (!req.ok) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
i18n[locale].ERRORS.UNKNOWN + ` (status: ${req.status})`
|
|
241
|
+
);
|
|
242
|
+
}
|
|
191
243
|
const data = await req.json();
|
|
192
244
|
return data.welcomeMessage;
|
|
193
245
|
}, "getWelcomeMessage");
|
|
@@ -196,11 +248,19 @@ var getWelcomeMessage = /* @__PURE__ */ __name(async (apiUrl, locale = "en") =>
|
|
|
196
248
|
import { parseCookies, setCookie } from "nookies";
|
|
197
249
|
var ChatCookieManager = class {
|
|
198
250
|
constructor() {
|
|
251
|
+
this.storageKey = "ibtiChatbot@chat";
|
|
199
252
|
this.cookieKey = "ibtiChatbot@chat";
|
|
253
|
+
// Keep for migration purposes
|
|
254
|
+
this.maxAgeInHours = 24;
|
|
200
255
|
}
|
|
201
256
|
static {
|
|
202
257
|
__name(this, "ChatCookieManager");
|
|
203
258
|
}
|
|
259
|
+
/**
|
|
260
|
+
* Validates that the data can be safely serialized to JSON
|
|
261
|
+
* @param data - Data to validate
|
|
262
|
+
* @throws Error if data cannot be serialized
|
|
263
|
+
*/
|
|
204
264
|
checkValidJSONData(data) {
|
|
205
265
|
try {
|
|
206
266
|
JSON.parse(JSON.stringify(data));
|
|
@@ -208,27 +268,144 @@ var ChatCookieManager = class {
|
|
|
208
268
|
throw new Error("Invalid chat context data.");
|
|
209
269
|
}
|
|
210
270
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
271
|
+
/**
|
|
272
|
+
* Checks if the stored data has expired based on creation timestamp
|
|
273
|
+
* @param createdAt - ISO timestamp string when data was created
|
|
274
|
+
* @returns true if data is older than maxAgeInHours
|
|
275
|
+
*/
|
|
276
|
+
isDataExpired(createdAt) {
|
|
277
|
+
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
278
|
+
const created = new Date(createdAt).getTime();
|
|
279
|
+
const maxAgeInMs = this.maxAgeInHours * 60 * 60 * 1e3;
|
|
280
|
+
return now - created > maxAgeInMs;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Migrates data from cookies to localStorage if cookies exist and localStorage doesn't
|
|
284
|
+
* @returns true if migration was performed
|
|
285
|
+
*/
|
|
286
|
+
migrateFromCookies() {
|
|
287
|
+
if (typeof window === "undefined") return false;
|
|
288
|
+
if (localStorage.getItem(this.storageKey)) {
|
|
289
|
+
return false;
|
|
216
290
|
}
|
|
217
291
|
try {
|
|
218
|
-
const
|
|
219
|
-
|
|
292
|
+
const cookies = document.cookie.split(";");
|
|
293
|
+
const cookie = cookies.find((c) => {
|
|
294
|
+
const trimmed = c.trim();
|
|
295
|
+
return trimmed.startsWith(`${this.cookieKey}=`);
|
|
296
|
+
});
|
|
297
|
+
if (cookie) {
|
|
298
|
+
const equalIndex = cookie.indexOf("=");
|
|
299
|
+
if (equalIndex !== -1) {
|
|
300
|
+
const cookieValue = decodeURIComponent(cookie.substring(equalIndex + 1).trim());
|
|
301
|
+
const data = JSON.parse(cookieValue);
|
|
302
|
+
if (Array.isArray(data)) {
|
|
303
|
+
const storageData = {
|
|
304
|
+
messages: data,
|
|
305
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
306
|
+
};
|
|
307
|
+
localStorage.setItem(this.storageKey, JSON.stringify(storageData));
|
|
308
|
+
} else if (data.messages) {
|
|
309
|
+
localStorage.setItem(this.storageKey, JSON.stringify(data));
|
|
310
|
+
}
|
|
311
|
+
document.cookie = `${this.cookieKey}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
|
|
312
|
+
return true;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
220
315
|
} catch (err) {
|
|
221
|
-
|
|
222
|
-
return [];
|
|
316
|
+
console.warn("Failed to migrate from cookies to localStorage:", err);
|
|
223
317
|
}
|
|
318
|
+
return false;
|
|
224
319
|
}
|
|
320
|
+
/**
|
|
321
|
+
* Retrieves chat messages from localStorage (client-side) or cookies (server-side).
|
|
322
|
+
* Automatically migrates from cookies to localStorage and cleans expired data.
|
|
323
|
+
* @returns Array of chat messages, empty array if none found or expired
|
|
324
|
+
*/
|
|
325
|
+
getData() {
|
|
326
|
+
if (typeof window !== "undefined") {
|
|
327
|
+
this.migrateFromCookies();
|
|
328
|
+
const storedValue = localStorage.getItem(this.storageKey);
|
|
329
|
+
if (!storedValue) {
|
|
330
|
+
return [];
|
|
331
|
+
}
|
|
332
|
+
try {
|
|
333
|
+
const data = JSON.parse(storedValue);
|
|
334
|
+
if (Array.isArray(data)) {
|
|
335
|
+
const storageData = {
|
|
336
|
+
messages: data,
|
|
337
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
338
|
+
};
|
|
339
|
+
localStorage.setItem(this.storageKey, JSON.stringify(storageData));
|
|
340
|
+
return data;
|
|
341
|
+
}
|
|
342
|
+
if (data.createdAt && this.isDataExpired(data.createdAt)) {
|
|
343
|
+
this.saveData([]);
|
|
344
|
+
return [];
|
|
345
|
+
}
|
|
346
|
+
return data.messages || [];
|
|
347
|
+
} catch (err) {
|
|
348
|
+
console.warn("Failed to parse chat storage data:", err);
|
|
349
|
+
this.saveData([]);
|
|
350
|
+
return [];
|
|
351
|
+
}
|
|
352
|
+
} else {
|
|
353
|
+
const cookies = parseCookies();
|
|
354
|
+
const cookieValue = cookies[this.cookieKey];
|
|
355
|
+
if (!cookieValue) {
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
358
|
+
try {
|
|
359
|
+
const data = JSON.parse(cookieValue);
|
|
360
|
+
if (Array.isArray(data)) {
|
|
361
|
+
return data;
|
|
362
|
+
}
|
|
363
|
+
if (data.createdAt && this.isDataExpired(data.createdAt)) {
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
return data.messages || [];
|
|
367
|
+
} catch (err) {
|
|
368
|
+
console.warn("Failed to parse chat cookie:", err);
|
|
369
|
+
return [];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Saves chat messages to localStorage (client-side) or cookies (server-side).
|
|
375
|
+
* Data expires after 24 hours (checked on read, not enforced by storage).
|
|
376
|
+
* @param data - Array of chat messages to persist
|
|
377
|
+
*/
|
|
225
378
|
saveData(data) {
|
|
226
379
|
try {
|
|
227
380
|
this.checkValidJSONData(data);
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
381
|
+
const storageData = {
|
|
382
|
+
messages: data,
|
|
383
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
384
|
+
};
|
|
385
|
+
const storageValue = JSON.stringify(storageData);
|
|
386
|
+
if (typeof window !== "undefined") {
|
|
387
|
+
try {
|
|
388
|
+
localStorage.setItem(this.storageKey, storageValue);
|
|
389
|
+
const verifyData = localStorage.getItem(this.storageKey);
|
|
390
|
+
if (!verifyData) {
|
|
391
|
+
throw new Error("Failed to verify localStorage save");
|
|
392
|
+
}
|
|
393
|
+
document.cookie = `${this.cookieKey}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;`;
|
|
394
|
+
} catch (err) {
|
|
395
|
+
console.error("Failed to save to localStorage:", err);
|
|
396
|
+
if (err instanceof DOMException && err.code === 22) {
|
|
397
|
+
console.warn("localStorage quota exceeded. Consider clearing old data.");
|
|
398
|
+
}
|
|
399
|
+
throw new Error("Failed to save chat context data to localStorage");
|
|
400
|
+
}
|
|
401
|
+
} else {
|
|
402
|
+
setCookie(null, this.cookieKey, storageValue, {
|
|
403
|
+
expiresIn: 60 * 60 * 24
|
|
404
|
+
// 24 hours in seconds
|
|
405
|
+
});
|
|
406
|
+
}
|
|
231
407
|
} catch (err) {
|
|
408
|
+
console.error("Failed to save chat data:", err);
|
|
232
409
|
throw new Error("Fail to save chat context data");
|
|
233
410
|
}
|
|
234
411
|
}
|
|
@@ -254,6 +431,10 @@ var useChatbotMessages = /* @__PURE__ */ __name(({
|
|
|
254
431
|
const [loading, setLoading] = useState2(false);
|
|
255
432
|
const [writing, setWriting] = useState2(false);
|
|
256
433
|
const [error, setError] = useState2();
|
|
434
|
+
const [apiConnectionError, setApiConnectionError] = useState2(false);
|
|
435
|
+
const prevWritingRef = useRef(false);
|
|
436
|
+
const chatMessagesRef = useRef([]);
|
|
437
|
+
const saveTimeoutRef = useRef(null);
|
|
257
438
|
const suggestedQuestions = useChatbotSuggestedQuestions({
|
|
258
439
|
chatContext: chatMessages.map((item) => ({
|
|
259
440
|
role: item.role,
|
|
@@ -262,6 +443,30 @@ var useChatbotMessages = /* @__PURE__ */ __name(({
|
|
|
262
443
|
apiURL,
|
|
263
444
|
locale
|
|
264
445
|
});
|
|
446
|
+
const persistMessages = /* @__PURE__ */ __name((messages, immediate = false) => {
|
|
447
|
+
if (!initialized) return;
|
|
448
|
+
chatMessagesRef.current = messages;
|
|
449
|
+
if (saveTimeoutRef.current) {
|
|
450
|
+
clearTimeout(saveTimeoutRef.current);
|
|
451
|
+
saveTimeoutRef.current = null;
|
|
452
|
+
}
|
|
453
|
+
if (immediate) {
|
|
454
|
+
try {
|
|
455
|
+
chatCookie.saveData(messages);
|
|
456
|
+
} catch (err) {
|
|
457
|
+
console.error("Failed to persist messages:", err);
|
|
458
|
+
}
|
|
459
|
+
} else {
|
|
460
|
+
saveTimeoutRef.current = setTimeout(() => {
|
|
461
|
+
try {
|
|
462
|
+
chatCookie.saveData(chatMessagesRef.current);
|
|
463
|
+
} catch (err) {
|
|
464
|
+
console.error("Failed to persist messages (debounced):", err);
|
|
465
|
+
}
|
|
466
|
+
saveTimeoutRef.current = null;
|
|
467
|
+
}, 500);
|
|
468
|
+
}
|
|
469
|
+
}, "persistMessages");
|
|
265
470
|
const createQuestionMessageIntoHistory = /* @__PURE__ */ __name((question, id) => {
|
|
266
471
|
const timestamp = (/* @__PURE__ */ new Date()).toUTCString();
|
|
267
472
|
const messageData = {
|
|
@@ -275,9 +480,10 @@ var useChatbotMessages = /* @__PURE__ */ __name(({
|
|
|
275
480
|
messageData
|
|
276
481
|
];
|
|
277
482
|
setChatMessages(newHistory);
|
|
483
|
+
persistMessages(newHistory, true);
|
|
278
484
|
return messageData;
|
|
279
485
|
}, "createQuestionMessageIntoHistory");
|
|
280
|
-
const createOrUpdateAnswerMessageIntoHistory = /* @__PURE__ */ __name((answer, id, error2 = false) => {
|
|
486
|
+
const createOrUpdateAnswerMessageIntoHistory = /* @__PURE__ */ __name((answer, id, error2 = false, shouldPersist = false) => {
|
|
281
487
|
const timestamp = (/* @__PURE__ */ new Date()).toUTCString();
|
|
282
488
|
const messageData = {
|
|
283
489
|
id,
|
|
@@ -289,7 +495,7 @@ var useChatbotMessages = /* @__PURE__ */ __name(({
|
|
|
289
495
|
setChatMessages((prev) => {
|
|
290
496
|
const itemAlreadyExists = prev.some((item) => item.id == id);
|
|
291
497
|
if (itemAlreadyExists) {
|
|
292
|
-
|
|
498
|
+
const updated = prev.map((item) => {
|
|
293
499
|
if (item.id == id)
|
|
294
500
|
return {
|
|
295
501
|
...item,
|
|
@@ -297,8 +503,12 @@ var useChatbotMessages = /* @__PURE__ */ __name(({
|
|
|
297
503
|
};
|
|
298
504
|
return item;
|
|
299
505
|
});
|
|
506
|
+
persistMessages(updated, shouldPersist);
|
|
507
|
+
return updated;
|
|
300
508
|
}
|
|
301
|
-
|
|
509
|
+
const newHistory = [...prev, messageData];
|
|
510
|
+
persistMessages(newHistory, shouldPersist);
|
|
511
|
+
return newHistory;
|
|
302
512
|
});
|
|
303
513
|
return messageData;
|
|
304
514
|
}, "createOrUpdateAnswerMessageIntoHistory");
|
|
@@ -325,45 +535,107 @@ var useChatbotMessages = /* @__PURE__ */ __name(({
|
|
|
325
535
|
onReceiving(receivedMessage) {
|
|
326
536
|
setLoading(false);
|
|
327
537
|
setWriting(true);
|
|
328
|
-
createOrUpdateAnswerMessageIntoHistory(receivedMessage, answerId);
|
|
538
|
+
createOrUpdateAnswerMessageIntoHistory(receivedMessage, answerId, false, false);
|
|
329
539
|
},
|
|
330
540
|
onDone: /* @__PURE__ */ __name(() => {
|
|
331
541
|
setWriting(false);
|
|
542
|
+
setTimeout(() => {
|
|
543
|
+
setChatMessages((currentMessages) => {
|
|
544
|
+
if (initialized && currentMessages.length > 0) {
|
|
545
|
+
if (saveTimeoutRef.current) {
|
|
546
|
+
clearTimeout(saveTimeoutRef.current);
|
|
547
|
+
saveTimeoutRef.current = null;
|
|
548
|
+
}
|
|
549
|
+
chatCookie.saveData(currentMessages);
|
|
550
|
+
chatMessagesRef.current = currentMessages;
|
|
551
|
+
}
|
|
552
|
+
return currentMessages;
|
|
553
|
+
});
|
|
554
|
+
}, 100);
|
|
332
555
|
suggestedQuestions.fetchData();
|
|
333
556
|
}, "onDone")
|
|
334
557
|
});
|
|
335
558
|
} catch (err) {
|
|
336
559
|
if (err instanceof Error) {
|
|
337
|
-
createOrUpdateAnswerMessageIntoHistory(err.message, answerId, true);
|
|
560
|
+
createOrUpdateAnswerMessageIntoHistory(err.message, answerId, true, true);
|
|
338
561
|
}
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
{
|
|
343
|
-
id: uuidv4(),
|
|
344
|
-
timestamp: (/* @__PURE__ */ new Date()).toUTCString(),
|
|
345
|
-
role: chatContext.role,
|
|
346
|
-
content: chatContext.content
|
|
562
|
+
const isConnectionError = err instanceof TypeError || err instanceof Error && (err.message.toLowerCase().includes("fetch") || err.message.toLowerCase().includes("network") || err.message.toLowerCase().includes("failed to fetch"));
|
|
563
|
+
if (isConnectionError) {
|
|
564
|
+
setApiConnectionError(true);
|
|
347
565
|
}
|
|
348
|
-
|
|
566
|
+
setError(err);
|
|
567
|
+
setLoading(false);
|
|
568
|
+
setWriting(false);
|
|
569
|
+
}
|
|
349
570
|
dispatchAssitantAnswer();
|
|
350
571
|
}, "makeQuestion");
|
|
572
|
+
useEffect(() => {
|
|
573
|
+
if (!initialized) return;
|
|
574
|
+
if (prevWritingRef.current && !writing && !loading && chatMessages.length > 0) {
|
|
575
|
+
if (saveTimeoutRef.current) {
|
|
576
|
+
clearTimeout(saveTimeoutRef.current);
|
|
577
|
+
saveTimeoutRef.current = null;
|
|
578
|
+
}
|
|
579
|
+
try {
|
|
580
|
+
chatCookie.saveData(chatMessages);
|
|
581
|
+
chatMessagesRef.current = chatMessages;
|
|
582
|
+
} catch (err) {
|
|
583
|
+
console.error("Failed to persist messages on writing complete:", err);
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
prevWritingRef.current = writing;
|
|
587
|
+
}, [writing, loading, chatMessages, initialized]);
|
|
588
|
+
useEffect(() => {
|
|
589
|
+
chatMessagesRef.current = chatMessages;
|
|
590
|
+
}, [chatMessages]);
|
|
591
|
+
useEffect(() => {
|
|
592
|
+
return () => {
|
|
593
|
+
if (saveTimeoutRef.current) {
|
|
594
|
+
clearTimeout(saveTimeoutRef.current);
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
}, []);
|
|
351
598
|
const init = /* @__PURE__ */ __name(async () => {
|
|
599
|
+
try {
|
|
600
|
+
const isApiAvailable = await checkApiHealth(apiURL, locale);
|
|
601
|
+
if (!isApiAvailable) {
|
|
602
|
+
setApiConnectionError(true);
|
|
603
|
+
setInitialized(true);
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
setApiConnectionError(false);
|
|
607
|
+
} catch (err) {
|
|
608
|
+
setApiConnectionError(true);
|
|
609
|
+
setError(err);
|
|
610
|
+
setInitialized(true);
|
|
611
|
+
return;
|
|
612
|
+
}
|
|
352
613
|
const savedData = chatCookie.getData();
|
|
353
614
|
if (savedData && savedData.length > 0) {
|
|
354
615
|
setChatMessages(savedData);
|
|
616
|
+
setInitialized(true);
|
|
355
617
|
} else {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
618
|
+
try {
|
|
619
|
+
const firstMessage = await getWelcomeMessage(apiURL, locale);
|
|
620
|
+
setChatMessages([
|
|
621
|
+
{
|
|
622
|
+
id: uuidv4(),
|
|
623
|
+
timestamp: (/* @__PURE__ */ new Date()).toUTCString(),
|
|
624
|
+
role: "assistant",
|
|
625
|
+
content: firstMessage
|
|
626
|
+
}
|
|
627
|
+
]);
|
|
628
|
+
setApiConnectionError(false);
|
|
629
|
+
} catch (err) {
|
|
630
|
+
const isConnectionError = err instanceof TypeError || err instanceof Error && (err.message.toLowerCase().includes("fetch") || err.message.toLowerCase().includes("network") || err.message.toLowerCase().includes("failed to fetch"));
|
|
631
|
+
if (isConnectionError) {
|
|
632
|
+
setApiConnectionError(true);
|
|
363
633
|
}
|
|
364
|
-
|
|
634
|
+
setError(err);
|
|
635
|
+
} finally {
|
|
636
|
+
setInitialized(true);
|
|
637
|
+
}
|
|
365
638
|
}
|
|
366
|
-
setInitialized(true);
|
|
367
639
|
}, "init");
|
|
368
640
|
useEffect(() => {
|
|
369
641
|
if (initialized) return;
|
|
@@ -375,6 +647,7 @@ var useChatbotMessages = /* @__PURE__ */ __name(({
|
|
|
375
647
|
loading,
|
|
376
648
|
writing,
|
|
377
649
|
error,
|
|
650
|
+
apiConnectionError,
|
|
378
651
|
suggestedQuestions
|
|
379
652
|
};
|
|
380
653
|
}, "useChatbotMessages");
|
|
@@ -393,7 +666,9 @@ var ChatbotProvider = /* @__PURE__ */ __name(({
|
|
|
393
666
|
locale,
|
|
394
667
|
children,
|
|
395
668
|
apiURL,
|
|
396
|
-
theme
|
|
669
|
+
theme,
|
|
670
|
+
isOpen = false,
|
|
671
|
+
texts
|
|
397
672
|
}) => {
|
|
398
673
|
const {
|
|
399
674
|
makeQuestion,
|
|
@@ -401,22 +676,26 @@ var ChatbotProvider = /* @__PURE__ */ __name(({
|
|
|
401
676
|
loading,
|
|
402
677
|
writing,
|
|
403
678
|
error,
|
|
679
|
+
apiConnectionError,
|
|
404
680
|
suggestedQuestions
|
|
405
681
|
} = useChatbotMessages_default({
|
|
406
682
|
apiURL,
|
|
407
683
|
locale
|
|
408
684
|
});
|
|
409
|
-
const [opened, setOpened] = useState3(
|
|
410
|
-
const scrollRef =
|
|
685
|
+
const [opened, setOpened] = useState3(isOpen);
|
|
686
|
+
const scrollRef = useRef2(null);
|
|
687
|
+
useEffect2(() => {
|
|
688
|
+
setOpened(isOpen);
|
|
689
|
+
}, [isOpen]);
|
|
411
690
|
const openedToggle = /* @__PURE__ */ __name(() => {
|
|
412
691
|
setOpened((state) => !state);
|
|
413
692
|
}, "openedToggle");
|
|
414
693
|
const status = useMemo(() => {
|
|
415
694
|
if (writing) return "writing";
|
|
416
|
-
if (error) return "unavailable";
|
|
695
|
+
if (apiConnectionError || error) return "unavailable";
|
|
417
696
|
if (loading) return "loading";
|
|
418
697
|
return "online";
|
|
419
|
-
}, [writing, loading, error]);
|
|
698
|
+
}, [writing, loading, error, apiConnectionError]);
|
|
420
699
|
return /* @__PURE__ */ React3.createElement(
|
|
421
700
|
ChatbotContext.Provider,
|
|
422
701
|
{
|
|
@@ -430,8 +709,10 @@ var ChatbotProvider = /* @__PURE__ */ __name(({
|
|
|
430
709
|
opened,
|
|
431
710
|
openedToggle,
|
|
432
711
|
status,
|
|
712
|
+
apiConnectionError,
|
|
433
713
|
suggestedQuestions,
|
|
434
|
-
apiURL
|
|
714
|
+
apiURL,
|
|
715
|
+
texts
|
|
435
716
|
}
|
|
436
717
|
},
|
|
437
718
|
/* @__PURE__ */ React3.createElement(ThemeProvider, { theme: themes[theme] }, children)
|
|
@@ -439,7 +720,7 @@ var ChatbotProvider = /* @__PURE__ */ __name(({
|
|
|
439
720
|
}, "ChatbotProvider");
|
|
440
721
|
|
|
441
722
|
// src/components/ChatbotDevice/index.tsx
|
|
442
|
-
import
|
|
723
|
+
import React14 from "react";
|
|
443
724
|
|
|
444
725
|
// src/components/ChatbotDevice/styles.ts
|
|
445
726
|
import { breakpoints, screens } from "@ibti-tech/ui";
|
|
@@ -451,8 +732,6 @@ var Wrapper = styled.div`
|
|
|
451
732
|
display: flex;
|
|
452
733
|
flex-direction: column;
|
|
453
734
|
transition: ${(props) => props.theme.transitionDurations.fast};
|
|
454
|
-
border-end-end-radius: ${(props) => props.theme.borderRadius.medium};
|
|
455
|
-
border-end-start-radius: ${(props) => props.theme.borderRadius.medium};
|
|
456
735
|
overflow: hidden;
|
|
457
736
|
pointer-events: all;
|
|
458
737
|
height: 100vh;
|
|
@@ -460,14 +739,45 @@ var Wrapper = styled.div`
|
|
|
460
739
|
box-sizing: border-box;
|
|
461
740
|
position: relative;
|
|
462
741
|
|
|
742
|
+
@media screen and (max-width: ${breakpoints.tablet}px) {
|
|
743
|
+
${(props) => props.$opened && props.$verticalPosition === "bottom" ? css`
|
|
744
|
+
max-height: 100vh;
|
|
745
|
+
` : ""}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
${(props) => props.$verticalPosition === "top" ? css`
|
|
749
|
+
border-end-end-radius: ${(props2) => props2.theme.borderRadius.medium};
|
|
750
|
+
border-end-start-radius: ${(props2) => props2.theme.borderRadius.medium};
|
|
751
|
+
` : css`
|
|
752
|
+
border-start-end-radius: ${(props2) => props2.theme.borderRadius.medium};
|
|
753
|
+
border-start-start-radius: ${(props2) => props2.theme.borderRadius.medium};
|
|
754
|
+
`}
|
|
755
|
+
|
|
463
756
|
${screens.tablet} {
|
|
464
757
|
height: 500px;
|
|
465
758
|
max-width: ${breakpoints.mobileL}px;
|
|
466
759
|
}
|
|
467
760
|
|
|
468
|
-
${(props) => !props.$opened && css`
|
|
469
|
-
|
|
470
|
-
|
|
761
|
+
${(props) => !props.$opened && (props.$verticalPosition === "top" ? css`
|
|
762
|
+
transform: translateY(calc(-100% + 32px));
|
|
763
|
+
` : css`
|
|
764
|
+
transform: translateY(calc(100% - 32px));
|
|
765
|
+
width: 100%;
|
|
766
|
+
${screens.tablet} {
|
|
767
|
+
width: ${breakpoints.mobileL}px;
|
|
768
|
+
max-width: ${breakpoints.mobileL}px;
|
|
769
|
+
min-width: ${breakpoints.mobileL}px;
|
|
770
|
+
}
|
|
771
|
+
> *:not(:last-child) {
|
|
772
|
+
display: none;
|
|
773
|
+
}
|
|
774
|
+
> *:last-child {
|
|
775
|
+
flex-shrink: 0;
|
|
776
|
+
min-height: 32px;
|
|
777
|
+
height: 32px;
|
|
778
|
+
width: 100%;
|
|
779
|
+
}
|
|
780
|
+
`)}
|
|
471
781
|
`;
|
|
472
782
|
|
|
473
783
|
// src/components/ChatbotHeader/index.tsx
|
|
@@ -518,6 +828,120 @@ var BotIcon = /* @__PURE__ */ __name(() => {
|
|
|
518
828
|
));
|
|
519
829
|
}, "BotIcon");
|
|
520
830
|
|
|
831
|
+
// src/hooks/useChatbotTexts.ts
|
|
832
|
+
var useChatbotTexts = /* @__PURE__ */ __name(() => {
|
|
833
|
+
const { locale, texts } = useChatbot();
|
|
834
|
+
const defaultTexts = i18n[locale];
|
|
835
|
+
if (!texts || !texts[locale]) {
|
|
836
|
+
return defaultTexts;
|
|
837
|
+
}
|
|
838
|
+
const customTexts = texts[locale];
|
|
839
|
+
const getText = /* @__PURE__ */ __name((custom, defaultValue = "") => custom && custom.trim() !== "" ? custom : defaultValue, "getText");
|
|
840
|
+
return {
|
|
841
|
+
CHATBOT_NAME: getText(
|
|
842
|
+
customTexts.CHATBOT_NAME,
|
|
843
|
+
defaultTexts.CHATBOT_NAME
|
|
844
|
+
),
|
|
845
|
+
INPUT_PLACEHOLDER: getText(
|
|
846
|
+
customTexts.INPUT_PLACEHOLDER,
|
|
847
|
+
defaultTexts.INPUT_PLACEHOLDER
|
|
848
|
+
),
|
|
849
|
+
CHATBOT_BAR: {
|
|
850
|
+
OPEN: getText(
|
|
851
|
+
customTexts.CHATBOT_BAR?.OPEN,
|
|
852
|
+
defaultTexts.CHATBOT_BAR.OPEN
|
|
853
|
+
),
|
|
854
|
+
CLOSE: getText(
|
|
855
|
+
customTexts.CHATBOT_BAR?.CLOSE,
|
|
856
|
+
defaultTexts.CHATBOT_BAR.CLOSE
|
|
857
|
+
)
|
|
858
|
+
},
|
|
859
|
+
CHAT_FEEDBACK: {
|
|
860
|
+
TITLE: getText(
|
|
861
|
+
customTexts.CHAT_FEEDBACK?.TITLE,
|
|
862
|
+
defaultTexts.CHAT_FEEDBACK.TITLE
|
|
863
|
+
),
|
|
864
|
+
DESCRIPTION: getText(
|
|
865
|
+
customTexts.CHAT_FEEDBACK?.DESCRIPTION,
|
|
866
|
+
defaultTexts.CHAT_FEEDBACK.DESCRIPTION
|
|
867
|
+
),
|
|
868
|
+
MESSAGE_FIELD: getText(
|
|
869
|
+
customTexts.CHAT_FEEDBACK?.MESSAGE_FIELD,
|
|
870
|
+
defaultTexts.CHAT_FEEDBACK.MESSAGE_FIELD
|
|
871
|
+
),
|
|
872
|
+
SUBMIT_BUTTON: getText(
|
|
873
|
+
customTexts.CHAT_FEEDBACK?.SUBMIT_BUTTON,
|
|
874
|
+
defaultTexts.CHAT_FEEDBACK.SUBMIT_BUTTON
|
|
875
|
+
),
|
|
876
|
+
CLOSE_BUTTON: getText(
|
|
877
|
+
customTexts.CHAT_FEEDBACK?.CLOSE_BUTTON,
|
|
878
|
+
defaultTexts.CHAT_FEEDBACK.CLOSE_BUTTON
|
|
879
|
+
),
|
|
880
|
+
RATE: getText(
|
|
881
|
+
customTexts.CHAT_FEEDBACK?.RATE,
|
|
882
|
+
defaultTexts.CHAT_FEEDBACK.RATE
|
|
883
|
+
)
|
|
884
|
+
},
|
|
885
|
+
SUGGESTED_QUESTIONS: {
|
|
886
|
+
TITLE: getText(
|
|
887
|
+
customTexts.SUGGESTED_QUESTIONS?.TITLE,
|
|
888
|
+
defaultTexts.SUGGESTED_QUESTIONS.TITLE
|
|
889
|
+
),
|
|
890
|
+
LOADING: getText(
|
|
891
|
+
customTexts.SUGGESTED_QUESTIONS?.LOADING,
|
|
892
|
+
defaultTexts.SUGGESTED_QUESTIONS.LOADING
|
|
893
|
+
)
|
|
894
|
+
},
|
|
895
|
+
STATUS: {
|
|
896
|
+
ONLINE: getText(customTexts.STATUS?.ONLINE, defaultTexts.STATUS.ONLINE),
|
|
897
|
+
LOADING: getText(
|
|
898
|
+
customTexts.STATUS?.LOADING,
|
|
899
|
+
defaultTexts.STATUS.LOADING
|
|
900
|
+
),
|
|
901
|
+
WRITING: getText(
|
|
902
|
+
customTexts.STATUS?.WRITING,
|
|
903
|
+
defaultTexts.STATUS.WRITING
|
|
904
|
+
),
|
|
905
|
+
UNAVAILABLE: getText(
|
|
906
|
+
customTexts.STATUS?.UNAVAILABLE,
|
|
907
|
+
defaultTexts.STATUS.UNAVAILABLE
|
|
908
|
+
),
|
|
909
|
+
INACTIVE: getText(
|
|
910
|
+
customTexts.STATUS?.INACTIVE,
|
|
911
|
+
defaultTexts.STATUS.INACTIVE
|
|
912
|
+
)
|
|
913
|
+
},
|
|
914
|
+
ERRORS: {
|
|
915
|
+
UNKNOWN: getText(
|
|
916
|
+
customTexts.ERRORS?.UNKNOWN,
|
|
917
|
+
defaultTexts.ERRORS.UNKNOWN
|
|
918
|
+
)
|
|
919
|
+
},
|
|
920
|
+
MESSAGE_ACTIONS: {
|
|
921
|
+
COPY: getText(
|
|
922
|
+
customTexts.MESSAGE_ACTIONS?.COPY,
|
|
923
|
+
defaultTexts.MESSAGE_ACTIONS.COPY
|
|
924
|
+
),
|
|
925
|
+
SHARE: getText(
|
|
926
|
+
customTexts.MESSAGE_ACTIONS?.SHARE,
|
|
927
|
+
defaultTexts.MESSAGE_ACTIONS.SHARE
|
|
928
|
+
),
|
|
929
|
+
RESEND: getText(
|
|
930
|
+
customTexts.MESSAGE_ACTIONS?.RESEND,
|
|
931
|
+
defaultTexts.MESSAGE_ACTIONS.RESEND
|
|
932
|
+
)
|
|
933
|
+
},
|
|
934
|
+
USER_LABEL: getText(
|
|
935
|
+
customTexts.USER_LABEL,
|
|
936
|
+
defaultTexts.USER_LABEL
|
|
937
|
+
),
|
|
938
|
+
WRITING_MESSAGE: getText(
|
|
939
|
+
customTexts.WRITING_MESSAGE,
|
|
940
|
+
defaultTexts.WRITING_MESSAGE
|
|
941
|
+
)
|
|
942
|
+
};
|
|
943
|
+
}, "useChatbotTexts");
|
|
944
|
+
|
|
521
945
|
// src/components/ChatbotStatusLabel/index.tsx
|
|
522
946
|
import React5 from "react";
|
|
523
947
|
|
|
@@ -541,14 +965,14 @@ var Wrapper3 = styled3.span`
|
|
|
541
965
|
// src/components/ChatbotStatusLabel/index.tsx
|
|
542
966
|
import { useTheme } from "styled-components";
|
|
543
967
|
var ChatbotStatusLabel = /* @__PURE__ */ __name(({}) => {
|
|
544
|
-
const { status } = useChatbot_default();
|
|
545
|
-
const
|
|
968
|
+
const { status, apiConnectionError } = useChatbot_default();
|
|
969
|
+
const texts = useChatbotTexts();
|
|
546
970
|
const theme = useTheme();
|
|
547
971
|
const statusLabel = {
|
|
548
|
-
online:
|
|
549
|
-
loading:
|
|
550
|
-
writing:
|
|
551
|
-
unavailable:
|
|
972
|
+
online: texts.STATUS.ONLINE,
|
|
973
|
+
loading: texts.STATUS.LOADING,
|
|
974
|
+
writing: texts.STATUS.WRITING,
|
|
975
|
+
unavailable: apiConnectionError ? texts.STATUS.INACTIVE : texts.STATUS.UNAVAILABLE
|
|
552
976
|
};
|
|
553
977
|
const statusColor = {
|
|
554
978
|
online: theme.colors.palette.success.normal,
|
|
@@ -563,11 +987,11 @@ var ChatbotStatusLabel_default = ChatbotStatusLabel;
|
|
|
563
987
|
// src/components/ChatbotHeader/index.tsx
|
|
564
988
|
import { Button } from "@ibti-tech/ui";
|
|
565
989
|
var ChatbotHeader = /* @__PURE__ */ __name(({ chatFeedbackBox }) => {
|
|
566
|
-
const
|
|
567
|
-
return /* @__PURE__ */ React6.createElement(Wrapper2, null, /* @__PURE__ */ React6.createElement(ProfileImage, null, /* @__PURE__ */ React6.createElement(BotIcon, null)), /* @__PURE__ */ React6.createElement(ProfileInfo, null, /* @__PURE__ */ React6.createElement(Name, null,
|
|
990
|
+
const texts = useChatbotTexts();
|
|
991
|
+
return /* @__PURE__ */ React6.createElement(Wrapper2, null, /* @__PURE__ */ React6.createElement(ProfileImage, null, /* @__PURE__ */ React6.createElement(BotIcon, null)), /* @__PURE__ */ React6.createElement(ProfileInfo, null, /* @__PURE__ */ React6.createElement(Name, null, texts.CHATBOT_NAME), /* @__PURE__ */ React6.createElement(ChatbotStatusLabel_default, null)), /* @__PURE__ */ React6.createElement(
|
|
568
992
|
Button,
|
|
569
993
|
{
|
|
570
|
-
label:
|
|
994
|
+
label: texts.CHAT_FEEDBACK.RATE,
|
|
571
995
|
onClick: chatFeedbackBox.open,
|
|
572
996
|
size: "small",
|
|
573
997
|
layer: 2,
|
|
@@ -578,31 +1002,74 @@ var ChatbotHeader = /* @__PURE__ */ __name(({ chatFeedbackBox }) => {
|
|
|
578
1002
|
var ChatbotHeader_default = ChatbotHeader;
|
|
579
1003
|
|
|
580
1004
|
// src/components/ChatbotBody/index.tsx
|
|
581
|
-
import
|
|
1005
|
+
import React10, { useEffect as useEffect6, useRef as useRef5 } from "react";
|
|
582
1006
|
|
|
583
1007
|
// src/components/ChatbotBody/styles.ts
|
|
584
1008
|
import { styled as styled4 } from "styled-components";
|
|
585
1009
|
var ChatbotInput = styled4.div``;
|
|
586
1010
|
var MessagesList = styled4.ul`
|
|
587
|
-
padding: ${(props) => props.theme.spacing.components.medium}
|
|
1011
|
+
padding: ${(props) => props.theme.spacing.components.medium}
|
|
1012
|
+
${(props) => props.theme.spacing.components.large}
|
|
1013
|
+
${(props) => props.theme.spacing.components.large}
|
|
1014
|
+
${(props) => props.theme.spacing.components.medium};
|
|
588
1015
|
display: flex;
|
|
589
1016
|
flex-direction: column;
|
|
590
|
-
gap:
|
|
1017
|
+
gap: 0;
|
|
591
1018
|
`;
|
|
592
1019
|
var Wrapper4 = styled4.div`
|
|
593
1020
|
overflow: hidden;
|
|
594
1021
|
overflow-y: auto;
|
|
595
1022
|
flex: 1;
|
|
596
1023
|
height: 100%;
|
|
1024
|
+
padding-right: ${(props) => props.theme.spacing.components.small};
|
|
1025
|
+
|
|
1026
|
+
/* Custom scrollbar styles */
|
|
1027
|
+
&::-webkit-scrollbar {
|
|
1028
|
+
width: 8px;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
&::-webkit-scrollbar-track {
|
|
1032
|
+
background: transparent;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
&::-webkit-scrollbar-thumb {
|
|
1036
|
+
background: ${(props) => props.theme.colors.palette.primary.normal};
|
|
1037
|
+
border-radius: 4px;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
1041
|
+
opacity: 0.8;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/* Firefox */
|
|
1045
|
+
scrollbar-width: thin;
|
|
1046
|
+
scrollbar-color: ${(props) => props.theme.colors.palette.primary.normal} transparent;
|
|
597
1047
|
`;
|
|
598
1048
|
|
|
599
1049
|
// src/components/MessageBalloon/index.tsx
|
|
600
|
-
import React7 from "react";
|
|
1050
|
+
import React7, { useState as useState4, useRef as useRef3, useEffect as useEffect3 } from "react";
|
|
601
1051
|
|
|
602
1052
|
// src/components/MessageBalloon/styles.ts
|
|
1053
|
+
import { mix } from "polished";
|
|
603
1054
|
import { css as css2, styled as styled5 } from "styled-components";
|
|
604
1055
|
var Time = styled5.span`
|
|
605
1056
|
font-size: ${(props) => props.theme.fontSizes.small};
|
|
1057
|
+
color: ${(props) => props.theme.colors.content.detail};
|
|
1058
|
+
white-space: nowrap;
|
|
1059
|
+
|
|
1060
|
+
${({ $type }) => {
|
|
1061
|
+
switch ($type) {
|
|
1062
|
+
case "received":
|
|
1063
|
+
return css2`
|
|
1064
|
+
text-align: left;
|
|
1065
|
+
`;
|
|
1066
|
+
default:
|
|
1067
|
+
case "sent":
|
|
1068
|
+
return css2`
|
|
1069
|
+
text-align: right;
|
|
1070
|
+
`;
|
|
1071
|
+
}
|
|
1072
|
+
}}
|
|
606
1073
|
`;
|
|
607
1074
|
var Balloon = styled5.div`
|
|
608
1075
|
padding: ${(props) => props.theme.spacing.components.small};
|
|
@@ -627,6 +1094,7 @@ var Balloon = styled5.div`
|
|
|
627
1094
|
case "received":
|
|
628
1095
|
return css2`
|
|
629
1096
|
background: ${(props) => props.theme.colors.layers[2].background};
|
|
1097
|
+
color: ${(props) => props.theme.colors.content.text};
|
|
630
1098
|
border-top-left-radius: 0;
|
|
631
1099
|
|
|
632
1100
|
${$error && css2`
|
|
@@ -645,8 +1113,9 @@ var Balloon = styled5.div`
|
|
|
645
1113
|
case "sent":
|
|
646
1114
|
return css2`
|
|
647
1115
|
background: ${(props) => props.theme.colors.palette.primary.normal};
|
|
1116
|
+
color: white;
|
|
648
1117
|
border-top-right-radius: 0;
|
|
649
|
-
|
|
1118
|
+
text-align: left;
|
|
650
1119
|
|
|
651
1120
|
&::after {
|
|
652
1121
|
border-width: 0px 0px 10px 10px;
|
|
@@ -664,9 +1133,19 @@ var Balloon = styled5.div`
|
|
|
664
1133
|
flex-direction: column;
|
|
665
1134
|
gap: 1.3em;
|
|
666
1135
|
|
|
1136
|
+
p {
|
|
1137
|
+
margin: 0;
|
|
1138
|
+
color: inherit;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
667
1141
|
a {
|
|
668
1142
|
color: ${(props) => props.theme.colors.palette.primary.normal};
|
|
669
1143
|
font-weight: semibold;
|
|
1144
|
+
|
|
1145
|
+
${({ $type }) => $type === "sent" && css2`
|
|
1146
|
+
color: white;
|
|
1147
|
+
text-decoration: underline;
|
|
1148
|
+
`}
|
|
670
1149
|
}
|
|
671
1150
|
|
|
672
1151
|
ol,
|
|
@@ -674,16 +1153,220 @@ var Balloon = styled5.div`
|
|
|
674
1153
|
display: flex;
|
|
675
1154
|
flex-direction: column;
|
|
676
1155
|
gap: 1.3em;
|
|
1156
|
+
margin: 0;
|
|
1157
|
+
padding-left: 1.5em;
|
|
1158
|
+
color: inherit;
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
li {
|
|
1162
|
+
color: inherit;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
code {
|
|
1166
|
+
background: ${(props) => props.$type === "received" ? props.theme.colors.layers[1].background : "rgba(0, 0, 0, 0.2)"};
|
|
1167
|
+
color: inherit;
|
|
1168
|
+
padding: 0.2em 0.4em;
|
|
1169
|
+
border-radius: ${(props) => props.theme.borderRadius.small};
|
|
1170
|
+
font-size: 0.9em;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
pre {
|
|
1174
|
+
background: ${(props) => props.$type === "received" ? props.theme.colors.layers[1].background : "rgba(0, 0, 0, 0.2)"};
|
|
1175
|
+
color: inherit;
|
|
1176
|
+
padding: ${(props) => props.theme.spacing.components.small};
|
|
1177
|
+
border-radius: ${(props) => props.theme.borderRadius.small};
|
|
1178
|
+
overflow-x: auto;
|
|
1179
|
+
margin: 0;
|
|
1180
|
+
|
|
1181
|
+
/* Custom scrollbar styles */
|
|
1182
|
+
&::-webkit-scrollbar {
|
|
1183
|
+
height: 8px;
|
|
1184
|
+
}
|
|
1185
|
+
|
|
1186
|
+
&::-webkit-scrollbar-track {
|
|
1187
|
+
background: transparent;
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
&::-webkit-scrollbar-thumb {
|
|
1191
|
+
background: ${(props) => props.theme.colors.palette.primary.normal};
|
|
1192
|
+
border-radius: 4px;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
1196
|
+
opacity: 0.8;
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
/* Firefox */
|
|
1200
|
+
scrollbar-width: thin;
|
|
1201
|
+
scrollbar-color: ${(props) => props.theme.colors.palette.primary.normal} transparent;
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
pre code {
|
|
1205
|
+
background: transparent;
|
|
1206
|
+
padding: 0;
|
|
1207
|
+
}
|
|
1208
|
+
|
|
1209
|
+
strong,
|
|
1210
|
+
b {
|
|
1211
|
+
color: inherit;
|
|
1212
|
+
font-weight: ${(props) => props.theme.fontFamily.montserrat.weights.bold};
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
em,
|
|
1216
|
+
i {
|
|
1217
|
+
color: inherit;
|
|
677
1218
|
}
|
|
678
1219
|
`;
|
|
679
1220
|
var Label = styled5.span`
|
|
680
1221
|
font-size: ${(props) => props.theme.fontSizes.small};
|
|
1222
|
+
color: ${(props) => props.theme.colors.content.detail};
|
|
1223
|
+
`;
|
|
1224
|
+
var BalloonAndActionsWrapper = styled5.div`
|
|
1225
|
+
display: flex;
|
|
1226
|
+
flex-direction: column;
|
|
1227
|
+
gap: 2px;
|
|
1228
|
+
margin-bottom: ${(props) => props.theme.spacing.components.medium};
|
|
1229
|
+
|
|
1230
|
+
${({ $type }) => {
|
|
1231
|
+
switch ($type) {
|
|
1232
|
+
case "received":
|
|
1233
|
+
return css2``;
|
|
1234
|
+
default:
|
|
1235
|
+
case "sent":
|
|
1236
|
+
return css2`
|
|
1237
|
+
align-items: flex-end;
|
|
1238
|
+
`;
|
|
1239
|
+
}
|
|
1240
|
+
}}
|
|
1241
|
+
`;
|
|
1242
|
+
var BalloonContainer = styled5.div`
|
|
1243
|
+
position: relative;
|
|
1244
|
+
width: max-content;
|
|
1245
|
+
max-width: 100%;
|
|
1246
|
+
|
|
1247
|
+
${({ $type }) => {
|
|
1248
|
+
switch ($type) {
|
|
1249
|
+
case "received":
|
|
1250
|
+
return css2`
|
|
1251
|
+
display: inline-block;
|
|
1252
|
+
`;
|
|
1253
|
+
default:
|
|
1254
|
+
case "sent":
|
|
1255
|
+
return css2`
|
|
1256
|
+
display: block;
|
|
1257
|
+
margin-left: auto;
|
|
1258
|
+
`;
|
|
1259
|
+
}
|
|
1260
|
+
}}
|
|
1261
|
+
`;
|
|
1262
|
+
var TimestampAndActionsRow = styled5.div`
|
|
1263
|
+
display: flex;
|
|
1264
|
+
align-items: center;
|
|
1265
|
+
gap: 10px;
|
|
1266
|
+
width: 100%;
|
|
1267
|
+
|
|
1268
|
+
${({ $type }) => {
|
|
1269
|
+
switch ($type) {
|
|
1270
|
+
case "received":
|
|
1271
|
+
return css2`
|
|
1272
|
+
flex-direction: row-reverse;
|
|
1273
|
+
justify-content: flex-end;
|
|
1274
|
+
`;
|
|
1275
|
+
default:
|
|
1276
|
+
case "sent":
|
|
1277
|
+
return css2`
|
|
1278
|
+
flex-direction: row;
|
|
1279
|
+
justify-content: flex-end;
|
|
1280
|
+
`;
|
|
1281
|
+
}
|
|
1282
|
+
}}
|
|
1283
|
+
`;
|
|
1284
|
+
var ActionsContainer = styled5.div`
|
|
1285
|
+
display: flex;
|
|
1286
|
+
gap: ${(props) => props.theme.spacing.components.xsmall};
|
|
1287
|
+
align-items: center;
|
|
1288
|
+
z-index: 10;
|
|
1289
|
+
opacity: ${(props) => props.$isVisible ? 1 : 0};
|
|
1290
|
+
visibility: ${(props) => props.$isVisible ? "visible" : "hidden"};
|
|
1291
|
+
transition: opacity 0.2s ease, visibility 0.2s ease;
|
|
1292
|
+
pointer-events: ${(props) => props.$isVisible ? "auto" : "none"};
|
|
1293
|
+
margin: 0;
|
|
1294
|
+
padding: 0;
|
|
1295
|
+
|
|
1296
|
+
@keyframes fadeIn {
|
|
1297
|
+
from {
|
|
1298
|
+
opacity: 0;
|
|
1299
|
+
transform: translateY(-5px) scale(0.9);
|
|
1300
|
+
}
|
|
1301
|
+
to {
|
|
1302
|
+
opacity: 1;
|
|
1303
|
+
transform: translateY(0) scale(1);
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
${({ $type }) => {
|
|
1308
|
+
switch ($type) {
|
|
1309
|
+
case "received":
|
|
1310
|
+
return css2`
|
|
1311
|
+
left: 0;
|
|
1312
|
+
`;
|
|
1313
|
+
default:
|
|
1314
|
+
case "sent":
|
|
1315
|
+
return css2`
|
|
1316
|
+
right: 0;
|
|
1317
|
+
`;
|
|
1318
|
+
}
|
|
1319
|
+
}}
|
|
1320
|
+
`;
|
|
1321
|
+
var ActionButton = styled5.button`
|
|
1322
|
+
display: flex;
|
|
1323
|
+
align-items: center;
|
|
1324
|
+
justify-content: center;
|
|
1325
|
+
width: 28px;
|
|
1326
|
+
height: 28px;
|
|
1327
|
+
padding: 0;
|
|
1328
|
+
border: none;
|
|
1329
|
+
background: ${(props) => props.theme.colors.layers[1].background};
|
|
1330
|
+
color: ${(props) => props.theme.colors.content.text};
|
|
1331
|
+
border-radius: ${(props) => props.theme.borderRadius.small};
|
|
1332
|
+
cursor: pointer;
|
|
1333
|
+
position: relative;
|
|
1334
|
+
transition: all 0.2s ease;
|
|
1335
|
+
opacity: 0.85;
|
|
1336
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
1337
|
+
|
|
1338
|
+
&:hover {
|
|
1339
|
+
opacity: 1;
|
|
1340
|
+
background: ${(props) => props.theme.colors.layers[2].background};
|
|
1341
|
+
transform: scale(1.1);
|
|
1342
|
+
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.15);
|
|
1343
|
+
}
|
|
1344
|
+
|
|
1345
|
+
&:active {
|
|
1346
|
+
transform: scale(0.95);
|
|
1347
|
+
}
|
|
1348
|
+
`;
|
|
1349
|
+
var Tooltip = styled5.span`
|
|
1350
|
+
position: absolute;
|
|
1351
|
+
white-space: nowrap;
|
|
1352
|
+
padding: ${(props) => props.theme.spacing.components.xsmall}
|
|
1353
|
+
${(props) => props.theme.spacing.components.small};
|
|
1354
|
+
background: ${(props) => mix(0.1, props.theme.colors.content.text, props.theme.colors.layers[2].background)};
|
|
1355
|
+
color: ${(props) => props.theme.colors.content.text};
|
|
1356
|
+
border-radius: ${(props) => props.theme.borderRadius.small};
|
|
1357
|
+
font-size: ${(props) => props.theme.fontSizes.xsmall};
|
|
1358
|
+
pointer-events: none;
|
|
1359
|
+
z-index: 30;
|
|
1360
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
|
|
1361
|
+
bottom: calc(100% + ${(props) => props.theme.spacing.components.xsmall});
|
|
1362
|
+
left: 50%;
|
|
1363
|
+
transform: translateX(-50%);
|
|
681
1364
|
`;
|
|
682
1365
|
var Wrapper5 = styled5.div`
|
|
683
1366
|
font-size: ${(props) => props.theme.fontSizes.small};
|
|
684
1367
|
display: flex;
|
|
685
1368
|
flex-direction: column;
|
|
686
|
-
gap:
|
|
1369
|
+
gap: 2px;
|
|
687
1370
|
|
|
688
1371
|
${(props) => {
|
|
689
1372
|
switch (props.$type) {
|
|
@@ -707,6 +1390,7 @@ var formatMessageTime = /* @__PURE__ */ __name((dateUTC, currentDateUTC, locale)
|
|
|
707
1390
|
// src/components/MessageBalloon/index.tsx
|
|
708
1391
|
import Markdown from "react-markdown";
|
|
709
1392
|
import { CircleExclamationIcon } from "@ibti-tech/ui";
|
|
1393
|
+
import { Copy, Share2, RotateCw } from "lucide-react";
|
|
710
1394
|
var messageTypes = {
|
|
711
1395
|
assistant: "received",
|
|
712
1396
|
user: "sent"
|
|
@@ -716,16 +1400,204 @@ var MessageBalloon = /* @__PURE__ */ __name(({
|
|
|
716
1400
|
currentDateUTC
|
|
717
1401
|
}) => {
|
|
718
1402
|
const messageType = messageTypes[data.role];
|
|
719
|
-
const
|
|
720
|
-
const { locale } = useChatbot_default();
|
|
721
|
-
|
|
1403
|
+
const texts = useChatbotTexts();
|
|
1404
|
+
const { locale, makeQuestion } = useChatbot_default();
|
|
1405
|
+
const [isHovered, setIsHovered] = useState4(false);
|
|
1406
|
+
const [showTooltip, setShowTooltip] = useState4(null);
|
|
1407
|
+
const [copied, setCopied] = useState4(false);
|
|
1408
|
+
const copyTimeoutRef = useRef3(null);
|
|
1409
|
+
useEffect3(() => {
|
|
1410
|
+
return () => {
|
|
1411
|
+
if (copyTimeoutRef.current) {
|
|
1412
|
+
clearTimeout(copyTimeoutRef.current);
|
|
1413
|
+
}
|
|
1414
|
+
};
|
|
1415
|
+
}, []);
|
|
1416
|
+
const handleCopy = /* @__PURE__ */ __name(async () => {
|
|
1417
|
+
try {
|
|
1418
|
+
await navigator.clipboard.writeText(data.content);
|
|
1419
|
+
setCopied(true);
|
|
1420
|
+
setShowTooltip("copy");
|
|
1421
|
+
if (copyTimeoutRef.current) {
|
|
1422
|
+
clearTimeout(copyTimeoutRef.current);
|
|
1423
|
+
}
|
|
1424
|
+
copyTimeoutRef.current = setTimeout(() => {
|
|
1425
|
+
setCopied(false);
|
|
1426
|
+
setShowTooltip((prev) => prev === "copy" ? null : prev);
|
|
1427
|
+
}, 2e3);
|
|
1428
|
+
} catch (err) {
|
|
1429
|
+
console.error("Failed to copy:", err);
|
|
1430
|
+
}
|
|
1431
|
+
}, "handleCopy");
|
|
1432
|
+
const handleShare = /* @__PURE__ */ __name(async () => {
|
|
1433
|
+
if (navigator.share) {
|
|
1434
|
+
try {
|
|
1435
|
+
await navigator.share({
|
|
1436
|
+
title: texts.CHATBOT_NAME,
|
|
1437
|
+
text: data.content
|
|
1438
|
+
});
|
|
1439
|
+
} catch (err) {
|
|
1440
|
+
console.error("Failed to share:", err);
|
|
1441
|
+
}
|
|
1442
|
+
} else {
|
|
1443
|
+
handleCopy();
|
|
1444
|
+
}
|
|
1445
|
+
}, "handleShare");
|
|
1446
|
+
const handleResend = /* @__PURE__ */ __name(() => {
|
|
1447
|
+
if (data.role === "user") {
|
|
1448
|
+
makeQuestion(data.content);
|
|
1449
|
+
}
|
|
1450
|
+
}, "handleResend");
|
|
1451
|
+
return /* @__PURE__ */ React7.createElement(Wrapper5, { $type: messageType }, data.role == "assistant" && /* @__PURE__ */ React7.createElement(Label, null, texts.CHATBOT_NAME), data.role == "user" && /* @__PURE__ */ React7.createElement(Label, null, texts.USER_LABEL), /* @__PURE__ */ React7.createElement(
|
|
1452
|
+
BalloonAndActionsWrapper,
|
|
1453
|
+
{
|
|
1454
|
+
onMouseEnter: () => setIsHovered(true),
|
|
1455
|
+
onMouseLeave: () => setIsHovered(false),
|
|
1456
|
+
$type: messageType
|
|
1457
|
+
},
|
|
1458
|
+
/* @__PURE__ */ React7.createElement(BalloonContainer, { $type: messageType }, /* @__PURE__ */ React7.createElement(Balloon, { $type: messageType, $error: data.error }, data.error && /* @__PURE__ */ React7.createElement(CircleExclamationIcon, null), /* @__PURE__ */ React7.createElement(Markdown, null, data.content))),
|
|
1459
|
+
/* @__PURE__ */ React7.createElement(TimestampAndActionsRow, { $type: messageType }, /* @__PURE__ */ React7.createElement(
|
|
1460
|
+
ActionsContainer,
|
|
1461
|
+
{
|
|
1462
|
+
$type: messageType,
|
|
1463
|
+
$isVisible: isHovered,
|
|
1464
|
+
onMouseEnter: () => setIsHovered(true),
|
|
1465
|
+
onMouseLeave: () => setIsHovered(false)
|
|
1466
|
+
},
|
|
1467
|
+
data.role === "user" && /* @__PURE__ */ React7.createElement(
|
|
1468
|
+
ActionButton,
|
|
1469
|
+
{
|
|
1470
|
+
$messageType: messageType,
|
|
1471
|
+
onClick: handleResend,
|
|
1472
|
+
onMouseEnter: () => setShowTooltip("resend"),
|
|
1473
|
+
onMouseLeave: () => setShowTooltip(null),
|
|
1474
|
+
"aria-label": texts.MESSAGE_ACTIONS.RESEND
|
|
1475
|
+
},
|
|
1476
|
+
/* @__PURE__ */ React7.createElement(RotateCw, { size: 14 }),
|
|
1477
|
+
showTooltip === "resend" && /* @__PURE__ */ React7.createElement(Tooltip, { $messageType: messageType }, texts.MESSAGE_ACTIONS.RESEND)
|
|
1478
|
+
),
|
|
1479
|
+
/* @__PURE__ */ React7.createElement(
|
|
1480
|
+
ActionButton,
|
|
1481
|
+
{
|
|
1482
|
+
$messageType: messageType,
|
|
1483
|
+
onClick: handleCopy,
|
|
1484
|
+
onMouseEnter: () => {
|
|
1485
|
+
if (!copied) {
|
|
1486
|
+
setShowTooltip("copy");
|
|
1487
|
+
}
|
|
1488
|
+
},
|
|
1489
|
+
onMouseLeave: () => {
|
|
1490
|
+
if (!copied) {
|
|
1491
|
+
setShowTooltip(null);
|
|
1492
|
+
}
|
|
1493
|
+
},
|
|
1494
|
+
"aria-label": texts.MESSAGE_ACTIONS.COPY
|
|
1495
|
+
},
|
|
1496
|
+
/* @__PURE__ */ React7.createElement(Copy, { size: 14 }),
|
|
1497
|
+
(showTooltip === "copy" || copied) && /* @__PURE__ */ React7.createElement(Tooltip, { $messageType: messageType }, copied ? locale === "pt-BR" ? "Copiado!" : "Copied!" : texts.MESSAGE_ACTIONS.COPY)
|
|
1498
|
+
),
|
|
1499
|
+
/* @__PURE__ */ React7.createElement(
|
|
1500
|
+
ActionButton,
|
|
1501
|
+
{
|
|
1502
|
+
$messageType: messageType,
|
|
1503
|
+
onClick: handleShare,
|
|
1504
|
+
onMouseEnter: () => setShowTooltip("share"),
|
|
1505
|
+
onMouseLeave: () => setShowTooltip(null),
|
|
1506
|
+
"aria-label": texts.MESSAGE_ACTIONS.SHARE
|
|
1507
|
+
},
|
|
1508
|
+
/* @__PURE__ */ React7.createElement(Share2, { size: 14 }),
|
|
1509
|
+
showTooltip === "share" && /* @__PURE__ */ React7.createElement(Tooltip, { $messageType: messageType }, texts.MESSAGE_ACTIONS.SHARE)
|
|
1510
|
+
)
|
|
1511
|
+
), /* @__PURE__ */ React7.createElement(Time, { $type: messageType }, formatMessageTime(data.timestamp, currentDateUTC, locale)))
|
|
1512
|
+
));
|
|
722
1513
|
}, "MessageBalloon");
|
|
723
1514
|
var MessageBalloon_default = MessageBalloon;
|
|
724
1515
|
|
|
1516
|
+
// src/components/WritingIndicator/index.tsx
|
|
1517
|
+
import React8 from "react";
|
|
1518
|
+
|
|
1519
|
+
// src/components/WritingIndicator/styles.ts
|
|
1520
|
+
import { keyframes, styled as styled6 } from "styled-components";
|
|
1521
|
+
var dotAnimation = keyframes`
|
|
1522
|
+
0%, 20% {
|
|
1523
|
+
opacity: 0;
|
|
1524
|
+
transform: scale(0.8);
|
|
1525
|
+
}
|
|
1526
|
+
50% {
|
|
1527
|
+
opacity: 1;
|
|
1528
|
+
transform: scale(1);
|
|
1529
|
+
}
|
|
1530
|
+
80%, 100% {
|
|
1531
|
+
opacity: 0.3;
|
|
1532
|
+
transform: scale(0.8);
|
|
1533
|
+
}
|
|
1534
|
+
`;
|
|
1535
|
+
var Dots = styled6.span`
|
|
1536
|
+
display: inline-flex;
|
|
1537
|
+
gap: 4px;
|
|
1538
|
+
align-items: center;
|
|
1539
|
+
margin-left: 4px;
|
|
1540
|
+
`;
|
|
1541
|
+
var Dot = styled6.span`
|
|
1542
|
+
width: 6px;
|
|
1543
|
+
height: 6px;
|
|
1544
|
+
border-radius: 50%;
|
|
1545
|
+
background: currentColor;
|
|
1546
|
+
animation: ${dotAnimation} 1.4s ease-in-out infinite;
|
|
1547
|
+
animation-delay: ${(props) => props.$delay}s;
|
|
1548
|
+
`;
|
|
1549
|
+
var Text = styled6.span`
|
|
1550
|
+
display: inline-block;
|
|
1551
|
+
`;
|
|
1552
|
+
var Balloon2 = styled6.div`
|
|
1553
|
+
padding: ${(props) => props.theme.spacing.components.small};
|
|
1554
|
+
width: max-content;
|
|
1555
|
+
max-width: 100%;
|
|
1556
|
+
border-radius: ${(props) => props.theme.borderRadius.medium};
|
|
1557
|
+
border-top-left-radius: 0;
|
|
1558
|
+
position: relative;
|
|
1559
|
+
line-height: 1.5em;
|
|
1560
|
+
display: flex;
|
|
1561
|
+
align-items: center;
|
|
1562
|
+
background: ${(props) => props.theme.colors.layers[2].background};
|
|
1563
|
+
color: ${(props) => props.theme.colors.content.text};
|
|
1564
|
+
|
|
1565
|
+
&::after {
|
|
1566
|
+
position: absolute;
|
|
1567
|
+
content: '';
|
|
1568
|
+
width: 0;
|
|
1569
|
+
height: 0;
|
|
1570
|
+
border-style: solid;
|
|
1571
|
+
border-width: 0px 10px 10px 0;
|
|
1572
|
+
border-color: transparent
|
|
1573
|
+
${(props) => props.theme.colors.layers[2].background} transparent
|
|
1574
|
+
transparent;
|
|
1575
|
+
top: 0;
|
|
1576
|
+
left: -10px;
|
|
1577
|
+
}
|
|
1578
|
+
`;
|
|
1579
|
+
var Label2 = styled6.span`
|
|
1580
|
+
font-size: ${(props) => props.theme.fontSizes.small};
|
|
1581
|
+
`;
|
|
1582
|
+
var Wrapper6 = styled6.div`
|
|
1583
|
+
font-size: ${(props) => props.theme.fontSizes.small};
|
|
1584
|
+
display: flex;
|
|
1585
|
+
flex-direction: column;
|
|
1586
|
+
gap: ${(props) => props.theme.spacing.components.xsmall};
|
|
1587
|
+
`;
|
|
1588
|
+
|
|
1589
|
+
// src/components/WritingIndicator/index.tsx
|
|
1590
|
+
var WritingIndicator = /* @__PURE__ */ __name(() => {
|
|
1591
|
+
const texts = useChatbotTexts();
|
|
1592
|
+
const { locale } = useChatbot();
|
|
1593
|
+
return /* @__PURE__ */ React8.createElement(Wrapper6, null, /* @__PURE__ */ React8.createElement(Label2, null, texts.CHATBOT_NAME), /* @__PURE__ */ React8.createElement(Balloon2, null, /* @__PURE__ */ React8.createElement(Text, null, texts.WRITING_MESSAGE), /* @__PURE__ */ React8.createElement(Dots, null, /* @__PURE__ */ React8.createElement(Dot, { $delay: 0 }), /* @__PURE__ */ React8.createElement(Dot, { $delay: 0.2 }), /* @__PURE__ */ React8.createElement(Dot, { $delay: 0.4 }))));
|
|
1594
|
+
}, "WritingIndicator");
|
|
1595
|
+
var WritingIndicator_default = WritingIndicator;
|
|
1596
|
+
|
|
725
1597
|
// src/hooks/useElementScroll.ts
|
|
726
|
-
import { useEffect as
|
|
1598
|
+
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
727
1599
|
var useElementScroll = /* @__PURE__ */ __name((elementRef) => {
|
|
728
|
-
const [scrollProgress, setScrollProgress] =
|
|
1600
|
+
const [scrollProgress, setScrollProgress] = useState5(0);
|
|
729
1601
|
const calculateScrollPercentage = /* @__PURE__ */ __name(() => {
|
|
730
1602
|
if (!elementRef.current) return;
|
|
731
1603
|
const element = elementRef.current;
|
|
@@ -737,7 +1609,7 @@ var useElementScroll = /* @__PURE__ */ __name((elementRef) => {
|
|
|
737
1609
|
const progressValue = Math.min(100, Math.max(0, scrolled));
|
|
738
1610
|
setScrollProgress(isNaN(progressValue) ? 100 : progressValue);
|
|
739
1611
|
}, "calculateScrollPercentage");
|
|
740
|
-
|
|
1612
|
+
useEffect4(() => {
|
|
741
1613
|
if (!elementRef.current) return;
|
|
742
1614
|
const handleIntersection = /* @__PURE__ */ __name(() => {
|
|
743
1615
|
calculateScrollPercentage();
|
|
@@ -772,12 +1644,12 @@ var useElementScroll = /* @__PURE__ */ __name((elementRef) => {
|
|
|
772
1644
|
}, "useElementScroll");
|
|
773
1645
|
|
|
774
1646
|
// src/hooks/useUpdatedTime.ts
|
|
775
|
-
import { useEffect as
|
|
1647
|
+
import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
776
1648
|
var useUpdatedTime = /* @__PURE__ */ __name(({
|
|
777
1649
|
intervalInSeconds
|
|
778
1650
|
}) => {
|
|
779
|
-
const [date, setDate] =
|
|
780
|
-
|
|
1651
|
+
const [date, setDate] = useState6(/* @__PURE__ */ new Date());
|
|
1652
|
+
useEffect5(() => {
|
|
781
1653
|
const time = 1e3 * intervalInSeconds;
|
|
782
1654
|
const interval = setInterval(() => {
|
|
783
1655
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -791,40 +1663,40 @@ var useUpdatedTime = /* @__PURE__ */ __name(({
|
|
|
791
1663
|
}, "useUpdatedTime");
|
|
792
1664
|
|
|
793
1665
|
// src/components/SuggestedQuestions/index.tsx
|
|
794
|
-
import
|
|
1666
|
+
import React9 from "react";
|
|
795
1667
|
|
|
796
1668
|
// src/components/SuggestedQuestions/styles.ts
|
|
797
1669
|
import { Button as Button2 } from "@ibti-tech/ui";
|
|
798
|
-
import { styled as
|
|
799
|
-
var QuestionButton =
|
|
1670
|
+
import { styled as styled7 } from "styled-components";
|
|
1671
|
+
var QuestionButton = styled7(Button2)`
|
|
800
1672
|
text-align: left;
|
|
801
1673
|
justify-content: flex-start;
|
|
802
1674
|
height: auto;
|
|
803
1675
|
padding: ${(props) => props.theme.spacing.components.small};
|
|
804
1676
|
`;
|
|
805
|
-
var QuestionListItem =
|
|
806
|
-
var QuestionList =
|
|
1677
|
+
var QuestionListItem = styled7.li``;
|
|
1678
|
+
var QuestionList = styled7.ul`
|
|
807
1679
|
display: flex;
|
|
808
1680
|
flex-direction: column;
|
|
809
1681
|
gap: ${(props) => props.theme.spacing.components.small};
|
|
810
1682
|
`;
|
|
811
|
-
var Title =
|
|
1683
|
+
var Title = styled7.span`
|
|
812
1684
|
display: block;
|
|
813
1685
|
font-size: ${(props) => props.theme.fontSizes.small};
|
|
814
1686
|
font-weight: ${(props) => props.theme.fontFamily.montserrat.weights.bold};
|
|
815
1687
|
margin-bottom: ${(props) => props.theme.spacing.components.medium};
|
|
816
1688
|
/* text-align: center; */
|
|
817
1689
|
`;
|
|
818
|
-
var
|
|
1690
|
+
var Wrapper7 = styled7.div`
|
|
819
1691
|
padding: ${(props) => props.theme.spacing.components.medium};
|
|
820
1692
|
`;
|
|
821
1693
|
|
|
822
1694
|
// src/components/SuggestedQuestions/index.tsx
|
|
823
1695
|
var SuggestedQuestions = /* @__PURE__ */ __name(({}) => {
|
|
824
|
-
const
|
|
1696
|
+
const texts = useChatbotTexts();
|
|
825
1697
|
const { suggestedQuestions, makeQuestion } = useChatbot_default();
|
|
826
1698
|
if (suggestedQuestions.data.length === 0) return;
|
|
827
|
-
return /* @__PURE__ */
|
|
1699
|
+
return /* @__PURE__ */ React9.createElement(Wrapper7, null, /* @__PURE__ */ React9.createElement(Title, null, texts.SUGGESTED_QUESTIONS.TITLE), /* @__PURE__ */ React9.createElement(QuestionList, null, suggestedQuestions.data.map((question) => /* @__PURE__ */ React9.createElement(QuestionListItem, { key: question }, /* @__PURE__ */ React9.createElement(
|
|
828
1700
|
QuestionButton,
|
|
829
1701
|
{
|
|
830
1702
|
label: question,
|
|
@@ -843,11 +1715,11 @@ var SuggestedQuestions_default = SuggestedQuestions;
|
|
|
843
1715
|
|
|
844
1716
|
// src/components/ChatbotBody/index.tsx
|
|
845
1717
|
var ChatbotBody = /* @__PURE__ */ __name(({}) => {
|
|
846
|
-
const { chatMessages, suggestedQuestions } = useChatbot();
|
|
847
|
-
const scrollableElementRef =
|
|
1718
|
+
const { chatMessages, suggestedQuestions, loading } = useChatbot();
|
|
1719
|
+
const scrollableElementRef = useRef5(null);
|
|
848
1720
|
const { scrollProgress, scrollToEnd } = useElementScroll(scrollableElementRef);
|
|
849
1721
|
const { dateUTC } = useUpdatedTime({ intervalInSeconds: 15 });
|
|
850
|
-
|
|
1722
|
+
useEffect6(() => {
|
|
851
1723
|
if (scrollProgress > 85) scrollToEnd();
|
|
852
1724
|
document.addEventListener(
|
|
853
1725
|
CUSTOM_EVENT_NAMES.ASSISTANT_ANSWER_FINISHED,
|
|
@@ -860,23 +1732,28 @@ var ChatbotBody = /* @__PURE__ */ __name(({}) => {
|
|
|
860
1732
|
);
|
|
861
1733
|
};
|
|
862
1734
|
}, [chatMessages, suggestedQuestions]);
|
|
863
|
-
|
|
1735
|
+
useEffect6(() => {
|
|
1736
|
+
if (loading) {
|
|
1737
|
+
scrollToEnd();
|
|
1738
|
+
}
|
|
1739
|
+
}, [loading, scrollToEnd]);
|
|
1740
|
+
return /* @__PURE__ */ React10.createElement(Wrapper4, { ref: scrollableElementRef }, /* @__PURE__ */ React10.createElement(MessagesList, null, chatMessages.map((msgData) => /* @__PURE__ */ React10.createElement(
|
|
864
1741
|
MessageBalloon_default,
|
|
865
1742
|
{
|
|
866
1743
|
key: msgData.id,
|
|
867
1744
|
data: msgData,
|
|
868
1745
|
currentDateUTC: dateUTC
|
|
869
1746
|
}
|
|
870
|
-
))), /* @__PURE__ */
|
|
1747
|
+
)), loading && /* @__PURE__ */ React10.createElement(WritingIndicator_default, null)), /* @__PURE__ */ React10.createElement(SuggestedQuestions_default, null));
|
|
871
1748
|
}, "ChatbotBody");
|
|
872
1749
|
var ChatbotBody_default = ChatbotBody;
|
|
873
1750
|
|
|
874
1751
|
// src/components/ChatbotFooter/index.tsx
|
|
875
|
-
import
|
|
1752
|
+
import React11, { useState as useState7, useRef as useRef6, useEffect as useEffect7 } from "react";
|
|
876
1753
|
|
|
877
1754
|
// src/components/ChatbotFooter/styles.ts
|
|
878
|
-
import { styled as
|
|
879
|
-
var LoadingSuggestedQuestions =
|
|
1755
|
+
import { styled as styled8 } from "styled-components";
|
|
1756
|
+
var LoadingSuggestedQuestions = styled8.span`
|
|
880
1757
|
display: flex;
|
|
881
1758
|
align-items: center;
|
|
882
1759
|
gap: ${(props) => props.theme.spacing.components.small};
|
|
@@ -884,11 +1761,84 @@ var LoadingSuggestedQuestions = styled7.span`
|
|
|
884
1761
|
padding: ${(props) => props.theme.spacing.components.small}
|
|
885
1762
|
${(props) => props.theme.spacing.components.medium};
|
|
886
1763
|
`;
|
|
887
|
-
var Form =
|
|
1764
|
+
var Form = styled8.form`
|
|
888
1765
|
display: flex;
|
|
889
1766
|
gap: ${(props) => props.theme.spacing.components.small};
|
|
1767
|
+
|
|
1768
|
+
/* Remove border from submit button */
|
|
1769
|
+
button[type='submit'] {
|
|
1770
|
+
border: none !important;
|
|
1771
|
+
outline: none !important;
|
|
1772
|
+
box-shadow: none !important;
|
|
1773
|
+
}
|
|
1774
|
+
|
|
1775
|
+
/* Chatbot textarea styles */
|
|
1776
|
+
.textareaField {
|
|
1777
|
+
font-family: inherit !important;
|
|
1778
|
+
|
|
1779
|
+
&,
|
|
1780
|
+
*,
|
|
1781
|
+
textarea {
|
|
1782
|
+
font-size: ${(props) => props.theme.fontSizes.medium} !important;
|
|
1783
|
+
font-family: inherit !important;
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
textarea {
|
|
1787
|
+
border-radius: ${(props) => props.theme.borderRadius.medium} !important;
|
|
1788
|
+
border: 1px solid ${(props) => props.theme.colors.layers[2].border} !important;
|
|
1789
|
+
padding: ${(props) => props.theme.spacing.components.small}
|
|
1790
|
+
${(props) => props.theme.spacing.components.medium} !important;
|
|
1791
|
+
min-height: 40px !important;
|
|
1792
|
+
max-height: 200px !important;
|
|
1793
|
+
resize: none !important;
|
|
1794
|
+
line-height: 1.5 !important;
|
|
1795
|
+
width: 100% !important;
|
|
1796
|
+
box-sizing: border-box !important;
|
|
1797
|
+
font-family: inherit !important;
|
|
1798
|
+
overflow-y: auto !important;
|
|
1799
|
+
overflow-x: hidden !important;
|
|
1800
|
+
|
|
1801
|
+
/* Custom scrollbar styles */
|
|
1802
|
+
&::-webkit-scrollbar {
|
|
1803
|
+
width: 8px;
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
&::-webkit-scrollbar-track {
|
|
1807
|
+
background: transparent;
|
|
1808
|
+
}
|
|
1809
|
+
|
|
1810
|
+
&::-webkit-scrollbar-thumb {
|
|
1811
|
+
background: ${(props) => props.theme.colors.palette.primary.normal} !important;
|
|
1812
|
+
border-radius: 4px;
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1815
|
+
&::-webkit-scrollbar-thumb:hover {
|
|
1816
|
+
opacity: 0.8;
|
|
1817
|
+
}
|
|
1818
|
+
|
|
1819
|
+
/* Firefox */
|
|
1820
|
+
scrollbar-width: thin !important;
|
|
1821
|
+
scrollbar-color: ${(props) => props.theme.colors.palette.primary.normal} transparent !important;
|
|
1822
|
+
|
|
1823
|
+
&:focus {
|
|
1824
|
+
outline: none !important;
|
|
1825
|
+
border-color: ${(props) => props.theme.colors.palette.primary.normal} !important;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
&::placeholder {
|
|
1829
|
+
color: ${(props) => props.theme.colors.content.detail} !important;
|
|
1830
|
+
font-size: ${(props) => props.theme.fontSizes.medium} !important;
|
|
1831
|
+
font-family: inherit !important;
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
&:focus-within textarea {
|
|
1836
|
+
outline: none !important;
|
|
1837
|
+
border-color: ${(props) => props.theme.colors.palette.primary.normal} !important;
|
|
1838
|
+
}
|
|
1839
|
+
}
|
|
890
1840
|
`;
|
|
891
|
-
var
|
|
1841
|
+
var Wrapper8 = styled8.div`
|
|
892
1842
|
padding: ${(props) => props.theme.spacing.components.small};
|
|
893
1843
|
`;
|
|
894
1844
|
|
|
@@ -901,31 +1851,60 @@ import {
|
|
|
901
1851
|
} from "@ibti-tech/ui";
|
|
902
1852
|
var ChatbotFooter = /* @__PURE__ */ __name(({}) => {
|
|
903
1853
|
const { makeQuestion, loading, writing, suggestedQuestions } = useChatbot_default();
|
|
904
|
-
const [questionInput, setQuestionInput] =
|
|
905
|
-
const
|
|
1854
|
+
const [questionInput, setQuestionInput] = useState7("");
|
|
1855
|
+
const wrapperRef = useRef6(null);
|
|
1856
|
+
const texts = useChatbotTexts();
|
|
906
1857
|
const handleSubmit = /* @__PURE__ */ __name(async (e) => {
|
|
907
1858
|
e.preventDefault();
|
|
1859
|
+
if (!questionInput.trim() || loading || writing) {
|
|
1860
|
+
return;
|
|
1861
|
+
}
|
|
1862
|
+
const questionToSend = questionInput.trim();
|
|
908
1863
|
setQuestionInput("");
|
|
909
|
-
await makeQuestion(
|
|
1864
|
+
await makeQuestion(questionToSend);
|
|
910
1865
|
}, "handleSubmit");
|
|
911
|
-
|
|
1866
|
+
useEffect7(() => {
|
|
1867
|
+
const textarea = wrapperRef.current?.querySelector(
|
|
1868
|
+
".textareaField textarea"
|
|
1869
|
+
);
|
|
1870
|
+
if (textarea) {
|
|
1871
|
+
textarea.style.height = "auto";
|
|
1872
|
+
textarea.style.height = `${textarea.scrollHeight}px`;
|
|
1873
|
+
const handleKeyDown = /* @__PURE__ */ __name((e) => {
|
|
1874
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
1875
|
+
e.preventDefault();
|
|
1876
|
+
if (questionInput.trim() && !loading && !writing) {
|
|
1877
|
+
const form = textarea.closest("form");
|
|
1878
|
+
if (form) {
|
|
1879
|
+
form.requestSubmit();
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
}
|
|
1883
|
+
}, "handleKeyDown");
|
|
1884
|
+
textarea.addEventListener("keydown", handleKeyDown);
|
|
1885
|
+
return () => {
|
|
1886
|
+
textarea.removeEventListener("keydown", handleKeyDown);
|
|
1887
|
+
};
|
|
1888
|
+
}
|
|
1889
|
+
}, [questionInput, loading, writing]);
|
|
1890
|
+
return /* @__PURE__ */ React11.createElement(Wrapper8, { "data-testid": "chatbot-footer", ref: wrapperRef }, suggestedQuestions.loading && /* @__PURE__ */ React11.createElement(LoadingSuggestedQuestions, null, /* @__PURE__ */ React11.createElement(Spinner, { size: "extra-small" }), texts.SUGGESTED_QUESTIONS.LOADING), /* @__PURE__ */ React11.createElement(Form, { onSubmit: handleSubmit }, /* @__PURE__ */ React11.createElement(
|
|
912
1891
|
TextArea,
|
|
913
1892
|
{
|
|
914
1893
|
fillWidth: true,
|
|
915
1894
|
disabled: loading || writing,
|
|
916
1895
|
value: questionInput,
|
|
917
1896
|
onChange: (e) => setQuestionInput(e.target.value),
|
|
918
|
-
placeholder:
|
|
1897
|
+
placeholder: texts.INPUT_PLACEHOLDER,
|
|
919
1898
|
className: "textareaField",
|
|
920
1899
|
rows: 1,
|
|
921
1900
|
layer: 2
|
|
922
1901
|
}
|
|
923
|
-
), /* @__PURE__ */
|
|
1902
|
+
), /* @__PURE__ */ React11.createElement(
|
|
924
1903
|
IconButton,
|
|
925
1904
|
{
|
|
926
1905
|
icon: ArrowUpIcon,
|
|
927
1906
|
loading,
|
|
928
|
-
disabled: loading || writing || !questionInput,
|
|
1907
|
+
disabled: loading || writing || !questionInput.trim(),
|
|
929
1908
|
type: "submit"
|
|
930
1909
|
}
|
|
931
1910
|
)));
|
|
@@ -934,13 +1913,11 @@ var ChatbotFooter_default = ChatbotFooter;
|
|
|
934
1913
|
|
|
935
1914
|
// src/components/ChatbotToggle/styles.ts
|
|
936
1915
|
import { screens as screens2 } from "@ibti-tech/ui";
|
|
937
|
-
import { styled as
|
|
938
|
-
var ButtonWrapper =
|
|
1916
|
+
import { css as css4, styled as styled9 } from "styled-components";
|
|
1917
|
+
var ButtonWrapper = styled9.button`
|
|
939
1918
|
height: 32px;
|
|
940
1919
|
width: 100%;
|
|
941
1920
|
background: transparent;
|
|
942
|
-
/* background-color: ${(props) => props.theme.colors.layers[1].background};
|
|
943
|
-
border: 1px solid ${(props) => props.theme.colors.layers[1].border}; */
|
|
944
1921
|
color: ${(props) => props.theme.colors.palette.primary.normal};
|
|
945
1922
|
padding: ${(props) => props.theme.spacing.components.small};
|
|
946
1923
|
font-size: ${(props) => props.theme.fontSizes.small};
|
|
@@ -950,6 +1927,21 @@ var ButtonWrapper = styled8.button`
|
|
|
950
1927
|
justify-content: center;
|
|
951
1928
|
gap: ${(props) => props.theme.spacing.components.small};
|
|
952
1929
|
border-radius: ${(props) => props.theme.borderRadius.medium};
|
|
1930
|
+
border: none !important;
|
|
1931
|
+
outline: none !important;
|
|
1932
|
+
box-shadow: none !important;
|
|
1933
|
+
flex-shrink: 0;
|
|
1934
|
+
|
|
1935
|
+
${(props) => !props.$opened && props.$verticalPosition === "bottom" && css4`
|
|
1936
|
+
background-color: ${props.theme.colors.layers[1].background};
|
|
1937
|
+
cursor: pointer;
|
|
1938
|
+
min-height: 32px;
|
|
1939
|
+
height: 32px;
|
|
1940
|
+
width: 100%;
|
|
1941
|
+
flex-shrink: 0;
|
|
1942
|
+
box-sizing: border-box;
|
|
1943
|
+
border-radius: ${(props2) => props2.theme.borderRadius.medium} ${(props2) => props2.theme.borderRadius.medium} 0 0;
|
|
1944
|
+
`}
|
|
953
1945
|
|
|
954
1946
|
${screens2.tablet} {
|
|
955
1947
|
transition: ${(props) => props.theme.transitionDurations.default};
|
|
@@ -962,50 +1954,116 @@ var ButtonWrapper = styled8.button`
|
|
|
962
1954
|
`;
|
|
963
1955
|
|
|
964
1956
|
// src/components/ChatbotToggle/index.tsx
|
|
965
|
-
import
|
|
1957
|
+
import React12 from "react";
|
|
966
1958
|
import { ChevronDownIcon, ChevronUpIcon } from "@ibti-tech/ui/dist/icons";
|
|
967
|
-
var ChatbotToggle = /* @__PURE__ */ __name((
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
const
|
|
972
|
-
|
|
1959
|
+
var ChatbotToggle = /* @__PURE__ */ __name(({
|
|
1960
|
+
verticalPosition = "bottom",
|
|
1961
|
+
opened: openedProp
|
|
1962
|
+
}) => {
|
|
1963
|
+
const { opened: openedContext, openedToggle } = useChatbot_default();
|
|
1964
|
+
const opened = openedProp ?? openedContext;
|
|
1965
|
+
const texts = useChatbotTexts();
|
|
1966
|
+
const toggleText = (opened ? texts.CHATBOT_BAR.CLOSE : texts.CHATBOT_BAR.OPEN).replace("{{CHATBOT_NAME}}", texts.CHATBOT_NAME);
|
|
1967
|
+
const Chevron = verticalPosition === "top" ? opened ? ChevronUpIcon : ChevronDownIcon : opened ? ChevronDownIcon : ChevronUpIcon;
|
|
1968
|
+
return /* @__PURE__ */ React12.createElement(
|
|
1969
|
+
ButtonWrapper,
|
|
1970
|
+
{
|
|
1971
|
+
onClick: openedToggle,
|
|
1972
|
+
$opened: opened,
|
|
1973
|
+
$verticalPosition: verticalPosition
|
|
1974
|
+
},
|
|
1975
|
+
/* @__PURE__ */ React12.createElement(BotIcon, null),
|
|
1976
|
+
/* @__PURE__ */ React12.createElement("span", null, toggleText),
|
|
1977
|
+
/* @__PURE__ */ React12.createElement(Chevron, null)
|
|
1978
|
+
);
|
|
973
1979
|
}, "ChatbotToggle");
|
|
974
1980
|
var ChatbotToggle_default = ChatbotToggle;
|
|
975
1981
|
|
|
976
1982
|
// src/components/ChatUserFeedbackRating/index.tsx
|
|
977
|
-
import
|
|
1983
|
+
import React13, { useState as useState8 } from "react";
|
|
978
1984
|
import { Button as Button4, RatingStars, TextArea as TextArea2 } from "@ibti-tech/ui";
|
|
979
1985
|
|
|
980
1986
|
// src/components/ChatUserFeedbackRating/styles.ts
|
|
981
1987
|
import { CardBase } from "@ibti-tech/ui";
|
|
982
|
-
import { css as
|
|
983
|
-
var ActionButtons =
|
|
1988
|
+
import { css as css5, styled as styled10 } from "styled-components";
|
|
1989
|
+
var ActionButtons = styled10.div`
|
|
984
1990
|
display: flex;
|
|
985
1991
|
justify-content: flex-end;
|
|
986
1992
|
gap: ${(props) => props.theme.spacing.components.small};
|
|
1993
|
+
|
|
1994
|
+
/* Remove border from submit button */
|
|
1995
|
+
button[type='submit'] {
|
|
1996
|
+
border: none !important;
|
|
1997
|
+
outline: none !important;
|
|
1998
|
+
box-shadow: none !important;
|
|
1999
|
+
}
|
|
987
2000
|
`;
|
|
988
|
-
var Form2 =
|
|
2001
|
+
var Form2 = styled10.form`
|
|
989
2002
|
display: flex;
|
|
990
2003
|
flex-direction: column;
|
|
991
2004
|
gap: ${(props) => props.theme.spacing.components.medium};
|
|
2005
|
+
|
|
2006
|
+
/* Feedback textarea styles */
|
|
2007
|
+
.feedbackTextarea {
|
|
2008
|
+
font-family: inherit !important;
|
|
2009
|
+
|
|
2010
|
+
&,
|
|
2011
|
+
*,
|
|
2012
|
+
textarea {
|
|
2013
|
+
font-size: ${(props) => props.theme.fontSizes.medium} !important;
|
|
2014
|
+
font-family: inherit !important;
|
|
2015
|
+
}
|
|
2016
|
+
|
|
2017
|
+
textarea {
|
|
2018
|
+
border-radius: ${(props) => props.theme.borderRadius.medium} !important;
|
|
2019
|
+
border: 1px solid ${(props) => props.theme.colors.layers[2].border} !important;
|
|
2020
|
+
padding: ${(props) => props.theme.spacing.components.small}
|
|
2021
|
+
${(props) => props.theme.spacing.components.medium} !important;
|
|
2022
|
+
min-height: 40px !important;
|
|
2023
|
+
resize: none !important;
|
|
2024
|
+
line-height: 1.5 !important;
|
|
2025
|
+
width: 100% !important;
|
|
2026
|
+
box-sizing: border-box !important;
|
|
2027
|
+
font-family: inherit !important;
|
|
2028
|
+
color: ${(props) => props.theme.colors.content.text} !important;
|
|
2029
|
+
background-color: ${(props) => props.theme.colors.layers[2].background} !important;
|
|
2030
|
+
|
|
2031
|
+
&:focus {
|
|
2032
|
+
outline: none !important;
|
|
2033
|
+
border-color: ${(props) => props.theme.colors.palette.primary.normal} !important;
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
&::placeholder {
|
|
2037
|
+
color: ${(props) => props.theme.colors.content.detail} !important;
|
|
2038
|
+
font-size: ${(props) => props.theme.fontSizes.medium} !important;
|
|
2039
|
+
font-family: inherit !important;
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
|
|
2043
|
+
&:focus-within textarea {
|
|
2044
|
+
outline: none !important;
|
|
2045
|
+
border-color: ${(props) => props.theme.colors.palette.primary.normal} !important;
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
992
2048
|
`;
|
|
993
|
-
var Description =
|
|
2049
|
+
var Description = styled10.div`
|
|
994
2050
|
font-size: ${(props) => props.theme.fontSizes.small};
|
|
2051
|
+
color: ${(props) => props.theme.colors.content.text};
|
|
995
2052
|
margin-bottom: ${(props) => props.theme.spacing.components.medium};
|
|
996
2053
|
`;
|
|
997
|
-
var Title2 =
|
|
2054
|
+
var Title2 = styled10.span`
|
|
998
2055
|
display: block;
|
|
999
2056
|
font-weight: ${(props) => props.theme.fontFamily.montserrat.weights.bold};
|
|
2057
|
+
color: ${(props) => props.theme.colors.content.text};
|
|
1000
2058
|
margin-bottom: ${(props) => props.theme.spacing.components.small};
|
|
1001
2059
|
`;
|
|
1002
|
-
var Box =
|
|
2060
|
+
var Box = styled10(CardBase)`
|
|
1003
2061
|
width: 100%;
|
|
1004
2062
|
height: max-content;
|
|
1005
2063
|
padding: ${(props) => props.theme.spacing.components.medium};
|
|
1006
2064
|
transition: ${(props) => props.theme.transitionDurations.default};
|
|
1007
2065
|
`;
|
|
1008
|
-
var
|
|
2066
|
+
var Wrapper9 = styled10.div`
|
|
1009
2067
|
position: absolute;
|
|
1010
2068
|
z-index: 1;
|
|
1011
2069
|
left: 0;
|
|
@@ -1018,11 +2076,11 @@ var Wrapper8 = styled9.div`
|
|
|
1018
2076
|
padding: ${(props) => props.theme.spacing.components.medium};
|
|
1019
2077
|
transition: ${(props) => props.theme.transitionDurations.default};
|
|
1020
2078
|
|
|
1021
|
-
${(props) => props.$opened ?
|
|
2079
|
+
${(props) => props.$opened ? css5`
|
|
1022
2080
|
background-color: rgba(0, 0, 0, 0.15);
|
|
1023
2081
|
backdrop-filter: blur(3px);
|
|
1024
2082
|
opacity: 1;
|
|
1025
|
-
` :
|
|
2083
|
+
` : css5`
|
|
1026
2084
|
pointer-events: none;
|
|
1027
2085
|
opacity: 0;
|
|
1028
2086
|
|
|
@@ -1037,9 +2095,9 @@ var ChatUserFeedbackRating = /* @__PURE__ */ __name(({
|
|
|
1037
2095
|
chatFeedbackBox
|
|
1038
2096
|
}) => {
|
|
1039
2097
|
const chatbot = useChatbot_default();
|
|
1040
|
-
const [ratingValue, setRatingValue] =
|
|
1041
|
-
const [descriptionValue, setDescriptionValue] =
|
|
1042
|
-
const
|
|
2098
|
+
const [ratingValue, setRatingValue] = useState8(5);
|
|
2099
|
+
const [descriptionValue, setDescriptionValue] = useState8("");
|
|
2100
|
+
const texts = useChatbotTexts();
|
|
1043
2101
|
const handleSubmit = /* @__PURE__ */ __name((e) => {
|
|
1044
2102
|
e.preventDefault();
|
|
1045
2103
|
chatFeedbackBox.sendUserRating({
|
|
@@ -1047,35 +2105,36 @@ var ChatUserFeedbackRating = /* @__PURE__ */ __name(({
|
|
|
1047
2105
|
ratingScore: ratingValue
|
|
1048
2106
|
});
|
|
1049
2107
|
}, "handleSubmit");
|
|
1050
|
-
return /* @__PURE__ */
|
|
2108
|
+
return /* @__PURE__ */ React13.createElement(Wrapper9, { $opened: chatFeedbackBox.opened && chatbot.opened }, /* @__PURE__ */ React13.createElement(Box, null, /* @__PURE__ */ React13.createElement(Title2, null, texts.CHAT_FEEDBACK.TITLE), /* @__PURE__ */ React13.createElement(Description, null, texts.CHAT_FEEDBACK.DESCRIPTION), /* @__PURE__ */ React13.createElement(Form2, { onSubmit: handleSubmit }, /* @__PURE__ */ React13.createElement(
|
|
1051
2109
|
RatingStars,
|
|
1052
2110
|
{
|
|
1053
2111
|
value: ratingValue,
|
|
1054
2112
|
setValue: setRatingValue,
|
|
1055
2113
|
layer: 2
|
|
1056
2114
|
}
|
|
1057
|
-
), /* @__PURE__ */
|
|
2115
|
+
), /* @__PURE__ */ React13.createElement(
|
|
1058
2116
|
TextArea2,
|
|
1059
2117
|
{
|
|
1060
2118
|
layer: 2,
|
|
1061
|
-
placeholder:
|
|
2119
|
+
placeholder: texts.CHAT_FEEDBACK.MESSAGE_FIELD,
|
|
1062
2120
|
fillWidth: true,
|
|
1063
2121
|
value: descriptionValue,
|
|
1064
|
-
onChange: (e) => setDescriptionValue(e.target.value)
|
|
2122
|
+
onChange: (e) => setDescriptionValue(e.target.value),
|
|
2123
|
+
className: "feedbackTextarea"
|
|
1065
2124
|
}
|
|
1066
|
-
), /* @__PURE__ */
|
|
2125
|
+
), /* @__PURE__ */ React13.createElement(ActionButtons, null, /* @__PURE__ */ React13.createElement(
|
|
1067
2126
|
Button4,
|
|
1068
2127
|
{
|
|
1069
2128
|
onClick: chatFeedbackBox.close,
|
|
1070
|
-
label:
|
|
2129
|
+
label: texts.CHAT_FEEDBACK.CLOSE_BUTTON,
|
|
1071
2130
|
size: "small",
|
|
1072
2131
|
variant: "layerBased"
|
|
1073
2132
|
}
|
|
1074
|
-
), /* @__PURE__ */
|
|
2133
|
+
), /* @__PURE__ */ React13.createElement(
|
|
1075
2134
|
Button4,
|
|
1076
2135
|
{
|
|
1077
2136
|
type: "submit",
|
|
1078
|
-
label:
|
|
2137
|
+
label: texts.CHAT_FEEDBACK.SUBMIT_BUTTON,
|
|
1079
2138
|
size: "small",
|
|
1080
2139
|
loading: chatFeedbackBox.loading
|
|
1081
2140
|
}
|
|
@@ -1083,15 +2142,12 @@ var ChatUserFeedbackRating = /* @__PURE__ */ __name(({
|
|
|
1083
2142
|
}, "ChatUserFeedbackRating");
|
|
1084
2143
|
|
|
1085
2144
|
// src/contexts/Chatbot/useChatFeedbackBox.ts
|
|
1086
|
-
import {
|
|
2145
|
+
import { useState as useState9 } from "react";
|
|
1087
2146
|
var useChatFeedbackBox = /* @__PURE__ */ __name(() => {
|
|
1088
2147
|
const { chatMessages, apiURL, locale } = useChatbot_default();
|
|
1089
|
-
const [rated, setRated] =
|
|
1090
|
-
const [opened, setOpened] =
|
|
1091
|
-
const [loading, setLoading] =
|
|
1092
|
-
useEffect6(() => {
|
|
1093
|
-
if (chatMessages.length > 6 && !rated) setOpened(true);
|
|
1094
|
-
}, [chatMessages]);
|
|
2148
|
+
const [rated, setRated] = useState9(false);
|
|
2149
|
+
const [opened, setOpened] = useState9(false);
|
|
2150
|
+
const [loading, setLoading] = useState9(false);
|
|
1095
2151
|
const open = /* @__PURE__ */ __name(() => {
|
|
1096
2152
|
setOpened(true);
|
|
1097
2153
|
}, "open");
|
|
@@ -1131,42 +2187,93 @@ var useChatFeedbackBox = /* @__PURE__ */ __name(() => {
|
|
|
1131
2187
|
}, "useChatFeedbackBox");
|
|
1132
2188
|
|
|
1133
2189
|
// src/components/ChatbotDevice/index.tsx
|
|
1134
|
-
var ChatbotDevice = /* @__PURE__ */ __name(({
|
|
2190
|
+
var ChatbotDevice = /* @__PURE__ */ __name(({
|
|
2191
|
+
verticalPosition = "bottom"
|
|
2192
|
+
}) => {
|
|
1135
2193
|
const { opened } = useChatbot_default();
|
|
1136
2194
|
const chatFeedbackBox = useChatFeedbackBox();
|
|
1137
|
-
return /* @__PURE__ */
|
|
2195
|
+
return /* @__PURE__ */ React14.createElement(Wrapper, { $opened: opened, $verticalPosition: verticalPosition }, /* @__PURE__ */ React14.createElement(ChatUserFeedbackRating, { chatFeedbackBox }), /* @__PURE__ */ React14.createElement(ChatbotHeader_default, { chatFeedbackBox }), /* @__PURE__ */ React14.createElement(ChatbotBody_default, null), /* @__PURE__ */ React14.createElement(ChatbotFooter_default, null), /* @__PURE__ */ React14.createElement(ChatbotToggle_default, { verticalPosition, opened }));
|
|
1138
2196
|
}, "ChatbotDevice");
|
|
1139
2197
|
var ChatbotDevice_default = ChatbotDevice;
|
|
1140
2198
|
|
|
1141
2199
|
// src/components/ChatbotBar/styles.ts
|
|
1142
2200
|
import { breakpoints as breakpoints3, screens as screens3 } from "@ibti-tech/ui";
|
|
1143
2201
|
import { Container } from "@ibti-tech/ui/dist/components/Container";
|
|
1144
|
-
import { styled as
|
|
1145
|
-
var BarContainer =
|
|
2202
|
+
import { css as css6, styled as styled11 } from "styled-components";
|
|
2203
|
+
var BarContainer = styled11(Container)`
|
|
1146
2204
|
@media screen and (max-width: ${breakpoints3.tablet}px) {
|
|
1147
2205
|
padding: 0;
|
|
1148
2206
|
}
|
|
1149
2207
|
|
|
1150
2208
|
${screens3.tablet} {
|
|
1151
2209
|
display: flex;
|
|
1152
|
-
justify-content: flex-end;
|
|
2210
|
+
justify-content: ${(props) => props.$horizontalPosition === "right" ? "flex-end" : "flex-start"};
|
|
2211
|
+
|
|
2212
|
+
${(props) => !props.$opened && props.$verticalPosition === "bottom" ? css6`
|
|
2213
|
+
width: ${breakpoints3.mobileL}px;
|
|
2214
|
+
max-width: ${breakpoints3.mobileL}px;
|
|
2215
|
+
min-width: ${breakpoints3.mobileL}px;
|
|
2216
|
+
padding-left: 0;
|
|
2217
|
+
` : ""}
|
|
1153
2218
|
}
|
|
1154
2219
|
`;
|
|
1155
|
-
var
|
|
2220
|
+
var Wrapper10 = styled11.div`
|
|
2221
|
+
position: fixed;
|
|
1156
2222
|
width: 100%;
|
|
1157
|
-
padding-bottom: ${(props) => props.theme.spacing.components.xsmall};
|
|
1158
|
-
background-color: ${(props) => props.theme.colors.layers[0].background};
|
|
1159
|
-
border-bottom: 1px solid ${(props) => props.theme.colors.layers[0].border};
|
|
1160
|
-
height: 40px;
|
|
1161
|
-
z-index: 2;
|
|
1162
|
-
pointer-events: none;
|
|
1163
2223
|
z-index: ${(props) => props.theme.zIndex.modals};
|
|
2224
|
+
pointer-events: none;
|
|
2225
|
+
|
|
2226
|
+
${(props) => props.$verticalPosition === "top" ? css6`
|
|
2227
|
+
top: 0;
|
|
2228
|
+
padding-top: ${(props2) => props2.theme.spacing.components.xsmall};
|
|
2229
|
+
` : css6`
|
|
2230
|
+
bottom: 0;
|
|
2231
|
+
padding-bottom: ${(props2) => props2.theme.spacing.components.xsmall};
|
|
2232
|
+
|
|
2233
|
+
@media screen and (max-width: ${breakpoints3.tablet}px) {
|
|
2234
|
+
${props.$opened ? css6`
|
|
2235
|
+
padding-bottom: 0;
|
|
2236
|
+
` : ""}
|
|
2237
|
+
}
|
|
2238
|
+
`}
|
|
2239
|
+
|
|
2240
|
+
${screens3.tablet} {
|
|
2241
|
+
width: auto;
|
|
2242
|
+
background-color: transparent;
|
|
2243
|
+
border: none;
|
|
2244
|
+
padding: 0;
|
|
2245
|
+
${(props) => props.$horizontalPosition === "right" ? css6`
|
|
2246
|
+
right: ${(props2) => props2.theme.spacing.components.medium};
|
|
2247
|
+
` : css6`
|
|
2248
|
+
left: ${(props2) => props2.theme.spacing.components.medium};
|
|
2249
|
+
`}
|
|
2250
|
+
}
|
|
1164
2251
|
`;
|
|
1165
2252
|
|
|
1166
2253
|
// src/components/ChatbotBar/index.tsx
|
|
1167
|
-
import
|
|
1168
|
-
var ChatbotBar = /* @__PURE__ */ __name((
|
|
1169
|
-
|
|
2254
|
+
import React15 from "react";
|
|
2255
|
+
var ChatbotBar = /* @__PURE__ */ __name(({
|
|
2256
|
+
verticalPosition = "bottom",
|
|
2257
|
+
horizontalPosition = "right"
|
|
2258
|
+
}) => {
|
|
2259
|
+
const { opened } = useChatbot_default();
|
|
2260
|
+
return /* @__PURE__ */ React15.createElement(
|
|
2261
|
+
Wrapper10,
|
|
2262
|
+
{
|
|
2263
|
+
$verticalPosition: verticalPosition,
|
|
2264
|
+
$horizontalPosition: horizontalPosition,
|
|
2265
|
+
$opened: opened
|
|
2266
|
+
},
|
|
2267
|
+
/* @__PURE__ */ React15.createElement(
|
|
2268
|
+
BarContainer,
|
|
2269
|
+
{
|
|
2270
|
+
$horizontalPosition: horizontalPosition,
|
|
2271
|
+
$opened: opened,
|
|
2272
|
+
$verticalPosition: verticalPosition
|
|
2273
|
+
},
|
|
2274
|
+
/* @__PURE__ */ React15.createElement(ChatbotDevice_default, { verticalPosition })
|
|
2275
|
+
)
|
|
2276
|
+
);
|
|
1170
2277
|
}, "ChatbotBar");
|
|
1171
2278
|
export {
|
|
1172
2279
|
ChatbotBar,
|