@jarve/bug-reporter 0.3.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/dist/index.js +100 -67
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +94 -61
- 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
|
|
@@ -58,30 +59,62 @@ function cn(...inputs) {
|
|
|
58
59
|
// src/floating-button.tsx
|
|
59
60
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
60
61
|
function FloatingButton({ isActive, onClick, position = "right" }) {
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
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",
|
|
64
67
|
{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
]
|
|
79
112
|
}
|
|
80
113
|
);
|
|
81
114
|
}
|
|
82
115
|
|
|
83
116
|
// src/capture-overlay.tsx
|
|
84
|
-
var
|
|
117
|
+
var import_react2 = require("react");
|
|
85
118
|
var import_html_to_image = require("html-to-image");
|
|
86
119
|
|
|
87
120
|
// src/utils.ts
|
|
@@ -410,23 +443,23 @@ function CaptureOverlay({
|
|
|
410
443
|
onCapture,
|
|
411
444
|
onCancel
|
|
412
445
|
}) {
|
|
413
|
-
const [hoveredElement, setHoveredElement] = (0,
|
|
414
|
-
const [hoveredRect, setHoveredRect] = (0,
|
|
415
|
-
const [isCapturing3, setIsCapturing] = (0,
|
|
416
|
-
const [isTouchMode, setIsTouchMode] = (0,
|
|
417
|
-
const [selectedSection, setSelectedSection] = (0,
|
|
418
|
-
const [selectedRect, setSelectedRect] = (0,
|
|
419
|
-
const [selectedTarget, setSelectedTarget] = (0,
|
|
420
|
-
const overlayRef = (0,
|
|
421
|
-
const hoveredElementRef = (0,
|
|
422
|
-
const rafRef = (0,
|
|
423
|
-
const touchCoordsRef = (0,
|
|
424
|
-
(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)(() => {
|
|
425
458
|
if (isActive) {
|
|
426
459
|
setIsTouchMode(isTouchCapable());
|
|
427
460
|
}
|
|
428
461
|
}, [isActive]);
|
|
429
|
-
const captureScreenshot = (0,
|
|
462
|
+
const captureScreenshot = (0, import_react2.useCallback)(
|
|
430
463
|
async (section, target, coords) => {
|
|
431
464
|
const elementInfo = collectElementInfo(target, section, coords);
|
|
432
465
|
setIsCapturing(true);
|
|
@@ -504,7 +537,7 @@ function CaptureOverlay({
|
|
|
504
537
|
},
|
|
505
538
|
[siteId, reporterName, reporterEmail, onCapture]
|
|
506
539
|
);
|
|
507
|
-
const handleMouseMove = (0,
|
|
540
|
+
const handleMouseMove = (0, import_react2.useCallback)(
|
|
508
541
|
(e) => {
|
|
509
542
|
if (!isActive || isCapturing3 || isTouchMode) return;
|
|
510
543
|
if (rafRef.current) return;
|
|
@@ -526,7 +559,7 @@ function CaptureOverlay({
|
|
|
526
559
|
},
|
|
527
560
|
[isActive, isCapturing3, isTouchMode]
|
|
528
561
|
);
|
|
529
|
-
const handleClick = (0,
|
|
562
|
+
const handleClick = (0, import_react2.useCallback)(
|
|
530
563
|
async (e) => {
|
|
531
564
|
if (!isActive || isCapturing3 || isTouchMode) return;
|
|
532
565
|
const target = e.target;
|
|
@@ -540,7 +573,7 @@ function CaptureOverlay({
|
|
|
540
573
|
},
|
|
541
574
|
[isActive, isCapturing3, isTouchMode, captureScreenshot]
|
|
542
575
|
);
|
|
543
|
-
const handleTouchEnd = (0,
|
|
576
|
+
const handleTouchEnd = (0, import_react2.useCallback)(
|
|
544
577
|
(e) => {
|
|
545
578
|
if (!isActive || isCapturing3) return;
|
|
546
579
|
const touch = e.changedTouches[0];
|
|
@@ -557,11 +590,11 @@ function CaptureOverlay({
|
|
|
557
590
|
},
|
|
558
591
|
[isActive, isCapturing3]
|
|
559
592
|
);
|
|
560
|
-
const handleConfirmCapture = (0,
|
|
593
|
+
const handleConfirmCapture = (0, import_react2.useCallback)(async () => {
|
|
561
594
|
if (!selectedSection || !selectedTarget || !touchCoordsRef.current) return;
|
|
562
595
|
await captureScreenshot(selectedSection, selectedTarget, touchCoordsRef.current);
|
|
563
596
|
}, [selectedSection, selectedTarget, captureScreenshot]);
|
|
564
|
-
const handlePointerDown = (0,
|
|
597
|
+
const handlePointerDown = (0, import_react2.useCallback)(
|
|
565
598
|
(e) => {
|
|
566
599
|
if (!isActive) return;
|
|
567
600
|
if (e.pointerType === "touch") {
|
|
@@ -572,7 +605,7 @@ function CaptureOverlay({
|
|
|
572
605
|
},
|
|
573
606
|
[isActive]
|
|
574
607
|
);
|
|
575
|
-
const handleKeyDown = (0,
|
|
608
|
+
const handleKeyDown = (0, import_react2.useCallback)(
|
|
576
609
|
(e) => {
|
|
577
610
|
if (e.key === "Escape" && isActive) {
|
|
578
611
|
e.preventDefault();
|
|
@@ -582,7 +615,7 @@ function CaptureOverlay({
|
|
|
582
615
|
},
|
|
583
616
|
[isActive, onCancel]
|
|
584
617
|
);
|
|
585
|
-
const handleScroll = (0,
|
|
618
|
+
const handleScroll = (0, import_react2.useCallback)(() => {
|
|
586
619
|
if (hoveredElementRef.current) {
|
|
587
620
|
setHoveredRect(hoveredElementRef.current.getBoundingClientRect());
|
|
588
621
|
}
|
|
@@ -590,7 +623,7 @@ function CaptureOverlay({
|
|
|
590
623
|
setSelectedRect(selectedSection.getBoundingClientRect());
|
|
591
624
|
}
|
|
592
625
|
}, [selectedSection]);
|
|
593
|
-
(0,
|
|
626
|
+
(0, import_react2.useEffect)(() => {
|
|
594
627
|
if (!isActive) {
|
|
595
628
|
setHoveredElement(null);
|
|
596
629
|
setHoveredRect(null);
|
|
@@ -712,7 +745,7 @@ function CaptureOverlay({
|
|
|
712
745
|
}
|
|
713
746
|
|
|
714
747
|
// src/report-modal.tsx
|
|
715
|
-
var
|
|
748
|
+
var import_react3 = require("react");
|
|
716
749
|
var import_lucide_react2 = require("lucide-react");
|
|
717
750
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
718
751
|
function ReportModal({
|
|
@@ -723,24 +756,24 @@ function ReportModal({
|
|
|
723
756
|
user,
|
|
724
757
|
onClose
|
|
725
758
|
}) {
|
|
726
|
-
const [messages, setMessages] = (0,
|
|
727
|
-
const [input, setInput] = (0,
|
|
728
|
-
const [isLoading, setIsLoading] = (0,
|
|
729
|
-
const [modalState, setModalState] = (0,
|
|
730
|
-
const [reportId, setReportId] = (0,
|
|
731
|
-
const [screenshotUrl, setScreenshotUrl] = (0,
|
|
732
|
-
const [errorMessage, setErrorMessage] = (0,
|
|
733
|
-
const chatEndRef = (0,
|
|
734
|
-
const inputRef = (0,
|
|
735
|
-
const hasInitRef = (0,
|
|
736
|
-
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)(
|
|
737
770
|
() => ({
|
|
738
771
|
"Content-Type": "application/json",
|
|
739
772
|
"X-Bug-Reporter-Key": apiConfig.apiKey
|
|
740
773
|
}),
|
|
741
774
|
[apiConfig.apiKey]
|
|
742
775
|
);
|
|
743
|
-
(0,
|
|
776
|
+
(0, import_react3.useEffect)(() => {
|
|
744
777
|
if ((captureResult == null ? void 0 : captureResult.screenshot) && captureResult.screenshot.size > 0) {
|
|
745
778
|
const url = URL.createObjectURL(captureResult.screenshot);
|
|
746
779
|
setScreenshotUrl((prev) => {
|
|
@@ -757,7 +790,7 @@ function ReportModal({
|
|
|
757
790
|
return null;
|
|
758
791
|
});
|
|
759
792
|
}, [captureResult]);
|
|
760
|
-
const sendInitialMessage = (0,
|
|
793
|
+
const sendInitialMessage = (0, import_react3.useCallback)(async () => {
|
|
761
794
|
if (!captureResult) return;
|
|
762
795
|
setIsLoading(true);
|
|
763
796
|
try {
|
|
@@ -798,23 +831,23 @@ function ReportModal({
|
|
|
798
831
|
setIsLoading(false);
|
|
799
832
|
}
|
|
800
833
|
}, [captureResult, apiConfig.apiUrl, apiHeaders]);
|
|
801
|
-
(0,
|
|
834
|
+
(0, import_react3.useEffect)(() => {
|
|
802
835
|
if (isOpen && captureResult && !hasInitRef.current) {
|
|
803
836
|
hasInitRef.current = true;
|
|
804
837
|
sendInitialMessage();
|
|
805
838
|
}
|
|
806
839
|
}, [isOpen, captureResult, sendInitialMessage]);
|
|
807
|
-
(0,
|
|
840
|
+
(0, import_react3.useEffect)(() => {
|
|
808
841
|
var _a;
|
|
809
842
|
(_a = chatEndRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
|
|
810
843
|
}, [messages]);
|
|
811
|
-
(0,
|
|
844
|
+
(0, import_react3.useEffect)(() => {
|
|
812
845
|
var _a;
|
|
813
846
|
if (isOpen && !isLoading) {
|
|
814
847
|
(_a = inputRef.current) == null ? void 0 : _a.focus();
|
|
815
848
|
}
|
|
816
849
|
}, [isOpen, isLoading, messages]);
|
|
817
|
-
const submitReport = (0,
|
|
850
|
+
const submitReport = (0, import_react3.useCallback)(
|
|
818
851
|
async (conversation, structuredReport) => {
|
|
819
852
|
if (!captureResult || modalState !== "chatting") return;
|
|
820
853
|
setModalState("submitting");
|
|
@@ -878,7 +911,7 @@ function ReportModal({
|
|
|
878
911
|
},
|
|
879
912
|
[captureResult, apiConfig.apiUrl, apiHeaders, modalState]
|
|
880
913
|
);
|
|
881
|
-
const handleManualSubmit = (0,
|
|
914
|
+
const handleManualSubmit = (0, import_react3.useCallback)(() => {
|
|
882
915
|
submitReport(messages);
|
|
883
916
|
}, [submitReport, messages]);
|
|
884
917
|
async function sendMessage() {
|
|
@@ -1113,10 +1146,10 @@ function JarveBugReporter({
|
|
|
1113
1146
|
children
|
|
1114
1147
|
}) {
|
|
1115
1148
|
const safeApiKey = apiKey || "";
|
|
1116
|
-
const [captureMode, setCaptureMode] = (0,
|
|
1117
|
-
const [captureResult, setCaptureResult] = (0,
|
|
1118
|
-
const [showModal, setShowModal] = (0,
|
|
1119
|
-
(0,
|
|
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)(() => {
|
|
1120
1153
|
startCapturing();
|
|
1121
1154
|
startNetworkCapture();
|
|
1122
1155
|
return () => {
|
|
@@ -1124,18 +1157,18 @@ function JarveBugReporter({
|
|
|
1124
1157
|
stopNetworkCapture();
|
|
1125
1158
|
};
|
|
1126
1159
|
}, []);
|
|
1127
|
-
const toggleCaptureMode = (0,
|
|
1160
|
+
const toggleCaptureMode = (0, import_react4.useCallback)(() => {
|
|
1128
1161
|
setCaptureMode((prev) => !prev);
|
|
1129
1162
|
}, []);
|
|
1130
|
-
const handleCapture = (0,
|
|
1163
|
+
const handleCapture = (0, import_react4.useCallback)((result) => {
|
|
1131
1164
|
setCaptureResult(result);
|
|
1132
1165
|
setCaptureMode(false);
|
|
1133
1166
|
setShowModal(true);
|
|
1134
1167
|
}, []);
|
|
1135
|
-
const handleCancelCapture = (0,
|
|
1168
|
+
const handleCancelCapture = (0, import_react4.useCallback)(() => {
|
|
1136
1169
|
setCaptureMode(false);
|
|
1137
1170
|
}, []);
|
|
1138
|
-
const handleCloseModal = (0,
|
|
1171
|
+
const handleCloseModal = (0, import_react4.useCallback)(() => {
|
|
1139
1172
|
setShowModal(false);
|
|
1140
1173
|
setCaptureResult(null);
|
|
1141
1174
|
clearCapturedErrors();
|