@xpert-ai/chatkit-react 0.1.2 → 0.3.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, _shadow, _resolveLoaded, _loaded, _messenger, _ChatKitElementBase_instances, emitAndThrow_fn, setOptionsDataAttributes_fn, 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, _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
51
  import * as React from "react";
52
52
  import React__default from "react";
53
53
  import { jsx } from "react/jsx-runtime";
@@ -1006,6 +1006,252 @@ class ChatFrameMessenger extends BaseMessenger {
1006
1006
  return true;
1007
1007
  }
1008
1008
  }
1009
+ const PET_ANIMATION_NAMES = [
1010
+ "idle",
1011
+ "running-right",
1012
+ "running-left",
1013
+ "waving",
1014
+ "jumping",
1015
+ "failed",
1016
+ "waiting",
1017
+ "running",
1018
+ "review"
1019
+ ];
1020
+ const petSpriteAtlas = {
1021
+ columns: 8,
1022
+ rows: 9,
1023
+ cellWidth: 192,
1024
+ cellHeight: 208,
1025
+ animations: {
1026
+ idle: {
1027
+ row: 0,
1028
+ frames: 6,
1029
+ frameDurations: [280, 110, 110, 140, 140, 320]
1030
+ },
1031
+ "running-right": {
1032
+ row: 1,
1033
+ frames: 8,
1034
+ frameDurations: [120, 120, 120, 120, 120, 120, 120, 220]
1035
+ },
1036
+ "running-left": {
1037
+ row: 2,
1038
+ frames: 8,
1039
+ frameDurations: [120, 120, 120, 120, 120, 120, 120, 220]
1040
+ },
1041
+ waving: {
1042
+ row: 3,
1043
+ frames: 4,
1044
+ frameDurations: [140, 140, 140, 280]
1045
+ },
1046
+ jumping: {
1047
+ row: 4,
1048
+ frames: 5,
1049
+ frameDurations: [140, 140, 140, 140, 280]
1050
+ },
1051
+ failed: {
1052
+ row: 5,
1053
+ frames: 8,
1054
+ frameDurations: [140, 140, 140, 140, 140, 140, 140, 240]
1055
+ },
1056
+ waiting: {
1057
+ row: 6,
1058
+ frames: 6,
1059
+ frameDurations: [150, 150, 150, 150, 150, 260]
1060
+ },
1061
+ running: {
1062
+ row: 7,
1063
+ frames: 6,
1064
+ frameDurations: [120, 120, 120, 120, 120, 220]
1065
+ },
1066
+ review: {
1067
+ row: 8,
1068
+ frames: 6,
1069
+ frameDurations: [150, 150, 150, 150, 150, 280]
1070
+ }
1071
+ }
1072
+ };
1073
+ const DEFAULT_PET_BOUNDS_PADDING = {
1074
+ top: 0,
1075
+ right: 0,
1076
+ bottom: 0,
1077
+ left: 0
1078
+ };
1079
+ const DEFAULT_PET_STORAGE_KEY = "chatkit:pet:position:v1";
1080
+ const DEFAULT_PET_SPRITESHEET_URL = "/pets/boba/spritesheet.webp";
1081
+ const DEFAULT_PET_CHARACTER = {
1082
+ type: "sprite-atlas",
1083
+ src: DEFAULT_PET_SPRITESHEET_URL
1084
+ };
1085
+ const DEFAULT_POSITION = {
1086
+ pin: "bottom-right",
1087
+ draggable: true,
1088
+ scale: 0.25,
1089
+ persist: true,
1090
+ zIndex: 40
1091
+ };
1092
+ function mergeFrameAnimation(base, override) {
1093
+ return {
1094
+ row: (override == null ? void 0 : override.row) ?? base.row,
1095
+ frames: (override == null ? void 0 : override.frames) ?? base.frames,
1096
+ frameDurations: (override == null ? void 0 : override.frameDurations) && override.frameDurations.length > 0 ? override.frameDurations : base.frameDurations
1097
+ };
1098
+ }
1099
+ function mergePetSpriteAtlas(override) {
1100
+ var _a2;
1101
+ const animations = {};
1102
+ for (const name of PET_ANIMATION_NAMES) {
1103
+ animations[name] = mergeFrameAnimation(
1104
+ petSpriteAtlas.animations[name],
1105
+ (_a2 = override == null ? void 0 : override.animations) == null ? void 0 : _a2[name]
1106
+ );
1107
+ }
1108
+ return {
1109
+ columns: (override == null ? void 0 : override.columns) ?? petSpriteAtlas.columns,
1110
+ rows: (override == null ? void 0 : override.rows) ?? petSpriteAtlas.rows,
1111
+ cellWidth: (override == null ? void 0 : override.cellWidth) ?? petSpriteAtlas.cellWidth,
1112
+ cellHeight: (override == null ? void 0 : override.cellHeight) ?? petSpriteAtlas.cellHeight,
1113
+ animations
1114
+ };
1115
+ }
1116
+ function normalizeCharacter(character) {
1117
+ if (!character) {
1118
+ return DEFAULT_PET_CHARACTER;
1119
+ }
1120
+ if (character.src) {
1121
+ return character;
1122
+ }
1123
+ return DEFAULT_PET_CHARACTER;
1124
+ }
1125
+ function normalizePetOptions(pet) {
1126
+ if (!pet) {
1127
+ return null;
1128
+ }
1129
+ if (pet === true) {
1130
+ return {
1131
+ character: DEFAULT_PET_CHARACTER,
1132
+ position: DEFAULT_POSITION,
1133
+ behavior: "auto",
1134
+ ariaLabel: "Animated pet",
1135
+ imageRendering: "auto"
1136
+ };
1137
+ }
1138
+ if (pet.enabled === false) {
1139
+ return null;
1140
+ }
1141
+ return {
1142
+ character: normalizeCharacter(pet.character),
1143
+ position: {
1144
+ ...DEFAULT_POSITION,
1145
+ ...pet.position
1146
+ },
1147
+ behavior: pet.behavior ?? "auto",
1148
+ ariaLabel: pet.ariaLabel ?? "Animated pet",
1149
+ imageRendering: pet.imageRendering ?? "auto"
1150
+ };
1151
+ }
1152
+ function resolvePetCharacter(character) {
1153
+ if (!character.src) {
1154
+ return null;
1155
+ }
1156
+ return {
1157
+ kind: "atlas",
1158
+ src: character.src,
1159
+ atlas: mergePetSpriteAtlas(character.atlas)
1160
+ };
1161
+ }
1162
+ function normalizeBoundsPadding(value) {
1163
+ if (typeof value === "number") {
1164
+ return {
1165
+ top: value,
1166
+ right: value,
1167
+ bottom: value,
1168
+ left: value
1169
+ };
1170
+ }
1171
+ return {
1172
+ top: (value == null ? void 0 : value.top) ?? DEFAULT_PET_BOUNDS_PADDING.top,
1173
+ right: (value == null ? void 0 : value.right) ?? DEFAULT_PET_BOUNDS_PADDING.right,
1174
+ bottom: (value == null ? void 0 : value.bottom) ?? DEFAULT_PET_BOUNDS_PADDING.bottom,
1175
+ left: (value == null ? void 0 : value.left) ?? DEFAULT_PET_BOUNDS_PADDING.left
1176
+ };
1177
+ }
1178
+ function clampPetPosition(position, size, viewport, padding) {
1179
+ const minX = padding.left;
1180
+ const minY = padding.top;
1181
+ const maxX = Math.max(minX, viewport.width - size.width - padding.right);
1182
+ const maxY = Math.max(minY, viewport.height - size.height - padding.bottom);
1183
+ return {
1184
+ x: Math.min(maxX, Math.max(minX, position.x)),
1185
+ y: Math.min(maxY, Math.max(minY, position.y))
1186
+ };
1187
+ }
1188
+ function getPinnedPetPosition(pin, size, viewport, padding) {
1189
+ const horizontalCenter = (viewport.width - size.width) / 2;
1190
+ const verticalCenter = (viewport.height - size.height) / 2;
1191
+ const right = viewport.width - size.width - padding.right;
1192
+ const bottom = viewport.height - size.height - padding.bottom;
1193
+ switch (pin) {
1194
+ case "top-left":
1195
+ return clampPetPosition(
1196
+ { x: padding.left, y: padding.top },
1197
+ size,
1198
+ viewport,
1199
+ padding
1200
+ );
1201
+ case "top":
1202
+ return clampPetPosition(
1203
+ { x: horizontalCenter, y: padding.top },
1204
+ size,
1205
+ viewport,
1206
+ padding
1207
+ );
1208
+ case "top-right":
1209
+ return clampPetPosition(
1210
+ { x: right, y: padding.top },
1211
+ size,
1212
+ viewport,
1213
+ padding
1214
+ );
1215
+ case "left":
1216
+ return clampPetPosition(
1217
+ { x: padding.left, y: verticalCenter },
1218
+ size,
1219
+ viewport,
1220
+ padding
1221
+ );
1222
+ case "center":
1223
+ return clampPetPosition(
1224
+ { x: horizontalCenter, y: verticalCenter },
1225
+ size,
1226
+ viewport,
1227
+ padding
1228
+ );
1229
+ case "right":
1230
+ return clampPetPosition(
1231
+ { x: right, y: verticalCenter },
1232
+ size,
1233
+ viewport,
1234
+ padding
1235
+ );
1236
+ case "bottom-left":
1237
+ return clampPetPosition(
1238
+ { x: padding.left, y: bottom },
1239
+ size,
1240
+ viewport,
1241
+ padding
1242
+ );
1243
+ case "bottom":
1244
+ return clampPetPosition(
1245
+ { x: horizontalCenter, y: bottom },
1246
+ size,
1247
+ viewport,
1248
+ padding
1249
+ );
1250
+ case "bottom-right":
1251
+ default:
1252
+ return clampPetPosition({ x: right, y: bottom }, size, viewport, padding);
1253
+ }
1254
+ }
1009
1255
  const removeMethods = (obj, seen = /* @__PURE__ */ new WeakSet()) => {
1010
1256
  if (typeof obj === "function") return "[ChatKitMethod]";
1011
1257
  if (typeof obj !== "object" || obj === null) return obj;
@@ -1024,6 +1270,1191 @@ const removeMethods = (obj, seen = /* @__PURE__ */ new WeakSet()) => {
1024
1270
  }
1025
1271
  return result;
1026
1272
  };
