glitchgrab 1.25.0 → 1.27.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.js CHANGED
@@ -54,7 +54,7 @@ __export(index_exports, {
54
54
  module.exports = __toCommonJS(index_exports);
55
55
 
56
56
  // src/provider.tsx
57
- var import_react2 = require("react");
57
+ var import_react3 = require("react");
58
58
 
59
59
  // src/error-boundary.tsx
60
60
  var React = __toESM(require("react"));
@@ -499,9 +499,290 @@ var GlitchgrabErrorBoundary = class extends React.Component {
499
499
  };
500
500
 
501
501
  // src/report-dialog.tsx
502
- var import_react = require("react");
502
+ var import_react2 = require("react");
503
503
  var import_react_dom = require("react-dom");
504
+
505
+ // src/annotation-canvas.tsx
506
+ var import_react = require("react");
504
507
  var import_jsx_runtime = require("react/jsx-runtime");
508
+ var PALETTE = ["#ef4444", "#f59e0b", "#22c55e", "#3b82f6", "#a855f7", "#ffffff"];
509
+ function drawStroke(ctx, s) {
510
+ ctx.strokeStyle = s.color;
511
+ ctx.lineWidth = s.width;
512
+ ctx.lineCap = "round";
513
+ ctx.lineJoin = "round";
514
+ if (s.type === "freehand") {
515
+ if (s.points.length < 2) return;
516
+ ctx.beginPath();
517
+ ctx.moveTo(s.points[0].x, s.points[0].y);
518
+ for (let i = 1; i < s.points.length; i++) ctx.lineTo(s.points[i].x, s.points[i].y);
519
+ ctx.stroke();
520
+ } else {
521
+ ctx.beginPath();
522
+ ctx.arc(s.cx, s.cy, s.r, 0, Math.PI * 2);
523
+ ctx.stroke();
524
+ }
525
+ }
526
+ function AnnotationCanvas({ imageSrc, onSave, onCancel }) {
527
+ const canvasRef = (0, import_react.useRef)(null);
528
+ const imgRef = (0, import_react.useRef)(null);
529
+ const [ready, setReady] = (0, import_react.useState)(false);
530
+ const [tool, setTool] = (0, import_react.useState)("pen");
531
+ const [color, setColor] = (0, import_react.useState)(PALETTE[0]);
532
+ const [strokeWidth, setStrokeWidth] = (0, import_react.useState)(4);
533
+ const [strokes, setStrokes] = (0, import_react.useState)([]);
534
+ const [currentStroke, setCurrentStroke] = (0, import_react.useState)(null);
535
+ (0, import_react.useEffect)(() => {
536
+ const img = new Image();
537
+ img.onload = () => {
538
+ imgRef.current = img;
539
+ const canvas = canvasRef.current;
540
+ if (canvas) {
541
+ canvas.width = img.naturalWidth;
542
+ canvas.height = img.naturalHeight;
543
+ }
544
+ setReady(true);
545
+ };
546
+ img.src = imageSrc;
547
+ }, [imageSrc]);
548
+ (0, import_react.useEffect)(() => {
549
+ if (!ready) return;
550
+ const canvas = canvasRef.current;
551
+ const img = imgRef.current;
552
+ if (!canvas || !img) return;
553
+ const ctx = canvas.getContext("2d");
554
+ if (!ctx) return;
555
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
556
+ ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
557
+ for (const s of strokes) drawStroke(ctx, s);
558
+ if (currentStroke) drawStroke(ctx, currentStroke);
559
+ }, [ready, strokes, currentStroke]);
560
+ const getPos = (e) => {
561
+ const canvas = e.currentTarget;
562
+ const rect = canvas.getBoundingClientRect();
563
+ return {
564
+ x: (e.clientX - rect.left) * canvas.width / rect.width,
565
+ y: (e.clientY - rect.top) * canvas.height / rect.height
566
+ };
567
+ };
568
+ const handlePointerDown = (e) => {
569
+ e.currentTarget.setPointerCapture(e.pointerId);
570
+ const { x, y } = getPos(e);
571
+ setCurrentStroke(
572
+ tool === "pen" ? { type: "freehand", color, width: strokeWidth, points: [{ x, y }] } : { type: "circle", color, width: strokeWidth, cx: x, cy: y, r: 0 }
573
+ );
574
+ };
575
+ const handlePointerMove = (e) => {
576
+ if (!currentStroke) return;
577
+ const { x, y } = getPos(e);
578
+ setCurrentStroke((prev) => {
579
+ if (!prev) return prev;
580
+ if (prev.type === "freehand") return { ...prev, points: [...prev.points, { x, y }] };
581
+ return { ...prev, r: Math.hypot(x - prev.cx, y - prev.cy) };
582
+ });
583
+ };
584
+ const handlePointerUp = () => {
585
+ setCurrentStroke((prev) => {
586
+ if (prev) setStrokes((s) => [...s, prev]);
587
+ return null;
588
+ });
589
+ };
590
+ const handleSave = () => {
591
+ const canvas = canvasRef.current;
592
+ if (!canvas) return;
593
+ onSave(canvas.toDataURL("image/jpeg", 0.85));
594
+ };
595
+ const iconBtn = (active = false) => ({
596
+ width: "30px",
597
+ height: "30px",
598
+ display: "flex",
599
+ alignItems: "center",
600
+ justifyContent: "center",
601
+ borderRadius: "6px",
602
+ border: `1.5px solid ${active ? "#22d3ee" : "rgba(255,255,255,0.15)"}`,
603
+ background: active ? "rgba(34,211,238,0.15)" : "transparent",
604
+ color: "#fff",
605
+ cursor: "pointer",
606
+ padding: 0
607
+ });
608
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
609
+ "div",
610
+ {
611
+ style: {
612
+ position: "fixed",
613
+ inset: 0,
614
+ zIndex: 2147483647,
615
+ backgroundColor: "rgba(0,0,0,0.9)",
616
+ display: "flex",
617
+ flexDirection: "column",
618
+ alignItems: "center",
619
+ justifyContent: "center",
620
+ padding: "16px"
621
+ },
622
+ onClick: (e) => {
623
+ e.stopPropagation();
624
+ if (e.target === e.currentTarget) onCancel();
625
+ },
626
+ onPointerDown: (e) => e.stopPropagation(),
627
+ children: [
628
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
629
+ "canvas",
630
+ {
631
+ ref: canvasRef,
632
+ onPointerDown: handlePointerDown,
633
+ onPointerMove: handlePointerMove,
634
+ onPointerUp: handlePointerUp,
635
+ style: {
636
+ maxWidth: "100%",
637
+ maxHeight: "calc(100vh - 140px)",
638
+ borderRadius: "8px",
639
+ touchAction: "none",
640
+ cursor: "crosshair",
641
+ display: "block"
642
+ }
643
+ }
644
+ ),
645
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
646
+ "div",
647
+ {
648
+ style: {
649
+ marginTop: "14px",
650
+ display: "flex",
651
+ alignItems: "center",
652
+ gap: "8px",
653
+ flexWrap: "wrap",
654
+ justifyContent: "center",
655
+ maxWidth: "100%"
656
+ },
657
+ children: [
658
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => setTool("pen"), style: iconBtn(tool === "pen"), title: "Freehand", "aria-label": "Freehand tool", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) }) }),
659
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { type: "button", onClick: () => setTool("circle"), style: iconBtn(tool === "circle"), title: "Circle", "aria-label": "Circle tool", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "8", stroke: "currentColor", strokeWidth: "1.8" }) }) }),
660
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: "1px", height: "20px", background: "rgba(255,255,255,0.15)" } }),
661
+ PALETTE.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
662
+ "button",
663
+ {
664
+ type: "button",
665
+ onClick: () => setColor(c),
666
+ "aria-label": `Color ${c}`,
667
+ style: {
668
+ width: "22px",
669
+ height: "22px",
670
+ borderRadius: "50%",
671
+ background: c,
672
+ border: color === c ? "2px solid #22d3ee" : "2px solid rgba(255,255,255,0.3)",
673
+ cursor: "pointer",
674
+ padding: 0
675
+ }
676
+ },
677
+ c
678
+ )),
679
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
680
+ "input",
681
+ {
682
+ type: "color",
683
+ value: color,
684
+ onChange: (e) => setColor(e.target.value),
685
+ title: "Custom color",
686
+ "aria-label": "Custom color",
687
+ style: {
688
+ width: "22px",
689
+ height: "22px",
690
+ padding: 0,
691
+ border: "none",
692
+ background: "none",
693
+ cursor: "pointer"
694
+ }
695
+ }
696
+ ),
697
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: "1px", height: "20px", background: "rgba(255,255,255,0.15)" } }),
698
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
699
+ "input",
700
+ {
701
+ type: "range",
702
+ min: 2,
703
+ max: 12,
704
+ value: strokeWidth,
705
+ onChange: (e) => setStrokeWidth(Number(e.target.value)),
706
+ title: "Stroke width",
707
+ "aria-label": "Stroke width",
708
+ style: { width: "70px" }
709
+ }
710
+ ),
711
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { width: "1px", height: "20px", background: "rgba(255,255,255,0.15)" } }),
712
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
713
+ "button",
714
+ {
715
+ type: "button",
716
+ onClick: () => setStrokes((s) => s.slice(0, -1)),
717
+ disabled: strokes.length === 0,
718
+ style: { ...iconBtn(), opacity: strokes.length === 0 ? 0.35 : 1 },
719
+ title: "Undo",
720
+ "aria-label": "Undo",
721
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M9 14L4 9l5-5M4 9h10a6 6 0 010 12h-2", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) })
722
+ }
723
+ ),
724
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
725
+ "button",
726
+ {
727
+ type: "button",
728
+ onClick: () => setStrokes([]),
729
+ disabled: strokes.length === 0,
730
+ style: { ...iconBtn(), opacity: strokes.length === 0 ? 0.35 : 1 },
731
+ title: "Clear all",
732
+ "aria-label": "Clear all",
733
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M3 6h18M8 6V4a1 1 0 011-1h6a1 1 0 011 1v2m2 0v14a1 1 0 01-1 1H7a1 1 0 01-1-1V6h12z", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round" }) })
734
+ }
735
+ )
736
+ ]
737
+ }
738
+ ),
739
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "12px", display: "flex", gap: "8px" }, children: [
740
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
741
+ "button",
742
+ {
743
+ type: "button",
744
+ onClick: onCancel,
745
+ style: {
746
+ padding: "8px 16px",
747
+ borderRadius: "8px",
748
+ border: "1.5px solid rgba(255,255,255,0.2)",
749
+ background: "transparent",
750
+ color: "#fff",
751
+ fontSize: "13px",
752
+ fontWeight: 600,
753
+ cursor: "pointer",
754
+ fontFamily: "inherit"
755
+ },
756
+ children: "Cancel"
757
+ }
758
+ ),
759
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
760
+ "button",
761
+ {
762
+ type: "button",
763
+ onClick: handleSave,
764
+ style: {
765
+ padding: "8px 16px",
766
+ borderRadius: "8px",
767
+ border: "none",
768
+ background: "#22d3ee",
769
+ color: "#09090b",
770
+ fontSize: "13px",
771
+ fontWeight: 600,
772
+ cursor: "pointer",
773
+ fontFamily: "inherit"
774
+ },
775
+ children: "Save annotation"
776
+ }
777
+ )
778
+ ] })
779
+ ]
780
+ }
781
+ );
782
+ }
783
+
784
+ // src/report-dialog.tsx
785
+ var import_jsx_runtime2 = require("react/jsx-runtime");
505
786
  function useIsDark() {
506
787
  if (typeof window === "undefined") return true;
507
788
  try {
@@ -690,39 +971,40 @@ function ReportDialog({
690
971
  types,
691
972
  showSeverity = true
692
973
  }) {
693
- const [isEnhancing, setIsEnhancing] = (0, import_react.useState)(false);
694
- const [isEnhanced, setIsEnhanced] = (0, import_react.useState)(false);
695
- const [originalDescription, setOriginalDescription] = (0, import_react.useState)(
974
+ const [isEnhancing, setIsEnhancing] = (0, import_react2.useState)(false);
975
+ const [isEnhanced, setIsEnhanced] = (0, import_react2.useState)(false);
976
+ const [originalDescription, setOriginalDescription] = (0, import_react2.useState)(
696
977
  null
697
978
  );
698
- const [isListening, setIsListening] = (0, import_react.useState)(false);
699
- const [isTranscribing, setIsTranscribing] = (0, import_react.useState)(false);
700
- const [voiceError, setVoiceError] = (0, import_react.useState)(null);
701
- const [screenshotDragOver, setScreenshotDragOver] = (0, import_react.useState)(false);
702
- const [mounted, setMounted] = (0, import_react.useState)(false);
703
- (0, import_react.useEffect)(() => {
979
+ const [isListening, setIsListening] = (0, import_react2.useState)(false);
980
+ const [isTranscribing, setIsTranscribing] = (0, import_react2.useState)(false);
981
+ const [voiceError, setVoiceError] = (0, import_react2.useState)(null);
982
+ const [screenshotDragOver, setScreenshotDragOver] = (0, import_react2.useState)(false);
983
+ const [mounted, setMounted] = (0, import_react2.useState)(false);
984
+ (0, import_react2.useEffect)(() => {
704
985
  setMounted(true);
705
986
  }, []);
706
- const [isOpen, setIsOpen] = (0, import_react.useState)(false);
707
- const [description, setDescription] = (0, import_react.useState)("");
708
- const [isSubmitting, setIsSubmitting] = (0, import_react.useState)(false);
709
- const [submitted, setSubmitted] = (0, import_react.useState)(false);
710
- const [screenshots, setScreenshots] = (0, import_react.useState)([]);
711
- const [previewIndex, setPreviewIndex] = (0, import_react.useState)(null);
712
- const fileInputRef = (0, import_react.useRef)(null);
713
- const modalRef = (0, import_react.useRef)(null);
714
- const previewImgRef = (0, import_react.useRef)(null);
715
- const textareaRef = (0, import_react.useRef)(null);
716
- const recognitionRef = (0, import_react.useRef)(null);
717
- const voiceBaseRef = (0, import_react.useRef)("");
718
- const usingWebSpeechRef = (0, import_react.useRef)(false);
719
- const textBeforeVoiceRef = (0, import_react.useRef)("");
720
- const mediaRecorderRef = (0, import_react.useRef)(null);
721
- const streamRef = (0, import_react.useRef)(null);
722
- const sarvamChunksRef = (0, import_react.useRef)([]);
723
- const spaceTimerRef = (0, import_react.useRef)(null);
724
- const isPushToTalkRef = (0, import_react.useRef)(false);
725
- (0, import_react.useEffect)(() => {
987
+ const [isOpen, setIsOpen] = (0, import_react2.useState)(false);
988
+ const [description, setDescription] = (0, import_react2.useState)("");
989
+ const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
990
+ const [submitted, setSubmitted] = (0, import_react2.useState)(false);
991
+ const [screenshots, setScreenshots] = (0, import_react2.useState)([]);
992
+ const [previewIndex, setPreviewIndex] = (0, import_react2.useState)(null);
993
+ const [annotatingIndex, setAnnotatingIndex] = (0, import_react2.useState)(null);
994
+ const fileInputRef = (0, import_react2.useRef)(null);
995
+ const modalRef = (0, import_react2.useRef)(null);
996
+ const previewImgRef = (0, import_react2.useRef)(null);
997
+ const textareaRef = (0, import_react2.useRef)(null);
998
+ const recognitionRef = (0, import_react2.useRef)(null);
999
+ const voiceBaseRef = (0, import_react2.useRef)("");
1000
+ const usingWebSpeechRef = (0, import_react2.useRef)(false);
1001
+ const textBeforeVoiceRef = (0, import_react2.useRef)("");
1002
+ const mediaRecorderRef = (0, import_react2.useRef)(null);
1003
+ const streamRef = (0, import_react2.useRef)(null);
1004
+ const sarvamChunksRef = (0, import_react2.useRef)([]);
1005
+ const spaceTimerRef = (0, import_react2.useRef)(null);
1006
+ const isPushToTalkRef = (0, import_react2.useRef)(false);
1007
+ (0, import_react2.useEffect)(() => {
726
1008
  if (!isOpen) return;
727
1009
  const dialogs = Array.from(
728
1010
  document.querySelectorAll(
@@ -732,14 +1014,17 @@ function ReportDialog({
732
1014
  dialogs.forEach((d) => d.setAttribute("inert", ""));
733
1015
  return () => dialogs.forEach((d) => d.removeAttribute("inert"));
734
1016
  }, [isOpen]);
735
- const [step, setStep] = (0, import_react.useState)(1);
736
- const [reportType, setReportType] = (0, import_react.useState)("BUG");
737
- const [severity, setSeverity] = (0, import_react.useState)("medium");
738
- const [validationError, setValidationError] = (0, import_react.useState)(null);
739
- const [placeholderIdx, setPlaceholderIdx] = (0, import_react.useState)(0);
1017
+ const [step, setStep] = (0, import_react2.useState)(1);
1018
+ const [reportType, setReportType] = (0, import_react2.useState)("BUG");
1019
+ const [severity, setSeverity] = (0, import_react2.useState)("medium");
1020
+ const [validationError, setValidationError] = (0, import_react2.useState)(null);
1021
+ const [placeholderIdx, setPlaceholderIdx] = (0, import_react2.useState)(0);
740
1022
  const availableTypes = types != null ? types : [
741
1023
  "BUG",
742
1024
  "FEATURE_REQUEST",
1025
+ "UI_IMPROVEMENT",
1026
+ "PERFORMANCE",
1027
+ "SECURITY",
743
1028
  "QUESTION",
744
1029
  "OTHER"
745
1030
  ];
@@ -768,7 +1053,13 @@ function ReportDialog({
768
1053
  scale: 0.5,
769
1054
  logging: false,
770
1055
  useCORS: true,
771
- allowTaint: true
1056
+ allowTaint: true,
1057
+ x: window.scrollX,
1058
+ y: window.scrollY,
1059
+ width: window.innerWidth,
1060
+ height: window.innerHeight,
1061
+ windowWidth: window.innerWidth,
1062
+ windowHeight: window.innerHeight
772
1063
  });
773
1064
  setScreenshots([canvas.toDataURL("image/jpeg", 0.6)]);
774
1065
  } catch (e) {
@@ -787,14 +1078,20 @@ function ReportDialog({
787
1078
  scale: 0.5,
788
1079
  logging: false,
789
1080
  useCORS: true,
790
- allowTaint: true
1081
+ allowTaint: true,
1082
+ x: window.scrollX,
1083
+ y: window.scrollY,
1084
+ width: window.innerWidth,
1085
+ height: window.innerHeight,
1086
+ windowWidth: window.innerWidth,
1087
+ windowHeight: window.innerHeight
791
1088
  });
792
1089
  setScreenshots([canvas.toDataURL("image/jpeg", 0.6)]);
793
1090
  } catch (e) {
794
1091
  }
795
1092
  setIsOpen(true);
796
1093
  };
797
- (0, import_react.useEffect)(() => {
1094
+ (0, import_react2.useEffect)(() => {
798
1095
  const handler = (e) => {
799
1096
  if (isOpen) return;
800
1097
  const detail = e.detail;
@@ -808,7 +1105,7 @@ function ReportDialog({
808
1105
  window.addEventListener("glitchgrab:open-report", handler);
809
1106
  return () => window.removeEventListener("glitchgrab:open-report", handler);
810
1107
  }, [isOpen, handleOpen]);
811
- (0, import_react.useEffect)(() => {
1108
+ (0, import_react2.useEffect)(() => {
812
1109
  if (!isOpen) return;
813
1110
  const handleEsc = (e) => {
814
1111
  if (e.key === "Escape") {
@@ -819,8 +1116,8 @@ function ReportDialog({
819
1116
  document.addEventListener("keydown", handleEsc);
820
1117
  return () => document.removeEventListener("keydown", handleEsc);
821
1118
  }, [isOpen, previewIndex]);
822
- (0, import_react.useEffect)(() => {
823
- if (previewIndex === null) return;
1119
+ (0, import_react2.useEffect)(() => {
1120
+ if (previewIndex === null || annotatingIndex !== null) return;
824
1121
  const handlePointerDown = (e) => {
825
1122
  var _a;
826
1123
  if (!((_a = previewImgRef.current) == null ? void 0 : _a.contains(e.target))) {
@@ -829,8 +1126,8 @@ function ReportDialog({
829
1126
  };
830
1127
  document.addEventListener("pointerdown", handlePointerDown, true);
831
1128
  return () => document.removeEventListener("pointerdown", handlePointerDown, true);
832
- }, [previewIndex]);
833
- (0, import_react.useEffect)(() => {
1129
+ }, [previewIndex, annotatingIndex]);
1130
+ (0, import_react2.useEffect)(() => {
834
1131
  if (!isOpen) return;
835
1132
  const handlePaste = (e) => {
836
1133
  var _a;
@@ -855,7 +1152,7 @@ function ReportDialog({
855
1152
  window.addEventListener("paste", handlePaste);
856
1153
  return () => window.removeEventListener("paste", handlePaste);
857
1154
  }, [isOpen]);
858
- (0, import_react.useEffect)(() => {
1155
+ (0, import_react2.useEffect)(() => {
859
1156
  if (!isOpen || !transcribeAudio2) return;
860
1157
  const id = setInterval(() => {
861
1158
  setPlaceholderIdx((i) => (i + 1) % 2);
@@ -1072,9 +1369,9 @@ function ReportDialog({
1072
1369
  }
1073
1370
  };
1074
1371
  if (!mounted) return null;
1075
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1372
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1076
1373
  isOpen && (0, import_react_dom.createPortal)(
1077
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("style", { children: `
1374
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("style", { children: `
1078
1375
  @keyframes gg-pulse{0%,100%{opacity:1}50%{opacity:0.35}}
1079
1376
  @keyframes gg-b1{0%,100%{height:3px}40%{height:13px}}
1080
1377
  @keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
@@ -1084,7 +1381,7 @@ function ReportDialog({
1084
1381
  document.body
1085
1382
  ),
1086
1383
  isOpen && (0, import_react_dom.createPortal)(
1087
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1384
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1088
1385
  "div",
1089
1386
  {
1090
1387
  style: {
@@ -1103,7 +1400,7 @@ function ReportDialog({
1103
1400
  },
1104
1401
  onPointerDown: (e) => e.stopPropagation(),
1105
1402
  onFocus: (e) => e.stopPropagation(),
1106
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1403
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1107
1404
  "div",
1108
1405
  {
1109
1406
  ref: modalRef,
@@ -1122,7 +1419,7 @@ function ReportDialog({
1122
1419
  isolation: "isolate"
1123
1420
  },
1124
1421
  children: [
1125
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1422
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1126
1423
  "div",
1127
1424
  {
1128
1425
  style: {
@@ -1130,7 +1427,7 @@ function ReportDialog({
1130
1427
  borderBottom: `1px solid ${t.border}`
1131
1428
  },
1132
1429
  children: [
1133
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1430
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1134
1431
  "div",
1135
1432
  {
1136
1433
  style: {
@@ -1139,7 +1436,7 @@ function ReportDialog({
1139
1436
  alignItems: "center"
1140
1437
  },
1141
1438
  children: [
1142
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1439
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1143
1440
  "div",
1144
1441
  {
1145
1442
  style: {
@@ -1148,7 +1445,7 @@ function ReportDialog({
1148
1445
  gap: "8px"
1149
1446
  },
1150
1447
  children: [
1151
- step > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1448
+ step > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1152
1449
  "button",
1153
1450
  {
1154
1451
  type: "button",
@@ -1162,14 +1459,14 @@ function ReportDialog({
1162
1459
  alignItems: "center"
1163
1460
  },
1164
1461
  "aria-label": "Back",
1165
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1462
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1166
1463
  "svg",
1167
1464
  {
1168
1465
  width: "16",
1169
1466
  height: "16",
1170
1467
  viewBox: "0 0 16 16",
1171
1468
  fill: "none",
1172
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1469
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1173
1470
  "path",
1174
1471
  {
1175
1472
  d: "M10 3L5 8L10 13",
@@ -1183,7 +1480,7 @@ function ReportDialog({
1183
1480
  )
1184
1481
  }
1185
1482
  ),
1186
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1483
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1187
1484
  "span",
1188
1485
  {
1189
1486
  style: {
@@ -1197,7 +1494,7 @@ function ReportDialog({
1197
1494
  ]
1198
1495
  }
1199
1496
  ),
1200
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1497
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1201
1498
  "button",
1202
1499
  {
1203
1500
  type: "button",
@@ -1212,7 +1509,7 @@ function ReportDialog({
1212
1509
  justifyContent: "center"
1213
1510
  },
1214
1511
  "aria-label": "Close",
1215
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1512
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1216
1513
  "svg",
1217
1514
  {
1218
1515
  width: "16",
@@ -1220,7 +1517,7 @@ function ReportDialog({
1220
1517
  viewBox: "0 0 16 16",
1221
1518
  fill: "none",
1222
1519
  style: { display: "block" },
1223
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1520
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1224
1521
  "path",
1225
1522
  {
1226
1523
  d: "M4 4L12 12M12 4L4 12",
@@ -1236,7 +1533,7 @@ function ReportDialog({
1236
1533
  ]
1237
1534
  }
1238
1535
  ),
1239
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1536
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1240
1537
  "div",
1241
1538
  {
1242
1539
  style: {
@@ -1246,12 +1543,12 @@ function ReportDialog({
1246
1543
  gap: "0",
1247
1544
  marginTop: "12px"
1248
1545
  },
1249
- children: [1, 2].map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1546
+ children: [1, 2].map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1250
1547
  "div",
1251
1548
  {
1252
1549
  style: { display: "flex", alignItems: "center" },
1253
1550
  children: [
1254
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1551
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1255
1552
  "div",
1256
1553
  {
1257
1554
  style: {
@@ -1263,7 +1560,7 @@ function ReportDialog({
1263
1560
  }
1264
1561
  }
1265
1562
  ),
1266
- i < 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1563
+ i < 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1267
1564
  "div",
1268
1565
  {
1269
1566
  style: {
@@ -1283,7 +1580,7 @@ function ReportDialog({
1283
1580
  ]
1284
1581
  }
1285
1582
  ),
1286
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "16px" }, children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1583
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "16px" }, children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1287
1584
  "div",
1288
1585
  {
1289
1586
  style: {
@@ -1298,8 +1595,8 @@ function ReportDialog({
1298
1595
  " sent. Thank you!"
1299
1596
  ]
1300
1597
  }
1301
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1302
- step === 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1598
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1599
+ step === 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1303
1600
  "div",
1304
1601
  {
1305
1602
  style: {
@@ -1307,7 +1604,7 @@ function ReportDialog({
1307
1604
  gridTemplateColumns: "1fr 1fr",
1308
1605
  gap: "8px"
1309
1606
  },
1310
- children: availableTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1607
+ children: availableTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1311
1608
  "button",
1312
1609
  {
1313
1610
  type: "button",
@@ -1337,8 +1634,8 @@ function ReportDialog({
1337
1634
  },
1338
1635
  children: [
1339
1636
  getTypeIcon(type, t.accent),
1340
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
1341
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1637
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
1638
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1342
1639
  "span",
1343
1640
  {
1344
1641
  style: {
@@ -1355,9 +1652,9 @@ function ReportDialog({
1355
1652
  ))
1356
1653
  }
1357
1654
  ),
1358
- step === 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1359
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { position: "relative" }, children: [
1360
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1655
+ step === 2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1656
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { position: "relative" }, children: [
1657
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1361
1658
  "textarea",
1362
1659
  {
1363
1660
  ref: textareaRef,
@@ -1398,7 +1695,7 @@ function ReportDialog({
1398
1695
  autoFocus: true
1399
1696
  }
1400
1697
  ),
1401
- (isListening || isTranscribing) && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1698
+ (isListening || isTranscribing) && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1402
1699
  "span",
1403
1700
  {
1404
1701
  style: {
@@ -1416,7 +1713,7 @@ function ReportDialog({
1416
1713
  zIndex: 1
1417
1714
  },
1418
1715
  children: [
1419
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1716
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1420
1717
  "span",
1421
1718
  {
1422
1719
  style: {
@@ -1431,7 +1728,7 @@ function ReportDialog({
1431
1728
  }
1432
1729
  ),
1433
1730
  isTranscribing ? "Transcribing\u2026" : "REC",
1434
- isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1731
+ isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1435
1732
  "span",
1436
1733
  {
1437
1734
  style: {
@@ -1458,7 +1755,7 @@ function ReportDialog({
1458
1755
  dur: "0.55s",
1459
1756
  delay: "0.15s"
1460
1757
  }
1461
- ].map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1758
+ ].map((b, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1462
1759
  "span",
1463
1760
  {
1464
1761
  style: {
@@ -1478,7 +1775,7 @@ function ReportDialog({
1478
1775
  ]
1479
1776
  }
1480
1777
  ),
1481
- enhanceText2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1778
+ enhanceText2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1482
1779
  "button",
1483
1780
  {
1484
1781
  type: "button",
@@ -1523,7 +1820,7 @@ function ReportDialog({
1523
1820
  },
1524
1821
  title: "Polish grammar \u2014 preserves your meaning",
1525
1822
  children: [
1526
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1823
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1527
1824
  "svg",
1528
1825
  {
1529
1826
  width: "11",
@@ -1531,7 +1828,7 @@ function ReportDialog({
1531
1828
  viewBox: "0 0 24 24",
1532
1829
  fill: "none",
1533
1830
  "aria-hidden": "true",
1534
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1831
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1535
1832
  "path",
1536
1833
  {
1537
1834
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3zM19 15l.75 2.25L22 18l-2.25.75L19 21l-.75-2.25L16 18l2.25-.75L19 15z",
@@ -1546,7 +1843,7 @@ function ReportDialog({
1546
1843
  ]
1547
1844
  }
1548
1845
  ),
1549
- transcribeAudio2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1846
+ transcribeAudio2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1550
1847
  "button",
1551
1848
  {
1552
1849
  type: "button",
@@ -1572,7 +1869,7 @@ function ReportDialog({
1572
1869
  padding: 0,
1573
1870
  transition: "border-color 0.2s ease, color 0.2s ease"
1574
1871
  },
1575
- children: isListening ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1872
+ children: isListening ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1576
1873
  "svg",
1577
1874
  {
1578
1875
  width: "12",
@@ -1580,7 +1877,7 @@ function ReportDialog({
1580
1877
  viewBox: "0 0 24 24",
1581
1878
  fill: "currentColor",
1582
1879
  "aria-hidden": "true",
1583
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1880
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1584
1881
  "rect",
1585
1882
  {
1586
1883
  x: "6",
@@ -1591,7 +1888,7 @@ function ReportDialog({
1591
1888
  }
1592
1889
  )
1593
1890
  }
1594
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1891
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1595
1892
  "svg",
1596
1893
  {
1597
1894
  width: "13",
@@ -1600,7 +1897,7 @@ function ReportDialog({
1600
1897
  fill: "none",
1601
1898
  "aria-hidden": "true",
1602
1899
  children: [
1603
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1900
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1604
1901
  "rect",
1605
1902
  {
1606
1903
  x: "9",
@@ -1612,7 +1909,7 @@ function ReportDialog({
1612
1909
  strokeWidth: "1.8"
1613
1910
  }
1614
1911
  ),
1615
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1912
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1616
1913
  "path",
1617
1914
  {
1618
1915
  d: "M5 10a7 7 0 0014 0M12 19v3M9 22h6",
@@ -1627,7 +1924,7 @@ function ReportDialog({
1627
1924
  }
1628
1925
  )
1629
1926
  ] }),
1630
- transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1927
+ transcribeAudio2 && !isListening && !isTranscribing && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1631
1928
  "div",
1632
1929
  {
1633
1930
  style: {
@@ -1641,16 +1938,16 @@ function ReportDialog({
1641
1938
  userSelect: "none"
1642
1939
  },
1643
1940
  children: [
1644
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1645
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
1646
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
1647
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
1941
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1942
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z" }),
1943
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M19 10v2a7 7 0 0 1-14 0v-2" }),
1944
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("line", { x1: "12", x2: "12", y1: "19", y2: "22" })
1648
1945
  ] }),
1649
1946
  "Hold Space to speak \u2014 we'll transcribe it"
1650
1947
  ]
1651
1948
  }
1652
1949
  ),
1653
- isEnhanced && originalDescription !== null && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
1950
+ isEnhanced && originalDescription !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1654
1951
  "div",
1655
1952
  {
1656
1953
  style: {
@@ -1664,7 +1961,7 @@ function ReportDialog({
1664
1961
  border: `1px solid ${t.accent}40`
1665
1962
  },
1666
1963
  children: [
1667
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1964
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1668
1965
  "svg",
1669
1966
  {
1670
1967
  width: "12",
@@ -1672,7 +1969,7 @@ function ReportDialog({
1672
1969
  viewBox: "0 0 24 24",
1673
1970
  fill: "none",
1674
1971
  style: { flexShrink: 0 },
1675
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1972
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1676
1973
  "path",
1677
1974
  {
1678
1975
  d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z",
@@ -1683,7 +1980,7 @@ function ReportDialog({
1683
1980
  )
1684
1981
  }
1685
1982
  ),
1686
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1983
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1687
1984
  "span",
1688
1985
  {
1689
1986
  style: {
@@ -1694,7 +1991,7 @@ function ReportDialog({
1694
1991
  children: "AI enhanced"
1695
1992
  }
1696
1993
  ),
1697
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1994
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1698
1995
  "button",
1699
1996
  {
1700
1997
  type: "button",
@@ -1716,7 +2013,7 @@ function ReportDialog({
1716
2013
  children: "Keep"
1717
2014
  }
1718
2015
  ),
1719
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2016
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1720
2017
  "button",
1721
2018
  {
1722
2019
  type: "button",
@@ -1742,7 +2039,7 @@ function ReportDialog({
1742
2039
  ]
1743
2040
  }
1744
2041
  ),
1745
- voiceError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2042
+ voiceError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1746
2043
  "p",
1747
2044
  {
1748
2045
  style: {
@@ -1754,8 +2051,8 @@ function ReportDialog({
1754
2051
  children: voiceError
1755
2052
  }
1756
2053
  ),
1757
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
1758
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2054
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: "10px" }, children: [
2055
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1759
2056
  "span",
1760
2057
  {
1761
2058
  style: {
@@ -1771,7 +2068,7 @@ function ReportDialog({
1771
2068
  ]
1772
2069
  }
1773
2070
  ),
1774
- screenshots.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2071
+ screenshots.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1775
2072
  "div",
1776
2073
  {
1777
2074
  style: {
@@ -1780,7 +2077,7 @@ function ReportDialog({
1780
2077
  gap: "8px",
1781
2078
  marginBottom: "8px"
1782
2079
  },
1783
- children: screenshots.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2080
+ children: screenshots.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1784
2081
  "div",
1785
2082
  {
1786
2083
  style: {
@@ -1789,7 +2086,7 @@ function ReportDialog({
1789
2086
  height: "56px"
1790
2087
  },
1791
2088
  children: [
1792
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2089
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1793
2090
  "img",
1794
2091
  {
1795
2092
  src,
@@ -1807,7 +2104,7 @@ function ReportDialog({
1807
2104
  }
1808
2105
  }
1809
2106
  ),
1810
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2107
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1811
2108
  "button",
1812
2109
  {
1813
2110
  type: "button",
@@ -1833,14 +2130,14 @@ function ReportDialog({
1833
2130
  alignItems: "center",
1834
2131
  justifyContent: "center"
1835
2132
  },
1836
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2133
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1837
2134
  "svg",
1838
2135
  {
1839
2136
  width: "8",
1840
2137
  height: "8",
1841
2138
  viewBox: "0 0 10 10",
1842
2139
  fill: "none",
1843
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2140
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1844
2141
  "path",
1845
2142
  {
1846
2143
  d: "M1 1L9 9M9 1L1 9",
@@ -1852,6 +2149,52 @@ function ReportDialog({
1852
2149
  }
1853
2150
  )
1854
2151
  }
2152
+ ),
2153
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2154
+ "button",
2155
+ {
2156
+ type: "button",
2157
+ onClick: () => setAnnotatingIndex(i),
2158
+ "aria-label": `Annotate screenshot ${i + 1}`,
2159
+ title: "Annotate",
2160
+ style: {
2161
+ position: "absolute",
2162
+ top: "50%",
2163
+ left: "50%",
2164
+ transform: "translate(-50%, -50%)",
2165
+ width: "24px",
2166
+ height: "24px",
2167
+ borderRadius: "50%",
2168
+ border: "none",
2169
+ background: t.accent,
2170
+ color: t.accentText,
2171
+ padding: 0,
2172
+ cursor: "pointer",
2173
+ display: "flex",
2174
+ alignItems: "center",
2175
+ justifyContent: "center",
2176
+ boxShadow: "0 2px 8px rgba(0,0,0,0.45)"
2177
+ },
2178
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2179
+ "svg",
2180
+ {
2181
+ width: "12",
2182
+ height: "12",
2183
+ viewBox: "0 0 24 24",
2184
+ fill: "none",
2185
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2186
+ "path",
2187
+ {
2188
+ d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
2189
+ stroke: "currentColor",
2190
+ strokeWidth: "2.2",
2191
+ strokeLinecap: "round",
2192
+ strokeLinejoin: "round"
2193
+ }
2194
+ )
2195
+ }
2196
+ )
2197
+ }
1855
2198
  )
1856
2199
  ]
1857
2200
  },
@@ -1859,7 +2202,7 @@ function ReportDialog({
1859
2202
  ))
1860
2203
  }
1861
2204
  ),
1862
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2205
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1863
2206
  "div",
1864
2207
  {
1865
2208
  onClick: () => {
@@ -1895,7 +2238,7 @@ function ReportDialog({
1895
2238
  background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
1896
2239
  transition: "border-color 0.15s ease, background 0.15s ease"
1897
2240
  },
1898
- children: screenshots.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2241
+ children: screenshots.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1899
2242
  "p",
1900
2243
  {
1901
2244
  style: {
@@ -1906,8 +2249,8 @@ function ReportDialog({
1906
2249
  },
1907
2250
  children: screenshotDragOver ? "Drop to attach" : "+ Add more \xB7 Drag & drop \xB7 Paste"
1908
2251
  }
1909
- ) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
1910
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2252
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
2253
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1911
2254
  "svg",
1912
2255
  {
1913
2256
  width: "22",
@@ -1920,7 +2263,7 @@ function ReportDialog({
1920
2263
  opacity: 0.45
1921
2264
  },
1922
2265
  children: [
1923
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2266
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1924
2267
  "rect",
1925
2268
  {
1926
2269
  x: "3",
@@ -1932,7 +2275,7 @@ function ReportDialog({
1932
2275
  strokeWidth: "1.5"
1933
2276
  }
1934
2277
  ),
1935
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2278
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1936
2279
  "circle",
1937
2280
  {
1938
2281
  cx: "8.5",
@@ -1942,7 +2285,7 @@ function ReportDialog({
1942
2285
  strokeWidth: "1.5"
1943
2286
  }
1944
2287
  ),
1945
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2288
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1946
2289
  "path",
1947
2290
  {
1948
2291
  d: "M21 15l-5-5L5 21",
@@ -1955,7 +2298,7 @@ function ReportDialog({
1955
2298
  ]
1956
2299
  }
1957
2300
  ),
1958
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2301
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1959
2302
  "p",
1960
2303
  {
1961
2304
  style: {
@@ -1967,7 +2310,7 @@ function ReportDialog({
1967
2310
  children: screenshotDragOver ? "Drop to attach" : "Add screenshots"
1968
2311
  }
1969
2312
  ),
1970
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2313
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1971
2314
  "p",
1972
2315
  {
1973
2316
  style: {
@@ -1982,8 +2325,8 @@ function ReportDialog({
1982
2325
  }
1983
2326
  )
1984
2327
  ] }),
1985
- showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
1986
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2328
+ showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: "10px" }, children: [
2329
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1987
2330
  "span",
1988
2331
  {
1989
2332
  style: {
@@ -1995,7 +2338,7 @@ function ReportDialog({
1995
2338
  children: "Severity"
1996
2339
  }
1997
2340
  ),
1998
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2341
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1999
2342
  "button",
2000
2343
  {
2001
2344
  type: "button",
@@ -2019,7 +2362,7 @@ function ReportDialog({
2019
2362
  s
2020
2363
  )) })
2021
2364
  ] }),
2022
- validationError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2365
+ validationError && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2023
2366
  "p",
2024
2367
  {
2025
2368
  style: {
@@ -2030,7 +2373,7 @@ function ReportDialog({
2030
2373
  children: validationError
2031
2374
  }
2032
2375
  ),
2033
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2376
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2034
2377
  "button",
2035
2378
  {
2036
2379
  type: "button",
@@ -2055,7 +2398,7 @@ function ReportDialog({
2055
2398
  )
2056
2399
  ] })
2057
2400
  ] }) }),
2058
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2401
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2059
2402
  "div",
2060
2403
  {
2061
2404
  style: {
@@ -2063,7 +2406,7 @@ function ReportDialog({
2063
2406
  borderTop: `1px solid ${t.border}`,
2064
2407
  textAlign: "center"
2065
2408
  },
2066
- children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "11px", color: t.textMuted }, children: "Powered by Glitchgrab" })
2409
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t.textMuted }, children: "Powered by Glitchgrab" })
2067
2410
  }
2068
2411
  )
2069
2412
  ]
@@ -2073,7 +2416,7 @@ function ReportDialog({
2073
2416
  ),
2074
2417
  document.body
2075
2418
  ),
2076
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2419
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2077
2420
  "input",
2078
2421
  {
2079
2422
  ref: fileInputRef,
@@ -2085,7 +2428,7 @@ function ReportDialog({
2085
2428
  }
2086
2429
  ),
2087
2430
  previewIndex !== null && screenshots[previewIndex] && (0, import_react_dom.createPortal)(
2088
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
2431
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2089
2432
  "div",
2090
2433
  {
2091
2434
  style: {
@@ -2106,37 +2449,114 @@ function ReportDialog({
2106
2449
  },
2107
2450
  onMouseDown: (e) => e.stopPropagation(),
2108
2451
  children: [
2109
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2110
- "img",
2452
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2453
+ "div",
2111
2454
  {
2112
2455
  ref: previewImgRef,
2113
- src: screenshots[previewIndex],
2114
- alt: "Screenshot preview",
2456
+ style: { position: "relative", maxWidth: "100%" },
2115
2457
  onClick: (e) => e.stopPropagation(),
2116
- style: {
2117
- maxWidth: "100%",
2118
- maxHeight: "calc(100vh - 80px)",
2119
- borderRadius: "8px",
2120
- objectFit: "contain",
2121
- cursor: "default"
2122
- }
2458
+ children: [
2459
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2460
+ "img",
2461
+ {
2462
+ src: screenshots[previewIndex],
2463
+ alt: "Screenshot preview",
2464
+ style: {
2465
+ maxWidth: "100%",
2466
+ maxHeight: "calc(100vh - 80px)",
2467
+ borderRadius: "8px",
2468
+ objectFit: "contain",
2469
+ cursor: "default",
2470
+ display: "block"
2471
+ }
2472
+ }
2473
+ ),
2474
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2475
+ "button",
2476
+ {
2477
+ type: "button",
2478
+ onClick: (e) => {
2479
+ e.stopPropagation();
2480
+ setAnnotatingIndex(previewIndex);
2481
+ },
2482
+ style: {
2483
+ position: "absolute",
2484
+ top: "12px",
2485
+ right: "12px",
2486
+ display: "inline-flex",
2487
+ alignItems: "center",
2488
+ gap: "6px",
2489
+ padding: "8px 14px",
2490
+ borderRadius: "999px",
2491
+ border: "none",
2492
+ background: t.accent,
2493
+ color: t.accentText,
2494
+ fontSize: "13px",
2495
+ fontWeight: 700,
2496
+ cursor: "pointer",
2497
+ fontFamily: "inherit",
2498
+ boxShadow: "0 4px 14px rgba(0,0,0,0.35)",
2499
+ animation: "gg-pulse 2s ease-in-out infinite"
2500
+ },
2501
+ children: [
2502
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "13", height: "13", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2503
+ "path",
2504
+ {
2505
+ d: "M12 20h9M16.5 3.5a2.12 2.12 0 013 3L7 19l-4 1 1-4L16.5 3.5z",
2506
+ stroke: "currentColor",
2507
+ strokeWidth: "2",
2508
+ strokeLinecap: "round",
2509
+ strokeLinejoin: "round"
2510
+ }
2511
+ ) }),
2512
+ "Annotate"
2513
+ ]
2514
+ }
2515
+ )
2516
+ ]
2123
2517
  }
2124
2518
  ),
2125
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2126
- "span",
2519
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2520
+ "div",
2127
2521
  {
2128
2522
  style: {
2129
2523
  marginTop: "12px",
2130
- color: t.textMuted,
2131
- fontSize: "12px"
2524
+ display: "flex",
2525
+ alignItems: "center",
2526
+ gap: "12px"
2132
2527
  },
2133
- children: screenshots.length > 1 ? `${previewIndex + 1} / ${screenshots.length} \xB7 Click outside to close` : "Click outside to close"
2528
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2529
+ "span",
2530
+ {
2531
+ style: {
2532
+ color: t.textMuted,
2533
+ fontSize: "12px"
2534
+ },
2535
+ children: screenshots.length > 1 ? `${previewIndex + 1} / ${screenshots.length} \xB7 Click outside to close` : "Click outside to close"
2536
+ }
2537
+ )
2134
2538
  }
2135
2539
  )
2136
2540
  ]
2137
2541
  }
2138
2542
  ),
2139
2543
  document.body
2544
+ ),
2545
+ annotatingIndex !== null && screenshots[annotatingIndex] && (0, import_react_dom.createPortal)(
2546
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2547
+ AnnotationCanvas,
2548
+ {
2549
+ imageSrc: screenshots[annotatingIndex],
2550
+ onCancel: () => setAnnotatingIndex(null),
2551
+ onSave: (dataUrl) => {
2552
+ setScreenshots(
2553
+ (prev) => prev.map((s, i) => i === annotatingIndex ? dataUrl : s)
2554
+ );
2555
+ setAnnotatingIndex(null);
2556
+ }
2557
+ }
2558
+ ),
2559
+ document.body
2140
2560
  )
2141
2561
  ] });
2142
2562
  }
@@ -2146,6 +2566,12 @@ function getTypeLabel(type) {
2146
2566
  return "Bug Report";
2147
2567
  case "FEATURE_REQUEST":
2148
2568
  return "Feature Request";
2569
+ case "UI_IMPROVEMENT":
2570
+ return "UI Improvement";
2571
+ case "PERFORMANCE":
2572
+ return "Performance";
2573
+ case "SECURITY":
2574
+ return "Security";
2149
2575
  case "QUESTION":
2150
2576
  return "Question";
2151
2577
  case "OTHER":
@@ -2158,6 +2584,12 @@ function getTypeSubtitle(type) {
2158
2584
  return "Something isn't working";
2159
2585
  case "FEATURE_REQUEST":
2160
2586
  return "Suggest an improvement";
2587
+ case "UI_IMPROVEMENT":
2588
+ return "Something looks off";
2589
+ case "PERFORMANCE":
2590
+ return "Something is slow";
2591
+ case "SECURITY":
2592
+ return "Report a security concern";
2161
2593
  case "QUESTION":
2162
2594
  return "Ask a question";
2163
2595
  case "OTHER":
@@ -2171,6 +2603,12 @@ function getPlaceholder(type, idx = 0, hasVoice = false) {
2171
2603
  return "What went wrong? Describe it or paste an error...";
2172
2604
  case "FEATURE_REQUEST":
2173
2605
  return "Describe the feature you'd like...";
2606
+ case "UI_IMPROVEMENT":
2607
+ return "What looks off? Describe the visual issue...";
2608
+ case "PERFORMANCE":
2609
+ return "What's slow? Describe when it happens...";
2610
+ case "SECURITY":
2611
+ return "Describe the security concern...";
2174
2612
  case "QUESTION":
2175
2613
  return "What would you like to know?";
2176
2614
  case "OTHER":
@@ -2187,7 +2625,7 @@ function getTypeIcon(type, color, size = 24) {
2187
2625
  };
2188
2626
  switch (type) {
2189
2627
  case "BUG":
2190
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2628
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2191
2629
  "path",
2192
2630
  {
2193
2631
  d: "M8 2L6.5 3.5M16 2L17.5 3.5M3 9H7M17 9H21M12 2a5 5 0 015 5v4a5 5 0 01-10 0V7a5 5 0 015-5zM7 16l-2 3M17 16l2 3",
@@ -2197,7 +2635,7 @@ function getTypeIcon(type, color, size = 24) {
2197
2635
  }
2198
2636
  ) });
2199
2637
  case "FEATURE_REQUEST":
2200
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2638
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2201
2639
  "path",
2202
2640
  {
2203
2641
  d: "M12 2L15.09 8.26L22 9.27L17 14.14L18.18 21.02L12 17.77L5.82 21.02L7 14.14L2 9.27L8.91 8.26L12 2z",
@@ -2206,10 +2644,55 @@ function getTypeIcon(type, color, size = 24) {
2206
2644
  strokeLinejoin: "round"
2207
2645
  }
2208
2646
  ) });
2647
+ case "UI_IMPROVEMENT":
2648
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
2649
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2650
+ "rect",
2651
+ {
2652
+ x: "3",
2653
+ y: "3",
2654
+ width: "18",
2655
+ height: "18",
2656
+ rx: "2",
2657
+ stroke: color,
2658
+ strokeWidth: "1.5"
2659
+ }
2660
+ ),
2661
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2662
+ "path",
2663
+ {
2664
+ d: "M3 9h18M9 21V9",
2665
+ stroke: color,
2666
+ strokeWidth: "1.5",
2667
+ strokeLinecap: "round"
2668
+ }
2669
+ )
2670
+ ] });
2671
+ case "PERFORMANCE":
2672
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2673
+ "path",
2674
+ {
2675
+ d: "M12 21a9 9 0 100-18 9 9 0 000 18zM12 12l4-4M12 7v.01",
2676
+ stroke: color,
2677
+ strokeWidth: "1.5",
2678
+ strokeLinecap: "round",
2679
+ strokeLinejoin: "round"
2680
+ }
2681
+ ) });
2682
+ case "SECURITY":
2683
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2684
+ "path",
2685
+ {
2686
+ d: "M12 3l7 3v5c0 4.5-3 8.5-7 10-4-1.5-7-5.5-7-10V6l7-3z",
2687
+ stroke: color,
2688
+ strokeWidth: "1.5",
2689
+ strokeLinejoin: "round"
2690
+ }
2691
+ ) });
2209
2692
  case "QUESTION":
2210
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
2211
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
2212
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2693
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
2694
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
2695
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2213
2696
  "path",
2214
2697
  {
2215
2698
  d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01",
@@ -2221,7 +2704,7 @@ function getTypeIcon(type, color, size = 24) {
2221
2704
  )
2222
2705
  ] });
2223
2706
  case "OTHER":
2224
- return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
2707
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2225
2708
  "path",
2226
2709
  {
2227
2710
  d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z",
@@ -2234,11 +2717,11 @@ function getTypeIcon(type, color, size = 24) {
2234
2717
  }
2235
2718
 
2236
2719
  // src/provider.tsx
2237
- var import_jsx_runtime2 = require("react/jsx-runtime");
2720
+ var import_jsx_runtime3 = require("react/jsx-runtime");
2238
2721
  var DEFAULT_BASE_URL2 = "https://glitchgrab.dev";
2239
- var GlitchgrabContext = (0, import_react2.createContext)(null);
2722
+ var GlitchgrabContext = (0, import_react3.createContext)(null);
2240
2723
  function useGlitchgrab() {
2241
- const ctx = (0, import_react2.useContext)(GlitchgrabContext);
2724
+ const ctx = (0, import_react3.useContext)(GlitchgrabContext);
2242
2725
  if (!ctx) {
2243
2726
  throw new Error("useGlitchgrab must be used within a GlitchgrabProvider");
2244
2727
  }
@@ -2258,13 +2741,13 @@ function GlitchgrabProviderInner({
2258
2741
  showSeverity,
2259
2742
  ignoreErrors
2260
2743
  }) {
2261
- const visitedPagesRef = (0, import_react2.useRef)([]);
2262
- (0, import_react2.useEffect)(() => {
2744
+ const visitedPagesRef = (0, import_react3.useRef)([]);
2745
+ (0, import_react3.useEffect)(() => {
2263
2746
  if (enableBreadcrumbs) {
2264
2747
  initBreadcrumbs(maxBreadcrumbs2);
2265
2748
  }
2266
2749
  }, [enableBreadcrumbs, maxBreadcrumbs2]);
2267
- (0, import_react2.useEffect)(() => {
2750
+ (0, import_react3.useEffect)(() => {
2268
2751
  try {
2269
2752
  if (typeof window === "undefined") return;
2270
2753
  const trackPage = () => {
@@ -2301,12 +2784,16 @@ function GlitchgrabProviderInner({
2301
2784
  } catch (e) {
2302
2785
  }
2303
2786
  }, []);
2304
- (0, import_react2.useEffect)(() => {
2787
+ (0, import_react3.useEffect)(() => {
2305
2788
  try {
2306
2789
  if (typeof window === "undefined") return;
2307
2790
  if (process.env.NODE_ENV === "development") return;
2308
2791
  const EXTENSION_ORIGIN_RE = /\b(?:chrome|safari|moz)-extension:\/\//;
2792
+ const KNOWN_NOISE_RE = [
2793
+ /Object Not Found Matching Id:\d+, MethodName:update, ParamCount:\d+/
2794
+ ];
2309
2795
  const matchesIgnore = (message) => {
2796
+ if (KNOWN_NOISE_RE.some((pattern) => pattern.test(message))) return true;
2310
2797
  if (!ignoreErrors || ignoreErrors.length === 0) return false;
2311
2798
  return ignoreErrors.some(
2312
2799
  (pattern) => pattern instanceof RegExp ? pattern.test(message) : message.includes(pattern)
@@ -2420,7 +2907,7 @@ function GlitchgrabProviderInner({
2420
2907
  } catch (e) {
2421
2908
  }
2422
2909
  }, [token, baseUrl, onError, onReportSent, session, ignoreErrors]);
2423
- const report = (0, import_react2.useCallback)(
2910
+ const report = (0, import_react3.useCallback)(
2424
2911
  async (type, description, metadata) => {
2425
2912
  var _a;
2426
2913
  try {
@@ -2453,17 +2940,17 @@ function GlitchgrabProviderInner({
2453
2940
  },
2454
2941
  [token, baseUrl, onReportSent, session]
2455
2942
  );
2456
- const reportBug = (0, import_react2.useCallback)(
2943
+ const reportBug = (0, import_react3.useCallback)(
2457
2944
  (description, metadata) => report("BUG", description, metadata),
2458
2945
  [report]
2459
2946
  );
2460
- const addBreadcrumb2 = (0, import_react2.useCallback)(
2947
+ const addBreadcrumb2 = (0, import_react3.useCallback)(
2461
2948
  (message, data) => {
2462
2949
  addBreadcrumb("custom", message, data);
2463
2950
  },
2464
2951
  []
2465
2952
  );
2466
- const enhance = (0, import_react2.useCallback)(
2953
+ const enhance = (0, import_react3.useCallback)(
2467
2954
  async (text, screenshot) => {
2468
2955
  try {
2469
2956
  const ctx = captureContext(visitedPagesRef.current);
@@ -2479,7 +2966,7 @@ function GlitchgrabProviderInner({
2479
2966
  },
2480
2967
  [token, baseUrl]
2481
2968
  );
2482
- const transcribe = (0, import_react2.useCallback)(
2969
+ const transcribe = (0, import_react3.useCallback)(
2483
2970
  async (blob) => {
2484
2971
  try {
2485
2972
  return await transcribeAudio(blob, token, baseUrl);
@@ -2489,12 +2976,12 @@ function GlitchgrabProviderInner({
2489
2976
  },
2490
2977
  [token, baseUrl]
2491
2978
  );
2492
- const openReportDialog = (0, import_react2.useCallback)((options) => {
2979
+ const openReportDialog = (0, import_react3.useCallback)((options) => {
2493
2980
  if (typeof window !== "undefined") {
2494
2981
  window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
2495
2982
  }
2496
2983
  }, []);
2497
- (0, import_react2.useEffect)(() => {
2984
+ (0, import_react3.useEffect)(() => {
2498
2985
  try {
2499
2986
  if (typeof window === "undefined") return;
2500
2987
  const handleKeyDown = (e) => {
@@ -2508,7 +2995,7 @@ function GlitchgrabProviderInner({
2508
2995
  } catch (e) {
2509
2996
  }
2510
2997
  }, [openReportDialog]);
2511
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2998
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
2512
2999
  GlitchgrabContext.Provider,
2513
3000
  {
2514
3001
  value: {
@@ -2521,7 +3008,7 @@ function GlitchgrabProviderInner({
2521
3008
  enhanceText: enhance
2522
3009
  },
2523
3010
  children: [
2524
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
3011
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
2525
3012
  GlitchgrabErrorBoundary,
2526
3013
  {
2527
3014
  token,
@@ -2533,27 +3020,27 @@ function GlitchgrabProviderInner({
2533
3020
  children
2534
3021
  }
2535
3022
  ),
2536
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportDialog, { report, enhanceText: enhance, transcribeAudio: transcribe, types, showSeverity })
3023
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ReportDialog, { report, enhanceText: enhance, transcribeAudio: transcribe, types, showSeverity })
2537
3024
  ]
2538
3025
  }
2539
3026
  );
2540
3027
  }
2541
3028
  function GlitchgrabProvider(props) {
2542
- if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
3029
+ if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: props.children });
2543
3030
  const resolvedProps = {
2544
3031
  ...props,
2545
3032
  baseUrl: props.baseUrl || DEFAULT_BASE_URL2
2546
3033
  };
2547
3034
  try {
2548
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
3035
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
2549
3036
  } catch (e) {
2550
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
3037
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: props.children });
2551
3038
  }
2552
3039
  }
2553
3040
 
2554
3041
  // src/report-button.tsx
2555
- var import_react3 = require("react");
2556
- var import_jsx_runtime3 = require("react/jsx-runtime");
3042
+ var import_react4 = require("react");
3043
+ var import_jsx_runtime4 = require("react/jsx-runtime");
2557
3044
  function useGlitchgrabSafe() {
2558
3045
  try {
2559
3046
  return useGlitchgrab();
@@ -2568,7 +3055,7 @@ function ReportButton({
2568
3055
  children
2569
3056
  }) {
2570
3057
  var _a, _b;
2571
- const [capturing, setCapturing] = (0, import_react3.useState)(false);
3058
+ const [capturing, setCapturing] = (0, import_react4.useState)(false);
2572
3059
  const glitchgrab = useGlitchgrabSafe();
2573
3060
  if (!glitchgrab) return null;
2574
3061
  const handleClick = async () => {
@@ -2577,7 +3064,7 @@ function ReportButton({
2577
3064
  setCapturing(false);
2578
3065
  };
2579
3066
  if (children) {
2580
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: children({ onClick: handleClick, capturing }) });
3067
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_jsx_runtime4.Fragment, { children: children({ onClick: handleClick, capturing }) });
2581
3068
  }
2582
3069
  const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
2583
3070
  const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
@@ -2585,7 +3072,7 @@ function ReportButton({
2585
3072
  ...isLeft ? { left: "16px" } : { right: "16px" },
2586
3073
  ...isTop ? { top: "16px" } : { bottom: "16px" }
2587
3074
  };
2588
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
3075
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
2589
3076
  "button",
2590
3077
  {
2591
3078
  type: "button",
@@ -2620,7 +3107,7 @@ function ReportButton({
2620
3107
  },
2621
3108
  "aria-label": label,
2622
3109
  children: [
2623
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3110
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2624
3111
  "svg",
2625
3112
  {
2626
3113
  width: "16",
@@ -2628,7 +3115,7 @@ function ReportButton({
2628
3115
  viewBox: "0 0 16 16",
2629
3116
  fill: "none",
2630
3117
  style: { flexShrink: 0 },
2631
- children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
3118
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
2632
3119
  "path",
2633
3120
  {
2634
3121
  d: "M8 1C4.134 1 1 4.134 1 8s3.134 7 7 7 7-3.134 7-7-3.134-7-7-7zm0 12.5a.75.75 0 110-1.5.75.75 0 010 1.5zm.75-3.5a.75.75 0 01-1.5 0V5a.75.75 0 011.5 0v5z",
@@ -2644,18 +3131,18 @@ function ReportButton({
2644
3131
  }
2645
3132
 
2646
3133
  // src/use-reports.ts
2647
- var import_react4 = require("react");
3134
+ var import_react5 = require("react");
2648
3135
  var BASE_URL = "https://glitchgrab.dev";
2649
3136
  function useGlitchgrabReports({
2650
3137
  token,
2651
3138
  userId,
2652
3139
  limit = 100
2653
3140
  }) {
2654
- const [reports, setReports] = (0, import_react4.useState)([]);
2655
- const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
2656
- const [isFetching, setIsFetching] = (0, import_react4.useState)(false);
2657
- const [error, setError] = (0, import_react4.useState)(null);
2658
- const fetchReports = (0, import_react4.useCallback)(async () => {
3141
+ const [reports, setReports] = (0, import_react5.useState)([]);
3142
+ const [isLoading, setIsLoading] = (0, import_react5.useState)(true);
3143
+ const [isFetching, setIsFetching] = (0, import_react5.useState)(false);
3144
+ const [error, setError] = (0, import_react5.useState)(null);
3145
+ const fetchReports = (0, import_react5.useCallback)(async () => {
2659
3146
  var _a, _b;
2660
3147
  if (!token || !userId) {
2661
3148
  setIsLoading(false);
@@ -2681,7 +3168,7 @@ function useGlitchgrabReports({
2681
3168
  setIsFetching(false);
2682
3169
  }
2683
3170
  }, [token, userId, limit]);
2684
- (0, import_react4.useEffect)(() => {
3171
+ (0, import_react5.useEffect)(() => {
2685
3172
  fetchReports();
2686
3173
  }, [fetchReports]);
2687
3174
  return { reports, isLoading, isFetching, error, refetch: fetchReports };
@@ -2718,9 +3205,9 @@ function useGlitchgrabActions({
2718
3205
  onSuccess,
2719
3206
  onError
2720
3207
  }) {
2721
- const [isPending, setIsPending] = (0, import_react4.useState)(false);
2722
- const [error, setError] = (0, import_react4.useState)(null);
2723
- const run = (0, import_react4.useCallback)(
3208
+ const [isPending, setIsPending] = (0, import_react5.useState)(false);
3209
+ const [error, setError] = (0, import_react5.useState)(null);
3210
+ const run = (0, import_react5.useCallback)(
2724
3211
  async (reportId, body) => {
2725
3212
  setIsPending(true);
2726
3213
  setError(null);