@jarve/bug-reporter 0.2.0 → 0.3.1
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 +8 -7
- package/dist/index.d.mts +5 -1
- package/dist/index.d.ts +5 -1
- package/dist/index.js +226 -149
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +209 -132
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -43,9 +43,10 @@ __export(index_exports, {
|
|
|
43
43
|
module.exports = __toCommonJS(index_exports);
|
|
44
44
|
|
|
45
45
|
// src/bug-reporter.tsx
|
|
46
|
-
var
|
|
46
|
+
var import_react4 = require("react");
|
|
47
47
|
|
|
48
48
|
// src/floating-button.tsx
|
|
49
|
+
var import_react = require("react");
|
|
49
50
|
var import_lucide_react = require("lucide-react");
|
|
50
51
|
|
|
51
52
|
// src/cn.ts
|
|
@@ -57,26 +58,63 @@ function cn(...inputs) {
|
|
|
57
58
|
|
|
58
59
|
// src/floating-button.tsx
|
|
59
60
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
60
|
-
function FloatingButton({ isActive, onClick }) {
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
function FloatingButton({ isActive, onClick, position = "right" }) {
|
|
62
|
+
const [hovered, setHovered] = (0, import_react.useState)(false);
|
|
63
|
+
const isLeft = position === "left";
|
|
64
|
+
const sideClasses = isLeft ? "left-4 md:left-6" : "right-4 md:right-6";
|
|
65
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
66
|
+
"div",
|
|
63
67
|
{
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
68
|
+
className: cn("fixed z-[9999]", "bottom-4 md:bottom-6", sideClasses),
|
|
69
|
+
onMouseEnter: () => setHovered(true),
|
|
70
|
+
onMouseLeave: () => setHovered(false),
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
73
|
+
"div",
|
|
74
|
+
{
|
|
75
|
+
className: cn(
|
|
76
|
+
"pointer-events-none absolute bottom-full mb-2 w-max max-w-[200px] rounded-lg bg-gray-900 px-3 py-2 text-xs leading-relaxed text-white shadow-lg transition-all duration-200",
|
|
77
|
+
isLeft ? "left-0" : "right-0",
|
|
78
|
+
hovered && !isActive ? "translate-y-0 opacity-100" : "translate-y-1 opacity-0"
|
|
79
|
+
),
|
|
80
|
+
children: [
|
|
81
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "font-semibold", children: "Report a bug" }),
|
|
82
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("br", {}),
|
|
83
|
+
"Click to screenshot an issue and chat with AI to submit a bug report.",
|
|
84
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
85
|
+
"div",
|
|
86
|
+
{
|
|
87
|
+
className: cn(
|
|
88
|
+
"absolute top-full h-0 w-0 border-x-[6px] border-t-[6px] border-x-transparent border-t-gray-900",
|
|
89
|
+
isLeft ? "left-4" : "right-4"
|
|
90
|
+
)
|
|
91
|
+
}
|
|
92
|
+
)
|
|
93
|
+
]
|
|
94
|
+
}
|
|
95
|
+
),
|
|
96
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
97
|
+
"button",
|
|
98
|
+
{
|
|
99
|
+
onClick,
|
|
100
|
+
className: cn(
|
|
101
|
+
"flex items-center justify-center rounded-full shadow-lg transition-all duration-200",
|
|
102
|
+
"hover:scale-110 focus:ring-2 focus:ring-offset-2 focus:outline-none",
|
|
103
|
+
"h-11 w-11 md:h-12 md:w-12",
|
|
104
|
+
isActive ? "animate-pulse bg-red-500 text-white focus:ring-red-400" : "bg-indigo-600 text-white hover:bg-indigo-700 focus:ring-indigo-400"
|
|
105
|
+
),
|
|
106
|
+
title: isActive ? "Cancel bug capture" : "Report a bug",
|
|
107
|
+
"aria-label": isActive ? "Cancel bug capture" : "Report a bug",
|
|
108
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Bug, { className: "h-4 w-4 md:h-5 md:w-5" })
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
]
|
|
74
112
|
}
|
|
75
113
|
);
|
|
76
114
|
}
|
|
77
115
|
|
|
78
116
|
// src/capture-overlay.tsx
|
|
79
|
-
var
|
|
117
|
+
var import_react2 = require("react");
|
|
80
118
|
var import_html_to_image = require("html-to-image");
|
|
81
119
|
|
|
82
120
|
// src/utils.ts
|
|
@@ -196,8 +234,7 @@ var errorListener = null;
|
|
|
196
234
|
var rejectionListener = null;
|
|
197
235
|
function startCapturing() {
|
|
198
236
|
if (isCapturing) return;
|
|
199
|
-
if (console.error.__bugReporterPatched)
|
|
200
|
-
return;
|
|
237
|
+
if (console.error.__bugReporterPatched) return;
|
|
201
238
|
isCapturing = true;
|
|
202
239
|
capturedErrors = [];
|
|
203
240
|
originalConsoleError = console.error;
|
|
@@ -406,23 +443,23 @@ function CaptureOverlay({
|
|
|
406
443
|
onCapture,
|
|
407
444
|
onCancel
|
|
408
445
|
}) {
|
|
409
|
-
const [hoveredElement, setHoveredElement] = (0,
|
|
410
|
-
const [hoveredRect, setHoveredRect] = (0,
|
|
411
|
-
const [isCapturing3, setIsCapturing] = (0,
|
|
412
|
-
const [isTouchMode, setIsTouchMode] = (0,
|
|
413
|
-
const [selectedSection, setSelectedSection] = (0,
|
|
414
|
-
const [selectedRect, setSelectedRect] = (0,
|
|
415
|
-
const [selectedTarget, setSelectedTarget] = (0,
|
|
416
|
-
const overlayRef = (0,
|
|
417
|
-
const hoveredElementRef = (0,
|
|
418
|
-
const rafRef = (0,
|
|
419
|
-
const touchCoordsRef = (0,
|
|
420
|
-
(0,
|
|
446
|
+
const [hoveredElement, setHoveredElement] = (0, import_react2.useState)(null);
|
|
447
|
+
const [hoveredRect, setHoveredRect] = (0, import_react2.useState)(null);
|
|
448
|
+
const [isCapturing3, setIsCapturing] = (0, import_react2.useState)(false);
|
|
449
|
+
const [isTouchMode, setIsTouchMode] = (0, import_react2.useState)(false);
|
|
450
|
+
const [selectedSection, setSelectedSection] = (0, import_react2.useState)(null);
|
|
451
|
+
const [selectedRect, setSelectedRect] = (0, import_react2.useState)(null);
|
|
452
|
+
const [selectedTarget, setSelectedTarget] = (0, import_react2.useState)(null);
|
|
453
|
+
const overlayRef = (0, import_react2.useRef)(null);
|
|
454
|
+
const hoveredElementRef = (0, import_react2.useRef)(null);
|
|
455
|
+
const rafRef = (0, import_react2.useRef)(null);
|
|
456
|
+
const touchCoordsRef = (0, import_react2.useRef)(null);
|
|
457
|
+
(0, import_react2.useEffect)(() => {
|
|
421
458
|
if (isActive) {
|
|
422
459
|
setIsTouchMode(isTouchCapable());
|
|
423
460
|
}
|
|
424
461
|
}, [isActive]);
|
|
425
|
-
const captureScreenshot = (0,
|
|
462
|
+
const captureScreenshot = (0, import_react2.useCallback)(
|
|
426
463
|
async (section, target, coords) => {
|
|
427
464
|
const elementInfo = collectElementInfo(target, section, coords);
|
|
428
465
|
setIsCapturing(true);
|
|
@@ -443,12 +480,21 @@ function CaptureOverlay({
|
|
|
443
480
|
skipFonts: true
|
|
444
481
|
});
|
|
445
482
|
const blob = dataUrlToBlob(dataUrl);
|
|
446
|
-
const metadata = collectMetadata(
|
|
483
|
+
const metadata = collectMetadata(
|
|
484
|
+
section,
|
|
485
|
+
siteId,
|
|
486
|
+
reporterName,
|
|
487
|
+
reporterEmail,
|
|
488
|
+
elementInfo
|
|
489
|
+
);
|
|
447
490
|
const consoleErrors = getCapturedErrors();
|
|
448
491
|
const networkErrors = getCapturedNetworkErrors();
|
|
449
492
|
onCapture({ screenshot: blob, metadata, consoleErrors, networkErrors });
|
|
450
493
|
} catch (err) {
|
|
451
|
-
console.warn(
|
|
494
|
+
console.warn(
|
|
495
|
+
"Bug reporter: first capture attempt failed, retrying with simpler settings",
|
|
496
|
+
err
|
|
497
|
+
);
|
|
452
498
|
try {
|
|
453
499
|
const dataUrl = await (0, import_html_to_image.toPng)(section, {
|
|
454
500
|
quality: 0.6,
|
|
@@ -457,13 +503,25 @@ function CaptureOverlay({
|
|
|
457
503
|
cacheBust: true
|
|
458
504
|
});
|
|
459
505
|
const retryBlob = dataUrlToBlob(dataUrl);
|
|
460
|
-
const metadata = collectMetadata(
|
|
506
|
+
const metadata = collectMetadata(
|
|
507
|
+
section,
|
|
508
|
+
siteId,
|
|
509
|
+
reporterName,
|
|
510
|
+
reporterEmail,
|
|
511
|
+
elementInfo
|
|
512
|
+
);
|
|
461
513
|
const consoleErrors = getCapturedErrors();
|
|
462
514
|
const networkErrors = getCapturedNetworkErrors();
|
|
463
515
|
onCapture({ screenshot: retryBlob, metadata, consoleErrors, networkErrors });
|
|
464
516
|
} catch (e) {
|
|
465
517
|
console.error("Bug reporter: screenshot capture failed after retry");
|
|
466
|
-
const metadata = collectMetadata(
|
|
518
|
+
const metadata = collectMetadata(
|
|
519
|
+
section,
|
|
520
|
+
siteId,
|
|
521
|
+
reporterName,
|
|
522
|
+
reporterEmail,
|
|
523
|
+
elementInfo
|
|
524
|
+
);
|
|
467
525
|
const consoleErrors = getCapturedErrors();
|
|
468
526
|
const networkErrors = getCapturedNetworkErrors();
|
|
469
527
|
onCapture({
|
|
@@ -479,7 +537,7 @@ function CaptureOverlay({
|
|
|
479
537
|
},
|
|
480
538
|
[siteId, reporterName, reporterEmail, onCapture]
|
|
481
539
|
);
|
|
482
|
-
const handleMouseMove = (0,
|
|
540
|
+
const handleMouseMove = (0, import_react2.useCallback)(
|
|
483
541
|
(e) => {
|
|
484
542
|
if (!isActive || isCapturing3 || isTouchMode) return;
|
|
485
543
|
if (rafRef.current) return;
|
|
@@ -501,7 +559,7 @@ function CaptureOverlay({
|
|
|
501
559
|
},
|
|
502
560
|
[isActive, isCapturing3, isTouchMode]
|
|
503
561
|
);
|
|
504
|
-
const handleClick = (0,
|
|
562
|
+
const handleClick = (0, import_react2.useCallback)(
|
|
505
563
|
async (e) => {
|
|
506
564
|
if (!isActive || isCapturing3 || isTouchMode) return;
|
|
507
565
|
const target = e.target;
|
|
@@ -515,7 +573,7 @@ function CaptureOverlay({
|
|
|
515
573
|
},
|
|
516
574
|
[isActive, isCapturing3, isTouchMode, captureScreenshot]
|
|
517
575
|
);
|
|
518
|
-
const handleTouchEnd = (0,
|
|
576
|
+
const handleTouchEnd = (0, import_react2.useCallback)(
|
|
519
577
|
(e) => {
|
|
520
578
|
if (!isActive || isCapturing3) return;
|
|
521
579
|
const touch = e.changedTouches[0];
|
|
@@ -532,11 +590,11 @@ function CaptureOverlay({
|
|
|
532
590
|
},
|
|
533
591
|
[isActive, isCapturing3]
|
|
534
592
|
);
|
|
535
|
-
const handleConfirmCapture = (0,
|
|
593
|
+
const handleConfirmCapture = (0, import_react2.useCallback)(async () => {
|
|
536
594
|
if (!selectedSection || !selectedTarget || !touchCoordsRef.current) return;
|
|
537
595
|
await captureScreenshot(selectedSection, selectedTarget, touchCoordsRef.current);
|
|
538
596
|
}, [selectedSection, selectedTarget, captureScreenshot]);
|
|
539
|
-
const handlePointerDown = (0,
|
|
597
|
+
const handlePointerDown = (0, import_react2.useCallback)(
|
|
540
598
|
(e) => {
|
|
541
599
|
if (!isActive) return;
|
|
542
600
|
if (e.pointerType === "touch") {
|
|
@@ -547,7 +605,7 @@ function CaptureOverlay({
|
|
|
547
605
|
},
|
|
548
606
|
[isActive]
|
|
549
607
|
);
|
|
550
|
-
const handleKeyDown = (0,
|
|
608
|
+
const handleKeyDown = (0, import_react2.useCallback)(
|
|
551
609
|
(e) => {
|
|
552
610
|
if (e.key === "Escape" && isActive) {
|
|
553
611
|
e.preventDefault();
|
|
@@ -557,7 +615,7 @@ function CaptureOverlay({
|
|
|
557
615
|
},
|
|
558
616
|
[isActive, onCancel]
|
|
559
617
|
);
|
|
560
|
-
const handleScroll = (0,
|
|
618
|
+
const handleScroll = (0, import_react2.useCallback)(() => {
|
|
561
619
|
if (hoveredElementRef.current) {
|
|
562
620
|
setHoveredRect(hoveredElementRef.current.getBoundingClientRect());
|
|
563
621
|
}
|
|
@@ -565,7 +623,7 @@ function CaptureOverlay({
|
|
|
565
623
|
setSelectedRect(selectedSection.getBoundingClientRect());
|
|
566
624
|
}
|
|
567
625
|
}, [selectedSection]);
|
|
568
|
-
(0,
|
|
626
|
+
(0, import_react2.useEffect)(() => {
|
|
569
627
|
if (!isActive) {
|
|
570
628
|
setHoveredElement(null);
|
|
571
629
|
setHoveredRect(null);
|
|
@@ -594,7 +652,16 @@ function CaptureOverlay({
|
|
|
594
652
|
document.removeEventListener("click", handleClick, true);
|
|
595
653
|
if (rafRef.current) cancelAnimationFrame(rafRef.current);
|
|
596
654
|
};
|
|
597
|
-
}, [
|
|
655
|
+
}, [
|
|
656
|
+
isActive,
|
|
657
|
+
isTouchMode,
|
|
658
|
+
handleMouseMove,
|
|
659
|
+
handleClick,
|
|
660
|
+
handleTouchEnd,
|
|
661
|
+
handlePointerDown,
|
|
662
|
+
handleKeyDown,
|
|
663
|
+
handleScroll
|
|
664
|
+
]);
|
|
598
665
|
const highlightRect = isTouchMode ? selectedRect : hoveredRect;
|
|
599
666
|
const showHighlight = isTouchMode ? !!selectedSection : !!hoveredElement && !!hoveredRect;
|
|
600
667
|
if (!isActive) return null;
|
|
@@ -605,20 +672,21 @@ function CaptureOverlay({
|
|
|
605
672
|
"data-bug-reporter": true,
|
|
606
673
|
role: "alert",
|
|
607
674
|
"aria-live": "assertive",
|
|
608
|
-
className: "fixed top-0
|
|
675
|
+
className: "fixed top-0 right-0 left-0 z-[10000] flex items-center justify-center gap-3 bg-indigo-600 px-4 py-2 text-center text-sm font-medium text-white",
|
|
609
676
|
children: isTouchMode ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
610
677
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { children: "Tap the section with the bug" }),
|
|
611
678
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
612
679
|
"button",
|
|
613
680
|
{
|
|
614
681
|
onClick: onCancel,
|
|
615
|
-
className: "
|
|
682
|
+
className: "min-h-[44px] rounded-md bg-white/20 px-3 py-1 text-sm font-medium",
|
|
616
683
|
children: "Cancel"
|
|
617
684
|
}
|
|
618
685
|
)
|
|
619
686
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
620
|
-
"Click on the section with the bug. Press
|
|
621
|
-
|
|
687
|
+
"Click on the section with the bug. Press",
|
|
688
|
+
" ",
|
|
689
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("kbd", { className: "mx-1 rounded bg-indigo-800 px-1.5 py-0.5 text-xs", children: "Esc" }),
|
|
622
690
|
" to cancel."
|
|
623
691
|
] })
|
|
624
692
|
}
|
|
@@ -628,7 +696,7 @@ function CaptureOverlay({
|
|
|
628
696
|
{
|
|
629
697
|
ref: overlayRef,
|
|
630
698
|
"data-bug-reporter": true,
|
|
631
|
-
className: "
|
|
699
|
+
className: "pointer-events-none fixed z-[9998] rounded-sm border-2 border-indigo-500 transition-all duration-150 ease-out",
|
|
632
700
|
style: {
|
|
633
701
|
top: highlightRect.top - 2,
|
|
634
702
|
left: highlightRect.left - 2,
|
|
@@ -642,11 +710,11 @@ function CaptureOverlay({
|
|
|
642
710
|
"div",
|
|
643
711
|
{
|
|
644
712
|
"data-bug-reporter": true,
|
|
645
|
-
className: "fixed
|
|
713
|
+
className: "fixed right-0 bottom-0 left-0 z-[10000] border-t border-gray-200 bg-white shadow-lg",
|
|
646
714
|
style: { paddingBottom: "env(safe-area-inset-bottom, 0px)" },
|
|
647
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between px-4 py-3
|
|
648
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "text-sm font-medium text-gray-900
|
|
649
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex gap-2
|
|
715
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center justify-between gap-3 px-4 py-3", children: [
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "truncate text-sm font-medium text-gray-900", children: "Capture this section?" }),
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex shrink-0 gap-2", children: [
|
|
650
718
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
651
719
|
"button",
|
|
652
720
|
{
|
|
@@ -656,7 +724,7 @@ function CaptureOverlay({
|
|
|
656
724
|
setSelectedTarget(null);
|
|
657
725
|
touchCoordsRef.current = null;
|
|
658
726
|
},
|
|
659
|
-
className: "
|
|
727
|
+
className: "min-h-[44px] rounded-md border border-gray-300 px-4 text-sm font-medium text-gray-700",
|
|
660
728
|
children: "Cancel"
|
|
661
729
|
}
|
|
662
730
|
),
|
|
@@ -664,7 +732,7 @@ function CaptureOverlay({
|
|
|
664
732
|
"button",
|
|
665
733
|
{
|
|
666
734
|
onClick: handleConfirmCapture,
|
|
667
|
-
className: "
|
|
735
|
+
className: "min-h-[44px] rounded-md bg-indigo-600 px-4 text-sm font-medium text-white",
|
|
668
736
|
children: "Capture"
|
|
669
737
|
}
|
|
670
738
|
)
|
|
@@ -677,7 +745,7 @@ function CaptureOverlay({
|
|
|
677
745
|
}
|
|
678
746
|
|
|
679
747
|
// src/report-modal.tsx
|
|
680
|
-
var
|
|
748
|
+
var import_react3 = require("react");
|
|
681
749
|
var import_lucide_react2 = require("lucide-react");
|
|
682
750
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
683
751
|
function ReportModal({
|
|
@@ -688,24 +756,24 @@ function ReportModal({
|
|
|
688
756
|
user,
|
|
689
757
|
onClose
|
|
690
758
|
}) {
|
|
691
|
-
const [messages, setMessages] = (0,
|
|
692
|
-
const [input, setInput] = (0,
|
|
693
|
-
const [isLoading, setIsLoading] = (0,
|
|
694
|
-
const [modalState, setModalState] = (0,
|
|
695
|
-
const [reportId, setReportId] = (0,
|
|
696
|
-
const [screenshotUrl, setScreenshotUrl] = (0,
|
|
697
|
-
const [errorMessage, setErrorMessage] = (0,
|
|
698
|
-
const chatEndRef = (0,
|
|
699
|
-
const inputRef = (0,
|
|
700
|
-
const hasInitRef = (0,
|
|
701
|
-
const apiHeaders = (0,
|
|
759
|
+
const [messages, setMessages] = (0, import_react3.useState)([]);
|
|
760
|
+
const [input, setInput] = (0, import_react3.useState)("");
|
|
761
|
+
const [isLoading, setIsLoading] = (0, import_react3.useState)(false);
|
|
762
|
+
const [modalState, setModalState] = (0, import_react3.useState)("chatting");
|
|
763
|
+
const [reportId, setReportId] = (0, import_react3.useState)(null);
|
|
764
|
+
const [screenshotUrl, setScreenshotUrl] = (0, import_react3.useState)(null);
|
|
765
|
+
const [errorMessage, setErrorMessage] = (0, import_react3.useState)(null);
|
|
766
|
+
const chatEndRef = (0, import_react3.useRef)(null);
|
|
767
|
+
const inputRef = (0, import_react3.useRef)(null);
|
|
768
|
+
const hasInitRef = (0, import_react3.useRef)(false);
|
|
769
|
+
const apiHeaders = (0, import_react3.useMemo)(
|
|
702
770
|
() => ({
|
|
703
771
|
"Content-Type": "application/json",
|
|
704
772
|
"X-Bug-Reporter-Key": apiConfig.apiKey
|
|
705
773
|
}),
|
|
706
774
|
[apiConfig.apiKey]
|
|
707
775
|
);
|
|
708
|
-
(0,
|
|
776
|
+
(0, import_react3.useEffect)(() => {
|
|
709
777
|
if ((captureResult == null ? void 0 : captureResult.screenshot) && captureResult.screenshot.size > 0) {
|
|
710
778
|
const url = URL.createObjectURL(captureResult.screenshot);
|
|
711
779
|
setScreenshotUrl((prev) => {
|
|
@@ -722,7 +790,7 @@ function ReportModal({
|
|
|
722
790
|
return null;
|
|
723
791
|
});
|
|
724
792
|
}, [captureResult]);
|
|
725
|
-
const sendInitialMessage = (0,
|
|
793
|
+
const sendInitialMessage = (0, import_react3.useCallback)(async () => {
|
|
726
794
|
if (!captureResult) return;
|
|
727
795
|
setIsLoading(true);
|
|
728
796
|
try {
|
|
@@ -738,7 +806,9 @@ function ReportModal({
|
|
|
738
806
|
})
|
|
739
807
|
});
|
|
740
808
|
if (response.status === 401) {
|
|
741
|
-
console.error(
|
|
809
|
+
console.error(
|
|
810
|
+
"Bug reporter: invalid or missing API key. Check your BugReporter apiKey prop."
|
|
811
|
+
);
|
|
742
812
|
setMessages([
|
|
743
813
|
{
|
|
744
814
|
role: "assistant",
|
|
@@ -761,23 +831,23 @@ function ReportModal({
|
|
|
761
831
|
setIsLoading(false);
|
|
762
832
|
}
|
|
763
833
|
}, [captureResult, apiConfig.apiUrl, apiHeaders]);
|
|
764
|
-
(0,
|
|
834
|
+
(0, import_react3.useEffect)(() => {
|
|
765
835
|
if (isOpen && captureResult && !hasInitRef.current) {
|
|
766
836
|
hasInitRef.current = true;
|
|
767
837
|
sendInitialMessage();
|
|
768
838
|
}
|
|
769
839
|
}, [isOpen, captureResult, sendInitialMessage]);
|
|
770
|
-
(0,
|
|
840
|
+
(0, import_react3.useEffect)(() => {
|
|
771
841
|
var _a;
|
|
772
842
|
(_a = chatEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
|
|
773
843
|
}, [messages]);
|
|
774
|
-
(0,
|
|
844
|
+
(0, import_react3.useEffect)(() => {
|
|
775
845
|
var _a;
|
|
776
846
|
if (isOpen && !isLoading) {
|
|
777
847
|
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
778
848
|
}
|
|
779
849
|
}, [isOpen, isLoading, messages]);
|
|
780
|
-
const submitReport = (0,
|
|
850
|
+
const submitReport = (0, import_react3.useCallback)(
|
|
781
851
|
async (conversation, structuredReport) => {
|
|
782
852
|
if (!captureResult || modalState !== "chatting") return;
|
|
783
853
|
setModalState("submitting");
|
|
@@ -835,25 +905,20 @@ function ReportModal({
|
|
|
835
905
|
setModalState("submitted");
|
|
836
906
|
} catch (err) {
|
|
837
907
|
console.error("Bug reporter: failed to submit report", err);
|
|
838
|
-
setErrorMessage(
|
|
839
|
-
err instanceof Error ? err.message : "Failed to submit report"
|
|
840
|
-
);
|
|
908
|
+
setErrorMessage(err instanceof Error ? err.message : "Failed to submit report");
|
|
841
909
|
setModalState("error");
|
|
842
910
|
}
|
|
843
911
|
},
|
|
844
912
|
[captureResult, apiConfig.apiUrl, apiHeaders, modalState]
|
|
845
913
|
);
|
|
846
|
-
const handleManualSubmit = (0,
|
|
914
|
+
const handleManualSubmit = (0, import_react3.useCallback)(() => {
|
|
847
915
|
submitReport(messages);
|
|
848
916
|
}, [submitReport, messages]);
|
|
849
917
|
async function sendMessage() {
|
|
850
918
|
if (!input.trim() || isLoading || !captureResult) return;
|
|
851
919
|
const userMessage = input.trim();
|
|
852
920
|
setInput("");
|
|
853
|
-
const newMessages = [
|
|
854
|
-
...messages,
|
|
855
|
-
{ role: "user", content: userMessage }
|
|
856
|
-
];
|
|
921
|
+
const newMessages = [...messages, { role: "user", content: userMessage }];
|
|
857
922
|
setMessages(newMessages);
|
|
858
923
|
setIsLoading(true);
|
|
859
924
|
try {
|
|
@@ -869,7 +934,9 @@ function ReportModal({
|
|
|
869
934
|
})
|
|
870
935
|
});
|
|
871
936
|
if (response.status === 401) {
|
|
872
|
-
console.error(
|
|
937
|
+
console.error(
|
|
938
|
+
"Bug reporter: invalid or missing API key. Check your BugReporter apiKey prop."
|
|
939
|
+
);
|
|
873
940
|
setMessages([
|
|
874
941
|
...newMessages,
|
|
875
942
|
{
|
|
@@ -881,10 +948,7 @@ function ReportModal({
|
|
|
881
948
|
}
|
|
882
949
|
if (!response.ok) throw new Error("Failed to get AI response");
|
|
883
950
|
const data = await response.json();
|
|
884
|
-
setMessages([
|
|
885
|
-
...newMessages,
|
|
886
|
-
{ role: "assistant", content: data.message }
|
|
887
|
-
]);
|
|
951
|
+
setMessages([...newMessages, { role: "assistant", content: data.message }]);
|
|
888
952
|
if (data.readyToSubmit && data.structuredReport) {
|
|
889
953
|
await submitReport(
|
|
890
954
|
[...newMessages, { role: "assistant", content: data.message }],
|
|
@@ -935,65 +999,66 @@ function ReportModal({
|
|
|
935
999
|
"div",
|
|
936
1000
|
{
|
|
937
1001
|
className: cn(
|
|
938
|
-
"
|
|
939
|
-
"w-full max-w-lg
|
|
940
|
-
"max-[768px]:mx-0 max-[768px]:
|
|
1002
|
+
"flex flex-col overflow-hidden rounded-xl border border-gray-200 bg-white shadow-2xl dark:border-gray-800 dark:bg-gray-950",
|
|
1003
|
+
"mx-4 w-full max-w-lg",
|
|
1004
|
+
"max-[768px]:mx-0 max-[768px]:h-full max-[768px]:max-w-none max-[768px]:rounded-none",
|
|
941
1005
|
"min-[769px]:max-h-[85vh]"
|
|
942
1006
|
),
|
|
943
1007
|
children: [
|
|
944
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center justify-between
|
|
1008
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center justify-between border-b border-gray-200 bg-gray-50/30 px-4 py-3 dark:border-gray-800 dark:bg-gray-900/30", children: [
|
|
945
1009
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
|
|
946
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "font-semibold text-
|
|
1010
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: "Bug Report" }),
|
|
947
1011
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: siteId })
|
|
948
1012
|
] }),
|
|
949
1013
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
950
1014
|
"button",
|
|
951
1015
|
{
|
|
952
1016
|
onClick: handleClose,
|
|
953
|
-
className: "p-1.5
|
|
1017
|
+
className: "rounded-md p-1.5 transition-colors hover:bg-gray-100 dark:hover:bg-gray-800",
|
|
954
1018
|
"aria-label": "Close",
|
|
955
1019
|
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { className: "h-4 w-4 text-gray-600 dark:text-gray-400" })
|
|
956
1020
|
}
|
|
957
1021
|
)
|
|
958
1022
|
] }),
|
|
959
|
-
screenshotUrl && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "
|
|
1023
|
+
screenshotUrl && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "border-b border-gray-200 bg-gray-50/10 px-4 py-3 dark:border-gray-800 dark:bg-gray-900/10", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
960
1024
|
"img",
|
|
961
1025
|
{
|
|
962
1026
|
src: screenshotUrl,
|
|
963
1027
|
alt: "Captured section",
|
|
964
|
-
className: "
|
|
1028
|
+
className: "max-h-40 w-full rounded-md border border-gray-200 object-contain dark:border-gray-700"
|
|
965
1029
|
}
|
|
966
1030
|
) }),
|
|
967
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex-1 overflow-y-auto px-4 py-3
|
|
968
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.CheckCircle2, { className: "h-12 w-12 text-green-500
|
|
969
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: "font-semibold text-
|
|
970
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "text-sm text-gray-500 dark:text-gray-400
|
|
971
|
-
"Reference:
|
|
972
|
-
|
|
1031
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "min-h-0 flex-1 space-y-3 overflow-y-auto px-4 py-3", children: modalState === "submitted" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
1032
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.CheckCircle2, { className: "mb-3 h-12 w-12 text-green-500" }),
|
|
1033
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: "Report Submitted" }),
|
|
1034
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: [
|
|
1035
|
+
"Reference:",
|
|
1036
|
+
" ",
|
|
1037
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("code", { className: "rounded bg-gray-100 px-1.5 py-0.5 text-xs dark:bg-gray-800", children: reportId == null ? void 0 : reportId.slice(0, 8) })
|
|
973
1038
|
] }),
|
|
974
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400
|
|
1039
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: "Thanks for the report \u2014 we'll look into it." }),
|
|
975
1040
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
976
1041
|
"button",
|
|
977
1042
|
{
|
|
978
1043
|
onClick: handleClose,
|
|
979
|
-
className: "mt-4 px-4 py-2
|
|
1044
|
+
className: "mt-4 rounded-md bg-indigo-600 px-4 py-2 text-sm text-white transition-colors hover:bg-indigo-700",
|
|
980
1045
|
children: "Done"
|
|
981
1046
|
}
|
|
982
1047
|
)
|
|
983
1048
|
] }) : modalState === "error" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
984
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { className: "h-12 w-12 text-red-500
|
|
985
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: "font-semibold text-
|
|
986
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400
|
|
1049
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.X, { className: "mb-3 h-12 w-12 text-red-500" }),
|
|
1050
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: "Submission Failed" }),
|
|
1051
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: errorMessage || "Something went wrong. Please try again." }),
|
|
987
1052
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
988
1053
|
"button",
|
|
989
1054
|
{
|
|
990
1055
|
onClick: () => setModalState("chatting"),
|
|
991
|
-
className: "mt-4 px-4 py-2
|
|
1056
|
+
className: "mt-4 rounded-md bg-indigo-600 px-4 py-2 text-sm text-white transition-colors hover:bg-indigo-700",
|
|
992
1057
|
children: "Try Again"
|
|
993
1058
|
}
|
|
994
1059
|
)
|
|
995
1060
|
] }) : modalState === "submitting" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col items-center justify-center py-8", children: [
|
|
996
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.Loader2, { className: "h-8 w-8 animate-spin text-indigo-500
|
|
1061
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.Loader2, { className: "mb-3 h-8 w-8 animate-spin text-indigo-500" }),
|
|
997
1062
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Submitting your report..." })
|
|
998
1063
|
] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
999
1064
|
(captureResult == null ? void 0 : captureResult.screenshot.size) === 0 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "text-xs text-amber-600", children: "Screenshot could not be captured. Please describe the visual issue in detail." }),
|
|
@@ -1002,42 +1067,53 @@ function ReportModal({
|
|
|
1002
1067
|
{
|
|
1003
1068
|
className: cn(
|
|
1004
1069
|
"text-sm leading-relaxed",
|
|
1005
|
-
msg.role === "assistant" ? "
|
|
1070
|
+
msg.role === "assistant" ? "rounded-lg bg-gray-100/50 p-3 text-gray-900 dark:bg-gray-800/50 dark:text-gray-100" : "ml-8 rounded-lg bg-indigo-600 p-3 text-white"
|
|
1006
1071
|
),
|
|
1007
1072
|
children: msg.content
|
|
1008
1073
|
},
|
|
1009
1074
|
i
|
|
1010
1075
|
)),
|
|
1011
|
-
isLoading && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "bg-gray-100/50 dark:bg-gray-800/50
|
|
1076
|
+
isLoading && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2 rounded-lg bg-gray-100/50 p-3 dark:bg-gray-800/50", children: [
|
|
1012
1077
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.Loader2, { className: "h-3.5 w-3.5 animate-spin text-gray-500" }),
|
|
1013
1078
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Thinking..." })
|
|
1014
1079
|
] }),
|
|
1015
1080
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: chatEndRef })
|
|
1016
1081
|
] }) }),
|
|
1017
|
-
modalState === "chatting" && /* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1018
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("
|
|
1033
|
-
|
|
1082
|
+
modalState === "chatting" && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "border-t border-gray-200 px-4 py-3 dark:border-gray-800", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
1083
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1084
|
+
"textarea",
|
|
1085
|
+
{
|
|
1086
|
+
ref: inputRef,
|
|
1087
|
+
value: input,
|
|
1088
|
+
onChange: (e) => setInput(e.target.value),
|
|
1089
|
+
onKeyDown: handleKeyDown,
|
|
1090
|
+
placeholder: "Describe what's wrong...",
|
|
1091
|
+
rows: 2,
|
|
1092
|
+
className: "w-full resize-none rounded-md border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 focus:border-transparent focus:ring-2 focus:ring-indigo-400 focus:outline-none dark:border-gray-700 dark:bg-gray-950 dark:text-gray-100",
|
|
1093
|
+
disabled: isLoading
|
|
1094
|
+
}
|
|
1095
|
+
),
|
|
1096
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex flex-col gap-2", children: [
|
|
1097
|
+
captureResult && (captureResult.consoleErrors.length > 0 || captureResult.networkErrors.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "flex-1 text-xs text-amber-600", children: [
|
|
1098
|
+
[
|
|
1099
|
+
captureResult.consoleErrors.length > 0 ? `${captureResult.consoleErrors.length} console error${captureResult.consoleErrors.length !== 1 ? "s" : ""}` : null,
|
|
1100
|
+
captureResult.networkErrors.length > 0 ? `${captureResult.networkErrors.length} failed request${captureResult.networkErrors.length !== 1 ? "s" : ""}` : null
|
|
1101
|
+
].filter(Boolean).join(" + "),
|
|
1102
|
+
" ",
|
|
1103
|
+
"captured \u2014 these will be included in the report."
|
|
1104
|
+
] }),
|
|
1105
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex justify-end gap-2", children: [
|
|
1106
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1034
1107
|
"button",
|
|
1035
1108
|
{
|
|
1036
1109
|
onClick: sendMessage,
|
|
1037
1110
|
disabled: !input.trim() || isLoading,
|
|
1038
|
-
className: "
|
|
1111
|
+
className: "flex items-center gap-1 rounded-md bg-indigo-600 px-3 py-2 text-nowrap text-white transition-colors hover:bg-indigo-700 disabled:cursor-not-allowed disabled:opacity-50",
|
|
1039
1112
|
title: "Send message",
|
|
1040
|
-
children:
|
|
1113
|
+
children: [
|
|
1114
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.Send, { className: "h-4 w-4" }),
|
|
1115
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-sm font-medium", children: "Send message" })
|
|
1116
|
+
]
|
|
1041
1117
|
}
|
|
1042
1118
|
),
|
|
1043
1119
|
messages.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -1045,22 +1121,14 @@ function ReportModal({
|
|
|
1045
1121
|
{
|
|
1046
1122
|
onClick: handleManualSubmit,
|
|
1047
1123
|
disabled: isLoading,
|
|
1048
|
-
className: "px-
|
|
1124
|
+
className: "rounded-md bg-green-600 px-3 py-2 text-xs font-medium text-nowrap text-white transition-colors hover:bg-green-700 disabled:opacity-50",
|
|
1049
1125
|
title: "Submit report now",
|
|
1050
|
-
children: "Submit"
|
|
1126
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-sm font-medium", children: "Submit report" })
|
|
1051
1127
|
}
|
|
1052
1128
|
)
|
|
1053
1129
|
] })
|
|
1054
|
-
] }),
|
|
1055
|
-
captureResult && (captureResult.consoleErrors.length > 0 || captureResult.networkErrors.length > 0) && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("p", { className: "text-xs text-amber-600 mt-1.5", children: [
|
|
1056
|
-
[
|
|
1057
|
-
captureResult.consoleErrors.length > 0 ? `${captureResult.consoleErrors.length} console error${captureResult.consoleErrors.length !== 1 ? "s" : ""}` : null,
|
|
1058
|
-
captureResult.networkErrors.length > 0 ? `${captureResult.networkErrors.length} failed request${captureResult.networkErrors.length !== 1 ? "s" : ""}` : null
|
|
1059
|
-
].filter(Boolean).join(" + "),
|
|
1060
|
-
" ",
|
|
1061
|
-
"captured \u2014 these will be included in the report."
|
|
1062
1130
|
] })
|
|
1063
|
-
] })
|
|
1131
|
+
] }) })
|
|
1064
1132
|
]
|
|
1065
1133
|
}
|
|
1066
1134
|
)
|
|
@@ -1074,12 +1142,14 @@ function JarveBugReporter({
|
|
|
1074
1142
|
apiUrl,
|
|
1075
1143
|
apiKey,
|
|
1076
1144
|
user,
|
|
1145
|
+
buttonPosition,
|
|
1077
1146
|
children
|
|
1078
1147
|
}) {
|
|
1079
|
-
const
|
|
1080
|
-
const [
|
|
1081
|
-
const [
|
|
1082
|
-
(0,
|
|
1148
|
+
const safeApiKey = apiKey || "";
|
|
1149
|
+
const [captureMode, setCaptureMode] = (0, import_react4.useState)(false);
|
|
1150
|
+
const [captureResult, setCaptureResult] = (0, import_react4.useState)(null);
|
|
1151
|
+
const [showModal, setShowModal] = (0, import_react4.useState)(false);
|
|
1152
|
+
(0, import_react4.useEffect)(() => {
|
|
1083
1153
|
startCapturing();
|
|
1084
1154
|
startNetworkCapture();
|
|
1085
1155
|
return () => {
|
|
@@ -1087,29 +1157,36 @@ function JarveBugReporter({
|
|
|
1087
1157
|
stopNetworkCapture();
|
|
1088
1158
|
};
|
|
1089
1159
|
}, []);
|
|
1090
|
-
const toggleCaptureMode = (0,
|
|
1160
|
+
const toggleCaptureMode = (0, import_react4.useCallback)(() => {
|
|
1091
1161
|
setCaptureMode((prev) => !prev);
|
|
1092
1162
|
}, []);
|
|
1093
|
-
const handleCapture = (0,
|
|
1163
|
+
const handleCapture = (0, import_react4.useCallback)((result) => {
|
|
1094
1164
|
setCaptureResult(result);
|
|
1095
1165
|
setCaptureMode(false);
|
|
1096
1166
|
setShowModal(true);
|
|
1097
1167
|
}, []);
|
|
1098
|
-
const handleCancelCapture = (0,
|
|
1168
|
+
const handleCancelCapture = (0, import_react4.useCallback)(() => {
|
|
1099
1169
|
setCaptureMode(false);
|
|
1100
1170
|
}, []);
|
|
1101
|
-
const handleCloseModal = (0,
|
|
1171
|
+
const handleCloseModal = (0, import_react4.useCallback)(() => {
|
|
1102
1172
|
setShowModal(false);
|
|
1103
1173
|
setCaptureResult(null);
|
|
1104
1174
|
clearCapturedErrors();
|
|
1105
1175
|
clearCapturedNetworkErrors();
|
|
1106
1176
|
}, []);
|
|
1107
|
-
const siteId =
|
|
1177
|
+
const siteId = safeApiKey.startsWith("brk_") ? safeApiKey.slice(4, 12) : "external";
|
|
1108
1178
|
const reporterName = (user == null ? void 0 : user.name) || "Anonymous";
|
|
1109
1179
|
const reporterEmail = (user == null ? void 0 : user.email) || "unknown@external";
|
|
1110
1180
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
1111
1181
|
children,
|
|
1112
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1182
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1183
|
+
FloatingButton,
|
|
1184
|
+
{
|
|
1185
|
+
isActive: captureMode,
|
|
1186
|
+
onClick: toggleCaptureMode,
|
|
1187
|
+
position: buttonPosition
|
|
1188
|
+
}
|
|
1189
|
+
),
|
|
1113
1190
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
1114
1191
|
CaptureOverlay,
|
|
1115
1192
|
{
|