@product7/feedback-sdk 1.3.8 → 1.3.9

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 (39) hide show
  1. package/dist/feedback-sdk.js +2824 -2371
  2. package/dist/feedback-sdk.js.map +1 -1
  3. package/dist/feedback-sdk.min.js +1 -1
  4. package/dist/feedback-sdk.min.js.map +1 -1
  5. package/package.json +1 -1
  6. package/src/api/services/MessengerService.js +5 -5
  7. package/src/core/APIService.js +33 -14
  8. package/src/index.js +1 -1
  9. package/src/styles/base.js +1 -1
  10. package/src/styles/changelog.js +58 -40
  11. package/src/styles/components.js +19 -2
  12. package/src/styles/design-tokens.js +4 -4
  13. package/src/styles/feedback.js +3 -8
  14. package/src/styles/messenger-components.js +473 -0
  15. package/src/styles/messenger-core.js +37 -268
  16. package/src/styles/messenger-features.js +89 -267
  17. package/src/styles/messenger-views.js +391 -325
  18. package/src/styles/messenger.js +17 -558
  19. package/src/styles/styles.js +21 -24
  20. package/src/styles/{surveys.js → survey.js} +55 -20
  21. package/src/widgets/BaseWidget.js +1 -1
  22. package/src/widgets/ButtonWidget.js +1 -1
  23. package/src/widgets/ChangelogWidget.js +1 -1
  24. package/src/widgets/InlineWidget.js +1 -1
  25. package/src/widgets/MessengerWidget.js +15 -9
  26. package/src/widgets/SurveyWidget.js +1 -1
  27. package/src/widgets/TabWidget.js +1 -1
  28. package/src/widgets/messenger/MessengerState.js +5 -2
  29. package/src/widgets/messenger/components/MessengerLauncher.js +22 -18
  30. package/src/widgets/messenger/components/MessengerPanel.js +1 -1
  31. package/src/widgets/messenger/components/NavigationTabs.js +36 -15
  32. package/src/widgets/messenger/views/ChangelogView.js +8 -32
  33. package/src/widgets/messenger/views/ChatView.js +96 -60
  34. package/src/widgets/messenger/views/ConversationsView.js +67 -45
  35. package/src/widgets/messenger/views/HelpView.js +22 -32
  36. package/src/widgets/messenger/views/HomeView.js +58 -40
  37. package/src/widgets/messenger/views/PreChatFormView.js +12 -5
  38. package/src/styles/messenger-help.js +0 -298
  39. package/src/styles/messenger-themes.js +0 -500
@@ -40,7 +40,10 @@ export class ChatView {
40
40
  data.conversationId === this.state.activeConversationId
41
41
  ) {
42
42
  this._updateContent();
43
- } else if (type === 'messagesUpdate' && data.conversationId === this.state.activeConversationId) {
43
+ } else if (
44
+ type === 'messagesUpdate' &&
45
+ data.conversationId === this.state.activeConversationId
46
+ ) {
44
47
  this._updateContent();
45
48
  }
46
49
  });
