@xpert-ai/chatkit-web-component 0.2.1 → 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.
@@ -51,7 +51,7 @@ var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot
51
51
  var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
52
52
  var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
53
53
 
54
- 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;
54
+ 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;
55
55
  class EventEmitter {
56
56
  constructor() {
57
57
  __publicField(this, "callbacks", /* @__PURE__ */ new Map());
@@ -869,6 +869,252 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
869
869
  return true;
870
870
  }
871
871
  }
872
+ const PET_ANIMATION_NAMES = [
873
+ "idle",
874
+ "running-right",
875
+ "running-left",
876
+ "waving",
877
+ "jumping",
878
+ "failed",
879
+ "waiting",
880
+ "running",
881
+ "review"
882
+ ];
883
+ const petSpriteAtlas = {
884
+ columns: 8,
885
+ rows: 9,
886
+ cellWidth: 192,
887
+ cellHeight: 208,
888
+ animations: {
889
+ idle: {
890
+ row: 0,
891
+ frames: 6,
892
+ frameDurations: [280, 110, 110, 140, 140, 320]
893
+ },
894
+ "running-right": {
895
+ row: 1,
896
+ frames: 8,
897
+ frameDurations: [120, 120, 120, 120, 120, 120, 120, 220]
898
+ },
899
+ "running-left": {
900
+ row: 2,
901
+ frames: 8,
902
+ frameDurations: [120, 120, 120, 120, 120, 120, 120, 220]
903
+ },
904
+ waving: {
905
+ row: 3,
906
+ frames: 4,
907
+ frameDurations: [140, 140, 140, 280]
908
+ },
909
+ jumping: {
910
+ row: 4,
911
+ frames: 5,
912
+ frameDurations: [140, 140, 140, 140, 280]
913
+ },
914
+ failed: {
915
+ row: 5,
916
+ frames: 8,
917
+ frameDurations: [140, 140, 140, 140, 140, 140, 140, 240]
918
+ },
919
+ waiting: {
920
+ row: 6,
921
+ frames: 6,
922
+ frameDurations: [150, 150, 150, 150, 150, 260]
923
+ },
924
+ running: {
925
+ row: 7,
926
+ frames: 6,
927
+ frameDurations: [120, 120, 120, 120, 120, 220]
928
+ },
929
+ review: {
930
+ row: 8,
931
+ frames: 6,
932
+ frameDurations: [150, 150, 150, 150, 150, 280]
933
+ }
934
+ }
935
+ };
936
+ const DEFAULT_PET_BOUNDS_PADDING = {
937
+ top: 0,
938
+ right: 0,
939
+ bottom: 0,
940
+ left: 0
941
+ };
942
+ const DEFAULT_PET_STORAGE_KEY = "chatkit:pet:position:v1";
943
+ const DEFAULT_PET_SPRITESHEET_URL = "/pets/boba/spritesheet.webp";
944
+ const DEFAULT_PET_CHARACTER = {
945
+ type: "sprite-atlas",
946
+ src: DEFAULT_PET_SPRITESHEET_URL
947
+ };
948
+ const DEFAULT_POSITION = {
949
+ pin: "bottom-right",
950
+ draggable: true,
951
+ scale: 0.25,
952
+ persist: true,
953
+ zIndex: 40
954
+ };
955
+ function mergeFrameAnimation(base, override) {
956
+ return {
957
+ row: (override == null ? void 0 : override.row) ?? base.row,
958
+ frames: (override == null ? void 0 : override.frames) ?? base.frames,
959
+ frameDurations: (override == null ? void 0 : override.frameDurations) && override.frameDurations.length > 0 ? override.frameDurations : base.frameDurations
960
+ };
961
+ }
962
+ function mergePetSpriteAtlas(override) {
963
+ var _a2;
964
+ const animations = {};
965
+ for (const name of PET_ANIMATION_NAMES) {
966
+ animations[name] = mergeFrameAnimation(
967
+ petSpriteAtlas.animations[name],
968
+ (_a2 = override == null ? void 0 : override.animations) == null ? void 0 : _a2[name]
969
+ );
970
+ }
971
+ return {
972
+ columns: (override == null ? void 0 : override.columns) ?? petSpriteAtlas.columns,
973
+ rows: (override == null ? void 0 : override.rows) ?? petSpriteAtlas.rows,
974
+ cellWidth: (override == null ? void 0 : override.cellWidth) ?? petSpriteAtlas.cellWidth,
975
+ cellHeight: (override == null ? void 0 : override.cellHeight) ?? petSpriteAtlas.cellHeight,
976
+ animations
977
+ };
978
+ }
979
+ function normalizeCharacter(character) {
980
+ if (!character) {
981
+ return DEFAULT_PET_CHARACTER;
982
+ }
983
+ if (character.src) {
984
+ return character;
985
+ }
986
+ return DEFAULT_PET_CHARACTER;
987
+ }
988
+ function normalizePetOptions(pet) {
989
+ if (!pet) {
990
+ return null;
991
+ }
992
+ if (pet === true) {
993
+ return {
994
+ character: DEFAULT_PET_CHARACTER,
995
+ position: DEFAULT_POSITION,
996
+ behavior: "auto",
997
+ ariaLabel: "Animated pet",
998
+ imageRendering: "auto"
999
+ };
1000
+ }
1001
+ if (pet.enabled === false) {
1002
+ return null;
1003
+ }
1004
+ return {
1005
+ character: normalizeCharacter(pet.character),
1006
+ position: {
1007
+ ...DEFAULT_POSITION,
1008
+ ...pet.position
1009
+ },
1010
+ behavior: pet.behavior ?? "auto",
1011
+ ariaLabel: pet.ariaLabel ?? "Animated pet",
1012
+ imageRendering: pet.imageRendering ?? "auto"
1013
+ };
1014
+ }
1015
+ function resolvePetCharacter(character) {
1016
+ if (!character.src) {
1017
+ return null;
1018
+ }
1019
+ return {
1020
+ kind: "atlas",
1021
+ src: character.src,
1022
+ atlas: mergePetSpriteAtlas(character.atlas)
1023
+ };
1024
+ }
1025
+ function normalizeBoundsPadding(value) {
1026
+ if (typeof value === "number") {
1027
+ return {
1028
+ top: value,
1029
+ right: value,
1030
+ bottom: value,
1031
+ left: value
1032
+ };
1033
+ }
1034
+ return {
1035
+ top: (value == null ? void 0 : value.top) ?? DEFAULT_PET_BOUNDS_PADDING.top,
1036
+ right: (value == null ? void 0 : value.right) ?? DEFAULT_PET_BOUNDS_PADDING.right,
1037
+ bottom: (value == null ? void 0 : value.bottom) ?? DEFAULT_PET_BOUNDS_PADDING.bottom,
1038
+ left: (value == null ? void 0 : value.left) ?? DEFAULT_PET_BOUNDS_PADDING.left
1039
+ };
1040
+ }
1041
+ function clampPetPosition(position, size, viewport, padding) {
1042
+ const minX = padding.left;
1043
+ const minY = padding.top;
1044
+ const maxX = Math.max(minX, viewport.width - size.width - padding.right);
1045
+ const maxY = Math.max(minY, viewport.height - size.height - padding.bottom);
1046
+ return {
1047
+ x: Math.min(maxX, Math.max(minX, position.x)),
1048
+ y: Math.min(maxY, Math.max(minY, position.y))
1049
+ };
1050
+ }
1051
+ function getPinnedPetPosition(pin, size, viewport, padding) {
1052
+ const horizontalCenter = (viewport.width - size.width) / 2;
1053
+ const verticalCenter = (viewport.height - size.height) / 2;
1054
+ const right = viewport.width - size.width - padding.right;
1055
+ const bottom = viewport.height - size.height - padding.bottom;
1056
+ switch (pin) {
1057
+ case "top-left":
1058
+ return clampPetPosition(
1059
+ { x: padding.left, y: padding.top },
1060
+ size,
1061
+ viewport,
1062
+ padding
1063
+ );
1064
+ case "top":
1065
+ return clampPetPosition(
1066
+ { x: horizontalCenter, y: padding.top },
1067
+ size,
1068
+ viewport,
1069
+ padding
1070
+ );
1071
+ case "top-right":
1072
+ return clampPetPosition(
1073
+ { x: right, y: padding.top },
1074
+ size,
1075
+ viewport,
1076
+ padding
1077
+ );
1078
+ case "left":
1079
+ return clampPetPosition(
1080
+ { x: padding.left, y: verticalCenter },
1081
+ size,
1082
+ viewport,
1083
+ padding
1084
+ );
1085
+ case "center":
1086
+ return clampPetPosition(
1087
+ { x: horizontalCenter, y: verticalCenter },
1088
+ size,
1089
+ viewport,
1090
+ padding
1091
+ );
1092
+ case "right":
1093
+ return clampPetPosition(
1094
+ { x: right, y: verticalCenter },
1095
+ size,
1096
+ viewport,
1097
+ padding
1098
+ );
1099
+ case "bottom-left":
1100
+ return clampPetPosition(
1101
+ { x: padding.left, y: bottom },
1102
+ size,
1103
+ viewport,
1104
+ padding
1105
+ );
1106
+ case "bottom":
1107
+ return clampPetPosition(
1108
+ { x: horizontalCenter, y: bottom },
1109
+ size,
1110
+ viewport,
1111
+ padding
1112
+ );
1113
+ case "bottom-right":
1114
+ default:
1115
+ return clampPetPosition({ x: right, y: bottom }, size, viewport, padding);
1116
+ }
1117
+ }
872
1118
  const removeMethods = (obj, seen = /* @__PURE__ */ new WeakSet()) => {
873
1119
  if (typeof obj === "function") return "[ChatKitMethod]";
874
1120
  if (typeof obj !== "object" || obj === null) return obj;
@@ -887,6 +1133,1191 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
887
1133
  }
888
1134
  return result;
889
1135
  };
