@ihoomanai/chat-widget 2.5.4 → 2.5.6
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.cjs.js +30 -14
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +30 -14
- package/dist/index.esm.js.map +1 -1
- package/dist/index.esm.min.js +1 -1
- package/dist/index.esm.min.js.map +1 -1
- package/dist/index.umd.js +30 -14
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/widget.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/widget.ts +31 -13
package/src/widget.ts
CHANGED
|
@@ -439,7 +439,7 @@ function createWidget(): void {
|
|
|
439
439
|
<div class="ihooman-history-view">
|
|
440
440
|
<div class="ihooman-history-header">
|
|
441
441
|
<span class="ihooman-history-title">Your Conversations</span>
|
|
442
|
-
<button class="ihooman-history-new" style="display: inline-flex; align-items: center; gap: 4px; background: linear-gradient(135deg, ${config.gradientFrom}, ${config.gradientTo}); color: white; border: none; padding: 6px
|
|
442
|
+
<button class="ihooman-history-new" style="all: revert; display: inline-flex !important; align-items: center !important; gap: 4px !important; background: linear-gradient(135deg, ${config.gradientFrom}, ${config.gradientTo}) !important; color: white !important; border: none !important; padding: 6px 10px !important; border-radius: 6px !important; font-size: 12px !important; font-weight: 500 !important; cursor: pointer !important; width: auto !important; height: auto !important; min-width: 0 !important; aspect-ratio: auto !important;">${icons.plus} New Chat</button>
|
|
443
443
|
</div>
|
|
444
444
|
<div class="ihooman-history-list"></div>
|
|
445
445
|
</div>
|
|
@@ -561,13 +561,13 @@ function addMessage(content: string, sender: 'user' | 'bot' = 'bot', metadata: M
|
|
|
561
561
|
|
|
562
562
|
let escalationButtonsHtml = '';
|
|
563
563
|
if (showEscalationButtons) {
|
|
564
|
-
// Use inline styles
|
|
565
|
-
const btnBaseStyle = 'display: inline-flex; align-items: center; gap: 6px; padding: 8px
|
|
566
|
-
const primaryStyle = `${btnBaseStyle} background: linear-gradient(135deg, ${config.gradientFrom}, ${config.gradientTo}); color: white;`;
|
|
567
|
-
const secondaryStyle = `${btnBaseStyle} background: rgba(0,0,0,0.05); color: inherit; border: 1px solid rgba(0,0,0,0.1);`;
|
|
564
|
+
// Use inline styles with !important to override any external CSS
|
|
565
|
+
const btnBaseStyle = 'all: revert; display: inline-flex !important; align-items: center !important; justify-content: center !important; gap: 6px !important; padding: 8px 12px !important; border-radius: 6px !important; border: none !important; cursor: pointer !important; font-size: 12px !important; font-weight: 500 !important; line-height: 1.2 !important; width: auto !important; height: auto !important; min-width: 0 !important; min-height: 0 !important; max-width: none !important; max-height: none !important; aspect-ratio: auto !important; box-sizing: border-box !important;';
|
|
566
|
+
const primaryStyle = `${btnBaseStyle} background: linear-gradient(135deg, ${config.gradientFrom}, ${config.gradientTo}) !important; color: white !important;`;
|
|
567
|
+
const secondaryStyle = `${btnBaseStyle} background: rgba(0,0,0,0.05) !important; color: inherit !important; border: 1px solid rgba(0,0,0,0.1) !important;`;
|
|
568
568
|
|
|
569
569
|
escalationButtonsHtml = `
|
|
570
|
-
<div class="ihooman-escalation-actions">
|
|
570
|
+
<div class="ihooman-escalation-actions" style="display: flex !important; gap: 8px !important; margin-top: 10px !important; flex-wrap: wrap !important;">
|
|
571
571
|
<button class="ihooman-escalation-btn primary" data-action="live-agent" style="${primaryStyle}">
|
|
572
572
|
${icons.agent}
|
|
573
573
|
<span>Talk to Agent</span>
|
|
@@ -1198,6 +1198,9 @@ function connectWebSocket(chatEndpoint?: string): void {
|
|
|
1198
1198
|
}
|
|
1199
1199
|
|
|
1200
1200
|
try {
|
|
1201
|
+
// Stop any existing heartbeat before creating new connection
|
|
1202
|
+
stopHeartbeat();
|
|
1203
|
+
|
|
1201
1204
|
ws = new WebSocket(wsUrl);
|
|
1202
1205
|
|
|
1203
1206
|
ws.onopen = () => {
|
|
@@ -1205,23 +1208,35 @@ function connectWebSocket(chatEndpoint?: string): void {
|
|
|
1205
1208
|
reconnectAttempts = 0;
|
|
1206
1209
|
updateStatus(true);
|
|
1207
1210
|
emit('connected');
|
|
1211
|
+
// Start heartbeat after connection is established
|
|
1212
|
+
startHeartbeat();
|
|
1208
1213
|
};
|
|
1209
1214
|
|
|
1210
|
-
ws.onclose = () => {
|
|
1215
|
+
ws.onclose = (event) => {
|
|
1211
1216
|
state.isConnected = false;
|
|
1212
1217
|
updateStatus(false);
|
|
1218
|
+
stopHeartbeat();
|
|
1213
1219
|
emit('disconnected');
|
|
1214
1220
|
|
|
1221
|
+
// Log close reason for debugging
|
|
1222
|
+
console.log(`WebSocket closed: code=${event.code}, reason=${event.reason || 'none'}, wasClean=${event.wasClean}`);
|
|
1223
|
+
|
|
1215
1224
|
// Don't reconnect if this was an intentional disconnect (e.g., starting new conversation)
|
|
1216
1225
|
if (intentionalDisconnect) {
|
|
1217
1226
|
intentionalDisconnect = false;
|
|
1218
1227
|
return;
|
|
1219
1228
|
}
|
|
1220
1229
|
|
|
1230
|
+
// Don't reconnect if the widget is closed
|
|
1231
|
+
if (!state.isOpen) {
|
|
1232
|
+
return;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1221
1235
|
// Attempt reconnection with exponential backoff
|
|
1222
1236
|
if (reconnectAttempts < maxReconnectAttempts) {
|
|
1223
1237
|
reconnectAttempts++;
|
|
1224
1238
|
const delay = Math.min(1000 * Math.pow(2, reconnectAttempts), 30000);
|
|
1239
|
+
console.log(`WebSocket reconnecting in ${delay}ms (attempt ${reconnectAttempts}/${maxReconnectAttempts})`);
|
|
1225
1240
|
setTimeout(() => connectWebSocket(chatEndpoint), delay);
|
|
1226
1241
|
} else {
|
|
1227
1242
|
// Fall back to polling after max reconnect attempts
|
|
@@ -1275,9 +1290,6 @@ function connectWebSocket(chatEndpoint?: string): void {
|
|
|
1275
1290
|
}
|
|
1276
1291
|
};
|
|
1277
1292
|
|
|
1278
|
-
// Start heartbeat to keep connection alive
|
|
1279
|
-
startHeartbeat();
|
|
1280
|
-
|
|
1281
1293
|
} catch {
|
|
1282
1294
|
// WebSocket not supported, fall back to polling
|
|
1283
1295
|
console.warn('WebSocket not supported, using polling');
|
|
@@ -1292,15 +1304,21 @@ let heartbeatInterval: ReturnType<typeof setInterval> | null = null;
|
|
|
1292
1304
|
|
|
1293
1305
|
/**
|
|
1294
1306
|
* Start heartbeat to keep WebSocket connection alive
|
|
1307
|
+
* Sends ping every 25 seconds to prevent Cloudflare/proxy timeouts
|
|
1295
1308
|
*/
|
|
1296
1309
|
function startHeartbeat(): void {
|
|
1297
|
-
|
|
1310
|
+
// Clear any existing heartbeat first
|
|
1311
|
+
stopHeartbeat();
|
|
1298
1312
|
|
|
1299
1313
|
heartbeatInterval = setInterval(() => {
|
|
1300
1314
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
1301
|
-
|
|
1315
|
+
try {
|
|
1316
|
+
ws.send(JSON.stringify({ type: 'ping' }));
|
|
1317
|
+
} catch (e) {
|
|
1318
|
+
console.warn('Failed to send heartbeat ping:', e);
|
|
1319
|
+
}
|
|
1302
1320
|
}
|
|
1303
|
-
},
|
|
1321
|
+
}, 25000); // Ping every 25 seconds (Cloudflare timeout is 100s, but some proxies are shorter)
|
|
1304
1322
|
}
|
|
1305
1323
|
|
|
1306
1324
|
/**
|