glitchgrab 1.29.0 → 1.30.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
@@ -1011,6 +1011,7 @@ function ReportDialog({
1011
1011
  const [isSubmitting, setIsSubmitting] = (0, import_react2.useState)(false);
1012
1012
  const [submitted, setSubmitted] = (0, import_react2.useState)(false);
1013
1013
  const [screenshots, setScreenshots] = (0, import_react2.useState)([]);
1014
+ const [attachments, setAttachments] = (0, import_react2.useState)([]);
1014
1015
  const [previewIndex, setPreviewIndex] = (0, import_react2.useState)(null);
1015
1016
  const [annotatingIndex, setAnnotatingIndex] = (0, import_react2.useState)(null);
1016
1017
  const fileInputRef = (0, import_react2.useRef)(null);
@@ -1055,14 +1056,26 @@ function ReportDialog({
1055
1056
  const handleFileUpload = (e) => {
1056
1057
  const files = e.target.files;
1057
1058
  if (!files || files.length === 0) return;
1058
- Array.from(files).forEach((file) => {
1059
+ addFiles(Array.from(files));
1060
+ e.target.value = "";
1061
+ };
1062
+ const addFiles = (files) => {
1063
+ files.forEach((file) => {
1059
1064
  const reader = new FileReader();
1060
- reader.onload = () => {
1061
- setScreenshots((prev) => [...prev, reader.result]);
1062
- };
1065
+ if (file.type.startsWith("image/")) {
1066
+ reader.onload = () => {
1067
+ setScreenshots((prev) => [...prev, reader.result]);
1068
+ };
1069
+ } else {
1070
+ reader.onload = () => {
1071
+ setAttachments((prev) => [
1072
+ ...prev,
1073
+ { name: file.name, size: file.size, dataUrl: reader.result }
1074
+ ]);
1075
+ };
1076
+ }
1063
1077
  reader.readAsDataURL(file);
1064
1078
  });
1065
- e.target.value = "";
1066
1079
  };
1067
1080
  const retakeScreenshot = async () => {
1068
1081
  setPreviewIndex(null);
@@ -1368,6 +1381,7 @@ function ReportDialog({
1368
1381
  setIsSubmitting(true);
1369
1382
  const metadata = {};
1370
1383
  if (screenshots.length > 0) metadata.screenshots = JSON.stringify(screenshots);
1384
+ if (attachments.length > 0) metadata.attachments = JSON.stringify(attachments);
1371
1385
  if (showSeverity && reportType === "BUG") {
1372
1386
  metadata.severity = severity;
1373
1387
  }
@@ -1380,6 +1394,7 @@ function ReportDialog({
1380
1394
  setSubmitted(true);
1381
1395
  setDescription("");
1382
1396
  setScreenshots([]);
1397
+ setAttachments([]);
1383
1398
  setTimeout(() => {
1384
1399
  setSubmitted(false);
1385
1400
  handleClose();
@@ -1399,6 +1414,21 @@ function ReportDialog({
1399
1414
  @keyframes gg-b2{0%,100%{height:8px}50%{height:3px}}
1400
1415
  @keyframes gg-b3{0%,100%{height:4px}30%{height:14px}70%{height:5px}}
1401
1416
  @keyframes gg-b4{0%,100%{height:6px}60%{height:13px}}
1417
+ @keyframes gg-bug-crawl{0%,100%{transform:translateX(0) rotate(0deg)}20%{transform:translateX(-1.5px) rotate(-6deg)}40%{transform:translateX(1.5px) rotate(5deg)}60%{transform:translateX(-1px) rotate(-4deg)}80%{transform:translateX(1px) rotate(3deg)}}
1418
+ @keyframes gg-star-spin{0%,100%{transform:scale(1) rotate(0deg)}50%{transform:scale(1.15) rotate(15deg)}}
1419
+ @keyframes gg-ui-grow{0%,100%{transform:scaleY(1)}50%{transform:scaleY(1.12)}}
1420
+ @keyframes gg-perf-sweep{0%,100%{transform:rotate(0deg)}30%{transform:rotate(-12deg)}70%{transform:rotate(10deg)}}
1421
+ @keyframes gg-shield-pulse{0%,100%{transform:scale(1);opacity:1}50%{transform:scale(1.08);opacity:.75}}
1422
+ @keyframes gg-question-shake{0%,100%{transform:rotate(0deg)}25%{transform:rotate(-7deg)}75%{transform:rotate(7deg)}}
1423
+ @keyframes gg-chat-tilt{0%,100%{transform:rotate(0deg) translateY(0)}50%{transform:rotate(-6deg) translateY(-2px)}}
1424
+ button[data-gg-type] > svg{transform-origin:center}
1425
+ button[data-gg-type="BUG"] > svg{animation:gg-bug-crawl 2.2s ease-in-out infinite}
1426
+ button[data-gg-type="FEATURE_REQUEST"] > svg{animation:gg-star-spin 2.6s ease-in-out infinite}
1427
+ button[data-gg-type="UI_IMPROVEMENT"] > svg{animation:gg-ui-grow 1.8s ease-in-out infinite;transform-origin:bottom}
1428
+ button[data-gg-type="PERFORMANCE"] > svg{animation:gg-perf-sweep 2.4s ease-in-out infinite}
1429
+ button[data-gg-type="SECURITY"] > svg{animation:gg-shield-pulse 2.2s ease-in-out infinite;transform-origin:top}
1430
+ button[data-gg-type="QUESTION"] > svg{animation:gg-question-shake 2s ease-in-out infinite}
1431
+ button[data-gg-type="OTHER"] > svg{animation:gg-chat-tilt 2.2s ease-in-out infinite}
1402
1432
  ` }),
1403
1433
  document.body
1404
1434
  ),
@@ -1516,7 +1546,19 @@ function ReportDialog({
1516
1546
  },
1517
1547
  children: step === 1 ? "What's on your mind?" : "Tell us more"
1518
1548
  }
1519
- ),
1549
+ )
1550
+ ]
1551
+ }
1552
+ ),
1553
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1554
+ "div",
1555
+ {
1556
+ style: {
1557
+ display: "flex",
1558
+ alignItems: "center",
1559
+ gap: "8px"
1560
+ },
1561
+ children: [
1520
1562
  step === 1 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1521
1563
  "span",
1522
1564
  {
@@ -1534,45 +1576,45 @@ function ReportDialog({
1534
1576
  },
1535
1577
  children: getShortcutLabel()
1536
1578
  }
1579
+ ),
1580
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1581
+ "button",
1582
+ {
1583
+ type: "button",
1584
+ onClick: handleClose,
1585
+ style: {
1586
+ background: "none",
1587
+ border: "none",
1588
+ cursor: "pointer",
1589
+ padding: "4px",
1590
+ display: "flex",
1591
+ alignItems: "center",
1592
+ justifyContent: "center"
1593
+ },
1594
+ "aria-label": "Close",
1595
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1596
+ "svg",
1597
+ {
1598
+ width: "16",
1599
+ height: "16",
1600
+ viewBox: "0 0 16 16",
1601
+ fill: "none",
1602
+ style: { display: "block" },
1603
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1604
+ "path",
1605
+ {
1606
+ d: "M4 4L12 12M12 4L4 12",
1607
+ stroke: t.textMuted,
1608
+ strokeWidth: "2",
1609
+ strokeLinecap: "round"
1610
+ }
1611
+ )
1612
+ }
1613
+ )
1614
+ }
1537
1615
  )
1538
1616
  ]
1539
1617
  }
1540
- ),
1541
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1542
- "button",
1543
- {
1544
- type: "button",
1545
- onClick: handleClose,
1546
- style: {
1547
- background: "none",
1548
- border: "none",
1549
- cursor: "pointer",
1550
- padding: "4px",
1551
- display: "flex",
1552
- alignItems: "center",
1553
- justifyContent: "center"
1554
- },
1555
- "aria-label": "Close",
1556
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1557
- "svg",
1558
- {
1559
- width: "16",
1560
- height: "16",
1561
- viewBox: "0 0 16 16",
1562
- fill: "none",
1563
- style: { display: "block" },
1564
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1565
- "path",
1566
- {
1567
- d: "M4 4L12 12M12 4L4 12",
1568
- stroke: t.textMuted,
1569
- strokeWidth: "2",
1570
- strokeLinecap: "round"
1571
- }
1572
- )
1573
- }
1574
- )
1575
- }
1576
1618
  )
1577
1619
  ]
1578
1620
  }
@@ -1661,6 +1703,7 @@ function ReportDialog({
1661
1703
  "button",
1662
1704
  {
1663
1705
  type: "button",
1706
+ "data-gg-type": type,
1664
1707
  onClick: () => {
1665
1708
  setReportType(type);
1666
1709
  setStep(2);
@@ -2116,8 +2159,8 @@ function ReportDialog({
2116
2159
  fontWeight: 500
2117
2160
  },
2118
2161
  children: [
2119
- "Screenshots",
2120
- screenshots.length > 0 ? ` (${screenshots.length})` : ""
2162
+ "Attachments",
2163
+ screenshots.length + attachments.length > 0 ? ` (${screenshots.length + attachments.length})` : ""
2121
2164
  ]
2122
2165
  }
2123
2166
  ),
@@ -2255,6 +2298,133 @@ function ReportDialog({
2255
2298
  ))
2256
2299
  }
2257
2300
  ),
2301
+ attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2302
+ "div",
2303
+ {
2304
+ style: {
2305
+ display: "flex",
2306
+ flexDirection: "column",
2307
+ gap: "6px",
2308
+ marginBottom: "8px"
2309
+ },
2310
+ children: attachments.map((a, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2311
+ "div",
2312
+ {
2313
+ style: {
2314
+ display: "flex",
2315
+ alignItems: "center",
2316
+ gap: "8px",
2317
+ padding: "6px 8px",
2318
+ borderRadius: "6px",
2319
+ border: `1px solid ${t.border}`
2320
+ },
2321
+ children: [
2322
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2323
+ "svg",
2324
+ {
2325
+ width: "14",
2326
+ height: "14",
2327
+ viewBox: "0 0 24 24",
2328
+ fill: "none",
2329
+ style: { flexShrink: 0, opacity: 0.6 },
2330
+ children: [
2331
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2332
+ "path",
2333
+ {
2334
+ d: "M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z",
2335
+ stroke: t.textMuted,
2336
+ strokeWidth: "1.5",
2337
+ strokeLinecap: "round",
2338
+ strokeLinejoin: "round"
2339
+ }
2340
+ ),
2341
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2342
+ "path",
2343
+ {
2344
+ d: "M14 2v6h6",
2345
+ stroke: t.textMuted,
2346
+ strokeWidth: "1.5",
2347
+ strokeLinecap: "round",
2348
+ strokeLinejoin: "round"
2349
+ }
2350
+ )
2351
+ ]
2352
+ }
2353
+ ),
2354
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2355
+ "span",
2356
+ {
2357
+ style: {
2358
+ fontSize: "11px",
2359
+ color: t.text,
2360
+ flex: 1,
2361
+ overflow: "hidden",
2362
+ textOverflow: "ellipsis",
2363
+ whiteSpace: "nowrap"
2364
+ },
2365
+ children: a.name
2366
+ }
2367
+ ),
2368
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
2369
+ "span",
2370
+ {
2371
+ style: { fontSize: "10px", color: t.textMuted },
2372
+ children: [
2373
+ (a.size / 1024).toFixed(0),
2374
+ "KB"
2375
+ ]
2376
+ }
2377
+ ),
2378
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2379
+ "button",
2380
+ {
2381
+ type: "button",
2382
+ onClick: () => setAttachments(
2383
+ (prev) => prev.filter((_, idx) => idx !== i)
2384
+ ),
2385
+ "aria-label": `Remove ${a.name}`,
2386
+ style: {
2387
+ width: "16px",
2388
+ height: "16px",
2389
+ borderRadius: "50%",
2390
+ border: "none",
2391
+ background: "#ef4444",
2392
+ color: "#fff",
2393
+ fontSize: "10px",
2394
+ lineHeight: 1,
2395
+ padding: 0,
2396
+ cursor: "pointer",
2397
+ display: "flex",
2398
+ alignItems: "center",
2399
+ justifyContent: "center",
2400
+ flexShrink: 0
2401
+ },
2402
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2403
+ "svg",
2404
+ {
2405
+ width: "8",
2406
+ height: "8",
2407
+ viewBox: "0 0 10 10",
2408
+ fill: "none",
2409
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2410
+ "path",
2411
+ {
2412
+ d: "M1 1L9 9M9 1L1 9",
2413
+ stroke: "currentColor",
2414
+ strokeWidth: "1.5",
2415
+ strokeLinecap: "round"
2416
+ }
2417
+ )
2418
+ }
2419
+ )
2420
+ }
2421
+ )
2422
+ ]
2423
+ },
2424
+ i
2425
+ ))
2426
+ }
2427
+ ),
2258
2428
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2259
2429
  "div",
2260
2430
  {
@@ -2265,17 +2435,7 @@ function ReportDialog({
2265
2435
  onDrop: (e) => {
2266
2436
  e.preventDefault();
2267
2437
  setScreenshotDragOver(false);
2268
- const files = Array.from(
2269
- e.dataTransfer.files
2270
- ).filter((f) => f.type.startsWith("image/"));
2271
- files.forEach((file) => {
2272
- const reader = new FileReader();
2273
- reader.onload = () => setScreenshots((prev) => [
2274
- ...prev,
2275
- reader.result
2276
- ]);
2277
- reader.readAsDataURL(file);
2278
- });
2438
+ addFiles(Array.from(e.dataTransfer.files));
2279
2439
  },
2280
2440
  onDragOver: (e) => {
2281
2441
  e.preventDefault();
@@ -2285,13 +2445,13 @@ function ReportDialog({
2285
2445
  style: {
2286
2446
  border: `1.5px dashed ${screenshotDragOver ? t.accent : t.inputBorder}`,
2287
2447
  borderRadius: "8px",
2288
- padding: screenshots.length > 0 ? "8px 12px" : "18px 12px",
2448
+ padding: screenshots.length + attachments.length > 0 ? "8px 12px" : "18px 12px",
2289
2449
  textAlign: "center",
2290
2450
  cursor: "pointer",
2291
2451
  background: screenshotDragOver ? isDark ? "rgba(34,211,238,0.06)" : "rgba(8,145,178,0.04)" : "transparent",
2292
2452
  transition: "border-color 0.15s ease, background 0.15s ease"
2293
2453
  },
2294
- children: screenshots.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2454
+ children: screenshots.length + attachments.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
2295
2455
  "p",
2296
2456
  {
2297
2457
  style: {
@@ -2360,7 +2520,7 @@ function ReportDialog({
2360
2520
  fontWeight: 600,
2361
2521
  color: t.text
2362
2522
  },
2363
- children: screenshotDragOver ? "Drop to attach" : "Add screenshots"
2523
+ children: screenshotDragOver ? "Drop to attach" : "Add screenshots or files"
2364
2524
  }
2365
2525
  ),
2366
2526
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
@@ -2371,7 +2531,7 @@ function ReportDialog({
2371
2531
  fontSize: "11px",
2372
2532
  color: t.textMuted
2373
2533
  },
2374
- children: "Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
2534
+ children: "Images, PDF, DOC, XLS \xB7 Drag & drop \xB7 Paste \u2318V / Ctrl+V \xB7 Click to browse"
2375
2535
  }
2376
2536
  )
2377
2537
  ] })
@@ -2476,7 +2636,7 @@ function ReportDialog({
2476
2636
  {
2477
2637
  ref: fileInputRef,
2478
2638
  type: "file",
2479
- accept: "image/*",
2639
+ accept: "image/*,.pdf,.doc,.docx,.xls,.xlsx,.csv",
2480
2640
  multiple: true,
2481
2641
  onChange: handleFileUpload,
2482
2642
  style: { display: "none" }