1136
+ const DRAG_DIRECTION_THRESHOLD_PX = 2;
1137
+ const PET_BASE_RENDER_SCALE = 0.5;
1138
+ const PET_FRAME_DURATION_MULTIPLIER = 1.5;
1139
+ const PET_RESTING_FRAME_DURATION_MULTIPLIER = 3;
1140
+ const PET_RESTING_DELAY_MS = 2e3;
1141
+ const PET_SUMMARY_GAP = 12;
1142
+ const PET_SUMMARY_WIDTH = 320;
1143
+ const PET_SUMMARY_MARGIN = 12;
1144
+ const PET_OVERLAY_COPY = {
1145
+ "en-US": {
1146
+ hideMessage: "Hide message",
1147
+ expandMessage: "Expand message",
1148
+ collapseMessage: "Collapse message",
1149
+ restoreMessage: "Show message",
1150
+ replyButton: "Reply",
1151
+ replyPlaceholder: "Reply...",
1152
+ sendButton: "Send",
1153
+ sendingButton: "Sending...",
1154
+ sendFailed: "Failed to send"
1155
+ },
1156
+ "zh-CN": {
1157
+ hideMessage: "隐藏消息",
1158
+ expandMessage: "展开消息",
1159
+ collapseMessage: "收起消息",
1160
+ restoreMessage: "显示消息",
1161
+ replyButton: "回复",
1162
+ replyPlaceholder: "输入回复...",
1163
+ sendButton: "发送",
1164
+ sendingButton: "发送中...",
1165
+ sendFailed: "发送失败"
1166
+ }
1167
+ };
1168
+ function stopEventPropagation(event) {
1169
+ event.stopPropagation();
1170
+ }
1171
+ function getViewportSize() {
1172
+ const visualViewport = window.visualViewport;
1173
+ return {
1174
+ width: (visualViewport == null ? void 0 : visualViewport.width) || window.innerWidth || 320,
1175
+ height: (visualViewport == null ? void 0 : visualViewport.height) || window.innerHeight || 480
1176
+ };
1177
+ }
1178
+ function readPersistedPosition(storageKey, persist) {
1179
+ if (!persist) {
1180
+ return null;
1181
+ }
1182
+ try {
1183
+ const raw = window.localStorage.getItem(storageKey);
1184
+ if (!raw) {
1185
+ return null;
1186
+ }
1187
+ const parsed = JSON.parse(raw);
1188
+ if (!parsed || typeof parsed !== "object" || typeof parsed.x !== "number" || typeof parsed.y !== "number") {
1189
+ return null;
1190
+ }
1191
+ return { x: parsed.x, y: parsed.y };
1192
+ } catch {
1193
+ return null;
1194
+ }
1195
+ }
1196
+ function writePersistedPosition(storageKey, persist, position) {
1197
+ if (!persist) {
1198
+ return;
1199
+ }
1200
+ try {
1201
+ window.localStorage.setItem(storageKey, JSON.stringify(position));
1202
+ } catch {
1203
+ }
1204
+ }
1205
+ function escapeCssUrl(value) {
1206
+ return value.replace(/["\\]/g, "\\$&");
1207
+ }
1208
+ function getRenderScale(scale) {
1209
+ return Math.max(0.1, scale) * PET_BASE_RENDER_SCALE;
1210
+ }
1211
+ function clampNumber(value, min, max) {
1212
+ return Math.min(max, Math.max(min, value));
1213
+ }
1214
+ function getDefaultLocale() {
1215
+ if (typeof window !== "undefined") {
1216
+ try {
1217
+ const stored = window.localStorage.getItem("chatkit:locale");
1218
+ if (stored) {
1219
+ return stored;
1220
+ }
1221
+ } catch {
1222
+ }
1223
+ }
1224
+ return typeof navigator !== "undefined" ? navigator.language : null;
1225
+ }
1226
+ function resolveCopyLocale(locale) {
1227
+ const normalized = (locale ?? getDefaultLocale() ?? "").trim().toLowerCase();
1228
+ if (normalized === "zh-cn" || normalized === "zh-hans" || normalized.startsWith("zh")) {
1229
+ return "zh-CN";
1230
+ }
1231
+ return "en-US";
1232
+ }
1233
+ function isPetState(value) {
1234
+ return value === "idle" || value === "running-right" || value === "running-left" || value === "waving" || value === "jumping" || value === "failed" || value === "waiting" || value === "running" || value === "review";
1235
+ }
1236
+ function parsePetStateChangePayload(value) {
1237
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1238
+ return null;
1239
+ }
1240
+ const payload = value;
1241
+ return isPetState(payload.state) ? { state: payload.state } : null;
1242
+ }
1243
+ function parsePetOptionsChangePayload(value) {
1244
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1245
+ return null;
1246
+ }
1247
+ const payload = value;
1248
+ if (payload.pet === null || typeof payload.pet === "boolean") {
1249
+ return { pet: payload.pet };
1250
+ }
1251
+ if (payload.pet && typeof payload.pet === "object" && !Array.isArray(payload.pet)) {
1252
+ return { pet: payload.pet };
1253
+ }
1254
+ return null;
1255
+ }
1256
+ function isThreadSummaryStatus(value) {
1257
+ return value === "running" || value === "completed" || value === "failed";
1258
+ }
1259
+ function getThreadSummaryKey(summary) {
1260
+ if (!summary) {
1261
+ return null;
1262
+ }
1263
+ return [
1264
+ summary.threadId,
1265
+ summary.messageId || summary.updatedAt || summary.message
1266
+ ].join(":");
1267
+ }
1268
+ function parseThreadSummaryPayload(value) {
1269
+ if (value === null) {
1270
+ return { summary: null };
1271
+ }
1272
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1273
+ return null;
1274
+ }
1275
+ const payload = value;
1276
+ 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)) {
1277
+ return null;
1278
+ }
1279
+ return {
1280
+ summary: {
1281
+ threadId: payload.threadId,
1282
+ title: payload.title,
1283
+ message: payload.message,
1284
+ status: payload.status,
1285
+ ...typeof payload.messageId === "string" && payload.messageId.trim() ? { messageId: payload.messageId } : {},
1286
+ ...typeof payload.updatedAt === "string" && payload.updatedAt.trim() ? { updatedAt: payload.updatedAt } : {}
1287
+ }
1288
+ };
1289
+ }
1290
+ function parseThreadSummaryLogPayload(value) {
1291
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
1292
+ return null;
1293
+ }
1294
+ const payload = value;
1295
+ if (payload.name !== "thread.summary") {
1296
+ return null;
1297
+ }
1298
+ return parseThreadSummaryPayload(payload.data ?? null);
1299
+ }
1300
+ class PetOverlay {
1301
+ constructor(root, options) {
1302
+ this.overlayElement = null;
1303
+ this.petElement = null;
1304
+ this.summaryElement = null;
1305
+ this.summaryToggleElement = null;
1306
+ this.mediaElement = null;
1307
+ this.options = null;
1308
+ this.resolved = null;
1309
+ this.summary = null;
1310
+ this.summaryRenderKey = null;
1311
+ this.dismissedSummaryKey = null;
1312
+ this.isSummaryCollapsed = false;
1313
+ this.isSummaryExpanded = false;
1314
+ this.isSummaryHovering = false;
1315
+ this.isReplyOpen = false;
1316
+ this.isReplySubmitting = false;
1317
+ this.replyError = null;
1318
+ this.replyDraft = "";
1319
+ this.replyInputElement = null;
1320
+ this.copyLocale = resolveCopyLocale();
1321
+ this.copy = PET_OVERLAY_COPY[this.copyLocale];
1322
+ this.currentState = "waiting";
1323
+ this.lastAutoState = "waiting";
1324
+ this.transient = null;
1325
+ this.position = null;
1326
+ this.dragPosition = null;
1327
+ this.dragOffset = { x: 0, y: 0 };
1328
+ this.lastDragPosition = null;
1329
+ this.lastDragClientX = null;
1330
+ this.dragAnimation = null;
1331
+ this.isDragging = false;
1332
+ this.isHovering = false;
1333
+ this.movedDuringDrag = false;
1334
+ this.prefersReducedMotion = false;
1335
+ this.frame = 0;
1336
+ this.completed = false;
1337
+ this.activeAnimationName = null;
1338
+ this.activeAnimationMode = null;
1339
+ this.frameTimer = null;
1340
+ this.restingDelayTimer = null;
1341
+ this.mediaQuery = null;
1342
+ this.connected = false;
1343
+ this.handleViewportChange = () => {
1344
+ this.render();
1345
+ };
1346
+ this.handleReducedMotionChange = () => {
1347
+ var _a2;
1348
+ this.prefersReducedMotion = Boolean((_a2 = this.mediaQuery) == null ? void 0 : _a2.matches);
1349
+ if (this.prefersReducedMotion) {
1350
+ this.transient = null;
1351
+ }
1352
+ this.render();
1353
+ };
1354
+ this.handlePointerEnter = () => {
1355
+ this.clearRestingDelayTimer();
1356
+ this.isHovering = true;
1357
+ this.rescheduleAnimation();
1358
+ };
1359
+ this.handlePointerLeave = () => {
1360
+ if (!this.isDragging) {
1361
+ this.enterRestingAfterDelay();
1362
+ }
1363
+ };
1364
+ this.handleSummaryPointerEnter = () => {
1365
+ this.isSummaryHovering = true;
1366
+ this.render();
1367
+ };
1368
+ this.handleSummaryPointerLeave = () => {
1369
+ this.isSummaryHovering = false;
1370
+ if (!this.isReplyOpen) {
1371
+ this.render();
1372
+ }
1373
+ };
1374
+ this.handleSummaryClick = () => {
1375
+ var _a2, _b2;
1376
+ const threadId = (_a2 = this.summary) == null ? void 0 : _a2.threadId.trim();
1377
+ if (!threadId) {
1378
+ return;
1379
+ }
1380
+ (_b2 = this.onThreadSummaryActivate) == null ? void 0 : _b2.call(this, threadId);
1381
+ };
1382
+ this.handleSummaryDelete = () => {
1383
+ const summaryKey = getThreadSummaryKey(this.summary);
1384
+ if (summaryKey) {
1385
+ this.dismissedSummaryKey = summaryKey;
1386
+ }
1387
+ this.isSummaryCollapsed = false;
1388
+ this.isReplyOpen = false;
1389
+ this.replyDraft = "";
1390
+ this.replyError = null;
1391
+ this.removeSummaryElements();
1392
+ };
1393
+ this.handleSummaryCollapseToggle = () => {
1394
+ this.isSummaryCollapsed = !this.isSummaryCollapsed;
1395
+ this.isSummaryExpanded = false;
1396
+ this.isReplyOpen = false;
1397
+ this.replyError = null;
1398
+ this.render();
1399
+ };
1400
+ this.handleSummaryExpandToggle = () => {
1401
+ this.isSummaryExpanded = !this.isSummaryExpanded;
1402
+ this.render();
1403
+ };
1404
+ this.handleReplyOpen = () => {
1405
+ this.isReplyOpen = true;
1406
+ this.replyError = null;
1407
+ this.render();
1408
+ };
1409
+ this.handleReplyInput = (event) => {
1410
+ const target = event.currentTarget;
1411
+ if (target instanceof HTMLInputElement) {
1412
+ this.replyDraft = target.value;
1413
+ this.replyError = null;
1414
+ }
1415
+ };
1416
+ this.handleReplySubmit = (event) => {
1417
+ event.preventDefault();
1418
+ void this.submitReply();
1419
+ };
1420
+ this.handleReplyKeyDown = (event) => {
1421
+ if (event.key !== "Escape") {
1422
+ return;
1423
+ }
1424
+ event.preventDefault();
1425
+ this.isReplyOpen = false;
1426
+ this.replyError = null;
1427
+ this.render();
1428
+ };
1429
+ this.handlePointerDown = (event) => {
1430
+ var _a2, _b2;
1431
+ if (!((_a2 = this.options) == null ? void 0 : _a2.position.draggable) || event.button !== 0) {
1432
+ return;
1433
+ }
1434
+ event.preventDefault();
1435
+ const rect = (_b2 = this.petElement) == null ? void 0 : _b2.getBoundingClientRect();
1436
+ if (!rect) {
1437
+ return;
1438
+ }
1439
+ const nextPosition = {
1440
+ x: rect.left,
1441
+ y: rect.top
1442
+ };
1443
+ this.dragOffset = {
1444
+ x: event.clientX - rect.left,
1445
+ y: event.clientY - rect.top
1446
+ };
1447
+ this.lastDragPosition = nextPosition;
1448
+ this.lastDragClientX = event.clientX;
1449
+ this.dragAnimation = null;
1450
+ this.movedDuringDrag = false;
1451
+ this.dragPosition = nextPosition;
1452
+ this.isDragging = true;
1453
+ this.clearRestingDelayTimer();
1454
+ this.isHovering = true;
1455
+ this.installDragListeners();
1456
+ this.rescheduleAnimation();
1457
+ };
1458
+ this.handlePointerMove = (event) => {
1459
+ const nextPosition = this.getNextDragPosition(event);
1460
+ const last = this.lastDragPosition;
1461
+ if (last && (Math.abs(last.x - nextPosition.x) > DRAG_DIRECTION_THRESHOLD_PX || Math.abs(last.y - nextPosition.y) > DRAG_DIRECTION_THRESHOLD_PX)) {
1462
+ this.movedDuringDrag = true;
1463
+ }
1464
+ if (this.lastDragClientX !== null) {
1465
+ const deltaX = event.clientX - this.lastDragClientX;
1466
+ if (deltaX > DRAG_DIRECTION_THRESHOLD_PX) {
1467
+ this.dragAnimation = "running-right";
1468
+ } else if (deltaX < -DRAG_DIRECTION_THRESHOLD_PX) {
1469
+ this.dragAnimation = "running-left";
1470
+ }
1471
+ }
1472
+ this.lastDragClientX = event.clientX;
1473
+ this.lastDragPosition = nextPosition;
1474
+ this.dragPosition = nextPosition;
1475
+ this.render();
1476
+ };
1477
+ this.handlePointerUp = (event) => {
1478
+ const finalPosition = this.lastDragPosition ?? this.getNextDragPosition(event);
1479
+ this.isDragging = false;
1480
+ this.dragPosition = null;
1481
+ this.dragAnimation = null;
1482
+ this.lastDragClientX = null;
1483
+ this.removeDragListeners();
1484
+ this.persistPosition(finalPosition);
1485
+ if (event.pointerType === "mouse" && this.isPointerOverPet(event)) {
1486
+ this.isHovering = true;
1487
+ this.rescheduleAnimation();
1488
+ } else {
1489
+ this.enterRestingAfterDelay();
1490
+ this.rescheduleAnimation();
1491
+ }
1492
+ };
1493
+ this.handleClick = () => {
1494
+ var _a2;
1495
+ if (this.movedDuringDrag) {
1496
+ return;
1497
+ }
1498
+ (_a2 = this.onActivate) == null ? void 0 : _a2.call(this);
1499
+ if (this.prefersReducedMotion) {
1500
+ return;
1501
+ }
1502
+ this.transient = { name: "waving" };
1503
+ this.render();
1504
+ };
1505
+ this.root = root;
1506
+ this.onActivate = options == null ? void 0 : options.onActivate;
1507
+ this.onReply = options == null ? void 0 : options.onReply;
1508
+ this.onThreadSummaryActivate = options == null ? void 0 : options.onThreadSummaryActivate;
1509
+ this.connect();
1510
+ }
1511
+ connect() {
1512
+ if (this.connected) {
1513
+ return;
1514
+ }
1515
+ this.connected = true;
1516
+ this.installViewportListeners();
1517
+ this.installReducedMotionListener();
1518
+ this.render();
1519
+ }
1520
+ setOptions(pet) {
1521
+ const nextOptions = normalizePetOptions(pet);
1522
+ this.options = nextOptions;
1523
+ if (!nextOptions) {
1524
+ this.isDragging = false;
1525
+ this.isHovering = false;
1526
+ this.position = null;
1527
+ this.dragPosition = null;
1528
+ this.dragAnimation = null;
1529
+ this.lastDragPosition = null;
1530
+ this.lastDragClientX = null;
1531
+ this.transient = null;
1532
+ this.resolved = null;
1533
+ this.clearRestingDelayTimer();
1534
+ this.removeDragListeners();
1535
+ this.removeOverlay();
1536
+ return;
1537
+ }
1538
+ this.position = readPersistedPosition(
1539
+ DEFAULT_PET_STORAGE_KEY,
1540
+ nextOptions.position.persist
1541
+ );
1542
+ if (nextOptions.behavior === "auto" && !this.prefersReducedMotion) {
1543
+ this.transient = { name: "waving" };
1544
+ }
1545
+ this.resolveCharacter();
1546
+ this.render();
1547
+ }
1548
+ setState(state) {
1549
+ var _a2;
1550
+ const previous = this.lastAutoState;
1551
+ this.lastAutoState = state;
1552
+ this.currentState = state;
1553
+ if (((_a2 = this.options) == null ? void 0 : _a2.behavior) === "auto" && !this.prefersReducedMotion && state === "idle" && (previous === "running" || previous === "review") && !this.transient) {
1554
+ this.transient = { name: "jumping" };
1555
+ } else if (state !== "idle") {
1556
+ this.transient = null;
1557
+ }
1558
+ this.render();
1559
+ }
1560
+ setLocale(locale) {
1561
+ const nextLocale = resolveCopyLocale(locale);
1562
+ if (nextLocale === this.copyLocale) {
1563
+ return;
1564
+ }
1565
+ this.copyLocale = nextLocale;
1566
+ this.copy = PET_OVERLAY_COPY[nextLocale];
1567
+ this.summaryRenderKey = null;
1568
+ this.render();
1569
+ }
1570
+ setThreadSummary(summary) {
1571
+ const previousKey = getThreadSummaryKey(this.summary);
1572
+ const nextKey = getThreadSummaryKey(summary);
1573
+ this.summary = summary;
1574
+ if (!summary) {
1575
+ this.isSummaryCollapsed = false;
1576
+ this.isSummaryExpanded = false;
1577
+ this.isSummaryHovering = false;
1578
+ this.isReplyOpen = false;
1579
+ this.isReplySubmitting = false;
1580
+ this.replyError = null;
1581
+ this.replyDraft = "";
1582
+ this.summaryRenderKey = null;
1583
+ this.removeSummaryElements();
1584
+ return;
1585
+ }
1586
+ if (previousKey !== nextKey) {
1587
+ this.isSummaryCollapsed = false;
1588
+ this.isSummaryExpanded = false;
1589
+ this.isSummaryHovering = false;
1590
+ this.isReplyOpen = false;
1591
+ this.isReplySubmitting = false;
1592
+ this.replyError = null;
1593
+ this.replyDraft = "";
1594
+ }
1595
+ this.render();
1596
+ }
1597
+ setThreadSummaryStatus(status) {
1598
+ if (!this.summary || this.summary.status === status) {
1599
+ return;
1600
+ }
1601
+ this.summary = { ...this.summary, status };
1602
+ this.render();
1603
+ }
1604
+ destroy() {
1605
+ var _a2, _b2, _c2, _d;
1606
+ if (!this.connected) {
1607
+ return;
1608
+ }
1609
+ this.connected = false;
1610
+ this.clearRestingDelayTimer();
1611
+ this.clearTimers();
1612
+ this.removeDragListeners();
1613
+ this.removeOverlay();
1614
+ window.removeEventListener("resize", this.handleViewportChange);
1615
+ (_a2 = window.visualViewport) == null ? void 0 : _a2.removeEventListener(
1616
+ "resize",
1617
+ this.handleViewportChange
1618
+ );
1619
+ (_b2 = window.visualViewport) == null ? void 0 : _b2.removeEventListener(
1620
+ "scroll",
1621
+ this.handleViewportChange
1622
+ );
1623
+ (_d = (_c2 = this.mediaQuery) == null ? void 0 : _c2.removeEventListener) == null ? void 0 : _d.call(
1624
+ _c2,
1625
+ "change",
1626
+ this.handleReducedMotionChange
1627
+ );
1628
+ this.mediaQuery = null;
1629
+ }
1630
+ installViewportListeners() {
1631
+ var _a2, _b2;
1632
+ window.addEventListener("resize", this.handleViewportChange);
1633
+ (_a2 = window.visualViewport) == null ? void 0 : _a2.addEventListener("resize", this.handleViewportChange);
1634
+ (_b2 = window.visualViewport) == null ? void 0 : _b2.addEventListener("scroll", this.handleViewportChange);
1635
+ }
1636
+ installReducedMotionListener() {
1637
+ var _a2, _b2;
1638
+ if (!window.matchMedia) {
1639
+ return;
1640
+ }
1641
+ this.mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
1642
+ this.prefersReducedMotion = this.mediaQuery.matches;
1643
+ (_b2 = (_a2 = this.mediaQuery).addEventListener) == null ? void 0 : _b2.call(
1644
+ _a2,
1645
+ "change",
1646
+ this.handleReducedMotionChange
1647
+ );
1648
+ }
1649
+ resolveCharacter() {
1650
+ if (!this.options) {
1651
+ this.resolved = null;
1652
+ return;
1653
+ }
1654
+ const character = this.options.character;
1655
+ this.resolved = resolvePetCharacter(character);
1656
+ }
1657
+ ensureOverlay() {
1658
+ if (this.overlayElement && this.petElement) {
1659
+ return;
1660
+ }
1661
+ const overlay = document.createElement("div");
1662
+ overlay.setAttribute("data-chatkit-host-pet-layer", "");
1663
+ overlay.style.position = "fixed";
1664
+ overlay.style.inset = "0";
1665
+ overlay.style.pointerEvents = "none";
1666
+ overlay.style.overflow = "visible";
1667
+ const style = document.createElement("style");
1668
+ style.textContent = `
1669
+ @keyframes chatkit-pet-summary-spin {
1670
+ to { transform: rotate(360deg); }
1671
+ }
1672
+ `;
1673
+ const pet = document.createElement("div");
1674
+ pet.setAttribute("data-chatkit-host-pet", "");
1675
+ pet.style.position = "absolute";
1676
+ pet.style.top = "0";
1677
+ pet.style.left = "0";
1678
+ pet.style.pointerEvents = "auto";
1679
+ pet.style.touchAction = "none";
1680
+ pet.style.userSelect = "none";
1681
+ pet.style.willChange = "transform";
1682
+ pet.addEventListener("pointerenter", this.handlePointerEnter);
1683
+ pet.addEventListener("pointerleave", this.handlePointerLeave);
1684
+ pet.addEventListener("pointerdown", this.handlePointerDown);
1685
+ pet.addEventListener("click", this.handleClick);
1686
+ overlay.append(style, pet);
1687
+ this.root.append(overlay);
1688
+ this.overlayElement = overlay;
1689
+ this.petElement = pet;
1690
+ }
1691
+ removeOverlay() {
1692
+ var _a2;
1693
+ this.clearRestingDelayTimer();
1694
+ this.clearTimers();
1695
+ if (this.petElement) {
1696
+ this.petElement.removeEventListener(
1697
+ "pointerenter",
1698
+ this.handlePointerEnter
1699
+ );
1700
+ this.petElement.removeEventListener(
1701
+ "pointerleave",
1702
+ this.handlePointerLeave
1703
+ );
1704
+ this.petElement.removeEventListener("pointerdown", this.handlePointerDown);
1705
+ this.petElement.removeEventListener("click", this.handleClick);
1706
+ }
1707
+ this.isHovering = false;
1708
+ this.removeSummaryElements();
1709
+ (_a2 = this.overlayElement) == null ? void 0 : _a2.remove();
1710
+ this.overlayElement = null;
1711
+ this.petElement = null;
1712
+ this.mediaElement = null;
1713
+ }
1714
+ removeSummaryElements() {
1715
+ var _a2, _b2;
1716
+ (_a2 = this.summaryElement) == null ? void 0 : _a2.remove();
1717
+ (_b2 = this.summaryToggleElement) == null ? void 0 : _b2.remove();
1718
+ this.summaryElement = null;
1719
+ this.summaryToggleElement = null;
1720
+ this.replyInputElement = null;
1721
+ this.summaryRenderKey = null;
1722
+ }
1723
+ getSize() {
1724
+ if (!this.options || !this.resolved) {
1725
+ return { width: 0, height: 0 };
1726
+ }
1727
+ const scale = getRenderScale(this.options.position.scale);
1728
+ const baseSize = {
1729
+ width: this.resolved.atlas.cellWidth,
1730
+ height: this.resolved.atlas.cellHeight
1731
+ };
1732
+ return {
1733
+ width: baseSize.width * scale,
1734
+ height: baseSize.height * scale
1735
+ };
1736
+ }
1737
+ getCurrentPosition(size) {
1738
+ const options = this.options;
1739
+ if (!options) {
1740
+ return { x: 0, y: 0 };
1741
+ }
1742
+ const viewport = getViewportSize();
1743
+ const padding = normalizeBoundsPadding(options.position.boundsPadding);
1744
+ const pin = options.position.pin === void 0 ? "bottom-right" : options.position.pin;
1745
+ const pinnedPosition = pin ? getPinnedPetPosition(pin, size, viewport, padding) : null;
1746
+ return clampPetPosition(
1747
+ this.dragPosition ?? this.position ?? pinnedPosition ?? { x: padding.left, y: padding.top },
1748
+ size,
1749
+ viewport,
1750
+ padding
1751
+ );
1752
+ }
1753
+ persistPosition(nextPosition) {
1754
+ if (!this.options) {
1755
+ return;
1756
+ }
1757
+ const size = this.getSize();
1758
+ const clamped = clampPetPosition(
1759
+ nextPosition,
1760
+ size,
1761
+ getViewportSize(),
1762
+ normalizeBoundsPadding(this.options.position.boundsPadding)
1763
+ );
1764
+ this.position = clamped;
1765
+ writePersistedPosition(
1766
+ DEFAULT_PET_STORAGE_KEY,
1767
+ this.options.position.persist,
1768
+ clamped
1769
+ );
1770
+ }
1771
+ getActiveAnimationName() {
1772
+ if (!this.options) {
1773
+ return "idle";
1774
+ }
1775
+ if (this.isDragging) {
1776
+ return this.dragAnimation ?? "running";
1777
+ }
1778
+ if (this.transient) {
1779
+ return this.transient.name;
1780
+ }
1781
+ if (this.options.behavior === "manual") {
1782
+ return "idle";
1783
+ }
1784
+ return this.currentState;
1785
+ }
1786
+ getActiveAnimationMode() {
1787
+ if (this.isDragging) {
1788
+ return "loop";
1789
+ }
1790
+ return this.transient ? "once" : "loop";
1791
+ }
1792
+ resetAnimationIfNeeded(name, mode) {
1793
+ if (this.activeAnimationName === name && this.activeAnimationMode === mode) {
1794
+ return;
1795
+ }
1796
+ this.clearTimers();
1797
+ this.activeAnimationName = name;
1798
+ this.activeAnimationMode = mode;
1799
+ this.frame = 0;
1800
+ this.completed = false;
1801
+ }
1802
+ render() {
1803
+ if (!this.options || !this.resolved) {
1804
+ this.clearTimers();
1805
+ if (this.petElement) {
1806
+ this.petElement.replaceChildren();
1807
+ }
1808
+ this.removeSummaryElements();
1809
+ this.mediaElement = null;
1810
+ this.activeAnimationName = null;
1811
+ this.activeAnimationMode = null;
1812
+ this.frame = 0;
1813
+ this.completed = false;
1814
+ return;
1815
+ }
1816
+ this.ensureOverlay();
1817
+ const overlay = this.overlayElement;
1818
+ const pet = this.petElement;
1819
+ if (!overlay || !pet) {
1820
+ return;
1821
+ }
1822
+ const size = this.getSize();
1823
+ const position = this.getCurrentPosition(size);
1824
+ const animationName = this.getActiveAnimationName();
1825
+ const animationMode = this.getActiveAnimationMode();
1826
+ this.resetAnimationIfNeeded(animationName, animationMode);
1827
+ overlay.style.zIndex = String(this.options.position.zIndex);
1828
+ pet.style.width = `${size.width}px`;
1829
+ pet.style.height = `${size.height}px`;
1830
+ pet.style.transform = `translate3d(${position.x}px, ${position.y}px, 0)`;
1831
+ pet.style.cursor = this.options.position.draggable ? this.isDragging ? "grabbing" : "grab" : "default";
1832
+ pet.dataset.petAnimation = animationName;
1833
+ pet.setAttribute("aria-label", this.options.ariaLabel);
1834
+ pet.setAttribute("role", "img");
1835
+ this.renderAtlas(animationName, animationMode);
1836
+ this.renderThreadSummary(position, size);
1837
+ this.scheduleNextFrame(animationName, animationMode);
1838
+ }
1839
+ renderThreadSummary(position, size) {
1840
+ var _a2, _b2, _c2;
1841
+ const summary = this.summary;
1842
+ const summaryKey = getThreadSummaryKey(summary);
1843
+ if (!summary || !summaryKey || this.dismissedSummaryKey === summaryKey) {
1844
+ this.removeSummaryElements();
1845
+ return;
1846
+ }
1847
+ if (this.isSummaryCollapsed) {
1848
+ this.renderCollapsedSummary(position, size);
1849
+ return;
1850
+ }
1851
+ const nextRenderKey = [
1852
+ summaryKey,
1853
+ summary.title,
1854
+ summary.message,
1855
+ summary.status,
1856
+ this.copyLocale,
1857
+ this.isSummaryExpanded ? "expanded" : "compact",
1858
+ this.isSummaryHovering ? "hover" : "rest",
1859
+ this.isReplyOpen ? "reply" : "closed",
1860
+ this.isReplySubmitting ? "submitting" : "ready",
1861
+ this.replyError ?? ""
1862
+ ].join("|");
1863
+ if (!this.summaryElement || this.summaryRenderKey !== nextRenderKey) {
1864
+ (_a2 = this.summaryElement) == null ? void 0 : _a2.remove();
1865
+ (_b2 = this.summaryToggleElement) == null ? void 0 : _b2.remove();
1866
+ this.summaryElement = this.createSummaryBubble(summary);
1867
+ this.summaryToggleElement = this.createSummaryToggleButton("v");
1868
+ (_c2 = this.overlayElement) == null ? void 0 : _c2.append(this.summaryElement, this.summaryToggleElement);
1869
+ this.summaryRenderKey = nextRenderKey;
1870
+ if (this.isReplyOpen && !this.isReplySubmitting) {
1871
+ window.setTimeout(() => {
1872
+ var _a3;
1873
+ return (_a3 = this.replyInputElement) == null ? void 0 : _a3.focus();
1874
+ }, 0);
1875
+ }
1876
+ }
1877
+ this.positionSummaryBubble(position, size);
1878
+ }
1879
+ renderCollapsedSummary(position, size) {
1880
+ var _a2, _b2;
1881
+ (_a2 = this.summaryElement) == null ? void 0 : _a2.remove();
1882
+ this.summaryElement = null;
1883
+ this.summaryRenderKey = null;
1884
+ if (!this.summaryToggleElement) {
1885
+ this.summaryToggleElement = this.createSummaryToggleButton("1");
1886
+ (_b2 = this.overlayElement) == null ? void 0 : _b2.append(this.summaryToggleElement);
1887
+ }
1888
+ this.summaryToggleElement.textContent = "1";
1889
+ this.positionSummaryToggleBadge(position, size);
1890
+ }
1891
+ positionSummaryToggleBadge(position, size) {
1892
+ const badge = this.summaryToggleElement;
1893
+ if (!badge) {
1894
+ return;
1895
+ }
1896
+ const viewport = getViewportSize();
1897
+ const badgeSize = 34;
1898
+ const x = clampNumber(
1899
+ position.x + size.width - badgeSize * 0.35,
1900
+ PET_SUMMARY_MARGIN,
1901
+ viewport.width - badgeSize - PET_SUMMARY_MARGIN
1902
+ );
1903
+ const y = clampNumber(
1904
+ position.y - badgeSize * 0.35,
1905
+ PET_SUMMARY_MARGIN,
1906
+ viewport.height - badgeSize - PET_SUMMARY_MARGIN
1907
+ );
1908
+ badge.style.width = `${badgeSize}px`;
1909
+ badge.style.height = `${badgeSize}px`;
1910
+ badge.style.transform = `translate3d(${x}px, ${y}px, 0)`;
1911
+ badge.style.borderRadius = "999px";
1912
+ }
1913
+ positionSummaryBubble(position, size) {
1914
+ const bubble = this.summaryElement;
1915
+ const toggle = this.summaryToggleElement;
1916
+ if (!bubble || !toggle) {
1917
+ return;
1918
+ }
1919
+ const viewport = getViewportSize();
1920
+ const width = Math.min(PET_SUMMARY_WIDTH, viewport.width - PET_SUMMARY_MARGIN * 2);
1921
+ bubble.style.width = `${width}px`;
1922
+ const bubbleHeight = bubble.offsetHeight || 96;
1923
+ const aboveY = position.y - bubbleHeight - PET_SUMMARY_GAP;
1924
+ const showAbove = aboveY >= PET_SUMMARY_MARGIN;
1925
+ const y = showAbove ? aboveY : clampNumber(
1926
+ position.y + size.height + PET_SUMMARY_GAP,
1927
+ PET_SUMMARY_MARGIN,
1928
+ viewport.height - bubbleHeight - PET_SUMMARY_MARGIN
1929
+ );
1930
+ const x = clampNumber(
1931
+ position.x + size.width / 2 - width / 2,
1932
+ PET_SUMMARY_MARGIN,
1933
+ viewport.width - width - PET_SUMMARY_MARGIN
1934
+ );
1935
+ bubble.style.transform = `translate3d(${x}px, ${y}px, 0)`;
1936
+ this.positionSummaryToggleBadge(position, size);
1937
+ }
1938
+ createSummaryBubble(summary) {
1939
+ const shouldShowReplyButton = this.isSummaryHovering && !this.isReplyOpen;
1940
+ const bubble = document.createElement("div");
1941
+ bubble.setAttribute("data-chatkit-pet-summary", "");
1942
+ bubble.addEventListener("pointerenter", this.handleSummaryPointerEnter);
1943
+ bubble.addEventListener("pointerleave", this.handleSummaryPointerLeave);
1944
+ bubble.addEventListener("click", this.handleSummaryClick);
1945
+ bubble.style.position = "absolute";
1946
+ bubble.style.top = "0";
1947
+ bubble.style.left = "0";
1948
+ bubble.style.boxSizing = "border-box";
1949
+ bubble.style.pointerEvents = "auto";
1950
+ bubble.style.padding = "12px 14px";
1951
+ bubble.style.paddingBottom = "12px";
1952
+ bubble.style.border = "1px solid rgba(148, 163, 184, 0.22)";
1953
+ bubble.style.borderRadius = "22px";
1954
+ bubble.style.background = "rgba(255, 255, 255, 0.94)";
1955
+ bubble.style.color = "#1f2937";
1956
+ bubble.style.boxShadow = "0 8px 24px rgba(15, 23, 42, 0.1)";
1957
+ bubble.style.font = '500 14px/1.35 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
1958
+ bubble.style.backdropFilter = "blur(10px)";
1959
+ const header = document.createElement("div");
1960
+ header.style.display = "flex";
1961
+ header.style.alignItems = "center";
1962
+ header.style.gap = "8px";
1963
+ if (this.isSummaryHovering || this.isReplyOpen) {
1964
+ header.append(
1965
+ this.createSummaryActionButton(
1966
+ "x",
1967
+ this.copy.hideMessage,
1968
+ this.handleSummaryDelete
1969
+ )
1970
+ );
1971
+ }
1972
+ const title = document.createElement("div");
1973
+ title.textContent = summary.title;
1974
+ title.style.minWidth = "0";
1975
+ title.style.flex = "1";
1976
+ title.style.overflow = "hidden";
1977
+ title.style.textOverflow = "ellipsis";
1978
+ title.style.whiteSpace = "nowrap";
1979
+ title.style.fontWeight = "700";
1980
+ title.style.fontSize = "15px";
1981
+ header.append(title);
1982
+ if (this.isSummaryHovering || this.isReplyOpen) {
1983
+ header.append(
1984
+ this.createSummaryActionButton(
1985
+ this.isSummaryExpanded ? "-" : ">",
1986
+ this.isSummaryExpanded ? this.copy.collapseMessage : this.copy.expandMessage,
1987
+ this.handleSummaryExpandToggle
1988
+ )
1989
+ );
1990
+ } else {
1991
+ header.append(this.createStatusIcon(summary.status));
1992
+ }
1993
+ const message = document.createElement("div");
1994
+ message.textContent = summary.message;
1995
+ message.style.marginTop = "4px";
1996
+ message.style.fontWeight = "400";
1997
+ message.style.color = "#374151";
1998
+ message.style.overflow = "hidden";
1999
+ if (this.isSummaryExpanded) {
2000
+ message.style.maxHeight = "7em";
2001
+ message.style.overflowY = "auto";
2002
+ } else {
2003
+ message.style.display = "-webkit-box";
2004
+ message.style.setProperty("-webkit-line-clamp", "2");
2005
+ message.style.setProperty("-webkit-box-orient", "vertical");
2006
+ }
2007
+ bubble.append(header, message);
2008
+ if (shouldShowReplyButton) {
2009
+ const reply = this.createTextButton(
2010
+ this.copy.replyButton,
2011
+ this.handleReplyOpen
2012
+ );
2013
+ reply.style.position = "absolute";
2014
+ reply.style.right = "14px";
2015
+ reply.style.bottom = "10px";
2016
+ bubble.append(reply);
2017
+ }
2018
+ if (this.isReplyOpen) {
2019
+ bubble.append(this.createReplyForm());
2020
+ }
2021
+ return bubble;
2022
+ }
2023
+ createSummaryToggleButton(label) {
2024
+ const button = document.createElement("button");
2025
+ button.type = "button";
2026
+ button.textContent = label;
2027
+ button.title = label === "1" ? this.copy.restoreMessage : this.copy.collapseMessage;
2028
+ button.addEventListener("click", stopEventPropagation);
2029
+ button.addEventListener("click", this.handleSummaryCollapseToggle);
2030
+ button.style.position = "absolute";
2031
+ button.style.top = "0";
2032
+ button.style.left = "0";
2033
+ button.style.pointerEvents = "auto";
2034
+ button.style.border = "1px solid rgba(148, 163, 184, 0.28)";
2035
+ button.style.background = "rgba(248, 250, 252, 0.94)";
2036
+ button.style.color = "#475569";
2037
+ button.style.boxShadow = "0 6px 18px rgba(15, 23, 42, 0.1)";
2038
+ button.style.cursor = "pointer";
2039
+ button.style.font = '600 15px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2040
+ button.style.display = "flex";
2041
+ button.style.alignItems = "center";
2042
+ button.style.justifyContent = "center";
2043
+ return button;
2044
+ }
2045
+ createStatusIcon(status) {
2046
+ const icon = document.createElement("span");
2047
+ icon.setAttribute("aria-hidden", "true");
2048
+ icon.style.display = "inline-flex";
2049
+ icon.style.width = "16px";
2050
+ icon.style.height = "16px";
2051
+ icon.style.alignItems = "center";
2052
+ icon.style.justifyContent = "center";
2053
+ icon.style.flex = "0 0 auto";
2054
+ if (status === "running") {
2055
+ icon.style.border = "2px solid rgba(71, 85, 105, 0.32)";
2056
+ icon.style.borderTopColor = "#64748b";
2057
+ icon.style.borderRadius = "999px";
2058
+ icon.style.animation = "chatkit-pet-summary-spin 900ms linear infinite";
2059
+ return icon;
2060
+ }
2061
+ icon.style.borderRadius = "999px";
2062
+ icon.style.fontSize = "12px";
2063
+ icon.style.fontWeight = "700";
2064
+ if (status === "failed") {
2065
+ icon.textContent = "!";
2066
+ icon.style.background = "#fee2e2";
2067
+ icon.style.color = "#b91c1c";
2068
+ return icon;
2069
+ }
2070
+ icon.textContent = "";
2071
+ icon.style.border = "2px solid #22c55e";
2072
+ icon.style.position = "relative";
2073
+ const check = document.createElement("span");
2074
+ check.style.width = "7px";
2075
+ check.style.height = "4px";
2076
+ check.style.borderLeft = "2px solid #22c55e";
2077
+ check.style.borderBottom = "2px solid #22c55e";
2078
+ check.style.transform = "rotate(-45deg) translate(1px, -1px)";
2079
+ icon.append(check);
2080
+ return icon;
2081
+ }
2082
+ createSummaryActionButton(label, title, onClick) {
2083
+ const button = document.createElement("button");
2084
+ button.type = "button";
2085
+ button.textContent = label;
2086
+ button.title = title;
2087
+ button.addEventListener("click", (event) => {
2088
+ event.preventDefault();
2089
+ event.stopPropagation();
2090
+ onClick();
2091
+ });
2092
+ button.style.width = "26px";
2093
+ button.style.height = "26px";
2094
+ button.style.border = "0";
2095
+ button.style.borderRadius = "999px";
2096
+ button.style.background = "rgba(241, 245, 249, 0.96)";
2097
+ button.style.color = "#475569";
2098
+ button.style.cursor = "pointer";
2099
+ button.style.font = '600 15px/1 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2100
+ return button;
2101
+ }
2102
+ createTextButton(label, onClick) {
2103
+ const button = document.createElement("button");
2104
+ button.type = "button";
2105
+ button.textContent = label;
2106
+ button.addEventListener("click", (event) => {
2107
+ event.preventDefault();
2108
+ event.stopPropagation();
2109
+ onClick();
2110
+ });
2111
+ button.style.border = "1px solid rgba(148, 163, 184, 0.28)";
2112
+ button.style.borderRadius = "999px";
2113
+ button.style.background = "rgba(248, 250, 252, 0.95)";
2114
+ button.style.color = "#334155";
2115
+ button.style.cursor = "pointer";
2116
+ button.style.padding = "3px 10px";
2117
+ button.style.font = '600 12px/1.4 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2118
+ return button;
2119
+ }
2120
+ createReplyForm() {
2121
+ const form = document.createElement("form");
2122
+ form.addEventListener("click", stopEventPropagation);
2123
+ form.addEventListener("submit", this.handleReplySubmit);
2124
+ form.addEventListener("keydown", this.handleReplyKeyDown);
2125
+ form.style.display = "flex";
2126
+ form.style.gap = "6px";
2127
+ form.style.alignItems = "center";
2128
+ form.style.marginTop = "8px";
2129
+ const input = document.createElement("input");
2130
+ input.type = "text";
2131
+ input.value = this.replyDraft;
2132
+ input.disabled = this.isReplySubmitting;
2133
+ input.placeholder = this.copy.replyPlaceholder;
2134
+ input.addEventListener("input", this.handleReplyInput);
2135
+ input.style.minWidth = "0";
2136
+ input.style.flex = "1";
2137
+ input.style.border = "1px solid rgba(148, 163, 184, 0.35)";
2138
+ input.style.borderRadius = "999px";
2139
+ input.style.padding = "6px 10px";
2140
+ input.style.font = '400 13px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2141
+ this.replyInputElement = input;
2142
+ const send = document.createElement("button");
2143
+ send.type = "submit";
2144
+ send.textContent = this.isReplySubmitting ? this.copy.sendingButton : this.copy.sendButton;
2145
+ send.disabled = this.isReplySubmitting;
2146
+ send.style.border = "0";
2147
+ send.style.borderRadius = "999px";
2148
+ send.style.background = "#22c55e";
2149
+ send.style.color = "#052e16";
2150
+ send.style.cursor = this.isReplySubmitting ? "default" : "pointer";
2151
+ send.style.padding = "6px 10px";
2152
+ send.style.font = '700 12px/1.2 system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif';
2153
+ form.append(input, send);
2154
+ if (this.replyError) {
2155
+ const error = document.createElement("div");
2156
+ error.textContent = this.copy.sendFailed;
2157
+ error.style.flexBasis = "100%";
2158
+ error.style.color = "#b91c1c";
2159
+ error.style.fontSize = "12px";
2160
+ form.style.flexWrap = "wrap";
2161
+ form.append(error);
2162
+ }
2163
+ return form;
2164
+ }
2165
+ renderAtlas(animationName, animationMode) {
2166
+ var _a2;
2167
+ if (!this.petElement || ((_a2 = this.resolved) == null ? void 0 : _a2.kind) !== "atlas" || !this.options) {
2168
+ return;
2169
+ }
2170
+ if (!(this.mediaElement instanceof HTMLDivElement)) {
2171
+ const frame = document.createElement("div");
2172
+ frame.setAttribute("aria-hidden", "true");
2173
+ this.petElement.replaceChildren(frame);
2174
+ this.mediaElement = frame;
2175
+ }
2176
+ const frameElement = this.mediaElement;
2177
+ const atlas = this.resolved.atlas;
2178
+ const definition = atlas.animations[animationName] ?? atlas.animations.idle;
2179
+ const safeFrame = animationMode === "once" && this.completed ? Math.max(0, definition.frames - 1) : Math.min(this.frame, Math.max(0, definition.frames - 1));
2180
+ const scale = getRenderScale(this.options.position.scale);
2181
+ const sourceWidth = atlas.cellWidth;
2182
+ const sourceHeight = atlas.cellHeight;
2183
+ const backgroundWidth = atlas.columns * sourceWidth;
2184
+ const backgroundHeight = atlas.rows * sourceHeight;
2185
+ frameElement.style.width = `${sourceWidth}px`;
2186
+ frameElement.style.height = `${sourceHeight}px`;
2187
+ frameElement.style.overflow = "hidden";
2188
+ frameElement.style.transform = `scale(${scale})`;
2189
+ frameElement.style.transformOrigin = "top left";
2190
+ frameElement.style.pointerEvents = "none";
2191
+ frameElement.style.backgroundImage = `url("${escapeCssUrl(
2192
+ this.resolved.src
2193
+ )}")`;
2194
+ frameElement.style.backgroundRepeat = "no-repeat";
2195
+ frameElement.style.backgroundSize = `${backgroundWidth}px ${backgroundHeight}px`;
2196
+ frameElement.style.backgroundPosition = `${-safeFrame * sourceWidth}px ${-definition.row * sourceHeight}px`;
2197
+ frameElement.style.imageRendering = this.options.imageRendering;
2198
+ frameElement.dataset.petFrame = String(safeFrame);
2199
+ }
2200
+ scheduleNextFrame(animationName, animationMode) {
2201
+ if (this.prefersReducedMotion || this.completed || !this.resolved) {
2202
+ this.clearTimers();
2203
+ return;
2204
+ }
2205
+ if (this.frameTimer !== null) {
2206
+ return;
2207
+ }
2208
+ const atlas = this.resolved.atlas;
2209
+ const definition = atlas.animations[animationName] ?? atlas.animations.idle;
2210
+ const duration = definition.frameDurations[this.frame] ?? definition.frameDurations[definition.frameDurations.length - 1] ?? 150;
2211
+ const baseDuration = duration * PET_FRAME_DURATION_MULTIPLIER;
2212
+ const effectiveDuration = this.isHovering || this.isDragging ? baseDuration : baseDuration * PET_RESTING_FRAME_DURATION_MULTIPLIER;
2213
+ this.frameTimer = window.setTimeout(() => {
2214
+ this.frameTimer = null;
2215
+ const nextFrame = this.frame + 1;
2216
+ if (nextFrame >= definition.frames) {
2217
+ if (animationMode === "once") {
2218
+ this.completed = true;
2219
+ this.frame = Math.max(0, definition.frames - 1);
2220
+ this.finishTransient();
2221
+ return;
2222
+ }
2223
+ this.frame = 0;
2224
+ this.render();
2225
+ return;
2226
+ }
2227
+ this.frame = nextFrame;
2228
+ this.render();
2229
+ }, effectiveDuration);
2230
+ }
2231
+ clearTimers() {
2232
+ if (this.frameTimer !== null) {
2233
+ window.clearTimeout(this.frameTimer);
2234
+ this.frameTimer = null;
2235
+ }
2236
+ }
2237
+ clearRestingDelayTimer() {
2238
+ if (this.restingDelayTimer !== null) {
2239
+ window.clearTimeout(this.restingDelayTimer);
2240
+ this.restingDelayTimer = null;
2241
+ }
2242
+ }
2243
+ finishTransient() {
2244
+ this.transient = null;
2245
+ this.activeAnimationName = null;
2246
+ this.activeAnimationMode = null;
2247
+ this.render();
2248
+ }
2249
+ rescheduleAnimation() {
2250
+ this.clearTimers();
2251
+ this.render();
2252
+ }
2253
+ enterRestingAfterDelay() {
2254
+ this.clearRestingDelayTimer();
2255
+ this.isHovering = true;
2256
+ this.restingDelayTimer = window.setTimeout(() => {
2257
+ this.restingDelayTimer = null;
2258
+ if (this.isDragging) {
2259
+ return;
2260
+ }
2261
+ this.isHovering = false;
2262
+ this.rescheduleAnimation();
2263
+ }, PET_RESTING_DELAY_MS);
2264
+ }
2265
+ isPointerOverPet(event) {
2266
+ var _a2;
2267
+ const rect = (_a2 = this.petElement) == null ? void 0 : _a2.getBoundingClientRect();
2268
+ if (!rect) {
2269
+ return false;
2270
+ }
2271
+ return event.clientX >= rect.left && event.clientX <= rect.right && event.clientY >= rect.top && event.clientY <= rect.bottom;
2272
+ }
2273
+ async submitReply() {
2274
+ var _a2;
2275
+ const text = this.replyDraft.trim();
2276
+ if (!text || this.isReplySubmitting) {
2277
+ return;
2278
+ }
2279
+ this.isReplySubmitting = true;
2280
+ this.replyError = null;
2281
+ this.render();
2282
+ try {
2283
+ await ((_a2 = this.onReply) == null ? void 0 : _a2.call(this, text));
2284
+ this.replyDraft = "";
2285
+ this.isReplyOpen = false;
2286
+ this.isSummaryHovering = false;
2287
+ } catch {
2288
+ this.replyError = "Failed to send";
2289
+ } finally {
2290
+ this.isReplySubmitting = false;
2291
+ this.render();
2292
+ }
2293
+ }
2294
+ getNextDragPosition(event) {
2295
+ if (!this.options) {
2296
+ return { x: 0, y: 0 };
2297
+ }
2298
+ return clampPetPosition(
2299
+ {
2300
+ x: event.clientX - this.dragOffset.x,
2301
+ y: event.clientY - this.dragOffset.y
2302
+ },
2303
+ this.getSize(),
2304
+ getViewportSize(),
2305
+ normalizeBoundsPadding(this.options.position.boundsPadding)
2306
+ );
2307
+ }
2308
+ installDragListeners() {
2309
+ window.addEventListener("pointermove", this.handlePointerMove);
2310
+ window.addEventListener("pointerup", this.handlePointerUp, { once: true });
2311
+ window.addEventListener("pointercancel", this.handlePointerUp, {
2312
+ once: true
2313
+ });
2314
+ }
2315
+ removeDragListeners() {
2316
+ window.removeEventListener("pointermove", this.handlePointerMove);
2317
+ window.removeEventListener("pointerup", this.handlePointerUp);
2318
+ window.removeEventListener("pointercancel", this.handlePointerUp);
2319
+ }
2320
+ }
890
2321
  function getInnerOptions(options) {
891
2322
  return removeMethods(options);
892
2323
  }
