@crestapps/ai-chat-ui 2.0.0-preview.224 → 2.0.0-preview.226

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/ai-chat.css CHANGED
@@ -561,3 +561,34 @@ img.medium-zoom-image--opened {
561
561
  .ai-chat-message-item table tbody tr:nth-child(even) {
562
562
  background-color: var(--bs-tertiary-bg, #f8f9fa);
563
563
  }
564
+
565
+ /* Persona avatar shown on assistant messages in place of the robot icon. */
566
+ .ai-chat-assistant-avatar {
567
+ display: block;
568
+ width: 1.5rem;
569
+ height: 1.5rem;
570
+ border-radius: 50%;
571
+ object-fit: cover;
572
+ }
573
+
574
+ .ai-bot-avatar,
575
+ .ai-streaming-avatar {
576
+ display: inline-flex;
577
+ flex-shrink: 0;
578
+ vertical-align: middle;
579
+ }
580
+
581
+ @keyframes ai-chat-avatar-pulse {
582
+ 0%, 100% { opacity: 1; }
583
+ 50% { opacity: 0.45; }
584
+ }
585
+
586
+ .ai-streaming-avatar {
587
+ animation: ai-chat-avatar-pulse 1.5s ease-in-out infinite;
588
+ }
589
+
590
+ @media (prefers-reduced-motion: reduce) {
591
+ .ai-streaming-avatar {
592
+ animation: none;
593
+ }
594
+ }
package/dist/ai-chat.js CHANGED
@@ -13,6 +13,7 @@
13
13
  downloadChartButtonText: "Download",
14
14
  userLabel: "You",
15
15
  assistantLabel: "Assistant",
16
+ assistantAvatarUrl: null,
16
17
  thumbsUpTitle: "Thumbs up",
17
18
  thumbsDownTitle: "Thumbs down",
18
19
  copyTitle: "Click here to copy response to clipboard.",
@@ -46,7 +47,7 @@
46
47
  </div>
47
48
  <div v-else-if="message.role !== 'indicator'" class="ai-chat-message-heading ai-chat-message-heading-assistant">
48
49
  <div :class="getAssistantRoleClasses(message)">
49
- <span :class="getAssistantIconClasses(message, index)"><i :class="getAssistantIcon(message)"></i></span>
50
+ <span :class="getAssistantIconClasses(message, index)"><img v-if="getAssistantAvatarUrl(message)" class="ai-chat-assistant-avatar" :src="getAssistantAvatarUrl(message)" alt="" /><i v-else :class="getAssistantIcon(message)"></i></span>
50
51
  <span class="ai-chat-message-role-label">{{ getAssistantLabel(message) }}</span>
51
52
  </div>
52
53
  </div>
@@ -100,8 +101,8 @@
100
101
  indicatorTemplate: `
101
102
  <div class="ai-chat-message-heading ai-chat-message-heading-assistant">
102
103
  <div class="ai-chat-msg-role ai-chat-msg-role-assistant">
103
- <span class="ai-streaming-icon"><i class="fa fa-robot" style="display: inline-block;"></i></span>
104
- <span class="ai-chat-message-role-label">Assistant</span>
104
+ {{ assistantIcon }}
105
+ <span class="ai-chat-message-role-label">{{ assistantLabel }}</span>
105
106
  </div>
106
107
  </div>
107
108
  `
@@ -445,17 +446,22 @@
445
446
  if (!source || typeof source !== "object") return {};
446
447
  return Object.fromEntries(Object.entries(source).filter(([, value]) => value !== void 0));
447
448
  }
448
- function resolveIndicatorTemplate(template, assistantLabel) {
449
+ function resolveIndicatorTemplate(template, assistantLabel, assistantAvatarUrl) {
449
450
  if (!template) return template;
450
451
  const encodedAssistantLabel = escapeHtmlEntities(assistantLabel || "Assistant");
451
- return template.replace(/\{\{\s*assistantLabel\s*\}\}/g, encodedAssistantLabel);
452
+ const avatarUrl = sanitizeUrl(assistantAvatarUrl);
453
+ const assistantIcon = avatarUrl ? "<span class=\"ai-streaming-avatar\"><img class=\"ai-chat-assistant-avatar\" src=\"" + escapeHtmlAttribute(avatarUrl) + "\" alt=\"\" /></span>" : "<span class=\"ai-streaming-icon\"><i class=\"fa fa-robot\" style=\"display: inline-block;\"></i></span>";
454
+ return template.replace(/\{\{\s*assistantLabel\s*\}\}/g, encodedAssistantLabel).replace(/\{\{\s*assistantIcon\s*\}\}/g, assistantIcon);
455
+ }
456
+ function escapeHtmlAttribute(text) {
457
+ return escapeHtmlEntities(text).replace(/"/g, "&quot;").replace(/'/g, "&#39;");
452
458
  }
453
459
  const initialize = (instanceConfig) => {
454
460
  const normalizedInstanceConfig = compactObject(instanceConfig);
455
461
  const normalizedWidgetConfig = compactObject(normalizedInstanceConfig.widget);
456
462
  const config = Object.assign({}, defaultConfig, normalizedInstanceConfig);
457
463
  config.widget = Object.assign({}, defaultConfig.widget || {}, normalizedWidgetConfig);
458
- config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel);
464
+ config.indicatorTemplate = resolveIndicatorTemplate(config.indicatorTemplate, config.assistantLabel, config.assistantAvatarUrl);
459
465
  const hasWidgetConfig = !!(normalizedWidgetConfig.chatWidgetContainer && normalizedWidgetConfig.chatWidgetStateName);
460
466
  const widgetBehavior = window.coreAIChatWidgetBehavior || null;
461
467
  defaultConfig = config;
@@ -505,6 +511,7 @@
505
511
  metricsEnabled: !!config.metricsEnabled,
506
512
  userLabel: config.userLabel,
507
513
  assistantLabel: config.assistantLabel,
514
+ assistantAvatarUrl: sanitizeUrl(config.assistantAvatarUrl) || null,
508
515
  thumbsUpTitle: config.thumbsUpTitle,
509
516
  thumbsDownTitle: config.thumbsDownTitle,
510
517
  copyTitle: config.copyTitle,
@@ -852,8 +859,13 @@
852
859
  },
853
860
  getAssistantIconClasses(message, index) {
854
861
  var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;
862
+ if (this.getAssistantAvatarUrl(message)) return [this.shouldAnimateAssistantIcon(message, index) ? "ai-streaming-avatar" : "ai-bot-avatar"];
855
863
  return [this.shouldAnimateAssistantIcon(message, index) ? "ai-streaming-icon" : "ai-bot-icon", appearance && appearance.cssClass ? appearance.cssClass : ""];
856
864
  },
865
+ getAssistantAvatarUrl(message) {
866
+ if (!this.assistantAvatarUrl || message && this.normalizeAssistantAppearance(message.appearance)) return null;
867
+ return this.assistantAvatarUrl;
868
+ },
857
869
  getAssistantIcon(message) {
858
870
  var appearance = message ? this.normalizeAssistantAppearance(message.appearance) : null;
859
871
  return appearance && appearance.icon ? appearance.icon : "fa fa-robot";
@@ -2278,6 +2290,7 @@
2278
2290
  sessionUrlTemplate: getAttributeValue(element, "data-coreai-chat-session-url-template"),
2279
2291
  userLabel: getAttributeValue(element, "data-coreai-chat-user-label"),
2280
2292
  assistantLabel: getAttributeValue(element, "data-coreai-chat-assistant-label"),
2293
+ assistantAvatarUrl: getAttributeValue(element, "data-coreai-chat-assistant-avatar-url"),
2281
2294
  copyTitle: getAttributeValue(element, "data-coreai-chat-copy-title"),
2282
2295
  copiedTitle: getAttributeValue(element, "data-coreai-chat-copied-title")
2283
2296
  };