1273
+ const DRAG_DIRECTION_THRESHOLD_PX = 2;
1274
+ const PET_BASE_RENDER_SCALE = 0.5;
1275
+ const PET_FRAME_DURATION_MULTIPLIER = 1.5;
1276
+ const PET_RESTING_FRAME_DURATION_MULTIPLIER = 3;
1277
+ const PET_RESTING_DELAY_MS = 2e3;
1278
+ const PET_SUMMARY_GAP = 12;
1279
+ const PET_SUMMARY_WIDTH = 320;
1280
+ const PET_SUMMARY_MARGIN = 12;
1281
+ const PET_OVERLAY_COPY = {
1282
+ "en-US": {
1283
+ hideMessage: "Hide message",
1284
+ expandMessage: "Expand message",
1285
+ collapseMessage: "Collapse message",
1286
+ restoreMessage: "Show message",
1287
+ replyButton: "Reply",
1288
+ replyPlaceholder: "Reply...",
1289
+ sendButton: "Send",
1290
+ sendingButton: "Sending...",
1291
+ sendFailed: "Failed to send"
1292
+ },
1293
+ "zh-CN": {
1294
+ hideMessage: "隐藏消息",
1295
+ expandMessage: "展开消息",
1296
+ collapseMessage: "收起消息",
1297
+ restoreMessage: "显示消息",
1298
+ replyButton: "回复",
1299
+ replyPlaceholder: "输入回复...",
1300
+ sendButton: "发送",
1301
+ sendingButton: "发送中...",
1302
+ sendFailed: "发送失败"
1303
+ }
1304
+ };
1305
+ function stopEventPropagation(event) {
1306
+ event.stopPropagation();
1307
+ }
1308
+ function getViewportSize() {
1309
+ const visualViewport = window.visualViewport;
1310
+ return {
1311
+ width: (visualViewport == null ? void 0 : visualViewport.width) || window.innerWidth || 320,
1312
+ height: (visualViewport == null ? void 0 : visualViewport.height) || window.innerHeight || 480
1313
+ };
1314
+ }
1315
+ function readPersistedPosition(storageKey, persist) {
1316
+ if (!persist) {
1317
+ return null;
1318
+ }
1319
+ try {
1320
+ const raw = window.localStorage.getItem(storageKey);
1321
+ if (!raw) {
1322
+ return null;
1323
+ }
1324
+ const parsed = JSON.parse(raw);
1325
+ if (!parsed || typeof parsed !== "object" || typeof parsed.x !== "number" || typeof parsed.y !== "number") {
1326
+ return null;
1327
+ }
1328
+ return { x: parsed.x, y: parsed.y };
1329
+ } catch {
1330
+ return null;
1331
+ }
1332
+ }
1333
+ function writePersistedPosition(storageKey, persist, position) {
1334
+ if (!persist) {
1335
+ return;
1336
+ }
1337
+ try {
1338
+ window.localStorage.setItem(storageKey, JSON.stringify(position));
1339
+ } catch {
1340
+ }
1341
+ }
1342
+ function escapeCssUrl(value) {
1343
+ return value.replace(/["\\]/g, "\\$&");
1344
+ }
1345
+ function getRenderScale(scale) {
1346
+ return Math.max(0.1, scale) * PET_BASE_RENDER_SCALE;
1347
+ }
1348
+ function clampNumber(value, min, max) {
1349
+ return Math.min(max, Math.max(min, value));
1350
+ }
1351
+ function getDefaultLocale() {
1352
+ if (typeof window !== "undefined") {
1353
+ try {
1354
+ const stored = window.localStorage.getItem("chatkit:locale");
1355
+ if (stored) {
1356
+ return stored;
1357
+ }
1358
+ } catch {
1359
+ }
1360
+ }
1361
+ return typeof navigator !== "undefined" ? navigator.language : null;
1362
+ }
1363
+ function resolveCopyLocale(locale) {
1364
+ const normalized = (locale ?? getDefaultLocale() ?? "").trim().toLowerCase();
1365
+ if (normalized === "zh-cn" || normalized === "zh-hans" || normalized.startsWith("zh")) {
1366
+ return "zh-CN";
1367
+ }
1368
+ return "en-US";
1369
+ }
1370
+ function isPetState(value) {
1371
+ return value === "idle" || value === "running-right" || value === "running-left" || value === "waving" || value === "jumping" || value === "failed" || value === "waiting" || value === "running" || value === "review";
1372
+ }
1373
+ function parsePetStateChangePayload(value) {
1374
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1375
+ return null;
1376
+ }
1377
+ const payload = value;
1378
+ return isPetState(payload.state) ? { state: payload.state } : null;
1379
+ }
1380
+ function parsePetOptionsChangePayload(value) {
1381
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1382
+ return null;
1383
+ }
1384
+ const payload = value;
1385
+ if (payload.pet === null || typeof payload.pet === "boolean") {
1386
+ return { pet: payload.pet };
1387
+ }
1388
+ if (payload.pet && typeof payload.pet === "object" && !Array.isArray(payload.pet)) {
1389
+ return { pet: payload.pet };
1390
+ }
1391
+ return null;
1392
+ }
1393
+ function isThreadSummaryStatus(value) {
1394
+ return value === "running" || value === "completed" || value === "failed";
1395
+ }
1396
+ function getThreadSummaryKey(summary) {
1397
+ if (!summary) {
1398
+ return null;
1399
+ }
1400
+ return [
1401
+ summary.threadId,
1402
+ summary.messageId || summary.updatedAt || summary.message
1403
+ ].join(":");
1404
+ }
1405
+ function parseThreadSummaryPayload(value) {
1406
+ if (value === null) {
1407
+ return { summary: null };
1408
+ }
1409
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1410
+ return null;
1411
+ }
1412
+ const payload = value;
1413
+ if (typeof payload.threadId !== "string" || !payload.threadId.trim() || typeof payload.title !== "string" || !payload.title.trim() || typeof payload.message !== "string" || !payload.message.trim() || !isThreadSummaryStatus(payload.status)) {
1414
+ return null;
1415
+ }
1416
+ return {
1417
+ summary: {
1418
+ threadId: payload.threadId,
1419
+ title: payload.title,
1420
+ message: payload.message,
1421
+ status: payload.status,
1422
+ ...typeof payload.messageId === "string" && payload.messageId.trim() ? { messageId: payload.messageId } : {},
1423
+ ...typeof payload.updatedAt === "string" && payload.updatedAt.trim() ? { updatedAt: payload.updatedAt } : {}
1424
+ }
1425
+ };
1426
+ }
1427
+ function parseThreadSummaryLogPayload(value) {
1428
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1429
+ return null;
1430
+ }
1431
+ const payload = value;
1432
+ if (payload.name !== "thread.summary") {
1433
+ return null;
1434
+ }
1435
+ return parseThreadSummaryPayload(payload.data ?? null);
1436
+ }
1437
+ class PetOverlay {
1438
+ constructor(root, options) {
1439
+ this.overlayElement = null;
1440
+ this.petElement = null;
1441
+ this.summaryElement = null;
1442
+ this.summaryToggleElement = null;
1443
+ this.mediaElement = null;
1444
+ this.options = null;
1445
+ this.resolved = null;
1446
+ this.summary = null;
1447
+ this.summaryRenderKey = null;
1448
+ this.dismissedSummaryKey = null;
1449
+ this.isSummaryCollapsed = false;
1450
+ this.isSummaryExpanded = false;
1451
+ this.isSummaryHovering = false;
1452
+ this.isReplyOpen = false;
1453
+ this.isReplySubmitting = false;
1454
+ this.replyError = null;
1455
+ this.replyDraft = "";
1456
+ this.replyInputElement = null;
1457
+ this.copyLocale = resolveCopyLocale();
1458
+ this.copy = PET_OVERLAY_COPY[this.copyLocale];
1459
+ this.currentState = "waiting";
1460
+ this.lastAutoState = "waiting";
1461
+ this.transient = null;
1462
+ this.position = null;
1463
+ this.dragPosition = null;
1464
+ this.dragOffset = { x: 0, y: 0 };
1465
+ this.lastDragPosition = null;
1466
+ this.lastDragClientX = null;
1467
+ this.dragAnimation = null;
1468
+ this.isDragging = false;
1469
+ this.isHovering = false;
1470
+ this.movedDuringDrag = false;
1471
+ this.prefersReducedMotion = false;
1472
+ this.frame = 0;
1473
+ this.completed = false;
1474
+ this.activeAnimationName = null;
1475
+ this.activeAnimationMode = null;
1476
+ this.frameTimer = null;
1477
+ this.restingDelayTimer = null;
1478
+ this.mediaQuery = null;
1479
+ this.connected = false;
1480
+ this.handleViewportChange = () => {
1481
+ this.render();
1482
+ };
1483
+ this.handleReducedMotionChange = () => {
1484
+ var _a2;
1485
+ this.prefersReducedMotion = Boolean((_a2 = this.mediaQuery) == null ? void 0 : _a2.matches);
1486
+ if (this.prefersReducedMotion) {
1487
+ this.transient = null;
1488
+ }
1489
+ this.render();
1490
+ };
1491
+ this.handlePointerEnter = () => {
1492
+ this.clearRestingDelayTimer();
1493
+ this.isHovering = true;
1494
+ this.rescheduleAnimation();
1495
+ };
1496
+ this.handlePointerLeave = () => {
1497
+ if (!this.isDragging) {
1498
+ this.enterRestingAfterDelay();
1499
+ }
1500
+ };
1501
+ this.handleSummaryPointerEnter = () => {
1502
+ this.isSummaryHovering = true;
1503
+ this.render();
1504
+ };
1505
+ this.handleSummaryPointerLeave = () => {
1506
+ this.isSummaryHovering = false;
1507
+ if (!this.isReplyOpen) {
1508
+ this.render();
1509
+ }
1510
+ };
1511
+ this.handleSummaryClick = () => {
1512
+ var _a2, _b2;
1513
+ const threadId = (_a2 = this.summary) == null ? void 0 : _a2.threadId.trim();
1514
+ if (!threadId) {
1515
+ return;
1516
+ }
1517
+ (_b2 = this.onThreadSummaryActivate) == null ? void 0 : _b2.call(this, threadId);
1518
+ };
1519
+ this.handleSummaryDelete = () => {
1520
+ const summaryKey = getThreadSummaryKey(this.summary);
1521
+ if (summaryKey) {
1522
+ this.dismissedSummaryKey = summaryKey;
1523
+ }
1524
+ this.isSummaryCollapsed = false;
1525
+ this.isReplyOpen = false;
1526
+ this.replyDraft = "";
1527
+ this.replyError = null;
1528
+ this.removeSummaryElements();
1529
+ };
1530
+ this.handleSummaryCollapseToggle = () => {
1531
+ this.isSummaryCollapsed = !this.isSummaryCollapsed;
1532
+ this.isSummaryExpanded = false;
1533
+ this.isReplyOpen = false;
1534
+ this.replyError = null;
1535
+ this.render();
1536
+ };
1537
+ this.handleSummaryExpandToggle = () => {
1538
+ this.isSummaryExpanded = !this.isSummaryExpanded;
1539
+ this.render();
1540
+ };
1541
+ this.handleReplyOpen = () => {
1542
+ this.isReplyOpen = true;
1543
+ this.replyError = null;
1544
+ this.render();
1545
+ };
1546
+ this.handleReplyInput = (event) => {
1547
+ const target = event.currentTarget;
1548
+ if (target instanceof HTMLInputElement) {
1549
+ this.replyDraft = target.value;
1550
+ this.replyError = null;
1551
+ }
1552
+ };
1553
+ this.handleReplySubmit = (event) => {
1554
+ event.preventDefault();
1555
+ void this.submitReply();
1556
+ };
1557
+ this.handleReplyKeyDown = (event) => {
1558
+ if (event.key !== "Escape") {
1559
+ return;
1560
+ }
1561
+ event.preventDefault();
1562
+ this.isReplyOpen = false;
1563
+ this.replyError = null;
1564
+ this.render();
1565
+ };
1566
+ this.handlePointerDown = (event) => {
1567
+ var _a2, _b2;
1568
+ if (!((_a2 = this.options) == null ? void 0 : _a2.position.draggable) || event.button !== 0) {
1569
+ return;
1570
+ }
1571
+ event.preventDefault();
1572
+ const rect = (_b2 = this.petElement) == null ? void 0 : _b2.getBoundingClientRect();
1573
+ if (!rect) {
1574
+ return;
1575
+ }
1576
+ const nextPosition = {
1577
+ x: rect.left,
1578
+ y: rect.top
1579
+ };
1580
+ this.dragOffset = {
1581
+ x: event.clientX - rect.left,
1582
+ y: event.clientY - rect.top
1583
+ };
1584
+ this.lastDragPosition = nextPosition;
1585
+ this.lastDragClientX = event.clientX;
1586
+ this.dragAnimation = null;
1587
+ this.movedDuringDrag = false;
1588
+ this.dragPosition = nextPosition;
1589
+ this.isDragging = true;
1590
+ this.clearRestingDelayTimer();
1591
+ this.isHovering = true;
1592
+ this.installDragListeners();
1593
+ this.rescheduleAnimation();
1594
+ };
1595
+ this.handlePointerMove = (event) => {
1596
+ const nextPosition = this.getNextDragPosition(event);
1597
+ const last = this.lastDragPosition;
1598
+ if (last && (Math.abs(last.x - nextPosition.x) > DRAG_DIRECTION_THRESHOLD_PX || Math.abs(last.y - nextPosition.y) > DRAG_DIRECTION_THRESHOLD_PX)) {
1599
+ this.movedDuringDrag = true;
1600
+ }
1601
+ if (this.lastDragClientX !== null) {
1602
+ const deltaX = event.clientX - this.lastDragClientX;
1603
+ if (deltaX > DRAG_DIRECTION_THRESHOLD_PX) {
1604
+ this.dragAnimation = "running-right";
1605
+ } else if (deltaX < -DRAG_DIRECTION_THRESHOLD_PX) {
1606
+ this.dragAnimation = "running-left";
1607
+ }
1608
+ }
1609
+ this.lastDragClientX = event.clientX;
1610
+ this.lastDragPosition = nextPosition;
1611
+ this.dragPosition = nextPosition;
1612
+ this.render();
1613
+ };
1614
+ this.handlePointerUp = (event) => {
1615
+ const finalPosition = this.lastDragPosition ?? this.getNextDragPosition(event);
1616
+ this.isDragging = false;
1617
+ this.dragPosition = null;
1618
+ this.dragAnimation = null;
1619
+ this.lastDragClientX = null;
1620
+ this.removeDragListeners();
1621
+ this.persistPosition(finalPosition);
1622
+ if (event.pointerType === "mouse" && this.isPointerOverPet(event)) {
1623
+ this.isHovering = true;
1624
+ this.rescheduleAnimation();
1625
+ } else {
1626
+ this.enterRestingAfterDelay();
1627
+ this.rescheduleAnimation();
1628
+ }
1629
+ };
1630
+ this.handleClick = () => {
1631
+ var _a2;
1632
+ if (this.movedDuringDrag) {
1633
+ return;
1634
+ }
1635
+ (_a2 = this.onActivate) == null ? void 0 : _a2.call(this);
1636
+ if (this.prefersReducedMotion) {
1637
+ return;
1638
+ }
1639
+ this.transient = { name: "waving" };
1640
+ this.render();
1641
+ };
1642
+ this.root = root;
1643
+ this.onActivate = options == null ? void 0 : options.onActivate;
1644
+ this.onReply = options == null ? void 0 : options.onReply;
1645
+ this.onThreadSummaryActivate = options == null ? void 0 : options.onThreadSummaryActivate;
1646
+ this.connect();
1647
+ }
1648
+ connect() {
1649
+ if (this.connected) {
1650
+ return;
1651
+ }
1652
+ this.connected = true;
1653
+ this.installViewportListeners();
1654
+ this.installReducedMotionListener();
1655
+ this.render();
1656
+ }
1657
+ setOptions(pet) {
1658
+ const nextOptions = normalizePetOptions(pet);
1659
+ this.options = nextOptions;
1660
+ if (!nextOptions) {
1661
+ this.isDragging = false;
1662
+ this.isHovering = false;
1663
+ this.position = null;
1664
+ this.dragPosition = null;
1665
+ this.dragAnimation = null;
1666
+ this.lastDragPosition = null;
1667
+ this.lastDragClientX = null;
1668
+ this.transient = null;
1669
+ this.resolved = null;
1670
+ this.clearRestingDelayTimer();
1671
+ this.removeDragListeners();
1672
+ this.removeOverlay();
1673
+ return;
1674
+ }
1675
+ this.position = readPersistedPosition(
1676
+ DEFAULT_PET_STORAGE_KEY,
1677
+ nextOptions.position.persist
1678
+ );
1679
+ if (nextOptions.behavior === "auto" && !this.prefersReducedMotion) {
1680
+ this.transient = { name: "waving" };
1681
+ }
1682
+ this.resolveCharacter();
1683
+ this.render();
1684
+ }
1685
+ setState(state) {
1686
+ var _a2;
1687
+ const previous = this.lastAutoState;
1688
+ this.lastAutoState = state;
1689
+ this.currentState = state;
1690
+ if (((_a2 = this.options) == null ? void 0 : _a2.behavior) === "auto" && !this.prefersReducedMotion && state === "idle" && (previous === "running" || previous === "review") && !this.transient) {
1691
+ this.transient = { name: "jumping" };
1692
+ } else if (state !== "idle") {
1693
+ this.transient = null;
1694
+ }
1695
+ this.render();
1696
+ }
1697
+ setLocale(locale) {
1698
+ const nextLocale = resolveCopyLocale(locale);
1699
+ if (nextLocale === this.copyLocale) {
1700
+ return;
1701
+ }
1702
+ this.copyLocale = nextLocale;
1703
+ this.copy = PET_OVERLAY_COPY[nextLocale];
1704
+ this.summaryRenderKey = null;
1705
+ this.render();
1706
+ }
1707
+ setThreadSummary(summary) {
1708
+ const previousKey = getThreadSummaryKey(this.summary);
1709
+ const nextKey = getThreadSummaryKey(summary);
1710
+ this.summary = summary;
1711
+ if (!summary) {
1712
+ this.isSummaryCollapsed = false;
1713
+ this.isSummaryExpanded = false;
1714
+ this.isSummaryHovering = false;
1715
+ this.isReplyOpen = false;
1716
+ this.isReplySubmitting = false;
1717
+ this.replyError = null;
1718
+ this.replyDraft = "";
1719
+ this.summaryRenderKey = null;
1720
+ this.removeSummaryElements();
1721
+ return;
1722
+ }
1723
+ if (previousKey !== nextKey) {
1724
+ this.isSummaryCollapsed = false;
1725
+ this.isSummaryExpanded = false;
1726
+ this.isSummaryHovering = false;
1727
+ this.isReplyOpen = false;
1728
+ this.isReplySubmitting = false;
1729
+ this.replyError = null;
1730
+ this.replyDraft = "";
1731
+ }
1732
+ this.render();
1733
+ }
1734
+ setThreadSummaryStatus(status) {
1735
+ if (!this.summary || this.summary.status === status) {
1736
+ return;
1737
+ }
1738
+ this.summary = { ...this.summary, status };
1739
+ this.render();
1740
+ }
1741
+ destroy() {
1742
+ var _a2, _b2, _c2, _d;
1743
+ if (!this.connected) {
1744
+ return;
1745
+ }
1746
+ this.connected = false;
1747
+ this.clearRestingDelayTimer();
1748
+ this.clearTimers();
1749
+ this.removeDragListeners();
1750
+ this.removeOverlay();
1751
+ window.removeEventListener("resize", this.handleViewportChange);
1752
+ (_a2 = window.visualViewport) == null ? void 0 : _a2.removeEventListener(
1753
+ "resize",
1754
+ this.handleViewportChange
1755
+ );
1756
+ (_b2 = window.visualViewport) == null ? void 0 : _b2.removeEventListener(
1757
+ "scroll",
1758
+ this.handleViewportChange
1759
+ );
1760
+ (_d = (_c2 = this.mediaQuery) == null ? void 0 : _c2.removeEventListener) == null ? void 0 : _d.call(
1761
+ _c2,
1762
+ "change",
1763
+ this.handleReducedMotionChange
1764
+ );
1765
+ this.mediaQuery = null;
1766
+ }
1767
+ installViewportListeners() {
1768
+ var _a2, _b2;
1769
+ window.addEventListener("resize", this.handleViewportChange);
1770
+ (_a2 = window.visualViewport) == null ? void 0 : _a2.addEventListener("resize", this.handleViewportChange);
1771
+ (_b2 = window.visualViewport) == null ? void 0 : _b2.addEventListener("scroll", this.handleViewportChange);
1772
+ }
1773
+ installReducedMotionListener() {
1774
+ var _a2, _b2;
1775
+ if (!window.matchMedia) {
1776
+ return;
1777
+ }
1778
+ this.mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
1779
+ this.prefersReducedMotion = this.mediaQuery.matches;
1780
+ (_b2 = (_a2 = this.mediaQuery).addEventListener) == null ? void 0 : _b2.call(
1781
+ _a2,
1782
+ "change",
1783
+ this.handleReducedMotionChange
1784
+ );
1785
+ }
1786
+ resolveCharacter() {
1787
+ if (!this.options) {
1788
+ this.resolved = null;
1789
+ return;
1790
+ }
1791
+ const character = this.options.character;
1792
+ this.resolved = resolvePetCharacter(character);
1793
+ }
1794
+ ensureOverlay() {
1795
+ if (this.overlayElement && this.petElement) {
1796
+ return;
1797
+ }
1798
+ const overlay = document.createElement("div");
1799
+ overlay.setAttribute("data-chatkit-host-pet-layer", "");
1800
+ overlay.style.position = "fixed";
1801
+ overlay.style.inset = "0";
1802
+ overlay.style.pointerEvents = "none";
1803
+ overlay.style.overflow = "visible";
1804
+ const style = document.createElement("style");
1805
+ style.textContent = `
1806
+ @keyframes chatkit-pet-summary-spin {
1807
+ to { transform: rotate(360deg); }
1808
+ }
1809
+ `;
1810
+ const pet = document.createElement("div");
1811
+ pet.setAttribute("data-chatkit-host-pet", "");
1812
+ pet.style.position = "absolute";
1813
+ pet.style.top = "0";
1814
+ pet.style.left = "0";
1815
+ pet.style.pointerEvents = "auto";
1816
+ pet.style.touchAction = "none";
1817
+ pet.style.userSelect = "none";
1818
+ pet.style.willChange = "transform";
1819
+ pet.addEventListener("pointerenter", this.handlePointerEnter);
1820
+ pet.addEventListener("pointerleave", this.handlePointerLeave);
1821
+ pet.addEventListener("pointerdown", this.handlePointerDown);
1822
+ pet.addEventListener("click", this.handleClick);
1823
+ overlay.append(style, pet);
1824
+ this.root.append(overlay);
1825
+ this.overlayElement = overlay;
1826
+ this.petElement = pet;
1827
+ }
1828
+ removeOverlay() {
1829
+ var _a2;
1830
+ this.clearRestingDelayTimer();
1831
+ this.clearTimers();
1832
+ if (this.petElement) {
1833
+ this.petElement.removeEventListener(
1834
+ "pointerenter",
1835
+ this.handlePointerEnter
1836
+ );
1837
+ this.petElement.removeEventListener(
1838
+ "pointerleave",
1839
+ this.handlePointerLeave
1840
+ );
1841
+ this.petElement.removeEventListener("pointerdown", this.handlePointerDown);
1842
+ this.petElement.removeEventListener("click", this.handleClick);
1843
+ }
1844
+ this.isHovering = false;
1845
+ this.removeSummaryElements();
1846
+ (_a2 = this.overlayElement) == null ? void 0 : _a2.remove();
1847
+ this.overlayElement = null;
1848
+ this.petElement = null;
1849
+ this.mediaElement = null;
1850
+ }
1851
+ removeSummaryElements() {
1852
+ var _a2, _b2;
1853
+ (_a2 = this.summaryElement) == null ? void 0 : _a2.remove();
1854
+ (_b2 = this.summaryToggleElement) == null ? void 0 : _b2.remove();
1855
+ this.summaryElement = null;
1856
+ this.summaryToggleElement = null;
1857
+ this.replyInputElement = null;
1858
+ this.summaryRenderKey = null;
1859
+ }
1860
+ getSize() {
1861
+ if (!this.options || !this.resolved) {
1862
+ return { width: 0, height: 0 };
1863
+ }
1864
+ const scale = getRenderScale(this.options.position.scale);
1865
+ const baseSize = {
1866
+ width: this.resolved.atlas.cellWidth,
1867
+ height: this.resolved.atlas.cellHeight
1868
+ };
1869
+ return {
1870
+ width: baseSize.width * scale,
1871
+ height: baseSize.height * scale
1872
+ };
1873
+ }
1874
+ getCurrentPosition(size) {
1875
+ const options = this.options;
1876
+ if (!options) {
1877
+ return { x: 0, y: 0 };
1878
+ }
1879
+ const viewport = getViewportSize();
1880
+ const padding = normalizeBoundsPadding(options.position.boundsPadding);
1881
+ const pin = options.position.pin === void 0 ? "bottom-right" : options.position.pin;
1882
+ const pinnedPosition = pin ? getPinnedPetPosition(pin, size, viewport, padding) : null;
1883
+ return clampPetPosition(
1884
+ this.dragPosition ?? this.position ?? pinnedPosition ?? { x: padding.left, y: padding.top },
1885
+ size,
1886
+ viewport,
1887
+ padding
1888
+ );
1889
+ }
1890
+ persistPosition(nextPosition) {
1891
+ if (!this.options) {
1892
+ return;
1893
+ }
1894
+ const size = this.getSize();
1895
+ const clamped = clampPetPosition(
1896
+ nextPosition,
1897
+ size,
1898
+ getViewportSize(),
1899
+ normalizeBoundsPadding(this.options.position.boundsPadding)
1900
+ );
1901
+ this.position = clamped;
1902
+ writePersistedPosition(
1903
+ DEFAULT_PET_STORAGE_KEY,
1904
+ this.options.position.persist,
1905
+ clamped
1906
+ );
1907
+ }
1908
+ getActiveAnimationName() {
1909
+ if (!this.options) {
1910
+ return "idle";
1911
+ }
1912
+ if (this.isDragging) {
1913
+ return this.dragAnimation ?? "running";
1914
+ }
1915
+ if (this.transient) {
1916
+ return this.transient.name;
1917
+ }
1918
+ if (this.options.behavior === "manual") {
1919
+ return "idle";
1920
+ }
1921
+ return this.currentState;
1922
+ }
1923
+ getActiveAnimationMode() {
1924
+ if (this.isDragging) {
1925
+ return "loop";
1926
+ }
1927
+ return this.transient ? "once" : "loop";
1928
+ }
1929
+ resetAnimationIfNeeded(name, mode) {
1930
+ if (this.activeAnimationName === name && this.activeAnimationMode === mode) {
1931
+ return;
1932
+ }
1933
+ this.clearTimers();
1934
+ this.activeAnimationName = name;
1935
+ this.activeAnimationMode = mode;
1936
+ this.frame = 0;
1937
+ this.completed = false;
1938
+ }
1939
+ render() {
1940
+ if (!this.options || !this.resolved) {
1941
+ this.clearTimers();
1942
+ if (this.petElement) {
1943
+ this.petElement.replaceChildren();
1944
+ }
1945
+ this.removeSummaryElements();
1946
+ this.mediaElement = null;
1947
+ this.activeAnimationName = null;
1948
+ this.activeAnimationMode = null;
1949
+ this.frame = 0;
1950
+ this.completed = false;
1951
+ return;
1952
+ }
1953
+ this.ensureOverlay();
1954
+ const overlay = this.overlayElement;
1955
+ const pet = this.petElement;
1956
+ if (!overlay || !pet) {
1957
+ return;
1958
+ }
1959
+ const size = this.getSize();
1960
+ const position = this.getCurrentPosition(size);
1961
+ const animationName = this.getActiveAnimationName();
1962
+ const animationMode = this.getActiveAnimationMode();
1963
+ this.resetAnimationIfNeeded(animationName, animationMode);
1964
+ overlay.style.zIndex = String(this.options.position.zIndex);
1965
+ pet.style.width = `${size.width}px`;
1966
+ pet.style.height = `${size.height}px`;
1967
+ pet.style.transform = `translate3d(${position.x}px, ${position.y}px, 0)`;
1968
+ pet.style.cursor = this.options.position.draggable ? this.isDragging ? "grabbing" : "grab" : "default";
1969
+ pet.dataset.petAnimation = animationName;
1970
+ pet.setAttribute("aria-label", this.options.ariaLabel);
1971
+ pet.setAttribute("role", "img");
1972
+ this.renderAtlas(animationName, animationMode);
1973
+ this.renderThreadSummary(position, size);
1974
+ this.scheduleNextFrame(animationName, animationMode);
1975
+ }
1976
+ renderThreadSummary(position, size) {
1977
+ var _a2, _b2, _c2;
1978
+ const summary = this.summary;
1979
+ const summaryKey = getThreadSummaryKey(summary);
1980
+ if (!summary || !summaryKey || this.dismissedSummaryKey === summaryKey) {
1981
+ this.removeSummaryElements();
1982
+ return;
1983
+ }
1984
+ if (this.isSummaryCollapsed) {
1985
+ this.renderCollapsedSummary(position, size);
1986
+ return;
1987
+ }
1988
+ const nextRenderKey = [
1989
+ summaryKey,
1990
+ summary.title,
1991
+ summary.message,
1992
+ summary.status,
1993
+ this.copyLocale,
1994
+ this.isSummaryExpanded ? "expanded" : "compact",
1995
+ this.isSummaryHovering ? "hover" : "rest",
1996
+ this.isReplyOpen ? "reply" : "closed",
1997
+ this.isReplySubmitting ? "submitting" : "ready",
1998
+ this.replyError ?? ""
1999
+ ].join("|");
2000
+ if (!this.summaryElement || this.summaryRenderKey !== nextRenderKey) {
2001
+ (_a2 = this.summaryElement) == null ? void 0 : _a2.remove();
2002
+ (_b2 = this.summaryToggleElement) == null ? void 0 : _b2.remove();
2003
+ this.summaryElement = this.createSummaryBubble(summary);
2004
+ this.summaryToggleElement = this.createSummaryToggleButton("v");
2005
+ (_c2 = this.overlayElement) == null ? void 0 : _c2.append(this.summaryElement, this.summaryToggleElement);
2006
+ this.summaryRenderKey = nextRenderKey;
2007
+ if (this.isReplyOpen && !this.isReplySubmitting) {
2008
+ window.setTimeout(() => {
2009
+ var _a3;
2010
+ return (_a3 = this.replyInputElement) == null ? void 0 : _a3.focus();
2011
+ }, 0);
2012
+ }
2013
+ }
2014
+ this.positionSummaryBubble(position, size);
2015
+ }
2016
+ renderCollapsedSummary(position, size) {
2017
+ var _a2, _b2;
2018
+ (_a2 = this.summaryElement) == null ? void 0 : _a2.remove();
2019
+ this.summaryElement = null;
2020
+ this.summaryRenderKey = null;
2021
+ if (!this.summaryToggleElement) {
2022
+ this.summaryToggleElement = this.createSummaryToggleButton("1");
2023
+ (_b2 = this.overlayElement) == null ? void 0 : _b2.append(this.summaryToggleElement);
2024
+ }
2025
+ this.summaryToggleElement.textContent = "1";
2026
+ this.positionSummaryToggleBadge(position, size);
2027
+ }
2028
+ positionSummaryToggleBadge(position, size) {
2029
+ const badge = this.summaryToggleElement;
2030
+ if (!badge) {
2031
+ return;
2032
+ }
2033
+ const viewport = getViewportSize();
2034
+ const badgeSize = 34;
2035
+ const x = clampNumber(
2036
+ position.x + size.width - badgeSize * 0.35,
2037
+ PET_SUMMARY_MARGIN,
2038
+ viewport.width - badgeSize - PET_SUMMARY_MARGIN
2039
+ );
2040
+ const y = clampNumber(
2041
+ position.y - badgeSize * 0.35,
2042
+ PET_SUMMARY_MARGIN,
2043
+ viewport.height - badgeSize - PET_SUMMARY_MARGIN
2044
+ );
2045
+ badge.style.width = `${badgeSize}px`;
2046
+ badge.style.height = `${badgeSize}px`;
2047
+ badge.style.transform = `translate3d(${x}px, ${y}px, 0)`;
2048
+ badge.style.borderRadius = "999px";
2049
+ }
2050
+ positionSummaryBubble(position, size) {
2051
+ const bubble = this.summaryElement;
2052
+ const toggle = this.summaryToggleElement;
2053
+ if (!bubble || !toggle) {
2054
+ return;
2055
+ }
2056
+ const viewport = getViewportSize();
2057
+ const width = Math.min(PET_SUMMARY_WIDTH, viewport.width - PET_SUMMARY_MARGIN * 2);
2058
+ bubble.style.width = `${width}px`;
2059
+ const bubbleHeight = bubble.offsetHeight || 96;
2060
+ const aboveY = position.y - bubbleHeight - PET_SUMMARY_GAP;
2061
+ const showAbove = aboveY >= PET_SUMMARY_MARGIN;
2062
+ const y = showAbove ? aboveY : clampNumber(
2063
+ position.y + size.height + PET_SUMMARY_GAP,
2064
+ PET_SUMMARY_MARGIN,
2065
+ viewport.height - bubbleHeight - PET_SUMMARY_MARGIN
2066
+ );
2067
+ const x = clampNumber(
2068
+ position.x + size.width / 2 - width / 2,
2069
+ PET_SUMMARY_MARGIN,
2070
+ viewport.width - width - PET_SUMMARY_MARGIN
2071
+ );
2072
+ bubble.style.transform = `translate3d(${x}px, ${y}px, 0)`;
2073
+ this.positionSummaryToggleBadge(position, size);
2074
+ }
2075
+ createSummaryBubble(summary) {
2076
+ const shouldShowReplyButton = this.isSummaryHovering && !this.isReplyOpen;
2077
+ const bubble = document.createElement("div");
2078
+ bubble.setAttribute("data-chatkit-pet-summary", "");
2079
+ bubble.addEventListener("pointerenter", this.handleSummaryPointerEnter);
2080
+ bubble.addEventListener("pointerleave", this.handleSummaryPointerLeave);
2081
+ bubble.addEventListener("click", this.handleSummaryClick);
2082
+ bubble.style.position = "absolute";
2083
+ bubble.style.top = "0";
2084
+ bubble.style.left = "0";
2085
+ bubble.style.boxSizing = "border-box";
2086
+ bubble.style.pointerEvents = "auto";
2087
+ bubble.style.padding = "12px 14px";
2088
+ bubble.style.paddingBottom = "12px";
2089
+ bubble.style.border = "1px solid rgba(148, 163, 184, 0.22)";
2090
+ bubble.style.borderRadius = "22px";
2091
+ bubble.style.background = "rgba(255, 255, 255, 0.94)";
2092
+ bubble.style.color = "#1f2937";
2093
+ bubble.style.boxShadow = "0 8px 24px rgba(15, 23, 42, 0.1)";
2094
+ bubble.style.font = '500 14px/1.35 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2095
+ bubble.style.backdropFilter = "blur(10px)";
2096
+ const header = document.createElement("div");
2097
+ header.style.display = "flex";
2098
+ header.style.alignItems = "center";
2099
+ header.style.gap = "8px";
2100
+ if (this.isSummaryHovering || this.isReplyOpen) {
2101
+ header.append(
2102
+ this.createSummaryActionButton(
2103
+ "x",
2104
+ this.copy.hideMessage,
2105
+ this.handleSummaryDelete
2106
+ )
2107
+ );
2108
+ }
2109
+ const title = document.createElement("div");
2110
+ title.textContent = summary.title;
2111
+ title.style.minWidth = "0";
2112
+ title.style.flex = "1";
2113
+ title.style.overflow = "hidden";
2114
+ title.style.textOverflow = "ellipsis";
2115
+ title.style.whiteSpace = "nowrap";
2116
+ title.style.fontWeight = "700";
2117
+ title.style.fontSize = "15px";
2118
+ header.append(title);
2119
+ if (this.isSummaryHovering || this.isReplyOpen) {
2120
+ header.append(
2121
+ this.createSummaryActionButton(
2122
+ this.isSummaryExpanded ? "-" : ">",
2123
+ this.isSummaryExpanded ? this.copy.collapseMessage : this.copy.expandMessage,
2124
+ this.handleSummaryExpandToggle
2125
+ )
2126
+ );
2127
+ } else {
2128
+ header.append(this.createStatusIcon(summary.status));
2129
+ }
2130
+ const message = document.createElement("div");
2131
+ message.textContent = summary.message;
2132
+ message.style.marginTop = "4px";
2133
+ message.style.fontWeight = "400";
2134
+ message.style.color = "#374151";
2135
+ message.style.overflow = "hidden";
2136
+ if (this.isSummaryExpanded) {
2137
+ message.style.maxHeight = "7em";
2138
+ message.style.overflowY = "auto";
2139
+ } else {
2140
+ message.style.display = "-webkit-box";
2141
+ message.style.setProperty("-webkit-line-clamp", "2");
2142
+ message.style.setProperty("-webkit-box-orient", "vertical");
2143
+ }
2144
+ bubble.append(header, message);
2145
+ if (shouldShowReplyButton) {
2146
+ const reply = this.createTextButton(
2147
+ this.copy.replyButton,
2148
+ this.handleReplyOpen
2149
+ );
2150
+ reply.style.position = "absolute";
2151
+ reply.style.right = "14px";
2152
+ reply.style.bottom = "10px";
2153
+ bubble.append(reply);
2154
+ }
2155
+ if (this.isReplyOpen) {
2156
+ bubble.append(this.createReplyForm());
2157
+ }
2158
+ return bubble;
2159
+ }
2160
+ createSummaryToggleButton(label) {
2161
+ const button = document.createElement("button");
2162
+ button.type = "button";
2163
+ button.textContent = label;
2164
+ button.title = label === "1" ? this.copy.restoreMessage : this.copy.collapseMessage;
2165
+ button.addEventListener("click", stopEventPropagation);
2166
+ button.addEventListener("click", this.handleSummaryCollapseToggle);
2167
+ button.style.position = "absolute";
2168
+ button.style.top = "0";
2169
+ button.style.left = "0";
2170
+ button.style.pointerEvents = "auto";
2171
+ button.style.border = "1px solid rgba(148, 163, 184, 0.28)";
2172
+ button.style.background = "rgba(248, 250, 252, 0.94)";
2173
+ button.style.color = "#475569";
2174
+ button.style.boxShadow = "0 6px 18px rgba(15, 23, 42, 0.1)";
2175
+ button.style.cursor = "pointer";
2176
+ button.style.font = '600 15px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2177
+ button.style.display = "flex";
2178
+ button.style.alignItems = "center";
2179
+ button.style.justifyContent = "center";
2180
+ return button;
2181
+ }
2182
+ createStatusIcon(status) {
2183
+ const icon = document.createElement("span");
2184
+ icon.setAttribute("aria-hidden", "true");
2185
+ icon.style.display = "inline-flex";
2186
+ icon.style.width = "16px";
2187
+ icon.style.height = "16px";
2188
+ icon.style.alignItems = "center";
2189
+ icon.style.justifyContent = "center";
2190
+ icon.style.flex = "0 0 auto";
2191
+ if (status === "running") {
2192
+ icon.style.border = "2px solid rgba(71, 85, 105, 0.32)";
2193
+ icon.style.borderTopColor = "#64748b";
2194
+ icon.style.borderRadius = "999px";
2195
+ icon.style.animation = "chatkit-pet-summary-spin 900ms linear infinite";
2196
+ return icon;
2197
+ }
2198
+ icon.style.borderRadius = "999px";
2199
+ icon.style.fontSize = "12px";
2200
+ icon.style.fontWeight = "700";
2201
+ if (status === "failed") {
2202
+ icon.textContent = "!";
2203
+ icon.style.background = "#fee2e2";
2204
+ icon.style.color = "#b91c1c";
2205
+ return icon;
2206
+ }
2207
+ icon.textContent = "";
2208
+ icon.style.border = "2px solid #22c55e";
2209
+ icon.style.position = "relative";
2210
+ const check = document.createElement("span");
2211
+ check.style.width = "7px";
2212
+ check.style.height = "4px";
2213
+ check.style.borderLeft = "2px solid #22c55e";
2214
+ check.style.borderBottom = "2px solid #22c55e";
2215
+ check.style.transform = "rotate(-45deg) translate(1px, -1px)";
2216
+ icon.append(check);
2217
+ return icon;
2218
+ }
2219
+ createSummaryActionButton(label, title, onClick) {
2220
+ const button = document.createElement("button");
2221
+ button.type = "button";
2222
+ button.textContent = label;
2223
+ button.title = title;
2224
+ button.addEventListener("click", (event) => {
2225
+ event.preventDefault();
2226
+ event.stopPropagation();
2227
+ onClick();
2228
+ });
2229
+ button.style.width = "26px";
2230
+ button.style.height = "26px";
2231
+ button.style.border = "0";
2232
+ button.style.borderRadius = "999px";
2233
+ button.style.background = "rgba(241, 245, 249, 0.96)";
2234
+ button.style.color = "#475569";
2235
+ button.style.cursor = "pointer";
2236
+ button.style.font = '600 15px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2237
+ return button;
2238
+ }
2239
+ createTextButton(label, onClick) {
2240
+ const button = document.createElement("button");
2241
+ button.type = "button";
2242
+ button.textContent = label;
2243
+ button.addEventListener("click", (event) => {
2244
+ event.preventDefault();
2245
+ event.stopPropagation();
2246
+ onClick();
2247
+ });
2248
+ button.style.border = "1px solid rgba(148, 163, 184, 0.28)";
2249
+ button.style.borderRadius = "999px";
2250
+ button.style.background = "rgba(248, 250, 252, 0.95)";
2251
+ button.style.color = "#334155";
2252
+ button.style.cursor = "pointer";
2253
+ button.style.padding = "3px 10px";
2254
+ button.style.font = '600 12px/1.4 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2255
+ return button;
2256
+ }
2257
+ createReplyForm() {
2258
+ const form = document.createElement("form");
2259
+ form.addEventListener("click", stopEventPropagation);
2260
+ form.addEventListener("submit", this.handleReplySubmit);
2261
+ form.addEventListener("keydown", this.handleReplyKeyDown);
2262
+ form.style.display = "flex";
2263
+ form.style.gap = "6px";
2264
+ form.style.alignItems = "center";
2265
+ form.style.marginTop = "8px";
2266
+ const input = document.createElement("input");
2267
+ input.type = "text";
2268
+ input.value = this.replyDraft;
2269
+ input.disabled = this.isReplySubmitting;
2270
+ input.placeholder = this.copy.replyPlaceholder;
2271
+ input.addEventListener("input", this.handleReplyInput);
2272
+ input.style.minWidth = "0";
2273
+ input.style.flex = "1";
2274
+ input.style.border = "1px solid rgba(148, 163, 184, 0.35)";
2275
+ input.style.borderRadius = "999px";
2276
+ input.style.padding = "6px 10px";
2277
+ input.style.font = '400 13px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2278
+ this.replyInputElement = input;
2279
+ const send = document.createElement("button");
2280
+ send.type = "submit";
2281
+ send.textContent = this.isReplySubmitting ? this.copy.sendingButton : this.copy.sendButton;
2282
+ send.disabled = this.isReplySubmitting;
2283
+ send.style.border = "0";
2284
+ send.style.borderRadius = "999px";
2285
+ send.style.background = "#22c55e";
2286
+ send.style.color = "#052e16";
2287
+ send.style.cursor = this.isReplySubmitting ? "default" : "pointer";
2288
+ send.style.padding = "6px 10px";
2289
+ send.style.font = '700 12px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2290
+ form.append(input, send);
2291
+ if (this.replyError) {
2292
+ const error = document.createElement("div");
2293
+ error.textContent = this.copy.sendFailed;
2294
+ error.style.flexBasis = "100%";
2295
+ error.style.color = "#b91c1c";
2296
+ error.style.fontSize = "12px";
2297
+ form.style.flexWrap = "wrap";
2298
+ form.append(error);
2299
+ }
2300
+ return form;
2301
+ }
2302
+ renderAtlas(animationName, animationMode) {
2303
+ var _a2;
2304
+ if (!this.petElement || ((_a2 = this.resolved) == null ? void 0 : _a2.kind) !== "atlas" || !this.options) {
2305
+ return;
2306
+ }
2307
+ if (!(this.mediaElement instanceof HTMLDivElement)) {
2308
+ const frame = document.createElement("div");
2309
+ frame.setAttribute("aria-hidden", "true");
2310
+ this.petElement.replaceChildren(frame);
2311
+ this.mediaElement = frame;
2312
+ }
2313
+ const frameElement = this.mediaElement;
2314
+ const atlas = this.resolved.atlas;
2315
+ const definition = atlas.animations[animationName] ?? atlas.animations.idle;
2316
+ const safeFrame = animationMode === "once" && this.completed ? Math.max(0, definition.frames - 1) : Math.min(this.frame, Math.max(0, definition.frames - 1));
2317
+ const scale = getRenderScale(this.options.position.scale);
2318
+ const sourceWidth = atlas.cellWidth;
2319
+ const sourceHeight = atlas.cellHeight;
2320
+ const backgroundWidth = atlas.columns * sourceWidth;
2321
+ const backgroundHeight = atlas.rows * sourceHeight;
2322
+ frameElement.style.width = `${sourceWidth}px`;
2323
+ frameElement.style.height = `${sourceHeight}px`;
2324
+ frameElement.style.overflow = "hidden";
2325
+ frameElement.style.transform = `scale(${scale})`;
2326
+ frameElement.style.transformOrigin = "top left";
2327
+ frameElement.style.pointerEvents = "none";
2328
+ frameElement.style.backgroundImage = `url("${escapeCssUrl(
2329
+ this.resolved.src
2330
+ )}")`;
2331
+ frameElement.style.backgroundRepeat = "no-repeat";
2332
+ frameElement.style.backgroundSize = `${backgroundWidth}px ${backgroundHeight}px`;
2333
+ frameElement.style.backgroundPosition = `${-safeFrame * sourceWidth}px ${-definition.row * sourceHeight}px`;
2334
+ frameElement.style.imageRendering = this.options.imageRendering;
2335
+ frameElement.dataset.petFrame = String(safeFrame);
2336
+ }
2337
+ scheduleNextFrame(animationName, animationMode) {
2338
+ if (this.prefersReducedMotion || this.completed || !this.resolved) {
2339
+ this.clearTimers();
2340
+ return;
2341
+ }
2342
+ if (this.frameTimer !== null) {
2343
+ return;
2344
+ }
2345
+ const atlas = this.resolved.atlas;
2346
+ const definition = atlas.animations[animationName] ?? atlas.animations.idle;
2347
+ const duration = definition.frameDurations[this.frame] ?? definition.frameDurations[definition.frameDurations.length - 1] ?? 150;
2348
+ const baseDuration = duration * PET_FRAME_DURATION_MULTIPLIER;
2349
+ const effectiveDuration = this.isHovering || this.isDragging ? baseDuration : baseDuration * PET_RESTING_FRAME_DURATION_MULTIPLIER;
2350
+ this.frameTimer = window.setTimeout(() => {
2351
+ this.frameTimer = null;
2352
+ const nextFrame = this.frame + 1;
2353
+ if (nextFrame >= definition.frames) {
2354
+ if (animationMode === "once") {
2355
+ this.completed = true;
2356
+ this.frame = Math.max(0, definition.frames - 1);
2357
+ this.finishTransient();
2358
+ return;
2359
+ }
2360
+ this.frame = 0;
2361
+ this.render();
2362
+ return;
2363
+ }
2364
+ this.frame = nextFrame;
2365
+ this.render();
2366
+ }, effectiveDuration);
2367
+ }
2368
+ clearTimers() {
2369
+ if (this.frameTimer !== null) {
2370
+ window.clearTimeout(this.frameTimer);
2371
+ this.frameTimer = null;
2372
+ }
2373
+ }
2374
+ clearRestingDelayTimer() {
2375
+ if (this.restingDelayTimer !== null) {
2376
+ window.clearTimeout(this.restingDelayTimer);
2377
+ this.restingDelayTimer = null;
2378
+ }
2379
+ }
2380
+ finishTransient() {
2381
+ this.transient = null;
2382
+ this.activeAnimationName = null;
2383
+ this.activeAnimationMode = null;
2384
+ this.render();
2385
+ }
2386
+ rescheduleAnimation() {
2387
+ this.clearTimers();
2388
+ this.render();
2389
+ }
2390
+ enterRestingAfterDelay() {
2391
+ this.clearRestingDelayTimer();
2392
+ this.isHovering = true;
2393
+ this.restingDelayTimer = window.setTimeout(() => {
2394
+ this.restingDelayTimer = null;
2395
+ if (this.isDragging) {
2396
+ return;
2397
+ }
2398
+ this.isHovering = false;
2399
+ this.rescheduleAnimation();
2400
+ }, PET_RESTING_DELAY_MS);
2401
+ }
2402
+ isPointerOverPet(event) {
2403
+ var _a2;
2404
+ const rect = (_a2 = this.petElement) == null ? void 0 : _a2.getBoundingClientRect();
2405
+ if (!rect) {
2406
+ return false;
2407
+ }
2408
+ return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
2409
+ }
2410
+ async submitReply() {
2411
+ var _a2;
2412
+ const text = this.replyDraft.trim();
2413
+ if (!text || this.isReplySubmitting) {
2414
+ return;
2415
+ }
2416
+ this.isReplySubmitting = true;
2417
+ this.replyError = null;
2418
+ this.render();
2419
+ try {
2420
+ await ((_a2 = this.onReply) == null ? void 0 : _a2.call(this, text));
2421
+ this.replyDraft = "";
2422
+ this.isReplyOpen = false;
2423
+ this.isSummaryHovering = false;
2424
+ } catch {
2425
+ this.replyError = "Failed to send";
2426
+ } finally {
2427
+ this.isReplySubmitting = false;
2428
+ this.render();
2429
+ }
2430
+ }
2431
+ getNextDragPosition(event) {
2432
+ if (!this.options) {
2433
+ return { x: 0, y: 0 };
2434
+ }
2435
+ return clampPetPosition(
2436
+ {
2437
+ x: event.clientX - this.dragOffset.x,
2438
+ y: event.clientY - this.dragOffset.y
2439
+ },
2440
+ this.getSize(),
2441
+ getViewportSize(),
2442
+ normalizeBoundsPadding(this.options.position.boundsPadding)
2443
+ );
2444
+ }
2445
+ installDragListeners() {
2446
+ window.addEventListener("pointermove", this.handlePointerMove);
2447
+ window.addEventListener("pointerup", this.handlePointerUp, { once: true });
2448
+ window.addEventListener("pointercancel", this.handlePointerUp, {
2449
+ once: true
2450
+ });
2451
+ }
2452
+ removeDragListeners() {
2453
+ window.removeEventListener("pointermove", this.handlePointerMove);
2454
+ window.removeEventListener("pointerup", this.handlePointerUp);
2455
+ window.removeEventListener("pointercancel", this.handlePointerUp);
2456
+ }
2457
+ }
1027
2458
  function getInnerOptions(options) {
1028
2459
  return removeMethods(options);
1029
2460
  }