@@ -60,7 +63,6 @@ export class ChatView {
60
63
  ? this._renderEmptyState(isNewConversation)
61
64
  : messages.map((msg) => this._renderMessage(msg)).join('');
62
65
 
63
- const avatarHtml = this._renderConversationAvatar(conversation);
64
66
  const title = isNewConversation
65
67
  ? 'New conversation'
66
68
  : conversation?.title || 'Chat with team';
@@ -78,7 +80,6 @@ export class ChatView {
78
80
  </svg>
79
81
  </button>
80
82
  <div class="messenger-chat-header-info">
81
- ${avatarHtml}
82
83
  <span class="messenger-chat-title">${title}</span>
83
84
  </div>
84
85
  <button class="sdk-close-btn" aria-label="Close">
@@ -90,12 +91,16 @@ export class ChatView {
90
91
 
91
92
  <div class="messenger-chat-messages">
92
93
  ${messagesHtml}
93
- ${isClosed ? `
94
+ ${
95
+ isClosed
96
+ ? `
94
97
  <div class="messenger-closed-banner">
95
98
  <i class="ph ph-check-circle"></i>
96
99
  <span>This conversation has been resolved</span>
97
100
  </div>
98
- ` : ''}
101
+ `
102
+ : ''
103
+ }
99
104
  <div class="messenger-typing-indicator">
100
105
  <div class="messenger-typing-dots">
101
106
  <span></span><span></span><span></span>
@@ -104,7 +109,10 @@ export class ChatView {
104
109
  </div>
105
110
  </div>
106
111
 
107
- ${isClosed ? '' : `
112
+ ${
113
+ isClosed
114
+ ? ''
115
+ : `
108
116
  <div class="messenger-compose-attachments-preview"></div>
109
117
 
110
118
  <div class="messenger-chat-compose">
@@ -121,10 +129,13 @@ export class ChatView {
121
129
  </button>
122
130
  <input type="file" class="messenger-compose-file-input" multiple accept="image/*,.pdf,.doc,.docx,.xls,.xlsx,.txt,.zip" />
123
131
  </div>
124
- `}
132
+ `
133
+ }
125
134
  `;
126
135
 
127
- this._typingIndicator = this.element.querySelector('.messenger-typing-indicator');
136
+ this._typingIndicator = this.element.querySelector(
137
+ '.messenger-typing-indicator'
138
+ );
128
139
  this._attachEvents();
129
140
  this._scrollToBottom();
130
141
  this._renderAttachmentPreviews();
@@ -132,7 +143,8 @@ export class ChatView {
132
143
 
133
144
  _renderEmptyState(isNewConversation = false) {
134
145
  const avatarHtml = this._renderTeamAvatars();
135
- const responseTime = this.state.responseTime || 'We typically reply within a few minutes';
146
+ const responseTime =
147
+ this.state.responseTime || 'We typically reply within a few minutes';
136
148
  const isOnline = this.state.agentsOnline;
137
149
 
138
150
  return `
@@ -150,26 +162,34 @@ export class ChatView {
150
162
 
151
163
  _renderMessageAttachments(attachments) {
152
164
  if (!attachments || attachments.length === 0) return '';
153
- return attachments.map((att) => {
154
- if (att.type === 'image') {
155
- return `<img class="messenger-message-image" src="${this._escapeHtml(att.url)}" alt="${this._escapeHtml(att.name || 'image')}" data-url="${this._escapeHtml(att.url)}" />`;
156
- }
157
- return `<a class="messenger-message-file" href="${this._escapeHtml(att.url)}" data-url="${this._escapeHtml(att.url)}" data-name="${this._escapeHtml(att.name || 'file')}">
165
+ return attachments
166
+ .map((att) => {
167
+ if (att.type === 'image') {
168
+ return `<img class="messenger-message-image" src="${this._escapeHtml(att.url)}" alt="${this._escapeHtml(att.name || 'image')}" data-url="${this._escapeHtml(att.url)}" />`;
169
+ }
170
+ return `<a class="messenger-message-file" href="${this._escapeHtml(att.url)}" data-url="${this._escapeHtml(att.url)}" data-name="${this._escapeHtml(att.name || 'file')}">
158
171
  <i class="ph ph-file"></i>
159
172
  <span>${this._escapeHtml(att.name || 'file')}</span>
160
173
  <i class="ph ph-download-simple messenger-file-download-icon"></i>
161
174
  </a>`;
162
- }).join('');
175
+ })
176
+ .join('');
163
177
  }
164
178
 
165
179
  _renderMessage(message) {
166
180
  const isOwn = message.isOwn;
167
- const messageClass = isOwn ? 'messenger-message-own' : 'messenger-message-received';
181
+ const messageClass = isOwn
182
+ ? 'messenger-message-own'
183
+ : 'messenger-message-received';
168
184
  const timeStr = this._formatMessageTime(message.timestamp);
169
185
  const attachmentsHtml = this._renderMessageAttachments(message.attachments);
170
186
 
171
- const contentHtml = message.content ? `<div class="messenger-message-content">${this._formatMessageContent(message.content)}</div>` : '';
172
- const bubbleHtml = contentHtml ? `<div class="messenger-message-bubble">${contentHtml}</div>` : '';
187
+ const contentHtml = message.content
188
+ ? `<div class="messenger-message-content">${this._formatMessageContent(message.content)}</div>`
189
+ : '';
190
+ const bubbleHtml = contentHtml
191
+ ? `<div class="messenger-message-bubble">${contentHtml}</div>`
192
+ : '';
173
193
 
174
194
  if (isOwn) {
175
195
  return `
@@ -184,13 +204,15 @@ export class ChatView {
184
204
  const avatarHtml = this._renderSenderAvatar(message.sender);
185
205
  return `
186
206
  <div class="messenger-message ${messageClass}">
187
- <div class="messenger-message-avatar">${avatarHtml}</div>
188
- <div class="messenger-message-wrapper">
189
- <div class="messenger-message-sender">${message.sender?.name || 'Support'}</div>
190
- ${bubbleHtml}
191
- ${attachmentsHtml}
192
- <div class="messenger-message-time">${timeStr}</div>
207
+ <div class="messenger-message-sender">${message.sender?.name || 'Support'}</div>
208
+ <div class="messenger-message-row">
209
+ <div class="messenger-message-avatar">${avatarHtml}</div>
210
+ <div class="messenger-message-wrapper">
211
+ ${bubbleHtml}
212
+ ${attachmentsHtml}
213
+ </div>
193
214
  </div>
215
+ <div class="messenger-message-time">${timeStr}</div>
194
216
  </div>
195
217
  `;
196
218
  }
@@ -203,17 +225,6 @@ export class ChatView {
203
225
  return `<div class="sdk-avatar sdk-avatar-sm">${initial}</div>`;
204
226
  }
205
227
 
206
- _renderConversationAvatar(conversation) {
207
- if (!conversation?.participants?.length) {
208
- return `<div class="sdk-avatar sdk-avatar-sm">S</div>`;
209
- }
210
- const p = conversation.participants[0];
211
- if (p.avatarUrl) {
212
- return `<div class="sdk-avatar sdk-avatar-sm"><img src="${p.avatarUrl}" alt="${p.name}" /></div>`;
213
- }
214
- return `<div class="sdk-avatar sdk-avatar-sm">${(p.name || 'S').charAt(0).toUpperCase()}</div>`;
215
- }
216
-
217
228
  _renderTeamAvatars() {
218
229
  const avatars = this.state.teamAvatars;
219
230
  if (!avatars || avatars.length === 0) {
@@ -258,7 +269,9 @@ export class ChatView {
258
269
  }
259
270
 
260
271
  _appendMessage(message) {
261
- const messagesContainer = this.element.querySelector('.messenger-chat-messages');
272
+ const messagesContainer = this.element.querySelector(
273
+ '.messenger-chat-messages'
274
+ );
262
275
  const emptyState = messagesContainer.querySelector('.messenger-chat-empty');
263
276
  if (emptyState) {
264
277
  emptyState.remove();
@@ -271,7 +284,9 @@ export class ChatView {
271
284
  }
272
285
 
273
286
  _scrollToBottom() {
274
- const messagesContainer = this.element.querySelector('.messenger-chat-messages');
287
+ const messagesContainer = this.element.querySelector(
288
+ '.messenger-chat-messages'
289
+ );
275
290
  if (messagesContainer) {
276
291
  setTimeout(() => {
277
292
  messagesContainer.scrollTop = messagesContainer.scrollHeight;
@@ -283,12 +298,15 @@ export class ChatView {
283
298
  const input = this.element.querySelector('.messenger-compose-input');
284
299
  const sendBtn = this.element.querySelector('.messenger-compose-send');
285
300
  if (input && sendBtn) {
286
- sendBtn.disabled = !input.value.trim() && this._pendingAttachments.length === 0;
301
+ sendBtn.disabled =
302
+ !input.value.trim() && this._pendingAttachments.length === 0;
287
303
  }
288
304
  }
289
305
 
290
306
  _renderAttachmentPreviews() {
291
- const container = this.element.querySelector('.messenger-compose-attachments-preview');
307
+ const container = this.element.querySelector(
308
+ '.messenger-compose-attachments-preview'
309
+ );
292
310
  if (!container) return;
293
311
 
294
312
  if (this._pendingAttachments.length === 0) {
@@ -298,27 +316,31 @@ export class ChatView {
298
316
  }
299
317
 
300
318
  container.style.display = 'flex';
301
- container.innerHTML = this._pendingAttachments.map((att, i) => {
302
- const isImage = att.type.startsWith('image');
303
- const thumb = isImage
304
- ? `<img class="messenger-attachment-thumb" src="${att.preview}" alt="${this._escapeHtml(att.file.name)}" />`
305
- : `<div class="messenger-attachment-thumb messenger-attachment-file-icon"><i class="ph ph-file"></i></div>`;
306
- return `
319
+ container.innerHTML = this._pendingAttachments
320
+ .map((att, i) => {
321
+ const isImage = att.type.startsWith('image');
322
+ const thumb = isImage
323
+ ? `<img class="messenger-attachment-thumb" src="${att.preview}" alt="${this._escapeHtml(att.file.name)}" />`
324
+ : `<div class="messenger-attachment-thumb messenger-attachment-file-icon"><i class="ph ph-file"></i></div>`;
325
+ return `
307
326
  <div class="messenger-attachment-preview" data-index="${i}">
308
327
  ${thumb}
309
328
  <button class="messenger-attachment-remove" data-index="${i}" aria-label="Remove">&times;</button>
310
329
  </div>
311
330
  `;
312
- }).join('');
331
+ })
332
+ .join('');
313
333
 
314
- container.querySelectorAll('.messenger-attachment-remove').forEach((btn) => {
315
- btn.addEventListener('click', (e) => {
316
- const idx = parseInt(e.currentTarget.dataset.index, 10);
317
- this._pendingAttachments.splice(idx, 1);
318
- this._renderAttachmentPreviews();
319
- this._updateSendButtonState();
334
+ container
335
+ .querySelectorAll('.messenger-attachment-remove')
336
+ .forEach((btn) => {
337
+ btn.addEventListener('click', (e) => {
338
+ const idx = parseInt(e.currentTarget.dataset.index, 10);
339
+ this._pendingAttachments.splice(idx, 1);
340
+ this._renderAttachmentPreviews();
341
+ this._updateSendButtonState();
342
+ });
320
343
  });
321
- });
322
344
  }
323
345
 
324
346
  _attachEvents() {
@@ -361,7 +383,9 @@ export class ChatView {
361
383
  }
362
384
 
363
385
  const attachBtn = this.element.querySelector('.messenger-compose-attach');
364
- const fileInput = this.element.querySelector('.messenger-compose-file-input');
386
+ const fileInput = this.element.querySelector(
387
+ '.messenger-compose-file-input'
388
+ );
365
389
 
366
390
  if (attachBtn && fileInput) {
367
391
  attachBtn.addEventListener('click', () => {
@@ -388,7 +412,9 @@ export class ChatView {
388
412
  });
389
413
  }
390
414
 
391
- const messagesContainer = this.element.querySelector('.messenger-chat-messages');
415
+ const messagesContainer = this.element.querySelector(
416
+ '.messenger-chat-messages'
417
+ );
392
418
  if (messagesContainer) {
393
419
  messagesContainer.addEventListener('click', (e) => {
394
420
  const fileLink = e.target.closest('.messenger-message-file');
@@ -429,12 +455,16 @@ export class ChatView {
429
455
 
430
456
  _escapeHtml(text) {
431
457
  if (!text) return '';
432
- return text.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
458
+ return text
459
+ .replace(/&/g, '&amp;')
460
+ .replace(/</g, '&lt;')
461
+ .replace(/>/g, '&gt;')
462
+ .replace(/"/g, '&quot;');
433
463
  }
434
464
 
435
465
  async _sendMessage() {
436
466
  if (this._isConversationClosed) return;
437
-
467
+
438
468
  const input = this.element.querySelector('.messenger-compose-input');
439
469
  const content = input.value.trim();
440
470
  const hasAttachments = this._pendingAttachments.length > 0;
@@ -466,7 +496,11 @@ export class ChatView {
466
496
  this.state.addMessage(this.state.activeConversationId, message);
467
497
 
468
498
  if (this.options.onSendMessage) {
469
- this.options.onSendMessage(this.state.activeConversationId, message, attachmentsToSend);
499
+ this.options.onSendMessage(
500
+ this.state.activeConversationId,
501
+ message,
502
+ attachmentsToSend
503
+ );
470
504
  }
471
505
  }
472
506
 
@@ -510,7 +544,9 @@ export class ChatView {
510
544
  _showTypingIndicator(userName) {
511
545
  if (this._typingIndicator) {
512
546
  this._typingIndicator.style.display = 'flex';
513
- const textEl = this._typingIndicator.querySelector('.messenger-typing-text');
547
+ const textEl = this._typingIndicator.querySelector(
548
+ '.messenger-typing-text'
549
+ );
514
550
  if (textEl) {
515
551
  textEl.textContent = `${userName || 'Support'} is typing...`;
516
552
  }
@@ -536,4 +572,4 @@ export class ChatView {
536
572
  this.element.parentNode.removeChild(this.element);
537
573
  }
538
574
  }
539
- }
575
+ }
@@ -4,6 +4,15 @@ export class ConversationsView {
4
4
  this.options = options;
5
5
  this.element = null;
6
6
  this._unsubscribe = null;
7
+ this.avatarColors = [
8
+ '#155EEF',
9
+ '#8b5cf6',
10
+ '#10b981',
11
+ '#f59e0b',
12
+ '#ef4444',
13
+ '#ec4899',
14
+ '#06b6d4',
15
+ ];
7
16
  }
8
17
 
9
18
  render() {
@@ -27,55 +36,61 @@ export class ConversationsView {
27
36
  return this.element;
28
37
  }
29
38
 
39
+ _getAvatarColor(name) {
40
+ // Generate consistent color based on name
41
+ const charCode = (name || 'S').charCodeAt(0);
42
+ return this.avatarColors[charCode % this.avatarColors.length];
43
+ }
44
+
30
45
  _updateContent() {
31
46
  const conversations = this.state.conversations;
32
- const avatarsHtml = this._renderAvatarStack();
33
47
 
34
48
  let conversationsHtml;
35
49
  if (conversations.length === 0) {
36
50
  conversationsHtml = `
37
- <div class="messenger-empty-state">
38
- <div class="messenger-empty-state-icon">
39
- <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" viewBox="0 0 256 256">
40
- <path d="M216,48H40A16,16,0,0,0,24,64V224a15.85,15.85,0,0,0,9.24,14.5A16.13,16.13,0,0,0,40,240a15.89,15.89,0,0,0,10.25-3.78.69.69,0,0,0,.13-.11L82.5,208H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM40,224h0ZM216,192H82.5a16,16,0,0,0-10.3,3.75l-.12.11L40,224V64H216Z"></path>
41
- </svg>
42
- </div>
43
- <h3>No conversations yet</h3>
44
- <p>Start a new conversation with our team</p>
45
- </div>
46
- `;
51
+ <div class="messenger-empty-state">
52
+ <div class="messenger-empty-state-icon">
53
+ <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" fill="currentColor" viewBox="0 0 256 256">
54
+ <path d="M216,48H40A16,16,0,0,0,24,64V224a15.85,15.85,0,0,0,9.24,14.5A16.13,16.13,0,0,0,40,240a15.89,15.89,0,0,0,10.25-3.78.69.69,0,0,0,.13-.11L82.5,208H216a16,16,0,0,0,16-16V64A16,16,0,0,0,216,48ZM40,224h0ZM216,192H82.5a16,16,0,0,0-10.3,3.75l-.12.11L40,224V64H216Z"></path>
55
+ </svg>
56
+ </div>
57
+ <h3>No conversations yet</h3>
58
+ <p>Start a new conversation with our team</p>
59
+ </div>
60
+ `;
47
61
  } else {
48
62
  conversationsHtml = `
49
- <div class="messenger-conversations-list">
50
- ${conversations.map((conv) => this._renderConversationItem(conv)).join('')}
51
- </div>
52
- `;
63
+ <div class="messenger-conversations-list">
64
+ ${conversations.map((conv) => this._renderConversationItem(conv)).join('')}
65
+ </div>
66
+ `;
53
67
  }
54
68
 
55
69
  this.element.innerHTML = `
56
- <div class="messenger-conversations-header">
57
- <h2>Messages</h2>
58
- <button class="sdk-close-btn" aria-label="Close">
59
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
60
- <path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
61
- </svg>
62
- </button>
63
- </div>
64
-
65
- <div class="messenger-conversations-body">
66
- ${conversationsHtml}
67
- </div>
68
-
69
- <div class="messenger-conversations-footer">
70
- <button class="messenger-new-message-btn">
71
- <div class="messenger-new-message-avatars">${avatarsHtml}</div>
72
- <span>Send us a message</span>
73
- <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#000000" viewBox="0 0 256 256">
74
- <path d="M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z"></path>
75
- </svg>
76
- </button>
77
- </div>
78
- `;
70
+ <div class="messenger-conversations-header">
71
+ <h2>Messages</h2>
72
+ <button class="sdk-close-btn" aria-label="Close">
73
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
74
+ <path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
75
+ </svg>
76
+ </button>
77
+ </div>
78
+
79
+ <div class="messenger-conversations-body">
80
+ ${conversationsHtml}
81
+ </div>
82
+
83
+ <div class="messenger-conversations-footer">
84
+ <button class="messenger-new-message-btn">
85
+ <span>Send us a message</span>
86
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 256 256" style="flex-shrink: 0;">
87
+ <rect width="256" height="256" fill="none"/>
88
+ <line x1="144" y1="128" x2="80" y2="128" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
89
+ <path d="M48.49,221.28A8,8,0,0,0,59.93,231l168-96.09a8,8,0,0,0,0-14l-168-95.85a8,8,0,0,0-11.44,9.67L80,128Z" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="16"/>
90
+ </svg>
91
+ </button>
92
+ </div>
93
+ `;
79
94
 
80
95
  this._attachEvents();
81
96
  }
@@ -108,34 +123,41 @@ export class ConversationsView {
108
123
 
109
124
  _renderConversationAvatars(participants) {
110
125
  if (!participants || participants.length === 0) {
111
- return `<div class="sdk-avatar sdk-avatar-md">S</div>`;
126
+ const color = this._getAvatarColor('S');
127
+ return `<div class="sdk-avatar sdk-avatar-md" style="background-color: ${color};">S</div>`;
112
128
  }
113
129
 
114
130
  const p = participants[0];
115
131
  if (p.avatarUrl) {
116
132
  return `<div class="sdk-avatar sdk-avatar-md"><img src="${p.avatarUrl}" alt="${p.name}" /></div>`;
117
133
  }
118
- return `<div class="sdk-avatar sdk-avatar-md">${(p.name || 'S').charAt(0).toUpperCase()}</div>`;
134
+ const initial = (p.name || 'S').charAt(0).toUpperCase();
135
+ const color = this._getAvatarColor(p.name);
136
+ return `<div class="sdk-avatar sdk-avatar-md" style="background-color: ${color};">${initial}</div>`;
119
137
  }
120
138
 
121
139
  _renderAvatarStack() {
122
140
  const avatars = this.state.teamAvatars;
123
141
  if (!avatars || avatars.length === 0) {
142
+ const color1 = this._getAvatarColor('S');
143
+ const color2 = this._getAvatarColor('T');
124
144
  return `
125
145
  <div class="messenger-avatar-stack">
126
- <div class="sdk-avatar sdk-avatar-sm">S</div>
127
- <div class="sdk-avatar sdk-avatar-sm">T</div>
146
+ <div class="sdk-avatar sdk-avatar-sm" style="background-color: ${color1};">S</div>
147
+ <div class="sdk-avatar sdk-avatar-sm" style="background-color: ${color2};">T</div>
128
148
  </div>
129
149
  `;
130
150
  }
131
151
 
132
152
  const avatarItems = avatars
133
153
  .slice(0, 2)
134
- .map((avatar) => {
154
+ .map((avatar, index) => {
135
155
  if (typeof avatar === 'string' && avatar.startsWith('http')) {
136
156
  return `<div class="sdk-avatar sdk-avatar-sm"><img src="${avatar}" alt="Team member" /></div>`;
137
157
  }
138
- return `<div class="sdk-avatar sdk-avatar-sm">${avatar.charAt(0).toUpperCase()}</div>`;
158
+ const initial = avatar.charAt(0).toUpperCase();
159
+ const color = this._getAvatarColor(avatar);
160
+ return `<div class="sdk-avatar sdk-avatar-sm" style="background-color: ${color};">${initial}</div>`;
139
161
  })
140
162
  .join('');
141
163
 
@@ -227,4 +249,4 @@ export class ConversationsView {
227
249
  this.element.parentNode.removeChild(this.element);
228
250
  }
229
251
  }
230
- }
252
+ }
@@ -24,39 +24,29 @@ export class HelpView {
24
24
  _updateContent() {
25
25
  const searchQuery = this.state.helpSearchQuery || '';
26
26
  const collections = this.state.helpArticles || [];
27
- const collectionCount = collections.length;
28
27
 
29
28
  this.element.innerHTML = `
30
- <div class="messenger-help-header">
31
- <h2>Help</h2>
32
- <button class="sdk-close-btn" aria-label="Close">
33
- <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="#000000" viewBox="0 0 256 256">
34
- <path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
35
- </svg>
36
- </button>
37
- </div>
38
-
39
- <div class="messenger-help-search">
40
- <div class="messenger-help-search-wrapper">
41
- <input
42
- type="text"
43
- class="sdk-input messenger-help-search-input"
44
- placeholder="Search for help"
45
- value="${searchQuery}"
46
- />
47
- <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="#000000" viewBox="0 0 256 256" class="messenger-help-search-icon">
48
- <path d="M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z"></path>
49
- </svg>
50
- </div>
51
- </div>
52
-
53
- <div class="messenger-help-body">
54
- <div class="messenger-help-collections-header">
55
- ${collectionCount} collections
56
- </div>
57
- <div class="messenger-help-collections"></div>
58
- </div>
59
- `;
29
+ <div class="messenger-help-header">
30
+ <div class="messenger-help-header-top">
31
+ <h2>Help</h2>
32
+ <button class="sdk-close-btn" aria-label="Close">
33
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" viewBox="0 0 256 256">
34
+ <path d="M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z"></path>
35
+ </svg>
36
+ </button>
37
+ </div>
38
+ <input
39
+ type="text"
40
+ class="messenger-help-search-input"
41
+ placeholder="Search for help..."
42
+ value="${searchQuery}"
43
+ />
44
+ </div>
45
+
46
+ <div class="messenger-help-body">
47
+ <div class="messenger-help-collections"></div>
48
+ </div>
49
+ `;
60
50
 
61
51
  this._updateCollectionsList();
62
52
  this._attachEvents();
@@ -189,4 +179,4 @@ export class HelpView {
189
179
  this.element.parentNode.removeChild(this.element);
190
180
  }
191
181
  }
192
- }
182
+ }