@@ -910,7 +2341,15 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
910
2341
  __privateAdd(this, _frameUrl);
911
2342
  __privateAdd(this, _frame);
912
2343
  __privateAdd(this, _wrapper);
2344
+ __privateAdd(this, _launcherCloseButton);
2345
+ __privateAdd(this, _launcherOpen, false);
2346
+ __privateAdd(this, _framePetOptionsOverride);
913
2347
  __privateAdd(this, _shadow, this.attachShadow({ mode: "open" }));
2348
+ __privateAdd(this, _petOverlay, new PetOverlay(__privateGet(this, _shadow), {
2349
+ onActivate: () => __privateMethod(this, _ChatKitElementBase_instances, handlePetActivate_fn).call(this),
2350
+ onReply: (text) => __privateMethod(this, _ChatKitElementBase_instances, handlePetReply_fn).call(this, text),
2351
+ onThreadSummaryActivate: (threadId) => void __privateMethod(this, _ChatKitElementBase_instances, handlePetThreadSummaryActivate_fn).call(this, threadId)
2352
+ }));
914
2353
  __privateAdd(this, _resolveLoaded);
915
2354
  __privateAdd(this, _loaded, new Promise((resolve) => {
916
2355
  __privateSet(this, _resolveLoaded, resolve);
@@ -1005,6 +2444,9 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1005
2444
  }
1006
2445
  }
1007
2446
  }));