@@ -1047,7 +2478,15 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1047
2478
  __privateAdd(this, _frameUrl);
1048
2479
  __privateAdd(this, _frame);
1049
2480
  __privateAdd(this, _wrapper);
2481
+ __privateAdd(this, _launcherCloseButton);
2482
+ __privateAdd(this, _launcherOpen, false);
2483
+ __privateAdd(this, _framePetOptionsOverride);
1050
2484
  __privateAdd(this, _shadow, this.attachShadow({ mode: "open" }));
2485
+ __privateAdd(this, _petOverlay, new PetOverlay(__privateGet(this, _shadow), {
2486
+ onActivate: () => __privateMethod(this, _ChatKitElementBase_instances, handlePetActivate_fn).call(this),
2487
+ onReply: (text) => __privateMethod(this, _ChatKitElementBase_instances, handlePetReply_fn).call(this, text),
2488
+ onThreadSummaryActivate: (threadId) => void __privateMethod(this, _ChatKitElementBase_instances, handlePetThreadSummaryActivate_fn).call(this, threadId)
2489
+ }));
1051
2490
  __privateAdd(this, _resolveLoaded);
1052
2491
  __privateAdd(this, _loaded, new Promise((resolve) => {
1053
2492
  __privateSet(this, _resolveLoaded, resolve);
@@ -1142,6 +2581,9 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1142
2581
  }
1143
2582
  }
1144
2583
  }));
