@mailoo/chat 0.0.0-stage → 1.32.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +150 -2
  3. package/dist/chat-message-Dw6tKBEb.d.cts +10 -0
  4. package/dist/chat-message-Dw6tKBEb.d.ts +10 -0
  5. package/dist/chunk-2Y37RYEL.js +141 -0
  6. package/dist/chunk-2Y37RYEL.js.map +1 -0
  7. package/dist/chunk-4TNHJERE.js +19 -0
  8. package/dist/chunk-4TNHJERE.js.map +1 -0
  9. package/dist/chunk-77E6HUHY.js +41 -0
  10. package/dist/chunk-77E6HUHY.js.map +1 -0
  11. package/dist/chunk-AU6EFFLV.js +431 -0
  12. package/dist/chunk-AU6EFFLV.js.map +1 -0
  13. package/dist/chunk-QZ7HWQDO.js +839 -0
  14. package/dist/chunk-QZ7HWQDO.js.map +1 -0
  15. package/dist/client/index.cjs +1658 -0
  16. package/dist/client/index.cjs.map +1 -0
  17. package/dist/client/index.d.cts +33 -0
  18. package/dist/client/index.d.ts +33 -0
  19. package/dist/client/index.js +597 -0
  20. package/dist/client/index.js.map +1 -0
  21. package/dist/hooks/index.cjs +751 -0
  22. package/dist/hooks/index.cjs.map +1 -0
  23. package/dist/hooks/index.d.cts +79 -0
  24. package/dist/hooks/index.d.ts +79 -0
  25. package/dist/hooks/index.js +32 -0
  26. package/dist/hooks/index.js.map +1 -0
  27. package/dist/index.cjs +213 -0
  28. package/dist/index.cjs.map +1 -0
  29. package/dist/index.d.cts +53 -0
  30. package/dist/index.d.ts +53 -0
  31. package/dist/index.js +27 -0
  32. package/dist/index.js.map +1 -0
  33. package/dist/mailoo-site-chat-widget-C7B797Lu.d.ts +130 -0
  34. package/dist/mailoo-site-chat-widget-h_cBqsJw.d.cts +130 -0
  35. package/dist/routes/index.cjs +204 -0
  36. package/dist/routes/index.cjs.map +1 -0
  37. package/dist/routes/index.d.cts +30 -0
  38. package/dist/routes/index.d.ts +30 -0
  39. package/dist/routes/index.js +174 -0
  40. package/dist/routes/index.js.map +1 -0
  41. package/dist/shared-glVmghqk.d.cts +40 -0
  42. package/dist/shared-glVmghqk.d.ts +40 -0
  43. package/dist/styles/widget.css +122 -0
  44. package/dist/welcome-presets/index.cjs +479 -0
  45. package/dist/welcome-presets/index.cjs.map +1 -0
  46. package/dist/welcome-presets/index.d.cts +53 -0
  47. package/dist/welcome-presets/index.d.ts +53 -0
  48. package/dist/welcome-presets/index.js +38 -0
  49. package/dist/welcome-presets/index.js.map +1 -0
  50. package/dist/welcome-presets/parse.cjs +44 -0
  51. package/dist/welcome-presets/parse.cjs.map +1 -0
  52. package/dist/welcome-presets/parse.d.cts +11 -0
  53. package/dist/welcome-presets/parse.d.ts +11 -0
  54. package/dist/welcome-presets/parse.js +9 -0
  55. package/dist/welcome-presets/parse.js.map +1 -0
  56. package/dist/widget-config-B5Tf7gqn.d.cts +32 -0
  57. package/dist/widget-config-B5Tf7gqn.d.ts +32 -0
  58. package/package.json +85 -3
