@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 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 import_react3 = require("react");
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 sideClasses = position === "left" ? "left-4 md:left-6" : "right-4 md:right-6";
62
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
63
- "button",
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
- onClick,
66
- className: cn(
67
- "fixed z-[9999] flex items-center justify-center rounded-full shadow-lg transition-all duration-200",
68
- "hover:scale-110 focus:ring-2 focus:ring-offset-2 focus:outline-none",
69
- // size + vertical position
70
- "bottom-4 h-11 w-11 md:bottom-6 md:h-12 md:w-12",
71
- // horizontal side
72
- sideClasses,
73
- // active vs idle colors
74
- 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"
75
- ),
76
- title: isActive ? "Cancel bug capture" : "Report a bug",
77
- "aria-label": isActive ? "Cancel bug capture" : "Report a bug",
78
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Bug, { className: "h-4 w-4 md:h-5 md:w-5" })
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 import_react = require("react");
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, import_react.useState)(null);
414
- const [hoveredRect, setHoveredRect] = (0, import_react.useState)(null);
415
- const [isCapturing3, setIsCapturing] = (0, import_react.useState)(false);
416
- const [isTouchMode, setIsTouchMode] = (0, import_react.useState)(false);
417
- const [selectedSection, setSelectedSection] = (0, import_react.useState)(null);
418
- const [selectedRect, setSelectedRect] = (0, import_react.useState)(null);
419
- const [selectedTarget, setSelectedTarget] = (0, import_react.useState)(null);
420
- const overlayRef = (0, import_react.useRef)(null);
421
- const hoveredElementRef = (0, import_react.useRef)(null);
422
- const rafRef = (0, import_react.useRef)(null);
423
- const touchCoordsRef = (0, import_react.useRef)(null);
424
- (0, import_react.useEffect)(() => {
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, import_react.useCallback)(
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, import_react.useCallback)(
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, import_react.useCallback)(
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, import_react.useCallback)(
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, import_react.useCallback)(async () => {
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, import_react.useCallback)(
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, import_react.useCallback)(
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, import_react.useCallback)(() => {
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, import_react.useEffect)(() => {
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 import_react2 = require("react");
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, import_react2.useState)([]);
727
- const [input, setInput] = (0, import_react2.useState)("");
728
- const [isLoading, setIsLoading] = (0, import_react2.useState)(false);
729
- const [modalState, setModalState] = (0, import_react2.useState)("chatting");
730
- const [reportId, setReportId] = (0, import_react2.useState)(null);
731
- const [screenshotUrl, setScreenshotUrl] = (0, import_react2.useState)(null);
732
- const [errorMessage, setErrorMessage] = (0, import_react2.useState)(null);
733
- const chatEndRef = (0, import_react2.useRef)(null);
734
- const inputRef = (0, import_react2.useRef)(null);
735
- const hasInitRef = (0, import_react2.useRef)(false);
736
- const apiHeaders = (0, import_react2.useMemo)(
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, import_react2.useEffect)(() => {
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, import_react2.useCallback)(async () => {
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, import_react2.useEffect)(() => {
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, import_react2.useEffect)(() => {
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, import_react2.useEffect)(() => {
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, import_react2.useCallback)(
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, import_react2.useCallback)(() => {
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, import_react3.useState)(false);
1117
- const [captureResult, setCaptureResult] = (0, import_react3.useState)(null);
1118
- const [showModal, setShowModal] = (0, import_react3.useState)(false);
1119
- (0, import_react3.useEffect)(() => {
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, import_react3.useCallback)(() => {
1160
+ const toggleCaptureMode = (0, import_react4.useCallback)(() => {
1128
1161
  setCaptureMode((prev) => !prev);
1129
1162
  }, []);
1130
- const handleCapture = (0, import_react3.useCallback)((result) => {
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, import_react3.useCallback)(() => {
1168
+ const handleCancelCapture = (0, import_react4.useCallback)(() => {
1136
1169
  setCaptureMode(false);
1137
1170
  }, []);
1138
- const handleCloseModal = (0, import_react3.useCallback)(() => {
1171
+ const handleCloseModal = (0, import_react4.useCallback)(() => {
1139
1172
  setShowModal(false);
1140
1173
  setCaptureResult(null);
1141
1174
  clearCapturedErrors();