@xpert-ai/chatkit-ui5 0.3.0 → 0.4.0

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/chatkit.cjs CHANGED
@@ -48,7 +48,7 @@ var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read fr
48
48
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
49
49
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
50
50
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
51
- var _a, _b, _setTrainingOptOut_dec, _hideHistory_dec, _showHistory_dec, _sendCustomAction_dec, _shareThread_dec, _setThreadId_dec, _setComposerValue_dec, _sendUserMessage_dec, _fetchUpdates_dec, _focusComposer_dec, _c, _opts, _frameUrl, _frame, _wrapper, _launcherCloseButton, _launcherOpen, _framePetOptionsOverride, _shadow, _petOverlay, _resolveLoaded, _loaded, _messenger, _ChatKitElementBase_instances, emitAndThrow_fn, setOptionsDataAttributes_fn, getDisplayMode_fn, getConfiguredPetOptions_fn, getOverlayPetOptions_fn, resolvePetAssetUrl_fn, resolveOverlayPetOptions_fn, getFrameOptions_fn, setLauncherOpen_fn, handlePetActivate_fn, handlePetReply_fn, handlePetThreadSummaryActivate_fn, _handleLauncherClose, getFrameUrl_fn, setFrameUrl_fn, consumeFrameUrl_fn, _handleFrameLoad, _initialized, maybeInit_fn, _init;
51
+ var _a, _b, _setTrainingOptOut_dec, _hideHistory_dec, _showHistory_dec, _sendCustomAction_dec, _shareThread_dec, _setThreadId_dec, _setRuntimeCapabilities_dec, _setComposerValue_dec, _sendUserMessage_dec, _fetchUpdates_dec, _focusComposer_dec, _c, _opts, _frameUrl, _frame, _wrapper, _launcherCloseButton, _launcherOpen, _chatMinimizedToPet, _framePetOptionsOverride, _petClosedByContextMenu, _shadow, _petOverlay, _resolveLoaded, _loaded, _messenger, _ChatKitElementBase_instances, emitAndThrow_fn, setOptionsDataAttributes_fn, getDisplayMode_fn, getConfiguredPetOptions_fn, mergeConfiguredPetPositionDefaults_fn, getOverlayPetOptions_fn, resolvePetAssetUrl_fn, resolveOverlayPetOptions_fn, getFrameOptions_fn, setLauncherOpen_fn, setChatMinimizedToPet_fn, syncPetOverlayOptions_fn, handlePetActivate_fn, handlePetClose_fn, handlePetReply_fn, handlePetThreadSummaryActivate_fn, _handleLauncherClose, getFrameUrl_fn, setFrameUrl_fn, consumeFrameUrl_fn, _handleFrameLoad, _initialized, maybeInit_fn, _init;
52
52
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
53
53
  const chatkitTypes = require("@xpert-ai/chatkit-types");
