@product7/product7-js 0.2.6 → 0.2.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.
@@ -2977,8 +2977,8 @@
2977
2977
  --msg-bg-elevated: #FFFFFF;
2978
2978
  --msg-bg-hover: #F9FAFB;
2979
2979
  --msg-bg-input: rgba(255, 255, 255, 0.7);
2980
- --msg-bg-bubble-own: #FFFFFF;
2981
- --msg-bg-bubble-received: #F3F4F6;
2980
+ --msg-bg-bubble-own: #F3F4F6;
2981
+ --msg-bg-bubble-received: rgba(21, 94, 239, 0.06);
2982
2982
  --msg-bg-header-gradient: linear-gradient(180deg, #e0e7ff 0%, #f0f4ff 35%, #FFFFFF 65%);
2983
2983
  --msg-bg-header-glow1: radial-gradient(circle, rgba(21, 94, 239, 0.08) 0%, transparent 70%);
2984
2984
  --msg-bg-header-glow2: radial-gradient(circle, rgba(139, 92, 246, 0.05) 0%, transparent 70%);
@@ -2987,7 +2987,7 @@
2987
2987
  --msg-text-tertiary: #6B7280;
2988
2988
  --msg-text-muted: #9CA3AF;
2989
2989
  --msg-border: #E5E7EB;
2990
- --msg-border-bubble: #E5E7EB;
2990
+ --msg-border-bubble: transparent;
2991
2991
  --msg-shadow-card: rgba(9, 30, 66, 0.25) 0px 1px 1px, rgba(9, 30, 66, 0.13) 0px 0px 1px 1px;
2992
2992
  --msg-shadow-card-hover: rgba(9, 30, 66, 0.3) 0px 2px 2px, rgba(9, 30, 66, 0.18) 0px 0px 1px 1px;
2993
2993
 
@@ -3391,6 +3391,82 @@
3391
3391
  max-width: 85%;
3392
3392
  }
3393
3393
 