2447
+ __privateAdd(this, _handleLauncherClose, () => {
2448
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, false);
2449
+ });
1008
2450
  __privateAdd(this, _handleFrameLoad, () => {
1009
2451
  var _a2;
1010
2452
  this.dataset.loaded = "true";
@@ -1022,6 +2464,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1022
2464
  this.capabilities = getCapabilities(profile);
1023
2465
  }
1024
2466
  connectedCallback() {
2467
+ __privateGet(this, _petOverlay).connect();
1025
2468
  const style = document.createElement("style");
1026
2469
  style.textContent = `
1027
2470
  :host {
@@ -1029,6 +2472,10 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1029
2472
  position: relative;
1030
2473
  height: 100%;
1031
2474
  width: 100%;
2475
+ overflow: visible;
2476
+ }
2477
+ :host([data-display-mode="pet"]) {
2478
+ display: contents;
1032
2479
  }
1033
2480
  .ck-iframe {
1034
2481
  border: none;
@@ -1047,12 +2494,115 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1047
2494
  overflow: hidden;
1048
2495
  opacity: 0;
1049
2496
  }
2497
+ .ck-launcher-close {
2498
+ display: none;
2499
+ }
2500
+ :host([data-display-mode="pet"]) .ck-wrapper {
2501
+ position: fixed;
2502
+ inset: auto 16px 16px auto;
2503
+ width: min(420px, calc(100vw - 32px));
2504
+ height: min(720px, calc(100vh - 32px));
2505
+ max-height: calc(100vh - 32px);
2506
+ overflow: visible;
2507
+ border: 1px solid rgba(148, 163, 184, 0.35);
2508
+ border-radius: 18px;
2509
+ background: Canvas;
2510
+ box-shadow:
2511
+ 0 24px 80px rgba(15, 23, 42, 0.22),
2512
+ 0 0 0 1px rgba(15, 23, 42, 0.04);
2513
+ opacity: 0;
2514
+ pointer-events: none;
2515
+ transform: translateY(12px) scale(0.98);
2516
+ transition:
2517
+ opacity 160ms ease,
2518
+ transform 160ms ease;
2519
+ z-index: 39;
2520
+ }
2521
+ :host([data-display-mode="pet"][data-chat-open="true"]) .ck-wrapper {
2522
+ opacity: 1;
2523
+ pointer-events: auto;
2524
+ transform: translateY(0) scale(1);
2525
+ }
2526
+ :host([data-display-mode="pet"]) .ck-iframe {
2527
+ border-radius: inherit;
2528
+ }
2529
+ :host([data-display-mode="pet"]) .ck-launcher-close {
2530
+ display: inline-flex;
2531
+ position: absolute;
2532
+ top: -10px;
2533
+ right: -10px;
2534
+ z-index: 2;
2535
+ width: 28px;
2536
+ height: 28px;
2537
+ align-items: center;
2538
+ justify-content: center;
2539
+ border: 1px solid rgba(148, 163, 184, 0.45);
2540
+ border-radius: 999px;
2541
+ background: rgba(255, 255, 255, 0.96);
2542
+ color: #475569;
2543
+ box-shadow: 0 8px 24px rgba(15, 23, 42, 0.18);
2544
+ cursor: pointer;
2545
+ font: inherit;
2546
+ font-size: 0;
2547
+ line-height: 1;
2548
+ }
2549
+ :host([data-display-mode="pet"]) .ck-launcher-close::before,
2550
+ :host([data-display-mode="pet"]) .ck-launcher-close::after {
2551
+ content: '';
2552
+ position: absolute;
2553
+ top: 50%;
2554
+ left: 50%;
2555
+ width: 14px;
2556
+ height: 2px;
2557
+ border-radius: 999px;
2558
+ background: currentColor;
2559
+ transform: translate(-50%, -50%) rotate(45deg);
2560
+ }
2561
+ :host([data-display-mode="pet"]) .ck-launcher-close::after {
2562
+ transform: translate(-50%, -50%) rotate(-45deg);
2563
+ }
2564
+ :host([data-display-mode="pet"]) .ck-launcher-close:hover {
2565
+ background: #fff;
2566
+ color: #0f172a;
2567
+ }
1050
2568
  :host([data-color-scheme="dark"]) .ck-iframe {
1051
2569
  color-scheme: dark only;
1052
2570
  }
2571
+ :host([data-color-scheme="dark"][data-display-mode="pet"]) .ck-wrapper {
2572
+ border-color: rgba(148, 163, 184, 0.28);
2573
+ background: #020617;
2574
+ box-shadow:
2575
+ 0 24px 80px rgba(0, 0, 0, 0.5),
2576
+ 0 0 0 1px rgba(255, 255, 255, 0.06);
2577
+ }
2578
+ :host([data-color-scheme="dark"][data-display-mode="pet"]) .ck-launcher-close {
2579
+ background: rgba(15, 23, 42, 0.88);
2580
+ border-color: rgba(148, 163, 184, 0.32);
2581
+ color: #cbd5e1;
2582
+ }
2583
+ :host([data-color-scheme="dark"][data-display-mode="pet"]) .ck-launcher-close:hover {
2584
+ background: #1e293b;
2585
+ color: #f8fafc;
2586
+ }
1053
2587
  :host([data-loaded="true"]) .ck-wrapper {
1054
2588
  opacity: 1;
1055
2589
  }
2590
+ :host([data-display-mode="pet"]:not([data-chat-open="true"])) .ck-wrapper {
2591
+ opacity: 0;
2592
+ }
2593
+ @media (max-width: 520px) {
2594
+ :host([data-display-mode="pet"]) .ck-wrapper {
2595
+ inset: auto 8px 8px 8px;
2596
+ width: auto;
2597
+ height: min(680px, calc(100vh - 16px));
2598
+ max-height: calc(100vh - 16px);
2599
+ border-radius: 16px;
2600
+ }
2601
+ :host([data-display-mode="pet"]) .ck-launcher-close {
2602
+ top: -8px;
2603
+ right: 8px;
2604
+ }
2605
+ }
1056
2606
  `;
1057
2607
  const frame = document.createElement("iframe");
1058
2608
  frame.className = "ck-iframe";
@@ -1068,6 +2618,13 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1068
2618
  wrapper.className = "ck-wrapper";
1069
2619
  wrapper.appendChild(frame);
1070
2620
  __privateSet(this, _wrapper, wrapper);
2621
+ const closeButton = document.createElement("button");
2622
+ closeButton.className = "ck-launcher-close";
2623
+ closeButton.type = "button";
2624
+ closeButton.setAttribute("aria-label", "Close chat");
2625
+ closeButton.addEventListener("click", __privateGet(this, _handleLauncherClose));
2626
+ wrapper.appendChild(closeButton);
2627
+ __privateSet(this, _launcherCloseButton, closeButton);
1071
2628
  __privateGet(this, _shadow).append(style);
1072
2629
  __privateGet(this, _messenger).on("left_header_icon_click", () => {
1073
2630
  var _a2, _b2, _c2;
@@ -1078,6 +2635,18 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1078
2635
  (_c2 = (_b2 = (_a2 = __privateGet(this, _opts)) == null ? void 0 : _a2.header) == null ? void 0 : _b2.rightAction) == null ? void 0 : _c2.onClick();
1079
2636
  });
1080
2637
  __privateGet(this, _messenger).on("public_event", ([event, data]) => {
2638
+ if (event === "log") {
2639
+ const payload = parseThreadSummaryLogPayload(data);
2640
+ if (payload) {
2641
+ __privateGet(this, _petOverlay).setThreadSummary(payload.summary);
2642
+ }
2643
+ } else if (event === "response.start") {
2644
+ __privateGet(this, _petOverlay).setThreadSummaryStatus("running");
2645
+ } else if (event === "response.end") {
2646
+ __privateGet(this, _petOverlay).setThreadSummaryStatus("completed");
2647
+ } else if (event === "response.stop") {
2648
+ __privateGet(this, _petOverlay).setThreadSummaryStatus("completed");
2649
+ }
1081
2650
  if (!this.capabilities.events.has(event)) return;
1082
2651
  if (event === "error" && "error" in data) {
1083
2652
  const error = fromPossibleFrameSafeError(data.error);
@@ -1091,6 +2660,19 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1091
2660
  }
1092
2661
  this.dispatchEvent(new CustomEvent(`chatkit.${event}`, { detail: data }));
1093
2662
  });
2663
+ __privateGet(this, _messenger).on("pet_state_change", (data) => {
2664
+ const payload = parsePetStateChangePayload(data);
2665
+ if (payload) {
2666
+ __privateGet(this, _petOverlay).setState(payload.state);
2667
+ }
2668
+ });
2669
+ __privateGet(this, _messenger).on("pet_options_change", (data) => {
2670
+ const payload = parsePetOptionsChangePayload(data);
2671
+ if (payload) {
2672
+ __privateSet(this, _framePetOptionsOverride, payload.pet);
2673
+ __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
2674
+ }
2675
+ });
1094
2676
  __privateGet(this, _messenger).on("unmount", () => {
1095
2677
  if (__privateGet(this, _wrapper) && __privateGet(this, _shadow).contains(__privateGet(this, _wrapper))) {
1096
2678
  __privateGet(this, _shadow).removeChild(__privateGet(this, _wrapper));
@@ -1113,16 +2695,25 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1113
2695
  }
1114
2696
  }
1115
2697
  disconnectedCallback() {
1116
- var _a2;
2698
+ var _a2, _b2;
1117
2699
  (_a2 = __privateGet(this, _frame)) == null ? void 0 : _a2.removeEventListener("load", __privateGet(this, _handleFrameLoad));
2700
+ (_b2 = __privateGet(this, _launcherCloseButton)) == null ? void 0 : _b2.removeEventListener(
2701
+ "click",
2702
+ __privateGet(this, _handleLauncherClose)
2703
+ );
1118
2704
  __privateGet(this, _messenger).disconnect();
2705
+ __privateGet(this, _petOverlay).destroy();
1119
2706
  }
1120
2707
  applySanitizedOptions(newOptions) {
1121
2708
  __privateSet(this, _opts, newOptions);
2709
+ __privateGet(this, _petOverlay).setLocale(newOptions.locale);
2710
+ __privateGet(this, _petOverlay).setOptions(__privateMethod(this, _ChatKitElementBase_instances, getOverlayPetOptions_fn).call(this));
1122
2711
  if (__privateGet(this, _initialized)) {
1123
2712
  __privateMethod(this, _ChatKitElementBase_instances, setOptionsDataAttributes_fn).call(this, __privateGet(this, _opts));
1124
2713
  __privateGet(this, _loaded).then(() => {
1125
- __privateGet(this, _messenger).commands.setOptions(getInnerOptions(newOptions));
2714
+ __privateGet(this, _messenger).commands.setOptions(
2715
+ getInnerOptions(__privateMethod(this, _ChatKitElementBase_instances, getFrameOptions_fn).call(this, newOptions))
2716
+ );
1126
2717
  });
1127
2718
  } else {
1128
2719
  __privateMethod(this, _ChatKitElementBase_instances, maybeInit_fn).call(this);
@@ -1194,7 +2785,11 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1194
2785
  _frameUrl = new WeakMap();
1195
2786
  _frame = new WeakMap();
1196
2787
  _wrapper = new WeakMap();
2788
+ _launcherCloseButton = new WeakMap();
2789
+ _launcherOpen = new WeakMap();
2790
+ _framePetOptionsOverride = new WeakMap();
1197
2791
  _shadow = new WeakMap();
2792
+ _petOverlay = new WeakMap();
1198
2793
  _resolveLoaded = new WeakMap();
1199
2794
  _loaded = new WeakMap();
1200
2795
  _messenger = new WeakMap();
@@ -1206,7 +2801,96 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1206
2801
  setOptionsDataAttributes_fn = function(options) {
1207
2802
  var _a2;
1208
2803
  this.dataset.colorScheme = typeof options.theme === "string" ? options.theme : ((_a2 = options.theme) == null ? void 0 : _a2.colorScheme) ?? "light";
2804
+ this.dataset.displayMode = __privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this, options);
2805
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this, options) !== "pet") {
2806
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, false);
2807
+ }
2808
+ };
2809
+ getDisplayMode_fn = function(options = __privateGet(this, _opts)) {
2810
+ return (options == null ? void 0 : options.displayMode) === "pet" ? "pet" : "chat";
2811
+ };
2812
+ getConfiguredPetOptions_fn = function(options = __privateGet(this, _opts)) {
2813
+ if (!options) {
2814
+ return null;
2815
+ }
2816
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this, options) === "pet" && !normalizePetOptions(options.pet ?? null)) {
2817
+ return true;
2818
+ }
2819
+ return options.pet ?? null;
2820
+ };
2821
+ getOverlayPetOptions_fn = function() {
2822
+ let pet = __privateGet(this, _framePetOptionsOverride) !== void 0 ? __privateGet(this, _framePetOptionsOverride) : __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this);
2823
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet" && !normalizePetOptions(pet ?? null)) {
2824
+ pet = true;
2825
+ }
2826
+ return __privateMethod(this, _ChatKitElementBase_instances, resolveOverlayPetOptions_fn).call(this, pet);
2827
+ };
2828
+ resolvePetAssetUrl_fn = function(src) {
2829
+ try {
2830
+ const base = new URL(
2831
+ __privateGet(this, _frameUrl) ?? window.location.href,
2832
+ window.location.origin
2833
+ );
2834
+ return new URL(src, base).toString();
2835
+ } catch {
2836
+ return src;
2837
+ }
2838
+ };
2839
+ resolveOverlayPetOptions_fn = function(pet) {
2840
+ const normalized = normalizePetOptions(pet ?? null);
2841
+ if (!normalized) {
2842
+ return null;
2843
+ }
2844
+ return {
2845
+ character: {
2846
+ ...normalized.character,
2847
+ src: __privateMethod(this, _ChatKitElementBase_instances, resolvePetAssetUrl_fn).call(this, normalized.character.src)
2848
+ },
2849
+ position: normalized.position,
2850
+ behavior: normalized.behavior,
2851
+ ariaLabel: normalized.ariaLabel,
2852
+ imageRendering: normalized.imageRendering
2853
+ };
2854
+ };
2855
+ getFrameOptions_fn = function(options) {
2856
+ const pet = __privateMethod(this, _ChatKitElementBase_instances, getConfiguredPetOptions_fn).call(this, options);
2857
+ if (pet === (options.pet ?? null)) {
2858
+ return options;
2859
+ }
2860
+ const nextOptions = { ...options };
2861
+ if (pet === null) {
2862
+ delete nextOptions.pet;
2863
+ } else {
2864
+ nextOptions.pet = pet;
2865
+ }
2866
+ return nextOptions;
2867
+ };
2868
+ setLauncherOpen_fn = function(open) {
2869
+ __privateSet(this, _launcherOpen, open);
2870
+ if (open) {
2871
+ this.dataset.chatOpen = "true";
2872
+ } else {
2873
+ delete this.dataset.chatOpen;
2874
+ }
2875
+ };
2876
+ handlePetActivate_fn = function() {
2877
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) !== "pet") {
2878
+ return;
2879
+ }
2880
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, true);
2881
+ __privateGet(this, _loaded).then(() => this.focusComposer()).catch(() => void 0);
2882
+ };
2883
+ handlePetReply_fn = async function(text) {
2884
+ await this.sendUserMessage({ text });
2885
+ };
2886
+ handlePetThreadSummaryActivate_fn = async function(threadId) {
2887
+ if (__privateMethod(this, _ChatKitElementBase_instances, getDisplayMode_fn).call(this) === "pet") {
2888
+ __privateMethod(this, _ChatKitElementBase_instances, setLauncherOpen_fn).call(this, true);
2889
+ }
2890
+ await this.setThreadId(threadId);
2891
+ await this.focusComposer();
1209
2892
  };
2893
+ _handleLauncherClose = new WeakMap();
1210
2894
  getFrameUrl_fn = function() {
1211
2895
  if (!__privateGet(this, _frameUrl)) {
1212
2896
  throw new IntegrationError(
@@ -1246,7 +2930,7 @@ var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "acce
1246
2930
  const frameURL = new URL(__privateMethod(this, _ChatKitElementBase_instances, getFrameUrl_fn).call(this), window.location.origin);
1247
2931
  __privateGet(this, _messenger).setTargetOrigin(frameURL.origin);
1248
2932
  frameURL.hash = encodeBase64({
1249
- options: getInnerOptions(__privateGet(this, _opts)),
2933
+ options: getInnerOptions(__privateMethod(this, _ChatKitElementBase_instances, getFrameOptions_fn).call(this, __privateGet(this, _opts))),
1250
2934
  referrer: window.location.origin,
1251
2935
  profile: this.profile
1252
2936
  });