@xcelsior/ui-chat 2.0.1 → 2.0.3

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/dist/index.mjs CHANGED
@@ -11,6 +11,7 @@ function useWebSocket(config, externalWebSocket) {
11
11
  const reconnectTimeoutRef = useRef(null);
12
12
  const reconnectAttemptsRef = useRef(0);
13
13
  const messageHandlerRef = useRef(null);
14
+ const abortedRef = useRef(false);
14
15
  const maxReconnectAttempts = 5;
15
16
  const reconnectDelay = 3e3;
16
17
  const isUsingExternalWs = !!externalWebSocket;
@@ -43,6 +44,7 @@ function useWebSocket(config, externalWebSocket) {
43
44
  };
44
45
  }, []);
45
46
  const connect = useCallback(() => {
47
+ if (abortedRef.current) return;
46
48
  console.log("connecting to WebSocket...", config.currentUser, config.conversationId);
47
49
  try {
48
50
  if (wsRef.current) {
@@ -62,6 +64,10 @@ function useWebSocket(config, externalWebSocket) {
62
64
  }
63
65
  const ws = new WebSocket(url.toString());
64
66
  ws.onopen = () => {
67
+ if (abortedRef.current) {
68
+ ws.close(1e3, "Effect cleaned up");
69
+ return;
70
+ }
65
71
  console.log("WebSocket connected");
66
72
  setIsConnected(true);
67
73
  setError(null);
@@ -69,12 +75,14 @@ function useWebSocket(config, externalWebSocket) {
69
75
  config.onConnectionChange?.(true);
70
76
  };
71
77
  ws.onerror = (event) => {
78
+ if (abortedRef.current) return;
72
79
  console.error("WebSocket error:", event);
73
80
  const err = new Error("WebSocket connection error");
74
81
  setError(err);
75
82
  config.onError?.(err);
76
83
  };
77
84
  ws.onclose = (event) => {
85
+ if (abortedRef.current) return;
78
86
  console.log("WebSocket closed:", event.code, event.reason);
79
87
  setIsConnected(false);
80
88
  config.onConnectionChange?.(false);
@@ -123,6 +131,7 @@ function useWebSocket(config, externalWebSocket) {
123
131
  );
124
132
  const reconnect = useCallback(() => {
125
133
  reconnectAttemptsRef.current = 0;
134
+ abortedRef.current = false;
126
135
  connect();
127
136
  }, [connect]);
128
137
  useEffect(() => {
@@ -132,8 +141,10 @@ function useWebSocket(config, externalWebSocket) {
132
141
  const cleanup = subscribeToMessage(externalWebSocket);
133
142
  return cleanup;
134
143
  }
144
+ abortedRef.current = false;
135
145
  connect();
136
146
  return () => {
147
+ abortedRef.current = true;
137
148
  if (reconnectTimeoutRef.current) {
138
149
  clearTimeout(reconnectTimeoutRef.current);
139
150
  }
@@ -912,7 +923,50 @@ function ChatHeader({ agent, onClose, onMinimize, theme }) {
912
923
 
913
924
  // src/components/MessageList.tsx
914
925
  import { useCallback as useCallback4, useEffect as useEffect6, useRef as useRef4 } from "react";
915
- import { Spinner } from "@xcelsior/design-system";
926
+
927
+ // src/components/Spinner.tsx
928
+ import { Fragment, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
929
+ var SIZE_MAP = {
930
+ sm: 16,
931
+ md: 24,
932
+ lg: 36
933
+ };
934
+ var BORDER_MAP = {
935
+ sm: 2,
936
+ md: 2,
937
+ lg: 3
938
+ };
939
+ function Spinner({ size = "md", color = "currentColor" }) {
940
+ const px = SIZE_MAP[size];
941
+ const border = BORDER_MAP[size];
942
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
943
+ /* @__PURE__ */ jsx3("style", { children: `
944
+ @keyframes xchat-spin {
945
+ to { transform: rotate(360deg); }
946
+ }
947
+ .xchat-spinner {
948
+ animation: xchat-spin 0.75s linear infinite;
949
+ border-radius: 50%;
950
+ display: inline-block;
951
+ flex-shrink: 0;
952
+ }
953
+ ` }),
954
+ /* @__PURE__ */ jsx3(
955
+ "span",
956
+ {
957
+ className: "xchat-spinner",
958
+ role: "status",
959
+ "aria-label": "Loading",
960
+ style: {
961
+ width: px,
962
+ height: px,
963
+ border: `${border}px solid rgba(128,128,128,0.25)`,
964
+ borderTopColor: color
965
+ }
966
+ }
967
+ )
968
+ ] });
969
+ }
916
970
 
917
971
  // src/components/MessageItem.tsx
918
972
  import { formatDistanceToNow } from "date-fns";
@@ -1007,7 +1061,7 @@ function getMarkdownStyles(theme, isLightTheme) {
1007
1061
  }
1008
1062
 
1009
1063
  // src/components/MarkdownMessage.tsx
1010
- import { jsx as jsx3 } from "react/jsx-runtime";
1064
+ import { jsx as jsx4 } from "react/jsx-runtime";
1011
1065
  function computeIsLightTheme(theme) {
1012
1066
  const bgColor = theme?.background || "#00001a";
1013
1067
  if (!bgColor.startsWith("#")) return false;
@@ -1026,18 +1080,18 @@ function MarkdownMessage({ content, theme }) {
1026
1080
  // inside the bubble.
1027
1081
  display: "block"
1028
1082
  };
1029
- return /* @__PURE__ */ jsx3("div", { style: wrapperStyle, children: /* @__PURE__ */ jsx3(
1083
+ return /* @__PURE__ */ jsx4("div", { style: wrapperStyle, children: /* @__PURE__ */ jsx4(
1030
1084
  ReactMarkdown,
1031
1085
  {
1032
1086
  components: {
1033
1087
  // Paragraphs
1034
- p: ({ children }) => /* @__PURE__ */ jsx3("p", { style: styles.paragraph, children }),
1088
+ p: ({ children }) => /* @__PURE__ */ jsx4("p", { style: styles.paragraph, children }),
1035
1089
  // Bold
1036
- strong: ({ children }) => /* @__PURE__ */ jsx3("strong", { style: styles.strong, children }),
1090
+ strong: ({ children }) => /* @__PURE__ */ jsx4("strong", { style: styles.strong, children }),
1037
1091
  // Italic
1038
- em: ({ children }) => /* @__PURE__ */ jsx3("em", { style: styles.emphasis, children }),
1092
+ em: ({ children }) => /* @__PURE__ */ jsx4("em", { style: styles.emphasis, children }),
1039
1093
  // Links — open in new tab
1040
- a: ({ href, children }) => /* @__PURE__ */ jsx3(
1094
+ a: ({ href, children }) => /* @__PURE__ */ jsx4(
1041
1095
  "a",
1042
1096
  {
1043
1097
  href,
@@ -1048,9 +1102,9 @@ function MarkdownMessage({ content, theme }) {
1048
1102
  }
1049
1103
  ),
1050
1104
  // Unordered list
1051
- ul: ({ children }) => /* @__PURE__ */ jsx3("ul", { style: { ...styles.list, listStyleType: "disc" }, children }),
1105
+ ul: ({ children }) => /* @__PURE__ */ jsx4("ul", { style: { ...styles.list, listStyleType: "disc" }, children }),
1052
1106
  // Ordered list
1053
- ol: ({ children }) => /* @__PURE__ */ jsx3(
1107
+ ol: ({ children }) => /* @__PURE__ */ jsx4(
1054
1108
  "ol",
1055
1109
  {
1056
1110
  style: { ...styles.list, listStyleType: "decimal" },
@@ -1058,7 +1112,7 @@ function MarkdownMessage({ content, theme }) {
1058
1112
  }
1059
1113
  ),
1060
1114
  // List item
1061
- li: ({ children }) => /* @__PURE__ */ jsx3("li", { style: styles.listItem, children }),
1115
+ li: ({ children }) => /* @__PURE__ */ jsx4("li", { style: styles.listItem, children }),
1062
1116
  // Inline code vs code block — react-markdown wraps fenced
1063
1117
  // code blocks as <pre><code className="language-*">. The
1064
1118
  // cleanest heuristic: if the className starts with
@@ -1068,7 +1122,7 @@ function MarkdownMessage({ content, theme }) {
1068
1122
  className?.startsWith("language-")
1069
1123
  );
1070
1124
  if (isBlock) {
1071
- return /* @__PURE__ */ jsx3(
1125
+ return /* @__PURE__ */ jsx4(
1072
1126
  "code",
1073
1127
  {
1074
1128
  className,
@@ -1077,10 +1131,10 @@ function MarkdownMessage({ content, theme }) {
1077
1131
  }
1078
1132
  );
1079
1133
  }
1080
- return /* @__PURE__ */ jsx3("code", { style: styles.code, children });
1134
+ return /* @__PURE__ */ jsx4("code", { style: styles.code, children });
1081
1135
  }),
1082
1136
  // Pre wrapper for code blocks
1083
- pre: ({ children }) => /* @__PURE__ */ jsx3(
1137
+ pre: ({ children }) => /* @__PURE__ */ jsx4(
1084
1138
  "pre",
1085
1139
  {
1086
1140
  style: {
@@ -1094,7 +1148,7 @@ function MarkdownMessage({ content, theme }) {
1094
1148
  }
1095
1149
  ),
1096
1150
  // Headings — h1 through h6 with progressive size reduction
1097
- h1: ({ children }) => /* @__PURE__ */ jsx3(
1151
+ h1: ({ children }) => /* @__PURE__ */ jsx4(
1098
1152
  "h1",
1099
1153
  {
1100
1154
  style: {
@@ -1104,7 +1158,7 @@ function MarkdownMessage({ content, theme }) {
1104
1158
  children
1105
1159
  }
1106
1160
  ),
1107
- h2: ({ children }) => /* @__PURE__ */ jsx3(
1161
+ h2: ({ children }) => /* @__PURE__ */ jsx4(
1108
1162
  "h2",
1109
1163
  {
1110
1164
  style: {
@@ -1114,7 +1168,7 @@ function MarkdownMessage({ content, theme }) {
1114
1168
  children
1115
1169
  }
1116
1170
  ),
1117
- h3: ({ children }) => /* @__PURE__ */ jsx3(
1171
+ h3: ({ children }) => /* @__PURE__ */ jsx4(
1118
1172
  "h3",
1119
1173
  {
1120
1174
  style: {
@@ -1124,8 +1178,8 @@ function MarkdownMessage({ content, theme }) {
1124
1178
  children
1125
1179
  }
1126
1180
  ),
1127
- h4: ({ children }) => /* @__PURE__ */ jsx3("h4", { style: { ...styles.heading, fontSize: "1em" }, children }),
1128
- h5: ({ children }) => /* @__PURE__ */ jsx3(
1181
+ h4: ({ children }) => /* @__PURE__ */ jsx4("h4", { style: { ...styles.heading, fontSize: "1em" }, children }),
1182
+ h5: ({ children }) => /* @__PURE__ */ jsx4(
1129
1183
  "h5",
1130
1184
  {
1131
1185
  style: {
@@ -1135,7 +1189,7 @@ function MarkdownMessage({ content, theme }) {
1135
1189
  children
1136
1190
  }
1137
1191
  ),
1138
- h6: ({ children }) => /* @__PURE__ */ jsx3(
1192
+ h6: ({ children }) => /* @__PURE__ */ jsx4(
1139
1193
  "h6",
1140
1194
  {
1141
1195
  style: {
@@ -1146,9 +1200,9 @@ function MarkdownMessage({ content, theme }) {
1146
1200
  }
1147
1201
  ),
1148
1202
  // Blockquote
1149
- blockquote: ({ children }) => /* @__PURE__ */ jsx3("blockquote", { style: styles.blockquote, children }),
1203
+ blockquote: ({ children }) => /* @__PURE__ */ jsx4("blockquote", { style: styles.blockquote, children }),
1150
1204
  // Horizontal rule
1151
- hr: () => /* @__PURE__ */ jsx3("hr", { style: styles.hr })
1205
+ hr: () => /* @__PURE__ */ jsx4("hr", { style: styles.hr })
1152
1206
  },
1153
1207
  children: content
1154
1208
  }
@@ -1156,7 +1210,7 @@ function MarkdownMessage({ content, theme }) {
1156
1210
  }
1157
1211
 
1158
1212
  // src/components/MessageItem.tsx
1159
- import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
1213
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1160
1214
  function MessageItem({
1161
1215
  message,
1162
1216
  currentUser,
@@ -1182,7 +1236,7 @@ function MessageItem({
1182
1236
  const textColor = theme?.text || (isLightTheme ? "#1a1a2e" : "#f7f7f8");
1183
1237
  const textMuted = theme?.textMuted || (isLightTheme ? "rgba(0,0,0,0.35)" : "rgba(247,247,248,0.35)");
1184
1238
  if (isSystemMessage) {
1185
- return /* @__PURE__ */ jsx4("div", { className: "flex justify-center my-3", children: /* @__PURE__ */ jsx4(
1239
+ return /* @__PURE__ */ jsx5("div", { className: "flex justify-center my-3", children: /* @__PURE__ */ jsx5(
1186
1240
  "div",
1187
1241
  {
1188
1242
  className: "px-4 py-1.5 rounded-full",
@@ -1190,7 +1244,7 @@ function MessageItem({
1190
1244
  backgroundColor: isLightTheme ? "rgba(0,0,0,0.04)" : "rgba(255,255,255,0.03)",
1191
1245
  boxShadow: isLightTheme ? "inset 0 0 0 1px rgba(0,0,0,0.06)" : "inset 0 0 0 0.5px rgba(255,255,255,0.06)"
1192
1246
  },
1193
- children: /* @__PURE__ */ jsx4(
1247
+ children: /* @__PURE__ */ jsx5(
1194
1248
  "p",
1195
1249
  {
1196
1250
  style: {
@@ -1229,12 +1283,12 @@ function MessageItem({
1229
1283
  borderRadius: "18px 18px 18px 4px",
1230
1284
  boxShadow: "inset 0 0 0 0.5px rgba(255,255,255,0.06), inset 0 1px 0 0 rgba(255,255,255,0.08)"
1231
1285
  };
1232
- return /* @__PURE__ */ jsxs3(
1286
+ return /* @__PURE__ */ jsxs4(
1233
1287
  "div",
1234
1288
  {
1235
1289
  className: `flex gap-2.5 mb-3 ${isOwnMessage ? "flex-row-reverse" : "flex-row"}`,
1236
1290
  children: [
1237
- showAvatar && !isOwnMessage && /* @__PURE__ */ jsx4("div", { className: "flex-shrink-0 mt-auto mb-5", children: isBotMessage || isAIMessage ? /* @__PURE__ */ jsx4(XcelsiorAvatar, { size: 28 }) : /* @__PURE__ */ jsx4(
1291
+ showAvatar && !isOwnMessage && /* @__PURE__ */ jsx5("div", { className: "flex-shrink-0 mt-auto mb-5", children: isBotMessage || isAIMessage ? /* @__PURE__ */ jsx5(XcelsiorAvatar, { size: 28 }) : /* @__PURE__ */ jsx5(
1238
1292
  "div",
1239
1293
  {
1240
1294
  className: "h-7 w-7 rounded-full flex items-center justify-center",
@@ -1242,7 +1296,7 @@ function MessageItem({
1242
1296
  background: isLightTheme ? `linear-gradient(135deg, ${primaryColor}30, rgba(0,0,0,0.04))` : `linear-gradient(135deg, ${primaryColor}60, rgba(255,255,255,0.06))`,
1243
1297
  boxShadow: isLightTheme ? "inset 0 0 0 1px rgba(0,0,0,0.08)" : "inset 0 0 0 0.5px rgba(255,255,255,0.1)"
1244
1298
  },
1245
- children: /* @__PURE__ */ jsxs3(
1299
+ children: /* @__PURE__ */ jsxs4(
1246
1300
  "svg",
1247
1301
  {
1248
1302
  width: "14",
@@ -1255,21 +1309,21 @@ function MessageItem({
1255
1309
  strokeLinejoin: "round",
1256
1310
  "aria-hidden": "true",
1257
1311
  children: [
1258
- /* @__PURE__ */ jsx4("title", { children: "Agent" }),
1259
- /* @__PURE__ */ jsx4("path", { d: "M3 18v-6a9 9 0 0 1 18 0v6" }),
1260
- /* @__PURE__ */ jsx4("path", { d: "M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z" })
1312
+ /* @__PURE__ */ jsx5("title", { children: "Agent" }),
1313
+ /* @__PURE__ */ jsx5("path", { d: "M3 18v-6a9 9 0 0 1 18 0v6" }),
1314
+ /* @__PURE__ */ jsx5("path", { d: "M21 19a2 2 0 0 1-2 2h-1a2 2 0 0 1-2-2v-3a2 2 0 0 1 2-2h3zM3 19a2 2 0 0 0 2 2h1a2 2 0 0 0 2-2v-3a2 2 0 0 0-2-2H3z" })
1261
1315
  ]
1262
1316
  }
1263
1317
  )
1264
1318
  }
1265
1319
  ) }),
1266
- showAvatar && isOwnMessage && /* @__PURE__ */ jsx4("div", { className: "w-7 flex-shrink-0" }),
1267
- /* @__PURE__ */ jsxs3(
1320
+ showAvatar && isOwnMessage && /* @__PURE__ */ jsx5("div", { className: "w-7 flex-shrink-0" }),
1321
+ /* @__PURE__ */ jsxs4(
1268
1322
  "div",
1269
1323
  {
1270
1324
  className: `flex flex-col max-w-[75%] ${isOwnMessage ? "items-end" : "items-start"}`,
1271
1325
  children: [
1272
- senderLabel && /* @__PURE__ */ jsx4(
1326
+ senderLabel && /* @__PURE__ */ jsx5(
1273
1327
  "span",
1274
1328
  {
1275
1329
  className: "mb-1 px-1 font-medium",
@@ -1281,7 +1335,7 @@ function MessageItem({
1281
1335
  children: senderLabel
1282
1336
  }
1283
1337
  ),
1284
- /* @__PURE__ */ jsxs3(
1338
+ /* @__PURE__ */ jsxs4(
1285
1339
  "div",
1286
1340
  {
1287
1341
  className: "px-4 py-2.5",
@@ -1294,12 +1348,12 @@ function MessageItem({
1294
1348
  children: [
1295
1349
  message.messageType === "text" && (isOwnMessage ? (
1296
1350
  // User messages: plain text — no markdown parsing
1297
- /* @__PURE__ */ jsx4("span", { style: { whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: message.content })
1351
+ /* @__PURE__ */ jsx5("span", { style: { whiteSpace: "pre-wrap", wordBreak: "break-word" }, children: message.content })
1298
1352
  ) : (
1299
1353
  // Bot / agent messages: full markdown rendering
1300
- /* @__PURE__ */ jsx4(MarkdownMessage, { content: message.content, theme })
1354
+ /* @__PURE__ */ jsx5(MarkdownMessage, { content: message.content, theme })
1301
1355
  )),
1302
- message.messageType === "image" && /* @__PURE__ */ jsx4("div", { children: /* @__PURE__ */ jsx4(
1356
+ message.messageType === "image" && /* @__PURE__ */ jsx5("div", { children: /* @__PURE__ */ jsx5(
1303
1357
  "img",
1304
1358
  {
1305
1359
  src: message.content,
@@ -1308,8 +1362,8 @@ function MessageItem({
1308
1362
  loading: "lazy"
1309
1363
  }
1310
1364
  ) }),
1311
- message.messageType === "file" && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
1312
- /* @__PURE__ */ jsxs3(
1365
+ message.messageType === "file" && /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
1366
+ /* @__PURE__ */ jsxs4(
1313
1367
  "svg",
1314
1368
  {
1315
1369
  width: "18",
@@ -1322,12 +1376,12 @@ function MessageItem({
1322
1376
  strokeLinejoin: "round",
1323
1377
  "aria-hidden": "true",
1324
1378
  children: [
1325
- /* @__PURE__ */ jsx4("title", { children: "File" }),
1326
- /* @__PURE__ */ jsx4("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48" })
1379
+ /* @__PURE__ */ jsx5("title", { children: "File" }),
1380
+ /* @__PURE__ */ jsx5("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48" })
1327
1381
  ]
1328
1382
  }
1329
1383
  ),
1330
- /* @__PURE__ */ jsx4(
1384
+ /* @__PURE__ */ jsx5(
1331
1385
  "a",
1332
1386
  {
1333
1387
  href: message.content,
@@ -1345,12 +1399,12 @@ function MessageItem({
1345
1399
  ]
1346
1400
  }
1347
1401
  ),
1348
- showTimestamp && /* @__PURE__ */ jsxs3(
1402
+ showTimestamp && /* @__PURE__ */ jsxs4(
1349
1403
  "div",
1350
1404
  {
1351
1405
  className: `flex items-center gap-1.5 mt-1 px-1 ${isOwnMessage ? "flex-row-reverse" : "flex-row"}`,
1352
1406
  children: [
1353
- /* @__PURE__ */ jsx4(
1407
+ /* @__PURE__ */ jsx5(
1354
1408
  "span",
1355
1409
  {
1356
1410
  style: {
@@ -1363,8 +1417,8 @@ function MessageItem({
1363
1417
  })
1364
1418
  }
1365
1419
  ),
1366
- isOwnMessage && message.status && /* @__PURE__ */ jsxs3("span", { style: { color: textMuted }, children: [
1367
- message.status === "sent" && /* @__PURE__ */ jsxs3(
1420
+ isOwnMessage && message.status && /* @__PURE__ */ jsxs4("span", { style: { color: textMuted }, children: [
1421
+ message.status === "sent" && /* @__PURE__ */ jsxs4(
1368
1422
  "svg",
1369
1423
  {
1370
1424
  width: "14",
@@ -1377,12 +1431,12 @@ function MessageItem({
1377
1431
  strokeLinejoin: "round",
1378
1432
  "aria-hidden": "true",
1379
1433
  children: [
1380
- /* @__PURE__ */ jsx4("title", { children: "Sent" }),
1381
- /* @__PURE__ */ jsx4("polyline", { points: "20 6 9 17 4 12" })
1434
+ /* @__PURE__ */ jsx5("title", { children: "Sent" }),
1435
+ /* @__PURE__ */ jsx5("polyline", { points: "20 6 9 17 4 12" })
1382
1436
  ]
1383
1437
  }
1384
1438
  ),
1385
- message.status === "delivered" && /* @__PURE__ */ jsxs3(
1439
+ message.status === "delivered" && /* @__PURE__ */ jsxs4(
1386
1440
  "svg",
1387
1441
  {
1388
1442
  width: "14",
@@ -1395,13 +1449,13 @@ function MessageItem({
1395
1449
  strokeLinejoin: "round",
1396
1450
  "aria-hidden": "true",
1397
1451
  children: [
1398
- /* @__PURE__ */ jsx4("title", { children: "Delivered" }),
1399
- /* @__PURE__ */ jsx4("polyline", { points: "18 6 7 17 2 12" }),
1400
- /* @__PURE__ */ jsx4("polyline", { points: "22 6 11 17" })
1452
+ /* @__PURE__ */ jsx5("title", { children: "Delivered" }),
1453
+ /* @__PURE__ */ jsx5("polyline", { points: "18 6 7 17 2 12" }),
1454
+ /* @__PURE__ */ jsx5("polyline", { points: "22 6 11 17" })
1401
1455
  ]
1402
1456
  }
1403
1457
  ),
1404
- message.status === "read" && /* @__PURE__ */ jsxs3(
1458
+ message.status === "read" && /* @__PURE__ */ jsxs4(
1405
1459
  "svg",
1406
1460
  {
1407
1461
  width: "14",
@@ -1414,9 +1468,9 @@ function MessageItem({
1414
1468
  strokeLinejoin: "round",
1415
1469
  "aria-hidden": "true",
1416
1470
  children: [
1417
- /* @__PURE__ */ jsx4("title", { children: "Read" }),
1418
- /* @__PURE__ */ jsx4("polyline", { points: "18 6 7 17 2 12" }),
1419
- /* @__PURE__ */ jsx4("polyline", { points: "22 6 11 17" })
1471
+ /* @__PURE__ */ jsx5("title", { children: "Read" }),
1472
+ /* @__PURE__ */ jsx5("polyline", { points: "18 6 7 17 2 12" }),
1473
+ /* @__PURE__ */ jsx5("polyline", { points: "22 6 11 17" })
1420
1474
  ]
1421
1475
  }
1422
1476
  )
@@ -1434,7 +1488,7 @@ function MessageItem({
1434
1488
 
1435
1489
  // src/components/ThinkingIndicator.tsx
1436
1490
  import { useEffect as useEffect5, useRef as useRef3, useState as useState6 } from "react";
1437
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1491
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1438
1492
  var PHRASE_POOLS = {
1439
1493
  // ── Greetings & small talk ──
1440
1494
  greeting: [
@@ -1653,7 +1707,7 @@ function ThinkingIndicator({
1653
1707
  }
1654
1708
  return () => clearTimeout(timeout);
1655
1709
  }, [displayText, isDeleting, phraseIndex]);
1656
- return /* @__PURE__ */ jsxs4(
1710
+ return /* @__PURE__ */ jsxs5(
1657
1711
  "div",
1658
1712
  {
1659
1713
  className: "flex gap-2.5 mb-3",
@@ -1661,8 +1715,8 @@ function ThinkingIndicator({
1661
1715
  "aria-live": "polite",
1662
1716
  "aria-label": "Xcelsior is thinking",
1663
1717
  children: [
1664
- showAvatar && /* @__PURE__ */ jsx5("div", { className: "flex-shrink-0 mt-auto mb-5", children: /* @__PURE__ */ jsx5(XcelsiorAvatar, { size: 28 }) }),
1665
- /* @__PURE__ */ jsx5("div", { className: "flex flex-col items-start", children: /* @__PURE__ */ jsx5(
1718
+ showAvatar && /* @__PURE__ */ jsx6("div", { className: "flex-shrink-0 mt-auto mb-5", children: /* @__PURE__ */ jsx6(XcelsiorAvatar, { size: 28 }) }),
1719
+ /* @__PURE__ */ jsx6("div", { className: "flex flex-col items-start", children: /* @__PURE__ */ jsx6(
1666
1720
  "div",
1667
1721
  {
1668
1722
  style: {
@@ -1672,8 +1726,8 @@ function ThinkingIndicator({
1672
1726
  padding: "12px 16px",
1673
1727
  minWidth: 160
1674
1728
  },
1675
- children: /* @__PURE__ */ jsxs4("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
1676
- /* @__PURE__ */ jsx5("div", { style: { display: "flex", gap: 4, alignItems: "center" }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx5(
1729
+ children: /* @__PURE__ */ jsxs5("div", { style: { display: "flex", alignItems: "center", gap: 8 }, children: [
1730
+ /* @__PURE__ */ jsx6("div", { style: { display: "flex", gap: 4, alignItems: "center" }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx6(
1677
1731
  "span",
1678
1732
  {
1679
1733
  style: {
@@ -1687,7 +1741,7 @@ function ThinkingIndicator({
1687
1741
  },
1688
1742
  i
1689
1743
  )) }),
1690
- /* @__PURE__ */ jsxs4(
1744
+ /* @__PURE__ */ jsxs5(
1691
1745
  "span",
1692
1746
  {
1693
1747
  style: {
@@ -1698,7 +1752,7 @@ function ThinkingIndicator({
1698
1752
  },
1699
1753
  children: [
1700
1754
  displayText,
1701
- /* @__PURE__ */ jsx5(
1755
+ /* @__PURE__ */ jsx6(
1702
1756
  "span",
1703
1757
  {
1704
1758
  style: {
@@ -1724,7 +1778,7 @@ function ThinkingIndicator({
1724
1778
  }
1725
1779
 
1726
1780
  // src/components/MessageList.tsx
1727
- import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1781
+ import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1728
1782
  function MessageList({
1729
1783
  messages,
1730
1784
  currentUser,
@@ -1805,11 +1859,11 @@ function MessageList({
1805
1859
  return () => container.removeEventListener("scroll", handleScroll);
1806
1860
  }, [handleScroll]);
1807
1861
  if (isLoading) {
1808
- return /* @__PURE__ */ jsx6("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx6(Spinner, { size: "lg" }) });
1862
+ return /* @__PURE__ */ jsx7("div", { className: "flex items-center justify-center h-full", children: /* @__PURE__ */ jsx7(Spinner, { size: "lg" }) });
1809
1863
  }
1810
1864
  if (messages.length === 0) {
1811
- return /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center h-full text-center", style: { padding: "40px 32px" }, children: [
1812
- /* @__PURE__ */ jsx6(
1865
+ return /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-center justify-center h-full text-center", style: { padding: "40px 32px" }, children: [
1866
+ /* @__PURE__ */ jsx7(
1813
1867
  "h3",
1814
1868
  {
1815
1869
  className: "font-semibold mb-2",
@@ -1821,7 +1875,7 @@ function MessageList({
1821
1875
  children: "How can we help?"
1822
1876
  }
1823
1877
  ),
1824
- /* @__PURE__ */ jsx6(
1878
+ /* @__PURE__ */ jsx7(
1825
1879
  "p",
1826
1880
  {
1827
1881
  className: "max-w-[240px]",
@@ -1835,11 +1889,11 @@ function MessageList({
1835
1889
  children: "Ask us anything. We are here to help you get the most out of Xcelsior."
1836
1890
  }
1837
1891
  ),
1838
- /* @__PURE__ */ jsx6("div", { className: "flex flex-wrap justify-center gap-2", children: [
1892
+ /* @__PURE__ */ jsx7("div", { className: "flex flex-wrap justify-center gap-2", children: [
1839
1893
  { label: "Our services", message: "What services does Xcelsior offer?" },
1840
1894
  { label: "Get a quote", message: "I would like to get a quote for a project" },
1841
1895
  { label: "Support", message: "I need help with something" }
1842
- ].map((action) => /* @__PURE__ */ jsx6(
1896
+ ].map((action) => /* @__PURE__ */ jsx7(
1843
1897
  "button",
1844
1898
  {
1845
1899
  type: "button",
@@ -1871,14 +1925,14 @@ function MessageList({
1871
1925
  )) })
1872
1926
  ] });
1873
1927
  }
1874
- return /* @__PURE__ */ jsxs5(
1928
+ return /* @__PURE__ */ jsxs6(
1875
1929
  "div",
1876
1930
  {
1877
1931
  ref: containerRef,
1878
1932
  className: "flex-1 overflow-y-auto px-4 py-3",
1879
1933
  style: { scrollBehavior: "smooth" },
1880
1934
  children: [
1881
- /* @__PURE__ */ jsx6("style", { children: `
1935
+ /* @__PURE__ */ jsx7("style", { children: `
1882
1936
  @keyframes thinkingPulse {
1883
1937
  0%, 60%, 100% { opacity: 0.3; transform: scale(0.8); }
1884
1938
  30% { opacity: 1; transform: scale(1); }
@@ -1888,9 +1942,9 @@ function MessageList({
1888
1942
  50% { opacity: 0; }
1889
1943
  }
1890
1944
  ` }),
1891
- isLoadingMore && /* @__PURE__ */ jsx6("div", { className: "flex justify-center py-3", children: /* @__PURE__ */ jsx6(Spinner, { size: "sm" }) }),
1892
- /* @__PURE__ */ jsx6("div", { ref: loadMoreTriggerRef }),
1893
- messages.map((message) => /* @__PURE__ */ jsx6(
1945
+ isLoadingMore && /* @__PURE__ */ jsx7("div", { className: "flex justify-center py-3", children: /* @__PURE__ */ jsx7(Spinner, { size: "sm" }) }),
1946
+ /* @__PURE__ */ jsx7("div", { ref: loadMoreTriggerRef }),
1947
+ messages.map((message) => /* @__PURE__ */ jsx7(
1894
1948
  MessageItem,
1895
1949
  {
1896
1950
  message,
@@ -1901,10 +1955,10 @@ function MessageList({
1901
1955
  },
1902
1956
  message.id
1903
1957
  )),
1904
- isTyping && /* @__PURE__ */ jsxs5("div", { className: "flex gap-2.5 mb-3", children: [
1905
- /* @__PURE__ */ jsx6("div", { className: "flex-shrink-0 mt-auto mb-5", children: /* @__PURE__ */ jsx6(XcelsiorAvatar, { size: 28 }) }),
1906
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-start", children: [
1907
- /* @__PURE__ */ jsx6(
1958
+ isTyping && /* @__PURE__ */ jsxs6("div", { className: "flex gap-2.5 mb-3", children: [
1959
+ /* @__PURE__ */ jsx7("div", { className: "flex-shrink-0 mt-auto mb-5", children: /* @__PURE__ */ jsx7(XcelsiorAvatar, { size: 28 }) }),
1960
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-col items-start", children: [
1961
+ /* @__PURE__ */ jsx7(
1908
1962
  "div",
1909
1963
  {
1910
1964
  className: "px-4 py-3",
@@ -1913,7 +1967,7 @@ function MessageList({
1913
1967
  borderRadius: "18px 18px 18px 4px",
1914
1968
  boxShadow: isLightTheme ? "inset 0 0 0 1px rgba(0,0,0,0.06)" : "inset 0 0 0 0.5px rgba(255,255,255,0.06), inset 0 1px 0 0 rgba(255,255,255,0.08)"
1915
1969
  },
1916
- children: /* @__PURE__ */ jsx6("div", { className: "flex gap-1.5 items-center", style: { height: 16 }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx6(
1970
+ children: /* @__PURE__ */ jsx7("div", { className: "flex gap-1.5 items-center", style: { height: 16 }, children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx7(
1917
1971
  "span",
1918
1972
  {
1919
1973
  className: "rounded-full animate-bounce",
@@ -1929,7 +1983,7 @@ function MessageList({
1929
1983
  )) })
1930
1984
  }
1931
1985
  ),
1932
- typingUser && /* @__PURE__ */ jsxs5(
1986
+ typingUser && /* @__PURE__ */ jsxs6(
1933
1987
  "span",
1934
1988
  {
1935
1989
  className: "mt-1 px-1",
@@ -1946,14 +2000,14 @@ function MessageList({
1946
2000
  )
1947
2001
  ] })
1948
2002
  ] }),
1949
- isBotThinking && !isTyping && /* @__PURE__ */ jsx6(
2003
+ isBotThinking && !isTyping && /* @__PURE__ */ jsx7(
1950
2004
  ThinkingIndicator,
1951
2005
  {
1952
2006
  theme,
1953
2007
  lastUserMessage: messages.filter((m) => m.senderType === "customer").pop()?.content
1954
2008
  }
1955
2009
  ),
1956
- /* @__PURE__ */ jsx6("div", { ref: messagesEndRef })
2010
+ /* @__PURE__ */ jsx7("div", { ref: messagesEndRef })
1957
2011
  ]
1958
2012
  }
1959
2013
  );
@@ -1963,7 +2017,7 @@ function MessageList({
1963
2017
  import { useEffect as useEffect7, useRef as useRef5, useState as useState7 } from "react";
1964
2018
  import { createPortal } from "react-dom";
1965
2019
  import Picker from "@emoji-mart/react";
1966
- import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
2020
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1967
2021
  function isLightColor(color) {
1968
2022
  let r = 0, g = 0, b = 0;
1969
2023
  if (color.startsWith("#")) {
@@ -2141,7 +2195,7 @@ ${uploadedFile.markdown}
2141
2195
  };
2142
2196
  const canSend = message.trim().length > 0 && !disabled;
2143
2197
  const placeholderColor = isLightTheme ? "rgba(0,0,0,0.35)" : "rgba(247,247,248,0.3)";
2144
- return /* @__PURE__ */ jsxs6(
2198
+ return /* @__PURE__ */ jsxs7(
2145
2199
  "div",
2146
2200
  {
2147
2201
  className: "px-4 py-3",
@@ -2149,7 +2203,7 @@ ${uploadedFile.markdown}
2149
2203
  borderTop: isLightTheme ? "1px solid rgba(0,0,0,0.06)" : "1px solid rgba(255,255,255,0.06)"
2150
2204
  },
2151
2205
  children: [
2152
- /* @__PURE__ */ jsxs6(
2206
+ /* @__PURE__ */ jsxs7(
2153
2207
  "div",
2154
2208
  {
2155
2209
  className: "relative flex items-center rounded-full transition-all duration-200",
@@ -2161,8 +2215,8 @@ ${uploadedFile.markdown}
2161
2215
  backdropFilter: "blur(32px)"
2162
2216
  },
2163
2217
  children: [
2164
- /* @__PURE__ */ jsx7("style", { children: `.xchat-input::placeholder { color: ${placeholderColor}; }` }),
2165
- /* @__PURE__ */ jsx7(
2218
+ /* @__PURE__ */ jsx8("style", { children: `.xchat-input::placeholder { color: ${placeholderColor}; }` }),
2219
+ /* @__PURE__ */ jsx8(
2166
2220
  "textarea",
2167
2221
  {
2168
2222
  ref: textAreaRef,
@@ -2191,8 +2245,8 @@ ${uploadedFile.markdown}
2191
2245
  disabled
2192
2246
  }
2193
2247
  ),
2194
- /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 px-2 shrink-0", children: [
2195
- enableEmoji && /* @__PURE__ */ jsx7(
2248
+ /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-1 px-2 shrink-0", children: [
2249
+ enableEmoji && /* @__PURE__ */ jsx8(
2196
2250
  "button",
2197
2251
  {
2198
2252
  ref: emojiButtonRef,
@@ -2222,7 +2276,7 @@ ${uploadedFile.markdown}
2222
2276
  },
2223
2277
  disabled,
2224
2278
  "aria-label": "Add emoji",
2225
- children: /* @__PURE__ */ jsxs6(
2279
+ children: /* @__PURE__ */ jsxs7(
2226
2280
  "svg",
2227
2281
  {
2228
2282
  width: "18",
@@ -2235,18 +2289,18 @@ ${uploadedFile.markdown}
2235
2289
  strokeLinejoin: "round",
2236
2290
  "aria-hidden": "true",
2237
2291
  children: [
2238
- /* @__PURE__ */ jsx7("title", { children: "Emoji" }),
2239
- /* @__PURE__ */ jsx7("circle", { cx: "12", cy: "12", r: "10" }),
2240
- /* @__PURE__ */ jsx7("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
2241
- /* @__PURE__ */ jsx7("line", { x1: "9", y1: "9", x2: "9.01", y2: "9" }),
2242
- /* @__PURE__ */ jsx7("line", { x1: "15", y1: "9", x2: "15.01", y2: "9" })
2292
+ /* @__PURE__ */ jsx8("title", { children: "Emoji" }),
2293
+ /* @__PURE__ */ jsx8("circle", { cx: "12", cy: "12", r: "10" }),
2294
+ /* @__PURE__ */ jsx8("path", { d: "M8 14s1.5 2 4 2 4-2 4-2" }),
2295
+ /* @__PURE__ */ jsx8("line", { x1: "9", y1: "9", x2: "9.01", y2: "9" }),
2296
+ /* @__PURE__ */ jsx8("line", { x1: "15", y1: "9", x2: "15.01", y2: "9" })
2243
2297
  ]
2244
2298
  }
2245
2299
  )
2246
2300
  }
2247
2301
  ),
2248
- enableFileUpload && fileUpload.canUpload && /* @__PURE__ */ jsxs6(Fragment, { children: [
2249
- /* @__PURE__ */ jsx7(
2302
+ enableFileUpload && fileUpload.canUpload && /* @__PURE__ */ jsxs7(Fragment2, { children: [
2303
+ /* @__PURE__ */ jsx8(
2250
2304
  "button",
2251
2305
  {
2252
2306
  type: "button",
@@ -2266,7 +2320,7 @@ ${uploadedFile.markdown}
2266
2320
  },
2267
2321
  disabled: disabled || fileUpload.isUploading,
2268
2322
  "aria-label": "Attach file",
2269
- children: fileUpload.isUploading ? /* @__PURE__ */ jsxs6(
2323
+ children: fileUpload.isUploading ? /* @__PURE__ */ jsxs7(
2270
2324
  "svg",
2271
2325
  {
2272
2326
  width: "18",
@@ -2278,11 +2332,11 @@ ${uploadedFile.markdown}
2278
2332
  className: "animate-spin",
2279
2333
  "aria-hidden": "true",
2280
2334
  children: [
2281
- /* @__PURE__ */ jsx7("title", { children: "Uploading" }),
2282
- /* @__PURE__ */ jsx7("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
2335
+ /* @__PURE__ */ jsx8("title", { children: "Uploading" }),
2336
+ /* @__PURE__ */ jsx8("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
2283
2337
  ]
2284
2338
  }
2285
- ) : /* @__PURE__ */ jsxs6(
2339
+ ) : /* @__PURE__ */ jsxs7(
2286
2340
  "svg",
2287
2341
  {
2288
2342
  width: "18",
@@ -2295,14 +2349,14 @@ ${uploadedFile.markdown}
2295
2349
  strokeLinejoin: "round",
2296
2350
  "aria-hidden": "true",
2297
2351
  children: [
2298
- /* @__PURE__ */ jsx7("title", { children: "Attach file" }),
2299
- /* @__PURE__ */ jsx7("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48" })
2352
+ /* @__PURE__ */ jsx8("title", { children: "Attach file" }),
2353
+ /* @__PURE__ */ jsx8("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48" })
2300
2354
  ]
2301
2355
  }
2302
2356
  )
2303
2357
  }
2304
2358
  ),
2305
- /* @__PURE__ */ jsx7(
2359
+ /* @__PURE__ */ jsx8(
2306
2360
  "input",
2307
2361
  {
2308
2362
  ref: fileInputRef,
@@ -2313,7 +2367,7 @@ ${uploadedFile.markdown}
2313
2367
  }
2314
2368
  )
2315
2369
  ] }),
2316
- /* @__PURE__ */ jsx7(
2370
+ /* @__PURE__ */ jsx8(
2317
2371
  "button",
2318
2372
  {
2319
2373
  type: "button",
@@ -2328,7 +2382,7 @@ ${uploadedFile.markdown}
2328
2382
  boxShadow: canSend ? `0 2px 8px -2px ${primaryColor}60` : "none"
2329
2383
  },
2330
2384
  "aria-label": "Send message",
2331
- children: /* @__PURE__ */ jsxs6(
2385
+ children: /* @__PURE__ */ jsxs7(
2332
2386
  "svg",
2333
2387
  {
2334
2388
  width: "18",
@@ -2341,9 +2395,9 @@ ${uploadedFile.markdown}
2341
2395
  strokeLinejoin: "round",
2342
2396
  "aria-hidden": "true",
2343
2397
  children: [
2344
- /* @__PURE__ */ jsx7("title", { children: "Send" }),
2345
- /* @__PURE__ */ jsx7("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
2346
- /* @__PURE__ */ jsx7("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
2398
+ /* @__PURE__ */ jsx8("title", { children: "Send" }),
2399
+ /* @__PURE__ */ jsx8("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
2400
+ /* @__PURE__ */ jsx8("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
2347
2401
  ]
2348
2402
  }
2349
2403
  )
@@ -2353,8 +2407,8 @@ ${uploadedFile.markdown}
2353
2407
  ]
2354
2408
  }
2355
2409
  ),
2356
- fileUpload.isUploading && /* @__PURE__ */ jsxs6("div", { className: "mt-2 px-1", children: [
2357
- /* @__PURE__ */ jsx7(
2410
+ fileUpload.isUploading && /* @__PURE__ */ jsxs7("div", { className: "mt-2 px-1", children: [
2411
+ /* @__PURE__ */ jsx8(
2358
2412
  "div",
2359
2413
  {
2360
2414
  className: "w-full rounded-full overflow-hidden",
@@ -2362,7 +2416,7 @@ ${uploadedFile.markdown}
2362
2416
  height: 3,
2363
2417
  backgroundColor: isLightTheme ? "rgba(0,0,0,0.06)" : "rgba(255,255,255,0.06)"
2364
2418
  },
2365
- children: /* @__PURE__ */ jsx7(
2419
+ children: /* @__PURE__ */ jsx8(
2366
2420
  "div",
2367
2421
  {
2368
2422
  className: "h-full rounded-full transition-all duration-300",
@@ -2374,7 +2428,7 @@ ${uploadedFile.markdown}
2374
2428
  )
2375
2429
  }
2376
2430
  ),
2377
- /* @__PURE__ */ jsxs6(
2431
+ /* @__PURE__ */ jsxs7(
2378
2432
  "p",
2379
2433
  {
2380
2434
  className: "mt-1",
@@ -2392,7 +2446,7 @@ ${uploadedFile.markdown}
2392
2446
  )
2393
2447
  ] }),
2394
2448
  showEmojiPicker && emojiData && emojiPickerPosition && typeof document !== "undefined" && createPortal(
2395
- /* @__PURE__ */ jsx7(
2449
+ /* @__PURE__ */ jsx8(
2396
2450
  "div",
2397
2451
  {
2398
2452
  ref: emojiPickerRef,
@@ -2407,7 +2461,7 @@ ${uploadedFile.markdown}
2407
2461
  "0 16px 48px -8px rgba(0,0,0,0.5)"
2408
2462
  ].join(", ")
2409
2463
  },
2410
- children: /* @__PURE__ */ jsx7(
2464
+ children: /* @__PURE__ */ jsx8(
2411
2465
  Picker,
2412
2466
  {
2413
2467
  data: emojiData,
@@ -2433,7 +2487,7 @@ ${uploadedFile.markdown}
2433
2487
  }
2434
2488
 
2435
2489
  // src/components/ChatWidget.tsx
2436
- import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
2490
+ import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2437
2491
  function getAnonymousUser() {
2438
2492
  let anonId;
2439
2493
  try {
@@ -2567,14 +2621,14 @@ function ChatWidget({
2567
2621
  outlineOffset: -1,
2568
2622
  transition: "outline 150ms ease"
2569
2623
  };
2570
- return /* @__PURE__ */ jsxs7(
2624
+ return /* @__PURE__ */ jsxs8(
2571
2625
  "div",
2572
2626
  {
2573
2627
  className: isFullPage ? `flex flex-col h-full ${className}` : `fixed bottom-20 ${positionClass} z-50 flex flex-col overflow-hidden ${className}`,
2574
2628
  style: { ...containerStyle, ...dotGridBg, ...edgeHintStyle },
2575
2629
  ...!isFullPage ? containerResizeProps : {},
2576
2630
  children: [
2577
- !isFullPage && /* @__PURE__ */ jsx8(
2631
+ !isFullPage && /* @__PURE__ */ jsx9(
2578
2632
  ChatHeader,
2579
2633
  {
2580
2634
  agent: effectiveUser.type === "customer" ? {
@@ -2588,7 +2642,7 @@ function ChatWidget({
2588
2642
  theme: config.theme
2589
2643
  }
2590
2644
  ),
2591
- !websocket.isConnected && /* @__PURE__ */ jsx8(
2645
+ !websocket.isConnected && /* @__PURE__ */ jsx9(
2592
2646
  "div",
2593
2647
  {
2594
2648
  className: "px-4 py-2",
@@ -2596,15 +2650,15 @@ function ChatWidget({
2596
2650
  backgroundColor: isLightTheme ? "rgba(255,169,56,0.08)" : "rgba(255,169,56,0.06)",
2597
2651
  borderBottom: `1px solid rgba(255,169,56,${isLightTheme ? "0.15" : "0.12"})`
2598
2652
  },
2599
- children: /* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
2600
- /* @__PURE__ */ jsx8(
2653
+ children: /* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-2", children: [
2654
+ /* @__PURE__ */ jsx9(
2601
2655
  "div",
2602
2656
  {
2603
2657
  className: "w-1.5 h-1.5 rounded-full animate-pulse",
2604
2658
  style: { backgroundColor: config.theme?.statusCaution || "#ffa938" }
2605
2659
  }
2606
2660
  ),
2607
- /* @__PURE__ */ jsx8(
2661
+ /* @__PURE__ */ jsx9(
2608
2662
  "span",
2609
2663
  {
2610
2664
  style: {
@@ -2615,7 +2669,7 @@ function ChatWidget({
2615
2669
  children: "Reconnecting..."
2616
2670
  }
2617
2671
  ),
2618
- /* @__PURE__ */ jsx8(
2672
+ /* @__PURE__ */ jsx9(
2619
2673
  "button",
2620
2674
  {
2621
2675
  type: "button",
@@ -2639,8 +2693,8 @@ function ChatWidget({
2639
2693
  ] })
2640
2694
  }
2641
2695
  ),
2642
- isLoading ? /* @__PURE__ */ jsx8("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs7("div", { className: "text-center", children: [
2643
- /* @__PURE__ */ jsx8(
2696
+ isLoading ? /* @__PURE__ */ jsx9("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs8("div", { className: "text-center", children: [
2697
+ /* @__PURE__ */ jsx9(
2644
2698
  "div",
2645
2699
  {
2646
2700
  className: "w-7 h-7 border-2 border-t-transparent rounded-full animate-spin mx-auto mb-3",
@@ -2650,7 +2704,7 @@ function ChatWidget({
2650
2704
  }
2651
2705
  }
2652
2706
  ),
2653
- /* @__PURE__ */ jsx8(
2707
+ /* @__PURE__ */ jsx9(
2654
2708
  "p",
2655
2709
  {
2656
2710
  style: {
@@ -2661,7 +2715,7 @@ function ChatWidget({
2661
2715
  children: "Loading messages..."
2662
2716
  }
2663
2717
  )
2664
- ] }) }) : /* @__PURE__ */ jsx8(
2718
+ ] }) }) : /* @__PURE__ */ jsx9(
2665
2719
  MessageList,
2666
2720
  {
2667
2721
  messages,
@@ -2677,7 +2731,7 @@ function ChatWidget({
2677
2731
  isBotThinking
2678
2732
  }
2679
2733
  ),
2680
- /* @__PURE__ */ jsx8(
2734
+ /* @__PURE__ */ jsx9(
2681
2735
  ChatInput,
2682
2736
  {
2683
2737
  onSend: handleSendMessage,
@@ -2687,7 +2741,7 @@ function ChatWidget({
2687
2741
  disabled: !websocket.isConnected
2688
2742
  }
2689
2743
  ),
2690
- !isFullPage && /* @__PURE__ */ jsx8(
2744
+ !isFullPage && /* @__PURE__ */ jsx9(
2691
2745
  "div",
2692
2746
  {
2693
2747
  className: "px-4 py-1.5 text-center",
@@ -2695,7 +2749,7 @@ function ChatWidget({
2695
2749
  borderTop: isLightTheme ? "1px solid rgba(0,0,0,0.06)" : "1px solid rgba(255,255,255,0.06)",
2696
2750
  backgroundColor: isLightTheme ? "rgba(0,0,0,0.03)" : "rgba(0,0,0,0.2)"
2697
2751
  },
2698
- children: /* @__PURE__ */ jsxs7(
2752
+ children: /* @__PURE__ */ jsxs8(
2699
2753
  "p",
2700
2754
  {
2701
2755
  style: {
@@ -2706,7 +2760,7 @@ function ChatWidget({
2706
2760
  children: [
2707
2761
  "Powered by",
2708
2762
  " ",
2709
- /* @__PURE__ */ jsx8("span", { style: {
2763
+ /* @__PURE__ */ jsx9("span", { style: {
2710
2764
  fontWeight: 600,
2711
2765
  color: isLightTheme ? "rgba(0,0,0,0.5)" : "rgba(247,247,248,0.45)"
2712
2766
  }, children: "Xcelsior" })
@@ -2725,7 +2779,7 @@ import { useCallback as useCallback8, useEffect as useEffect10, useState as useS
2725
2779
 
2726
2780
  // src/components/PreChatForm.tsx
2727
2781
  import { useState as useState8 } from "react";
2728
- import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2782
+ import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2729
2783
  function PreChatForm({
2730
2784
  onSubmit,
2731
2785
  className = "",
@@ -2786,7 +2840,7 @@ function PreChatForm({
2786
2840
  transition: "box-shadow 0.2s ease",
2787
2841
  caretColor: "#337eff"
2788
2842
  });
2789
- return /* @__PURE__ */ jsxs8(
2843
+ return /* @__PURE__ */ jsxs9(
2790
2844
  "div",
2791
2845
  {
2792
2846
  className: `fixed bottom-4 right-4 z-50 flex flex-col overflow-hidden ${className}`,
@@ -2806,7 +2860,7 @@ function PreChatForm({
2806
2860
  backgroundSize: "24px 24px"
2807
2861
  },
2808
2862
  children: [
2809
- /* @__PURE__ */ jsxs8(
2863
+ /* @__PURE__ */ jsxs9(
2810
2864
  "div",
2811
2865
  {
2812
2866
  className: "relative text-white overflow-hidden",
@@ -2814,7 +2868,7 @@ function PreChatForm({
2814
2868
  background: "linear-gradient(135deg, #337eff 0%, #005eff 50%, #001a66 100%)"
2815
2869
  },
2816
2870
  children: [
2817
- /* @__PURE__ */ jsx9(
2871
+ /* @__PURE__ */ jsx10(
2818
2872
  "div",
2819
2873
  {
2820
2874
  className: "absolute inset-0 pointer-events-none",
@@ -2823,9 +2877,9 @@ function PreChatForm({
2823
2877
  }
2824
2878
  }
2825
2879
  ),
2826
- /* @__PURE__ */ jsx9("div", { className: "relative px-5 py-4", children: /* @__PURE__ */ jsxs8("div", { className: "flex items-start justify-between", children: [
2827
- /* @__PURE__ */ jsxs8("div", { className: "flex-1", children: [
2828
- /* @__PURE__ */ jsx9(
2880
+ /* @__PURE__ */ jsx10("div", { className: "relative px-5 py-4", children: /* @__PURE__ */ jsxs9("div", { className: "flex items-start justify-between", children: [
2881
+ /* @__PURE__ */ jsxs9("div", { className: "flex-1", children: [
2882
+ /* @__PURE__ */ jsx10(
2829
2883
  "h2",
2830
2884
  {
2831
2885
  className: "font-semibold",
@@ -2836,7 +2890,7 @@ function PreChatForm({
2836
2890
  children: "Start a Conversation"
2837
2891
  }
2838
2892
  ),
2839
- /* @__PURE__ */ jsx9(
2893
+ /* @__PURE__ */ jsx10(
2840
2894
  "p",
2841
2895
  {
2842
2896
  className: "mt-1",
@@ -2849,8 +2903,8 @@ function PreChatForm({
2849
2903
  }
2850
2904
  )
2851
2905
  ] }),
2852
- /* @__PURE__ */ jsxs8("div", { className: "flex gap-1 ml-2", children: [
2853
- /* @__PURE__ */ jsx9(
2906
+ /* @__PURE__ */ jsxs9("div", { className: "flex gap-1 ml-2", children: [
2907
+ /* @__PURE__ */ jsx10(
2854
2908
  "button",
2855
2909
  {
2856
2910
  type: "button",
@@ -2864,7 +2918,7 @@ function PreChatForm({
2864
2918
  e.currentTarget.style.backgroundColor = "transparent";
2865
2919
  },
2866
2920
  "aria-label": "Minimize chat",
2867
- children: /* @__PURE__ */ jsxs8(
2921
+ children: /* @__PURE__ */ jsxs9(
2868
2922
  "svg",
2869
2923
  {
2870
2924
  width: "18",
@@ -2873,8 +2927,8 @@ function PreChatForm({
2873
2927
  stroke: "currentColor",
2874
2928
  viewBox: "0 0 24 24",
2875
2929
  children: [
2876
- /* @__PURE__ */ jsx9("title", { children: "Minimize" }),
2877
- /* @__PURE__ */ jsx9(
2930
+ /* @__PURE__ */ jsx10("title", { children: "Minimize" }),
2931
+ /* @__PURE__ */ jsx10(
2878
2932
  "path",
2879
2933
  {
2880
2934
  strokeLinecap: "round",
@@ -2888,7 +2942,7 @@ function PreChatForm({
2888
2942
  )
2889
2943
  }
2890
2944
  ),
2891
- /* @__PURE__ */ jsx9(
2945
+ /* @__PURE__ */ jsx10(
2892
2946
  "button",
2893
2947
  {
2894
2948
  type: "button",
@@ -2902,7 +2956,7 @@ function PreChatForm({
2902
2956
  e.currentTarget.style.backgroundColor = "transparent";
2903
2957
  },
2904
2958
  "aria-label": "Close chat",
2905
- children: /* @__PURE__ */ jsxs8(
2959
+ children: /* @__PURE__ */ jsxs9(
2906
2960
  "svg",
2907
2961
  {
2908
2962
  width: "18",
@@ -2911,8 +2965,8 @@ function PreChatForm({
2911
2965
  stroke: "currentColor",
2912
2966
  viewBox: "0 0 24 24",
2913
2967
  children: [
2914
- /* @__PURE__ */ jsx9("title", { children: "Close" }),
2915
- /* @__PURE__ */ jsx9(
2968
+ /* @__PURE__ */ jsx10("title", { children: "Close" }),
2969
+ /* @__PURE__ */ jsx10(
2916
2970
  "path",
2917
2971
  {
2918
2972
  strokeLinecap: "round",
@@ -2928,7 +2982,7 @@ function PreChatForm({
2928
2982
  )
2929
2983
  ] })
2930
2984
  ] }) }),
2931
- /* @__PURE__ */ jsx9(
2985
+ /* @__PURE__ */ jsx10(
2932
2986
  "div",
2933
2987
  {
2934
2988
  className: "h-px",
@@ -2940,9 +2994,9 @@ function PreChatForm({
2940
2994
  ]
2941
2995
  }
2942
2996
  ),
2943
- /* @__PURE__ */ jsxs8("form", { onSubmit: handleSubmit, className: "p-5 flex flex-col gap-4", children: [
2944
- /* @__PURE__ */ jsxs8("div", { children: [
2945
- /* @__PURE__ */ jsxs8(
2997
+ /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, className: "p-5 flex flex-col gap-4", children: [
2998
+ /* @__PURE__ */ jsxs9("div", { children: [
2999
+ /* @__PURE__ */ jsxs9(
2946
3000
  "label",
2947
3001
  {
2948
3002
  htmlFor: "chat-name",
@@ -2954,11 +3008,11 @@ function PreChatForm({
2954
3008
  },
2955
3009
  children: [
2956
3010
  "Name ",
2957
- /* @__PURE__ */ jsx9("span", { style: { color: "#ff6363" }, children: "*" })
3011
+ /* @__PURE__ */ jsx10("span", { style: { color: "#ff6363" }, children: "*" })
2958
3012
  ]
2959
3013
  }
2960
3014
  ),
2961
- /* @__PURE__ */ jsx9(
3015
+ /* @__PURE__ */ jsx10(
2962
3016
  "input",
2963
3017
  {
2964
3018
  type: "text",
@@ -2978,7 +3032,7 @@ function PreChatForm({
2978
3032
  autoComplete: "name"
2979
3033
  }
2980
3034
  ),
2981
- errors.name && /* @__PURE__ */ jsx9(
3035
+ errors.name && /* @__PURE__ */ jsx10(
2982
3036
  "p",
2983
3037
  {
2984
3038
  className: "mt-1.5",
@@ -2992,8 +3046,8 @@ function PreChatForm({
2992
3046
  }
2993
3047
  )
2994
3048
  ] }),
2995
- /* @__PURE__ */ jsxs8("div", { children: [
2996
- /* @__PURE__ */ jsxs8(
3049
+ /* @__PURE__ */ jsxs9("div", { children: [
3050
+ /* @__PURE__ */ jsxs9(
2997
3051
  "label",
2998
3052
  {
2999
3053
  htmlFor: "chat-email",
@@ -3005,11 +3059,11 @@ function PreChatForm({
3005
3059
  },
3006
3060
  children: [
3007
3061
  "Email ",
3008
- /* @__PURE__ */ jsx9("span", { style: { color: "#ff6363" }, children: "*" })
3062
+ /* @__PURE__ */ jsx10("span", { style: { color: "#ff6363" }, children: "*" })
3009
3063
  ]
3010
3064
  }
3011
3065
  ),
3012
- /* @__PURE__ */ jsx9(
3066
+ /* @__PURE__ */ jsx10(
3013
3067
  "input",
3014
3068
  {
3015
3069
  type: "email",
@@ -3029,7 +3083,7 @@ function PreChatForm({
3029
3083
  autoComplete: "email"
3030
3084
  }
3031
3085
  ),
3032
- errors.email && /* @__PURE__ */ jsx9(
3086
+ errors.email && /* @__PURE__ */ jsx10(
3033
3087
  "p",
3034
3088
  {
3035
3089
  className: "mt-1.5",
@@ -3043,7 +3097,7 @@ function PreChatForm({
3043
3097
  }
3044
3098
  )
3045
3099
  ] }),
3046
- /* @__PURE__ */ jsx9(
3100
+ /* @__PURE__ */ jsx10(
3047
3101
  "button",
3048
3102
  {
3049
3103
  type: "submit",
@@ -3065,8 +3119,8 @@ function PreChatForm({
3065
3119
  onMouseLeave: (e) => {
3066
3120
  e.currentTarget.style.boxShadow = "0 4px 16px -4px rgba(51,126,255,0.4)";
3067
3121
  },
3068
- children: isSubmitting ? /* @__PURE__ */ jsxs8("span", { className: "flex items-center justify-center gap-2", children: [
3069
- /* @__PURE__ */ jsxs8(
3122
+ children: isSubmitting ? /* @__PURE__ */ jsxs9("span", { className: "flex items-center justify-center gap-2", children: [
3123
+ /* @__PURE__ */ jsxs9(
3070
3124
  "svg",
3071
3125
  {
3072
3126
  className: "animate-spin",
@@ -3078,8 +3132,8 @@ function PreChatForm({
3078
3132
  strokeWidth: "2",
3079
3133
  "aria-label": "Loading",
3080
3134
  children: [
3081
- /* @__PURE__ */ jsx9("title", { children: "Loading" }),
3082
- /* @__PURE__ */ jsx9("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
3135
+ /* @__PURE__ */ jsx10("title", { children: "Loading" }),
3136
+ /* @__PURE__ */ jsx10("path", { d: "M21 12a9 9 0 11-6.219-8.56" })
3083
3137
  ]
3084
3138
  }
3085
3139
  ),
@@ -3087,7 +3141,7 @@ function PreChatForm({
3087
3141
  ] }) : "Start Chat"
3088
3142
  }
3089
3143
  ),
3090
- /* @__PURE__ */ jsx9(
3144
+ /* @__PURE__ */ jsx10(
3091
3145
  "p",
3092
3146
  {
3093
3147
  className: "text-center",
@@ -3100,7 +3154,7 @@ function PreChatForm({
3100
3154
  }
3101
3155
  )
3102
3156
  ] }),
3103
- /* @__PURE__ */ jsx9(
3157
+ /* @__PURE__ */ jsx10(
3104
3158
  "div",
3105
3159
  {
3106
3160
  className: "px-4 py-1.5 text-center",
@@ -3108,7 +3162,7 @@ function PreChatForm({
3108
3162
  borderTop: "1px solid rgba(255,255,255,0.06)",
3109
3163
  backgroundColor: "rgba(0,0,0,0.2)"
3110
3164
  },
3111
- children: /* @__PURE__ */ jsxs8(
3165
+ children: /* @__PURE__ */ jsxs9(
3112
3166
  "p",
3113
3167
  {
3114
3168
  style: {
@@ -3119,7 +3173,7 @@ function PreChatForm({
3119
3173
  children: [
3120
3174
  "Powered by",
3121
3175
  " ",
3122
- /* @__PURE__ */ jsx9("span", { style: { fontWeight: 600, color: "rgba(247,247,248,0.45)" }, children: "Xcelsior" })
3176
+ /* @__PURE__ */ jsx10("span", { style: { fontWeight: 600, color: "rgba(247,247,248,0.45)" }, children: "Xcelsior" })
3123
3177
  ]
3124
3178
  }
3125
3179
  )
@@ -3233,7 +3287,7 @@ function useChatWidgetState({
3233
3287
  }
3234
3288
 
3235
3289
  // src/components/Chat.tsx
3236
- import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
3290
+ import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3237
3291
  function generateSessionId() {
3238
3292
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
3239
3293
  return crypto.randomUUID();
@@ -3364,7 +3418,7 @@ function Chat({
3364
3418
  const primaryColor = config.theme?.primary || "#337eff";
3365
3419
  const primaryStrong = config.theme?.primaryStrong || "#005eff";
3366
3420
  if (currentState === "minimized") {
3367
- return /* @__PURE__ */ jsx10("div", { className: `fixed bottom-5 ${positionClass} z-50 ${className}`, children: /* @__PURE__ */ jsxs9(
3421
+ return /* @__PURE__ */ jsx11("div", { className: `fixed bottom-5 ${positionClass} z-50 ${className}`, children: /* @__PURE__ */ jsxs10(
3368
3422
  "button",
3369
3423
  {
3370
3424
  type: "button",
@@ -3389,8 +3443,8 @@ function Chat({
3389
3443
  "aria-label": "Open chat",
3390
3444
  ...handlers,
3391
3445
  children: [
3392
- /* @__PURE__ */ jsx10(ChatBubbleIcon, { size: 28, color: "white", className: "pointer-events-none" }),
3393
- /* @__PURE__ */ jsx10(
3446
+ /* @__PURE__ */ jsx11(ChatBubbleIcon, { size: 28, color: "white", className: "pointer-events-none" }),
3447
+ /* @__PURE__ */ jsx11(
3394
3448
  "span",
3395
3449
  {
3396
3450
  className: "absolute inset-0 rounded-full animate-ping pointer-events-none",
@@ -3406,7 +3460,7 @@ function Chat({
3406
3460
  ) });
3407
3461
  }
3408
3462
  if (identityMode === "form" && (!userInfo || !userInfo.email || !userInfo.name)) {
3409
- return /* @__PURE__ */ jsx10(
3463
+ return /* @__PURE__ */ jsx11(
3410
3464
  PreChatForm,
3411
3465
  {
3412
3466
  onSubmit: handlePreChatSubmit,
@@ -3432,7 +3486,7 @@ function Chat({
3432
3486
  transform: "translateY(12px) scale(0.97)",
3433
3487
  transition: "opacity 0.2s ease-in, transform 0.2s ease-in"
3434
3488
  };
3435
- return /* @__PURE__ */ jsx10("div", { style: widgetAnimationStyle, children: /* @__PURE__ */ jsx10(
3489
+ return /* @__PURE__ */ jsx11("div", { style: widgetAnimationStyle, children: /* @__PURE__ */ jsx11(
3436
3490
  ChatWidget,
3437
3491
  {
3438
3492
  config: fullConfig,
@@ -3445,12 +3499,12 @@ function Chat({
3445
3499
  }
3446
3500
 
3447
3501
  // src/components/TypingIndicator.tsx
3448
- import { jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
3502
+ import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
3449
3503
  function TypingIndicator({ isTyping, userName }) {
3450
3504
  if (!isTyping) {
3451
3505
  return null;
3452
3506
  }
3453
- return /* @__PURE__ */ jsx11(
3507
+ return /* @__PURE__ */ jsx12(
3454
3508
  "div",
3455
3509
  {
3456
3510
  className: "px-4 py-2",
@@ -3458,8 +3512,8 @@ function TypingIndicator({ isTyping, userName }) {
3458
3512
  borderTop: "1px solid rgba(255,255,255,0.06)",
3459
3513
  backgroundColor: "rgba(0,0,0,0.15)"
3460
3514
  },
3461
- children: /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-2", children: [
3462
- /* @__PURE__ */ jsx11("div", { className: "flex gap-1", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx11(
3515
+ children: /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-2", children: [
3516
+ /* @__PURE__ */ jsx12("div", { className: "flex gap-1", children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx12(
3463
3517
  "span",
3464
3518
  {
3465
3519
  className: "rounded-full animate-bounce",
@@ -3473,7 +3527,7 @@ function TypingIndicator({ isTyping, userName }) {
3473
3527
  },
3474
3528
  i
3475
3529
  )) }),
3476
- /* @__PURE__ */ jsx11(
3530
+ /* @__PURE__ */ jsx12(
3477
3531
  "span",
3478
3532
  {
3479
3533
  style: {