@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.mjs
CHANGED
|
@@ -20,9 +20,10 @@ var __spreadValues = (a, b) => {
|
|
|
20
20
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
21
|
|
|
22
22
|
// src/bug-reporter.tsx
|
|
23
|
-
import { useState as
|
|
23
|
+
import { useState as useState4, useEffect as useEffect3, useCallback as useCallback3 } from "react";
|
|
24
24
|
|
|
25
25
|
// src/floating-button.tsx
|
|
26
|
+
import { useState } from "react";
|
|
26
27
|
import { Bug } from "lucide-react";
|
|
27
28
|
|
|
28
29
|
// src/cn.ts
|
|
@@ -33,32 +34,64 @@ function cn(...inputs) {
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
// src/floating-button.tsx
|
|
36
|
-
import { jsx } from "react/jsx-runtime";
|
|
37
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
37
38
|
function FloatingButton({ isActive, onClick, position = "right" }) {
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
const [hovered, setHovered] = useState(false);
|
|
40
|
+
const isLeft = position === "left";
|
|
41
|
+
const sideClasses = isLeft ? "left-4 md:left-6" : "right-4 md:right-6";
|
|
42
|
+
return /* @__PURE__ */ jsxs(
|
|
43
|
+
"div",
|
|
41
44
|
{
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
className: cn("fixed z-[9999]", "bottom-4 md:bottom-6", sideClasses),
|
|
46
|
+
onMouseEnter: () => setHovered(true),
|
|
47
|
+
onMouseLeave: () => setHovered(false),
|
|
48
|
+
children: [
|
|
49
|
+
/* @__PURE__ */ jsxs(
|
|
50
|
+
"div",
|
|
51
|
+
{
|
|
52
|
+
className: cn(
|
|
53
|
+
"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",
|
|
54
|
+
isLeft ? "left-0" : "right-0",
|
|
55
|
+
hovered && !isActive ? "translate-y-0 opacity-100" : "translate-y-1 opacity-0"
|
|
56
|
+
),
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: "Report a bug" }),
|
|
59
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
60
|
+
"Click to screenshot an issue and chat with AI to submit a bug report.",
|
|
61
|
+
/* @__PURE__ */ jsx(
|
|
62
|
+
"div",
|
|
63
|
+
{
|
|
64
|
+
className: cn(
|
|
65
|
+
"absolute top-full h-0 w-0 border-x-[6px] border-t-[6px] border-x-transparent border-t-gray-900",
|
|
66
|
+
isLeft ? "left-4" : "right-4"
|
|
67
|
+
)
|
|
68
|
+
}
|
|
69
|
+
)
|
|
70
|
+
]
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ jsx(
|
|
74
|
+
"button",
|
|
75
|
+
{
|
|
76
|
+
onClick,
|
|
77
|
+
className: cn(
|
|
78
|
+
"flex items-center justify-center rounded-full shadow-lg transition-all duration-200",
|
|
79
|
+
"hover:scale-110 focus:ring-2 focus:ring-offset-2 focus:outline-none",
|
|
80
|
+
"h-11 w-11 md:h-12 md:w-12",
|
|
81
|
+
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"
|
|
82
|
+
),
|
|
83
|
+
title: isActive ? "Cancel bug capture" : "Report a bug",
|
|
84
|
+
"aria-label": isActive ? "Cancel bug capture" : "Report a bug",
|
|
85
|
+
children: /* @__PURE__ */ jsx(Bug, { className: "h-4 w-4 md:h-5 md:w-5" })
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
]
|
|
56
89
|
}
|
|
57
90
|
);
|
|
58
91
|
}
|
|
59
92
|
|
|
60
93
|
// src/capture-overlay.tsx
|
|
61
|
-
import { useEffect, useState, useCallback, useRef } from "react";
|
|
94
|
+
import { useEffect, useState as useState2, useCallback, useRef } from "react";
|
|
62
95
|
import { toPng } from "html-to-image";
|
|
63
96
|
|
|
64
97
|
// src/utils.ts
|
|
@@ -369,7 +402,7 @@ function clearCapturedNetworkErrors() {
|
|
|
369
402
|
}
|
|
370
403
|
|
|
371
404
|
// src/capture-overlay.tsx
|
|
372
|
-
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
405
|
+
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
373
406
|
function dataUrlToBlob(dataUrl) {
|
|
374
407
|
var _a;
|
|
375
408
|
const [header, base64] = dataUrl.split(",");
|
|
@@ -387,13 +420,13 @@ function CaptureOverlay({
|
|
|
387
420
|
onCapture,
|
|
388
421
|
onCancel
|
|
389
422
|
}) {
|
|
390
|
-
const [hoveredElement, setHoveredElement] =
|
|
391
|
-
const [hoveredRect, setHoveredRect] =
|
|
392
|
-
const [isCapturing3, setIsCapturing] =
|
|
393
|
-
const [isTouchMode, setIsTouchMode] =
|
|
394
|
-
const [selectedSection, setSelectedSection] =
|
|
395
|
-
const [selectedRect, setSelectedRect] =
|
|
396
|
-
const [selectedTarget, setSelectedTarget] =
|
|
423
|
+
const [hoveredElement, setHoveredElement] = useState2(null);
|
|
424
|
+
const [hoveredRect, setHoveredRect] = useState2(null);
|
|
425
|
+
const [isCapturing3, setIsCapturing] = useState2(false);
|
|
426
|
+
const [isTouchMode, setIsTouchMode] = useState2(false);
|
|
427
|
+
const [selectedSection, setSelectedSection] = useState2(null);
|
|
428
|
+
const [selectedRect, setSelectedRect] = useState2(null);
|
|
429
|
+
const [selectedTarget, setSelectedTarget] = useState2(null);
|
|
397
430
|
const overlayRef = useRef(null);
|
|
398
431
|
const hoveredElementRef = useRef(null);
|
|
399
432
|
const rafRef = useRef(null);
|
|
@@ -609,7 +642,7 @@ function CaptureOverlay({
|
|
|
609
642
|
const highlightRect = isTouchMode ? selectedRect : hoveredRect;
|
|
610
643
|
const showHighlight = isTouchMode ? !!selectedSection : !!hoveredElement && !!hoveredRect;
|
|
611
644
|
if (!isActive) return null;
|
|
612
|
-
return /* @__PURE__ */
|
|
645
|
+
return /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
613
646
|
/* @__PURE__ */ jsx2(
|
|
614
647
|
"div",
|
|
615
648
|
{
|
|
@@ -617,7 +650,7 @@ function CaptureOverlay({
|
|
|
617
650
|
role: "alert",
|
|
618
651
|
"aria-live": "assertive",
|
|
619
652
|
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",
|
|
620
|
-
children: isTouchMode ? /* @__PURE__ */
|
|
653
|
+
children: isTouchMode ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
621
654
|
/* @__PURE__ */ jsx2("span", { children: "Tap the section with the bug" }),
|
|
622
655
|
/* @__PURE__ */ jsx2(
|
|
623
656
|
"button",
|
|
@@ -627,7 +660,7 @@ function CaptureOverlay({
|
|
|
627
660
|
children: "Cancel"
|
|
628
661
|
}
|
|
629
662
|
)
|
|
630
|
-
] }) : /* @__PURE__ */
|
|
663
|
+
] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
631
664
|
"Click on the section with the bug. Press",
|
|
632
665
|
" ",
|
|
633
666
|
/* @__PURE__ */ jsx2("kbd", { className: "mx-1 rounded bg-indigo-800 px-1.5 py-0.5 text-xs", children: "Esc" }),
|
|
@@ -656,9 +689,9 @@ function CaptureOverlay({
|
|
|
656
689
|
"data-bug-reporter": true,
|
|
657
690
|
className: "fixed right-0 bottom-0 left-0 z-[10000] border-t border-gray-200 bg-white shadow-lg",
|
|
658
691
|
style: { paddingBottom: "env(safe-area-inset-bottom, 0px)" },
|
|
659
|
-
children: /* @__PURE__ */
|
|
692
|
+
children: /* @__PURE__ */ jsxs2("div", { className: "flex items-center justify-between gap-3 px-4 py-3", children: [
|
|
660
693
|
/* @__PURE__ */ jsx2("span", { className: "truncate text-sm font-medium text-gray-900", children: "Capture this section?" }),
|
|
661
|
-
/* @__PURE__ */
|
|
694
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex shrink-0 gap-2", children: [
|
|
662
695
|
/* @__PURE__ */ jsx2(
|
|
663
696
|
"button",
|
|
664
697
|
{
|
|
@@ -689,9 +722,9 @@ function CaptureOverlay({
|
|
|
689
722
|
}
|
|
690
723
|
|
|
691
724
|
// src/report-modal.tsx
|
|
692
|
-
import { useState as
|
|
725
|
+
import { useState as useState3, useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2, useMemo } from "react";
|
|
693
726
|
import { X, Send, Loader2, CheckCircle2 } from "lucide-react";
|
|
694
|
-
import { Fragment as Fragment2, jsx as jsx3, jsxs as
|
|
727
|
+
import { Fragment as Fragment2, jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
695
728
|
function ReportModal({
|
|
696
729
|
isOpen,
|
|
697
730
|
captureResult,
|
|
@@ -700,13 +733,13 @@ function ReportModal({
|
|
|
700
733
|
user,
|
|
701
734
|
onClose
|
|
702
735
|
}) {
|
|
703
|
-
const [messages, setMessages] =
|
|
704
|
-
const [input, setInput] =
|
|
705
|
-
const [isLoading, setIsLoading] =
|
|
706
|
-
const [modalState, setModalState] =
|
|
707
|
-
const [reportId, setReportId] =
|
|
708
|
-
const [screenshotUrl, setScreenshotUrl] =
|
|
709
|
-
const [errorMessage, setErrorMessage] =
|
|
736
|
+
const [messages, setMessages] = useState3([]);
|
|
737
|
+
const [input, setInput] = useState3("");
|
|
738
|
+
const [isLoading, setIsLoading] = useState3(false);
|
|
739
|
+
const [modalState, setModalState] = useState3("chatting");
|
|
740
|
+
const [reportId, setReportId] = useState3(null);
|
|
741
|
+
const [screenshotUrl, setScreenshotUrl] = useState3(null);
|
|
742
|
+
const [errorMessage, setErrorMessage] = useState3(null);
|
|
710
743
|
const chatEndRef = useRef2(null);
|
|
711
744
|
const inputRef = useRef2(null);
|
|
712
745
|
const hasInitRef = useRef2(false);
|
|
@@ -939,7 +972,7 @@ function ReportModal({
|
|
|
939
972
|
onClick: (e) => {
|
|
940
973
|
if (e.target === e.currentTarget) handleClose();
|
|
941
974
|
},
|
|
942
|
-
children: /* @__PURE__ */
|
|
975
|
+
children: /* @__PURE__ */ jsxs3(
|
|
943
976
|
"div",
|
|
944
977
|
{
|
|
945
978
|
className: cn(
|
|
@@ -949,8 +982,8 @@ function ReportModal({
|
|
|
949
982
|
"min-[769px]:max-h-[85vh]"
|
|
950
983
|
),
|
|
951
984
|
children: [
|
|
952
|
-
/* @__PURE__ */
|
|
953
|
-
/* @__PURE__ */
|
|
985
|
+
/* @__PURE__ */ jsxs3("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: [
|
|
986
|
+
/* @__PURE__ */ jsxs3("div", { children: [
|
|
954
987
|
/* @__PURE__ */ jsx3("h2", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: "Bug Report" }),
|
|
955
988
|
/* @__PURE__ */ jsx3("p", { className: "text-xs text-gray-500 dark:text-gray-400", children: siteId })
|
|
956
989
|
] }),
|
|
@@ -972,10 +1005,10 @@ function ReportModal({
|
|
|
972
1005
|
className: "max-h-40 w-full rounded-md border border-gray-200 object-contain dark:border-gray-700"
|
|
973
1006
|
}
|
|
974
1007
|
) }),
|
|
975
|
-
/* @__PURE__ */ jsx3("div", { className: "min-h-0 flex-1 space-y-3 overflow-y-auto px-4 py-3", children: modalState === "submitted" ? /* @__PURE__ */
|
|
1008
|
+
/* @__PURE__ */ jsx3("div", { className: "min-h-0 flex-1 space-y-3 overflow-y-auto px-4 py-3", children: modalState === "submitted" ? /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
976
1009
|
/* @__PURE__ */ jsx3(CheckCircle2, { className: "mb-3 h-12 w-12 text-green-500" }),
|
|
977
1010
|
/* @__PURE__ */ jsx3("h3", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: "Report Submitted" }),
|
|
978
|
-
/* @__PURE__ */
|
|
1011
|
+
/* @__PURE__ */ jsxs3("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: [
|
|
979
1012
|
"Reference:",
|
|
980
1013
|
" ",
|
|
981
1014
|
/* @__PURE__ */ jsx3("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) })
|
|
@@ -989,7 +1022,7 @@ function ReportModal({
|
|
|
989
1022
|
children: "Done"
|
|
990
1023
|
}
|
|
991
1024
|
)
|
|
992
|
-
] }) : modalState === "error" ? /* @__PURE__ */
|
|
1025
|
+
] }) : modalState === "error" ? /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
993
1026
|
/* @__PURE__ */ jsx3(X, { className: "mb-3 h-12 w-12 text-red-500" }),
|
|
994
1027
|
/* @__PURE__ */ jsx3("h3", { className: "text-lg font-semibold text-gray-900 dark:text-gray-100", children: "Submission Failed" }),
|
|
995
1028
|
/* @__PURE__ */ jsx3("p", { className: "mt-1 text-sm text-gray-500 dark:text-gray-400", children: errorMessage || "Something went wrong. Please try again." }),
|
|
@@ -1001,10 +1034,10 @@ function ReportModal({
|
|
|
1001
1034
|
children: "Try Again"
|
|
1002
1035
|
}
|
|
1003
1036
|
)
|
|
1004
|
-
] }) : modalState === "submitting" ? /* @__PURE__ */
|
|
1037
|
+
] }) : modalState === "submitting" ? /* @__PURE__ */ jsxs3("div", { className: "flex flex-col items-center justify-center py-8", children: [
|
|
1005
1038
|
/* @__PURE__ */ jsx3(Loader2, { className: "mb-3 h-8 w-8 animate-spin text-indigo-500" }),
|
|
1006
1039
|
/* @__PURE__ */ jsx3("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Submitting your report..." })
|
|
1007
|
-
] }) : /* @__PURE__ */
|
|
1040
|
+
] }) : /* @__PURE__ */ jsxs3(Fragment2, { children: [
|
|
1008
1041
|
(captureResult == null ? void 0 : captureResult.screenshot.size) === 0 && /* @__PURE__ */ jsx3("p", { className: "text-xs text-amber-600", children: "Screenshot could not be captured. Please describe the visual issue in detail." }),
|
|
1009
1042
|
messages.map((msg, i) => /* @__PURE__ */ jsx3(
|
|
1010
1043
|
"div",
|
|
@@ -1017,13 +1050,13 @@ function ReportModal({
|
|
|
1017
1050
|
},
|
|
1018
1051
|
i
|
|
1019
1052
|
)),
|
|
1020
|
-
isLoading && /* @__PURE__ */
|
|
1053
|
+
isLoading && /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2 rounded-lg bg-gray-100/50 p-3 dark:bg-gray-800/50", children: [
|
|
1021
1054
|
/* @__PURE__ */ jsx3(Loader2, { className: "h-3.5 w-3.5 animate-spin text-gray-500" }),
|
|
1022
1055
|
/* @__PURE__ */ jsx3("span", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Thinking..." })
|
|
1023
1056
|
] }),
|
|
1024
1057
|
/* @__PURE__ */ jsx3("div", { ref: chatEndRef })
|
|
1025
1058
|
] }) }),
|
|
1026
|
-
modalState === "chatting" && /* @__PURE__ */ jsx3("div", { className: "border-t border-gray-200 px-4 py-3 dark:border-gray-800", children: /* @__PURE__ */
|
|
1059
|
+
modalState === "chatting" && /* @__PURE__ */ jsx3("div", { className: "border-t border-gray-200 px-4 py-3 dark:border-gray-800", children: /* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
|
|
1027
1060
|
/* @__PURE__ */ jsx3(
|
|
1028
1061
|
"textarea",
|
|
1029
1062
|
{
|
|
@@ -1037,8 +1070,8 @@ function ReportModal({
|
|
|
1037
1070
|
disabled: isLoading
|
|
1038
1071
|
}
|
|
1039
1072
|
),
|
|
1040
|
-
/* @__PURE__ */
|
|
1041
|
-
captureResult && (captureResult.consoleErrors.length > 0 || captureResult.networkErrors.length > 0) && /* @__PURE__ */
|
|
1073
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-col gap-2", children: [
|
|
1074
|
+
captureResult && (captureResult.consoleErrors.length > 0 || captureResult.networkErrors.length > 0) && /* @__PURE__ */ jsxs3("p", { className: "flex-1 text-xs text-amber-600", children: [
|
|
1042
1075
|
[
|
|
1043
1076
|
captureResult.consoleErrors.length > 0 ? `${captureResult.consoleErrors.length} console error${captureResult.consoleErrors.length !== 1 ? "s" : ""}` : null,
|
|
1044
1077
|
captureResult.networkErrors.length > 0 ? `${captureResult.networkErrors.length} failed request${captureResult.networkErrors.length !== 1 ? "s" : ""}` : null
|
|
@@ -1046,8 +1079,8 @@ function ReportModal({
|
|
|
1046
1079
|
" ",
|
|
1047
1080
|
"captured \u2014 these will be included in the report."
|
|
1048
1081
|
] }),
|
|
1049
|
-
/* @__PURE__ */
|
|
1050
|
-
/* @__PURE__ */
|
|
1082
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex justify-end gap-2", children: [
|
|
1083
|
+
/* @__PURE__ */ jsxs3(
|
|
1051
1084
|
"button",
|
|
1052
1085
|
{
|
|
1053
1086
|
onClick: sendMessage,
|
|
@@ -1081,7 +1114,7 @@ function ReportModal({
|
|
|
1081
1114
|
}
|
|
1082
1115
|
|
|
1083
1116
|
// src/bug-reporter.tsx
|
|
1084
|
-
import { Fragment as Fragment3, jsx as jsx4, jsxs as
|
|
1117
|
+
import { Fragment as Fragment3, jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1085
1118
|
function JarveBugReporter({
|
|
1086
1119
|
apiUrl,
|
|
1087
1120
|
apiKey,
|
|
@@ -1090,9 +1123,9 @@ function JarveBugReporter({
|
|
|
1090
1123
|
children
|
|
1091
1124
|
}) {
|
|
1092
1125
|
const safeApiKey = apiKey || "";
|
|
1093
|
-
const [captureMode, setCaptureMode] =
|
|
1094
|
-
const [captureResult, setCaptureResult] =
|
|
1095
|
-
const [showModal, setShowModal] =
|
|
1126
|
+
const [captureMode, setCaptureMode] = useState4(false);
|
|
1127
|
+
const [captureResult, setCaptureResult] = useState4(null);
|
|
1128
|
+
const [showModal, setShowModal] = useState4(false);
|
|
1096
1129
|
useEffect3(() => {
|
|
1097
1130
|
startCapturing();
|
|
1098
1131
|
startNetworkCapture();
|
|
@@ -1121,7 +1154,7 @@ function JarveBugReporter({
|
|
|
1121
1154
|
const siteId = safeApiKey.startsWith("brk_") ? safeApiKey.slice(4, 12) : "external";
|
|
1122
1155
|
const reporterName = (user == null ? void 0 : user.name) || "Anonymous";
|
|
1123
1156
|
const reporterEmail = (user == null ? void 0 : user.email) || "unknown@external";
|
|
1124
|
-
return /* @__PURE__ */
|
|
1157
|
+
return /* @__PURE__ */ jsxs4(Fragment3, { children: [
|
|
1125
1158
|
children,
|
|
1126
1159
|
/* @__PURE__ */ jsx4(
|
|
1127
1160
|
FloatingButton,
|