cevro-messenger-sdk 0.1.19 → 0.1.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/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/index.js +145 -19
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/CevroMessenger.d.ts +7 -0
- package/dist/types/core/CevroMessenger.d.ts.map +1 -1
- package/dist/types/types/index.d.ts +2 -0
- package/dist/types/types/index.d.ts.map +1 -1
- package/dist/types/ui/ChatWindow.d.ts +6 -0
- package/dist/types/ui/ChatWindow.d.ts.map +1 -1
- package/dist/types/ui/MessageList.d.ts +17 -0
- package/dist/types/ui/MessageList.d.ts.map +1 -1
- package/dist/types/ui/PastConversation.d.ts +10 -1
- package/dist/types/ui/PastConversation.d.ts.map +1 -1
- package/dist/umd/cevro-messenger.min.js +1 -1
- package/dist/umd/cevro-messenger.min.js.map +1 -1
- package/package.json +1 -1
package/dist/esm/index.js
CHANGED
|
@@ -5065,10 +5065,13 @@ class MessageList {
|
|
|
5065
5065
|
__publicField(this, "element", null);
|
|
5066
5066
|
__publicField(this, "messagesContainer", null);
|
|
5067
5067
|
__publicField(this, "messages", /* @__PURE__ */ new Map());
|
|
5068
|
+
__publicField(this, "messageData", /* @__PURE__ */ new Map());
|
|
5068
5069
|
__publicField(this, "onQuickAction", null);
|
|
5069
5070
|
__publicField(this, "autoScroll", true);
|
|
5070
5071
|
__publicField(this, "closedMessageElement", null);
|
|
5071
5072
|
__publicField(this, "currentAgent", null);
|
|
5073
|
+
__publicField(this, "brandLogoUrl");
|
|
5074
|
+
__publicField(this, "firstAdminMessageId", null);
|
|
5072
5075
|
__publicField(this, "lastMessageBody");
|
|
5073
5076
|
__publicField(this, "lastMessageAt");
|
|
5074
5077
|
__publicField(this, "onScrollTopCallback", null);
|
|
@@ -5110,6 +5113,26 @@ class MessageList {
|
|
|
5110
5113
|
setAgent(agent) {
|
|
5111
5114
|
this.currentAgent = agent;
|
|
5112
5115
|
}
|
|
5116
|
+
/**
|
|
5117
|
+
* Set the brand logo shown as the avatar of the conversation's first message only
|
|
5118
|
+
*/
|
|
5119
|
+
setBrandLogoUrl(url) {
|
|
5120
|
+
this.brandLogoUrl = url;
|
|
5121
|
+
this.refreshFirstAdminMessageAvatar();
|
|
5122
|
+
}
|
|
5123
|
+
/**
|
|
5124
|
+
* Re-render the message currently holding the first-admin-message slot, e.g.
|
|
5125
|
+
* after the brand logo changes mid-session. No-ops if none is tracked yet.
|
|
5126
|
+
*/
|
|
5127
|
+
refreshFirstAdminMessageAvatar() {
|
|
5128
|
+
if (!this.firstAdminMessageId) return;
|
|
5129
|
+
const message = this.messageData.get(this.firstAdminMessageId);
|
|
5130
|
+
const el = this.messages.get(this.firstAdminMessageId);
|
|
5131
|
+
if (!message || !el) return;
|
|
5132
|
+
const rebuiltEl = this.createMessageElement(message, true);
|
|
5133
|
+
el.replaceWith(rebuiltEl);
|
|
5134
|
+
this.messages.set(this.firstAdminMessageId, rebuiltEl);
|
|
5135
|
+
}
|
|
5113
5136
|
/**
|
|
5114
5137
|
* Render the message list
|
|
5115
5138
|
*/
|
|
@@ -5188,7 +5211,12 @@ class MessageList {
|
|
|
5188
5211
|
this.updateMessage(message);
|
|
5189
5212
|
return;
|
|
5190
5213
|
}
|
|
5191
|
-
|
|
5214
|
+
this.messageData.set(message.id, message);
|
|
5215
|
+
const isFirst = message.inbound !== true && this.firstAdminMessageId === null;
|
|
5216
|
+
if (isFirst) {
|
|
5217
|
+
this.firstAdminMessageId = message.id;
|
|
5218
|
+
}
|
|
5219
|
+
const messageEl = this.createMessageElement(message, isFirst);
|
|
5192
5220
|
if (animate) {
|
|
5193
5221
|
messageEl.classList.add("cevro-message--animate");
|
|
5194
5222
|
}
|
|
@@ -5209,11 +5237,28 @@ class MessageList {
|
|
|
5209
5237
|
*/
|
|
5210
5238
|
prependMessages(messages) {
|
|
5211
5239
|
if (!this.messagesContainer || messages.length === 0) return;
|
|
5212
|
-
|
|
5240
|
+
let anchor = this.messagesContainer.firstElementChild;
|
|
5213
5241
|
const anchorOffset = anchor ? anchor.offsetTop - this.messagesContainer.scrollTop : 0;
|
|
5242
|
+
const earliestAdminMessage = messages.find((m) => m.inbound !== true);
|
|
5243
|
+
if (earliestAdminMessage && earliestAdminMessage.id !== this.firstAdminMessageId) {
|
|
5244
|
+
const previousFirstId = this.firstAdminMessageId;
|
|
5245
|
+
this.firstAdminMessageId = earliestAdminMessage.id;
|
|
5246
|
+
const previousFirstMessage = previousFirstId ? this.messageData.get(previousFirstId) : void 0;
|
|
5247
|
+
const previousFirstEl = previousFirstId ? this.messages.get(previousFirstId) : void 0;
|
|
5248
|
+
if (previousFirstId && previousFirstMessage && previousFirstEl) {
|
|
5249
|
+
const rebuiltEl = this.createMessageElement(previousFirstMessage, false);
|
|
5250
|
+
previousFirstEl.replaceWith(rebuiltEl);
|
|
5251
|
+
this.messages.set(previousFirstId, rebuiltEl);
|
|
5252
|
+
if (anchor === previousFirstEl) {
|
|
5253
|
+
anchor = rebuiltEl;
|
|
5254
|
+
}
|
|
5255
|
+
}
|
|
5256
|
+
}
|
|
5214
5257
|
for (const message of messages) {
|
|
5215
5258
|
if (this.messages.has(message.id)) continue;
|
|
5216
|
-
|
|
5259
|
+
this.messageData.set(message.id, message);
|
|
5260
|
+
const isFirst = message.id === this.firstAdminMessageId;
|
|
5261
|
+
const messageEl = this.createMessageElement(message, isFirst);
|
|
5217
5262
|
this.messagesContainer.insertBefore(messageEl, anchor);
|
|
5218
5263
|
this.messages.set(message.id, messageEl);
|
|
5219
5264
|
}
|
|
@@ -5240,10 +5285,16 @@ class MessageList {
|
|
|
5240
5285
|
const lookupId = oldId || message.id;
|
|
5241
5286
|
const existingEl = this.messages.get(lookupId);
|
|
5242
5287
|
if (!existingEl || !this.messagesContainer) return;
|
|
5243
|
-
|
|
5288
|
+
if (this.firstAdminMessageId === lookupId) {
|
|
5289
|
+
this.firstAdminMessageId = message.id;
|
|
5290
|
+
}
|
|
5291
|
+
const isFirst = this.firstAdminMessageId === message.id;
|
|
5292
|
+
this.messageData.set(message.id, message);
|
|
5293
|
+
const newEl = this.createMessageElement(message, isFirst);
|
|
5244
5294
|
this.messagesContainer.replaceChild(newEl, existingEl);
|
|
5245
5295
|
if (oldId && oldId !== message.id) {
|
|
5246
5296
|
this.messages.delete(oldId);
|
|
5297
|
+
this.messageData.delete(oldId);
|
|
5247
5298
|
}
|
|
5248
5299
|
this.messages.set(message.id, newEl);
|
|
5249
5300
|
}
|
|
@@ -5270,20 +5321,44 @@ class MessageList {
|
|
|
5270
5321
|
if (!messageEl) return;
|
|
5271
5322
|
messageEl.remove();
|
|
5272
5323
|
this.messages.delete(messageId);
|
|
5324
|
+
this.messageData.delete(messageId);
|
|
5325
|
+
if (this.firstAdminMessageId === messageId) {
|
|
5326
|
+
this.firstAdminMessageId = null;
|
|
5327
|
+
this.promoteNextAdminMessageToFirst();
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
/**
|
|
5331
|
+
* Give the first-message treatment to the earliest remaining admin message
|
|
5332
|
+
* (by DOM position), e.g. after the previous holder is removed.
|
|
5333
|
+
*/
|
|
5334
|
+
promoteNextAdminMessageToFirst() {
|
|
5335
|
+
if (!this.messagesContainer) return;
|
|
5336
|
+
for (const child of Array.from(this.messagesContainer.children)) {
|
|
5337
|
+
const id = child.dataset.messageId;
|
|
5338
|
+
if (!id) continue;
|
|
5339
|
+
const message = this.messageData.get(id);
|
|
5340
|
+
if (!message || message.inbound === true) continue;
|
|
5341
|
+
this.firstAdminMessageId = id;
|
|
5342
|
+
const rebuiltEl = this.createMessageElement(message, true);
|
|
5343
|
+
child.replaceWith(rebuiltEl);
|
|
5344
|
+
this.messages.set(id, rebuiltEl);
|
|
5345
|
+
return;
|
|
5346
|
+
}
|
|
5273
5347
|
}
|
|
5274
5348
|
/**
|
|
5275
5349
|
* Create message element
|
|
5276
5350
|
*/
|
|
5277
|
-
createMessageElement(message) {
|
|
5278
|
-
var _a, _b, _c, _d, _e;
|
|
5351
|
+
createMessageElement(message, isFirst = false) {
|
|
5352
|
+
var _a, _b, _c, _d, _e, _f;
|
|
5279
5353
|
const isMyMessage = message.inbound === true;
|
|
5280
5354
|
const wrapper = createElement("div", {
|
|
5281
5355
|
className: `cevro-message ${isMyMessage ? "cevro-message--outbound" : "cevro-message--inbound"}`,
|
|
5282
5356
|
"data-message-id": message.id,
|
|
5283
5357
|
"data-testid": `message-${message.id}`
|
|
5284
5358
|
});
|
|
5359
|
+
const showBrandLogo = !isMyMessage && isFirst && !!this.brandLogoUrl && isValidUrl(this.brandLogoUrl);
|
|
5360
|
+
const isHuman = !isMyMessage && !showBrandLogo && message.senderType === "human";
|
|
5285
5361
|
if (!isMyMessage) {
|
|
5286
|
-
const isHuman = message.senderType === "human";
|
|
5287
5362
|
const avatar = createElement("div", {
|
|
5288
5363
|
className: `cevro-message__avatar${isHuman ? " cevro-message__avatar--human" : ""}`
|
|
5289
5364
|
});
|
|
@@ -5295,22 +5370,26 @@ class MessageList {
|
|
|
5295
5370
|
});
|
|
5296
5371
|
initialsEl.textContent = initials;
|
|
5297
5372
|
avatar.appendChild(initialsEl);
|
|
5298
|
-
} else if (((_a = this.currentAgent) == null ? void 0 : _a.avatarUrl) && isValidUrl(this.currentAgent.avatarUrl)) {
|
|
5299
|
-
const img = createElement("img", {
|
|
5300
|
-
className: "cevro-message__avatar-img"
|
|
5301
|
-
});
|
|
5302
|
-
img.src = this.currentAgent.avatarUrl;
|
|
5303
|
-
img.alt = this.currentAgent.name || "Agent";
|
|
5304
|
-
avatar.appendChild(img);
|
|
5305
5373
|
} else {
|
|
5306
|
-
|
|
5374
|
+
const validAgentAvatarUrl = ((_a = this.currentAgent) == null ? void 0 : _a.avatarUrl) && isValidUrl(this.currentAgent.avatarUrl) ? this.currentAgent.avatarUrl : null;
|
|
5375
|
+
const avatarSrc = showBrandLogo ? this.brandLogoUrl : validAgentAvatarUrl;
|
|
5376
|
+
if (avatarSrc) {
|
|
5377
|
+
const img = createElement("img", {
|
|
5378
|
+
className: "cevro-message__avatar-img",
|
|
5379
|
+
src: avatarSrc,
|
|
5380
|
+
alt: showBrandLogo ? "Logo" : ((_b = this.currentAgent) == null ? void 0 : _b.name) || "Agent"
|
|
5381
|
+
});
|
|
5382
|
+
avatar.appendChild(img);
|
|
5383
|
+
} else {
|
|
5384
|
+
avatar.innerHTML = this.createBotAvatarSvg();
|
|
5385
|
+
}
|
|
5307
5386
|
}
|
|
5308
5387
|
wrapper.appendChild(avatar);
|
|
5309
5388
|
}
|
|
5310
5389
|
const contentWrapper = createElement("div", {
|
|
5311
5390
|
className: "cevro-message__content-wrapper"
|
|
5312
5391
|
});
|
|
5313
|
-
if (
|
|
5392
|
+
if (isHuman && message.agentName) {
|
|
5314
5393
|
const senderLabel = createElement("div", {
|
|
5315
5394
|
className: "cevro-message__sender-name"
|
|
5316
5395
|
});
|
|
@@ -5320,7 +5399,7 @@ class MessageList {
|
|
|
5320
5399
|
const bubble = createElement("div", {
|
|
5321
5400
|
className: "cevro-message__bubble"
|
|
5322
5401
|
});
|
|
5323
|
-
const isImage = message.type === "image" || ((
|
|
5402
|
+
const isImage = message.type === "image" || ((_c = message.attachment) == null ? void 0 : _c.category) === "image";
|
|
5324
5403
|
if (isImage && message.mediaUrl && isValidUrl(message.mediaUrl)) {
|
|
5325
5404
|
const imageContainer = createElement("div", {
|
|
5326
5405
|
className: "cevro-message__image-container"
|
|
@@ -5329,7 +5408,7 @@ class MessageList {
|
|
|
5329
5408
|
className: "cevro-message__image"
|
|
5330
5409
|
});
|
|
5331
5410
|
img.src = message.mediaUrl;
|
|
5332
|
-
img.alt = ((
|
|
5411
|
+
img.alt = ((_d = message.attachment) == null ? void 0 : _d.filename) || "Image";
|
|
5333
5412
|
img.loading = "lazy";
|
|
5334
5413
|
imageContainer.appendChild(img);
|
|
5335
5414
|
if (message.status === "sending") {
|
|
@@ -5361,7 +5440,7 @@ class MessageList {
|
|
|
5361
5440
|
bubble.appendChild(textContent);
|
|
5362
5441
|
}
|
|
5363
5442
|
contentWrapper.appendChild(bubble);
|
|
5364
|
-
if ((
|
|
5443
|
+
if ((_f = (_e = message.richContent) == null ? void 0 : _e.quickActions) == null ? void 0 : _f.length) {
|
|
5365
5444
|
const actionsContainer = createElement("div", {
|
|
5366
5445
|
className: "cevro-message__quick-actions"
|
|
5367
5446
|
});
|
|
@@ -5628,6 +5707,8 @@ class MessageList {
|
|
|
5628
5707
|
this.messagesContainer.innerHTML = "";
|
|
5629
5708
|
}
|
|
5630
5709
|
this.messages.clear();
|
|
5710
|
+
this.messageData.clear();
|
|
5711
|
+
this.firstAdminMessageId = null;
|
|
5631
5712
|
this.lastMessageBody = void 0;
|
|
5632
5713
|
this.lastMessageAt = void 0;
|
|
5633
5714
|
this.autoScroll = true;
|
|
@@ -5687,6 +5768,8 @@ class MessageList {
|
|
|
5687
5768
|
this.element = null;
|
|
5688
5769
|
this.messagesContainer = null;
|
|
5689
5770
|
this.messages.clear();
|
|
5771
|
+
this.messageData.clear();
|
|
5772
|
+
this.firstAdminMessageId = null;
|
|
5690
5773
|
}
|
|
5691
5774
|
}
|
|
5692
5775
|
class ChatWindow {
|
|
@@ -6539,6 +6622,14 @@ class ChatWindow {
|
|
|
6539
6622
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
6540
6623
|
return emailRegex.test(email);
|
|
6541
6624
|
}
|
|
6625
|
+
/**
|
|
6626
|
+
* Set the brand logo shown as the avatar of the conversation's first message only.
|
|
6627
|
+
* Distinct from the header logo (`updateCustomLogo`) — callers decide independently
|
|
6628
|
+
* whether the first-message avatar should follow the header logo.
|
|
6629
|
+
*/
|
|
6630
|
+
setBrandLogoUrl(logoUrl) {
|
|
6631
|
+
this.messageList.setBrandLogoUrl(logoUrl);
|
|
6632
|
+
}
|
|
6542
6633
|
updateCustomLogo(logoUrl) {
|
|
6543
6634
|
this.customLogoUrl = logoUrl;
|
|
6544
6635
|
if (!this.logoElement) return;
|
|
@@ -6878,6 +6969,19 @@ class PastConversation {
|
|
|
6878
6969
|
this.avatarUrl = url;
|
|
6879
6970
|
this.renderAvatar();
|
|
6880
6971
|
}
|
|
6972
|
+
/**
|
|
6973
|
+
* Set agent info for message avatars (the AI-persona photo fallback when
|
|
6974
|
+
* no brand logo applies)
|
|
6975
|
+
*/
|
|
6976
|
+
setAgent(agent) {
|
|
6977
|
+
this.messageList.setAgent(agent);
|
|
6978
|
+
}
|
|
6979
|
+
/**
|
|
6980
|
+
* Set the brand logo shown as the avatar of the conversation's first message only
|
|
6981
|
+
*/
|
|
6982
|
+
setBrandLogoUrl(url) {
|
|
6983
|
+
this.messageList.setBrandLogoUrl(url);
|
|
6984
|
+
}
|
|
6881
6985
|
renderAvatar() {
|
|
6882
6986
|
if (!this.avatarElement) return;
|
|
6883
6987
|
if (this.avatarUrl) {
|
|
@@ -7173,6 +7277,7 @@ const _CevroMessenger = class _CevroMessenger {
|
|
|
7173
7277
|
strings,
|
|
7174
7278
|
this.widgetAppearance.customLogoUrl
|
|
7175
7279
|
);
|
|
7280
|
+
this.chatWindow.setBrandLogoUrl(this.firstMessageBrandLogoUrl());
|
|
7176
7281
|
this.container.appendChild(this.chatWindow.render());
|
|
7177
7282
|
this.createConversationList(strings);
|
|
7178
7283
|
this.createPastConversation(strings);
|
|
@@ -7389,6 +7494,7 @@ const _CevroMessenger = class _CevroMessenger {
|
|
|
7389
7494
|
);
|
|
7390
7495
|
const el = this.pastConversation.render();
|
|
7391
7496
|
this.pastConversation.setAvatarUrl(this.widgetAppearance.customLogoUrl);
|
|
7497
|
+
this.pastConversation.setBrandLogoUrl(this.firstMessageBrandLogoUrl());
|
|
7392
7498
|
el.style.display = "none";
|
|
7393
7499
|
this.container.appendChild(el);
|
|
7394
7500
|
}
|
|
@@ -7604,6 +7710,9 @@ const _CevroMessenger = class _CevroMessenger {
|
|
|
7604
7710
|
if (result.agent && this.chatWindow) {
|
|
7605
7711
|
this.chatWindow.setAgent(result.agent);
|
|
7606
7712
|
}
|
|
7713
|
+
if (result.agent && this.pastConversation) {
|
|
7714
|
+
this.pastConversation.setAgent(result.agent);
|
|
7715
|
+
}
|
|
7607
7716
|
if (result.typingConfig) {
|
|
7608
7717
|
this.typingConfig = result.typingConfig;
|
|
7609
7718
|
}
|
|
@@ -7911,6 +8020,15 @@ const _CevroMessenger = class _CevroMessenger {
|
|
|
7911
8020
|
(_a = this.launcher) == null ? void 0 : _a.setUnreadCount(count);
|
|
7912
8021
|
this.events.emit("unread_count_change", { count });
|
|
7913
8022
|
}
|
|
8023
|
+
/**
|
|
8024
|
+
* The brand logo pairs with the global, workspace-voiced welcome
|
|
8025
|
+
* (`instantGreeting`) — pairing it with the personalized "Hi, I'm
|
|
8026
|
+
* {agentName}" welcome would put a company avatar next to agent-attributed
|
|
8027
|
+
* text.
|
|
8028
|
+
*/
|
|
8029
|
+
firstMessageBrandLogoUrl() {
|
|
8030
|
+
return this.widgetAppearance.instantGreeting ? this.widgetAppearance.customLogoUrl : void 0;
|
|
8031
|
+
}
|
|
7914
8032
|
updateAppearance(config) {
|
|
7915
8033
|
this.widgetAppearance = {
|
|
7916
8034
|
...this.widgetAppearance,
|
|
@@ -7928,6 +8046,12 @@ const _CevroMessenger = class _CevroMessenger {
|
|
|
7928
8046
|
if ("customLogoUrl" in config && this.chatWindow) {
|
|
7929
8047
|
this.chatWindow.updateCustomLogo(config.customLogoUrl);
|
|
7930
8048
|
}
|
|
8049
|
+
if (("customLogoUrl" in config || "instantGreeting" in config) && this.chatWindow) {
|
|
8050
|
+
this.chatWindow.setBrandLogoUrl(this.firstMessageBrandLogoUrl());
|
|
8051
|
+
}
|
|
8052
|
+
if (("customLogoUrl" in config || "instantGreeting" in config) && this.pastConversation) {
|
|
8053
|
+
this.pastConversation.setBrandLogoUrl(this.firstMessageBrandLogoUrl());
|
|
8054
|
+
}
|
|
7931
8055
|
this.events.emit("appearance:updated", this.widgetAppearance);
|
|
7932
8056
|
}
|
|
7933
8057
|
/**
|
|
@@ -8056,8 +8180,10 @@ const _CevroMessenger = class _CevroMessenger {
|
|
|
8056
8180
|
* @param avatarUrl - Agent avatar URL (optional)
|
|
8057
8181
|
*/
|
|
8058
8182
|
setPreviewAgent(name, avatarUrl) {
|
|
8183
|
+
var _a;
|
|
8059
8184
|
if (!this.config.preview || !this.chatWindow) return;
|
|
8060
8185
|
this.chatWindow.setAgent({ name, avatarUrl });
|
|
8186
|
+
(_a = this.pastConversation) == null ? void 0 : _a.setAgent({ name, avatarUrl });
|
|
8061
8187
|
}
|
|
8062
8188
|
/**
|
|
8063
8189
|
* Start typing indicator cycle (5s on, 5s off, repeat)
|