2584
+ __privateAdd(this, _handleLauncherClose, () => {
2585
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, false);
2586
+ });
1145
2587
  __privateAdd(this, _handleFrameLoad, () => {
1146
2588
  var _a2;
1147
2589
  this.dataset.loaded = "true";
@@ -1159,6 +2601,7 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1159
2601
  this.capabilities = getCapabilities(profile);
1160
2602
  }
1161
2603
  connectedCallback() {
2604
+ __privateGet(this, _petOverlay).connect();
1162
2605
  const style = document.createElement("style");
1163
2606
  style.textContent = `
1164
2607
  :host {
@@ -1166,6 +2609,10 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1166
2609
  position: relative;
1167
2610
  height: 100%;
1168
2611
  width: 100%;
2612
+ overflow: visible;
2613
+ }
2614
+ :host([data-display-mode="pet"]) {
2615
+ display: contents;
1169
2616
  }
1170
2617
  .ck-iframe {
1171
2618
  border: none;
@@ -1184,12 +2631,115 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1184
2631
  overflow: hidden;
1185
2632
  opacity: 0;
1186
2633
  }
2634
+ .ck-launcher-close {
2635
+ display: none;
2636
+ }
2637
+ :host([data-display-mode="pet"]) .ck-wrapper {
2638
+ position: fixed;
2639
+ inset: auto 16px 16px auto;
2640
+ width: min(420px, calc(100vw - 32px));
2641
+ height: min(720px, calc(100vh - 32px));
2642
+ max-height: calc(100vh - 32px);
2643
+ overflow: visible;
2644
+ border: 1px solid rgba(148, 163, 184, 0.35);
2645
+ border-radius: 18px;
2646
+ background: Canvas;
2647
+ box-shadow:
2648
+ 0 24px 80px rgba(15, 23, 42, 0.22),
2649
+ 0 0 0 1px rgba(15, 23, 42, 0.04);
2650
+ opacity: 0;
2651
+ pointer-events: none;
2652
+ transform: translateY(12px) scale(0.98);
2653
+ transition:
2654
+ opacity 160ms ease,
2655
+ transform 160ms ease;
2656
+ z-index: 39;
2657
+ }
2658
+ :host([data-display-mode="pet"][data-chat-open="true"]) .ck-wrapper {
2659
+ opacity: 1;
2660
+ pointer-events: auto;
2661
+ transform: translateY(0) scale(1);
2662
+ }
2663
+ :host([data-display-mode="pet"]) .ck-iframe {
2664
+ border-radius: inherit;
2665
+ }
2666
+ :host([data-display-mode="pet"]) .ck-launcher-close {
2667
+ display: inline-flex;
2668
+ position: absolute;
2669
+ top: -10px;
2670
+ right: -10px;
2671
+ z-index: 2;
2672
+ width: 28px;
2673
+ height: 28px;
2674
+ align-items: center;
2675
+ justify-content: center;
2676
+ border: 1px solid rgba(148, 163, 184, 0.45);
2677
+ border-radius: 999px;
2678
+ background: rgba(255, 255, 255, 0.96);
2679
+ color: #475569;
2680
+ box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
2681
+ cursor: pointer;
2682
+ font: inherit;
2683
+ font-size: 0;
2684
+ line-height: 1;
2685
+ }
2686
+ :host([data-display-mode="pet"]) .ck-launcher-close::before,
2687
+ :host([data-display-mode="pet"]) .ck-launcher-close::after {
2688
+ content: '';
2689
+ position: absolute;
2690
+ top: 50%;
2691
+ left: 50%;
2692
+ width: 14px;
2693
+ height: 2px;
2694
+ border-radius: 999px;
2695
+ background: currentColor;
2696
+ transform: translate(-50%, -50%) rotate(45deg);
2697
+ }
2698
+ :host([data-display-mode="pet"]) .ck-launcher-close::after {
2699
+ transform: translate(-50%, -50%) rotate(-45deg);
2700
+ }
2701
+ :host([data-display-mode="pet"]) .ck-launcher-close:hover {
2702
+ background: #fff;
2703
+ color: #0f172a;
2704
+ }
1187
2705
  :host([data-color-scheme="dark"]) .ck-iframe {
1188
2706
  color-scheme: dark only;
1189
2707
  }
2708
+ :host([data-color-scheme="dark"][data-display-mode="pet"]) .ck-wrapper {
2709
+ border-color: rgba(148, 163, 184, 0.28);
2710
+ background: #020617;
2711
+ box-shadow:
2712
+ 0 24px 80px rgba(0, 0, 0, 0.5),
2713
+ 0 0 0 1px rgba(255, 255, 255, 0.06);
2714
+ }
2715
+ :host([data-color-scheme="dark"][data-display-mode="pet"]) .ck-launcher-close {
2716
+ background: rgba(15, 23, 42, 0.88);
2717
+ border-color: rgba(148, 163, 184, 0.32);
2718
+ color: #cbd5e1;
2719
+ }
2720
+ :host([data-color-scheme="dark"][data-display-mode="pet"]) .ck-launcher-close:hover {
2721
+ background: #1e293b;
2722
+ color: #f8fafc;
2723
+ }
1190
2724
  :host([data-loaded="true"]) .ck-wrapper {
1191
2725
  opacity: 1;
1192
2726
  }
2727
+ :host([data-display-mode="pet"]:not([data-chat-open="true"])) .ck-wrapper {
2728
+ opacity: 0;
2729
+ }
2730
+ @media (max-width: 520px) {
2731
+ :host([data-display-mode="pet"]) .ck-wrapper {
2732
+ inset: auto 8px 8px 8px;
2733
+ width: auto;
2734
+ height: min(680px, calc(100vh - 16px));
2735
+ max-height: calc(100vh - 16px);
2736
+ border-radius: 16px;
2737
+ }
2738
+ :host([data-display-mode="pet"]) .ck-launcher-close {
2739
+ top: -8px;
2740
+ right: 8px;
2741
+ }
2742
+ }
1193
2743
  `;
1194
2744
  const frame = document.createElement("iframe");
1195
2745
  frame.className = "ck-iframe";
@@ -1205,6 +2755,13 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1205
2755
  wrapper.className = "ck-wrapper";
1206
2756
  wrapper.appendChild(frame);
1207
2757
  __privateSet(this, _wrapper, wrapper);
2758
+ const closeButton = document.createElement("button");
2759
+ closeButton.className = "ck-launcher-close";
2760
+ closeButton.type = "button";
2761
+ closeButton.setAttribute("aria-label", "Close chat");
2762
+ closeButton.addEventListener("click", __privateGet(this, _handleLauncherClose));
2763
+ wrapper.appendChild(closeButton);
2764
+ __privateSet(this, _launcherCloseButton, closeButton);
1208
2765
  __privateGet(this, _shadow).append(style);
1209
2766
  __privateGet(this, _messenger).on("left_header_icon_click", () => {
1210
2767
  var _a2, _b2, _c2;
@@ -1215,6 +2772,18 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1215
2772
  (_c2 = (_b2 = (_a2 = __privateGet(this, _opts)) == null ? void 0 : _a2.header) == null ? void 0 : _b2.rightAction) == null ? void 0 : _c2.onClick();
1216
2773
  });
1217
2774
  __privateGet(this, _messenger).on("public_event", ([event, data]) => {
2775
+ if (event === "log") {
2776
+ const payload = parseThreadSummaryLogPayload(data);
2777
+ if (payload) {
2778
+ __privateGet(this, _petOverlay).setThreadSummary(payload.summary);
2779
+ }
2780
+ } else if (event === "response.start") {
2781
+ __privateGet(this, _petOverlay).setThreadSummaryStatus("running");
2782
+ } else if (event === "response.end") {
2783
+ __privateGet(this, _petOverlay).setThreadSummaryStatus("completed");
2784
+ } else if (event === "response.stop") {
2785
+ __privateGet(this, _petOverlay).setThreadSummaryStatus("completed");
2786
+ }
1218
2787
  if (!this.capabilities.events.has(event)) return;
1219
2788
  if (event === "error" && "error" in data) {
1220
2789
  const error = fromPossibleFrameSafeError(data.error);
@@ -1228,6 +2797,19 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1228
2797
  }
1229
2798
  this.dispatchEvent(new CustomEvent(`chatkit.${event}`, { detail: data }));
1230
2799
  });
2800
+ __privateGet(this, _messenger).on("pet_state_change", (data) => {
2801
+ const payload = parsePetStateChangePayload(data);
2802
+ if (payload) {
2803
+ __privateGet(this, _petOverlay).setState(payload.state);
2804
+ }
2805
+ });
2806
+ __privateGet(this, _messenger).on("pet_options_change", (data) => {
2807
+ const payload = parsePetOptionsChangePayload(data);
2808
+ if (payload) {
2809
+ __privateSet(this, _framePetOptionsOverride, payload.pet);
2810
+ __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
2811
+ }
2812
+ });
1231
2813
  __privateGet(this, _messenger).on("unmount", () => {
1232
2814
  if (__privateGet(this, _wrapper) && __privateGet(this, _shadow).contains(__privateGet(this, _wrapper))) {
1233
2815
  __privateGet(this, _shadow).removeChild(__privateGet(this, _wrapper));
@@ -1250,16 +2832,25 @@ class ChatKitElementBase extends (_c = HTMLElement, _focusComposer_dec = [requir
1250
2832
  }
1251
2833
  }
1252
2834
  disconnectedCallback() {
1253
- var _a2;
2835
+ var _a2, _b2;
1254
2836
  (_a2 = __privateGet(this, _frame)) == null ? void 0 : _a2.removeEventListener("load", __privateGet(this, _handleFrameLoad));
2837
+ (_b2 = __privateGet(this, _launcherCloseButton)) == null ? void 0 : _b2.removeEventListener(
2838
+ "click",
2839
+ __privateGet(this, _handleLauncherClose)
2840
+ );
1255
2841
  __privateGet(this, _messenger).disconnect();
2842
+ __privateGet(this, _petOverlay).destroy();
1256
2843
  }
1257
2844
  applySanitizedOptions(newOptions) {
1258
2845
  __privateSet(this, _opts, newOptions);
2846
+ __privateGet(this, _petOverlay).setLocale(newOptions.locale);
2847
+ __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
1259
2848
  if (__privateGet(this, _initialized)) {
1260
2849
  __privateMethod(this, _ChatKitElementBase_instances, setOptionsDataAttributes_fn).call(this, __privateGet(this, _opts));
1261
2850
  __privateGet(this, _loaded).then(() => {
1262
- __privateGet(this, _messenger).commands.setOptions(getInnerOptions(newOptions));
2851
+ __privateGet(this, _messenger).commands.setOptions(
2852
+ getInnerOptions(__privateMethod(this, _ChatKitElementBase_instances, getFrameOptions_fn).call(this, newOptions))
2853
+ );
1263
2854
  });
1264
2855
  } else {
1265
2856
  __privateMethod(this, _ChatKitElementBase_instances, maybeInit_fn).call(this);
@@ -1331,7 +2922,11 @@ _opts = new WeakMap();
1331
2922
  _frameUrl = new WeakMap();
1332
2923
  _frame = new WeakMap();
1333
2924
  _wrapper = new WeakMap();
2925
+ _launcherCloseButton = new WeakMap();
2926
+ _launcherOpen = new WeakMap();
2927
+ _framePetOptionsOverride = new WeakMap();
1334
2928
  _shadow = new WeakMap();
2929
+ _petOverlay = new WeakMap();
1335
2930
  _resolveLoaded = new WeakMap();
1336
2931
  _loaded = new WeakMap();
1337
2932
  _messenger = new WeakMap();
@@ -1343,7 +2938,96 @@ emitAndThrow_fn = function(error) {
1343
2938
  setOptionsDataAttributes_fn = function(options) {
1344
2939
  var _a2;
1345
2940
  this.dataset.colorScheme = typeof options.theme === "string" ? options.theme : ((_a2 = options.theme) == null ? void 0 : _a2.colorScheme) ?? "light";
2941
+ this.dataset.displayMode = __privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this, options);
2942
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this, options) !== "pet") {
2943
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, false);
2944
+ }
2945
+ };
2946
+ getDisplayMode_fn = function(options = __privateGet(this, _opts)) {
2947
+ return (options == null ? void 0 : options.displayMode) === "pet" ? "pet" : "chat";
2948
+ };
2949
+ getConfiguredPetOptions_fn = function(options = __privateGet(this, _opts)) {
2950
+ if (!options) {
2951
+ return null;
2952
+ }
2953
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this, options) === "pet" && !normalizePetOptions(options.pet ?? null)) {
2954
+ return true;
2955
+ }
2956
+ return options.pet ?? null;
2957
+ };
2958
+ getOverlayPetOptions_fn = function() {
2959
+ let pet = __privateGet(this, _framePetOptionsOverride) !== void 0 ? __privateGet(this, _framePetOptionsOverride) : __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this);
2960
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet" && !normalizePetOptions(pet ?? null)) {
2961
+ pet = true;
2962
+ }
2963
+ return __privateMethod(this, _ChatKitElementBase_instances, resolveOverlayPetOptions_fn).call(this, pet);
2964
+ };
2965
+ resolvePetAssetUrl_fn = function(src) {
2966
+ try {
2967
+ const base = new URL(
2968
+ __privateGet(this, _frameUrl) ?? window.location.href,
2969
+ window.location.origin
2970
+ );
2971
+ return new URL(src, base).toString();
2972
+ } catch {
2973
+ return src;
2974
+ }
2975
+ };
2976
+ resolveOverlayPetOptions_fn = function(pet) {
2977
+ const normalized = normalizePetOptions(pet ?? null);
2978
+ if (!normalized) {
2979
+ return null;
2980
+ }
2981
+ return {
2982
+ character: {
2983
+ ...normalized.character,
2984
+ src: __privateMethod(this, _ChatKitElementBase_instances, resolvePetAssetUrl_fn).call(this, normalized.character.src)
2985
+ },
2986
+ position: normalized.position,
2987
+ behavior: normalized.behavior,
2988
+ ariaLabel: normalized.ariaLabel,
2989
+ imageRendering: normalized.imageRendering
2990
+ };
2991
+ };
2992
+ getFrameOptions_fn = function(options) {
2993
+ const pet = __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this, options);
2994
+ if (pet === (options.pet ?? null)) {
2995
+ return options;
2996
+ }
2997
+ const nextOptions = { ...options };
2998
+ if (pet === null) {
2999
+ delete nextOptions.pet;
3000
+ } else {
3001
+ nextOptions.pet = pet;
3002
+ }
3003
+ return nextOptions;
3004
+ };
3005
+ setLauncherOpen_fn = function(open) {
3006
+ __privateSet(this, _launcherOpen, open);
3007
+ if (open) {
3008
+ this.dataset.chatOpen = "true";
3009
+ } else {
3010
+ delete this.dataset.chatOpen;
3011
+ }
3012
+ };
3013
+ handlePetActivate_fn = function() {
3014
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) !== "pet") {
3015
+ return;
3016
+ }
3017
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, true);
3018
+ __privateGet(this, _loaded).then(() => this.focusComposer()).catch(() => void 0);
3019
+ };
3020
+ handlePetReply_fn = async function(text) {
3021
+ await this.sendUserMessage({ text });
3022
+ };
3023
+ handlePetThreadSummaryActivate_fn = async function(threadId) {
3024
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet") {
3025
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, true);
3026
+ }
3027
+ await this.setThreadId(threadId);
3028
+ await this.focusComposer();
1346
3029
  };
3030
+ _handleLauncherClose = new WeakMap();
1347
3031
  getFrameUrl_fn = function() {
1348
3032
  if (!__privateGet(this, _frameUrl)) {
1349
3033
  throw new IntegrationError2(
@@ -1383,7 +3067,7 @@ maybeInit_fn = function() {
1383
3067
  const frameURL = new URL(__privateMethod(this, _ChatKitElementBase_instances, getFrameUrl_fn).call(this), window.location.origin);
1384
3068
  __privateGet(this, _messenger).setTargetOrigin(frameURL.origin);
1385
3069
  frameURL.hash = encodeBase64({
1386
- options: getInnerOptions(__privateGet(this, _opts)),
3070
+ options: getInnerOptions(__privateMethod(this, _ChatKitElementBase_instances, getFrameOptions_fn).call(this, __privateGet(this, _opts))),
1387
3071
  referrer: window.location.origin,
1388
3072
  profile: this.profile
1389
3073
  });