glitchgrab 1.10.0 → 1.12.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
@@ -543,9 +543,9 @@ function GlitchgrabProviderInner({
543
543
  },
544
544
  []
545
545
  );
546
- const openReportDialog = (0, import_react.useCallback)(() => {
546
+ const openReportDialog = (0, import_react.useCallback)((options) => {
547
547
  if (typeof window !== "undefined") {
548
- window.dispatchEvent(new CustomEvent("glitchgrab:open-report"));
548
+ window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
549
549
  }
550
550
  }, []);
551
551
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -618,6 +618,9 @@ function ReportButton({
618
618
  position = "bottom-right",
619
619
  label = "Report Bug",
620
620
  className,
621
+ variant = "classic",
622
+ showSeverity = true,
623
+ types,
621
624
  children
622
625
  }) {
623
626
  var _a, _b;
@@ -631,8 +634,12 @@ function ReportButton({
631
634
  const fileInputRef = (0, import_react2.useRef)(null);
632
635
  const modalRef = (0, import_react2.useRef)(null);
633
636
  const glitchgrab = useGlitchgrabSafe();
637
+ const [step, setStep] = (0, import_react2.useState)(1);
638
+ const [reportType, setReportType] = (0, import_react2.useState)("BUG");
639
+ const [severity, setSeverity] = (0, import_react2.useState)("medium");
640
+ const availableTypes = types != null ? types : ["BUG", "FEATURE_REQUEST", "QUESTION", "OTHER"];
634
641
  if (!glitchgrab) return null;
635
- const { reportBug } = glitchgrab;
642
+ const { reportBug, report } = glitchgrab;
636
643
  const isDark = useIsDark();
637
644
  const t = getTheme(isDark);
638
645
  const handleFileUpload = (e) => {
@@ -667,6 +674,10 @@ function ReportButton({
667
674
  const handleOpen = async () => {
668
675
  setCapturing(true);
669
676
  setSubmitted(false);
677
+ if (variant === "stepper" && availableTypes.length === 1) {
678
+ setReportType(availableTypes[0]);
679
+ setStep(2);
680
+ }
670
681
  try {
671
682
  const { default: html2canvas } = await import("html2canvas-pro");
672
683
  const canvas = await html2canvas(document.body, {
@@ -682,35 +693,53 @@ function ReportButton({
682
693
  setIsOpen(true);
683
694
  };
684
695
  (0, import_react2.useEffect)(() => {
685
- const handler = () => {
686
- if (!isOpen) handleOpen();
696
+ const handler = (e) => {
697
+ if (isOpen) return;
698
+ const detail = e.detail;
699
+ if (detail == null ? void 0 : detail.description) setDescription(detail.description);
700
+ if (detail == null ? void 0 : detail.type) {
701
+ setReportType(detail.type);
702
+ if (variant === "stepper") setStep(2);
703
+ }
704
+ handleOpen();
687
705
  };
688
706
  window.addEventListener("glitchgrab:open-report", handler);
689
707
  return () => window.removeEventListener("glitchgrab:open-report", handler);
690
- }, [isOpen, handleOpen]);
708
+ }, [isOpen, handleOpen, variant]);
691
709
  (0, import_react2.useEffect)(() => {
692
710
  if (!isOpen) return;
693
711
  const handleEsc = (e) => {
694
712
  if (e.key === "Escape") {
695
713
  if (previewOpen) setPreviewOpen(false);
696
- else setIsOpen(false);
714
+ else handleClose();
697
715
  }
698
716
  };
699
717
  document.addEventListener("keydown", handleEsc);
700
718
  return () => document.removeEventListener("keydown", handleEsc);
701
719
  }, [isOpen, previewOpen]);
720
+ const handleClose = () => {
721
+ setIsOpen(false);
722
+ setStep(1);
723
+ setReportType("BUG");
724
+ setSeverity("medium");
725
+ };
702
726
  const handleSubmit = async () => {
703
727
  try {
704
728
  if (!description.trim() || isSubmitting) return;
705
729
  setIsSubmitting(true);
706
- const result = await reportBug(description.trim(), screenshot ? { screenshot } : void 0);
730
+ const metadata = {};
731
+ if (screenshot) metadata.screenshot = screenshot;
732
+ if (variant === "stepper" && showSeverity && reportType === "BUG") {
733
+ metadata.severity = severity;
734
+ }
735
+ const result = variant === "stepper" ? await report(reportType, description.trim(), Object.keys(metadata).length > 0 ? metadata : void 0) : await reportBug(description.trim(), Object.keys(metadata).length > 0 ? metadata : void 0);
707
736
  if (result) {
708
737
  setSubmitted(true);
709
738
  setDescription("");
710
739
  setScreenshot(null);
711
740
  setTimeout(() => {
712
741
  setSubmitted(false);
713
- setIsOpen(false);
742
+ handleClose();
714
743
  }, 2e3);
715
744
  }
716
745
  setIsSubmitting(false);
@@ -752,7 +781,7 @@ function ReportButton({
752
781
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
753
782
  },
754
783
  onClick: () => {
755
- if (!previewOpen) setIsOpen(false);
784
+ if (!previewOpen) handleClose();
756
785
  },
757
786
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
758
787
  "div",
@@ -774,54 +803,90 @@ function ReportButton({
774
803
  isolation: "isolate"
775
804
  },
776
805
  children: [
777
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
806
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
778
807
  "div",
779
808
  {
780
809
  style: {
781
810
  padding: "16px 16px 12px",
782
811
  borderBottom: `1px solid ${t.border}`
783
812
  },
784
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
785
- "div",
786
- {
787
- style: {
788
- display: "flex",
789
- justifyContent: "space-between",
790
- alignItems: "center"
791
- },
792
- children: [
793
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
794
- "span",
795
- {
796
- style: {
797
- fontSize: "15px",
798
- fontWeight: 600,
799
- color: t.text
800
- },
801
- children: "Report a Bug"
802
- }
803
- ),
804
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
805
- "button",
806
- {
807
- type: "button",
808
- onClick: () => setIsOpen(false),
809
- style: {
810
- background: "none",
811
- border: "none",
812
- cursor: "pointer",
813
- padding: "4px",
814
- display: "flex",
815
- alignItems: "center",
816
- justifyContent: "center"
817
- },
818
- "aria-label": "Close",
819
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", style: { display: "block" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 4L12 12M12 4L4 12", stroke: t.textMuted, strokeWidth: "2", strokeLinecap: "round" }) })
820
- }
821
- )
822
- ]
823
- }
824
- )
813
+ children: [
814
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
815
+ "div",
816
+ {
817
+ style: {
818
+ display: "flex",
819
+ justifyContent: "space-between",
820
+ alignItems: "center"
821
+ },
822
+ children: [
823
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
824
+ variant === "stepper" && step > 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
825
+ "button",
826
+ {
827
+ type: "button",
828
+ onClick: () => setStep((s) => s - 1),
829
+ style: {
830
+ background: "none",
831
+ border: "none",
832
+ cursor: "pointer",
833
+ padding: "2px",
834
+ display: "flex",
835
+ alignItems: "center"
836
+ },
837
+ "aria-label": "Back",
838
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M10 3L5 8L10 13", stroke: t.textMuted, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
839
+ }
840
+ ),
841
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
842
+ "span",
843
+ {
844
+ style: {
845
+ fontSize: "15px",
846
+ fontWeight: 600,
847
+ color: t.text
848
+ },
849
+ children: variant === "stepper" ? step === 1 ? "What's on your mind?" : step === 2 ? "Tell us more" : "Review & Send" : "Report a Bug"
850
+ }
851
+ )
852
+ ] }),
853
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
854
+ "button",
855
+ {
856
+ type: "button",
857
+ onClick: handleClose,
858
+ style: {
859
+ background: "none",
860
+ border: "none",
861
+ cursor: "pointer",
862
+ padding: "4px",
863
+ display: "flex",
864
+ alignItems: "center",
865
+ justifyContent: "center"
866
+ },
867
+ "aria-label": "Close",
868
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", style: { display: "block" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M4 4L12 12M12 4L4 12", stroke: t.textMuted, strokeWidth: "2", strokeLinecap: "round" }) })
869
+ }
870
+ )
871
+ ]
872
+ }
873
+ ),
874
+ variant === "stepper" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "0", marginTop: "12px" }, children: [1, 2, 3].map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", alignItems: "center" }, children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
876
+ width: "8px",
877
+ height: "8px",
878
+ borderRadius: "50%",
879
+ backgroundColor: s <= step ? t.accent : t.inputBorder,
880
+ transition: "background-color 0.2s ease"
881
+ } }),
882
+ i < 2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
883
+ width: "40px",
884
+ height: "2px",
885
+ backgroundColor: s < step ? t.accent : t.inputBorder,
886
+ transition: "background-color 0.2s ease"
887
+ } })
888
+ ] }, s)) })
889
+ ]
825
890
  }
