@xpert-ai/chatkit-web-component 0.3.0 → 0.3.1

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.
@@ -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, _setComposerValue_dec, _sendUserMessage_dec, _fetchUpdates_dec, _focusComposer_dec, _c, _opts, _frameUrl, _frame, _wrapper, _launcherCloseButton, _launcherOpen, _framePetOptionsOverride, _petClosedByContextMenu, _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, handlePetClose_fn, handlePetReply_fn, handlePetThreadSummaryActivate_fn, _handleLauncherClose, getFrameUrl_fn, setFrameUrl_fn, consumeFrameUrl_fn, _handleFrameLoad, _initialized, maybeInit_fn, _init;
51
51
  class EventEmitter {
52
52
  constructor() {
53
53
  __publicField(this, "callbacks", /* @__PURE__ */ new Map());
@@ -1137,8 +1137,10 @@ const PET_RESTING_DELAY_MS = 2e3;
1137
1137
  const PET_SUMMARY_GAP = 12;
1138
1138
  const PET_SUMMARY_WIDTH = 320;
1139
1139
  const PET_SUMMARY_MARGIN = 12;
1140
+ const PET_CONTEXT_MENU_MARGIN = 8;
1140
1141
  const PET_OVERLAY_COPY = {
1141
1142
  "en-US": {
1143
+ closePetMenuItem: "Close pet",
1142
1144
  hideMessage: "Hide message",
1143
1145
  expandMessage: "Expand message",
1144
1146
  collapseMessage: "Collapse message",
@@ -1150,6 +1152,7 @@ const PET_OVERLAY_COPY = {
1150
1152
  sendFailed: "Failed to send"
1151
1153
  },
1152
1154
  "zh-CN": {
1155
+ closePetMenuItem: "关闭宠物",
1153
1156
  hideMessage: "隐藏消息",
1154
1157
  expandMessage: "展开消息",
1155
1158
  collapseMessage: "收起消息",
@@ -1297,6 +1300,7 @@ class PetOverlay {
1297
1300
  constructor(root, options) {
1298
1301
  this.overlayElement = null;
1299
1302
  this.petElement = null;
1303
+ this.contextMenuElement = null;
1300
1304
  this.summaryElement = null;
1301
1305
  this.summaryToggleElement = null;
1302
1306
  this.mediaElement = null;
@@ -1337,6 +1341,7 @@ class PetOverlay {
1337
1341
  this.mediaQuery = null;
1338
1342
  this.connected = false;
1339
1343
  this.handleViewportChange = () => {
1344
+ this.closeContextMenu();
1340
1345
  this.render();
1341
1346
  };
1342
1347
  this.handleReducedMotionChange = () => {
@@ -1357,6 +1362,36 @@ class PetOverlay {
1357
1362
  this.enterRestingAfterDelay();
1358
1363
  }
1359
1364
  };
1365
+ this.handleContextMenu = (event) => {
1366
+ event.preventDefault();
1367
+ event.stopPropagation();
1368
+ this.openContextMenu({ x: event.clientX, y: event.clientY });
1369
+ };
1370
+ this.handleContextMenuEvent = (event) => {
1371
+ event.preventDefault();
1372
+ event.stopPropagation();
1373
+ };
1374
+ this.handleContextMenuOutsidePointerDown = (event) => {
1375
+ const menu = this.contextMenuElement;
1376
+ if (menu && event.composedPath().includes(menu)) {
1377
+ return;
1378
+ }
1379
+ this.closeContextMenu();
1380
+ };
1381
+ this.handleContextMenuKeyDown = (event) => {
1382
+ if (event.key !== "Escape") {
1383
+ return;
1384
+ }
1385
+ event.preventDefault();
1386
+ this.closeContextMenu();
1387
+ };
1388
+ this.handleClosePetMenuItemClick = (event) => {
1389
+ var _a2;
1390
+ event.preventDefault();
1391
+ event.stopPropagation();
1392
+ this.closeContextMenu();
1393
+ (_a2 = this.onClose) == null ? void 0 : _a2.call(this);
1394
+ };
1360
1395
  this.handleSummaryPointerEnter = () => {
1361
1396
  this.isSummaryHovering = true;
1362
1397
  this.render();
@@ -1424,7 +1459,11 @@ class PetOverlay {
1424
1459
  };
1425
1460
  this.handlePointerDown = (event) => {
1426
1461
  var _a2, _b2;
1427
- if (!((_a2 = this.options) == null ? void 0 : _a2.position.draggable) || event.button !== 0) {
1462
+ if (event.button !== 0 || event.ctrlKey) {
1463
+ return;
1464
+ }
1465
+ this.closeContextMenu();
1466
+ if (!((_a2 = this.options) == null ? void 0 : _a2.position.draggable)) {
1428
1467
  return;
1429
1468
  }
1430
1469
  event.preventDefault();
@@ -1500,6 +1539,7 @@ class PetOverlay {
1500
1539
  };
1501
1540
  this.root = root;
1502
1541
  this.onActivate = options == null ? void 0 : options.onActivate;
1542
+ this.onClose = options == null ? void 0 : options.onClose;
1503
1543
  this.onReply = options == null ? void 0 : options.onReply;
1504
1544
  this.onThreadSummaryActivate = options == null ? void 0 : options.onThreadSummaryActivate;
1505
1545
  this.connect();
@@ -1514,6 +1554,7 @@ class PetOverlay {
1514
1554
  this.render();
1515
1555
  }
1516
1556
  setOptions(pet) {
1557
+ this.closeContextMenu();
1517
1558
  const nextOptions = normalizePetOptions(pet);
1518
1559
  this.options = nextOptions;
1519
1560
  if (!nextOptions) {
@@ -1561,6 +1602,7 @@ class PetOverlay {
1561
1602
  this.copyLocale = nextLocale;
1562
1603
  this.copy = PET_OVERLAY_COPY[nextLocale];
1563
1604
  this.summaryRenderKey = null;
1605
+ this.closeContextMenu();
1564
1606
  this.render();
1565
1607
  }
1566
1608
  setThreadSummary(summary) {
@@ -1626,8 +1668,14 @@ class PetOverlay {
1626
1668
  installViewportListeners() {
1627
1669
  var _a2, _b2;
1628
1670
  window.addEventListener("resize", this.handleViewportChange);
1629
- (_a2 = window.visualViewport) == null ? void 0 : _a2.addEventListener("resize", this.handleViewportChange);
1630
- (_b2 = window.visualViewport) == null ? void 0 : _b2.addEventListener("scroll", this.handleViewportChange);
1671
+ (_a2 = window.visualViewport) == null ? void 0 : _a2.addEventListener(
1672
+ "resize",
1673
+ this.handleViewportChange
1674
+ );
1675
+ (_b2 = window.visualViewport) == null ? void 0 : _b2.addEventListener(
1676
+ "scroll",
1677
+ this.handleViewportChange
1678
+ );
1631
1679
  }
1632
1680
  installReducedMotionListener() {
1633
1681
  var _a2, _b2;
@@ -1678,6 +1726,7 @@ class PetOverlay {
1678
1726
  pet.addEventListener("pointerenter", this.handlePointerEnter);
1679
1727
  pet.addEventListener("pointerleave", this.handlePointerLeave);
1680
1728
  pet.addEventListener("pointerdown", this.handlePointerDown);
1729
+ pet.addEventListener("contextmenu", this.handleContextMenu);
1681
1730
  pet.addEventListener("click", this.handleClick);
1682
1731
  overlay.append(style, pet);
1683
1732
  this.root.append(overlay);
@@ -1688,6 +1737,7 @@ class PetOverlay {
1688
1737
  var _a2;
1689
1738
  this.clearRestingDelayTimer();
1690
1739
  this.clearTimers();
1740
+ this.closeContextMenu();
1691
1741
  if (this.petElement) {
1692
1742
  this.petElement.removeEventListener(
1693
1743
  "pointerenter",
@@ -1697,7 +1747,14 @@ class PetOverlay {
1697
1747
  "pointerleave",
1698
1748
  this.handlePointerLeave
1699
1749
  );
1700
- this.petElement.removeEventListener("pointerdown", this.handlePointerDown);
1750
+ this.petElement.removeEventListener(
1751
+ "pointerdown",
1752
+ this.handlePointerDown
1753
+ );
1754
+ this.petElement.removeEventListener(
1755
+ "contextmenu",
1756
+ this.handleContextMenu
1757
+ );
1701
1758
  this.petElement.removeEventListener("click", this.handleClick);
1702
1759
  }
1703
1760
  this.isHovering = false;
@@ -1861,7 +1918,10 @@ class PetOverlay {
1861
1918
  (_b2 = this.summaryToggleElement) == null ? void 0 : _b2.remove();
1862
1919
  this.summaryElement = this.createSummaryBubble(summary);
1863
1920
  this.summaryToggleElement = this.createSummaryToggleButton("v");
1864
- (_c2 = this.overlayElement) == null ? void 0 : _c2.append(this.summaryElement, this.summaryToggleElement);
1921
+ (_c2 = this.overlayElement) == null ? void 0 : _c2.append(
1922
+ this.summaryElement,
1923
+ this.summaryToggleElement
1924
+ );
1865
1925
  this.summaryRenderKey = nextRenderKey;
1866
1926
  if (this.isReplyOpen && !this.isReplySubmitting) {
1867
1927
  window.setTimeout(() => {
@@ -1913,7 +1973,10 @@ class PetOverlay {
1913
1973
  return;
1914
1974
  }
1915
1975
  const viewport = getViewportSize();
1916
- const width = Math.min(PET_SUMMARY_WIDTH, viewport.width - PET_SUMMARY_MARGIN * 2);
1976
+ const width = Math.min(
1977
+ PET_SUMMARY_WIDTH,
1978
+ viewport.width - PET_SUMMARY_MARGIN * 2
1979
+ );
1917
1980
  bubble.style.width = `${width}px`;
1918
1981
  const bubbleHeight = bubble.offsetHeight || 96;
1919
1982
  const aboveY = position.y - bubbleHeight - PET_SUMMARY_GAP;
@@ -2158,6 +2221,95 @@ class PetOverlay {
2158
2221
  }
2159
2222
  return form;
2160
2223
  }
2224
+ createContextMenu() {
2225
+ const menu = document.createElement("div");
2226
+ menu.setAttribute("data-chatkit-pet-context-menu", "");
2227
+ menu.setAttribute("role", "menu");
2228
+ menu.addEventListener("contextmenu", this.handleContextMenuEvent);
2229
+ menu.addEventListener("pointerdown", stopEventPropagation);
2230
+ menu.addEventListener("click", stopEventPropagation);
2231
+ menu.style.position = "absolute";
2232
+ menu.style.top = "0";
2233
+ menu.style.left = "0";
2234
+ menu.style.boxSizing = "border-box";
2235
+ menu.style.minWidth = "132px";
2236
+ menu.style.padding = "4px";
2237
+ menu.style.pointerEvents = "auto";
2238
+ menu.style.border = "1px solid rgba(148, 163, 184, 0.28)";
2239
+ menu.style.borderRadius = "10px";
2240
+ menu.style.background = "rgba(255, 255, 255, 0.96)";
2241
+ menu.style.color = "#1f2937";
2242
+ menu.style.boxShadow = "0 12px 28px rgba(15, 23, 42, 0.16)";
2243
+ menu.style.font = '500 13px/1.3 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2244
+ menu.style.backdropFilter = "blur(10px)";
2245
+ const closeItem = document.createElement("button");
2246
+ closeItem.type = "button";
2247
+ closeItem.textContent = this.copy.closePetMenuItem;
2248
+ closeItem.setAttribute("role", "menuitem");
2249
+ closeItem.addEventListener("click", this.handleClosePetMenuItemClick);
2250
+ closeItem.style.display = "block";
2251
+ closeItem.style.width = "100%";
2252
+ closeItem.style.border = "0";
2253
+ closeItem.style.borderRadius = "7px";
2254
+ closeItem.style.background = "transparent";
2255
+ closeItem.style.color = "inherit";
2256
+ closeItem.style.cursor = "pointer";
2257
+ closeItem.style.padding = "7px 10px";
2258
+ closeItem.style.textAlign = "left";
2259
+ closeItem.style.font = "inherit";
2260
+ menu.append(closeItem);
2261
+ return menu;
2262
+ }
2263
+ openContextMenu(position) {
2264
+ var _a2;
2265
+ const overlay = this.overlayElement;
2266
+ if (!overlay) {
2267
+ return;
2268
+ }
2269
+ this.closeContextMenu();
2270
+ const menu = this.createContextMenu();
2271
+ overlay.append(menu);
2272
+ this.contextMenuElement = menu;
2273
+ this.positionContextMenu(position);
2274
+ (_a2 = menu.querySelector("button")) == null ? void 0 : _a2.focus({ preventScroll: true });
2275
+ window.addEventListener(
2276
+ "pointerdown",
2277
+ this.handleContextMenuOutsidePointerDown,
2278
+ true
2279
+ );
2280
+ window.addEventListener("keydown", this.handleContextMenuKeyDown);
2281
+ }
2282
+ closeContextMenu() {
2283
+ var _a2;
2284
+ (_a2 = this.contextMenuElement) == null ? void 0 : _a2.remove();
2285
+ this.contextMenuElement = null;
2286
+ window.removeEventListener(
2287
+ "pointerdown",
2288
+ this.handleContextMenuOutsidePointerDown,
2289
+ true
2290
+ );
2291
+ window.removeEventListener("keydown", this.handleContextMenuKeyDown);
2292
+ }
2293
+ positionContextMenu(position) {
2294
+ const menu = this.contextMenuElement;
2295
+ if (!menu) {
2296
+ return;
2297
+ }
2298
+ const viewport = getViewportSize();
2299
+ const width = menu.offsetWidth || 132;
2300
+ const height = menu.offsetHeight || 40;
2301
+ const maxX = Math.max(
2302
+ PET_CONTEXT_MENU_MARGIN,
2303
+ viewport.width - width - PET_CONTEXT_MENU_MARGIN
2304
+ );
2305
+ const maxY = Math.max(
2306
+ PET_CONTEXT_MENU_MARGIN,
2307
+ viewport.height - height - PET_CONTEXT_MENU_MARGIN
2308
+ );
2309
+ const x = clampNumber(position.x, PET_CONTEXT_MENU_MARGIN, maxX);
2310
+ const y = clampNumber(position.y, PET_CONTEXT_MENU_MARGIN, maxY);
2311
+ menu.style.transform = `translate3d(${x}px, ${y}px, 0)`;
2312
+ }
2161
2313
  renderAtlas(animationName, animationMode) {
2162
2314
  var _a2;
2163
2315
  if (!this.petElement || ((_a2 = this.resolved) == null ? void 0 : _a2.kind) !== "atlas" || !this.options) {
@@ -2258,13 +2410,16 @@ class PetOverlay {
2258
2410
  this.rescheduleAnimation();
2259
2411
  }, PET_RESTING_DELAY_MS);
2260
2412
  }
2261
- isPointerOverPet(event) {
2413
+ isPointOverPet(clientX, clientY) {
2262
2414
  var _a2;
2263
2415
  const rect = (_a2 = this.petElement) == null ? void 0 : _a2.getBoundingClientRect();
2264
2416
  if (!rect) {
2265
2417
  return false;
2266
2418
  }
2267
- return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
2419
+ return clientX >= rect.left && clientX <= rect.right && clientY >= rect.top && clientY <= rect.bottom;
2420
+ }
2421
+ isPointerOverPet(event) {
2422
+ return this.isPointOverPet(event.clientX, event.clientY);
2268
2423
  }
2269
2424
  async submitReply() {
2270
2425
  var _a2;
@@ -2340,9 +2495,11 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2340
2495
  __privateAdd(this, _launcherCloseButton);
2341
2496
  __privateAdd(this, _launcherOpen, false);
2342
2497
  __privateAdd(this, _framePetOptionsOverride);
2498
+ __privateAdd(this, _petClosedByContextMenu, false);
2343
2499
  __privateAdd(this, _shadow, this.attachShadow({ mode: "open" }));
2344
2500
  __privateAdd(this, _petOverlay, new PetOverlay(__privateGet(this, _shadow), {
2345
2501
  onActivate: () => __privateMethod(this, _ChatKitElementBase_instances, handlePetActivate_fn).call(this),
2502
+ onClose: () => __privateMethod(this, _ChatKitElementBase_instances, handlePetClose_fn).call(this),
2346
2503
  onReply: (text) => __privateMethod(this, _ChatKitElementBase_instances, handlePetReply_fn).call(this, text),
2347
2504
  onThreadSummaryActivate: (threadId) => void __privateMethod(this, _ChatKitElementBase_instances, handlePetThreadSummaryActivate_fn).call(this, threadId)
2348
2505
  }));
@@ -2665,6 +2822,9 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2665
2822
  __privateGet(this, _messenger).on("pet_options_change", (data) => {
2666
2823
  const payload = parsePetOptionsChangePayload(data);
2667
2824
  if (payload) {
2825
+ if (!__privateGet(this, _petClosedByContextMenu) || payload.pet === null) {
2826
+ __privateSet(this, _petClosedByContextMenu, false);
2827
+ }
2668
2828
  __privateSet(this, _framePetOptionsOverride, payload.pet);
2669
2829
  __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
2670
2830
  }
@@ -2702,6 +2862,7 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
2702
2862
  }
2703
2863
  applySanitizedOptions(newOptions) {
2704
2864
  __privateSet(this, _opts, newOptions);
2865
+ __privateSet(this, _petClosedByContextMenu, false);
2705
2866
  __privateGet(this, _petOverlay).setLocale(newOptions.locale);
2706
2867
  __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
2707
2868
  if (__privateGet(this, _initialized)) {
@@ -2784,6 +2945,7 @@ _wrapper = new WeakMap();
2784
2945
  _launcherCloseButton = new WeakMap();
2785
2946
  _launcherOpen = new WeakMap();
2786
2947
  _framePetOptionsOverride = new WeakMap();
2948
+ _petClosedByContextMenu = new WeakMap();
2787
2949
  _shadow = new WeakMap();
2788
2950
  _petOverlay = new WeakMap();
2789
2951
  _resolveLoaded = new WeakMap();
@@ -2815,6 +2977,9 @@ getConfiguredPetOptions_fn = function(options = __privateGet(this, _opts)) {
2815
2977
  return options.pet ?? null;
2816
2978
  };
2817
2979
  getOverlayPetOptions_fn = function() {
2980
+ if (__privateGet(this, _petClosedByContextMenu)) {
2981
+ return null;
2982
+ }
2818
2983
  let pet = __privateGet(this, _framePetOptionsOverride) !== void 0 ? __privateGet(this, _framePetOptionsOverride) : __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this);
2819
2984
  if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet" && !normalizePetOptions(pet ?? null)) {
2820
2985
  pet = true;
@@ -2876,6 +3041,16 @@ handlePetActivate_fn = function() {
2876
3041
  __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, true);
2877
3042
  __privateGet(this, _loaded).then(() => this.focusComposer()).catch(() => void 0);
2878
3043
  };
3044
+ handlePetClose_fn = function() {
3045
+ __privateSet(this, _petClosedByContextMenu, true);
3046
+ __privateSet(this, _framePetOptionsOverride, null);
3047
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, false);
3048
+ __privateGet(this, _petOverlay).setOptions(null);
3049
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet") {
3050
+ return;
3051
+ }
3052
+ __privateGet(this, _loaded).then(() => __privateGet(this, _messenger).commands.setPetEnabled({ enabled: false })).catch(() => void 0);
3053
+ };
2879
3054
  handlePetReply_fn = async function(text) {
2880
3055
  await this.sendUserMessage({ text });
2881
3056
  };