@pocketping/widget 0.3.3 → 0.3.5
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.mjs → index.cjs} +494 -81
- package/dist/{index.d.mts → index.d.cts} +83 -5
- package/dist/index.d.ts +83 -5
- package/dist/index.js +455 -118
- package/dist/pocketping.min.global.js +90 -2
- package/package.json +9 -8
|
@@ -1,9 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
1
20
|
// src/index.ts
|
|
2
|
-
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
close: () => close,
|
|
24
|
+
default: () => index_default,
|
|
25
|
+
destroy: () => destroy,
|
|
26
|
+
getIdentity: () => getIdentity,
|
|
27
|
+
getTrackedElements: () => getTrackedElements,
|
|
28
|
+
identify: () => identify,
|
|
29
|
+
init: () => init,
|
|
30
|
+
offEvent: () => offEvent,
|
|
31
|
+
on: () => on,
|
|
32
|
+
onEvent: () => onEvent,
|
|
33
|
+
open: () => open,
|
|
34
|
+
reset: () => reset,
|
|
35
|
+
sendMessage: () => sendMessage,
|
|
36
|
+
setupTrackedElements: () => setupTrackedElements,
|
|
37
|
+
toggle: () => toggle,
|
|
38
|
+
trigger: () => trigger
|
|
39
|
+
});
|
|
40
|
+
module.exports = __toCommonJS(index_exports);
|
|
41
|
+
var import_preact2 = require("preact");
|
|
3
42
|
|
|
4
43
|
// src/components/ChatWidget.tsx
|
|
5
|
-
|
|
6
|
-
|
|
44
|
+
var import_preact = require("preact");
|
|
45
|
+
var import_hooks = require("preact/hooks");
|
|
7
46
|
|
|
8
47
|
// src/components/styles.ts
|
|
9
48
|
function styles(primaryColor, theme) {
|
|
@@ -348,17 +387,17 @@ function styles(primaryColor, theme) {
|
|
|
348
387
|
}
|
|
349
388
|
|
|
350
389
|
// src/components/ChatWidget.tsx
|
|
351
|
-
|
|
390
|
+
var import_jsx_runtime = require("preact/jsx-runtime");
|
|
352
391
|
function ChatWidget({ client: client2, config }) {
|
|
353
|
-
const [isOpen, setIsOpen] = useState(false);
|
|
354
|
-
const [messages, setMessages] = useState([]);
|
|
355
|
-
const [inputValue, setInputValue] = useState("");
|
|
356
|
-
const [isTyping, setIsTyping] = useState(false);
|
|
357
|
-
const [operatorOnline, setOperatorOnline] = useState(false);
|
|
358
|
-
const [isConnected, setIsConnected] = useState(false);
|
|
359
|
-
const messagesEndRef = useRef(null);
|
|
360
|
-
const inputRef = useRef(null);
|
|
361
|
-
useEffect(() => {
|
|
392
|
+
const [isOpen, setIsOpen] = (0, import_hooks.useState)(false);
|
|
393
|
+
const [messages, setMessages] = (0, import_hooks.useState)([]);
|
|
394
|
+
const [inputValue, setInputValue] = (0, import_hooks.useState)("");
|
|
395
|
+
const [isTyping, setIsTyping] = (0, import_hooks.useState)(false);
|
|
396
|
+
const [operatorOnline, setOperatorOnline] = (0, import_hooks.useState)(false);
|
|
397
|
+
const [isConnected, setIsConnected] = (0, import_hooks.useState)(false);
|
|
398
|
+
const messagesEndRef = (0, import_hooks.useRef)(null);
|
|
399
|
+
const inputRef = (0, import_hooks.useRef)(null);
|
|
400
|
+
(0, import_hooks.useEffect)(() => {
|
|
362
401
|
const unsubOpen = client2.on("openChange", setIsOpen);
|
|
363
402
|
const unsubMessage = client2.on("message", () => {
|
|
364
403
|
setMessages([...client2.getMessages()]);
|
|
@@ -387,15 +426,15 @@ function ChatWidget({ client: client2, config }) {
|
|
|
387
426
|
unsubConnect();
|
|
388
427
|
};
|
|
389
428
|
}, [client2]);
|
|
390
|
-
useEffect(() => {
|
|
429
|
+
(0, import_hooks.useEffect)(() => {
|
|
391
430
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
392
431
|
}, [messages]);
|
|
393
|
-
useEffect(() => {
|
|
432
|
+
(0, import_hooks.useEffect)(() => {
|
|
394
433
|
if (isOpen) {
|
|
395
434
|
inputRef.current?.focus();
|
|
396
435
|
}
|
|
397
436
|
}, [isOpen]);
|
|
398
|
-
const markMessagesAsRead = useCallback(() => {
|
|
437
|
+
const markMessagesAsRead = (0, import_hooks.useCallback)(() => {
|
|
399
438
|
if (!isOpen || !isConnected) return;
|
|
400
439
|
const unreadMessages = messages.filter(
|
|
401
440
|
(msg) => msg.sender !== "visitor" && msg.status !== "read"
|
|
@@ -405,14 +444,14 @@ function ChatWidget({ client: client2, config }) {
|
|
|
405
444
|
client2.sendReadStatus(messageIds, "read");
|
|
406
445
|
}
|
|
407
446
|
}, [isOpen, isConnected, messages, client2]);
|
|
408
|
-
useEffect(() => {
|
|
447
|
+
(0, import_hooks.useEffect)(() => {
|
|
409
448
|
if (!isOpen || !isConnected) return;
|
|
410
449
|
const timer = setTimeout(() => {
|
|
411
450
|
markMessagesAsRead();
|
|
412
451
|
}, 1e3);
|
|
413
452
|
return () => clearTimeout(timer);
|
|
414
453
|
}, [isOpen, isConnected, messages, markMessagesAsRead]);
|
|
415
|
-
useEffect(() => {
|
|
454
|
+
(0, import_hooks.useEffect)(() => {
|
|
416
455
|
const handleVisibilityChange = () => {
|
|
417
456
|
if (document.visibilityState === "visible" && isOpen) {
|
|
418
457
|
markMessagesAsRead();
|
|
@@ -421,7 +460,7 @@ function ChatWidget({ client: client2, config }) {
|
|
|
421
460
|
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
422
461
|
return () => document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
423
462
|
}, [isOpen, markMessagesAsRead]);
|
|
424
|
-
useEffect(() => {
|
|
463
|
+
(0, import_hooks.useEffect)(() => {
|
|
425
464
|
const unsubRead = client2.on(
|
|
426
465
|
"read",
|
|
427
466
|
() => {
|
|
@@ -451,71 +490,71 @@ function ChatWidget({ client: client2, config }) {
|
|
|
451
490
|
const position = config.position ?? "bottom-right";
|
|
452
491
|
const theme = getTheme(config.theme ?? "auto");
|
|
453
492
|
const primaryColor = config.primaryColor ?? "#6366f1";
|
|
454
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
455
|
-
/* @__PURE__ */ jsx("style", { children: styles(primaryColor, theme) }),
|
|
456
|
-
/* @__PURE__ */ jsxs(
|
|
493
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_preact.Fragment, { children: [
|
|
494
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: styles(primaryColor, theme) }),
|
|
495
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
457
496
|
"button",
|
|
458
497
|
{
|
|
459
498
|
class: `pp-toggle pp-${position}`,
|
|
460
499
|
onClick: () => client2.toggleOpen(),
|
|
461
500
|
"aria-label": isOpen ? "Close chat" : "Open chat",
|
|
462
501
|
children: [
|
|
463
|
-
isOpen ? /* @__PURE__ */ jsx(CloseIcon, {}) : /* @__PURE__ */ jsx(ChatIcon, {}),
|
|
464
|
-
!isOpen && operatorOnline && /* @__PURE__ */ jsx("span", { class: "pp-online-dot" })
|
|
502
|
+
isOpen ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ChatIcon, {}),
|
|
503
|
+
!isOpen && operatorOnline && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-online-dot" })
|
|
465
504
|
]
|
|
466
505
|
}
|
|
467
506
|
),
|
|
468
|
-
isOpen && /* @__PURE__ */ jsxs("div", { class: `pp-window pp-${position} pp-theme-${theme}`, children: [
|
|
469
|
-
/* @__PURE__ */ jsxs("div", { class: "pp-header", children: [
|
|
470
|
-
/* @__PURE__ */ jsxs("div", { class: "pp-header-info", children: [
|
|
471
|
-
config.operatorAvatar && /* @__PURE__ */ jsx("img", { src: config.operatorAvatar, alt: "", class: "pp-avatar" }),
|
|
472
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
473
|
-
/* @__PURE__ */ jsx("div", { class: "pp-header-title", children: config.operatorName ?? "Support" }),
|
|
474
|
-
/* @__PURE__ */ jsx("div", { class: "pp-header-status", children: operatorOnline ? /* @__PURE__ */ jsxs(
|
|
475
|
-
/* @__PURE__ */ jsx("span", { class: "pp-status-dot pp-online" }),
|
|
507
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: `pp-window pp-${position} pp-theme-${theme}`, children: [
|
|
508
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-header", children: [
|
|
509
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-header-info", children: [
|
|
510
|
+
config.operatorAvatar && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("img", { src: config.operatorAvatar, alt: "", class: "pp-avatar" }),
|
|
511
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { children: [
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-header-title", children: config.operatorName ?? "Support" }),
|
|
513
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-header-status", children: operatorOnline ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
514
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-status-dot pp-online" }),
|
|
476
515
|
" Online"
|
|
477
|
-
] }) : /* @__PURE__ */ jsxs(
|
|
478
|
-
/* @__PURE__ */ jsx("span", { class: "pp-status-dot" }),
|
|
516
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-status-dot" }),
|
|
479
518
|
" Away"
|
|
480
519
|
] }) })
|
|
481
520
|
] })
|
|
482
521
|
] }),
|
|
483
|
-
/* @__PURE__ */ jsx(
|
|
522
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
484
523
|
"button",
|
|
485
524
|
{
|
|
486
525
|
class: "pp-close-btn",
|
|
487
526
|
onClick: () => client2.setOpen(false),
|
|
488
527
|
"aria-label": "Close chat",
|
|
489
|
-
children: /* @__PURE__ */ jsx(CloseIcon, {})
|
|
528
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {})
|
|
490
529
|
}
|
|
491
530
|
)
|
|
492
531
|
] }),
|
|
493
|
-
/* @__PURE__ */ jsxs("div", { class: "pp-messages", children: [
|
|
494
|
-
config.welcomeMessage && messages.length === 0 && /* @__PURE__ */ jsx("div", { class: "pp-welcome", children: config.welcomeMessage }),
|
|
495
|
-
messages.map((msg) => /* @__PURE__ */ jsxs(
|
|
532
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-messages", children: [
|
|
533
|
+
config.welcomeMessage && messages.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-welcome", children: config.welcomeMessage }),
|
|
534
|
+
messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
496
535
|
"div",
|
|
497
536
|
{
|
|
498
537
|
class: `pp-message pp-message-${msg.sender}`,
|
|
499
538
|
children: [
|
|
500
|
-
/* @__PURE__ */ jsx("div", { class: "pp-message-content", children: msg.content }),
|
|
501
|
-
/* @__PURE__ */ jsxs("div", { class: "pp-message-time", children: [
|
|
539
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { class: "pp-message-content", children: msg.content }),
|
|
540
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-message-time", children: [
|
|
502
541
|
formatTime(msg.timestamp),
|
|
503
|
-
msg.sender === "ai" && /* @__PURE__ */ jsx("span", { class: "pp-ai-badge", children: "AI" }),
|
|
504
|
-
msg.sender === "visitor" && /* @__PURE__ */ jsx("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ jsx(StatusIcon, { status: msg.status }) })
|
|
542
|
+
msg.sender === "ai" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: "pp-ai-badge", children: "AI" }),
|
|
543
|
+
msg.sender === "visitor" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { class: `pp-status pp-status-${msg.status ?? "sent"}`, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(StatusIcon, { status: msg.status }) })
|
|
505
544
|
] })
|
|
506
545
|
]
|
|
507
546
|
},
|
|
508
547
|
msg.id
|
|
509
548
|
)),
|
|
510
|
-
isTyping && /* @__PURE__ */ jsxs("div", { class: "pp-message pp-message-operator pp-typing", children: [
|
|
511
|
-
/* @__PURE__ */ jsx("span", {}),
|
|
512
|
-
/* @__PURE__ */ jsx("span", {}),
|
|
513
|
-
/* @__PURE__ */ jsx("span", {})
|
|
549
|
+
isTyping && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-message pp-message-operator pp-typing", children: [
|
|
550
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
|
|
551
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {}),
|
|
552
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", {})
|
|
514
553
|
] }),
|
|
515
|
-
/* @__PURE__ */ jsx("div", { ref: messagesEndRef })
|
|
554
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: messagesEndRef })
|
|
516
555
|
] }),
|
|
517
|
-
/* @__PURE__ */ jsxs("form", { class: "pp-input-form", onSubmit: handleSubmit, children: [
|
|
518
|
-
/* @__PURE__ */ jsx(
|
|
556
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("form", { class: "pp-input-form", onSubmit: handleSubmit, children: [
|
|
557
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
519
558
|
"input",
|
|
520
559
|
{
|
|
521
560
|
ref: inputRef,
|
|
@@ -527,20 +566,20 @@ function ChatWidget({ client: client2, config }) {
|
|
|
527
566
|
disabled: !isConnected
|
|
528
567
|
}
|
|
529
568
|
),
|
|
530
|
-
/* @__PURE__ */ jsx(
|
|
569
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
531
570
|
"button",
|
|
532
571
|
{
|
|
533
572
|
type: "submit",
|
|
534
573
|
class: "pp-send-btn",
|
|
535
574
|
disabled: !inputValue.trim() || !isConnected,
|
|
536
575
|
"aria-label": "Send message",
|
|
537
|
-
children: /* @__PURE__ */ jsx(SendIcon, {})
|
|
576
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(SendIcon, {})
|
|
538
577
|
}
|
|
539
578
|
)
|
|
540
579
|
] }),
|
|
541
|
-
/* @__PURE__ */ jsxs("div", { class: "pp-footer", children: [
|
|
580
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { class: "pp-footer", children: [
|
|
542
581
|
"Powered by ",
|
|
543
|
-
/* @__PURE__ */ jsx("a", { href: "https://pocketping.io", target: "_blank", rel: "noopener", children: "PocketPing" })
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("a", { href: "https://pocketping.io", target: "_blank", rel: "noopener", children: "PocketPing" })
|
|
544
583
|
] })
|
|
545
584
|
] })
|
|
546
585
|
] });
|
|
@@ -566,41 +605,41 @@ function formatTime(timestamp) {
|
|
|
566
605
|
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
|
|
567
606
|
}
|
|
568
607
|
function ChatIcon() {
|
|
569
|
-
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
|
|
608
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
|
|
570
609
|
}
|
|
571
610
|
function CloseIcon() {
|
|
572
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
|
|
573
|
-
/* @__PURE__ */ jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
574
|
-
/* @__PURE__ */ jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
|
|
613
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
|
|
575
614
|
] });
|
|
576
615
|
}
|
|
577
616
|
function SendIcon() {
|
|
578
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
|
|
579
|
-
/* @__PURE__ */ jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
|
|
580
|
-
/* @__PURE__ */ jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
|
|
617
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", children: [
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
|
|
619
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
|
|
581
620
|
] });
|
|
582
621
|
}
|
|
583
622
|
function StatusIcon({ status }) {
|
|
584
623
|
if (!status || status === "sending" || status === "sent") {
|
|
585
|
-
return /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check", children: /* @__PURE__ */ jsx("polyline", { points: "3 8 7 12 13 4" }) });
|
|
624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "3 8 7 12 13 4" }) });
|
|
586
625
|
}
|
|
587
626
|
if (status === "delivered") {
|
|
588
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double", children: [
|
|
589
|
-
/* @__PURE__ */ jsx("polyline", { points: "1 8 5 12 11 4" }),
|
|
590
|
-
/* @__PURE__ */ jsx("polyline", { points: "7 8 11 12 17 4" })
|
|
627
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double", children: [
|
|
628
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "1 8 5 12 11 4" }),
|
|
629
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "7 8 11 12 17 4" })
|
|
591
630
|
] });
|
|
592
631
|
}
|
|
593
632
|
if (status === "read") {
|
|
594
|
-
return /* @__PURE__ */ jsxs("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double pp-check-read", children: [
|
|
595
|
-
/* @__PURE__ */ jsx("polyline", { points: "1 8 5 12 11 4" }),
|
|
596
|
-
/* @__PURE__ */ jsx("polyline", { points: "7 8 11 12 17 4" })
|
|
633
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { viewBox: "0 0 20 16", fill: "none", stroke: "currentColor", "stroke-width": "2", class: "pp-check-double pp-check-read", children: [
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "1 8 5 12 11 4" }),
|
|
635
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("polyline", { points: "7 8 11 12 17 4" })
|
|
597
636
|
] });
|
|
598
637
|
}
|
|
599
638
|
return null;
|
|
600
639
|
}
|
|
601
640
|
|
|
602
641
|
// src/version.ts
|
|
603
|
-
var VERSION = "0.3.
|
|
642
|
+
var VERSION = "0.3.5";
|
|
604
643
|
|
|
605
644
|
// src/client.ts
|
|
606
645
|
var PocketPingClient = class {
|
|
@@ -613,6 +652,13 @@ var PocketPingClient = class {
|
|
|
613
652
|
this.reconnectAttempts = 0;
|
|
614
653
|
this.maxReconnectAttempts = 5;
|
|
615
654
|
this.reconnectTimeout = null;
|
|
655
|
+
this.pollingTimeout = null;
|
|
656
|
+
this.pollingFailures = 0;
|
|
657
|
+
this.maxPollingFailures = 10;
|
|
658
|
+
this.trackedElementCleanups = [];
|
|
659
|
+
this.currentTrackedElements = [];
|
|
660
|
+
this.inspectorMode = false;
|
|
661
|
+
this.inspectorCleanup = null;
|
|
616
662
|
this.config = config;
|
|
617
663
|
}
|
|
618
664
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -622,11 +668,14 @@ var PocketPingClient = class {
|
|
|
622
668
|
const visitorId = this.getOrCreateVisitorId();
|
|
623
669
|
const storedSessionId = this.getStoredSessionId();
|
|
624
670
|
const storedIdentity = this.getStoredIdentity();
|
|
671
|
+
const urlParams = new URLSearchParams(window.location.search);
|
|
672
|
+
const inspectorToken = urlParams.get("pp_inspector");
|
|
625
673
|
const response = await this.fetch("/connect", {
|
|
626
674
|
method: "POST",
|
|
627
675
|
body: JSON.stringify({
|
|
628
676
|
visitorId,
|
|
629
677
|
sessionId: storedSessionId,
|
|
678
|
+
inspectorToken: inspectorToken || void 0,
|
|
630
679
|
metadata: {
|
|
631
680
|
url: window.location.href,
|
|
632
681
|
referrer: document.referrer || void 0,
|
|
@@ -649,6 +698,11 @@ var PocketPingClient = class {
|
|
|
649
698
|
};
|
|
650
699
|
this.storeSessionId(response.sessionId);
|
|
651
700
|
this.connectWebSocket();
|
|
701
|
+
if (response.inspectorMode) {
|
|
702
|
+
this.enableInspectorMode();
|
|
703
|
+
} else if (response.trackedElements?.length) {
|
|
704
|
+
this.setupTrackedElements(response.trackedElements);
|
|
705
|
+
}
|
|
652
706
|
this.emit("connect", this.session);
|
|
653
707
|
this.config.onConnect?.(response.sessionId);
|
|
654
708
|
return this.session;
|
|
@@ -660,6 +714,9 @@ var PocketPingClient = class {
|
|
|
660
714
|
if (this.reconnectTimeout) {
|
|
661
715
|
clearTimeout(this.reconnectTimeout);
|
|
662
716
|
}
|
|
717
|
+
this.stopPolling();
|
|
718
|
+
this.cleanupTrackedElements();
|
|
719
|
+
this.disableInspectorMode();
|
|
663
720
|
}
|
|
664
721
|
async sendMessage(content) {
|
|
665
722
|
if (!this.session) {
|
|
@@ -879,10 +936,15 @@ var PocketPingClient = class {
|
|
|
879
936
|
* Trigger a custom event to the backend
|
|
880
937
|
* @param eventName - The name of the event (e.g., 'clicked_pricing', 'viewed_demo')
|
|
881
938
|
* @param data - Optional payload to send with the event
|
|
939
|
+
* @param options - Optional trigger options (widgetMessage to open chat)
|
|
882
940
|
* @example
|
|
883
|
-
*
|
|
941
|
+
* // Silent event (just notify bridges)
|
|
942
|
+
* PocketPing.trigger('clicked_cta', { button: 'signup' })
|
|
943
|
+
*
|
|
944
|
+
* // Open widget with message
|
|
945
|
+
* PocketPing.trigger('clicked_pricing', { plan: 'pro' }, { widgetMessage: 'Need help choosing a plan?' })
|
|
884
946
|
*/
|
|
885
|
-
trigger(eventName, data) {
|
|
947
|
+
trigger(eventName, data, options) {
|
|
886
948
|
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
887
949
|
console.warn("[PocketPing] Cannot trigger event: WebSocket not connected");
|
|
888
950
|
return;
|
|
@@ -897,6 +959,10 @@ var PocketPingClient = class {
|
|
|
897
959
|
data: event
|
|
898
960
|
}));
|
|
899
961
|
this.emit(`event:${eventName}`, event);
|
|
962
|
+
if (options?.widgetMessage) {
|
|
963
|
+
this.setOpen(true);
|
|
964
|
+
this.emit("triggerMessage", { message: options.widgetMessage, eventName });
|
|
965
|
+
}
|
|
900
966
|
}
|
|
901
967
|
/**
|
|
902
968
|
* Subscribe to custom events from the backend
|
|
@@ -934,6 +1000,317 @@ var PocketPingClient = class {
|
|
|
934
1000
|
this.emit(`event:${event.name}`, event);
|
|
935
1001
|
}
|
|
936
1002
|
// ─────────────────────────────────────────────────────────────────
|
|
1003
|
+
// Tracked Elements (SaaS auto-tracking)
|
|
1004
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1005
|
+
/**
|
|
1006
|
+
* Setup tracked elements from config (used by SaaS dashboard)
|
|
1007
|
+
* @param elements - Array of tracked element configurations
|
|
1008
|
+
*/
|
|
1009
|
+
setupTrackedElements(elements) {
|
|
1010
|
+
this.cleanupTrackedElements();
|
|
1011
|
+
this.currentTrackedElements = elements;
|
|
1012
|
+
for (const config of elements) {
|
|
1013
|
+
const eventType = config.event || "click";
|
|
1014
|
+
const handler = (domEvent) => {
|
|
1015
|
+
const elementData = {
|
|
1016
|
+
...config.data,
|
|
1017
|
+
selector: config.selector,
|
|
1018
|
+
elementText: domEvent.target?.textContent?.trim().slice(0, 100),
|
|
1019
|
+
url: window.location.href
|
|
1020
|
+
};
|
|
1021
|
+
this.trigger(config.name, elementData, {
|
|
1022
|
+
widgetMessage: config.widgetMessage
|
|
1023
|
+
});
|
|
1024
|
+
};
|
|
1025
|
+
const delegatedHandler = (domEvent) => {
|
|
1026
|
+
const target = domEvent.target;
|
|
1027
|
+
if (target?.closest(config.selector)) {
|
|
1028
|
+
handler(domEvent);
|
|
1029
|
+
}
|
|
1030
|
+
};
|
|
1031
|
+
document.addEventListener(eventType, delegatedHandler, true);
|
|
1032
|
+
this.trackedElementCleanups.push(() => {
|
|
1033
|
+
document.removeEventListener(eventType, delegatedHandler, true);
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
if (elements.length > 0) {
|
|
1037
|
+
console.info(`[PocketPing] Tracking ${elements.length} element(s)`);
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
/**
|
|
1041
|
+
* Cleanup all tracked element listeners
|
|
1042
|
+
*/
|
|
1043
|
+
cleanupTrackedElements() {
|
|
1044
|
+
for (const cleanup of this.trackedElementCleanups) {
|
|
1045
|
+
cleanup();
|
|
1046
|
+
}
|
|
1047
|
+
this.trackedElementCleanups = [];
|
|
1048
|
+
this.currentTrackedElements = [];
|
|
1049
|
+
}
|
|
1050
|
+
/**
|
|
1051
|
+
* Get current tracked elements configuration
|
|
1052
|
+
*/
|
|
1053
|
+
getTrackedElements() {
|
|
1054
|
+
return [...this.currentTrackedElements];
|
|
1055
|
+
}
|
|
1056
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1057
|
+
// Inspector Mode (SaaS visual element selector)
|
|
1058
|
+
// ─────────────────────────────────────────────────────────────────
|
|
1059
|
+
/**
|
|
1060
|
+
* Enable inspector mode for visual element selection
|
|
1061
|
+
* This shows an overlay that allows clicking on elements to get their CSS selector
|
|
1062
|
+
*/
|
|
1063
|
+
enableInspectorMode() {
|
|
1064
|
+
if (this.inspectorMode) return;
|
|
1065
|
+
this.inspectorMode = true;
|
|
1066
|
+
console.info("[PocketPing] \u{1F50D} Inspector mode active - click on any element to select it");
|
|
1067
|
+
const overlay = document.createElement("div");
|
|
1068
|
+
overlay.id = "pp-inspector-overlay";
|
|
1069
|
+
overlay.innerHTML = `
|
|
1070
|
+
<style>
|
|
1071
|
+
#pp-inspector-overlay {
|
|
1072
|
+
position: fixed;
|
|
1073
|
+
top: 0;
|
|
1074
|
+
left: 0;
|
|
1075
|
+
right: 0;
|
|
1076
|
+
bottom: 0;
|
|
1077
|
+
z-index: 999999;
|
|
1078
|
+
pointer-events: none;
|
|
1079
|
+
}
|
|
1080
|
+
#pp-inspector-overlay * {
|
|
1081
|
+
pointer-events: auto;
|
|
1082
|
+
}
|
|
1083
|
+
#pp-inspector-banner {
|
|
1084
|
+
position: fixed;
|
|
1085
|
+
top: 16px;
|
|
1086
|
+
left: 50%;
|
|
1087
|
+
transform: translateX(-50%);
|
|
1088
|
+
background: linear-gradient(135deg, #6366f1, #8b5cf6);
|
|
1089
|
+
color: white;
|
|
1090
|
+
padding: 12px 24px;
|
|
1091
|
+
border-radius: 12px;
|
|
1092
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
1093
|
+
font-size: 14px;
|
|
1094
|
+
font-weight: 500;
|
|
1095
|
+
box-shadow: 0 4px 20px rgba(99, 102, 241, 0.4);
|
|
1096
|
+
display: flex;
|
|
1097
|
+
align-items: center;
|
|
1098
|
+
gap: 12px;
|
|
1099
|
+
z-index: 1000000;
|
|
1100
|
+
}
|
|
1101
|
+
#pp-inspector-banner svg {
|
|
1102
|
+
animation: pp-pulse 1.5s ease-in-out infinite;
|
|
1103
|
+
}
|
|
1104
|
+
@keyframes pp-pulse {
|
|
1105
|
+
0%, 100% { opacity: 1; }
|
|
1106
|
+
50% { opacity: 0.5; }
|
|
1107
|
+
}
|
|
1108
|
+
#pp-inspector-exit {
|
|
1109
|
+
background: rgba(255,255,255,0.2);
|
|
1110
|
+
border: none;
|
|
1111
|
+
color: white;
|
|
1112
|
+
padding: 6px 12px;
|
|
1113
|
+
border-radius: 6px;
|
|
1114
|
+
cursor: pointer;
|
|
1115
|
+
font-size: 12px;
|
|
1116
|
+
margin-left: 8px;
|
|
1117
|
+
}
|
|
1118
|
+
#pp-inspector-exit:hover {
|
|
1119
|
+
background: rgba(255,255,255,0.3);
|
|
1120
|
+
}
|
|
1121
|
+
.pp-inspector-highlight {
|
|
1122
|
+
outline: 3px dashed #6366f1 !important;
|
|
1123
|
+
outline-offset: 2px !important;
|
|
1124
|
+
background: rgba(99, 102, 241, 0.1) !important;
|
|
1125
|
+
}
|
|
1126
|
+
#pp-inspector-tooltip {
|
|
1127
|
+
position: fixed;
|
|
1128
|
+
background: #1f2937;
|
|
1129
|
+
color: white;
|
|
1130
|
+
padding: 8px 12px;
|
|
1131
|
+
border-radius: 8px;
|
|
1132
|
+
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
1133
|
+
font-size: 12px;
|
|
1134
|
+
pointer-events: none;
|
|
1135
|
+
z-index: 1000001;
|
|
1136
|
+
max-width: 400px;
|
|
1137
|
+
word-break: break-all;
|
|
1138
|
+
display: none;
|
|
1139
|
+
}
|
|
1140
|
+
</style>
|
|
1141
|
+
<div id="pp-inspector-banner">
|
|
1142
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1143
|
+
<circle cx="12" cy="12" r="10"/>
|
|
1144
|
+
<line x1="22" y1="22" x2="16.65" y2="16.65"/>
|
|
1145
|
+
<line x1="12" y1="8" x2="12" y2="12"/>
|
|
1146
|
+
<line x1="12" y1="16" x2="12" y2="16"/>
|
|
1147
|
+
</svg>
|
|
1148
|
+
<span>Inspector Mode - Click an element to capture its selector</span>
|
|
1149
|
+
<button id="pp-inspector-exit">Exit</button>
|
|
1150
|
+
</div>
|
|
1151
|
+
<div id="pp-inspector-tooltip"></div>
|
|
1152
|
+
`;
|
|
1153
|
+
document.body.appendChild(overlay);
|
|
1154
|
+
const tooltip = document.getElementById("pp-inspector-tooltip");
|
|
1155
|
+
let currentHighlight = null;
|
|
1156
|
+
const getSelector = (element) => {
|
|
1157
|
+
if (element.id && !element.id.startsWith("pp-")) {
|
|
1158
|
+
return `#${CSS.escape(element.id)}`;
|
|
1159
|
+
}
|
|
1160
|
+
const classes = Array.from(element.classList).filter((c) => !c.startsWith("pp-"));
|
|
1161
|
+
if (classes.length > 0) {
|
|
1162
|
+
const classSelector = "." + classes.map((c) => CSS.escape(c)).join(".");
|
|
1163
|
+
if (document.querySelectorAll(classSelector).length === 1) {
|
|
1164
|
+
return classSelector;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
for (const attr of Array.from(element.attributes)) {
|
|
1168
|
+
if (attr.name.startsWith("data-") && attr.value) {
|
|
1169
|
+
const dataSelector = `[${attr.name}="${CSS.escape(attr.value)}"]`;
|
|
1170
|
+
if (document.querySelectorAll(dataSelector).length === 1) {
|
|
1171
|
+
return dataSelector;
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
const path = [];
|
|
1176
|
+
let current = element;
|
|
1177
|
+
while (current && current !== document.body) {
|
|
1178
|
+
let selector = current.tagName.toLowerCase();
|
|
1179
|
+
if (current.id && !current.id.startsWith("pp-")) {
|
|
1180
|
+
selector = `#${CSS.escape(current.id)}`;
|
|
1181
|
+
path.unshift(selector);
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
1184
|
+
const parent = current.parentElement;
|
|
1185
|
+
if (parent) {
|
|
1186
|
+
const currentTagName = current.tagName;
|
|
1187
|
+
const siblings = Array.from(parent.children).filter(
|
|
1188
|
+
(c) => c.tagName === currentTagName
|
|
1189
|
+
);
|
|
1190
|
+
if (siblings.length > 1) {
|
|
1191
|
+
const index = siblings.indexOf(current) + 1;
|
|
1192
|
+
selector += `:nth-of-type(${index})`;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
path.unshift(selector);
|
|
1196
|
+
current = parent;
|
|
1197
|
+
}
|
|
1198
|
+
return path.join(" > ");
|
|
1199
|
+
};
|
|
1200
|
+
const handleMouseOver = (e) => {
|
|
1201
|
+
const target = e.target;
|
|
1202
|
+
if (target.closest("#pp-inspector-overlay") || target.closest("#pocketping-widget")) {
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
if (currentHighlight) {
|
|
1206
|
+
currentHighlight.classList.remove("pp-inspector-highlight");
|
|
1207
|
+
}
|
|
1208
|
+
target.classList.add("pp-inspector-highlight");
|
|
1209
|
+
currentHighlight = target;
|
|
1210
|
+
const selector = getSelector(target);
|
|
1211
|
+
tooltip.textContent = selector;
|
|
1212
|
+
tooltip.style.display = "block";
|
|
1213
|
+
tooltip.style.left = `${e.clientX + 15}px`;
|
|
1214
|
+
tooltip.style.top = `${e.clientY + 15}px`;
|
|
1215
|
+
const rect = tooltip.getBoundingClientRect();
|
|
1216
|
+
if (rect.right > window.innerWidth) {
|
|
1217
|
+
tooltip.style.left = `${e.clientX - rect.width - 15}px`;
|
|
1218
|
+
}
|
|
1219
|
+
if (rect.bottom > window.innerHeight) {
|
|
1220
|
+
tooltip.style.top = `${e.clientY - rect.height - 15}px`;
|
|
1221
|
+
}
|
|
1222
|
+
};
|
|
1223
|
+
const handleMouseOut = (e) => {
|
|
1224
|
+
const target = e.target;
|
|
1225
|
+
if (target.closest("#pp-inspector-overlay")) return;
|
|
1226
|
+
target.classList.remove("pp-inspector-highlight");
|
|
1227
|
+
tooltip.style.display = "none";
|
|
1228
|
+
};
|
|
1229
|
+
const handleClick = (e) => {
|
|
1230
|
+
const target = e.target;
|
|
1231
|
+
if (target.id === "pp-inspector-exit") {
|
|
1232
|
+
this.disableInspectorMode();
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
if (target.closest("#pp-inspector-overlay") || target.closest("#pocketping-widget")) {
|
|
1236
|
+
return;
|
|
1237
|
+
}
|
|
1238
|
+
e.preventDefault();
|
|
1239
|
+
e.stopPropagation();
|
|
1240
|
+
const selector = getSelector(target);
|
|
1241
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
1242
|
+
this.ws.send(JSON.stringify({
|
|
1243
|
+
type: "inspector_select",
|
|
1244
|
+
data: {
|
|
1245
|
+
selector,
|
|
1246
|
+
tagName: target.tagName.toLowerCase(),
|
|
1247
|
+
text: target.textContent?.trim().slice(0, 50) || "",
|
|
1248
|
+
url: window.location.href
|
|
1249
|
+
}
|
|
1250
|
+
}));
|
|
1251
|
+
}
|
|
1252
|
+
this.emit("inspectorSelect", { selector, element: target });
|
|
1253
|
+
target.classList.remove("pp-inspector-highlight");
|
|
1254
|
+
target.classList.add("pp-inspector-highlight");
|
|
1255
|
+
setTimeout(() => {
|
|
1256
|
+
target.classList.remove("pp-inspector-highlight");
|
|
1257
|
+
}, 500);
|
|
1258
|
+
const banner = document.getElementById("pp-inspector-banner");
|
|
1259
|
+
if (banner) {
|
|
1260
|
+
const originalHTML = banner.innerHTML;
|
|
1261
|
+
banner.innerHTML = `
|
|
1262
|
+
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
1263
|
+
<polyline points="20 6 9 17 4 12"/>
|
|
1264
|
+
</svg>
|
|
1265
|
+
<span>Selector captured: <code style="background:rgba(255,255,255,0.2);padding:2px 6px;border-radius:4px;font-family:monospace;">${selector}</code></span>
|
|
1266
|
+
`;
|
|
1267
|
+
setTimeout(() => {
|
|
1268
|
+
if (banner && this.inspectorMode) {
|
|
1269
|
+
banner.innerHTML = originalHTML;
|
|
1270
|
+
document.getElementById("pp-inspector-exit")?.addEventListener("click", () => {
|
|
1271
|
+
this.disableInspectorMode();
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
}, 2e3);
|
|
1275
|
+
}
|
|
1276
|
+
console.info(`[PocketPing] \u{1F4CC} Selector captured: ${selector}`);
|
|
1277
|
+
};
|
|
1278
|
+
document.addEventListener("mouseover", handleMouseOver, true);
|
|
1279
|
+
document.addEventListener("mouseout", handleMouseOut, true);
|
|
1280
|
+
document.addEventListener("click", handleClick, true);
|
|
1281
|
+
this.inspectorCleanup = () => {
|
|
1282
|
+
document.removeEventListener("mouseover", handleMouseOver, true);
|
|
1283
|
+
document.removeEventListener("mouseout", handleMouseOut, true);
|
|
1284
|
+
document.removeEventListener("click", handleClick, true);
|
|
1285
|
+
overlay.remove();
|
|
1286
|
+
if (currentHighlight) {
|
|
1287
|
+
currentHighlight.classList.remove("pp-inspector-highlight");
|
|
1288
|
+
}
|
|
1289
|
+
};
|
|
1290
|
+
document.getElementById("pp-inspector-exit")?.addEventListener("click", () => {
|
|
1291
|
+
this.disableInspectorMode();
|
|
1292
|
+
});
|
|
1293
|
+
}
|
|
1294
|
+
/**
|
|
1295
|
+
* Disable inspector mode
|
|
1296
|
+
*/
|
|
1297
|
+
disableInspectorMode() {
|
|
1298
|
+
if (!this.inspectorMode) return;
|
|
1299
|
+
this.inspectorMode = false;
|
|
1300
|
+
if (this.inspectorCleanup) {
|
|
1301
|
+
this.inspectorCleanup();
|
|
1302
|
+
this.inspectorCleanup = null;
|
|
1303
|
+
}
|
|
1304
|
+
console.info("[PocketPing] Inspector mode disabled");
|
|
1305
|
+
this.emit("inspectorDisabled", null);
|
|
1306
|
+
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Check if inspector mode is active
|
|
1309
|
+
*/
|
|
1310
|
+
isInspectorModeActive() {
|
|
1311
|
+
return this.inspectorMode;
|
|
1312
|
+
}
|
|
1313
|
+
// ─────────────────────────────────────────────────────────────────
|
|
937
1314
|
// WebSocket
|
|
938
1315
|
// ─────────────────────────────────────────────────────────────────
|
|
939
1316
|
connectWebSocket() {
|
|
@@ -1039,6 +1416,13 @@ var PocketPingClient = class {
|
|
|
1039
1416
|
const versionWarning = event.data;
|
|
1040
1417
|
this.handleVersionWarning(versionWarning);
|
|
1041
1418
|
break;
|
|
1419
|
+
case "config_update":
|
|
1420
|
+
const configData = event.data;
|
|
1421
|
+
if (configData.trackedElements) {
|
|
1422
|
+
this.setupTrackedElements(configData.trackedElements);
|
|
1423
|
+
this.emit("configUpdate", configData);
|
|
1424
|
+
}
|
|
1425
|
+
break;
|
|
1042
1426
|
}
|
|
1043
1427
|
}
|
|
1044
1428
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -1085,6 +1469,7 @@ var PocketPingClient = class {
|
|
|
1085
1469
|
try {
|
|
1086
1470
|
const lastMessageId = this.session.messages[this.session.messages.length - 1]?.id;
|
|
1087
1471
|
const newMessages = await this.fetchMessages(lastMessageId);
|
|
1472
|
+
this.pollingFailures = 0;
|
|
1088
1473
|
for (const message of newMessages) {
|
|
1089
1474
|
if (!this.session.messages.find((m) => m.id === message.id)) {
|
|
1090
1475
|
this.session.messages.push(message);
|
|
@@ -1093,14 +1478,30 @@ var PocketPingClient = class {
|
|
|
1093
1478
|
}
|
|
1094
1479
|
}
|
|
1095
1480
|
} catch (err) {
|
|
1096
|
-
|
|
1481
|
+
this.pollingFailures++;
|
|
1482
|
+
if (this.pollingFailures <= 3 || this.pollingFailures % 3 === 0) {
|
|
1483
|
+
console.warn(`[PocketPing] Polling failed (${this.pollingFailures}/${this.maxPollingFailures})`);
|
|
1484
|
+
}
|
|
1485
|
+
if (this.pollingFailures >= this.maxPollingFailures) {
|
|
1486
|
+
console.error("[PocketPing] Polling disabled after too many failures. Real-time updates unavailable.");
|
|
1487
|
+
this.emit("pollingDisabled", { failures: this.pollingFailures });
|
|
1488
|
+
return;
|
|
1489
|
+
}
|
|
1097
1490
|
}
|
|
1098
1491
|
if (this.session) {
|
|
1099
|
-
|
|
1492
|
+
const delay = this.pollingFailures > 0 ? Math.min(3e3 * Math.pow(2, this.pollingFailures - 1), 3e4) : 3e3;
|
|
1493
|
+
this.pollingTimeout = setTimeout(poll, delay);
|
|
1100
1494
|
}
|
|
1101
1495
|
};
|
|
1102
1496
|
poll();
|
|
1103
1497
|
}
|
|
1498
|
+
stopPolling() {
|
|
1499
|
+
if (this.pollingTimeout) {
|
|
1500
|
+
clearTimeout(this.pollingTimeout);
|
|
1501
|
+
this.pollingTimeout = null;
|
|
1502
|
+
}
|
|
1503
|
+
this.pollingFailures = 0;
|
|
1504
|
+
}
|
|
1104
1505
|
// ─────────────────────────────────────────────────────────────────
|
|
1105
1506
|
// HTTP
|
|
1106
1507
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -1208,7 +1609,7 @@ function init(config) {
|
|
|
1208
1609
|
container = document.createElement("div");
|
|
1209
1610
|
container.id = "pocketping-container";
|
|
1210
1611
|
document.body.appendChild(container);
|
|
1211
|
-
render(
|
|
1612
|
+
(0, import_preact2.render)((0, import_preact2.h)(ChatWidget, { client, config }), container);
|
|
1212
1613
|
client.connect().catch((err) => {
|
|
1213
1614
|
console.error("[PocketPing] Failed to connect:", err);
|
|
1214
1615
|
});
|
|
@@ -1216,7 +1617,7 @@ function init(config) {
|
|
|
1216
1617
|
}
|
|
1217
1618
|
function destroy() {
|
|
1218
1619
|
if (container) {
|
|
1219
|
-
render(null, container);
|
|
1620
|
+
(0, import_preact2.render)(null, container);
|
|
1220
1621
|
container.remove();
|
|
1221
1622
|
container = null;
|
|
1222
1623
|
}
|
|
@@ -1240,12 +1641,22 @@ function sendMessage(content) {
|
|
|
1240
1641
|
}
|
|
1241
1642
|
return client.sendMessage(content);
|
|
1242
1643
|
}
|
|
1243
|
-
function trigger(eventName, data) {
|
|
1644
|
+
function trigger(eventName, data, options) {
|
|
1244
1645
|
if (!client) {
|
|
1245
1646
|
console.warn("[PocketPing] Not initialized, cannot trigger event");
|
|
1246
1647
|
return;
|
|
1247
1648
|
}
|
|
1248
|
-
client.trigger(eventName, data);
|
|
1649
|
+
client.trigger(eventName, data, options);
|
|
1650
|
+
}
|
|
1651
|
+
function setupTrackedElements(elements) {
|
|
1652
|
+
if (!client) {
|
|
1653
|
+
console.warn("[PocketPing] Not initialized, cannot setup tracked elements");
|
|
1654
|
+
return;
|
|
1655
|
+
}
|
|
1656
|
+
client.setupTrackedElements(elements);
|
|
1657
|
+
}
|
|
1658
|
+
function getTrackedElements() {
|
|
1659
|
+
return client?.getTrackedElements() || [];
|
|
1249
1660
|
}
|
|
1250
1661
|
function onEvent(eventName, handler) {
|
|
1251
1662
|
if (!client) {
|
|
@@ -1297,12 +1708,13 @@ if (typeof document !== "undefined") {
|
|
|
1297
1708
|
}
|
|
1298
1709
|
}
|
|
1299
1710
|
}
|
|
1300
|
-
var index_default = { init, destroy, open, close, toggle, sendMessage, trigger, onEvent, offEvent, on, identify, reset, getIdentity };
|
|
1301
|
-
export
|
|
1711
|
+
var index_default = { init, destroy, open, close, toggle, sendMessage, trigger, onEvent, offEvent, on, identify, reset, getIdentity, setupTrackedElements, getTrackedElements };
|
|
1712
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1713
|
+
0 && (module.exports = {
|
|
1302
1714
|
close,
|
|
1303
|
-
index_default as default,
|
|
1304
1715
|
destroy,
|
|
1305
1716
|
getIdentity,
|
|
1717
|
+
getTrackedElements,
|
|
1306
1718
|
identify,
|
|
1307
1719
|
init,
|
|
1308
1720
|
offEvent,
|
|
@@ -1311,6 +1723,7 @@ export {
|
|
|
1311
1723
|
open,
|
|
1312
1724
|
reset,
|
|
1313
1725
|
sendMessage,
|
|
1726
|
+
setupTrackedElements,
|
|
1314
1727
|
toggle,
|
|
1315
1728
|
trigger
|
|
1316
|
-
};
|
|
1729
|
+
});
|