glitchgrab 1.20.1 → 1.22.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.mjs CHANGED
@@ -90,7 +90,10 @@ function interceptFetch() {
90
90
  const method = (_a = init == null ? void 0 : init.method) != null ? _a : "GET";
91
91
  const start = Date.now();
92
92
  try {
93
- const response = await origFetch.apply(window, [input, init]);
93
+ const response = await origFetch(
94
+ input,
95
+ init
96
+ );
94
97
  addBreadcrumb("api", `${method} ${url.slice(0, 100)} \u2192 ${response.status}`, {
95
98
  method,
96
99
  status: String(response.status),
@@ -222,7 +225,7 @@ function captureContext(visitedPages) {
222
225
  };
223
226
  }
224
227
  }
225
- var DEFAULT_BASE_URL = "https://www.glitchgrab.dev";
228
+ var DEFAULT_BASE_URL = "https://glitchgrab.dev";
226
229
  var MAX_RETRIES = 3;
227
230
  var RETRY_BASE_MS = 500;
228
231
  async function sendReport(payload, baseUrl) {
@@ -569,6 +572,7 @@ function ReportDialog({
569
572
  showSeverity = true
570
573
  }) {
571
574
  const [isEnhancing, setIsEnhancing] = useState(false);
575
+ const [screenshotDragOver, setScreenshotDragOver] = useState(false);
572
576
  const [mounted, setMounted] = useState(false);
573
577
  useEffect(() => {
574
578
  setMounted(true);
@@ -987,6 +991,144 @@ function ReportDialog({
987
991
  }
988
992
  )
989
993
  ] }),
994
+ /* @__PURE__ */ jsxs("div", { style: { marginTop: "10px" }, children: [
995
+ /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: t.textMuted, marginBottom: "6px", display: "block", fontWeight: 500 }, children: "Screenshot" }),
996
+ screenshot ? /* @__PURE__ */ jsxs("div", { children: [
997
+ /* @__PURE__ */ jsxs("div", { style: { position: "relative" }, children: [
998
+ /* @__PURE__ */ jsx(
999
+ "img",
1000
+ {
1001
+ src: screenshot,
1002
+ alt: "Page screenshot",
1003
+ onClick: () => setPreviewOpen(true),
1004
+ style: {
1005
+ width: "100%",
1006
+ borderRadius: "6px",
1007
+ border: `1px solid ${t.border}`,
1008
+ maxHeight: "64px",
1009
+ objectFit: "cover",
1010
+ objectPosition: "top",
1011
+ cursor: "zoom-in",
1012
+ display: "block"
1013
+ }
1014
+ }
1015
+ ),
1016
+ /* @__PURE__ */ jsx("span", { style: {
1017
+ position: "absolute",
1018
+ bottom: "5px",
1019
+ left: "6px",
1020
+ background: "rgba(0,0,0,0.55)",
1021
+ color: "#fff",
1022
+ fontSize: "10px",
1023
+ padding: "1px 5px",
1024
+ borderRadius: "3px",
1025
+ pointerEvents: "none"
1026
+ }, children: "click to preview" })
1027
+ ] }),
1028
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px", marginTop: "6px" }, children: [
1029
+ /* @__PURE__ */ jsxs(
1030
+ "button",
1031
+ {
1032
+ type: "button",
1033
+ onClick: () => setScreenshot(null),
1034
+ style: {
1035
+ flex: 1,
1036
+ padding: "6px 0",
1037
+ borderRadius: "6px",
1038
+ border: `1px solid ${t.inputBorder}`,
1039
+ background: "transparent",
1040
+ color: "#ef4444",
1041
+ fontSize: "12px",
1042
+ fontWeight: 500,
1043
+ cursor: "pointer",
1044
+ fontFamily: "inherit",
1045
+ display: "flex",
1046
+ alignItems: "center",
1047
+ justifyContent: "center",
1048
+ gap: "4px"
1049
+ },
1050
+ children: [
1051
+ /* @__PURE__ */ jsx("svg", { width: "11", height: "11", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M1 1L9 9M9 1L1 9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }),
1052
+ "Remove"
1053
+ ]
1054
+ }
1055
+ ),
1056
+ /* @__PURE__ */ jsxs(
1057
+ "button",
1058
+ {
1059
+ type: "button",
1060
+ onClick: () => {
1061
+ var _a;
1062
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
1063
+ },
1064
+ style: {
1065
+ flex: 1,
1066
+ padding: "6px 0",
1067
+ borderRadius: "6px",
1068
+ border: `1px solid ${t.inputBorder}`,
1069
+ background: "transparent",
1070
+ color: t.textMuted,
1071
+ fontSize: "12px",
1072
+ fontWeight: 500,
1073
+ cursor: "pointer",
1074
+ fontFamily: "inherit",
1075
+ display: "flex",
1076
+ alignItems: "center",
1077
+ justifyContent: "center",
1078
+ gap: "4px"
1079
+ },
1080
+ children: [
1081
+ /* @__PURE__ */ jsx("svg", { width: "11", height: "11", viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4M17 8l-5-5-5 5M12 3v12", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
1082
+ "Replace"
1083
+ ]
1084
+ }
1085
+ )
1086
+ ] })
1087
+ ] }) : (
1088
+ /* Drop zone */
1089
+ /* @__PURE__ */ jsxs(
1090
+ "div",
1091
+ {
1092
+ onClick: () => {
1093
+ var _a;
1094
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
1095
+ },
1096
+ onDrop: (e) => {
1097
+ e.preventDefault();
1098
+ setScreenshotDragOver(false);
1099
+ const file = Array.from(e.dataTransfer.files).find((f) => f.type.startsWith("image/"));
1100
+ if (!file) return;
1101
+ const reader = new FileReader();
1102
+ reader.onload = () => setScreenshot(reader.result);
1103
+ reader.readAsDataURL(file);
1104
+ },
1105
+ onDragOver: (e) => {
1106
+ e.preventDefault();
1107
+ setScreenshotDragOver(true);
1108
+ },
1109
+ onDragLeave: () => setScreenshotDragOver(false),
1110
+ style: {
1111
+ border: `1.5px dashed ${screenshotDragOver ? t.accent : t.inputBorder}`,
1112
+ borderRadius: "8px",
1113
+ padding: "18px 12px",
1114
+ textAlign: "center",
1115
+ cursor: "pointer",
1116
+ background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
1117
+ transition: "border-color 0.15s ease, background 0.15s ease"
1118
+ },
1119
+ children: [
1120
+ /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", style: { margin: "0 auto 6px", display: "block", opacity: 0.45 }, children: [
1121
+ /* @__PURE__ */ jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", stroke: t.textMuted, strokeWidth: "1.5" }),
1122
+ /* @__PURE__ */ jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5", stroke: t.textMuted, strokeWidth: "1.5" }),
1123
+ /* @__PURE__ */ jsx("path", { d: "M21 15l-5-5L5 21", stroke: t.textMuted, strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
1124
+ ] }),
1125
+ /* @__PURE__ */ jsx("p", { style: { margin: 0, fontSize: "12px", fontWeight: 600, color: t.text }, children: screenshotDragOver ? "Drop to attach" : "Add a screenshot" }),
1126
+ /* @__PURE__ */ jsx("p", { style: { margin: "3px 0 0", fontSize: "11px", color: t.textMuted }, children: "Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse" })
1127
+ ]
1128
+ }
1129
+ )
1130
+ )
1131
+ ] }),
990
1132
  showSeverity && reportType === "BUG" && /* @__PURE__ */ jsxs("div", { style: { marginTop: "10px" }, children: [
991
1133
  /* @__PURE__ */ jsx("span", { style: { fontSize: "12px", color: t.textMuted, marginBottom: "6px", display: "block" }, children: "Severity" }),
992
1134
  /* @__PURE__ */ jsx("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ jsx(
@@ -1088,91 +1230,23 @@ function ReportDialog({
1088
1230
  overflow: "hidden",
1089
1231
  lineHeight: "1.4"
1090
1232
  }, children: description.length > 200 ? description.slice(0, 200) + "..." : description }),
1091
- screenshot && /* @__PURE__ */ jsxs("div", { style: { marginBottom: "10px", position: "relative" }, children: [
1092
- /* @__PURE__ */ jsx(
1093
- "img",
1094
- {
1095
- src: screenshot,
1096
- alt: "Page screenshot",
1097
- onClick: () => setPreviewOpen(true),
1098
- style: {
1099
- width: "100%",
1100
- borderRadius: "6px",
1101
- border: `1px solid ${t.border}`,
1102
- maxHeight: "80px",
1103
- objectFit: "cover",
1104
- objectPosition: "top",
1105
- cursor: "pointer"
1106
- }
1107
- }
1108
- ),
1109
- /* @__PURE__ */ jsx(
1110
- "button",
1111
- {
1112
- type: "button",
1113
- onClick: () => setScreenshot(null),
1114
- style: {
1115
- position: "absolute",
1116
- top: "4px",
1117
- right: "4px",
1118
- background: "rgba(0,0,0,0.6)",
1119
- border: "none",
1120
- borderRadius: "50%",
1121
- width: "20px",
1122
- height: "20px",
1123
- cursor: "pointer",
1124
- display: "flex",
1125
- alignItems: "center",
1126
- justifyContent: "center"
1127
- },
1128
- "aria-label": "Remove screenshot",
1129
- children: /* @__PURE__ */ jsx("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M1 1L9 9M9 1L1 9", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round" }) })
1130
- }
1131
- )
1132
- ] }),
1133
- !screenshot && /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "6px", marginBottom: "10px" }, children: [
1134
- /* @__PURE__ */ jsx(
1135
- "button",
1136
- {
1137
- type: "button",
1138
- onClick: () => {
1139
- var _a;
1140
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
1141
- },
1142
- style: {
1143
- flex: 1,
1144
- padding: "8px",
1145
- borderRadius: "6px",
1146
- border: `1px dashed ${t.inputBorder}`,
1147
- textAlign: "center",
1148
- fontSize: "11px",
1149
- color: t.textMuted,
1150
- background: "none",
1151
- cursor: "pointer"
1152
- },
1153
- children: "Upload or paste (\u2318V)"
1154
- }
1155
- ),
1156
- /* @__PURE__ */ jsx(
1157
- "button",
1158
- {
1159
- type: "button",
1160
- onClick: retakeScreenshot,
1161
- style: {
1162
- flex: 1,
1163
- padding: "8px",
1164
- borderRadius: "6px",
1165
- border: `1px dashed ${t.inputBorder}`,
1166
- textAlign: "center",
1167
- fontSize: "11px",
1168
- color: t.textMuted,
1169
- background: "none",
1170
- cursor: "pointer"
1171
- },
1172
- children: "Retake screenshot"
1233
+ screenshot && /* @__PURE__ */ jsx("div", { style: { marginBottom: "10px", position: "relative" }, children: /* @__PURE__ */ jsx(
1234
+ "img",
1235
+ {
1236
+ src: screenshot,
1237
+ alt: "Page screenshot",
1238
+ onClick: () => setPreviewOpen(true),
1239
+ style: {
1240
+ width: "100%",
1241
+ borderRadius: "6px",
1242
+ border: `1px solid ${t.border}`,
1243
+ maxHeight: "80px",
1244
+ objectFit: "cover",
1245
+ objectPosition: "top",
1246
+ cursor: "pointer"
1173
1247
  }
1174
- )
1175
- ] }),
1248
+ }
1249
+ ) }),
1176
1250
  /* @__PURE__ */ jsx(
1177
1251
  "button",
1178
1252
  {
@@ -1335,7 +1409,7 @@ function getTypeIcon(type, color, size = 24) {
1335
1409
 
1336
1410
  // src/provider.tsx
1337
1411
  import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1338
- var DEFAULT_BASE_URL2 = "https://www.glitchgrab.dev";
1412
+ var DEFAULT_BASE_URL2 = "https://glitchgrab.dev";
1339
1413
  var GlitchgrabContext = createContext(null);
1340
1414
  function useGlitchgrab() {
1341
1415
  const ctx = useContext(GlitchgrabContext);
@@ -1404,18 +1478,25 @@ function GlitchgrabProviderInner({
1404
1478
  try {
1405
1479
  if (typeof window === "undefined") return;
1406
1480
  if (process.env.NODE_ENV === "development") return;
1481
+ const EXTENSION_ORIGIN_RE = /\b(?:chrome|safari|moz)-extension:\/\//;
1407
1482
  const handleError = (event) => {
1408
- var _a, _b, _c, _d, _e, _f;
1483
+ var _a, _b, _c, _d, _e, _f, _g;
1409
1484
  try {
1410
1485
  const isOpaqueCrossOrigin = event.message === "Script error." || event.message === "Script error" || !event.error && !event.filename;
1411
1486
  if (isOpaqueCrossOrigin) {
1412
1487
  return;
1413
1488
  }
1489
+ if (event.message === "ResizeObserver loop completed with undelivered notifications." || event.message === "ResizeObserver loop limit exceeded") {
1490
+ return;
1491
+ }
1492
+ if (event.filename && EXTENSION_ORIGIN_RE.test(event.filename) || ((_a = event.error) == null ? void 0 : _a.stack) && EXTENSION_ORIGIN_RE.test(event.error.stack)) {
1493
+ return;
1494
+ }
1414
1495
  const context = captureContext(visitedPagesRef.current);
1415
1496
  const sig = computeSignature({
1416
1497
  errorMessage: event.message,
1417
1498
  pageUrl: context.url,
1418
- errorStack: (_a = event.error) == null ? void 0 : _a.stack
1499
+ errorStack: (_b = event.error) == null ? void 0 : _b.stack
1419
1500
  });
1420
1501
  if (shouldSkipDuplicate(sig)) return;
1421
1502
  const payload = {
@@ -1423,17 +1504,17 @@ function GlitchgrabProviderInner({
1423
1504
  source: "SDK_AUTO",
1424
1505
  type: "BUG",
1425
1506
  errorMessage: event.message,
1426
- errorStack: (_b = event.error) == null ? void 0 : _b.stack,
1507
+ errorStack: (_c = event.error) == null ? void 0 : _c.stack,
1427
1508
  pageUrl: context.url,
1428
1509
  userAgent: context.userAgent,
1429
1510
  breadcrumbs: context.breadcrumbs,
1430
- deviceInfo: (_c = context.deviceInfo) != null ? _c : void 0,
1511
+ deviceInfo: (_d = context.deviceInfo) != null ? _d : void 0,
1431
1512
  metadata: {
1432
1513
  timestamp: context.timestamp,
1433
1514
  visitedPages: JSON.stringify(context.visitedPages),
1434
- filename: (_d = event.filename) != null ? _d : "",
1435
- lineno: String((_e = event.lineno) != null ? _e : ""),
1436
- colno: String((_f = event.colno) != null ? _f : ""),
1515
+ filename: (_e = event.filename) != null ? _e : "",
1516
+ lineno: String((_f = event.lineno) != null ? _f : ""),
1517
+ colno: String((_g = event.colno) != null ? _g : ""),
1437
1518
  ...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
1438
1519
  ...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
1439
1520
  ...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
@@ -1457,6 +1538,7 @@ function GlitchgrabProviderInner({
1457
1538
  return;
1458
1539
  }
1459
1540
  const errStack = reason instanceof Error ? reason.stack : void 0;
1541
+ if (errStack && EXTENSION_ORIGIN_RE.test(errStack)) return;
1460
1542
  const sig = computeSignature({
1461
1543
  errorMessage: errMsg,
1462
1544
  pageUrl: context.url,
@@ -1708,7 +1790,7 @@ function ReportButton({
1708
1790
 
1709
1791
  // src/use-reports.ts
1710
1792
  import { useState as useState4, useEffect as useEffect3, useCallback as useCallback2 } from "react";
1711
- var BASE_URL = "https://www.glitchgrab.dev";
1793
+ var BASE_URL = "https://glitchgrab.dev";
1712
1794
  function useGlitchgrabReports({
1713
1795
  token,
1714
1796
  userId,