3394
+ .messenger-message-system {
3395
+ align-self: center;
3396
+ display: flex;
3397
+ align-items: center;
3398
+ gap: var(--spacing-2);
3399
+ padding: var(--spacing-2) 0;
3400
+ width: 100%;
3401
+ }
3402
+
3403
+ .messenger-message-system::before,
3404
+ .messenger-message-system::after {
3405
+ content: '';
3406
+ flex: 1;
3407
+ height: 1px;
3408
+ background: var(--msg-border);
3409
+ }
3410
+
3411
+ .messenger-message-system-text {
3412
+ font-size: 0.6875rem;
3413
+ color: var(--msg-text-tertiary);
3414
+ white-space: nowrap;
3415
+ padding: 0 var(--spacing-2);
3416
+ letter-spacing: 0.01em;
3417
+ }
3418
+
3419
+ /* Rich join/leave system event */
3420
+ .messenger-message-system-event {
3421
+ align-self: center;
3422
+ display: flex;
3423
+ flex-direction: column;
3424
+ align-items: center;
3425
+ gap: var(--spacing-2);
3426
+ padding: var(--spacing-4) 0;
3427
+ width: 100%;
3428
+ text-align: center;
3429
+ }
3430
+
3431
+ .messenger-message-system-event-avatar {
3432
+ width: 3rem;
3433
+ height: 3rem;
3434
+ border-radius: var(--radius-full);
3435
+ border: 2px solid var(--msg-border);
3436
+ display: flex;
3437
+ align-items: center;
3438
+ justify-content: center;
3439
+ font-size: 1.125rem;
3440
+ font-weight: var(--font-weight-semibold);
3441
+ color: #ffffff;
3442
+ overflow: hidden;
3443
+ flex-shrink: 0;
3444
+ }
3445
+
3446
+ .messenger-message-system-event-avatar img {
3447
+ width: 100%;
3448
+ height: 100%;
3449
+ object-fit: cover;
3450
+ }
3451
+
3452
+ .messenger-message-system-event-name {
3453
+ font-size: var(--font-size-sm);
3454
+ font-weight: var(--font-weight-semibold);
3455
+ color: var(--msg-text);
3456
+ line-height: 1.3;
3457
+ }
3458
+
3459
+ .messenger-message-system-event-action {
3460
+ font-size: var(--font-size-xs);
3461
+ color: var(--msg-text-tertiary);
3462
+ margin-top: -2px;
3463
+ }
3464
+
3465
+ .messenger-message-system-event-time {
3466
+ font-size: 0.6875rem;
3467
+ color: var(--msg-text-muted);
3468
+ }
3469
+
3394
3470
  .messenger-message-own {
3395
3471
  align-self: flex-end;
3396
3472
  flex-direction: column;
@@ -3431,7 +3507,6 @@
3431
3507
  .messenger-message-own .messenger-message-bubble {
3432
3508
  background: var(--msg-bg-bubble-own);
3433
3509
  color: var(--msg-text);
3434
- border: 1px solid var(--msg-border-bubble);
3435
3510
  border-bottom-right-radius: 0.25rem;
3436
3511
  }
3437
3512
 
@@ -3443,7 +3518,7 @@
3443
3518
 
3444
3519
  .messenger-message-content {
3445
3520
  font-size: var(--font-size-base);
3446
- font-weight: var(--font-weight-medium);
3521
+ font-weight: var(--font-weight-semibold);
3447
3522
  line-height: var(--line-height-relaxed);
3448
3523
  }
3449
3524
 
@@ -3468,10 +3543,14 @@
3468
3543
  gap: 0.375rem;
3469
3544
  font-size: var(--font-size-xs);
3470
3545
  color: var(--msg-text-tertiary);
3471
- margin-top: 0.375rem;
3546
+ margin-top: 0.25rem;
3472
3547
  padding: 0 var(--spacing-1);
3473
3548
  }
3474
3549
 
