@eshal-bot/chat-widget 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +99 -0
- package/dist/chat-widget.css +853 -0
- package/dist/chat-widget.css.map +1 -0
- package/dist/chat-widget.esm.js +918 -0
- package/dist/chat-widget.esm.js.map +1 -0
- package/dist/chat-widget.js +35757 -0
- package/dist/chat-widget.js.map +1 -0
- package/dist/chat-widget.standalone.css +853 -0
- package/dist/chat-widget.standalone.css.map +1 -0
- package/dist/chat-widget.umd.js +923 -0
- package/dist/chat-widget.umd.js.map +1 -0
- package/dist/index.d.ts +79 -0
- package/package.json +76 -0
|
@@ -0,0 +1,918 @@
|
|
|
1
|
+
import { useState, useRef, useEffect, forwardRef, createElement } from 'react';
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
function _defineProperty(e, r, t) {
|
|
5
|
+
return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
6
|
+
value: t,
|
|
7
|
+
enumerable: !0,
|
|
8
|
+
configurable: !0,
|
|
9
|
+
writable: !0
|
|
10
|
+
}) : e[r] = t, e;
|
|
11
|
+
}
|
|
12
|
+
function ownKeys(e, r) {
|
|
13
|
+
var t = Object.keys(e);
|
|
14
|
+
if (Object.getOwnPropertySymbols) {
|
|
15
|
+
var o = Object.getOwnPropertySymbols(e);
|
|
16
|
+
r && (o = o.filter(function (r) {
|
|
17
|
+
return Object.getOwnPropertyDescriptor(e, r).enumerable;
|
|
18
|
+
})), t.push.apply(t, o);
|
|
19
|
+
}
|
|
20
|
+
return t;
|
|
21
|
+
}
|
|
22
|
+
function _objectSpread2(e) {
|
|
23
|
+
for (var r = 1; r < arguments.length; r++) {
|
|
24
|
+
var t = null != arguments[r] ? arguments[r] : {};
|
|
25
|
+
r % 2 ? ownKeys(Object(t), !0).forEach(function (r) {
|
|
26
|
+
_defineProperty(e, r, t[r]);
|
|
27
|
+
}) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) {
|
|
28
|
+
Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r));
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
return e;
|
|
32
|
+
}
|
|
33
|
+
function _toPrimitive(t, r) {
|
|
34
|
+
if ("object" != typeof t || !t) return t;
|
|
35
|
+
var e = t[Symbol.toPrimitive];
|
|
36
|
+
if (void 0 !== e) {
|
|
37
|
+
var i = e.call(t, r || "default");
|
|
38
|
+
if ("object" != typeof i) return i;
|
|
39
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
40
|
+
}
|
|
41
|
+
return ("string" === r ? String : Number)(t);
|
|
42
|
+
}
|
|
43
|
+
function _toPropertyKey(t) {
|
|
44
|
+
var i = _toPrimitive(t, "string");
|
|
45
|
+
return "symbol" == typeof i ? i : i + "";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Stream a support reply via Server-Sent Events
|
|
50
|
+
* Expects backend to emit JSON SSE events like:
|
|
51
|
+
* {"type":"processing_start", ...} | {"type":"text_chunk","content":"..."} | {"type":"complete", ...}
|
|
52
|
+
* Falls back to raw text if not JSON.
|
|
53
|
+
*/
|
|
54
|
+
const streamSupportReply = async _ref => {
|
|
55
|
+
let {
|
|
56
|
+
apiBaseUrl,
|
|
57
|
+
query,
|
|
58
|
+
organizationId,
|
|
59
|
+
apiKey,
|
|
60
|
+
headers = {},
|
|
61
|
+
onProcessingStart,
|
|
62
|
+
onProcessingEnd,
|
|
63
|
+
onTextChunk,
|
|
64
|
+
onDone,
|
|
65
|
+
onError
|
|
66
|
+
} = _ref;
|
|
67
|
+
if (!apiBaseUrl) {
|
|
68
|
+
throw new Error("apiBaseUrl is required");
|
|
69
|
+
}
|
|
70
|
+
const controller = new AbortController();
|
|
71
|
+
const url = "".concat(apiBaseUrl.replace(/\/$/, ""), "/api/v1/widget/chat");
|
|
72
|
+
try {
|
|
73
|
+
const response = await fetch(url, {
|
|
74
|
+
method: "POST",
|
|
75
|
+
headers: _objectSpread2(_objectSpread2({
|
|
76
|
+
"Content-Type": "application/json",
|
|
77
|
+
"x-eshal-org": organizationId
|
|
78
|
+
}, apiKey && {
|
|
79
|
+
Authorization: "Bearer ".concat(apiKey)
|
|
80
|
+
}), headers),
|
|
81
|
+
body: JSON.stringify({
|
|
82
|
+
message: query
|
|
83
|
+
}),
|
|
84
|
+
signal: controller.signal,
|
|
85
|
+
credentials: "include"
|
|
86
|
+
});
|
|
87
|
+
if (!response.ok) {
|
|
88
|
+
throw new Error("HTTP error! status: ".concat(response.status));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Expect text/event-stream but some servers omit header while still streaming
|
|
92
|
+
const reader = response.body.getReader();
|
|
93
|
+
const decoder = new TextDecoder();
|
|
94
|
+
let buffer = "";
|
|
95
|
+
const pump = async () => {
|
|
96
|
+
while (true) {
|
|
97
|
+
const {
|
|
98
|
+
value,
|
|
99
|
+
done
|
|
100
|
+
} = await reader.read();
|
|
101
|
+
if (done) break;
|
|
102
|
+
buffer += decoder.decode(value, {
|
|
103
|
+
stream: true
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Parse SSE lines
|
|
107
|
+
let lineEnd;
|
|
108
|
+
while ((lineEnd = buffer.indexOf("\n")) !== -1) {
|
|
109
|
+
const line = buffer.slice(0, lineEnd).trim();
|
|
110
|
+
buffer = buffer.slice(lineEnd + 1);
|
|
111
|
+
if (!line) continue;
|
|
112
|
+
if (line.startsWith("data:")) {
|
|
113
|
+
const raw = line.slice(5).trim();
|
|
114
|
+
if (raw === "[DONE]") {
|
|
115
|
+
if (onDone) onDone();
|
|
116
|
+
controller.abort();
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
try {
|
|
120
|
+
const evt = JSON.parse(raw);
|
|
121
|
+
if (evt && evt.type === "processing_start") {
|
|
122
|
+
if (onProcessingStart) onProcessingStart(evt);
|
|
123
|
+
} else if (evt && evt.type === "processing_end") {
|
|
124
|
+
if (onProcessingEnd) onProcessingEnd(evt);
|
|
125
|
+
} else if (evt && evt.type === "text_chunk" && typeof evt.content === "string") {
|
|
126
|
+
if (onTextChunk) onTextChunk(evt.content, evt);
|
|
127
|
+
} else if (evt && evt.type === "complete") {
|
|
128
|
+
if (onDone) onDone(evt);
|
|
129
|
+
} else {
|
|
130
|
+
if (onTextChunk) onTextChunk(raw);
|
|
131
|
+
}
|
|
132
|
+
} catch (_) {
|
|
133
|
+
// Only treat as text chunk if it's not a known control message
|
|
134
|
+
if (raw !== "processing_end" && raw !== "processing_start") {
|
|
135
|
+
if (onTextChunk) onTextChunk(raw);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// Flush remaining buffer (non-SSE servers may just stream text)
|
|
142
|
+
if (buffer && onTextChunk) onTextChunk(buffer);
|
|
143
|
+
if (onDone) onDone();
|
|
144
|
+
};
|
|
145
|
+
pump().catch(err => {
|
|
146
|
+
if (onError) onError(err);
|
|
147
|
+
});
|
|
148
|
+
return controller;
|
|
149
|
+
} catch (error) {
|
|
150
|
+
if (onError) onError(error);
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
const useChatState = _ref => {
|
|
156
|
+
let {
|
|
157
|
+
welcomeMessage,
|
|
158
|
+
companyLogo,
|
|
159
|
+
quickQuestions,
|
|
160
|
+
apiBaseUrl,
|
|
161
|
+
organizationId,
|
|
162
|
+
autoOpen,
|
|
163
|
+
openDelay,
|
|
164
|
+
darkMode
|
|
165
|
+
} = _ref;
|
|
166
|
+
const [isOpen, setIsOpen] = useState(autoOpen);
|
|
167
|
+
const [isMinimized, setIsMinimized] = useState(false);
|
|
168
|
+
const [isDark, setIsDark] = useState(darkMode);
|
|
169
|
+
const [messages, setMessages] = useState([{
|
|
170
|
+
id: 1,
|
|
171
|
+
text: welcomeMessage,
|
|
172
|
+
sender: "bot",
|
|
173
|
+
timestamp: new Date(),
|
|
174
|
+
avatar: null
|
|
175
|
+
}]);
|
|
176
|
+
const [inputValue, setInputValue] = useState("");
|
|
177
|
+
const [isTyping, setIsTyping] = useState(false);
|
|
178
|
+
const widgetRef = useRef(null);
|
|
179
|
+
|
|
180
|
+
// Auto open with delay
|
|
181
|
+
useEffect(() => {
|
|
182
|
+
if (autoOpen && openDelay > 0) {
|
|
183
|
+
const timer = setTimeout(() => setIsOpen(true), openDelay);
|
|
184
|
+
return () => clearTimeout(timer);
|
|
185
|
+
}
|
|
186
|
+
}, [autoOpen, openDelay]);
|
|
187
|
+
|
|
188
|
+
// Sync dark mode prop
|
|
189
|
+
useEffect(() => {
|
|
190
|
+
setIsDark(darkMode);
|
|
191
|
+
}, [darkMode]);
|
|
192
|
+
const handleSend = async () => {
|
|
193
|
+
if (!inputValue.trim()) return;
|
|
194
|
+
const newMessage = {
|
|
195
|
+
id: messages.length + 1,
|
|
196
|
+
text: inputValue,
|
|
197
|
+
sender: "user",
|
|
198
|
+
timestamp: new Date()
|
|
199
|
+
};
|
|
200
|
+
setMessages([...messages, newMessage]);
|
|
201
|
+
const messageText = inputValue;
|
|
202
|
+
setInputValue("");
|
|
203
|
+
setIsTyping(true);
|
|
204
|
+
try {
|
|
205
|
+
// Create placeholder bot message for streaming
|
|
206
|
+
const botMessageId = messages.length + 2;
|
|
207
|
+
setMessages(prev => [...prev, {
|
|
208
|
+
id: botMessageId,
|
|
209
|
+
text: "",
|
|
210
|
+
sender: "bot",
|
|
211
|
+
timestamp: new Date(),
|
|
212
|
+
avatar: null
|
|
213
|
+
}]);
|
|
214
|
+
await streamSupportReply({
|
|
215
|
+
apiBaseUrl,
|
|
216
|
+
organizationId,
|
|
217
|
+
query: messageText,
|
|
218
|
+
onProcessingStart: () => {
|
|
219
|
+
setIsTyping(true);
|
|
220
|
+
},
|
|
221
|
+
onProcessingEnd: () => {
|
|
222
|
+
setIsTyping(true);
|
|
223
|
+
},
|
|
224
|
+
onTextChunk: chunk => {
|
|
225
|
+
if (isTyping) {
|
|
226
|
+
setIsTyping(false);
|
|
227
|
+
}
|
|
228
|
+
;
|
|
229
|
+
setMessages(prev => prev.map(m => m.id === botMessageId ? _objectSpread2(_objectSpread2({}, m), {}, {
|
|
230
|
+
text: (m.text || "") + chunk
|
|
231
|
+
}) : m));
|
|
232
|
+
},
|
|
233
|
+
onDone: () => {
|
|
234
|
+
setIsTyping(false);
|
|
235
|
+
},
|
|
236
|
+
onError: error => {
|
|
237
|
+
console.error("SSE error:", error);
|
|
238
|
+
setIsTyping(false);
|
|
239
|
+
setMessages(prev => prev.map(m => m.id === botMessageId ? _objectSpread2(_objectSpread2({}, m), {}, {
|
|
240
|
+
text: "Sorry, I'm having trouble connecting right now. Please try again."
|
|
241
|
+
}) : m));
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
} catch (error) {
|
|
245
|
+
setIsTyping(false);
|
|
246
|
+
console.error("Error:", error);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const toggleChat = () => {
|
|
250
|
+
setIsOpen(!isOpen);
|
|
251
|
+
setIsMinimized(false);
|
|
252
|
+
};
|
|
253
|
+
const toggleTheme = () => {
|
|
254
|
+
setIsDark(!isDark);
|
|
255
|
+
};
|
|
256
|
+
const toggleMinimize = () => {
|
|
257
|
+
setIsMinimized(!isMinimized);
|
|
258
|
+
};
|
|
259
|
+
const closeChat = () => {
|
|
260
|
+
setIsOpen(false);
|
|
261
|
+
};
|
|
262
|
+
const handleQuickQuestion = question => {
|
|
263
|
+
setInputValue(question);
|
|
264
|
+
handleSend();
|
|
265
|
+
};
|
|
266
|
+
return {
|
|
267
|
+
// State
|
|
268
|
+
isOpen,
|
|
269
|
+
isMinimized,
|
|
270
|
+
isDark,
|
|
271
|
+
messages,
|
|
272
|
+
inputValue,
|
|
273
|
+
isTyping,
|
|
274
|
+
widgetRef,
|
|
275
|
+
quickQuestions,
|
|
276
|
+
// Actions
|
|
277
|
+
setInputValue,
|
|
278
|
+
handleSend,
|
|
279
|
+
handleQuickQuestion,
|
|
280
|
+
toggleChat,
|
|
281
|
+
toggleTheme,
|
|
282
|
+
toggleMinimize,
|
|
283
|
+
closeChat
|
|
284
|
+
};
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* @license lucide-react v0.303.0 - ISC
|
|
289
|
+
*
|
|
290
|
+
* This source code is licensed under the ISC license.
|
|
291
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
292
|
+
*/
|
|
293
|
+
|
|
294
|
+
var defaultAttributes = {
|
|
295
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
296
|
+
width: 24,
|
|
297
|
+
height: 24,
|
|
298
|
+
viewBox: "0 0 24 24",
|
|
299
|
+
fill: "none",
|
|
300
|
+
stroke: "currentColor",
|
|
301
|
+
strokeWidth: 2,
|
|
302
|
+
strokeLinecap: "round",
|
|
303
|
+
strokeLinejoin: "round"
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* @license lucide-react v0.303.0 - ISC
|
|
308
|
+
*
|
|
309
|
+
* This source code is licensed under the ISC license.
|
|
310
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
311
|
+
*/
|
|
312
|
+
|
|
313
|
+
|
|
314
|
+
const toKebabCase = (string) => string.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase().trim();
|
|
315
|
+
const createLucideIcon = (iconName, iconNode) => {
|
|
316
|
+
const Component = forwardRef(
|
|
317
|
+
({ color = "currentColor", size = 24, strokeWidth = 2, absoluteStrokeWidth, className = "", children, ...rest }, ref) => createElement(
|
|
318
|
+
"svg",
|
|
319
|
+
{
|
|
320
|
+
ref,
|
|
321
|
+
...defaultAttributes,
|
|
322
|
+
width: size,
|
|
323
|
+
height: size,
|
|
324
|
+
stroke: color,
|
|
325
|
+
strokeWidth: absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth,
|
|
326
|
+
className: ["lucide", `lucide-${toKebabCase(iconName)}`, className].join(" "),
|
|
327
|
+
...rest
|
|
328
|
+
},
|
|
329
|
+
[
|
|
330
|
+
...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
|
|
331
|
+
...Array.isArray(children) ? children : [children]
|
|
332
|
+
]
|
|
333
|
+
)
|
|
334
|
+
);
|
|
335
|
+
Component.displayName = `${iconName}`;
|
|
336
|
+
return Component;
|
|
337
|
+
};
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* @license lucide-react v0.303.0 - ISC
|
|
341
|
+
*
|
|
342
|
+
* This source code is licensed under the ISC license.
|
|
343
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
344
|
+
*/
|
|
345
|
+
|
|
346
|
+
|
|
347
|
+
const Bot = createLucideIcon("Bot", [
|
|
348
|
+
["path", { d: "M12 8V4H8", key: "hb8ula" }],
|
|
349
|
+
["rect", { width: "16", height: "12", x: "4", y: "8", rx: "2", key: "enze0r" }],
|
|
350
|
+
["path", { d: "M2 14h2", key: "vft8re" }],
|
|
351
|
+
["path", { d: "M20 14h2", key: "4cs60a" }],
|
|
352
|
+
["path", { d: "M15 13v2", key: "1xurst" }],
|
|
353
|
+
["path", { d: "M9 13v2", key: "rq6x2g" }]
|
|
354
|
+
]);
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* @license lucide-react v0.303.0 - ISC
|
|
358
|
+
*
|
|
359
|
+
* This source code is licensed under the ISC license.
|
|
360
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
361
|
+
*/
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
const MessageCircle = createLucideIcon("MessageCircle", [
|
|
365
|
+
["path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z", key: "vv11sd" }]
|
|
366
|
+
]);
|
|
367
|
+
|
|
368
|
+
/**
|
|
369
|
+
* @license lucide-react v0.303.0 - ISC
|
|
370
|
+
*
|
|
371
|
+
* This source code is licensed under the ISC license.
|
|
372
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
373
|
+
*/
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
const Minimize2 = createLucideIcon("Minimize2", [
|
|
377
|
+
["polyline", { points: "4 14 10 14 10 20", key: "11kfnr" }],
|
|
378
|
+
["polyline", { points: "20 10 14 10 14 4", key: "rlmsce" }],
|
|
379
|
+
["line", { x1: "14", x2: "21", y1: "10", y2: "3", key: "o5lafz" }],
|
|
380
|
+
["line", { x1: "3", x2: "10", y1: "21", y2: "14", key: "1atl0r" }]
|
|
381
|
+
]);
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* @license lucide-react v0.303.0 - ISC
|
|
385
|
+
*
|
|
386
|
+
* This source code is licensed under the ISC license.
|
|
387
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
388
|
+
*/
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
const Moon = createLucideIcon("Moon", [
|
|
392
|
+
["path", { d: "M12 3a6 6 0 0 0 9 9 9 9 0 1 1-9-9Z", key: "a7tn18" }]
|
|
393
|
+
]);
|
|
394
|
+
|
|
395
|
+
/**
|
|
396
|
+
* @license lucide-react v0.303.0 - ISC
|
|
397
|
+
*
|
|
398
|
+
* This source code is licensed under the ISC license.
|
|
399
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
400
|
+
*/
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
const Send = createLucideIcon("Send", [
|
|
404
|
+
["path", { d: "m22 2-7 20-4-9-9-4Z", key: "1q3vgg" }],
|
|
405
|
+
["path", { d: "M22 2 11 13", key: "nzbqef" }]
|
|
406
|
+
]);
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* @license lucide-react v0.303.0 - ISC
|
|
410
|
+
*
|
|
411
|
+
* This source code is licensed under the ISC license.
|
|
412
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
413
|
+
*/
|
|
414
|
+
|
|
415
|
+
|
|
416
|
+
const Sun = createLucideIcon("Sun", [
|
|
417
|
+
["circle", { cx: "12", cy: "12", r: "4", key: "4exip2" }],
|
|
418
|
+
["path", { d: "M12 2v2", key: "tus03m" }],
|
|
419
|
+
["path", { d: "M12 20v2", key: "1lh1kg" }],
|
|
420
|
+
["path", { d: "m4.93 4.93 1.41 1.41", key: "149t6j" }],
|
|
421
|
+
["path", { d: "m17.66 17.66 1.41 1.41", key: "ptbguv" }],
|
|
422
|
+
["path", { d: "M2 12h2", key: "1t8f8n" }],
|
|
423
|
+
["path", { d: "M20 12h2", key: "1q8mjw" }],
|
|
424
|
+
["path", { d: "m6.34 17.66-1.41 1.41", key: "1m8zz5" }],
|
|
425
|
+
["path", { d: "m19.07 4.93-1.41 1.41", key: "1shlcs" }]
|
|
426
|
+
]);
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* @license lucide-react v0.303.0 - ISC
|
|
430
|
+
*
|
|
431
|
+
* This source code is licensed under the ISC license.
|
|
432
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
433
|
+
*/
|
|
434
|
+
|
|
435
|
+
|
|
436
|
+
const User = createLucideIcon("User", [
|
|
437
|
+
["path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2", key: "975kel" }],
|
|
438
|
+
["circle", { cx: "12", cy: "7", r: "4", key: "17ys0d" }]
|
|
439
|
+
]);
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* @license lucide-react v0.303.0 - ISC
|
|
443
|
+
*
|
|
444
|
+
* This source code is licensed under the ISC license.
|
|
445
|
+
* See the LICENSE file in the root directory of this source tree.
|
|
446
|
+
*/
|
|
447
|
+
|
|
448
|
+
|
|
449
|
+
const X = createLucideIcon("X", [
|
|
450
|
+
["path", { d: "M18 6 6 18", key: "1bl5f8" }],
|
|
451
|
+
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
452
|
+
]);
|
|
453
|
+
|
|
454
|
+
const ChatHeader = _ref => {
|
|
455
|
+
let {
|
|
456
|
+
companyName,
|
|
457
|
+
companyLogo,
|
|
458
|
+
primaryColor,
|
|
459
|
+
isDark,
|
|
460
|
+
onToggleTheme,
|
|
461
|
+
onMinimize,
|
|
462
|
+
onClose
|
|
463
|
+
} = _ref;
|
|
464
|
+
return /*#__PURE__*/jsxs("div", {
|
|
465
|
+
className: "text-white px-5 py-4 flex items-center justify-between relative overflow-hidden",
|
|
466
|
+
style: {
|
|
467
|
+
background: "linear-gradient(135deg, ".concat(primaryColor, " 0%, ").concat(primaryColor, "dd 100%)")
|
|
468
|
+
},
|
|
469
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
470
|
+
className: "absolute inset-0 bg-gradient-to-br from-white/10 to-transparent pointer-events-none"
|
|
471
|
+
}), /*#__PURE__*/jsxs("div", {
|
|
472
|
+
className: "flex items-center gap-3 relative z-10",
|
|
473
|
+
children: [/*#__PURE__*/jsxs("div", {
|
|
474
|
+
className: "relative",
|
|
475
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
476
|
+
className: "w-11 h-11 rounded-xl flex items-center justify-center ".concat(companyLogo ? "bg-transparent" : "bg-white/20 backdrop-blur-sm"),
|
|
477
|
+
children: companyLogo ? /*#__PURE__*/jsx("img", {
|
|
478
|
+
src: companyLogo,
|
|
479
|
+
alt: "Logo",
|
|
480
|
+
className: "w-6 h-6 object-cover rounded"
|
|
481
|
+
}) : /*#__PURE__*/jsx(MessageCircle, {
|
|
482
|
+
className: "w-6 h-6"
|
|
483
|
+
})
|
|
484
|
+
}), /*#__PURE__*/jsx("div", {
|
|
485
|
+
className: "absolute -bottom-0.5 -right-0.5 w-3.5 h-3.5 bg-green-400 rounded-full border-2 border-white"
|
|
486
|
+
})]
|
|
487
|
+
}), /*#__PURE__*/jsxs("div", {
|
|
488
|
+
children: [/*#__PURE__*/jsx("h3", {
|
|
489
|
+
className: "font-semibold text-[15px] leading-tight",
|
|
490
|
+
children: companyName
|
|
491
|
+
}), /*#__PURE__*/jsxs("p", {
|
|
492
|
+
className: "text-xs text-white/90 flex items-center gap-1.5 mt-0.5",
|
|
493
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
494
|
+
className: "w-1.5 h-1.5 bg-green-400 rounded-full animate-pulse"
|
|
495
|
+
}), "Typically replies instantly"]
|
|
496
|
+
})]
|
|
497
|
+
})]
|
|
498
|
+
}), /*#__PURE__*/jsxs("div", {
|
|
499
|
+
className: "flex items-center gap-1 relative z-10",
|
|
500
|
+
children: [/*#__PURE__*/jsx("button", {
|
|
501
|
+
onClick: onToggleTheme,
|
|
502
|
+
className: "hover:bg-white/20 p-2 rounded-lg transition-all duration-200",
|
|
503
|
+
"aria-label": "Toggle theme",
|
|
504
|
+
children: isDark ? /*#__PURE__*/jsx(Sun, {
|
|
505
|
+
className: "w-4 h-4"
|
|
506
|
+
}) : /*#__PURE__*/jsx(Moon, {
|
|
507
|
+
className: "w-4 h-4"
|
|
508
|
+
})
|
|
509
|
+
}), /*#__PURE__*/jsx("button", {
|
|
510
|
+
onClick: onMinimize,
|
|
511
|
+
className: "hover:bg-white/20 p-2 rounded-lg transition-all duration-200",
|
|
512
|
+
"aria-label": "Minimize",
|
|
513
|
+
children: /*#__PURE__*/jsx(Minimize2, {
|
|
514
|
+
className: "w-4 h-4"
|
|
515
|
+
})
|
|
516
|
+
}), /*#__PURE__*/jsx("button", {
|
|
517
|
+
onClick: onClose,
|
|
518
|
+
className: "hover:bg-white/20 p-2 rounded-lg transition-all duration-200",
|
|
519
|
+
"aria-label": "Close",
|
|
520
|
+
children: /*#__PURE__*/jsx(X, {
|
|
521
|
+
className: "w-4 h-4"
|
|
522
|
+
})
|
|
523
|
+
})]
|
|
524
|
+
})]
|
|
525
|
+
});
|
|
526
|
+
};
|
|
527
|
+
|
|
528
|
+
const MessageBubble = _ref => {
|
|
529
|
+
let {
|
|
530
|
+
message,
|
|
531
|
+
isDark,
|
|
532
|
+
primaryColor,
|
|
533
|
+
isTyping,
|
|
534
|
+
companyLogo
|
|
535
|
+
} = _ref;
|
|
536
|
+
const isUser = message.sender === "user";
|
|
537
|
+
const isBot = message.sender === "bot";
|
|
538
|
+
const isTypingMessage = isBot && isTyping && (!message.text || message.text.length === 0);
|
|
539
|
+
return /*#__PURE__*/jsxs("div", {
|
|
540
|
+
className: "flex gap-3 ".concat(isUser ? "flex-row-reverse" : "flex-row", " animate-in"),
|
|
541
|
+
children: [isBot && /*#__PURE__*/jsx("div", {
|
|
542
|
+
className: "flex-shrink-0 mt-1",
|
|
543
|
+
children: message.avatar ? /*#__PURE__*/jsx("img", {
|
|
544
|
+
src: message.avatar,
|
|
545
|
+
alt: "Bot",
|
|
546
|
+
className: "w-8 h-8 rounded-full object-cover"
|
|
547
|
+
}) : /*#__PURE__*/jsx("div", {
|
|
548
|
+
className: "w-8 h-8 rounded-full flex items-center justify-center ".concat(isDark ? "bg-gray-700" : "bg-gray-200"),
|
|
549
|
+
children: /*#__PURE__*/jsx(Bot, {
|
|
550
|
+
className: "w-4 h-4",
|
|
551
|
+
style: {
|
|
552
|
+
color: primaryColor
|
|
553
|
+
}
|
|
554
|
+
})
|
|
555
|
+
})
|
|
556
|
+
}), /*#__PURE__*/jsxs("div", {
|
|
557
|
+
className: "flex flex-col ".concat(isUser ? "items-end" : "items-start", " max-w-[75%]"),
|
|
558
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
559
|
+
className: "rounded-2xl px-4 py-2.5 ".concat(isUser ? "text-white shadow-lg" : "".concat(isDark ? "bg-gray-800 text-gray-100 border-gray-700" : "bg-white text-gray-800 border-gray-200", " shadow-sm border"), " ").concat(isUser ? "rounded-tr-sm" : "rounded-tl-sm"),
|
|
560
|
+
style: isUser ? {
|
|
561
|
+
background: "linear-gradient(135deg, ".concat(primaryColor, " 0%, ").concat(primaryColor, "dd 100%)")
|
|
562
|
+
} : {},
|
|
563
|
+
children: isTypingMessage ? /*#__PURE__*/jsxs("div", {
|
|
564
|
+
className: "flex gap-1.5",
|
|
565
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
566
|
+
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
567
|
+
style: {
|
|
568
|
+
animationDelay: "0ms"
|
|
569
|
+
}
|
|
570
|
+
}), /*#__PURE__*/jsx("div", {
|
|
571
|
+
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
572
|
+
style: {
|
|
573
|
+
animationDelay: "150ms"
|
|
574
|
+
}
|
|
575
|
+
}), /*#__PURE__*/jsx("div", {
|
|
576
|
+
className: "w-2 h-2 rounded-full bg-gray-400 animate-bounce",
|
|
577
|
+
style: {
|
|
578
|
+
animationDelay: "300ms"
|
|
579
|
+
}
|
|
580
|
+
})]
|
|
581
|
+
}) : /*#__PURE__*/jsx("p", {
|
|
582
|
+
className: "text-[14px] leading-relaxed whitespace-pre-wrap break-words ".concat(isUser ? "text-white" : isDark ? "text-gray-100" : "text-gray-800"),
|
|
583
|
+
children: message.text
|
|
584
|
+
})
|
|
585
|
+
}), /*#__PURE__*/jsx("p", {
|
|
586
|
+
className: "text-[11px] mt-1.5 px-1 ".concat(isDark ? "text-gray-500" : "text-gray-400"),
|
|
587
|
+
children: message.timestamp.toLocaleTimeString([], {
|
|
588
|
+
hour: "2-digit",
|
|
589
|
+
minute: "2-digit"
|
|
590
|
+
})
|
|
591
|
+
})]
|
|
592
|
+
}), isUser && /*#__PURE__*/jsx("div", {
|
|
593
|
+
className: "flex-shrink-0 mt-1",
|
|
594
|
+
children: /*#__PURE__*/jsx("div", {
|
|
595
|
+
className: "w-8 h-8 rounded-full flex items-center justify-center ".concat(isDark ? "bg-gray-700" : "bg-gray-200"),
|
|
596
|
+
children: /*#__PURE__*/jsx(User, {
|
|
597
|
+
className: "w-4 h-4 text-gray-500"
|
|
598
|
+
})
|
|
599
|
+
})
|
|
600
|
+
})]
|
|
601
|
+
});
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
const MessageList = _ref => {
|
|
605
|
+
let {
|
|
606
|
+
messages,
|
|
607
|
+
isDark,
|
|
608
|
+
primaryColor,
|
|
609
|
+
isTyping,
|
|
610
|
+
companyLogo
|
|
611
|
+
} = _ref;
|
|
612
|
+
const messagesEndRef = useRef(null);
|
|
613
|
+
const scrollToBottom = () => {
|
|
614
|
+
var _messagesEndRef$curre;
|
|
615
|
+
(_messagesEndRef$curre = messagesEndRef.current) === null || _messagesEndRef$curre === void 0 || _messagesEndRef$curre.scrollIntoView({
|
|
616
|
+
behavior: "smooth"
|
|
617
|
+
});
|
|
618
|
+
};
|
|
619
|
+
useEffect(() => {
|
|
620
|
+
scrollToBottom();
|
|
621
|
+
}, [messages, isTyping]);
|
|
622
|
+
return /*#__PURE__*/jsxs("div", {
|
|
623
|
+
className: "chat-messages flex-1 overflow-y-auto px-5 py-4 space-y-4 ".concat(isDark ? "bg-gray-900" : "bg-gradient-to-b from-gray-50/50 to-white", " break-words"),
|
|
624
|
+
children: [messages.map(message => /*#__PURE__*/jsx(MessageBubble, {
|
|
625
|
+
message: message,
|
|
626
|
+
isDark: isDark,
|
|
627
|
+
primaryColor: primaryColor,
|
|
628
|
+
isTyping: isTyping,
|
|
629
|
+
companyLogo: companyLogo
|
|
630
|
+
}, message.id)), /*#__PURE__*/jsx("div", {
|
|
631
|
+
ref: messagesEndRef
|
|
632
|
+
})]
|
|
633
|
+
});
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
const ChatInput = _ref => {
|
|
637
|
+
let {
|
|
638
|
+
inputValue,
|
|
639
|
+
setInputValue,
|
|
640
|
+
onSend,
|
|
641
|
+
isDark,
|
|
642
|
+
primaryColor,
|
|
643
|
+
isOpen,
|
|
644
|
+
isMinimized
|
|
645
|
+
} = _ref;
|
|
646
|
+
const inputRef = useRef(null);
|
|
647
|
+
useEffect(() => {
|
|
648
|
+
if (isOpen && !isMinimized) {
|
|
649
|
+
var _inputRef$current;
|
|
650
|
+
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
|
|
651
|
+
}
|
|
652
|
+
}, [isOpen, isMinimized]);
|
|
653
|
+
const handleKeyPress = e => {
|
|
654
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
655
|
+
e.preventDefault();
|
|
656
|
+
onSend();
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
return /*#__PURE__*/jsxs("div", {
|
|
660
|
+
className: "px-5 py-4 border-t ".concat(isDark ? "border-gray-700 bg-gray-900" : "border-gray-200 bg-white"),
|
|
661
|
+
children: [/*#__PURE__*/jsxs("div", {
|
|
662
|
+
className: "flex gap-2.5 items-end",
|
|
663
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
664
|
+
className: "flex-1 flex items-center min-h-[48px] ".concat(isDark ? "bg-gray-800" : "bg-gray-50", " rounded-2xl border transition-all duration-200"),
|
|
665
|
+
style: {
|
|
666
|
+
borderColor: inputValue ? primaryColor : isDark ? "#374151" : "#e5e7eb",
|
|
667
|
+
borderWidth: inputValue ? "2px" : "1px"
|
|
668
|
+
},
|
|
669
|
+
children: /*#__PURE__*/jsx("textarea", {
|
|
670
|
+
id: "chat-widget-input",
|
|
671
|
+
ref: inputRef,
|
|
672
|
+
value: inputValue,
|
|
673
|
+
onChange: e => setInputValue(e.target.value),
|
|
674
|
+
onKeyDown: handleKeyPress,
|
|
675
|
+
placeholder: "Type your message...",
|
|
676
|
+
rows: "1",
|
|
677
|
+
className: "w-full px-4 py-0 bg-transparent rounded-xl leading-normal ".concat(isDark ? "text-gray-100" : "text-gray-900", " placeholder-gray-400 text-[14px] resize-none outline-none"),
|
|
678
|
+
style: {
|
|
679
|
+
maxHeight: "120px"
|
|
680
|
+
}
|
|
681
|
+
})
|
|
682
|
+
}), /*#__PURE__*/jsx("button", {
|
|
683
|
+
onClick: onSend,
|
|
684
|
+
disabled: !inputValue.trim(),
|
|
685
|
+
className: "h-12 w-12 p-0 rounded-xl transition-all duration-200 flex items-center justify-center shadow-lg disabled:opacity-40 disabled:cursor-not-allowed disabled:shadow-none ".concat(inputValue.trim() ? "scale-100" : "scale-95"),
|
|
686
|
+
style: {
|
|
687
|
+
backgroundColor: inputValue.trim() ? primaryColor : isDark ? "#374151" : "#e5e7eb",
|
|
688
|
+
color: inputValue.trim() ? "white" : "#9ca3af"
|
|
689
|
+
},
|
|
690
|
+
"aria-label": "Send message",
|
|
691
|
+
children: /*#__PURE__*/jsx(Send, {
|
|
692
|
+
className: "w-5 h-5"
|
|
693
|
+
})
|
|
694
|
+
})]
|
|
695
|
+
}), /*#__PURE__*/jsxs("p", {
|
|
696
|
+
className: "text-[11px] mt-2 px-1 ".concat(isDark ? "text-gray-600" : "text-gray-400", " flex items-center gap-1"),
|
|
697
|
+
children: [/*#__PURE__*/jsx("span", {
|
|
698
|
+
className: "w-1 h-1 rounded-full bg-green-500"
|
|
699
|
+
}), "We're online now"]
|
|
700
|
+
})]
|
|
701
|
+
});
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
const QuickQuestions = _ref => {
|
|
705
|
+
let {
|
|
706
|
+
questions = [],
|
|
707
|
+
isDark,
|
|
708
|
+
primaryColor,
|
|
709
|
+
onQuestionClick,
|
|
710
|
+
isTyping = false
|
|
711
|
+
} = _ref;
|
|
712
|
+
// Don't render if no questions or if typing/streaming
|
|
713
|
+
if (!questions.length || isTyping) {
|
|
714
|
+
return null;
|
|
715
|
+
}
|
|
716
|
+
return /*#__PURE__*/jsxs("div", {
|
|
717
|
+
className: "px-4 py-3 border-t border-gray-200 dark:border-gray-700",
|
|
718
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
719
|
+
className: "text-xs text-gray-500 dark:text-gray-400 mb-2 font-medium",
|
|
720
|
+
children: "Quick questions:"
|
|
721
|
+
}), /*#__PURE__*/jsx("div", {
|
|
722
|
+
className: "flex gap-2 overflow-x-auto scrollbar-hide pb-1",
|
|
723
|
+
children: questions.map((question, index) => /*#__PURE__*/jsx("button", {
|
|
724
|
+
onClick: () => onQuestionClick(question),
|
|
725
|
+
className: "text-xs px-4 py-2 rounded-lg border-2 font-medium transition-all duration-200 hover:scale-105 active:scale-95 whitespace-nowrap flex-shrink-0 shadow-sm",
|
|
726
|
+
style: {
|
|
727
|
+
backgroundColor: isDark ? "rgba(59, 130, 246, 0.15)" : "rgba(59, 130, 246, 0.08)",
|
|
728
|
+
borderColor: isDark ? "rgba(59, 130, 246, 0.4)" : "rgba(59, 130, 246, 0.3)",
|
|
729
|
+
color: isDark ? "rgba(147, 197, 253, 0.95)" : "rgba(30, 64, 175, 0.9)"
|
|
730
|
+
},
|
|
731
|
+
onMouseEnter: e => {
|
|
732
|
+
e.target.style.backgroundColor = isDark ? "rgba(59, 130, 246, 0.25)" : "rgba(59, 130, 246, 0.15)";
|
|
733
|
+
e.target.style.borderColor = isDark ? "rgba(59, 130, 246, 0.6)" : "rgba(59, 130, 246, 0.5)";
|
|
734
|
+
},
|
|
735
|
+
onMouseLeave: e => {
|
|
736
|
+
e.target.style.backgroundColor = isDark ? "rgba(59, 130, 246, 0.15)" : "rgba(59, 130, 246, 0.08)";
|
|
737
|
+
e.target.style.borderColor = isDark ? "rgba(59, 130, 246, 0.4)" : "rgba(59, 130, 246, 0.3)";
|
|
738
|
+
},
|
|
739
|
+
children: question
|
|
740
|
+
}, index))
|
|
741
|
+
})]
|
|
742
|
+
});
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
const ChatWindow = _ref => {
|
|
746
|
+
let {
|
|
747
|
+
isOpen,
|
|
748
|
+
isMinimized,
|
|
749
|
+
isDark,
|
|
750
|
+
primaryColor,
|
|
751
|
+
companyName,
|
|
752
|
+
companyLogo,
|
|
753
|
+
messages,
|
|
754
|
+
isTyping,
|
|
755
|
+
inputValue,
|
|
756
|
+
setInputValue,
|
|
757
|
+
onSend,
|
|
758
|
+
onToggleTheme,
|
|
759
|
+
onMinimize,
|
|
760
|
+
onClose,
|
|
761
|
+
quickQuestions,
|
|
762
|
+
onQuickQuestion
|
|
763
|
+
} = _ref;
|
|
764
|
+
if (!isOpen) return null;
|
|
765
|
+
return /*#__PURE__*/jsxs("div", {
|
|
766
|
+
className: "mb-4 ".concat(isDark ? "bg-gray-900 border-gray-700" : "bg-white border-gray-200", " rounded-2xl shadow-2xl border transition-all duration-300 ").concat(isMinimized ? "w-80 h-16" : "w-[380px] h-[650px]", " flex flex-col overflow-hidden"),
|
|
767
|
+
children: [/*#__PURE__*/jsx(ChatHeader, {
|
|
768
|
+
companyName: companyName,
|
|
769
|
+
companyLogo: companyLogo,
|
|
770
|
+
primaryColor: primaryColor,
|
|
771
|
+
isDark: isDark,
|
|
772
|
+
onToggleTheme: onToggleTheme,
|
|
773
|
+
onMinimize: onMinimize,
|
|
774
|
+
onClose: onClose
|
|
775
|
+
}), !isMinimized && /*#__PURE__*/jsxs(Fragment, {
|
|
776
|
+
children: [/*#__PURE__*/jsx(MessageList, {
|
|
777
|
+
messages: messages,
|
|
778
|
+
isDark: isDark,
|
|
779
|
+
primaryColor: primaryColor,
|
|
780
|
+
isTyping: isTyping,
|
|
781
|
+
companyLogo: companyLogo
|
|
782
|
+
}), /*#__PURE__*/jsx(QuickQuestions, {
|
|
783
|
+
questions: quickQuestions,
|
|
784
|
+
isDark: isDark,
|
|
785
|
+
primaryColor: primaryColor,
|
|
786
|
+
onQuestionClick: onQuickQuestion,
|
|
787
|
+
isTyping: isTyping
|
|
788
|
+
}), /*#__PURE__*/jsx(ChatInput, {
|
|
789
|
+
inputValue: inputValue,
|
|
790
|
+
setInputValue: setInputValue,
|
|
791
|
+
onSend: onSend,
|
|
792
|
+
isDark: isDark,
|
|
793
|
+
primaryColor: primaryColor,
|
|
794
|
+
isOpen: isOpen,
|
|
795
|
+
isMinimized: isMinimized
|
|
796
|
+
})]
|
|
797
|
+
})]
|
|
798
|
+
});
|
|
799
|
+
};
|
|
800
|
+
|
|
801
|
+
const ToggleButton = _ref => {
|
|
802
|
+
let {
|
|
803
|
+
isOpen,
|
|
804
|
+
isDark,
|
|
805
|
+
primaryColor,
|
|
806
|
+
onToggle
|
|
807
|
+
} = _ref;
|
|
808
|
+
return /*#__PURE__*/jsxs("button", {
|
|
809
|
+
onClick: onToggle,
|
|
810
|
+
className: "group relative w-16 h-16 rounded-full shadow-2xl transition-all duration-300 flex items-center justify-center text-white overflow-hidden ".concat(isOpen ? "rotate-0 scale-100" : "hover:scale-110"),
|
|
811
|
+
style: {
|
|
812
|
+
background: isOpen ? isDark ? "#1f2937" : "#374151" : "linear-gradient(135deg, ".concat(primaryColor, " 0%, ").concat(primaryColor, "dd 100%)"),
|
|
813
|
+
boxShadow: isOpen ? "0 10px 30px rgba(0,0,0,0.3)" : "0 10px 30px ".concat(primaryColor, "40")
|
|
814
|
+
},
|
|
815
|
+
"aria-label": isOpen ? "Close chat" : "Open chat",
|
|
816
|
+
children: [/*#__PURE__*/jsx("div", {
|
|
817
|
+
className: "absolute inset-0 rounded-full bg-white/20 scale-0 group-hover:scale-100 transition-transform duration-500"
|
|
818
|
+
}), /*#__PURE__*/jsx("div", {
|
|
819
|
+
className: "relative z-10 transition-transform duration-300",
|
|
820
|
+
children: isOpen ? /*#__PURE__*/jsx(X, {
|
|
821
|
+
className: "w-7 h-7"
|
|
822
|
+
}) : /*#__PURE__*/jsxs(Fragment, {
|
|
823
|
+
children: [/*#__PURE__*/jsx(MessageCircle, {
|
|
824
|
+
className: "w-7 h-7"
|
|
825
|
+
}), /*#__PURE__*/jsx("div", {
|
|
826
|
+
className: "absolute -top-1 -right-1 w-5 h-5 bg-red-500 rounded-full flex items-center justify-center text-[10px] font-bold border-2 border-white animate-pulse",
|
|
827
|
+
children: "1"
|
|
828
|
+
})]
|
|
829
|
+
})
|
|
830
|
+
})]
|
|
831
|
+
});
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
const ChatWidget = _ref => {
|
|
835
|
+
let {
|
|
836
|
+
darkMode = false,
|
|
837
|
+
primaryColor = "#2563eb",
|
|
838
|
+
position = "bottom-right",
|
|
839
|
+
companyName = "Support Team",
|
|
840
|
+
companyLogo = null,
|
|
841
|
+
welcomeMessage = "Hi! How can we help?",
|
|
842
|
+
quickQuestions = [],
|
|
843
|
+
apiBaseUrl,
|
|
844
|
+
organizationId,
|
|
845
|
+
autoOpen = false,
|
|
846
|
+
openDelay = 0,
|
|
847
|
+
locale = "en",
|
|
848
|
+
className = ""
|
|
849
|
+
} = _ref;
|
|
850
|
+
const {
|
|
851
|
+
isOpen,
|
|
852
|
+
isMinimized,
|
|
853
|
+
isDark,
|
|
854
|
+
messages,
|
|
855
|
+
inputValue,
|
|
856
|
+
isTyping,
|
|
857
|
+
widgetRef,
|
|
858
|
+
setInputValue,
|
|
859
|
+
handleSend,
|
|
860
|
+
handleQuickQuestion,
|
|
861
|
+
toggleChat,
|
|
862
|
+
toggleTheme,
|
|
863
|
+
toggleMinimize,
|
|
864
|
+
closeChat
|
|
865
|
+
} = useChatState({
|
|
866
|
+
welcomeMessage,
|
|
867
|
+
companyLogo,
|
|
868
|
+
quickQuestions,
|
|
869
|
+
apiBaseUrl,
|
|
870
|
+
organizationId,
|
|
871
|
+
autoOpen,
|
|
872
|
+
openDelay,
|
|
873
|
+
darkMode
|
|
874
|
+
});
|
|
875
|
+
|
|
876
|
+
// Set CSS variables for theming
|
|
877
|
+
useEffect(() => {
|
|
878
|
+
if (widgetRef.current) {
|
|
879
|
+
widgetRef.current.style.setProperty("--cw-primary", primaryColor);
|
|
880
|
+
}
|
|
881
|
+
}, [primaryColor, widgetRef]);
|
|
882
|
+
const positionClasses = {
|
|
883
|
+
"bottom-right": "bottom-5 right-5",
|
|
884
|
+
"bottom-left": "bottom-5 left-5",
|
|
885
|
+
"top-right": "top-5 right-5",
|
|
886
|
+
"top-left": "top-5 left-5"
|
|
887
|
+
};
|
|
888
|
+
return /*#__PURE__*/jsxs("div", {
|
|
889
|
+
ref: widgetRef,
|
|
890
|
+
className: "chat-widget-root fixed flex flex-col items-end z-[999999] ".concat(isDark ? "dark" : "", " ").concat(className, " ").concat(positionClasses[position] || positionClasses["bottom-right"]),
|
|
891
|
+
children: [/*#__PURE__*/jsx(ChatWindow, {
|
|
892
|
+
isOpen: isOpen,
|
|
893
|
+
isMinimized: isMinimized,
|
|
894
|
+
isDark: isDark,
|
|
895
|
+
primaryColor: primaryColor,
|
|
896
|
+
companyName: companyName,
|
|
897
|
+
companyLogo: companyLogo,
|
|
898
|
+
messages: messages,
|
|
899
|
+
isTyping: isTyping,
|
|
900
|
+
inputValue: inputValue,
|
|
901
|
+
setInputValue: setInputValue,
|
|
902
|
+
onSend: handleSend,
|
|
903
|
+
onToggleTheme: toggleTheme,
|
|
904
|
+
onMinimize: toggleMinimize,
|
|
905
|
+
onClose: closeChat,
|
|
906
|
+
quickQuestions: quickQuestions,
|
|
907
|
+
onQuickQuestion: handleQuickQuestion
|
|
908
|
+
}), /*#__PURE__*/jsx(ToggleButton, {
|
|
909
|
+
isOpen: isOpen,
|
|
910
|
+
isDark: isDark,
|
|
911
|
+
primaryColor: primaryColor,
|
|
912
|
+
onToggle: toggleChat
|
|
913
|
+
})]
|
|
914
|
+
});
|
|
915
|
+
};
|
|
916
|
+
|
|
917
|
+
export { ChatWidget as default };
|
|
918
|
+
//# sourceMappingURL=chat-widget.esm.js.map
|