@pocketping/widget 2.0.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/index.cjs +149 -24
- package/dist/index.d.cts +50 -8
- package/dist/index.d.ts +50 -8
- package/dist/index.js +149 -24
- package/dist/pocketping.min.global.js +61 -61
- package/package.json +1 -1
package/README.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -47,23 +47,59 @@ var import_preact = require("preact");
|
|
|
47
47
|
var import_hooks2 = require("preact/hooks");
|
|
48
48
|
|
|
49
49
|
// src/components/styles.ts
|
|
50
|
+
var DEFAULT_GRADIENT = { from: "#36e3ff", to: "#7c5cff", direction: "to right" };
|
|
51
|
+
function isGradient(value) {
|
|
52
|
+
return typeof value === "object" && value !== null && "from" in value && "to" in value;
|
|
53
|
+
}
|
|
54
|
+
function toCssColor(value) {
|
|
55
|
+
if (isGradient(value)) {
|
|
56
|
+
const direction = value.direction || "to right";
|
|
57
|
+
return `linear-gradient(${direction}, ${value.from}, ${value.to})`;
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
function getBaseColor(value) {
|
|
62
|
+
if (isGradient(value)) {
|
|
63
|
+
return value.to;
|
|
64
|
+
}
|
|
65
|
+
return value;
|
|
66
|
+
}
|
|
50
67
|
function resolveThemeColor(color, isDark, defaultLight, defaultDark) {
|
|
51
68
|
if (!color) {
|
|
52
|
-
return isDark ? defaultDark : defaultLight;
|
|
69
|
+
return toCssColor(isDark ? defaultDark : defaultLight);
|
|
53
70
|
}
|
|
54
71
|
if (typeof color === "string") {
|
|
55
72
|
return color;
|
|
56
73
|
}
|
|
57
|
-
|
|
74
|
+
if (isGradient(color)) {
|
|
75
|
+
return toCssColor(color);
|
|
76
|
+
}
|
|
77
|
+
const resolved = isDark ? color.dark : color.light;
|
|
78
|
+
return toCssColor(resolved);
|
|
79
|
+
}
|
|
80
|
+
function resolveBaseColor(color, isDark, defaultLight, defaultDark) {
|
|
81
|
+
if (!color) {
|
|
82
|
+
return getBaseColor(isDark ? defaultDark : defaultLight);
|
|
83
|
+
}
|
|
84
|
+
if (typeof color === "string") {
|
|
85
|
+
return color;
|
|
86
|
+
}
|
|
87
|
+
if (isGradient(color)) {
|
|
88
|
+
return getBaseColor(color);
|
|
89
|
+
}
|
|
90
|
+
const resolved = isDark ? color.dark : color.light;
|
|
91
|
+
return getBaseColor(resolved);
|
|
58
92
|
}
|
|
59
93
|
function styles(options) {
|
|
60
94
|
const { primaryColor, theme, headerColor, footerColor, chatBackground, toggleColor } = options;
|
|
61
95
|
const isDark = theme === "dark";
|
|
62
|
-
const resolvedHeaderColor = resolveThemeColor(headerColor, isDark,
|
|
96
|
+
const resolvedHeaderColor = resolveThemeColor(headerColor, isDark, DEFAULT_GRADIENT, "#202c33");
|
|
63
97
|
const resolvedFooterColor = resolveThemeColor(footerColor, isDark, "#f0f2f5", "#202c33");
|
|
64
|
-
const resolvedToggleColor = resolveThemeColor(toggleColor, isDark,
|
|
65
|
-
const
|
|
66
|
-
const
|
|
98
|
+
const resolvedToggleColor = resolveThemeColor(toggleColor, isDark, DEFAULT_GRADIENT, DEFAULT_GRADIENT);
|
|
99
|
+
const headerBaseColor = resolveBaseColor(headerColor, isDark, DEFAULT_GRADIENT, "#202c33");
|
|
100
|
+
const toggleBaseColor = resolveBaseColor(toggleColor, isDark, DEFAULT_GRADIENT, DEFAULT_GRADIENT);
|
|
101
|
+
const resolvedToggleHoverColor = adjustBrightness(toggleBaseColor, -15);
|
|
102
|
+
const resolvedSendButtonHoverColor = adjustBrightness(headerBaseColor, -15);
|
|
67
103
|
const whatsappPattern = isDark ? `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.03'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")` : `url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23000000' fill-opacity='0.03'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E")`;
|
|
68
104
|
const dotsPattern = isDark ? `url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='10' cy='10' r='1' fill='%23ffffff' fill-opacity='0.05'/%3E%3C/svg%3E")` : `url("data:image/svg+xml,%3Csvg width='20' height='20' viewBox='0 0 20 20' xmlns='http://www.w3.org/2000/svg'%3E%3Ccircle cx='10' cy='10' r='1' fill='%23000000' fill-opacity='0.05'/%3E%3C/svg%3E")`;
|
|
69
105
|
const resolvedChatBg = resolveThemeColor(chatBackground, isDark, "whatsapp", "whatsapp");
|
|
@@ -162,7 +198,7 @@ function styles(options) {
|
|
|
162
198
|
right: 4px;
|
|
163
199
|
width: 12px;
|
|
164
200
|
height: 12px;
|
|
165
|
-
background: #
|
|
201
|
+
background: #ff5fd4;
|
|
166
202
|
border-radius: 50%;
|
|
167
203
|
border: 2px solid white;
|
|
168
204
|
}
|
|
@@ -318,8 +354,8 @@ function styles(options) {
|
|
|
318
354
|
}
|
|
319
355
|
|
|
320
356
|
.pp-status-dot.pp-online {
|
|
321
|
-
background: #
|
|
322
|
-
box-shadow: 0 0 0 2px rgba(
|
|
357
|
+
background: #ff5fd4;
|
|
358
|
+
box-shadow: 0 0 0 2px rgba(255, 95, 212, 0.3);
|
|
323
359
|
}
|
|
324
360
|
|
|
325
361
|
.pp-close-btn {
|
|
@@ -1023,7 +1059,7 @@ function styles(options) {
|
|
|
1023
1059
|
justify-content: center;
|
|
1024
1060
|
gap: 16px;
|
|
1025
1061
|
z-index: 100;
|
|
1026
|
-
border: 3px dashed #
|
|
1062
|
+
border: 3px dashed #7c5cff;
|
|
1027
1063
|
border-radius: 12px;
|
|
1028
1064
|
margin: 4px;
|
|
1029
1065
|
pointer-events: none;
|
|
@@ -1032,7 +1068,7 @@ function styles(options) {
|
|
|
1032
1068
|
.pp-drop-icon svg {
|
|
1033
1069
|
width: 56px;
|
|
1034
1070
|
height: 56px;
|
|
1035
|
-
color: #
|
|
1071
|
+
color: #7c5cff;
|
|
1036
1072
|
}
|
|
1037
1073
|
|
|
1038
1074
|
.pp-drop-text {
|
|
@@ -1173,7 +1209,7 @@ function styles(options) {
|
|
|
1173
1209
|
padding: 10px 20px;
|
|
1174
1210
|
border: none;
|
|
1175
1211
|
border-radius: 8px;
|
|
1176
|
-
background: #
|
|
1212
|
+
background: #7c5cff;
|
|
1177
1213
|
color: white;
|
|
1178
1214
|
font-size: 14px;
|
|
1179
1215
|
font-weight: 500;
|
|
@@ -1182,7 +1218,7 @@ function styles(options) {
|
|
|
1182
1218
|
}
|
|
1183
1219
|
|
|
1184
1220
|
.pp-edit-save:hover:not(:disabled) {
|
|
1185
|
-
background: #
|
|
1221
|
+
background: #6a4ee6;
|
|
1186
1222
|
}
|
|
1187
1223
|
|
|
1188
1224
|
.pp-edit-save:disabled {
|
|
@@ -1197,7 +1233,7 @@ function styles(options) {
|
|
|
1197
1233
|
gap: 10px;
|
|
1198
1234
|
padding: 8px 12px;
|
|
1199
1235
|
background: ${resolvedFooterColor};
|
|
1200
|
-
border-left: 4px solid #
|
|
1236
|
+
border-left: 4px solid #7c5cff;
|
|
1201
1237
|
}
|
|
1202
1238
|
|
|
1203
1239
|
.pp-reply-preview-content {
|
|
@@ -1208,7 +1244,7 @@ function styles(options) {
|
|
|
1208
1244
|
.pp-reply-label {
|
|
1209
1245
|
display: block;
|
|
1210
1246
|
font-size: 12px;
|
|
1211
|
-
color: #
|
|
1247
|
+
color: #7c5cff;
|
|
1212
1248
|
font-weight: 500;
|
|
1213
1249
|
margin-bottom: 2px;
|
|
1214
1250
|
}
|
|
@@ -1252,7 +1288,7 @@ function styles(options) {
|
|
|
1252
1288
|
/* Reply Quote in Message */
|
|
1253
1289
|
.pp-reply-quote {
|
|
1254
1290
|
background: ${isDark ? "rgba(0,0,0,0.2)" : "rgba(0,0,0,0.05)"};
|
|
1255
|
-
border-left: 3px solid #
|
|
1291
|
+
border-left: 3px solid #7c5cff;
|
|
1256
1292
|
padding: 6px 10px;
|
|
1257
1293
|
margin-bottom: 4px;
|
|
1258
1294
|
border-radius: 0 6px 6px 0;
|
|
@@ -1264,7 +1300,7 @@ function styles(options) {
|
|
|
1264
1300
|
.pp-reply-sender {
|
|
1265
1301
|
display: block;
|
|
1266
1302
|
font-weight: 500;
|
|
1267
|
-
color: #
|
|
1303
|
+
color: #7c5cff;
|
|
1268
1304
|
margin-bottom: 2px;
|
|
1269
1305
|
font-size: 12px;
|
|
1270
1306
|
}
|
|
@@ -1294,7 +1330,7 @@ function styles(options) {
|
|
|
1294
1330
|
/* Reply quote in visitor message bubble needs higher contrast */
|
|
1295
1331
|
.pp-message-visitor .pp-reply-quote {
|
|
1296
1332
|
background: ${isDark ? "rgba(0,0,0,0.2)" : "rgba(0,0,0,0.08)"};
|
|
1297
|
-
border-left-color: ${isDark ? "rgba(255,255,255,0.5)" : "#
|
|
1333
|
+
border-left-color: ${isDark ? "rgba(255,255,255,0.5)" : "#7c5cff"};
|
|
1298
1334
|
}
|
|
1299
1335
|
|
|
1300
1336
|
.pp-message-visitor .pp-reply-quote-clickable:hover {
|
|
@@ -1302,7 +1338,7 @@ function styles(options) {
|
|
|
1302
1338
|
}
|
|
1303
1339
|
|
|
1304
1340
|
.pp-message-visitor .pp-reply-sender {
|
|
1305
|
-
color: ${isDark ? "rgba(255,255,255,0.9)" : "#
|
|
1341
|
+
color: ${isDark ? "rgba(255,255,255,0.9)" : "#7c5cff"};
|
|
1306
1342
|
}
|
|
1307
1343
|
|
|
1308
1344
|
.pp-message-visitor .pp-reply-content {
|
|
@@ -1316,13 +1352,13 @@ function styles(options) {
|
|
|
1316
1352
|
|
|
1317
1353
|
@keyframes pp-highlight-pulse {
|
|
1318
1354
|
0% {
|
|
1319
|
-
box-shadow: 0 0 0 0 rgba(
|
|
1355
|
+
box-shadow: 0 0 0 0 rgba(124, 92, 255, 0.5);
|
|
1320
1356
|
}
|
|
1321
1357
|
30% {
|
|
1322
|
-
box-shadow: 0 0 0 6px rgba(
|
|
1358
|
+
box-shadow: 0 0 0 6px rgba(124, 92, 255, 0.25);
|
|
1323
1359
|
}
|
|
1324
1360
|
100% {
|
|
1325
|
-
box-shadow: 0 0 0 0 rgba(
|
|
1361
|
+
box-shadow: 0 0 0 0 rgba(124, 92, 255, 0);
|
|
1326
1362
|
}
|
|
1327
1363
|
}
|
|
1328
1364
|
|
|
@@ -1583,7 +1619,7 @@ function styles(options) {
|
|
|
1583
1619
|
margin-top: 12px;
|
|
1584
1620
|
border: none;
|
|
1585
1621
|
border-radius: 8px;
|
|
1586
|
-
background: #
|
|
1622
|
+
background: #7c5cff;
|
|
1587
1623
|
color: white;
|
|
1588
1624
|
font-size: 15px;
|
|
1589
1625
|
font-weight: 500;
|
|
@@ -1592,7 +1628,7 @@ function styles(options) {
|
|
|
1592
1628
|
}
|
|
1593
1629
|
|
|
1594
1630
|
.pp-prechat-submit:hover:not(:disabled) {
|
|
1595
|
-
background: #
|
|
1631
|
+
background: #6a4ee6;
|
|
1596
1632
|
}
|
|
1597
1633
|
|
|
1598
1634
|
.pp-prechat-submit:active:not(:disabled) {
|
|
@@ -2980,6 +3016,10 @@ var PocketPingClient = class {
|
|
|
2980
3016
|
this.currentTrackedElements = [];
|
|
2981
3017
|
this.inspectorMode = false;
|
|
2982
3018
|
this.inspectorCleanup = null;
|
|
3019
|
+
this.connectedAt = 0;
|
|
3020
|
+
this.disconnectNotified = false;
|
|
3021
|
+
this.boundHandleUnload = null;
|
|
3022
|
+
this.boundHandleVisibilityChange = null;
|
|
2983
3023
|
this.config = config;
|
|
2984
3024
|
}
|
|
2985
3025
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -3053,6 +3093,9 @@ var PocketPingClient = class {
|
|
|
3053
3093
|
welcomeMessage: this.config.welcomeMessage
|
|
3054
3094
|
});
|
|
3055
3095
|
this.storeSessionId(response.sessionId);
|
|
3096
|
+
this.connectedAt = Date.now();
|
|
3097
|
+
this.disconnectNotified = false;
|
|
3098
|
+
this.setupUnloadListeners();
|
|
3056
3099
|
this.connectRealtime();
|
|
3057
3100
|
if (response.inspectorMode) {
|
|
3058
3101
|
this.enableInspectorMode();
|
|
@@ -3064,6 +3107,8 @@ var PocketPingClient = class {
|
|
|
3064
3107
|
return this.session;
|
|
3065
3108
|
}
|
|
3066
3109
|
disconnect() {
|
|
3110
|
+
this.notifyDisconnect();
|
|
3111
|
+
this.cleanupUnloadListeners();
|
|
3067
3112
|
if (this.ws) {
|
|
3068
3113
|
this.ws.onclose = null;
|
|
3069
3114
|
this.ws.onmessage = null;
|
|
@@ -4267,6 +4312,86 @@ var PocketPingClient = class {
|
|
|
4267
4312
|
this.pollingFailures = 0;
|
|
4268
4313
|
}
|
|
4269
4314
|
// ─────────────────────────────────────────────────────────────────
|
|
4315
|
+
// Visitor Disconnect Notification
|
|
4316
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4317
|
+
setupUnloadListeners() {
|
|
4318
|
+
this.boundHandleUnload = () => this.notifyDisconnect();
|
|
4319
|
+
window.addEventListener("beforeunload", this.boundHandleUnload);
|
|
4320
|
+
window.addEventListener("pagehide", this.boundHandleUnload);
|
|
4321
|
+
this.boundHandleVisibilityChange = () => {
|
|
4322
|
+
if (document.visibilityState === "hidden") {
|
|
4323
|
+
this.sendVisibilityPing("hidden");
|
|
4324
|
+
} else if (document.visibilityState === "visible") {
|
|
4325
|
+
this.sendVisibilityPing("visible");
|
|
4326
|
+
}
|
|
4327
|
+
};
|
|
4328
|
+
document.addEventListener("visibilitychange", this.boundHandleVisibilityChange);
|
|
4329
|
+
}
|
|
4330
|
+
cleanupUnloadListeners() {
|
|
4331
|
+
if (this.boundHandleUnload) {
|
|
4332
|
+
window.removeEventListener("beforeunload", this.boundHandleUnload);
|
|
4333
|
+
window.removeEventListener("pagehide", this.boundHandleUnload);
|
|
4334
|
+
this.boundHandleUnload = null;
|
|
4335
|
+
}
|
|
4336
|
+
if (this.boundHandleVisibilityChange) {
|
|
4337
|
+
document.removeEventListener("visibilitychange", this.boundHandleVisibilityChange);
|
|
4338
|
+
this.boundHandleVisibilityChange = null;
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
/**
|
|
4342
|
+
* Notify backend that visitor is leaving
|
|
4343
|
+
* Uses sendBeacon for reliability on page unload
|
|
4344
|
+
*/
|
|
4345
|
+
notifyDisconnect() {
|
|
4346
|
+
if (this.disconnectNotified || !this.session) {
|
|
4347
|
+
return;
|
|
4348
|
+
}
|
|
4349
|
+
this.disconnectNotified = true;
|
|
4350
|
+
const sessionDuration = this.connectedAt ? Math.round((Date.now() - this.connectedAt) / 1e3) : 0;
|
|
4351
|
+
const url = this.config.endpoint.replace(/\/$/, "") + "/disconnect";
|
|
4352
|
+
const data = JSON.stringify({
|
|
4353
|
+
sessionId: this.session.sessionId,
|
|
4354
|
+
duration: sessionDuration,
|
|
4355
|
+
reason: "page_unload"
|
|
4356
|
+
});
|
|
4357
|
+
if (navigator.sendBeacon) {
|
|
4358
|
+
const blob = new Blob([data], { type: "application/json" });
|
|
4359
|
+
navigator.sendBeacon(url, blob);
|
|
4360
|
+
} else {
|
|
4361
|
+
try {
|
|
4362
|
+
const xhr = new XMLHttpRequest();
|
|
4363
|
+
xhr.open("POST", url, false);
|
|
4364
|
+
xhr.setRequestHeader("Content-Type", "application/json");
|
|
4365
|
+
xhr.send(data);
|
|
4366
|
+
} catch {
|
|
4367
|
+
}
|
|
4368
|
+
}
|
|
4369
|
+
}
|
|
4370
|
+
/**
|
|
4371
|
+
* Send visibility ping to backend (for inactivity tracking)
|
|
4372
|
+
*/
|
|
4373
|
+
sendVisibilityPing(state) {
|
|
4374
|
+
if (!this.session) return;
|
|
4375
|
+
const url = this.config.endpoint.replace(/\/$/, "") + "/visibility";
|
|
4376
|
+
const data = JSON.stringify({
|
|
4377
|
+
sessionId: this.session.sessionId,
|
|
4378
|
+
state,
|
|
4379
|
+
timestamp: Date.now()
|
|
4380
|
+
});
|
|
4381
|
+
if (state === "hidden" && navigator.sendBeacon) {
|
|
4382
|
+
const blob = new Blob([data], { type: "application/json" });
|
|
4383
|
+
navigator.sendBeacon(url, blob);
|
|
4384
|
+
} else {
|
|
4385
|
+
fetch(url, {
|
|
4386
|
+
method: "POST",
|
|
4387
|
+
headers: { "Content-Type": "application/json" },
|
|
4388
|
+
body: data,
|
|
4389
|
+
keepalive: true
|
|
4390
|
+
}).catch(() => {
|
|
4391
|
+
});
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4394
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4270
4395
|
// HTTP
|
|
4271
4396
|
// ─────────────────────────────────────────────────────────────────
|
|
4272
4397
|
async fetch(path, options) {
|
package/dist/index.d.cts
CHANGED
|
@@ -6,6 +6,28 @@ interface ThemeColor {
|
|
|
6
6
|
light: string;
|
|
7
7
|
dark: string;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Gradient color value
|
|
11
|
+
* Creates a linear gradient between two colors
|
|
12
|
+
* @example { from: '#36e3ff', to: '#7c5cff', direction: 'to right' }
|
|
13
|
+
*/
|
|
14
|
+
interface GradientColor {
|
|
15
|
+
from: string;
|
|
16
|
+
to: string;
|
|
17
|
+
/** CSS gradient direction (default: 'to right') */
|
|
18
|
+
direction?: 'to right' | 'to left' | 'to bottom' | 'to top' | string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Color value that can be a solid color, gradient, or theme-aware
|
|
22
|
+
*/
|
|
23
|
+
type ColorValue = string | GradientColor | ThemeColor | ThemeGradientColor;
|
|
24
|
+
/**
|
|
25
|
+
* Theme-aware gradient - different gradients for light/dark themes
|
|
26
|
+
*/
|
|
27
|
+
interface ThemeGradientColor {
|
|
28
|
+
light: string | GradientColor;
|
|
29
|
+
dark: string | GradientColor;
|
|
30
|
+
}
|
|
9
31
|
interface PocketPingConfig {
|
|
10
32
|
/** Your backend endpoint for self-hosted (e.g., "https://yoursite.com/pocketping") */
|
|
11
33
|
endpoint?: string;
|
|
@@ -32,11 +54,14 @@ interface PocketPingConfig {
|
|
|
32
54
|
/** Text color on primary background (defaults to white) */
|
|
33
55
|
primaryTextColor?: string;
|
|
34
56
|
/**
|
|
35
|
-
* Header background color
|
|
36
|
-
* Can be a
|
|
37
|
-
* @example "#
|
|
57
|
+
* Header background color or gradient
|
|
58
|
+
* Can be a solid color, gradient, or theme-aware
|
|
59
|
+
* @example "#7c5cff"
|
|
60
|
+
* @example { from: '#36e3ff', to: '#7c5cff' }
|
|
61
|
+
* @example { light: "#7c5cff", dark: "#202c33" }
|
|
62
|
+
* @example { light: { from: '#36e3ff', to: '#7c5cff' }, dark: "#202c33" }
|
|
38
63
|
*/
|
|
39
|
-
headerColor?:
|
|
64
|
+
headerColor?: ColorValue;
|
|
40
65
|
/**
|
|
41
66
|
* Footer/input area background color
|
|
42
67
|
* Can be a string (same for both themes) or object with light/dark values
|
|
@@ -53,11 +78,13 @@ interface PocketPingConfig {
|
|
|
53
78
|
*/
|
|
54
79
|
chatBackground?: 'whatsapp' | 'dots' | 'plain' | string | ThemeColor;
|
|
55
80
|
/**
|
|
56
|
-
* Toggle button background color
|
|
57
|
-
* Can be a
|
|
58
|
-
* @example "#
|
|
81
|
+
* Toggle button background color or gradient
|
|
82
|
+
* Can be a solid color, gradient, or theme-aware
|
|
83
|
+
* @example "#7c5cff"
|
|
84
|
+
* @example { from: '#36e3ff', to: '#7c5cff' }
|
|
85
|
+
* @example { light: "#7c5cff", dark: "#7c5cff" }
|
|
59
86
|
*/
|
|
60
|
-
toggleColor?:
|
|
87
|
+
toggleColor?: ColorValue;
|
|
61
88
|
/** Widget position */
|
|
62
89
|
position?: 'bottom-right' | 'bottom-left';
|
|
63
90
|
/** Distance from edge in pixels (default: 20) */
|
|
@@ -273,6 +300,10 @@ declare class PocketPingClient {
|
|
|
273
300
|
private currentTrackedElements;
|
|
274
301
|
private inspectorMode;
|
|
275
302
|
private inspectorCleanup;
|
|
303
|
+
private connectedAt;
|
|
304
|
+
private disconnectNotified;
|
|
305
|
+
private boundHandleUnload;
|
|
306
|
+
private boundHandleVisibilityChange;
|
|
276
307
|
constructor(config: ResolvedPocketPingConfig);
|
|
277
308
|
connect(): Promise<Session>;
|
|
278
309
|
disconnect(): void;
|
|
@@ -424,6 +455,17 @@ declare class PocketPingClient {
|
|
|
424
455
|
private scheduleReconnect;
|
|
425
456
|
private startPolling;
|
|
426
457
|
private stopPolling;
|
|
458
|
+
private setupUnloadListeners;
|
|
459
|
+
private cleanupUnloadListeners;
|
|
460
|
+
/**
|
|
461
|
+
* Notify backend that visitor is leaving
|
|
462
|
+
* Uses sendBeacon for reliability on page unload
|
|
463
|
+
*/
|
|
464
|
+
private notifyDisconnect;
|
|
465
|
+
/**
|
|
466
|
+
* Send visibility ping to backend (for inactivity tracking)
|
|
467
|
+
*/
|
|
468
|
+
private sendVisibilityPing;
|
|
427
469
|
private fetch;
|
|
428
470
|
private checkVersionHeaders;
|
|
429
471
|
private getOrCreateVisitorId;
|
package/dist/index.d.ts
CHANGED
|
@@ -6,6 +6,28 @@ interface ThemeColor {
|
|
|
6
6
|
light: string;
|
|
7
7
|
dark: string;
|
|
8
8
|
}
|
|
9
|
+
/**
|
|
10
|
+
* Gradient color value
|
|
11
|
+
* Creates a linear gradient between two colors
|
|
12
|
+
* @example { from: '#36e3ff', to: '#7c5cff', direction: 'to right' }
|
|
13
|
+
*/
|
|
14
|
+
interface GradientColor {
|
|
15
|
+
from: string;
|
|
16
|
+
to: string;
|
|
17
|
+
/** CSS gradient direction (default: 'to right') */
|
|
18
|
+
direction?: 'to right' | 'to left' | 'to bottom' | 'to top' | string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Color value that can be a solid color, gradient, or theme-aware
|
|
22
|
+
*/
|
|
23
|
+
type ColorValue = string | GradientColor | ThemeColor | ThemeGradientColor;
|
|
24
|
+
/**
|
|
25
|
+
* Theme-aware gradient - different gradients for light/dark themes
|
|
26
|
+
*/
|
|
27
|
+
interface ThemeGradientColor {
|
|
28
|
+
light: string | GradientColor;
|
|
29
|
+
dark: string | GradientColor;
|
|
30
|
+
}
|
|
9
31
|
interface PocketPingConfig {
|
|
10
32
|
/** Your backend endpoint for self-hosted (e.g., "https://yoursite.com/pocketping") */
|
|
11
33
|
endpoint?: string;
|
|
@@ -32,11 +54,14 @@ interface PocketPingConfig {
|
|
|
32
54
|
/** Text color on primary background (defaults to white) */
|
|
33
55
|
primaryTextColor?: string;
|
|
34
56
|
/**
|
|
35
|
-
* Header background color
|
|
36
|
-
* Can be a
|
|
37
|
-
* @example "#
|
|
57
|
+
* Header background color or gradient
|
|
58
|
+
* Can be a solid color, gradient, or theme-aware
|
|
59
|
+
* @example "#7c5cff"
|
|
60
|
+
* @example { from: '#36e3ff', to: '#7c5cff' }
|
|
61
|
+
* @example { light: "#7c5cff", dark: "#202c33" }
|
|
62
|
+
* @example { light: { from: '#36e3ff', to: '#7c5cff' }, dark: "#202c33" }
|
|
38
63
|
*/
|
|
39
|
-
headerColor?:
|
|
64
|
+
headerColor?: ColorValue;
|
|
40
65
|
/**
|
|
41
66
|
* Footer/input area background color
|
|
42
67
|
* Can be a string (same for both themes) or object with light/dark values
|
|
@@ -53,11 +78,13 @@ interface PocketPingConfig {
|
|
|
53
78
|
*/
|
|
54
79
|
chatBackground?: 'whatsapp' | 'dots' | 'plain' | string | ThemeColor;
|
|
55
80
|
/**
|
|
56
|
-
* Toggle button background color
|
|
57
|
-
* Can be a
|
|
58
|
-
* @example "#
|
|
81
|
+
* Toggle button background color or gradient
|
|
82
|
+
* Can be a solid color, gradient, or theme-aware
|
|
83
|
+
* @example "#7c5cff"
|
|
84
|
+
* @example { from: '#36e3ff', to: '#7c5cff' }
|
|
85
|
+
* @example { light: "#7c5cff", dark: "#7c5cff" }
|
|
59
86
|
*/
|
|
60
|
-
toggleColor?:
|
|
87
|
+
toggleColor?: ColorValue;
|
|
61
88
|
/** Widget position */
|
|
62
89
|
position?: 'bottom-right' | 'bottom-left';
|
|
63
90
|
/** Distance from edge in pixels (default: 20) */
|
|
@@ -273,6 +300,10 @@ declare class PocketPingClient {
|
|
|
273
300
|
private currentTrackedElements;
|
|
274
301
|
private inspectorMode;
|
|
275
302
|
private inspectorCleanup;
|
|
303
|
+
private connectedAt;
|
|
304
|
+
private disconnectNotified;
|
|
305
|
+
private boundHandleUnload;
|
|
306
|
+
private boundHandleVisibilityChange;
|
|
276
307
|
constructor(config: ResolvedPocketPingConfig);
|
|
277
308
|
connect(): Promise<Session>;
|
|
278
309
|
disconnect(): void;
|
|
@@ -424,6 +455,17 @@ declare class PocketPingClient {
|
|
|
424
455
|
private scheduleReconnect;
|
|
425
456
|
private startPolling;
|
|
426
457
|
private stopPolling;
|
|
458
|
+
private setupUnloadListeners;
|
|
459
|
+
private cleanupUnloadListeners;
|
|
460
|
+
/**
|
|
461
|
+
* Notify backend that visitor is leaving
|
|
462
|
+
* Uses sendBeacon for reliability on page unload
|
|
463
|
+
*/
|
|
464
|
+
private notifyDisconnect;
|
|
465
|
+
/**
|
|
466
|
+
* Send visibility ping to backend (for inactivity tracking)
|
|
467
|
+
*/
|
|
468
|
+
private sendVisibilityPing;
|
|
427
469
|
private fetch;
|
|
428
470
|
private checkVersionHeaders;
|
|
429
471
|
private getOrCreateVisitorId;
|