3550
+ .messenger-message-meta-own {
3551
+ justify-content: flex-end;
3552
+ }
3553
+
3475
3554
  .messenger-message-image {
3476
3555
  max-width: 220px;
3477
3556
  max-height: 200px;
@@ -4257,8 +4336,8 @@
4257
4336
  --msg-bg-elevated: #232930;
4258
4337
  --msg-bg-hover: #232930;
4259
4338
  --msg-bg-input: #1a1e24;
4260
- --msg-bg-bubble-own: #2a3140;
4261
- --msg-bg-bubble-received: #1a1e24;
4339
+ --msg-bg-bubble-own: #1e2330;
4340
+ --msg-bg-bubble-received: rgba(21, 94, 239, 0.12);
4262
4341
  --msg-bg-header-gradient: linear-gradient(180deg, #1a1e2e 0%, #141720 50%, #0f1317 100%);
4263
4342
  --msg-bg-header-glow1: radial-gradient(circle, rgba(21, 94, 239, 0.07) 0%, transparent 70%);
4264
4343
  --msg-bg-header-glow2: radial-gradient(circle, rgba(139, 92, 246, 0.05) 0%, transparent 70%);
@@ -8347,7 +8426,9 @@
8347
8426
 
8348
8427
  this.agentsOnline = false;
8349
8428
  this.onlineCount = 0;
8350
- this.responseTime = 'Usually replies within a few minutes';
8429
+ this.onlineMessage = options.onlineMessage || "We're online now";
8430
+ this.responseTime =
8431
+ options.responseTime || 'We typically reply within a few minutes';
8351
8432
 
8352
8433
  this.typingUsers = {};
8353
8434
 
@@ -9356,6 +9437,10 @@
9356
9437
  }
9357
9438
 
9358
9439
  _renderMessage(message) {
9440
+ if (message.isSystem) {
9441
+ return this._renderSystemMessage(message);
9442
+ }
9443
+
9359
9444
  const isOwn = message.isOwn;
9360
9445
  const messageClass = isOwn
9361
9446
  ? 'messenger-message-own'
@@ -9375,12 +9460,11 @@
9375
9460
  <div class="messenger-message ${messageClass}">
9376
9461
  ${bubbleHtml}
9377
9462
  ${attachmentsHtml}
9463
+ ${timeStr ? `<div class="messenger-message-meta messenger-message-meta-own"><span>${timeStr}</span></div>` : ''}
9378
9464
  </div>
9379
9465
  `;
9380
9466
  }
9381
9467
 
9382
- const senderName = message.sender?.name || 'Support';
9383
- const senderRole = message.sender?.role || 'Agent';
9384
9468
  const avatarHtml = this._renderSenderAvatar(message.sender);
9385
9469
  return `
9386
9470
  <div class="messenger-message ${messageClass}">
@@ -9391,13 +9475,49 @@
9391
9475
  ${attachmentsHtml}
9392
9476
  </div>
9393
9477
  </div>
9394
- <div class="messenger-message-meta">
9395
- <span>${senderName}</span>
9396
- <span>·</span>
9397
- <span>${senderRole}</span>
9398
- <span>·</span>
9399
- <span>${timeStr}</span>
9478
+ ${timeStr ? `<div class="messenger-message-meta"><span>${timeStr}</span></div>` : ''}
9479
+ </div>
9480
+ `;
9481
+ }
9482
+
9483
+ _renderSystemMessage(message) {
9484
+ const content = message.content || '';
9485
+ const isJoinLeave =
9486
+ content.includes('joined the chat') ||
9487
+ content.includes('left the chat') ||
9488
+ content.includes('joined the conversation') ||
9489
+ content.includes('left the conversation');
9490
+
9491
+ if (isJoinLeave && message.sender) {
9492
+ const name = message.sender.name || '';
9493
+ const avatarUrl = message.sender.avatarUrl;
9494
+ const initial = name.charAt(0).toUpperCase() || '?';
9495
+ const colors = ['#5856d6', '#007aff', '#34c759', '#ff9500'];
9496
+ const colorIndex = name.charCodeAt(0) % colors.length;
9497
+ const avatarHtml = avatarUrl
9498
+ ? `<img src="${this._escapeHtml(avatarUrl)}" alt="${this._escapeHtml(name)}" />`
9499
+ : initial;
9500
+ const avatarStyle = avatarUrl
9501
+ ? ''
9502
+ : `style="background: ${colors[colorIndex]};"`;
9503
+ const timeStr = this._formatMessageTime(message.timestamp);
9504
+
9505
+ // Split "Name joined the chat" → name part already in sender, extract action
9506
+ const action = content.replace(name, '').trim();
9507
+
9508
+ return `
9509
+ <div class="messenger-message-system-event">
9510
+ <div class="messenger-message-system-event-avatar" ${avatarStyle}>${avatarHtml}</div>
9511
+ <span class="messenger-message-system-event-name">${this._escapeHtml(name)}</span>
9512
+ <span class="messenger-message-system-event-action">${this._escapeHtml(action)}</span>
9513
+ ${timeStr ? `<span class="messenger-message-system-event-time">${timeStr}</span>` : ''}
9400
9514
  </div>
9515
+ `;
9516
+ }
9517
+
9518
+ return `
9519
+ <div class="messenger-message-system">
9520
+ <span class="messenger-message-system-text">${this._escapeHtml(content)}</span>
9401
9521
  </div>
9402
9522
  `;
9403
9523
  }
@@ -9413,12 +9533,7 @@
9413
9533
  _renderTeamAvatars() {
9414
9534
  const avatars = this.state.teamAvatars;
9415
9535
  if (!avatars || avatars.length === 0) {
9416
- return `
9417
- <div class="messenger-avatar-stack">
9418
- <div class="sdk-avatar sdk-avatar-md">S</div>
9419
- <div class="sdk-avatar sdk-avatar-md">T</div>
9420
- </div>
9421
- `;
9536
+ return '';
9422
9537
  }
9423
9538
 
9424
9539
  const avatarItems = avatars
@@ -9437,11 +9552,17 @@
9437
9552
  _formatMessageTime(timestamp) {
9438
9553
  if (!timestamp) return '';
9439
9554
  const date = new Date(timestamp);
9440
- return date.toLocaleTimeString('en-US', {
9441
- hour: 'numeric',
9555
+ const datePart = date.toLocaleDateString('en-GB', {
9556
+ day: '2-digit',
9557
+ month: 'short',
9558
+ year: 'numeric',
9559
+ });
9560
+ const timePart = date.toLocaleTimeString('en-GB', {
9561
+ hour: '2-digit',
9442
9562
  minute: '2-digit',
9443
- hour12: true,
9563
+ hour12: false,
9444
9564
  });
9565
+ return `${datePart}, ${timePart}`;
9445
9566
  }
9446
9567
 
9447
9568
  _formatMessageContent(content) {
@@ -10391,6 +10512,7 @@
10391
10512
  <div class="messenger-home-welcome">
10392
10513
  <span class="messenger-home-greeting">${this.state.greetingMessage}</span>
10393
10514
  <span class="messenger-home-question">${this.state.welcomeMessage}</span>
10515
+ ${this._renderAvailabilityStatus()}
10394
10516
  </div>
10395
10517
  </div>
10396
10518
 
@@ -10410,12 +10532,7 @@
10410
10532
  const colors = ['#5856d6', '#007aff', '#34c759', '#ff9500'];
10411
10533
 
10412
10534
  if (!avatars || avatars.length === 0) {
10413
- return `
10414
- <div class="messenger-avatar-stack">
10415
- <div class="sdk-avatar sdk-avatar-lg" style="background: ${colors[0]};">S</div>
10416
- <div class="sdk-avatar sdk-avatar-lg" style="background: ${colors[1]};">T</div>
10417
- </div>
10418
- `;
10535
+ return '';
10419
10536
  }
10420
10537
 
10421
10538
  const avatarItems = avatars
@@ -10433,14 +10550,12 @@
10433
10550
 
10434
10551
  _renderAvailabilityStatus() {
10435
10552
  const isOnline = this.state.agentsOnline;
10436
- const responseTime =
10437
- this.state.responseTime || 'We typically reply within a few minutes';
10438
10553
 
10439
10554
  if (isOnline) {
10440
10555
  return `
10441
10556
  <div class="messenger-home-availability">
10442
10557
  <span class="messenger-availability-dot messenger-availability-online"></span>
10443
- <span class="messenger-availability-text">We're online now</span>
10558
+ <span class="messenger-availability-text">${this.state.onlineMessage}</span>
10444
10559
  </div>
10445
10560
  `;
10446
10561
  }
@@ -10448,7 +10563,7 @@
10448
10563
  return `
10449
10564
  <div class="messenger-home-availability">
10450
10565
  <span class="messenger-availability-dot messenger-availability-away"></span>
10451
- <span class="messenger-availability-text">${responseTime}</span>
10566
+ <span class="messenger-availability-text">${this.state.responseTime}</span>
10452
10567
  </div>
10453
10568
  `;
10454
10569
  }
@@ -10791,6 +10906,9 @@
10791
10906
  teamAvatars: options.teamAvatars || [],
10792
10907
  greetingMessage: options.greetingMessage || 'Hi there 👋',
10793
10908
  welcomeMessage: options.welcomeMessage || 'How can we help?',
10909
+ onlineMessage: options.onlineMessage || "We're online now",
10910
+ responseTime:
10911
+ options.responseTime || 'We typically reply within a few minutes',
10794
10912
  enableHelp: options.enableHelp !== false,
10795
10913
  enableChangelog: resolvedEnableChangelog,
10796
10914
  autoLoadData: options.autoLoadData !== false,
@@ -10812,6 +10930,8 @@
10812
10930
  teamAvatars: this.messengerOptions.teamAvatars,
10813
10931
  greetingMessage: this.messengerOptions.greetingMessage,
10814
10932
  welcomeMessage: this.messengerOptions.welcomeMessage,
10933
+ onlineMessage: this.messengerOptions.onlineMessage,
10934
+ responseTime: this.messengerOptions.responseTime,
10815
10935
  enableHelp: this.messengerOptions.enableHelp,
10816
10936
  enableChangelog: this.messengerOptions.enableChangelog,
10817
10937
  metadata: this.sdk?.apiService?.getMetadata() || null,
@@ -11133,6 +11253,7 @@
11133
11253
  id: message.id,
11134
11254
  content: message.content,
11135
11255
  isOwn: message.sender_type === 'customer',
11256
+ isSystem: message.sender_type === 'system',
11136
11257
  timestamp: message.created_at,
11137
11258
  attachments: attachments.length > 0 ? attachments : undefined,
11138
11259
  sender: {
@@ -11318,7 +11439,9 @@
11318
11439
  if (data.availability && typeof data.availability === 'object') {
11319
11440
  const availability = data.availability;
11320
11441
  this.messengerState.agentsOnline = Boolean(
11321
- availability.agentsOnline ?? availability.agents_online
11442
+ availability.agentsOnline ??
11443
+ availability.agents_online ??
11444
+ availability.is_online
11322
11445
  );
11323
11446
  this.messengerState.onlineCount =
11324
11447
  availability.onlineCount ?? availability.online_count ?? 0;
@@ -11446,6 +11569,7 @@
11446
11569
  id: msg.id,
11447
11570
  content: msg.content,
11448
11571
  isOwn: msg.sender_type === 'customer',
11572
+ isSystem: msg.sender_type === 'system',
11449
11573
  timestamp: msg.created_at,
11450
11574
  attachments:
11451
11575
  attachments && attachments.length > 0 ? attachments : undefined,
@@ -11496,14 +11620,25 @@
11496
11620
 
11497
11621
  this.messengerState.addConversation(newConversation);
11498
11622
 
11499
- this.messengerState.setMessages(conv.id, [
11623
+ const initialMessages = [
11500
11624
  {
11501
11625
  id: 'msg_' + Date.now(),
11502
11626
  content: message,
11503
11627
  isOwn: true,
11504
11628
  timestamp: new Date().toISOString(),
11505
11629
  },
11506
- ]);
11630
+ ];
11631
+
11632
+ initialMessages.push({
11633
+ id: 'system_rt_' + Date.now(),
11634
+ content: this.messengerState.agentsOnline
11635
+ ? 'One of our customer support agents will be with you shortly.'
11636
+ : this.messengerState.responseTime,
11637
+ isSystem: true,
11638
+ timestamp: new Date().toISOString(),
11639
+ });
11640
+
11641
+ this.messengerState.setMessages(conv.id, initialMessages);
11507
11642
 
11508
11643
  this.messengerState.setActiveConversation(conv.id);
11509
11644
  this.messengerState.setView('chat');
@@ -11529,7 +11664,8 @@
11529
11664
  try {
11530
11665
  const response = await this.apiService.checkAgentsOnline();
11531
11666
  if (response.status && response.data) {
11532
- this.messengerState.agentsOnline = response.data.agents_online;
11667
+ this.messengerState.agentsOnline =
11668
+ response.data.agents_online ?? response.data.is_online ?? false;
11533
11669
  this.messengerState.onlineCount = response.data.online_count || 0;
11534
11670
  this.messengerState.responseTime = response.data.response_time || '';
11535
11671