826
891
  ),
827
892
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { padding: "16px" }, children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -834,201 +899,474 @@ function ReportButton({
834
899
  fontSize: "14px",
835
900
  fontWeight: 500
836
901
  },
837
- children: "Bug report sent. Thank you!"
902
+ children: variant === "stepper" ? `${getTypeLabel(reportType)} sent. Thank you!` : "Bug report sent. Thank you!"
838
903
  }
839
- ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
840
- screenshot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: "10px", position: "relative" }, children: [
841
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
842
- "img",
843
- {
844
- src: screenshot,
845
- alt: "Page screenshot",
846
- onClick: () => setPreviewOpen(true),
847
- style: {
848
- width: "100%",
849
- borderRadius: "6px",
850
- border: `1px solid ${t.border}`,
851
- maxHeight: "120px",
852
- objectFit: "cover",
853
- objectPosition: "top",
854
- cursor: "pointer"
855
- }
856
- }
857
- ),
858
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
904
+ ) : variant === "stepper" ? (
905
+ /* ─── Stepper Flow ─── */
906
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
907
+ step === 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: availableTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
859
908
  "button",
860
909
  {
861
910
  type: "button",
862
- onClick: () => setScreenshot(null),
911
+ onClick: () => {
912
+ setReportType(type);
913
+ setStep(2);
914
+ },
863
915
  style: {
864
- position: "absolute",
865
- top: "4px",
866
- right: "4px",
867
- background: "rgba(0,0,0,0.6)",
868
- border: "none",
869
- borderRadius: "50%",
870
- width: "20px",
871
- height: "20px",
872
- cursor: "pointer",
873
916
  display: "flex",
917
+ flexDirection: "column",
874
918
  alignItems: "center",
875
- justifyContent: "center"
919
+ gap: "8px",
920
+ padding: "16px 8px",
921
+ borderRadius: "8px",
922
+ border: `1px solid ${t.inputBorder}`,
923
+ background: t.inputBg,
924
+ cursor: "pointer",
925
+ color: t.text,
926
+ fontFamily: "inherit",
927
+ transition: "border-color 0.15s ease"
876
928
  },
877
- "aria-label": "Remove screenshot",
878
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M1 1L9 9M9 1L1 9", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round" }) })
879
- }
880
- ),
881
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
882
- "div",
883
- {
884
- style: {
885
- position: "absolute",
886
- bottom: "4px",
887
- left: "6px",
888
- right: "6px",
889
- display: "flex",
890
- justifyContent: "space-between",
891
- alignItems: "center"
929
+ onMouseEnter: (e) => {
930
+ e.currentTarget.style.borderColor = t.accent;
931
+ },
932
+ onMouseLeave: (e) => {
933
+ e.currentTarget.style.borderColor = t.inputBorder;
892
934
  },
893
935
  children: [
894
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
895
- "span",
896
- {
897
- style: {
898
- background: "rgba(0,0,0,0.6)",
899
- color: "#fff",
900
- fontSize: "10px",
901
- padding: "2px 6px",
902
- borderRadius: "4px"
903
- },
904
- children: [
905
- "Screenshot (",
906
- Math.round(screenshot.length * 0.75 / 1024),
907
- "KB) \u2014 click to preview"
908
- ]
936
+ getTypeIcon(type, t.accent),
937
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
938
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "11px", color: t.textMuted, lineHeight: "1.3" }, children: getTypeSubtitle(type) })
939
+ ]
940
+ },
941
+ type
942
+ )) }),
943
+ step === 2 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
944
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
945
+ "textarea",
946
+ {
947
+ value: description,
948
+ onChange: (e) => setDescription(e.target.value),
949
+ placeholder: getPlaceholder(reportType),
950
+ style: {
951
+ width: "100%",
952
+ minHeight: "100px",
953
+ padding: "10px 12px",
954
+ borderRadius: "8px",
955
+ border: `1px solid ${t.inputBorder}`,
956
+ fontSize: "14px",
957
+ fontFamily: "inherit",
958
+ resize: "vertical",
959
+ outline: "none",
960
+ boxSizing: "border-box",
961
+ color: t.text,
962
+ backgroundColor: t.inputBg
963
+ },
964
+ onFocus: (e) => {
965
+ e.target.style.borderColor = t.accent;
966
+ },
967
+ onBlur: (e) => {
968
+ e.target.style.borderColor = t.inputBorder;
969
+ },
970
+ autoFocus: true
971
+ }
972
+ ),
973
+ showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginTop: "10px" }, children: [
974
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: { fontSize: "12px", color: t.textMuted, marginBottom: "6px", display: "block" }, children: "Severity" }),
975
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
976
+ "button",
977
+ {
978
+ type: "button",
979
+ onClick: () => setSeverity(s),
980
+ style: {
981
+ flex: 1,
982
+ padding: "6px 0",
983
+ borderRadius: "6px",
984
+ border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,
985
+ background: severity === s ? t.accent : "transparent",
986
+ color: severity === s ? t.accentText : t.text,
987
+ fontSize: "12px",
988
+ fontWeight: 600,
989
+ cursor: "pointer",
990
+ fontFamily: "inherit",
991
+ textTransform: "capitalize",
992
+ transition: "all 0.15s ease"
993
+ },
994
+ children: s
995
+ },
996
+ s
997
+ )) })
998
+ ] }),
999
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1000
+ "button",
1001
+ {
1002
+ type: "button",
1003
+ onClick: () => setStep(3),
1004
+ disabled: !description.trim(),
1005
+ style: {
1006
+ marginTop: "12px",
1007
+ width: "100%",
1008
+ padding: "10px",
1009
+ borderRadius: "8px",
1010
+ border: "none",
1011
+ backgroundColor: !description.trim() ? t.bgSecondary : t.accent,
1012
+ color: !description.trim() ? t.textMuted : t.accentText,
1013
+ fontSize: "14px",
1014
+ fontWeight: 600,
1015
+ cursor: !description.trim() ? "not-allowed" : "pointer",
1016
+ fontFamily: "inherit",
1017
+ transition: "background-color 0.15s ease"
1018
+ },
1019
+ children: "Next"
1020
+ }
1021
+ )
1022
+ ] }),
1023
+ step === 3 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1024
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap", marginBottom: "12px" }, children: [
1025
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: {
1026
+ display: "inline-flex",
1027
+ alignItems: "center",
1028
+ gap: "4px",
1029
+ padding: "4px 10px",
1030
+ borderRadius: "12px",
1031
+ fontSize: "12px",
1032
+ fontWeight: 600,
1033
+ backgroundColor: t.bgSecondary,
1034
+ color: t.text,
1035
+ border: `1px solid ${t.border}`
1036
+ }, children: [
1037
+ getTypeIcon(reportType, t.accent, 12),
1038
+ getTypeLabel(reportType)
1039
+ ] }),
1040
+ showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { style: {
1041
+ display: "inline-flex",
1042
+ alignItems: "center",
1043
+ padding: "4px 10px",
1044
+ borderRadius: "12px",
1045
+ fontSize: "12px",
1046
+ fontWeight: 600,
1047
+ backgroundColor: severity === "high" ? "#fef2f2" : severity === "medium" ? "#fffbeb" : "#f0fdf4",
1048
+ color: severity === "high" ? "#dc2626" : severity === "medium" ? "#d97706" : "#16a34a",
1049
+ border: `1px solid ${severity === "high" ? "#fecaca" : severity === "medium" ? "#fde68a" : "#bbf7d0"}`,
1050
+ textTransform: "capitalize"
1051
+ }, children: severity })
1052
+ ] }),
1053
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: {
1054
+ padding: "10px 12px",
1055
+ borderRadius: "8px",
1056
+ border: `1px solid ${t.inputBorder}`,
1057
+ backgroundColor: t.inputBg,
1058
+ fontSize: "13px",
1059
+ color: t.text,
1060
+ marginBottom: "10px",
1061
+ maxHeight: "80px",
1062
+ overflow: "hidden",
1063
+ lineHeight: "1.4"
1064
+ }, children: description.length > 200 ? description.slice(0, 200) + "..." : description }),
1065
+ screenshot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: "10px", position: "relative" }, children: [
1066
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1067
+ "img",
1068
+ {
1069
+ src: screenshot,
1070
+ alt: "Page screenshot",
1071
+ onClick: () => setPreviewOpen(true),
1072
+ style: {
1073
+ width: "100%",
1074
+ borderRadius: "6px",
1075
+ border: `1px solid ${t.border}`,
1076
+ maxHeight: "80px",
1077
+ objectFit: "cover",
1078
+ objectPosition: "top",
1079
+ cursor: "pointer"
909
1080
  }
910
- ),
911
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "4px" }, children: [
912
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
913
- "button",
1081
+ }
1082
+ ),
1083
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1084
+ "button",
1085
+ {
1086
+ type: "button",
1087
+ onClick: () => setScreenshot(null),
1088
+ style: {
1089
+ position: "absolute",
1090
+ top: "4px",
1091
+ right: "4px",
1092
+ background: "rgba(0,0,0,0.6)",
1093
+ border: "none",
1094
+ borderRadius: "50%",
1095
+ width: "20px",
1096
+ height: "20px",
1097
+ cursor: "pointer",
1098
+ display: "flex",
1099
+ alignItems: "center",
1100
+ justifyContent: "center"
1101
+ },
1102
+ "aria-label": "Remove screenshot",
1103
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M1 1L9 9M9 1L1 9", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round" }) })
1104
+ }
1105
+ )
1106
+ ] }),
1107
+ !screenshot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "6px", marginBottom: "10px" }, children: [
1108
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1109
+ "button",
1110
+ {
1111
+ type: "button",
1112
+ onClick: () => {
1113
+ var _a2;
1114
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
1115
+ },
1116
+ style: {
1117
+ flex: 1,
1118
+ padding: "8px",
1119
+ borderRadius: "6px",
1120
+ border: `1px dashed ${t.inputBorder}`,
1121
+ textAlign: "center",
1122
+ fontSize: "11px",
1123
+ color: t.textMuted,
1124
+ background: "none",
1125
+ cursor: "pointer"
1126
+ },
1127
+ children: "Upload screenshot"
1128
+ }
1129
+ ),
1130
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1131
+ "button",
1132
+ {
1133
+ type: "button",
1134
+ onClick: retakeScreenshot,
1135
+ style: {
1136
+ flex: 1,
1137
+ padding: "8px",
1138
+ borderRadius: "6px",
1139
+ border: `1px dashed ${t.inputBorder}`,
1140
+ textAlign: "center",
1141
+ fontSize: "11px",
1142
+ color: t.textMuted,
1143
+ background: "none",
1144
+ cursor: "pointer"
1145
+ },
1146
+ children: "Retake screenshot"
1147
+ }
1148
+ )
1149
+ ] }),
1150
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1151
+ "button",
1152
+ {
1153
+ type: "button",
1154
+ onClick: handleSubmit,
1155
+ disabled: isSubmitting,
1156
+ style: {
1157
+ width: "100%",
1158
+ padding: "10px",
1159
+ borderRadius: "8px",
1160
+ border: "none",
1161
+ backgroundColor: isSubmitting ? t.bgSecondary : t.accent,
1162
+ color: isSubmitting ? t.textMuted : t.accentText,
1163
+ fontSize: "14px",
1164
+ fontWeight: 600,
1165
+ cursor: isSubmitting ? "not-allowed" : "pointer",
1166
+ fontFamily: "inherit",
1167
+ transition: "background-color 0.15s ease"
1168
+ },
1169
+ children: isSubmitting ? "Sending..." : "Send Report"
1170
+ }
1171
+ )
1172
+ ] })
1173
+ ] })
1174
+ ) : (
1175
+ /* ─── Classic Flow ─── */
1176
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
1177
+ screenshot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: "10px", position: "relative" }, children: [
1178
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1179
+ "img",
1180
+ {
1181
+ src: screenshot,
1182
+ alt: "Page screenshot",
1183
+ onClick: () => setPreviewOpen(true),
1184
+ style: {
1185
+ width: "100%",
1186
+ borderRadius: "6px",
1187
+ border: `1px solid ${t.border}`,
1188
+ maxHeight: "120px",
1189
+ objectFit: "cover",
1190
+ objectPosition: "top",
1191
+ cursor: "pointer"
1192
+ }
1193
+ }
1194
+ ),
1195
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1196
+ "button",
1197
+ {
1198
+ type: "button",
1199
+ onClick: () => setScreenshot(null),
1200
+ style: {
1201
+ position: "absolute",
1202
+ top: "4px",
1203
+ right: "4px",
1204
+ background: "rgba(0,0,0,0.6)",
1205
+ border: "none",
1206
+ borderRadius: "50%",
1207
+ width: "20px",
1208
+ height: "20px",
1209
+ cursor: "pointer",
1210
+ display: "flex",
1211
+ alignItems: "center",
1212
+ justifyContent: "center"
1213
+ },
1214
+ "aria-label": "Remove screenshot",
1215
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M1 1L9 9M9 1L1 9", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round" }) })
1216
+ }
1217
+ ),
1218
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1219
+ "div",
1220
+ {
1221
+ style: {
1222
+ position: "absolute",
1223
+ bottom: "4px",
1224
+ left: "6px",
1225
+ right: "6px",
1226
+ display: "flex",
1227
+ justifyContent: "space-between",
1228
+ alignItems: "center"
1229
+ },
1230
+ children: [
1231
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1232
+ "span",
914
1233
  {
915
- type: "button",
916
- onClick: () => {
917
- var _a2;
918
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
919
- },
920
1234
  style: {
921
- background: t.accent,
922
- color: t.accentText,
1235
+ background: "rgba(0,0,0,0.6)",
1236
+ color: "#fff",
923
1237
  fontSize: "10px",
924
- padding: "3px 8px",
925
- borderRadius: "4px",
926
- border: "none",
927
- cursor: "pointer",
928
- fontWeight: 600
1238
+ padding: "2px 6px",
1239
+ borderRadius: "4px"
929
1240
  },
930
- children: "Upload"
1241
+ children: [
1242
+ "Screenshot (",
1243
+ Math.round(screenshot.length * 0.75 / 1024),
1244
+ "KB) \u2014 click to preview"
1245
+ ]
931
1246
  }
932
1247
  ),
933
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
934
- "button",
935
- {
936
- type: "button",
937
- onClick: retakeScreenshot,
938
- style: {
939
- background: t.accent,
940
- color: t.accentText,
941
- fontSize: "10px",
942
- padding: "3px 8px",
943
- borderRadius: "4px",
944
- border: "none",
945
- cursor: "pointer",
946
- fontWeight: 600
947
- },
948
- children: "Retake"
949
- }
950
- )
951
- ] })
952
- ]
1248
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "4px" }, children: [
1249
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1250
+ "button",
1251
+ {
1252
+ type: "button",
1253
+ onClick: () => {
1254
+ var _a2;
1255
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
1256
+ },
1257
+ style: {
1258
+ background: t.accent,
1259
+ color: t.accentText,
1260
+ fontSize: "10px",
1261
+ padding: "3px 8px",
1262
+ borderRadius: "4px",
1263
+ border: "none",
1264
+ cursor: "pointer",
1265
+ fontWeight: 600
1266
+ },
1267
+ children: "Upload"
1268
+ }
1269
+ ),
1270
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1271
+ "button",
1272
+ {
1273
+ type: "button",
1274
+ onClick: retakeScreenshot,
1275
+ style: {
1276
+ background: t.accent,
1277
+ color: t.accentText,
1278
+ fontSize: "10px",
1279
+ padding: "3px 8px",
1280
+ borderRadius: "4px",
1281
+ border: "none",
1282
+ cursor: "pointer",
1283
+ fontWeight: 600
1284
+ },
1285
+ children: "Retake"
1286
+ }
1287
+ )
1288
+ ] })
1289
+ ]
1290
+ }
1291
+ )
1292
+ ] }),
1293
+ !screenshot && !submitted && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1294
+ "button",
1295
+ {
1296
+ type: "button",
1297
+ onClick: () => {
1298
+ var _a2;
1299
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
1300
+ },
1301
+ style: {
1302
+ marginBottom: "10px",
1303
+ padding: "10px",
1304
+ borderRadius: "6px",
1305
+ border: `1px dashed ${t.inputBorder}`,
1306
+ textAlign: "center",
1307
+ fontSize: "11px",
1308
+ color: t.textMuted,
1309
+ width: "100%",
1310
+ background: "none",
1311
+ cursor: "pointer"
1312
+ },
1313
+ children: "Click to upload a screenshot"
1314
+ }
1315
+ ),
1316
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1317
+ "textarea",
1318
+ {
1319
+ value: description,
1320
+ onChange: (e) => setDescription(e.target.value),
1321
+ placeholder: "Describe what went wrong...",
1322
+ style: {
1323
+ width: "100%",
1324
+ minHeight: "100px",
1325
+ padding: "10px 12px",
1326
+ borderRadius: "8px",
1327
+ border: `1px solid ${t.inputBorder}`,
1328
+ fontSize: "14px",
1329
+ fontFamily: "inherit",
1330
+ resize: "vertical",
1331
+ outline: "none",
1332
+ boxSizing: "border-box",
1333
+ color: t.text,
1334
+ backgroundColor: t.inputBg
1335
+ },
1336
+ onFocus: (e) => {
1337
+ e.target.style.borderColor = t.accent;
1338
+ },
1339
+ onBlur: (e) => {
1340
+ e.target.style.borderColor = t.inputBorder;
1341
+ },
1342
+ autoFocus: true
1343
+ }
1344
+ ),
1345
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1346
+ "button",
1347
+ {
1348
+ type: "button",
1349
+ onClick: handleSubmit,
1350
+ disabled: !description.trim() || isSubmitting,
1351
+ style: {
1352
+ marginTop: "12px",
1353
+ width: "100%",
1354
+ padding: "10px",
1355
+ borderRadius: "8px",
1356
+ border: "none",
1357
+ backgroundColor: !description.trim() || isSubmitting ? t.bgSecondary : t.accent,
1358
+ color: !description.trim() || isSubmitting ? t.textMuted : t.accentText,
1359
+ fontSize: "14px",
1360
+ fontWeight: 600,
1361
+ cursor: !description.trim() || isSubmitting ? "not-allowed" : "pointer",
1362
+ fontFamily: "inherit",
1363
+ transition: "background-color 0.15s ease"
1364
+ },
1365
+ children: isSubmitting ? "Sending..." : "Send Report"
953
1366
  }