54
54
  class EventEmitter {
@@ -699,6 +699,7 @@ const BASE_CAPABILITY_ALLOWLIST = [
699
699
  "command.setOptions",
700
700
  "command.sendUserMessage",
701
701
  "command.setComposerValue",
702
+ "command.setRuntimeCapabilities",
702
703
  "command.setThreadId",
703
704
  "command.focusComposer",
704
705
  "command.fetchUpdates",
@@ -894,8 +895,11 @@ const PET_RESTING_DELAY_MS = 2e3;
894
895
  const PET_SUMMARY_GAP = 12;
895
896
  const PET_SUMMARY_WIDTH = 320;
896
897
  const PET_SUMMARY_MARGIN = 12;
898
+ const PET_CONTEXT_MENU_MARGIN = 8;
899
+ const PET_SUMMARY_FONT_FAMILY = 'system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
897
900
  const PET_OVERLAY_COPY = {
898
901
  "en-US": {
902
+ closePetMenuItem: "Close pet",
899
903
  hideMessage: "Hide message",
900
904
  expandMessage: "Expand message",
901
905
  collapseMessage: "Collapse message",
@@ -907,6 +911,7 @@ const PET_OVERLAY_COPY = {
907
911
  sendFailed: "Failed to send"
908
912
  },
909
913
  "zh-CN": {
914
+ closePetMenuItem: "关闭宠物",
910
915
  hideMessage: "隐藏消息",
911
916
  expandMessage: "展开消息",
912
917
  collapseMessage: "收起消息",
@@ -983,6 +988,65 @@ function resolveCopyLocale(locale) {
983
988
  }
984
989
  return "en-US";
985
990
  }
991
+ function getSummaryDensityMetrics(density) {
992
+ switch (density) {
993
+ case "compact":
994
+ return {
995
+ padding: "8px 10px",
996
+ gap: 6,
997
+ marginTop: 3,
998
+ toggleSize: 30,
999
+ actionSize: 22
1000
+ };
1001
+ case "spacious":
1002
+ return {
1003
+ padding: "14px 16px",
1004
+ gap: 10,
1005
+ marginTop: 6,
1006
+ toggleSize: 38,
1007
+ actionSize: 28
1008
+ };
1009
+ case "normal":
1010
+ default:
1011
+ return {
1012
+ padding: "12px 14px",
1013
+ gap: 8,
1014
+ marginTop: 4,
1015
+ toggleSize: 34,
1016
+ actionSize: 26
1017
+ };
1018
+ }
1019
+ }
1020
+ function getSummaryRadius(radius) {
1021
+ switch (radius) {
1022
+ case "pill":
1023
+ return 24;
1024
+ case "round":
1025
+ return 16;
1026
+ case "sharp":
1027
+ return 0;
1028
+ case "soft":
1029
+ default:
1030
+ return 12;
1031
+ }
1032
+ }
1033
+ function getSummaryThemeMetrics(theme) {
1034
+ var _a2, _b2;
1035
+ const themeObject = typeof theme === "string" ? null : theme;
1036
+ const baseSize = ((_a2 = themeObject == null ? void 0 : themeObject.typography) == null ? void 0 : _a2.baseSize) ?? 16;
1037
+ const density = (themeObject == null ? void 0 : themeObject.density) ?? "normal";
1038
+ const densityOffset = density === "compact" ? -1 : density === "spacious" ? 1 : 0;
1039
+ const bodySize = clampNumber(baseSize - 2 + densityOffset, 11, 17);
1040
+ const densityMetrics = getSummaryDensityMetrics(density);
1041
+ return {
1042
+ ...densityMetrics,
1043
+ bodySize,
1044
+ titleSize: bodySize + 1,
1045
+ iconSize: clampNumber(bodySize + 2, 13, 19),
1046
+ radius: getSummaryRadius(themeObject == null ? void 0 : themeObject.radius),
1047
+ fontFamily: ((_b2 = themeObject == null ? void 0 : themeObject.typography) == null ? void 0 : _b2.fontFamily) ?? PET_SUMMARY_FONT_FAMILY
1048
+ };
1049
+ }
986
1050
  function isPetState(value) {
987
1051
  return value === "idle" || value === "running-right" || value === "running-left" || value === "waving" || value === "jumping" || value === "failed" || value === "waiting" || value === "running" || value === "review";
988
1052
  }
@@ -1018,6 +1082,12 @@ function getThreadSummaryKey(summary) {
1018
1082
  summary.messageId || summary.updatedAt || summary.message
1019
1083
  ].join(":");
1020
1084
  }
1085
+ function getThreadSummaryInteractionKey(summary) {
1086
+ if (!summary) {
1087
+ return null;
1088
+ }
1089
+ return [summary.threadId, summary.messageId ?? ""].join(":");
1090
+ }
1021
1091
  function parseThreadSummaryPayload(value) {
1022
1092
  if (value === null) {
1023
1093
  return { summary: null };
@@ -1054,10 +1124,12 @@ class PetOverlay {
1054
1124
  constructor(root, options) {
1055
1125
  this.overlayElement = null;
1056
1126
  this.petElement = null;
1127
+ this.contextMenuElement = null;
1057
1128
  this.summaryElement = null;
1058
1129
  this.summaryToggleElement = null;
1059
1130
  this.mediaElement = null;
1060
1131
  this.options = null;
1132
+ this.theme = null;
1061
1133
  this.resolved = null;
1062
1134
  this.summary = null;
1063
1135
  this.summaryRenderKey = null;
@@ -1094,6 +1166,7 @@ class PetOverlay {
1094
1166
  this.mediaQuery = null;
1095
1167
  this.connected = false;
1096
1168
  this.handleViewportChange = () => {
1169
+ this.closeContextMenu();
1097
1170
  this.render();
1098
1171
  };
1099
1172
  this.handleReducedMotionChange = () => {
@@ -1114,6 +1187,36 @@ class PetOverlay {
1114
1187
  this.enterRestingAfterDelay();
1115
1188
  }
1116
1189
  };
1190
+ this.handleContextMenu = (event) => {
1191
+ event.preventDefault();
1192
+ event.stopPropagation();
1193
+ this.openContextMenu({ x: event.clientX, y: event.clientY });
1194
+ };
1195
+ this.handleContextMenuEvent = (event) => {
1196
+ event.preventDefault();
1197
+ event.stopPropagation();
1198
+ };
1199
+ this.handleContextMenuOutsidePointerDown = (event) => {
1200
+ const menu = this.contextMenuElement;
1201
+ if (menu && event.composedPath().includes(menu)) {
1202
+ return;
1203
+ }
1204
+ this.closeContextMenu();
1205
+ };
1206
+ this.handleContextMenuKeyDown = (event) => {
1207
+ if (event.key !== "Escape") {
1208
+ return;
1209
+ }
1210
+ event.preventDefault();
1211
+ this.closeContextMenu();
1212
+ };
1213
+ this.handleClosePetMenuItemClick = (event) => {
1214
+ var _a2;
1215
+ event.preventDefault();
1216
+ event.stopPropagation();
1217
+ this.closeContextMenu();
1218
+ (_a2 = this.onClose) == null ? void 0 : _a2.call(this);
1219
+ };
1117
1220
  this.handleSummaryPointerEnter = () => {
1118
1221
  this.isSummaryHovering = true;
1119
1222
  this.render();
@@ -1181,7 +1284,11 @@ class PetOverlay {
1181
1284
  };
1182
1285
  this.handlePointerDown = (event) => {
1183
1286
  var _a2, _b2;
1184
- if (!((_a2 = this.options) == null ? void 0 : _a2.position.draggable) || event.button !== 0) {
1287
+ if (event.button !== 0 || event.ctrlKey) {
1288
+ return;
1289
+ }
1290
+ this.closeContextMenu();
1291
+ if (!((_a2 = this.options) == null ? void 0 : _a2.position.draggable)) {
1185
1292
  return;
1186
1293
  }
1187
1294
  event.preventDefault();
@@ -1257,6 +1364,7 @@ class PetOverlay {
1257
1364
  };
1258
1365
  this.root = root;
1259
1366
  this.onActivate = options == null ? void 0 : options.onActivate;
1367
+ this.onClose = options == null ? void 0 : options.onClose;
1260
1368
  this.onReply = options == null ? void 0 : options.onReply;
1261
1369
  this.onThreadSummaryActivate = options == null ? void 0 : options.onThreadSummaryActivate;
1262
1370
  this.connect();
@@ -1270,9 +1378,11 @@ class PetOverlay {
1270
1378
  this.installReducedMotionListener();
1271
1379
  this.render();
1272
1380
  }
1273
- setOptions(pet) {
1381
+ setOptions(pet, theme) {
1382
+ this.closeContextMenu();
1274
1383
  const nextOptions = chatkitTypes.normalizePetOptions(pet);
1275
1384
  this.options = nextOptions;
1385
+ this.theme = theme ?? null;
1276
1386
  if (!nextOptions) {
1277
1387
  this.isDragging = false;
1278
1388
  this.isHovering = false;
@@ -1318,11 +1428,12 @@ class PetOverlay {
1318
1428
  this.copyLocale = nextLocale;
1319
1429
  this.copy = PET_OVERLAY_COPY[nextLocale];
1320
1430
  this.summaryRenderKey = null;
1431
+ this.closeContextMenu();
1321
1432
  this.render();
1322
1433
  }
1323
1434
  setThreadSummary(summary) {
1324
- const previousKey = getThreadSummaryKey(this.summary);
1325
- const nextKey = getThreadSummaryKey(summary);
1435
+ const previousKey = getThreadSummaryInteractionKey(this.summary);
1436
+ const nextKey = getThreadSummaryInteractionKey(summary);
1326
1437
  this.summary = summary;
1327
1438
  if (!summary) {
1328
1439
  this.isSummaryCollapsed = false;
@@ -1383,8 +1494,14 @@ class PetOverlay {
1383
1494
  installViewportListeners() {
1384
1495
  var _a2, _b2;
1385
1496
  window.addEventListener("resize", this.handleViewportChange);
1386
- (_a2 = window.visualViewport) == null ? void 0 : _a2.addEventListener("resize", this.handleViewportChange);
1387
- (_b2 = window.visualViewport) == null ? void 0 : _b2.addEventListener("scroll", this.handleViewportChange);
1497
+ (_a2 = window.visualViewport) == null ? void 0 : _a2.addEventListener(
1498
+ "resize",
1499
+ this.handleViewportChange
1500
+ );
1501
+ (_b2 = window.visualViewport) == null ? void 0 : _b2.addEventListener(
1502
+ "scroll",
1503
+ this.handleViewportChange
1504
+ );
1388
1505
  }
1389
1506
  installReducedMotionListener() {
1390
1507
  var _a2, _b2;
@@ -1435,6 +1552,7 @@ class PetOverlay {
1435
1552
  pet.addEventListener("pointerenter", this.handlePointerEnter);
1436
1553
  pet.addEventListener("pointerleave", this.handlePointerLeave);
1437
1554
  pet.addEventListener("pointerdown", this.handlePointerDown);
1555
+ pet.addEventListener("contextmenu", this.handleContextMenu);
1438
1556
  pet.addEventListener("click", this.handleClick);
1439
1557
  overlay.append(style, pet);
1440
1558
  this.root.append(overlay);
@@ -1445,6 +1563,7 @@ class PetOverlay {
1445
1563
  var _a2;
1446
1564
  this.clearRestingDelayTimer();
1447
1565
  this.clearTimers();
1566
+ this.closeContextMenu();
1448
1567
  if (this.petElement) {
1449
1568
  this.petElement.removeEventListener(
1450
1569
  "pointerenter",
@@ -1454,7 +1573,14 @@ class PetOverlay {
1454
1573
  "pointerleave",
1455
1574
  this.handlePointerLeave
1456
1575
  );
1457
- this.petElement.removeEventListener("pointerdown", this.handlePointerDown);
1576
+ this.petElement.removeEventListener(
1577
+ "pointerdown",
1578
+ this.handlePointerDown
1579
+ );
1580
+ this.petElement.removeEventListener(
1581
+ "contextmenu",
1582
+ this.handleContextMenu
1583
+ );
1458
1584
  this.petElement.removeEventListener("click", this.handleClick);
1459
1585
  }
1460
1586
  this.isHovering = false;
@@ -1602,10 +1728,6 @@ class PetOverlay {
1602
1728
  return;
1603
1729
  }
1604
1730
  const nextRenderKey = [
1605
- summaryKey,
1606
- summary.title,
1607
- summary.message,
1608
- summary.status,
1609
1731
  this.copyLocale,
1610
1732
  this.isSummaryExpanded ? "expanded" : "compact",
1611
1733
  this.isSummaryHovering ? "hover" : "rest",
@@ -1618,7 +1740,10 @@ class PetOverlay {
1618
1740
  (_b2 = this.summaryToggleElement) == null ? void 0 : _b2.remove();
1619
1741
  this.summaryElement = this.createSummaryBubble(summary);
1620
1742
  this.summaryToggleElement = this.createSummaryToggleButton("v");
1621
- (_c2 = this.overlayElement) == null ? void 0 : _c2.append(this.summaryElement, this.summaryToggleElement);
1743
+ (_c2 = this.overlayElement) == null ? void 0 : _c2.append(
1744
+ this.summaryElement,
1745
+ this.summaryToggleElement
1746
+ );
1622
1747
  this.summaryRenderKey = nextRenderKey;
1623
1748
  if (this.isReplyOpen && !this.isReplySubmitting) {
1624
1749
  window.setTimeout(() => {
@@ -1627,6 +1752,7 @@ class PetOverlay {
1627
1752
  }, 0);
1628
1753
  }
1629
1754
  }
1755
+ this.updateSummaryBubbleContent(summary);
1630
1756
  this.positionSummaryBubble(position, size);
1631
1757
  }
1632
1758
  renderCollapsedSummary(position, size) {
@@ -1647,7 +1773,7 @@ class PetOverlay {
1647
1773
  return;
1648
1774
  }
1649
1775
  const viewport = getViewportSize();
1650
- const badgeSize = 34;
1776
+ const badgeSize = getSummaryThemeMetrics(this.theme).toggleSize;
1651
1777
  const x = clampNumber(
1652
1778
  position.x + size.width - badgeSize * 0.35,
1653
1779
  PET_SUMMARY_MARGIN,
@@ -1670,7 +1796,10 @@ class PetOverlay {
1670
1796
  return;
1671
1797
  }
1672
1798
  const viewport = getViewportSize();
1673
- const width = Math.min(PET_SUMMARY_WIDTH, viewport.width - PET_SUMMARY_MARGIN * 2);
1799
+ const width = Math.min(
1800
+ PET_SUMMARY_WIDTH,
1801
+ viewport.width - PET_SUMMARY_MARGIN * 2
1802
+ );
1674
1803
  bubble.style.width = `${width}px`;
1675
1804
  const bubbleHeight = bubble.offsetHeight || 96;
1676
1805
  const aboveY = position.y - bubbleHeight - PET_SUMMARY_GAP;
@@ -1690,6 +1819,7 @@ class PetOverlay {
1690
1819
  }
1691
1820
  createSummaryBubble(summary) {
1692
1821
  const shouldShowReplyButton = this.isSummaryHovering && !this.isReplyOpen;
1822
+ const metrics = getSummaryThemeMetrics(this.theme);
1693
1823
  const bubble = document.createElement("div");
1694
1824
  bubble.setAttribute("data-chatkit-pet-summary", "");
1695
1825
  bubble.addEventListener("pointerenter", this.handleSummaryPointerEnter);
@@ -1700,19 +1830,18 @@ class PetOverlay {
1700
1830
  bubble.style.left = "0";
1701
1831
  bubble.style.boxSizing = "border-box";
1702
1832
  bubble.style.pointerEvents = "auto";
1703
- bubble.style.padding = "12px 14px";
1704
- bubble.style.paddingBottom = "12px";
1833
+ bubble.style.padding = metrics.padding;
1705
1834
  bubble.style.border = "1px solid rgba(148, 163, 184, 0.22)";
1706
- bubble.style.borderRadius = "22px";
1835
+ bubble.style.borderRadius = `${metrics.radius}px`;
1707
1836
  bubble.style.background = "rgba(255, 255, 255, 0.94)";
1708
1837
  bubble.style.color = "#1f2937";
1709
1838
  bubble.style.boxShadow = "0 8px 24px rgba(15, 23, 42, 0.1)";
1710
- bubble.style.font = '500 14px/1.35 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
1839
+ bubble.style.font = `500 ${metrics.bodySize}px/1.35 ${metrics.fontFamily}`;
1711
1840
  bubble.style.backdropFilter = "blur(10px)";
1712
1841
  const header = document.createElement("div");
1713
1842
  header.style.display = "flex";
1714
1843
  header.style.alignItems = "center";
1715
- header.style.gap = "8px";
1844
+ header.style.gap = `${metrics.gap}px`;
1716
1845
  if (this.isSummaryHovering || this.isReplyOpen) {
1717
1846
  header.append(
1718
1847
  this.createSummaryActionButton(
@@ -1730,7 +1859,8 @@ class PetOverlay {
1730
1859
  title.style.textOverflow = "ellipsis";
1731
1860
  title.style.whiteSpace = "nowrap";
1732
1861
  title.style.fontWeight = "700";
1733
- title.style.fontSize = "15px";
1862
+ title.style.fontSize = `${metrics.titleSize}px`;
1863
+ title.dataset.chatkitPetSummaryTitle = "";
1734
1864
  header.append(title);
1735
1865
  if (this.isSummaryHovering || this.isReplyOpen) {
1736
1866
  header.append(
@@ -1745,7 +1875,7 @@ class PetOverlay {
1745
1875
  }
1746
1876
  const message = document.createElement("div");
1747
1877
  message.textContent = summary.message;
1748
- message.style.marginTop = "4px";
1878
+ message.style.marginTop = `${metrics.marginTop}px`;
1749
1879
  message.style.fontWeight = "400";
1750
1880
  message.style.color = "#374151";
1751
1881
  message.style.overflow = "hidden";
@@ -1757,6 +1887,7 @@ class PetOverlay {
1757
1887
  message.style.setProperty("-webkit-line-clamp", "2");
1758
1888
  message.style.setProperty("-webkit-box-orient", "vertical");
1759
1889
  }
1890
+ message.dataset.chatkitPetSummaryMessage = "";
1760
1891
  bubble.append(header, message);
1761
1892
  if (shouldShowReplyButton) {
1762
1893
  const reply = this.createTextButton(
@@ -1773,7 +1904,30 @@ class PetOverlay {
1773
1904
  }
1774
1905
  return bubble;
1775
1906
  }
1907
+ updateSummaryBubbleContent(summary) {
1908
+ var _a2, _b2, _c2;
1909
+ const title = (_a2 = this.summaryElement) == null ? void 0 : _a2.querySelector(
1910
+ "[data-chatkit-pet-summary-title]"
1911
+ );
1912
+ if (title && title.textContent !== summary.title) {
1913
+ title.textContent = summary.title;
1914
+ }
1915
+ const message = (_b2 = this.summaryElement) == null ? void 0 : _b2.querySelector(
1916
+ "[data-chatkit-pet-summary-message]"
1917
+ );
1918
+ if (message && message.textContent !== summary.message) {
1919
+ message.textContent = summary.message;
1920
+ }
1921
+ const statusIcon = (_c2 = this.summaryElement) == null ? void 0 : _c2.querySelector(
1922
+ "[data-chatkit-pet-summary-status]"
1923
+ );
1924
+ if (statusIcon && statusIcon.dataset.chatkitPetSummaryStatus !== summary.status) {
1925
+ const nextIcon = this.createStatusIcon(summary.status);
1926
+ statusIcon.replaceWith(nextIcon);
1927
+ }
1928
+ }
1776
1929
  createSummaryToggleButton(label) {
1930
+ const metrics = getSummaryThemeMetrics(this.theme);
1777
1931
  const button = document.createElement("button");
1778
1932
  button.type = "button";
1779
1933
  button.textContent = label;
@@ -1789,18 +1943,21 @@ class PetOverlay {
1789
1943
  button.style.color = "#475569";
1790
1944
  button.style.boxShadow = "0 6px 18px rgba(15, 23, 42, 0.1)";
1791
1945
  button.style.cursor = "pointer";
1792
- button.style.font = '600 15px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
1946
+ button.style.font = `600 ${metrics.titleSize}px/1 ${metrics.fontFamily}`;
1793
1947
  button.style.display = "flex";
1794
1948
  button.style.alignItems = "center";
1795
1949
  button.style.justifyContent = "center";
1796
1950
  return button;
1797
1951
  }
1798
1952
  createStatusIcon(status) {
1953
+ const metrics = getSummaryThemeMetrics(this.theme);
1954
+ const iconSize = metrics.iconSize;
1799
1955
  const icon = document.createElement("span");
1800
1956
  icon.setAttribute("aria-hidden", "true");
1957
+ icon.dataset.chatkitPetSummaryStatus = status;
1801
1958
  icon.style.display = "inline-flex";
1802
- icon.style.width = "16px";
1803
- icon.style.height = "16px";
1959
+ icon.style.width = `${iconSize}px`;
1960
+ icon.style.height = `${iconSize}px`;
1804
1961
  icon.style.alignItems = "center";
1805
1962
  icon.style.justifyContent = "center";
1806
1963
  icon.style.flex = "0 0 auto";
@@ -1812,7 +1969,7 @@ class PetOverlay {
1812
1969
  return icon;
1813
1970
  }
1814
1971
  icon.style.borderRadius = "999px";
1815
- icon.style.fontSize = "12px";
1972
+ icon.style.fontSize = `${Math.max(10, iconSize - 4)}px`;
1816
1973
  icon.style.fontWeight = "700";
1817
1974
  if (status === "failed") {
1818
1975
  icon.textContent = "!";
@@ -1824,8 +1981,8 @@ class PetOverlay {
1824
1981
  icon.style.border = "2px solid #22c55e";
1825
1982
  icon.style.position = "relative";
1826
1983
  const check = document.createElement("span");
1827
- check.style.width = "7px";
1828
- check.style.height = "4px";
1984
+ check.style.width = `${Math.round(iconSize * 0.44)}px`;
1985
+ check.style.height = `${Math.round(iconSize * 0.25)}px`;
1829
1986
  check.style.borderLeft = "2px solid #22c55e";
1830
1987
  check.style.borderBottom = "2px solid #22c55e";
1831
1988
  check.style.transform = "rotate(-45deg) translate(1px, -1px)";
@@ -1833,6 +1990,7 @@ class PetOverlay {
1833
1990
  return icon;
1834
1991
  }
1835
1992
  createSummaryActionButton(label, title, onClick) {
1993
+ const metrics = getSummaryThemeMetrics(this.theme);
1836
1994
  const button = document.createElement("button");
1837
1995
  button.type = "button";
1838
1996
  button.textContent = label;
@@ -1842,14 +2000,14 @@ class PetOverlay {
1842
2000
  event.stopPropagation();
1843
2001
  onClick();
1844
2002
  });
1845
- button.style.width = "26px";
1846
- button.style.height = "26px";
2003
+ button.style.width = `${metrics.actionSize}px`;
2004
+ button.style.height = `${metrics.actionSize}px`;
1847
2005
  button.style.border = "0";
1848
2006
  button.style.borderRadius = "999px";
1849
2007
  button.style.background = "rgba(241, 245, 249, 0.96)";
1850
2008
  button.style.color = "#475569";
1851
2009
  button.style.cursor = "pointer";
1852
- button.style.font = '600 15px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2010
+ button.style.font = `600 ${metrics.titleSize}px/1 ${metrics.fontFamily}`;
1853
2011
  return button;
1854
2012
  }
1855
2013
  createTextButton(label, onClick) {
@@ -1915,6 +2073,95 @@ class PetOverlay {
1915
2073
  }
1916
2074
  return form;
1917
2075
  }
2076
+ createContextMenu() {
2077
+ const menu = document.createElement("div");
2078
+ menu.setAttribute("data-chatkit-pet-context-menu", "");
2079
+ menu.setAttribute("role", "menu");
2080
+ menu.addEventListener("contextmenu", this.handleContextMenuEvent);
2081
+ menu.addEventListener("pointerdown", stopEventPropagation);
2082
+ menu.addEventListener("click", stopEventPropagation);
2083
+ menu.style.position = "absolute";
2084
+ menu.style.top = "0";
2085
+ menu.style.left = "0";
2086
+ menu.style.boxSizing = "border-box";
2087
+ menu.style.minWidth = "132px";
2088
+ menu.style.padding = "4px";
2089
+ menu.style.pointerEvents = "auto";
2090
+ menu.style.border = "1px solid rgba(148, 163, 184, 0.28)";
2091
+ menu.style.borderRadius = "10px";
2092
+ menu.style.background = "rgba(255, 255, 255, 0.96)";
2093
+ menu.style.color = "#1f2937";
2094
+ menu.style.boxShadow = "0 12px 28px rgba(15, 23, 42, 0.16)";
2095
+ menu.style.font = '500 13px/1.3 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2096
+ menu.style.backdropFilter = "blur(10px)";
2097
+ const closeItem = document.createElement("button");
2098
+ closeItem.type = "button";
2099
+ closeItem.textContent = this.copy.closePetMenuItem;
2100
+ closeItem.setAttribute("role", "menuitem");
2101
+ closeItem.addEventListener("click", this.handleClosePetMenuItemClick);
2102
+ closeItem.style.display = "block";
2103
+ closeItem.style.width = "100%";
2104
+ closeItem.style.border = "0";
2105
+ closeItem.style.borderRadius = "7px";
2106
+ closeItem.style.background = "transparent";
2107
+ closeItem.style.color = "inherit";
2108
+ closeItem.style.cursor = "pointer";
2109
+ closeItem.style.padding = "7px 10px";
2110
+ closeItem.style.textAlign = "left";
2111
+ closeItem.style.font = "inherit";
2112
+ menu.append(closeItem);
2113
+ return menu;
2114
+ }
2115
+ openContextMenu(position) {
2116
+ var _a2;
2117
+ const overlay = this.overlayElement;
2118
+ if (!overlay) {
2119
+ return;
2120
+ }
2121
+ this.closeContextMenu();
2122
+ const menu = this.createContextMenu();
2123
+ overlay.append(menu);
2124
+ this.contextMenuElement = menu;
2125
+ this.positionContextMenu(position);
2126
+ (_a2 = menu.querySelector("button")) == null ? void 0 : _a2.focus({ preventScroll: true });
2127
+ window.addEventListener(
2128
+ "pointerdown",
2129
+ this.handleContextMenuOutsidePointerDown,
2130
+ true
2131
+ );
2132
+ window.addEventListener("keydown", this.handleContextMenuKeyDown);
2133
+ }
2134
+ closeContextMenu() {
2135
+ var _a2;
2136
+ (_a2 = this.contextMenuElement) == null ? void 0 : _a2.remove();
2137
+ this.contextMenuElement = null;
2138
+ window.removeEventListener(
2139
+ "pointerdown",
2140
+ this.handleContextMenuOutsidePointerDown,
2141
+ true
2142
+ );
2143
+ window.removeEventListener("keydown", this.handleContextMenuKeyDown);
2144
+ }
2145
+ positionContextMenu(position) {
2146
+ const menu = this.contextMenuElement;
2147
+ if (!menu) {
2148
+ return;
2149
+ }
2150
+ const viewport = getViewportSize();
2151
+ const width = menu.offsetWidth || 132;
2152
+ const height = menu.offsetHeight || 40;
2153
+ const maxX = Math.max(
2154
+ PET_CONTEXT_MENU_MARGIN,
2155
+ viewport.width - width - PET_CONTEXT_MENU_MARGIN
2156
+ );
2157
+ const maxY = Math.max(
2158
+ PET_CONTEXT_MENU_MARGIN,
2159
+ viewport.height - height - PET_CONTEXT_MENU_MARGIN
2160
+ );
2161
+ const x = clampNumber(position.x, PET_CONTEXT_MENU_MARGIN, maxX);
2162
+ const y = clampNumber(position.y, PET_CONTEXT_MENU_MARGIN, maxY);
2163
+ menu.style.transform = `translate3d(${x}px, ${y}px, 0)`;
2164
+ }
1918
2165
  renderAtlas(animationName, animationMode) {
1919
2166
  var _a2;
1920
2167
  if (!this.petElement || ((_a2 = this.resolved) == null ? void 0 : _a2.kind) !== "atlas" || !this.options) {
@@ -2015,13 +2262,16 @@ class PetOverlay {
2015
2262
  this.rescheduleAnimation();
2016
2263
  }, PET_RESTING_DELAY_MS);
2017
2264
  }
2018
- isPointerOverPet(event) {
2265
+ isPointOverPet(clientX, clientY) {
2019
2266
  var _a2;
2020
2267
  const rect = (_a2 = this.petElement) == null ? void 0 : _a2.getBoundingClientRect();
2021
2268
  if (!rect) {
2022
2269
  return false;
2023
2270
  }
2024
- return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
2271
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
2272
+ }
2273
+ isPointerOverPet(event) {
2274
+ return this.isPointOverPet(event.clientX, event.clientY);
2025
2275
  }
2026
2276
  async submitReply() {
2027
2277
  var _a2;
@@ -2085,7 +2335,7 @@ function requireCommandCapability(value, context) {
2085
2335
  return value.apply(this, args);
2086
2336
  };
2087
2337
  }
2088
- class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requireCommandCapability], _fetchUpdates_dec = [requireCommandCapability], _sendUserMessage_dec = [requireCommandCapability], _setComposerValue_dec = [requireCommandCapability], _setThreadId_dec = [requireCommandCapability], _shareThread_dec = [requireCommandCapability], _sendCustomAction_dec = [requireCommandCapability], _showHistory_dec = [requireCommandCapability], _hideHistory_dec = [requireCommandCapability], _setTrainingOptOut_dec = [requireCommandCapability], _c) {
2338
+ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requireCommandCapability], _fetchUpdates_dec = [requireCommandCapability], _sendUserMessage_dec = [requireCommandCapability], _setComposerValue_dec = [requireCommandCapability], _setRuntimeCapabilities_dec = [requireCommandCapability], _setThreadId_dec = [requireCommandCapability], _shareThread_dec = [requireCommandCapability], _sendCustomAction_dec = [requireCommandCapability], _showHistory_dec = [requireCommandCapability], _hideHistory_dec = [requireCommandCapability], _setTrainingOptOut_dec = [requireCommandCapability], _c) {
2089
2339
  constructor({ profile }) {
2090
2340
  super();
2091
2341
  __runInitializers(_init, 5, this);
@@ -2096,10 +2346,13 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2096
2346
  __privateAdd(this, _wrapper);
2097
2347
  __privateAdd(this, _launcherCloseButton);
2098
2348
  __privateAdd(this, _launcherOpen, false);
2349
+ __privateAdd(this, _chatMinimizedToPet, false);
2099
2350
  __privateAdd(this, _framePetOptionsOverride);
2351
+ __privateAdd(this, _petClosedByContextMenu, false);
2100
2352
  __privateAdd(this, _shadow, this.attachShadow({ mode: "open" }));
2101
2353
  __privateAdd(this, _petOverlay, new PetOverlay(__privateGet(this, _shadow), {
2102
2354
  onActivate: () => __privateMethod(this, _ChatKitElementBase_instances, handlePetActivate_fn).call(this),
2355
+ onClose: () => __privateMethod(this, _ChatKitElementBase_instances, handlePetClose_fn).call(this),
2103
2356
  onReply: (text) => __privateMethod(this, _ChatKitElementBase_instances, handlePetReply_fn).call(this, text),
2104
2357
  onThreadSummaryActivate: (threadId) => void __privateMethod(this, _ChatKitElementBase_instances, handlePetThreadSummaryActivate_fn).call(this, threadId)
2105
2358
  }));
@@ -2230,6 +2483,9 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2230
2483
  :host([data-display-mode="pet"]) {
2231
2484
  display: contents;
2232
2485
  }
2486
+ :host([data-chat-minimized-to-pet="true"]) {
2487
+ display: contents;
2488
+ }
2233
2489
  .ck-iframe {
2234
2490
  border: none;
2235
2491
  position: absolute;
@@ -2340,6 +2596,11 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2340
2596
  :host([data-loaded="true"]) .ck-wrapper {
2341
2597
  opacity: 1;
2342
2598
  }
2599
+ :host([data-chat-minimized-to-pet="true"]) .ck-wrapper {
2600
+ opacity: 0;
2601
+ pointer-events: none;
2602
+ visibility: hidden;
2603
+ }
2343
2604
  :host([data-display-mode="pet"]:not([data-chat-open="true"])) .ck-wrapper {
2344
2605
  opacity: 0;
2345
2606
  }
@@ -2422,8 +2683,21 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2422
2683
  __privateGet(this, _messenger).on("pet_options_change", (data) => {
2423
2684
  const payload = parsePetOptionsChangePayload(data);
2424
2685
  if (payload) {
2686
+ if (!__privateGet(this, _petClosedByContextMenu) || payload.pet === null) {
2687
+ __privateSet(this, _petClosedByContextMenu, false);
2688
+ }
2425
2689
  __privateSet(this, _framePetOptionsOverride, payload.pet);
2426
- __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
2690
+ __privateMethod(this, _ChatKitElementBase_instances, syncPetOverlayOptions_fn).call(this);
2691
+ }
2692
+ });
2693
+ __privateGet(this, _messenger).on("chat_minimize_change", (data) => {
2694
+ const minimized = typeof data === "object" && data !== null && "minimized" in data && data.minimized === true;
2695
+ if (minimized && !__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this)) {
2696
+ return;
2697
+ }
2698
+ __privateMethod(this, _ChatKitElementBase_instances, setChatMinimizedToPet_fn).call(this, minimized);
2699
+ if (minimized) {
2700
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, false);
2427
2701
  }
2428
2702
  });
2429
2703
  __privateGet(this, _messenger).on("unmount", () => {
@@ -2459,8 +2733,9 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2459
2733
  }
2460
2734
  applySanitizedOptions(newOptions) {
2461
2735
  __privateSet(this, _opts, newOptions);
2736
+ __privateSet(this, _petClosedByContextMenu, false);
2462
2737
  __privateGet(this, _petOverlay).setLocale(newOptions.locale);
2463
- __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
2738
+ __privateMethod(this, _ChatKitElementBase_instances, syncPetOverlayOptions_fn).call(this);
2464
2739
  if (__privateGet(this, _initialized)) {
2465
2740
  __privateMethod(this, _ChatKitElementBase_instances, setOptionsDataAttributes_fn).call(this, __privateGet(this, _opts));
2466
2741
  __privateGet(this, _loaded).then(() => {
@@ -2502,6 +2777,11 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2502
2777
  await __privateGet(this, _loaded);
2503
2778
  await ((_a2 = __privateGet(this, _messenger)) == null ? void 0 : _a2.commands.setComposerValue(params));
2504
2779
  }
2780
+ async setRuntimeCapabilities(selection) {
2781
+ var _a2;
2782
+ await __privateGet(this, _loaded);
2783
+ await ((_a2 = __privateGet(this, _messenger)) == null ? void 0 : _a2.commands.setRuntimeCapabilities(selection));
2784
+ }
2505
2785
  async setThreadId(threadId) {
2506
2786
  var _a2;
2507
2787
  await __privateGet(this, _loaded);
@@ -2540,7 +2820,9 @@ _frame = new WeakMap();
2540
2820
  _wrapper = new WeakMap();
2541
2821
  _launcherCloseButton = new WeakMap();
2542
2822
  _launcherOpen = new WeakMap();
2823
+ _chatMinimizedToPet = new WeakMap();
2543
2824
  _framePetOptionsOverride = new WeakMap();
2825
+ _petClosedByContextMenu = new WeakMap();
2544
2826
  _shadow = new WeakMap();
2545
2827
  _petOverlay = new WeakMap();
2546
2828
  _resolveLoaded = new WeakMap();
@@ -2571,8 +2853,42 @@ getConfiguredPetOptions_fn = function(options = __privateGet(this, _opts)) {
2571
2853
  }
2572
2854
  return options.pet ?? null;
2573
2855
  };
2856
+ mergeConfiguredPetPositionDefaults_fn = function(pet) {
2857
+ if (!pet) {
2858
+ return pet;
2859
+ }
2860
+ const configured = chatkitTypes.normalizePetOptions(
2861
+ __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this) ?? null
2862
+ );
2863
+ if (!configured) {
2864
+ return pet;
2865
+ }
2866
+ if (pet === true) {
2867
+ return { position: configured.position };
2868
+ }
2869
+ if (!pet.position) {
2870
+ return { ...pet, position: configured.position };
2871
+ }
2872
+ return {
2873
+ ...pet,
2874
+ position: {
2875
+ ...configured.position,
2876
+ ...pet.position,
2877
+ boundsPadding: pet.position.boundsPadding ?? configured.position.boundsPadding,
2878
+ pin: "pin" in pet.position ? pet.position.pin : configured.position.pin
2879
+ }
2880
+ };
2881
+ };
2574
2882
  getOverlayPetOptions_fn = function() {
2575
- let pet = __privateGet(this, _framePetOptionsOverride) !== void 0 ? __privateGet(this, _framePetOptionsOverride) : __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this);
2883
+ if (__privateGet(this, _petClosedByContextMenu)) {
2884
+ return null;
2885
+ }
2886
+ let pet;
2887
+ if (__privateGet(this, _framePetOptionsOverride) !== void 0) {
2888
+ pet = __privateMethod(this, _ChatKitElementBase_instances, mergeConfiguredPetPositionDefaults_fn).call(this, __privateGet(this, _framePetOptionsOverride));
2889
+ } else {
2890
+ pet = __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this);
2891
+ }
2576
2892
  if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet" && !chatkitTypes.normalizePetOptions(pet ?? null)) {
2577
2893
  pet = true;
2578
2894
  }
@@ -2626,13 +2942,49 @@ setLauncherOpen_fn = function(open) {
2626
2942
  delete this.dataset.chatOpen;
2627
2943
  }
2628
2944
  };
2945
+ setChatMinimizedToPet_fn = function(minimized) {
2946
+ const next = minimized && Boolean(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
2947
+ __privateSet(this, _chatMinimizedToPet, next);
2948
+ if (next) {
2949
+ this.dataset.chatMinimizedToPet = "true";
2950
+ } else {
2951
+ delete this.dataset.chatMinimizedToPet;
2952
+ }
2953
+ };
2954
+ syncPetOverlayOptions_fn = function() {
2955
+ var _a2;
2956
+ const overlayPetOptions = __privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this);
2957
+ __privateGet(this, _petOverlay).setOptions(overlayPetOptions, (_a2 = __privateGet(this, _opts)) == null ? void 0 : _a2.theme);
2958
+ if (!overlayPetOptions) {
2959
+ __privateMethod(this, _ChatKitElementBase_instances, setChatMinimizedToPet_fn).call(this, false);
2960
+ }
2961
+ };
2629
2962
  handlePetActivate_fn = function() {
2963
+ if (__privateGet(this, _chatMinimizedToPet)) {
2964
+ __privateMethod(this, _ChatKitElementBase_instances, setChatMinimizedToPet_fn).call(this, false);
2965
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet") {
2966
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, true);
2967
+ }
2968
+ __privateGet(this, _loaded).then(() => this.focusComposer()).catch(() => void 0);
2969
+ return;
2970
+ }
2630
2971
  if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) !== "pet") {
2631
2972
  return;
2632
2973
  }
2633
2974
  __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, true);
2634
2975
  __privateGet(this, _loaded).then(() => this.focusComposer()).catch(() => void 0);
2635
2976
  };
2977
+ handlePetClose_fn = function() {
2978
+ __privateSet(this, _petClosedByContextMenu, true);
2979
+ __privateSet(this, _framePetOptionsOverride, null);
2980
+ __privateMethod(this, _ChatKitElementBase_instances, setChatMinimizedToPet_fn).call(this, false);
2981
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, false);
2982
+ __privateGet(this, _petOverlay).setOptions(null);
2983
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet") {
2984
+ return;
2985
+ }
2986
+ __privateGet(this, _loaded).then(() => __privateGet(this, _messenger).commands.setPetEnabled({ enabled: false })).catch(() => void 0);
2987
+ };
2636
2988
  handlePetReply_fn = async function(text) {
2637
2989
  await this.sendUserMessage({ text });
2638
2990
  };
@@ -2697,6 +3049,7 @@ __decorateElement(_init, 1, "focusComposer", _focusComposer_dec, ChatKitElementB
2697
3049
  __decorateElement(_init, 1, "fetchUpdates", _fetchUpdates_dec, ChatKitElementBase);
2698
3050
  __decorateElement(_init, 1, "sendUserMessage", _sendUserMessage_dec, ChatKitElementBase);
2699
3051
  __decorateElement(_init, 1, "setComposerValue", _setComposerValue_dec, ChatKitElementBase);
3052
+ __decorateElement(_init, 1, "setRuntimeCapabilities", _setRuntimeCapabilities_dec, ChatKitElementBase);
2700
3053
  __decorateElement(_init, 1, "setThreadId", _setThreadId_dec, ChatKitElementBase);
2701
3054
  __decorateElement(_init, 1, "shareThread", _shareThread_dec, ChatKitElementBase);
2702
3055
  __decorateElement(_init, 1, "sendCustomAction", _sendCustomAction_dec, ChatKitElementBase);
@@ -2921,6 +3274,9 @@ const ChatKit = ControlBase.extend("xpertai.chatkit.ui5.ChatKit", {
2921
3274
  setComposerValue(...args) {
2922
3275
  return this._callMethod("setComposerValue", ...args);
2923
3276
  },
3277
+ setRuntimeCapabilities(...args) {
3278
+ return this._callMethod("setRuntimeCapabilities", ...args);
3279
+ },
2924
3280
  fetchUpdates(...args) {
2925
3281
  return this._callMethod("fetchUpdates", ...args);
2926
3282
  },