@pocketping/widget 2.3.0 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +160 -3
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +160 -3
- package/dist/pocketping.min.global.js +17 -17
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -705,7 +705,7 @@ function styles(options) {
|
|
|
705
705
|
|
|
706
706
|
.pp-input-form {
|
|
707
707
|
display: flex;
|
|
708
|
-
padding:
|
|
708
|
+
padding: 12px 10px 6px;
|
|
709
709
|
gap: 8px;
|
|
710
710
|
background: ${resolvedFooterColor};
|
|
711
711
|
align-items: flex-end;
|
|
@@ -2991,9 +2991,23 @@ function AttachmentDisplay({ attachment }) {
|
|
|
2991
2991
|
}
|
|
2992
2992
|
|
|
2993
2993
|
// src/version.ts
|
|
2994
|
-
var VERSION = "0.3.
|
|
2994
|
+
var VERSION = "0.3.8";
|
|
2995
2995
|
|
|
2996
2996
|
// src/client.ts
|
|
2997
|
+
function detectBotSignals() {
|
|
2998
|
+
return {
|
|
2999
|
+
// navigator.webdriver is true in Puppeteer/Selenium/Playwright
|
|
3000
|
+
webdriver: !!navigator.webdriver,
|
|
3001
|
+
// Headless browsers typically have no plugins
|
|
3002
|
+
plugins: navigator.plugins.length === 0,
|
|
3003
|
+
// Headless browsers may have empty languages
|
|
3004
|
+
languages: navigator.languages.length === 0,
|
|
3005
|
+
// HeadlessChrome doesn't have window.chrome
|
|
3006
|
+
chrome: /Chrome/.test(navigator.userAgent) && typeof window.chrome === "undefined",
|
|
3007
|
+
// Notification permission in headless is often 'denied' by default
|
|
3008
|
+
permissions: typeof Notification !== "undefined" && Notification.permission === "denied"
|
|
3009
|
+
};
|
|
3010
|
+
}
|
|
2997
3011
|
var PocketPingClient = class {
|
|
2998
3012
|
constructor(config) {
|
|
2999
3013
|
this.session = null;
|
|
@@ -3044,7 +3058,8 @@ var PocketPingClient = class {
|
|
|
3044
3058
|
userAgent: navigator.userAgent,
|
|
3045
3059
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
3046
3060
|
language: navigator.language,
|
|
3047
|
-
screenResolution: `${window.screen.width}x${window.screen.height}
|
|
3061
|
+
screenResolution: `${window.screen.width}x${window.screen.height}`,
|
|
3062
|
+
botSignals: detectBotSignals()
|
|
3048
3063
|
},
|
|
3049
3064
|
// Include stored identity if available
|
|
3050
3065
|
identity: storedIdentity || void 0
|
|
@@ -4009,6 +4024,14 @@ var PocketPingClient = class {
|
|
|
4009
4024
|
console.error("[PocketPing] Failed to parse SSE message:", err);
|
|
4010
4025
|
}
|
|
4011
4026
|
});
|
|
4027
|
+
this.sse.addEventListener("screenshot_request", (event) => {
|
|
4028
|
+
try {
|
|
4029
|
+
const data = JSON.parse(event.data);
|
|
4030
|
+
this.handleRealtimeEvent(data);
|
|
4031
|
+
} catch (err) {
|
|
4032
|
+
console.error("[PocketPing] Failed to parse SSE screenshot_request:", err);
|
|
4033
|
+
}
|
|
4034
|
+
});
|
|
4012
4035
|
this.sse.addEventListener("connected", () => {
|
|
4013
4036
|
});
|
|
4014
4037
|
this.sse.onerror = () => {
|
|
@@ -4191,6 +4214,10 @@ var PocketPingClient = class {
|
|
|
4191
4214
|
this.emit("configUpdate", configData);
|
|
4192
4215
|
}
|
|
4193
4216
|
break;
|
|
4217
|
+
case "screenshot_request":
|
|
4218
|
+
const screenshotData = event.data;
|
|
4219
|
+
this.handleScreenshotRequest(screenshotData);
|
|
4220
|
+
break;
|
|
4194
4221
|
}
|
|
4195
4222
|
}
|
|
4196
4223
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -4237,6 +4264,7 @@ var PocketPingClient = class {
|
|
|
4237
4264
|
try {
|
|
4238
4265
|
const lastEventTimestamp = this.getLastEventTimestamp();
|
|
4239
4266
|
const newMessages = await this.fetchMessages(lastEventTimestamp ?? void 0);
|
|
4267
|
+
await this.pollScreenshotRequests();
|
|
4240
4268
|
this.pollingFailures = 0;
|
|
4241
4269
|
for (const message of newMessages) {
|
|
4242
4270
|
const existingIndex = this.session.messages.findIndex((m) => m.id === message.id);
|
|
@@ -4487,6 +4515,135 @@ var PocketPingClient = class {
|
|
|
4487
4515
|
generateId() {
|
|
4488
4516
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
4489
4517
|
}
|
|
4518
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4519
|
+
// Screenshot Request Polling (for polling fallback mode)
|
|
4520
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4521
|
+
async pollScreenshotRequests() {
|
|
4522
|
+
if (!this.session) return;
|
|
4523
|
+
try {
|
|
4524
|
+
const response = await this.fetch(`/screenshot/requests?sessionId=${this.session.sessionId}`, { method: "GET" });
|
|
4525
|
+
for (const request of response.requests || []) {
|
|
4526
|
+
this.handleScreenshotRequest(request);
|
|
4527
|
+
}
|
|
4528
|
+
} catch (err) {
|
|
4529
|
+
}
|
|
4530
|
+
}
|
|
4531
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4532
|
+
// Screenshot Capture
|
|
4533
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4534
|
+
/**
|
|
4535
|
+
* Handle screenshot request from operator
|
|
4536
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
4537
|
+
*/
|
|
4538
|
+
async handleScreenshotRequest(data) {
|
|
4539
|
+
console.log("[PocketPing] Screenshot requested by", data.requestedBy, "via", data.requestedFrom, data.silent ? "(silent)" : "");
|
|
4540
|
+
try {
|
|
4541
|
+
const blob = await this.captureScreenshot();
|
|
4542
|
+
const initResponse = await this.fetch("/screenshot/upload", {
|
|
4543
|
+
method: "POST",
|
|
4544
|
+
body: JSON.stringify({
|
|
4545
|
+
sessionId: this.session?.sessionId,
|
|
4546
|
+
requestId: data.requestId
|
|
4547
|
+
})
|
|
4548
|
+
});
|
|
4549
|
+
const uploadResponse = await fetch(initResponse.uploadUrl, {
|
|
4550
|
+
method: "PUT",
|
|
4551
|
+
body: blob,
|
|
4552
|
+
headers: {
|
|
4553
|
+
"Content-Type": "image/png"
|
|
4554
|
+
}
|
|
4555
|
+
});
|
|
4556
|
+
if (!uploadResponse.ok) {
|
|
4557
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
4558
|
+
}
|
|
4559
|
+
await this.fetch("/screenshot/upload/complete", {
|
|
4560
|
+
method: "POST",
|
|
4561
|
+
body: JSON.stringify({
|
|
4562
|
+
sessionId: this.session?.sessionId,
|
|
4563
|
+
requestId: data.requestId,
|
|
4564
|
+
attachmentId: initResponse.attachmentId,
|
|
4565
|
+
size: blob.size
|
|
4566
|
+
})
|
|
4567
|
+
});
|
|
4568
|
+
console.log("[PocketPing] Screenshot captured and uploaded successfully");
|
|
4569
|
+
} catch (error) {
|
|
4570
|
+
console.error("[PocketPing] Screenshot capture failed:", error);
|
|
4571
|
+
}
|
|
4572
|
+
}
|
|
4573
|
+
/**
|
|
4574
|
+
* Capture screenshot of the viewport using html2canvas
|
|
4575
|
+
*/
|
|
4576
|
+
async captureScreenshot() {
|
|
4577
|
+
const html2canvas = await this.loadHtml2Canvas();
|
|
4578
|
+
const widgetContainer = document.getElementById("pocketping-widget");
|
|
4579
|
+
const widgetToggle = document.getElementById("pocketping-toggle");
|
|
4580
|
+
let widgetWasVisible = false;
|
|
4581
|
+
let toggleWasVisible = false;
|
|
4582
|
+
if (widgetContainer) {
|
|
4583
|
+
widgetWasVisible = widgetContainer.style.display !== "none";
|
|
4584
|
+
widgetContainer.style.display = "none";
|
|
4585
|
+
}
|
|
4586
|
+
if (widgetToggle) {
|
|
4587
|
+
toggleWasVisible = widgetToggle.style.display !== "none";
|
|
4588
|
+
widgetToggle.style.display = "none";
|
|
4589
|
+
}
|
|
4590
|
+
try {
|
|
4591
|
+
const canvas = await html2canvas(document.documentElement, {
|
|
4592
|
+
width: window.innerWidth,
|
|
4593
|
+
height: window.innerHeight,
|
|
4594
|
+
x: window.scrollX,
|
|
4595
|
+
y: window.scrollY,
|
|
4596
|
+
windowWidth: window.innerWidth,
|
|
4597
|
+
windowHeight: window.innerHeight,
|
|
4598
|
+
logging: false,
|
|
4599
|
+
useCORS: true,
|
|
4600
|
+
allowTaint: true
|
|
4601
|
+
});
|
|
4602
|
+
return new Promise((resolve, reject) => {
|
|
4603
|
+
canvas.toBlob(
|
|
4604
|
+
(blob) => {
|
|
4605
|
+
if (blob) {
|
|
4606
|
+
resolve(blob);
|
|
4607
|
+
} else {
|
|
4608
|
+
reject(new Error("Failed to create blob from canvas"));
|
|
4609
|
+
}
|
|
4610
|
+
},
|
|
4611
|
+
"image/png",
|
|
4612
|
+
0.9
|
|
4613
|
+
);
|
|
4614
|
+
});
|
|
4615
|
+
} finally {
|
|
4616
|
+
if (widgetContainer && widgetWasVisible) {
|
|
4617
|
+
widgetContainer.style.display = "";
|
|
4618
|
+
}
|
|
4619
|
+
if (widgetToggle && toggleWasVisible) {
|
|
4620
|
+
widgetToggle.style.display = "";
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
}
|
|
4624
|
+
/**
|
|
4625
|
+
* Dynamically load html2canvas from CDN
|
|
4626
|
+
*/
|
|
4627
|
+
async loadHtml2Canvas() {
|
|
4628
|
+
const win = window;
|
|
4629
|
+
if (typeof win.html2canvas !== "undefined") {
|
|
4630
|
+
return win.html2canvas;
|
|
4631
|
+
}
|
|
4632
|
+
return new Promise((resolve, reject) => {
|
|
4633
|
+
const script = document.createElement("script");
|
|
4634
|
+
script.src = "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js";
|
|
4635
|
+
script.onload = () => {
|
|
4636
|
+
const w = window;
|
|
4637
|
+
if (typeof w.html2canvas !== "undefined") {
|
|
4638
|
+
resolve(w.html2canvas);
|
|
4639
|
+
} else {
|
|
4640
|
+
reject(new Error("html2canvas failed to load"));
|
|
4641
|
+
}
|
|
4642
|
+
};
|
|
4643
|
+
script.onerror = () => reject(new Error("Failed to load html2canvas from CDN"));
|
|
4644
|
+
document.head.appendChild(script);
|
|
4645
|
+
});
|
|
4646
|
+
}
|
|
4490
4647
|
};
|
|
4491
4648
|
|
|
4492
4649
|
// src/index.ts
|
package/dist/index.d.cts
CHANGED
|
@@ -475,6 +475,20 @@ declare class PocketPingClient {
|
|
|
475
475
|
private storeIdentity;
|
|
476
476
|
private clearIdentity;
|
|
477
477
|
private generateId;
|
|
478
|
+
private pollScreenshotRequests;
|
|
479
|
+
/**
|
|
480
|
+
* Handle screenshot request from operator
|
|
481
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
482
|
+
*/
|
|
483
|
+
private handleScreenshotRequest;
|
|
484
|
+
/**
|
|
485
|
+
* Capture screenshot of the viewport using html2canvas
|
|
486
|
+
*/
|
|
487
|
+
private captureScreenshot;
|
|
488
|
+
/**
|
|
489
|
+
* Dynamically load html2canvas from CDN
|
|
490
|
+
*/
|
|
491
|
+
private loadHtml2Canvas;
|
|
478
492
|
}
|
|
479
493
|
|
|
480
494
|
declare function init(config: PocketPingConfig): PocketPingClient;
|
package/dist/index.d.ts
CHANGED
|
@@ -475,6 +475,20 @@ declare class PocketPingClient {
|
|
|
475
475
|
private storeIdentity;
|
|
476
476
|
private clearIdentity;
|
|
477
477
|
private generateId;
|
|
478
|
+
private pollScreenshotRequests;
|
|
479
|
+
/**
|
|
480
|
+
* Handle screenshot request from operator
|
|
481
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
482
|
+
*/
|
|
483
|
+
private handleScreenshotRequest;
|
|
484
|
+
/**
|
|
485
|
+
* Capture screenshot of the viewport using html2canvas
|
|
486
|
+
*/
|
|
487
|
+
private captureScreenshot;
|
|
488
|
+
/**
|
|
489
|
+
* Dynamically load html2canvas from CDN
|
|
490
|
+
*/
|
|
491
|
+
private loadHtml2Canvas;
|
|
478
492
|
}
|
|
479
493
|
|
|
480
494
|
declare function init(config: PocketPingConfig): PocketPingClient;
|
package/dist/index.js
CHANGED
|
@@ -664,7 +664,7 @@ function styles(options) {
|
|
|
664
664
|
|
|
665
665
|
.pp-input-form {
|
|
666
666
|
display: flex;
|
|
667
|
-
padding:
|
|
667
|
+
padding: 12px 10px 6px;
|
|
668
668
|
gap: 8px;
|
|
669
669
|
background: ${resolvedFooterColor};
|
|
670
670
|
align-items: flex-end;
|
|
@@ -2950,9 +2950,23 @@ function AttachmentDisplay({ attachment }) {
|
|
|
2950
2950
|
}
|
|
2951
2951
|
|
|
2952
2952
|
// src/version.ts
|
|
2953
|
-
var VERSION = "0.3.
|
|
2953
|
+
var VERSION = "0.3.8";
|
|
2954
2954
|
|
|
2955
2955
|
// src/client.ts
|
|
2956
|
+
function detectBotSignals() {
|
|
2957
|
+
return {
|
|
2958
|
+
// navigator.webdriver is true in Puppeteer/Selenium/Playwright
|
|
2959
|
+
webdriver: !!navigator.webdriver,
|
|
2960
|
+
// Headless browsers typically have no plugins
|
|
2961
|
+
plugins: navigator.plugins.length === 0,
|
|
2962
|
+
// Headless browsers may have empty languages
|
|
2963
|
+
languages: navigator.languages.length === 0,
|
|
2964
|
+
// HeadlessChrome doesn't have window.chrome
|
|
2965
|
+
chrome: /Chrome/.test(navigator.userAgent) && typeof window.chrome === "undefined",
|
|
2966
|
+
// Notification permission in headless is often 'denied' by default
|
|
2967
|
+
permissions: typeof Notification !== "undefined" && Notification.permission === "denied"
|
|
2968
|
+
};
|
|
2969
|
+
}
|
|
2956
2970
|
var PocketPingClient = class {
|
|
2957
2971
|
constructor(config) {
|
|
2958
2972
|
this.session = null;
|
|
@@ -3003,7 +3017,8 @@ var PocketPingClient = class {
|
|
|
3003
3017
|
userAgent: navigator.userAgent,
|
|
3004
3018
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
3005
3019
|
language: navigator.language,
|
|
3006
|
-
screenResolution: `${window.screen.width}x${window.screen.height}
|
|
3020
|
+
screenResolution: `${window.screen.width}x${window.screen.height}`,
|
|
3021
|
+
botSignals: detectBotSignals()
|
|
3007
3022
|
},
|
|
3008
3023
|
// Include stored identity if available
|
|
3009
3024
|
identity: storedIdentity || void 0
|
|
@@ -3968,6 +3983,14 @@ var PocketPingClient = class {
|
|
|
3968
3983
|
console.error("[PocketPing] Failed to parse SSE message:", err);
|
|
3969
3984
|
}
|
|
3970
3985
|
});
|
|
3986
|
+
this.sse.addEventListener("screenshot_request", (event) => {
|
|
3987
|
+
try {
|
|
3988
|
+
const data = JSON.parse(event.data);
|
|
3989
|
+
this.handleRealtimeEvent(data);
|
|
3990
|
+
} catch (err) {
|
|
3991
|
+
console.error("[PocketPing] Failed to parse SSE screenshot_request:", err);
|
|
3992
|
+
}
|
|
3993
|
+
});
|
|
3971
3994
|
this.sse.addEventListener("connected", () => {
|
|
3972
3995
|
});
|
|
3973
3996
|
this.sse.onerror = () => {
|
|
@@ -4150,6 +4173,10 @@ var PocketPingClient = class {
|
|
|
4150
4173
|
this.emit("configUpdate", configData);
|
|
4151
4174
|
}
|
|
4152
4175
|
break;
|
|
4176
|
+
case "screenshot_request":
|
|
4177
|
+
const screenshotData = event.data;
|
|
4178
|
+
this.handleScreenshotRequest(screenshotData);
|
|
4179
|
+
break;
|
|
4153
4180
|
}
|
|
4154
4181
|
}
|
|
4155
4182
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -4196,6 +4223,7 @@ var PocketPingClient = class {
|
|
|
4196
4223
|
try {
|
|
4197
4224
|
const lastEventTimestamp = this.getLastEventTimestamp();
|
|
4198
4225
|
const newMessages = await this.fetchMessages(lastEventTimestamp ?? void 0);
|
|
4226
|
+
await this.pollScreenshotRequests();
|
|
4199
4227
|
this.pollingFailures = 0;
|
|
4200
4228
|
for (const message of newMessages) {
|
|
4201
4229
|
const existingIndex = this.session.messages.findIndex((m) => m.id === message.id);
|
|
@@ -4446,6 +4474,135 @@ var PocketPingClient = class {
|
|
|
4446
4474
|
generateId() {
|
|
4447
4475
|
return `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;
|
|
4448
4476
|
}
|
|
4477
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4478
|
+
// Screenshot Request Polling (for polling fallback mode)
|
|
4479
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4480
|
+
async pollScreenshotRequests() {
|
|
4481
|
+
if (!this.session) return;
|
|
4482
|
+
try {
|
|
4483
|
+
const response = await this.fetch(`/screenshot/requests?sessionId=${this.session.sessionId}`, { method: "GET" });
|
|
4484
|
+
for (const request of response.requests || []) {
|
|
4485
|
+
this.handleScreenshotRequest(request);
|
|
4486
|
+
}
|
|
4487
|
+
} catch (err) {
|
|
4488
|
+
}
|
|
4489
|
+
}
|
|
4490
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4491
|
+
// Screenshot Capture
|
|
4492
|
+
// ─────────────────────────────────────────────────────────────────
|
|
4493
|
+
/**
|
|
4494
|
+
* Handle screenshot request from operator
|
|
4495
|
+
* @param data.silent - If true, screenshot won't appear in widget chat (only sent to bridges)
|
|
4496
|
+
*/
|
|
4497
|
+
async handleScreenshotRequest(data) {
|
|
4498
|
+
console.log("[PocketPing] Screenshot requested by", data.requestedBy, "via", data.requestedFrom, data.silent ? "(silent)" : "");
|
|
4499
|
+
try {
|
|
4500
|
+
const blob = await this.captureScreenshot();
|
|
4501
|
+
const initResponse = await this.fetch("/screenshot/upload", {
|
|
4502
|
+
method: "POST",
|
|
4503
|
+
body: JSON.stringify({
|
|
4504
|
+
sessionId: this.session?.sessionId,
|
|
4505
|
+
requestId: data.requestId
|
|
4506
|
+
})
|
|
4507
|
+
});
|
|
4508
|
+
const uploadResponse = await fetch(initResponse.uploadUrl, {
|
|
4509
|
+
method: "PUT",
|
|
4510
|
+
body: blob,
|
|
4511
|
+
headers: {
|
|
4512
|
+
"Content-Type": "image/png"
|
|
4513
|
+
}
|
|
4514
|
+
});
|
|
4515
|
+
if (!uploadResponse.ok) {
|
|
4516
|
+
throw new Error(`Upload failed: ${uploadResponse.status}`);
|
|
4517
|
+
}
|
|
4518
|
+
await this.fetch("/screenshot/upload/complete", {
|
|
4519
|
+
method: "POST",
|
|
4520
|
+
body: JSON.stringify({
|
|
4521
|
+
sessionId: this.session?.sessionId,
|
|
4522
|
+
requestId: data.requestId,
|
|
4523
|
+
attachmentId: initResponse.attachmentId,
|
|
4524
|
+
size: blob.size
|
|
4525
|
+
})
|
|
4526
|
+
});
|
|
4527
|
+
console.log("[PocketPing] Screenshot captured and uploaded successfully");
|
|
4528
|
+
} catch (error) {
|
|
4529
|
+
console.error("[PocketPing] Screenshot capture failed:", error);
|
|
4530
|
+
}
|
|
4531
|
+
}
|
|
4532
|
+
/**
|
|
4533
|
+
* Capture screenshot of the viewport using html2canvas
|
|
4534
|
+
*/
|
|
4535
|
+
async captureScreenshot() {
|
|
4536
|
+
const html2canvas = await this.loadHtml2Canvas();
|
|
4537
|
+
const widgetContainer = document.getElementById("pocketping-widget");
|
|
4538
|
+
const widgetToggle = document.getElementById("pocketping-toggle");
|
|
4539
|
+
let widgetWasVisible = false;
|
|
4540
|
+
let toggleWasVisible = false;
|
|
4541
|
+
if (widgetContainer) {
|
|
4542
|
+
widgetWasVisible = widgetContainer.style.display !== "none";
|
|
4543
|
+
widgetContainer.style.display = "none";
|
|
4544
|
+
}
|
|
4545
|
+
if (widgetToggle) {
|
|
4546
|
+
toggleWasVisible = widgetToggle.style.display !== "none";
|
|
4547
|
+
widgetToggle.style.display = "none";
|
|
4548
|
+
}
|
|
4549
|
+
try {
|
|
4550
|
+
const canvas = await html2canvas(document.documentElement, {
|
|
4551
|
+
width: window.innerWidth,
|
|
4552
|
+
height: window.innerHeight,
|
|
4553
|
+
x: window.scrollX,
|
|
4554
|
+
y: window.scrollY,
|
|
4555
|
+
windowWidth: window.innerWidth,
|
|
4556
|
+
windowHeight: window.innerHeight,
|
|
4557
|
+
logging: false,
|
|
4558
|
+
useCORS: true,
|
|
4559
|
+
allowTaint: true
|
|
4560
|
+
});
|
|
4561
|
+
return new Promise((resolve, reject) => {
|
|
4562
|
+
canvas.toBlob(
|
|
4563
|
+
(blob) => {
|
|
4564
|
+
if (blob) {
|
|
4565
|
+
resolve(blob);
|
|
4566
|
+
} else {
|
|
4567
|
+
reject(new Error("Failed to create blob from canvas"));
|
|
4568
|
+
}
|
|
4569
|
+
},
|
|
4570
|
+
"image/png",
|
|
4571
|
+
0.9
|
|
4572
|
+
);
|
|
4573
|
+
});
|
|
4574
|
+
} finally {
|
|
4575
|
+
if (widgetContainer && widgetWasVisible) {
|
|
4576
|
+
widgetContainer.style.display = "";
|
|
4577
|
+
}
|
|
4578
|
+
if (widgetToggle && toggleWasVisible) {
|
|
4579
|
+
widgetToggle.style.display = "";
|
|
4580
|
+
}
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
/**
|
|
4584
|
+
* Dynamically load html2canvas from CDN
|
|
4585
|
+
*/
|
|
4586
|
+
async loadHtml2Canvas() {
|
|
4587
|
+
const win = window;
|
|
4588
|
+
if (typeof win.html2canvas !== "undefined") {
|
|
4589
|
+
return win.html2canvas;
|
|
4590
|
+
}
|
|
4591
|
+
return new Promise((resolve, reject) => {
|
|
4592
|
+
const script = document.createElement("script");
|
|
4593
|
+
script.src = "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js";
|
|
4594
|
+
script.onload = () => {
|
|
4595
|
+
const w = window;
|
|
4596
|
+
if (typeof w.html2canvas !== "undefined") {
|
|
4597
|
+
resolve(w.html2canvas);
|
|
4598
|
+
} else {
|
|
4599
|
+
reject(new Error("html2canvas failed to load"));
|
|
4600
|
+
}
|
|
4601
|
+
};
|
|
4602
|
+
script.onerror = () => reject(new Error("Failed to load html2canvas from CDN"));
|
|
4603
|
+
document.head.appendChild(script);
|
|
4604
|
+
});
|
|
4605
|
+
}
|
|
4449
4606
|
};
|
|
4450
4607
|
|
|
4451
4608
|
// src/index.ts
|