954
1367
  )
955
- ] }),
956
- !screenshot && !submitted && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
957
- "button",
958
- {
959
- type: "button",
960
- onClick: () => {
961
- var _a2;
962
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
963
- },
964
- style: {
965
- marginBottom: "10px",
966
- padding: "10px",
967
- borderRadius: "6px",
968
- border: `1px dashed ${t.inputBorder}`,
969
- textAlign: "center",
970
- fontSize: "11px",
971
- color: t.textMuted,
972
- width: "100%",
973
- background: "none",
974
- cursor: "pointer"
975
- },
976
- children: "Click to upload a screenshot"
977
- }
978
- ),
979
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
980
- "textarea",
981
- {
982
- value: description,
983
- onChange: (e) => setDescription(e.target.value),
984
- placeholder: "Describe what went wrong...",
985
- style: {
986
- width: "100%",
987
- minHeight: "100px",
988
- padding: "10px 12px",
989
- borderRadius: "8px",
990
- border: `1px solid ${t.inputBorder}`,
991
- fontSize: "14px",
992
- fontFamily: "inherit",
993
- resize: "vertical",
994
- outline: "none",
995
- boxSizing: "border-box",
996
- color: t.text,
997
- backgroundColor: t.inputBg
998
- },
999
- onFocus: (e) => {
1000
- e.target.style.borderColor = t.accent;
1001
- },
1002
- onBlur: (e) => {
1003
- e.target.style.borderColor = t.inputBorder;
1004
- },
1005
- autoFocus: true
1006
- }
1007
- ),
1008
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1009
- "button",
1010
- {
1011
- type: "button",
1012
- onClick: handleSubmit,
1013
- disabled: !description.trim() || isSubmitting,
1014
- style: {
1015
- marginTop: "12px",
1016
- width: "100%",
1017
- padding: "10px",
1018
- borderRadius: "8px",
1019
- border: "none",
1020
- backgroundColor: !description.trim() || isSubmitting ? t.bgSecondary : t.accent,
1021
- color: !description.trim() || isSubmitting ? t.textMuted : t.accentText,
1022
- fontSize: "14px",
1023
- fontWeight: 600,
1024
- cursor: !description.trim() || isSubmitting ? "not-allowed" : "pointer",
1025
- fontFamily: "inherit",
1026
- transition: "background-color 0.15s ease"
1027
- },
1028
- children: isSubmitting ? "Sending..." : "Send Report"
1029
- }
1030
- )
1031
- ] }) }),
1368
+ ] })
1369
+ ) }),
1032
1370
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1033
1371
  "div",
