@ihoomanai/chat-widget 3.0.20 → 3.0.21
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 +37 -4
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.esm.js +37 -4
- 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 +37 -4
- 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 +32 -3
package/src/widget.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type {
|
|
|
17
17
|
WidgetView,
|
|
18
18
|
} from './types';
|
|
19
19
|
|
|
20
|
-
const VERSION = '3.0.
|
|
20
|
+
const VERSION = '3.0.21';
|
|
21
21
|
const STORAGE_PREFIX = 'ihooman_chat_';
|
|
22
22
|
const DEFAULT_SERVER_URL = 'https://api.ihooman.ai';
|
|
23
23
|
|
|
@@ -91,6 +91,7 @@ let state: WidgetState = {
|
|
|
91
91
|
|
|
92
92
|
let currentView: WidgetView = 'chat';
|
|
93
93
|
let isLiveAgentMode = false;
|
|
94
|
+
let isConversationClosed = false;
|
|
94
95
|
let shownProactiveIds: string[] = [];
|
|
95
96
|
let proactiveCooldowns: Record<string, number> = {};
|
|
96
97
|
let proactiveCheckInterval: ReturnType<typeof setInterval> | null = null;
|
|
@@ -334,6 +335,8 @@ function generateStyles(): string {
|
|
|
334
335
|
.ihooman-input-btn.send:hover { opacity: 0.9; }
|
|
335
336
|
.ihooman-input-btn.send:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
336
337
|
.ihooman-input-btn svg { width: 16px; height: 16px; }
|
|
338
|
+
.ihooman-input:disabled { opacity: 0.6; cursor: not-allowed; }
|
|
339
|
+
.ihooman-input-btn.attach:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
337
340
|
.ihooman-file-input { display: none; }
|
|
338
341
|
.ihooman-powered { text-align: center; padding: 8px; font-size: 11px; color: ${mutedColor}; background: ${bgColor}; }
|
|
339
342
|
.ihooman-powered a { color: ${primaryColor}; text-decoration: none; }
|
|
@@ -1133,7 +1136,26 @@ function hideTyping(): void {
|
|
|
1133
1136
|
if (typing) typing.remove();
|
|
1134
1137
|
}
|
|
1135
1138
|
|
|
1139
|
+
function disableInput(): void {
|
|
1140
|
+
if (elements.input) {
|
|
1141
|
+
elements.input.disabled = true;
|
|
1142
|
+
elements.input.placeholder = 'Conversation closed — start a new chat to continue';
|
|
1143
|
+
}
|
|
1144
|
+
if (elements.sendBtn) elements.sendBtn.disabled = true;
|
|
1145
|
+
if (elements.attachBtn) elements.attachBtn.disabled = true;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
function enableInput(): void {
|
|
1149
|
+
if (elements.input) {
|
|
1150
|
+
elements.input.disabled = false;
|
|
1151
|
+
elements.input.placeholder = config.placeholder || 'Type a message...';
|
|
1152
|
+
}
|
|
1153
|
+
if (elements.sendBtn) elements.sendBtn.disabled = !elements.input?.value.trim();
|
|
1154
|
+
if (elements.attachBtn) elements.attachBtn.disabled = false;
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1136
1157
|
function handleSendClick(): void {
|
|
1158
|
+
if (isConversationClosed) return;
|
|
1137
1159
|
const content = elements.input?.value.trim();
|
|
1138
1160
|
if (!content) return;
|
|
1139
1161
|
|
|
@@ -1163,6 +1185,7 @@ function hidePresetQuestions(): void {
|
|
|
1163
1185
|
}
|
|
1164
1186
|
|
|
1165
1187
|
async function sendMessageToServer(content: string): Promise<void> {
|
|
1188
|
+
if (isConversationClosed) return;
|
|
1166
1189
|
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
1167
1190
|
ws.send(JSON.stringify({ type: 'message', content }));
|
|
1168
1191
|
return;
|
|
@@ -1506,10 +1529,12 @@ function connectWebSocket(chatEndpoint?: string): void {
|
|
|
1506
1529
|
emit('escalation:accepted', { type: 'live_agent' });
|
|
1507
1530
|
}
|
|
1508
1531
|
if (metadata.closed_by_agent) {
|
|
1509
|
-
// Agent has closed the conversation -
|
|
1532
|
+
// Agent has closed the conversation - disable input, require new conversation
|
|
1510
1533
|
isLiveAgentMode = false;
|
|
1534
|
+
isConversationClosed = true;
|
|
1511
1535
|
stopLiveAgentPolling();
|
|
1512
1536
|
updateStatusBar('hidden');
|
|
1537
|
+
disableInput();
|
|
1513
1538
|
emit('escalation:end', { type: 'live_agent' });
|
|
1514
1539
|
}
|
|
1515
1540
|
|
|
@@ -1541,8 +1566,10 @@ function connectWebSocket(chatEndpoint?: string): void {
|
|
|
1541
1566
|
emit('escalation:accepted', { type: 'live_agent' });
|
|
1542
1567
|
} else if (data.status === 'disconnected') {
|
|
1543
1568
|
isLiveAgentMode = false;
|
|
1569
|
+
isConversationClosed = true;
|
|
1544
1570
|
stopLiveAgentPolling();
|
|
1545
1571
|
updateStatusBar('hidden');
|
|
1572
|
+
disableInput();
|
|
1546
1573
|
emit('escalation:end', { type: 'live_agent' });
|
|
1547
1574
|
}
|
|
1548
1575
|
} else if (data.type === 'error') {
|
|
@@ -1663,6 +1690,7 @@ function startNewConversation(): void {
|
|
|
1663
1690
|
state.visitorId = null;
|
|
1664
1691
|
state.messages = [];
|
|
1665
1692
|
isLiveAgentMode = false;
|
|
1693
|
+
isConversationClosed = false;
|
|
1666
1694
|
|
|
1667
1695
|
storage('session_id', null);
|
|
1668
1696
|
state.visitorId = generateId('v_');
|
|
@@ -1672,6 +1700,7 @@ function startNewConversation(): void {
|
|
|
1672
1700
|
|
|
1673
1701
|
updateStatusBar('hidden');
|
|
1674
1702
|
stopLiveAgentPolling();
|
|
1703
|
+
enableInput();
|
|
1675
1704
|
|
|
1676
1705
|
reconnectAttempts = 0;
|
|
1677
1706
|
|
|
@@ -1724,7 +1753,7 @@ function destroy(): void {
|
|
|
1724
1753
|
}
|
|
1725
1754
|
|
|
1726
1755
|
function sendMessage(content: string): void {
|
|
1727
|
-
if (!content.trim()) return;
|
|
1756
|
+
if (!content.trim() || isConversationClosed) return;
|
|
1728
1757
|
if (elements.input) elements.input.value = content;
|
|
1729
1758
|
handleSendClick();
|
|
1730
1759
|
}
|