@@ -0,0 +1,597 @@
1
+ "use client";
2
+ import {
3
+ chatWidgetCssVariables,
4
+ mailooChatLauncherRootClassNames,
5
+ resolveMailooChatLauncherPosition
6
+ } from "../chunk-77E6HUHY.js";
7
+ import {
8
+ defaultChatUiLabels,
9
+ useMailooChatSession
10
+ } from "../chunk-QZ7HWQDO.js";
11
+ import {
12
+ createMailooChatWelcomePresetRenderer,
13
+ mailooChatWelcomePresetPanelClassName,
14
+ useOptionalMailooChatWelcomePreset
15
+ } from "../chunk-AU6EFFLV.js";
16
+ import "../chunk-4TNHJERE.js";
17
+
18
+ // src/components/mailoo-site-chat-widget.tsx
19
+ import {
20
+ useCallback,
21
+ useEffect,
22
+ useRef,
23
+ useState
24
+ } from "react";
25
+ import {
26
+ ChatBubbleLeftRightIcon,
27
+ ChevronLeftIcon,
28
+ ChevronUpIcon,
29
+ InformationCircleIcon,
30
+ XMarkIcon
31
+ } from "@heroicons/react/24/outline";
32
+
33
+ // src/components/mailoo-chat-unavailable-panel.tsx
34
+ import { jsx, jsxs } from "react/jsx-runtime";
35
+ function actionHref(action) {
36
+ if (action.type === "mailto") {
37
+ return `mailto:${action.email.trim()}`;
38
+ }
39
+ return action.href;
40
+ }
41
+ function actionLabel(action, labels) {
42
+ if (action.type === "mailto") {
43
+ return action.label?.trim() || labels.contactCta;
44
+ }
45
+ return action.label;
46
+ }
47
+ function MailooChatUnavailablePanel({
48
+ fault,
49
+ labels,
50
+ retry,
51
+ unavailableAction,
52
+ brandBtnClass
53
+ }) {
54
+ const isRateLimited = fault.kind === "rate_limited";
55
+ const title = isRateLimited ? labels.rateLimitedTitle : labels.unavailableTitle;
56
+ const body = isRateLimited ? labels.rateLimitedBody : labels.unavailableBody;
57
+ return /* @__PURE__ */ jsxs(
58
+ "div",
59
+ {
60
+ className: "flex min-h-0 flex-1 flex-col justify-center gap-3 p-4 text-sm",
61
+ role: "alert",
62
+ children: [
63
+ /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
64
+ /* @__PURE__ */ jsx("p", { className: "font-medium text-gray-900 dark:text-white", children: title }),
65
+ /* @__PURE__ */ jsx("p", { className: "text-xs leading-snug text-gray-600 dark:text-gray-300", children: body })
66
+ ] }),
67
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
68
+ /* @__PURE__ */ jsx(
69
+ "button",
70
+ {
71
+ type: "button",
72
+ onClick: retry,
73
+ className: `w-full py-2 text-sm font-medium ${brandBtnClass}`,
74
+ children: labels.retryCta
75
+ }
76
+ ),
77
+ unavailableAction ? /* @__PURE__ */ jsx(
78
+ "a",
79
+ {
80
+ href: actionHref(unavailableAction),
81
+ ...unavailableAction.type === "link" ? { target: "_blank", rel: "noopener noreferrer" } : {},
82
+ className: "w-full rounded border border-gray-300 py-2 text-center text-sm font-medium text-gray-800 hover:bg-gray-50 dark:border-gray-600 dark:text-gray-100 dark:hover:bg-gray-800",
83
+ children: actionLabel(unavailableAction, labels)
84
+ }
85
+ ) : null
86
+ ] })
87
+ ]
88
+ }
89
+ );
90
+ }
91
+
92
+ // src/components/mailoo-site-chat-widget.tsx
93
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
94
+ function MailooSiteChatWidget(props) {
95
+ const {
96
+ apiOrigin,
97
+ projectUid,
98
+ integrationId,
99
+ welcomeMessage,
100
+ locale,
101
+ isAuthenticated,
102
+ widgetConfig,
103
+ className,
104
+ panelClassName,
105
+ launcherClassName,
106
+ open: openProp,
107
+ defaultOpen = false,
108
+ onOpenChange,
109
+ title: titleProp,
110
+ launcherLabel,
111
+ labels: labelsProp,
112
+ submitEndpoint,
113
+ messagesEndpoint,
114
+ pollIntervalMs,
115
+ enablePolling,
116
+ enableWebSocket,
117
+ position: positionProp,
118
+ zIndex,
119
+ onSessionCreated,
120
+ onMessageSent,
121
+ onError,
122
+ onFault,
123
+ unavailableAction,
124
+ renderLauncher,
125
+ renderHeader,
126
+ renderEmpty,
127
+ renderWelcome,
128
+ renderUnavailable
129
+ } = props;
130
+ const t = {
131
+ ...defaultChatUiLabels(locale),
132
+ ...labelsProp
133
+ };
134
+ const title = titleProp ?? t.title;
135
+ const isControlled = openProp !== void 0;
136
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
137
+ const open = isControlled ? openProp : uncontrolledOpen;
138
+ const setOpen = (next) => {
139
+ onOpenChange?.(next);
140
+ if (!isControlled) setUncontrolledOpen(next);
141
+ };
142
+ const [input, setInput] = useState("");
143
+ const [threadHintExpanded, setThreadHintExpanded] = useState(false);
144
+ const [selectedTopicId, setSelectedTopicId] = useState(null);
145
+ const [welcomeDone, setWelcomeDone] = useState(false);
146
+ const messagesScrollRef = useRef(null);
147
+ const stickToBottomRef = useRef(true);
148
+ const SCROLL_NEAR_BOTTOM_PX = 80;
149
+ const brandStyle = chatWidgetCssVariables(widgetConfig ?? void 0);
150
+ const brandBtn = "rounded bg-[var(--mailoo-chat-brand,#2563eb)] text-[var(--mailoo-chat-brand-on,#ffffff)] hover:opacity-90";
151
+ const headerTitle = widgetConfig?.welcomeTitle ?? title;
152
+ const headerTagline = widgetConfig?.welcomeTagline ?? welcomeMessage;
153
+ const topics = widgetConfig?.topics ?? [];
154
+ const anyOperatorOnline = (widgetConfig?.operators ?? []).some(
155
+ (op) => op.online
156
+ );
157
+ const session = useMailooChatSession({
158
+ apiOrigin,
159
+ projectUid,
160
+ integrationId,
161
+ isAuthenticated,
162
+ submitEndpoint,
163
+ messagesEndpoint,
164
+ pollIntervalMs,
165
+ enablePolling,
166
+ enableWebSocket,
167
+ enabled: open,
168
+ onSessionCreated,
169
+ onMessageSent,
170
+ onError,
171
+ onFault
172
+ });
173
+ const {
174
+ messages,
175
+ sending,
176
+ error,
177
+ fault,
178
+ retryAfterFault,
179
+ guestEmail,
180
+ guestName,
181
+ setGuestEmail,
182
+ setGuestName,
183
+ guestContactOk,
184
+ guestProfileHydrated,
185
+ confirmGuestContact,
186
+ resetGuestContact,
187
+ canCompose,
188
+ sendMessage
189
+ } = session;
190
+ const onMessagesScroll = useCallback(() => {
191
+ const el = messagesScrollRef.current;
192
+ if (!el) return;
193
+ const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
194
+ stickToBottomRef.current = distanceFromBottom <= SCROLL_NEAR_BOTTOM_PX;
195
+ }, []);
196
+ useEffect(() => {
197
+ if (!stickToBottomRef.current) return;
198
+ const el = messagesScrollRef.current;
199
+ if (!el) return;
200
+ el.scrollTop = el.scrollHeight;
201
+ }, [messages]);
202
+ const send = async () => {
203
+ const text = input.trim();
204
+ if (!text || sending) return;
205
+ stickToBottomRef.current = true;
206
+ const ok = await sendMessage(text, {
207
+ invalidEmailMessage: t.emailInvalid,
208
+ topicId: selectedTopicId ?? void 0
209
+ });
210
+ if (ok) setInput("");
211
+ };
212
+ const toggle = () => setOpen(!open);
213
+ const position = resolveMailooChatLauncherPosition(
214
+ positionProp,
215
+ widgetConfig
216
+ );
217
+ const needsGuestFields = !isAuthenticated && !guestContactOk;
218
+ const showUnavailable = fault != null;
219
+ const showEntry = !showUnavailable && guestProfileHydrated && messages.length === 0 && !welcomeDone;
220
+ const showWelcomeSkin = showEntry && renderWelcome != null;
221
+ const showBuiltinEntry = showEntry && renderWelcome == null;
222
+ const showComposer = !showUnavailable && (welcomeDone || messages.length > 0) && canCompose;
223
+ const showDefaultHeader = !showWelcomeSkin || showUnavailable;
224
+ const unavailableArgs = fault ? {
225
+ fault,
226
+ labels: t,
227
+ retry: retryAfterFault,
228
+ unavailableAction,
229
+ brandBtnClass: brandBtn
230
+ } : null;
231
+ const enterFromWelcome = (invalidEmailMessage) => {
232
+ if (isAuthenticated || guestContactOk) {
233
+ setWelcomeDone(true);
234
+ return true;
235
+ }
236
+ const ok = confirmGuestContact(invalidEmailMessage);
237
+ if (ok) setWelcomeDone(true);
238
+ return ok;
239
+ };
240
+ const onResetGuestContact = () => {
241
+ setWelcomeDone(false);
242
+ resetGuestContact();
243
+ };
244
+ const backToTopics = () => {
245
+ setWelcomeDone(false);
246
+ setThreadHintExpanded(false);
247
+ };
248
+ const canReturnToTopics = welcomeDone && !showUnavailable;
249
+ const welcomeArgs = {
250
+ widgetConfig,
251
+ welcomeMessage: headerTagline,
252
+ title: headerTitle,
253
+ locale,
254
+ labels: t,
255
+ brandBtnClass: brandBtn,
256
+ brandStyle,
257
+ topics,
258
+ selectedTopicId,
259
+ setSelectedTopicId,
260
+ needsGuestFields,
261
+ isAuthenticated,
262
+ guestEmail,
263
+ setGuestEmail,
264
+ guestName,
265
+ setGuestName,
266
+ error,
267
+ confirmGuestContact: enterFromWelcome
268
+ };
269
+ const rootClass = [
270
+ mailooChatLauncherRootClassNames(position),
271
+ className ?? ""
272
+ ].filter(Boolean).join(" ");
273
+ return /* @__PURE__ */ jsxs2(
274
+ "div",
275
+ {
276
+ className: rootClass,
277
+ "data-clarity-mask": "true",
278
+ style: {
279
+ ...brandStyle,
280
+ ...zIndex != null ? { zIndex } : {}
281
+ },
282
+ children: [
283
+ open && /* @__PURE__ */ jsxs2(
284
+ "div",
285
+ {
286
+ className: `mailoo-chat-panel ${panelClassName ?? ""}`,
287
+ style: brandStyle,
288
+ children: [
289
+ showDefaultHeader && (renderHeader ? renderHeader({
290
+ welcomeMessage: headerTagline,
291
+ title: headerTitle
292
+ }) : /* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-1 border-b border-gray-200 px-2 py-2 dark:border-gray-700", children: [
293
+ canReturnToTopics ? /* @__PURE__ */ jsx2(
294
+ "button",
295
+ {
296
+ type: "button",
297
+ onClick: backToTopics,
298
+ className: "mt-0.5 shrink-0 rounded p-1 text-gray-500 hover:bg-gray-100 hover:text-gray-800 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-100",
299
+ "aria-label": t.backToTopics,
300
+ title: t.backToTopics,
301
+ children: /* @__PURE__ */ jsx2(ChevronLeftIcon, { className: "h-5 w-5", "aria-hidden": true })
302
+ }
303
+ ) : null,
304
+ /* @__PURE__ */ jsxs2("div", { className: "min-w-0 flex-1 px-1", children: [
305
+ /* @__PURE__ */ jsx2("p", { className: "text-sm font-medium text-gray-900 dark:text-white", children: headerTitle }),
306
+ /* @__PURE__ */ jsx2("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: headerTagline })
307
+ ] })
308
+ ] })),
309
+ !isAuthenticated && !guestProfileHydrated && !showUnavailable && /* @__PURE__ */ jsx2("p", { className: "border-b border-gray-200 p-3 text-sm text-gray-500 dark:border-gray-700 dark:text-gray-400", children: t.loadingProfile }),
310
+ showUnavailable && unavailableArgs ? /* @__PURE__ */ jsxs2("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: [
311
+ messages.length > 0 ? /* @__PURE__ */ jsx2("div", { className: "min-h-0 max-h-[40%] space-y-2 overflow-y-auto border-b border-gray-200 p-3 text-sm dark:border-gray-700", children: messages.map((m) => /* @__PURE__ */ jsx2(
312
+ "div",
313
+ {
314
+ className: m.messageType === "OUTBOUND" ? "mailoo-chat-bubble--outbound ml-6 rounded-md p-2" : "mailoo-chat-bubble--inbound mr-6 rounded-md p-2",
315
+ children: /* @__PURE__ */ jsx2("p", { className: "whitespace-pre-wrap text-gray-900 dark:text-gray-100", children: m.content })
316
+ },
317
+ m.id
318
+ )) }) : null,
319
+ renderUnavailable ? renderUnavailable(unavailableArgs) : MailooChatUnavailablePanel(unavailableArgs)
320
+ ] }) : null,
321
+ showWelcomeSkin && /* @__PURE__ */ jsx2("div", { className: "flex min-h-0 flex-1 flex-col overflow-hidden", children: renderWelcome(welcomeArgs) }),
322
+ showBuiltinEntry && /* @__PURE__ */ jsxs2("div", { className: "space-y-3 border-b border-gray-200 p-3 text-sm dark:border-gray-700", children: [
323
+ topics.length > 0 && /* @__PURE__ */ jsx2("div", { className: "flex flex-wrap gap-2", children: topics.map(
324
+ (topic) => topic.action === "external_url" && topic.externalUrl ? /* @__PURE__ */ jsx2(
325
+ "a",
326
+ {
327
+ href: topic.externalUrl,
328
+ target: "_blank",
329
+ rel: "noopener noreferrer",
330
+ className: `px-2 py-1 text-xs font-medium ${brandBtn}`,
331
+ children: topic.label
332
+ },
333
+ topic.id
334
+ ) : /* @__PURE__ */ jsx2(
335
+ "button",
336
+ {
337
+ type: "button",
338
+ onClick: () => setSelectedTopicId(
339
+ (prev) => prev === topic.id ? null : topic.id
340
+ ),
341
+ className: `px-2 py-1 text-xs font-medium ${selectedTopicId === topic.id ? brandBtn : "rounded border border-gray-300 text-gray-700 dark:border-gray-600 dark:text-gray-200"}`,
342
+ children: topic.label
343
+ },
344
+ topic.id
345
+ )
346
+ ) }),
347
+ needsGuestFields && /* @__PURE__ */ jsxs2(Fragment, { children: [
348
+ /* @__PURE__ */ jsx2("p", { className: "text-gray-700 dark:text-gray-300", children: t.intro }),
349
+ /* @__PURE__ */ jsxs2("div", { children: [
350
+ /* @__PURE__ */ jsx2(
351
+ "label",
352
+ {
353
+ htmlFor: "mailoo-chat-guest-email",
354
+ className: "mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400",
355
+ children: t.emailLabel
356
+ }
357
+ ),
358
+ /* @__PURE__ */ jsx2(
359
+ "input",
360
+ {
361
+ id: "mailoo-chat-guest-email",
362
+ type: "email",
363
+ autoComplete: "email",
364
+ value: guestEmail,
365
+ onChange: (e) => setGuestEmail(e.target.value),
366
+ placeholder: t.emailPlaceholder,
367
+ className: "w-full rounded border border-gray-300 bg-white px-2 py-1.5 text-sm dark:border-gray-600 dark:bg-gray-800"
368
+ }
369
+ )
370
+ ] }),
371
+ /* @__PURE__ */ jsxs2("div", { children: [
372
+ /* @__PURE__ */ jsx2(
373
+ "label",
374
+ {
375
+ htmlFor: "mailoo-chat-guest-name",
376
+ className: "mb-1 block text-xs font-medium text-gray-600 dark:text-gray-400",
377
+ children: t.nameLabel
378
+ }
379
+ ),
380
+ /* @__PURE__ */ jsx2(
381
+ "input",
382
+ {
383
+ id: "mailoo-chat-guest-name",
384
+ type: "text",
385
+ autoComplete: "name",
386
+ value: guestName,
387
+ onChange: (e) => setGuestName(e.target.value),
388
+ placeholder: t.namePlaceholder,
389
+ className: "w-full rounded border border-gray-300 bg-white px-2 py-1.5 text-sm dark:border-gray-600 dark:bg-gray-800"
390
+ }
391
+ )
392
+ ] }),
393
+ error && /* @__PURE__ */ jsx2("p", { className: "text-xs text-red-600 dark:text-red-400", children: error })
394
+ ] }),
395
+ /* @__PURE__ */ jsx2(
396
+ "button",
397
+ {
398
+ type: "button",
399
+ onClick: () => enterFromWelcome(t.emailInvalid),
400
+ className: `w-full py-2 text-sm font-medium ${brandBtn}`,
401
+ children: t.continueCta
402
+ }
403
+ )
404
+ ] }),
405
+ showComposer && /* @__PURE__ */ jsxs2("div", { className: "flex min-h-0 flex-1 flex-col", children: [
406
+ !isAuthenticated && /* @__PURE__ */ jsxs2(Fragment, { children: [
407
+ /* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-gray-100 px-3 py-1.5 text-[11px] text-gray-500 dark:border-gray-800 dark:text-gray-400", children: [
408
+ /* @__PURE__ */ jsx2("span", { className: "truncate", children: guestEmail }),
409
+ /* @__PURE__ */ jsx2(
410
+ "button",
411
+ {
412
+ type: "button",
413
+ onClick: () => onResetGuestContact(),
414
+ className: "shrink-0 text-[var(--mailoo-chat-brand,#2563eb)] hover:underline",
415
+ children: t.changeContact
416
+ }
417
+ )
418
+ ] }),
419
+ threadHintExpanded && /* @__PURE__ */ jsx2("div", { className: "shrink-0 border-b border-gray-100 px-3 py-2 dark:border-gray-800", children: /* @__PURE__ */ jsxs2("div", { className: "flex items-start gap-2", children: [
420
+ /* @__PURE__ */ jsx2("p", { className: "min-w-0 flex-1 text-[11px] leading-snug text-gray-500 dark:text-gray-400", children: t.threadHint }),
421
+ /* @__PURE__ */ jsx2(
422
+ "button",
423
+ {
424
+ type: "button",
425
+ onClick: () => setThreadHintExpanded(false),
426
+ className: "shrink-0 rounded p-0.5 text-gray-400 hover:bg-gray-100 hover:text-gray-600 dark:hover:bg-gray-700 dark:hover:text-gray-300",
427
+ "aria-label": t.threadHintCollapse,
428
+ title: t.threadHintCollapse,
429
+ children: /* @__PURE__ */ jsx2(ChevronUpIcon, { className: "h-4 w-4", "aria-hidden": true })
430
+ }
431
+ )
432
+ ] }) })
433
+ ] }),
434
+ /* @__PURE__ */ jsxs2("div", { className: "relative min-h-0 w-full min-w-0 flex-1", children: [
435
+ !isAuthenticated && !threadHintExpanded && /* @__PURE__ */ jsx2(
436
+ "button",
437
+ {
438
+ type: "button",
439
+ onClick: () => setThreadHintExpanded(true),
440
+ className: "absolute right-3 top-2 z-20 rounded-full bg-white/95 p-1 shadow-md ring-1 ring-gray-200/80 hover:bg-gray-50 dark:bg-gray-800/95 dark:ring-gray-600 dark:hover:bg-gray-700",
441
+ "aria-expanded": false,
442
+ "aria-label": t.threadHintIconLabel,
443
+ title: t.threadHintIconLabel,
444
+ children: /* @__PURE__ */ jsx2(
445
+ InformationCircleIcon,
446
+ {
447
+ className: "h-5 w-5 text-gray-600 dark:text-gray-300",
448
+ "aria-hidden": true
449
+ }
450
+ )
451
+ }
452
+ ),
453
+ /* @__PURE__ */ jsxs2(
454
+ "div",
455
+ {
456
+ ref: messagesScrollRef,
457
+ onScroll: onMessagesScroll,
458
+ className: `h-full min-h-0 space-y-2 overflow-y-auto p-3 text-sm ${!isAuthenticated && !threadHintExpanded ? "pr-12 pt-2" : ""}`,
459
+ children: [
460
+ messages.length === 0 && (renderEmpty ? renderEmpty({ isAuthenticated }) : /* @__PURE__ */ jsx2("p", { className: "text-gray-500 dark:text-gray-400", children: isAuthenticated ? t.emptyThreadAuthenticated : t.emptyThreadGuest })),
461
+ messages.map((m) => /* @__PURE__ */ jsxs2(
462
+ "div",
463
+ {
464
+ className: m.messageType === "OUTBOUND" ? "mailoo-chat-bubble--outbound ml-6 rounded-md p-2" : "mailoo-chat-bubble--inbound mr-6 rounded-md p-2",
465
+ children: [
466
+ /* @__PURE__ */ jsx2("p", { className: "whitespace-pre-wrap text-gray-900 dark:text-gray-100", children: m.content }),
467
+ /* @__PURE__ */ jsx2("p", { className: "mt-1 text-[10px] text-gray-400", children: new Date(m.createdAt).toLocaleString() })
468
+ ]
469
+ },
470
+ m.id
471
+ ))
472
+ ]
473
+ }
474
+ )
475
+ ] }),
476
+ error && guestContactOk && /* @__PURE__ */ jsx2("p", { className: "px-3 text-xs text-red-600 dark:text-red-400", children: error }),
477
+ widgetConfig?.privacyPolicyUrl && /* @__PURE__ */ jsx2("p", { className: "px-3 pb-1 text-[10px] text-gray-500 dark:text-gray-400", children: /* @__PURE__ */ jsx2(
478
+ "a",
479
+ {
480
+ href: widgetConfig.privacyPolicyUrl,
481
+ target: "_blank",
482
+ rel: "noopener noreferrer",
483
+ className: "underline hover:text-gray-700 dark:hover:text-gray-300",
484
+ children: "Privacy"
485
+ }
486
+ ) }),
487
+ /* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 gap-2 border-t border-gray-200 p-2 dark:border-gray-700", children: [
488
+ /* @__PURE__ */ jsx2(
489
+ "input",
490
+ {
491
+ type: "text",
492
+ value: input,
493
+ onChange: (e) => setInput(e.target.value),
494
+ onKeyDown: (e) => {
495
+ if (e.key === "Enter") void send();
496
+ },
497
+ placeholder: t.composerPlaceholder,
498
+ className: "min-w-0 flex-1 rounded border border-gray-300 bg-white px-2 py-1.5 text-sm dark:border-gray-600 dark:bg-gray-800"
499
+ }
500
+ ),
501
+ /* @__PURE__ */ jsx2(
502
+ "button",
503
+ {
504
+ type: "button",
505
+ onClick: () => void send(),
506
+ disabled: sending,
507
+ className: `px-3 py-1.5 text-sm font-medium disabled:opacity-50 ${brandBtn}`,
508
+ children: t.send
509
+ }
510
+ )
511
+ ] })
512
+ ] })
513
+ ]
514
+ }
515
+ ),
516
+ renderLauncher ? renderLauncher({ open, toggle }) : /* @__PURE__ */ jsxs2(
517
+ "button",
518
+ {
519
+ type: "button",
520
+ onClick: toggle,
521
+ className: `mailoo-chat-launcher ${launcherClassName ?? ""}`,
522
+ "aria-label": open ? t.launcherClose : launcherLabel ?? t.launcherOpen,
523
+ children: [
524
+ open ? /* @__PURE__ */ jsx2(XMarkIcon, { className: "mailoo-chat-launcher__icon", "aria-hidden": true }) : /* @__PURE__ */ jsx2(
525
+ ChatBubbleLeftRightIcon,
526
+ {
527
+ className: "mailoo-chat-launcher__icon",
528
+ "aria-hidden": true
529
+ }
530
+ ),
531
+ !open && anyOperatorOnline ? /* @__PURE__ */ jsx2("span", { className: "mailoo-chat-launcher__online", "aria-hidden": true }) : null
532
+ ]
533
+ }
534
+ )
535
+ ]
536
+ }
537
+ );
538
+ }
539
+
540
+ // src/components/mailoo-site-chat-shell.tsx
541
+ import { useCallback as useCallback2, useEffect as useEffect2, useMemo, useState as useState2 } from "react";
542
+ import { jsx as jsx3 } from "react/jsx-runtime";
543
+ var MAILOO_SITE_CHAT_OPEN_EVENT = "mailoo-site-chat:open";
544
+ function MailooSiteChatShell({
545
+ chat,
546
+ unavailableAction,
547
+ renderUnavailable,
548
+ onError,
549
+ onFault
550
+ }) {
551
+ const welcomePreset = useOptionalMailooChatWelcomePreset();
552
+ const [open, setOpen] = useState2(false);
553
+ const openChat = useCallback2(() => setOpen(true), []);
554
+ useEffect2(() => {
555
+ const onOpen = () => openChat();
556
+ window.addEventListener(MAILOO_SITE_CHAT_OPEN_EVENT, onOpen);
557
+ return () => {
558
+ window.removeEventListener(MAILOO_SITE_CHAT_OPEN_EVENT, onOpen);
559
+ };
560
+ }, [openChat]);
561
+ const renderWelcome = useMemo(
562
+ () => welcomePreset ? createMailooChatWelcomePresetRenderer(welcomePreset.preset) : void 0,
563
+ [welcomePreset]
564
+ );
565
+ const panelClassName = welcomePreset ? mailooChatWelcomePresetPanelClassName(welcomePreset.preset) : void 0;
566
+ return /* @__PURE__ */ jsx3(
567
+ MailooSiteChatWidget,
568
+ {
569
+ apiOrigin: chat.apiOrigin,
570
+ projectUid: chat.projectUid,
571
+ integrationId: chat.integrationId,
572
+ welcomeMessage: chat.welcomeMessage,
573
+ locale: chat.locale,
574
+ isAuthenticated: chat.isAuthenticated,
575
+ widgetConfig: chat.widgetConfig,
576
+ open,
577
+ onOpenChange: setOpen,
578
+ renderWelcome,
579
+ panelClassName,
580
+ unavailableAction,
581
+ renderUnavailable,
582
+ onError,
583
+ onFault
584
+ }
585
+ );
586
+ }
587
+ function openMailooSiteChat() {
588
+ window.dispatchEvent(new Event(MAILOO_SITE_CHAT_OPEN_EVENT));
589
+ }
590
+ export {
591
+ MAILOO_SITE_CHAT_OPEN_EVENT,
592
+ MailooChatUnavailablePanel,
593
+ MailooSiteChatShell,
594
+ MailooSiteChatWidget,
595
+ openMailooSiteChat
596
+ };
597
+ //# sourceMappingURL=index.js.map