1034
1372
  {
@@ -1112,6 +1450,58 @@ function ReportButton({
1112
1450
  )
1113
1451
  ] });
1114
1452
  }
1453
+ function getTypeLabel(type) {
1454
+ switch (type) {
1455
+ case "BUG":
1456
+ return "Bug Report";
1457
+ case "FEATURE_REQUEST":
1458
+ return "Feature Request";
1459
+ case "QUESTION":
1460
+ return "Question";
1461
+ case "OTHER":
1462
+ return "Other";
1463
+ }
1464
+ }
1465
+ function getTypeSubtitle(type) {
1466
+ switch (type) {
1467
+ case "BUG":
1468
+ return "Something isn't working";
1469
+ case "FEATURE_REQUEST":
1470
+ return "Suggest an improvement";
1471
+ case "QUESTION":
1472
+ return "Ask a question";
1473
+ case "OTHER":
1474
+ return "General feedback";
1475
+ }
1476
+ }
1477
+ function getPlaceholder(type) {
1478
+ switch (type) {
1479
+ case "BUG":
1480
+ return "What went wrong?";
1481
+ case "FEATURE_REQUEST":
1482
+ return "Describe the feature you'd like...";
1483
+ case "QUESTION":
1484
+ return "What would you like to know?";
1485
+ case "OTHER":
1486
+ return "Tell us what's on your mind...";
1487
+ }
1488
+ }
1489
+ function getTypeIcon(type, color, size = 24) {
1490
+ const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 } };
1491
+ switch (type) {
1492
+ case "BUG":
1493
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { 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", stroke: color, strokeWidth: "1.5", strokeLinecap: "round" }) });
1494
+ case "FEATURE_REQUEST":
1495
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { 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", stroke: color, strokeWidth: "1.5", strokeLinejoin: "round" }) });
1496
+ case "QUESTION":
1497
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("svg", { ...props, children: [
1498
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
1499
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M9.09 9a3 3 0 015.83 1c0 2-3 3-3 3M12 17h.01", stroke: color, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1500
+ ] });
1501
+ case "OTHER":
1502
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21 15a2 2 0 01-2 2H7l-4 4V5a2 2 0 012-2h14a2 2 0 012 2v10z", stroke: color, strokeWidth: "1.5", strokeLinejoin: "round" }) });
1503
+ }
1504
+ }
1115
1505
  function DefaultTrigger({
1116
1506
  onClick,
1117
1507
  capturing,