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