glitchgrab 1.12.0 → 1.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +27 -8
- package/dist/index.d.ts +27 -8
- package/dist/index.js +536 -736
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +522 -722
- package/dist/index.mjs.map +1 -1
- package/package.json +11 -5
package/dist/index.js
CHANGED
|
@@ -50,7 +50,7 @@ __export(index_exports, {
|
|
|
50
50
|
module.exports = __toCommonJS(index_exports);
|
|
51
51
|
|
|
52
52
|
// src/provider.tsx
|
|
53
|
-
var
|
|
53
|
+
var import_react2 = require("react");
|
|
54
54
|
|
|
55
55
|
// src/error-boundary.tsx
|
|
56
56
|
var React = __toESM(require("react"));
|
|
@@ -359,244 +359,10 @@ var GlitchgrabErrorBoundary = class extends React.Component {
|
|
|
359
359
|
}
|
|
360
360
|
};
|
|
361
361
|
|
|
362
|
-
// src/
|
|
363
|
-
var
|
|
364
|
-
var DEFAULT_BASE_URL2 = "https://www.glitchgrab.dev";
|
|
365
|
-
var GlitchgrabContext = (0, import_react.createContext)(null);
|
|
366
|
-
function useGlitchgrab() {
|
|
367
|
-
const ctx = (0, import_react.useContext)(GlitchgrabContext);
|
|
368
|
-
if (!ctx) {
|
|
369
|
-
throw new Error("useGlitchgrab must be used within a GlitchgrabProvider");
|
|
370
|
-
}
|
|
371
|
-
return ctx;
|
|
372
|
-
}
|
|
373
|
-
function GlitchgrabProviderInner({
|
|
374
|
-
token,
|
|
375
|
-
session,
|
|
376
|
-
baseUrl,
|
|
377
|
-
onError,
|
|
378
|
-
onReportSent,
|
|
379
|
-
breadcrumbs: enableBreadcrumbs = true,
|
|
380
|
-
maxBreadcrumbs: maxBreadcrumbs2 = 50,
|
|
381
|
-
children,
|
|
382
|
-
fallback
|
|
383
|
-
}) {
|
|
384
|
-
const visitedPagesRef = (0, import_react.useRef)([]);
|
|
385
|
-
(0, import_react.useEffect)(() => {
|
|
386
|
-
if (enableBreadcrumbs) {
|
|
387
|
-
initBreadcrumbs(maxBreadcrumbs2);
|
|
388
|
-
}
|
|
389
|
-
}, [enableBreadcrumbs, maxBreadcrumbs2]);
|
|
390
|
-
(0, import_react.useEffect)(() => {
|
|
391
|
-
try {
|
|
392
|
-
if (typeof window === "undefined") return;
|
|
393
|
-
const trackPage = () => {
|
|
394
|
-
try {
|
|
395
|
-
const sanitized = sanitizeUrl(window.location.href);
|
|
396
|
-
const pages = visitedPagesRef.current;
|
|
397
|
-
if (pages[pages.length - 1] !== sanitized) {
|
|
398
|
-
pages.push(sanitized);
|
|
399
|
-
if (pages.length > 20) {
|
|
400
|
-
pages.splice(0, pages.length - 20);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
} catch (e) {
|
|
404
|
-
}
|
|
405
|
-
};
|
|
406
|
-
trackPage();
|
|
407
|
-
const handlePopState = () => trackPage();
|
|
408
|
-
window.addEventListener("popstate", handlePopState);
|
|
409
|
-
const origPushState = history.pushState.bind(history);
|
|
410
|
-
const origReplaceState = history.replaceState.bind(history);
|
|
411
|
-
history.pushState = function(...args) {
|
|
412
|
-
origPushState(...args);
|
|
413
|
-
trackPage();
|
|
414
|
-
};
|
|
415
|
-
history.replaceState = function(...args) {
|
|
416
|
-
origReplaceState(...args);
|
|
417
|
-
trackPage();
|
|
418
|
-
};
|
|
419
|
-
return () => {
|
|
420
|
-
window.removeEventListener("popstate", handlePopState);
|
|
421
|
-
history.pushState = origPushState;
|
|
422
|
-
history.replaceState = origReplaceState;
|
|
423
|
-
};
|
|
424
|
-
} catch (e) {
|
|
425
|
-
}
|
|
426
|
-
}, []);
|
|
427
|
-
(0, import_react.useEffect)(() => {
|
|
428
|
-
try {
|
|
429
|
-
if (typeof window === "undefined") return;
|
|
430
|
-
if (process.env.NODE_ENV === "development") return;
|
|
431
|
-
const handleError = (event) => {
|
|
432
|
-
var _a, _b, _c, _d, _e;
|
|
433
|
-
try {
|
|
434
|
-
const context = captureContext(visitedPagesRef.current);
|
|
435
|
-
const payload = {
|
|
436
|
-
token,
|
|
437
|
-
source: "SDK_AUTO",
|
|
438
|
-
type: "BUG",
|
|
439
|
-
errorMessage: event.message,
|
|
440
|
-
errorStack: (_a = event.error) == null ? void 0 : _a.stack,
|
|
441
|
-
pageUrl: context.url,
|
|
442
|
-
userAgent: context.userAgent,
|
|
443
|
-
breadcrumbs: context.breadcrumbs,
|
|
444
|
-
deviceInfo: (_b = context.deviceInfo) != null ? _b : void 0,
|
|
445
|
-
metadata: {
|
|
446
|
-
timestamp: context.timestamp,
|
|
447
|
-
visitedPages: JSON.stringify(context.visitedPages),
|
|
448
|
-
filename: (_c = event.filename) != null ? _c : "",
|
|
449
|
-
lineno: String((_d = event.lineno) != null ? _d : ""),
|
|
450
|
-
colno: String((_e = event.colno) != null ? _e : ""),
|
|
451
|
-
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
452
|
-
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
453
|
-
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {}
|
|
454
|
-
}
|
|
455
|
-
};
|
|
456
|
-
sendReport(payload, baseUrl).then((result) => {
|
|
457
|
-
if (result && onReportSent) onReportSent(result);
|
|
458
|
-
});
|
|
459
|
-
if (onError && event.error) onError(event.error);
|
|
460
|
-
} catch (e) {
|
|
461
|
-
}
|
|
462
|
-
};
|
|
463
|
-
const handleRejection = (event) => {
|
|
464
|
-
var _a;
|
|
465
|
-
try {
|
|
466
|
-
const context = captureContext(visitedPagesRef.current);
|
|
467
|
-
const reason = event.reason;
|
|
468
|
-
const payload = {
|
|
469
|
-
token,
|
|
470
|
-
source: "SDK_AUTO",
|
|
471
|
-
type: "BUG",
|
|
472
|
-
errorMessage: reason instanceof Error ? reason.message : String(reason),
|
|
473
|
-
errorStack: reason instanceof Error ? reason.stack : void 0,
|
|
474
|
-
pageUrl: context.url,
|
|
475
|
-
userAgent: context.userAgent,
|
|
476
|
-
breadcrumbs: context.breadcrumbs,
|
|
477
|
-
deviceInfo: (_a = context.deviceInfo) != null ? _a : void 0,
|
|
478
|
-
metadata: {
|
|
479
|
-
timestamp: context.timestamp,
|
|
480
|
-
visitedPages: JSON.stringify(context.visitedPages),
|
|
481
|
-
type: "unhandledrejection",
|
|
482
|
-
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
483
|
-
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
484
|
-
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {}
|
|
485
|
-
}
|
|
486
|
-
};
|
|
487
|
-
sendReport(payload, baseUrl).then((result) => {
|
|
488
|
-
if (result && onReportSent) onReportSent(result);
|
|
489
|
-
});
|
|
490
|
-
if (onError && reason instanceof Error) onError(reason);
|
|
491
|
-
} catch (e) {
|
|
492
|
-
}
|
|
493
|
-
};
|
|
494
|
-
window.addEventListener("error", handleError);
|
|
495
|
-
window.addEventListener("unhandledrejection", handleRejection);
|
|
496
|
-
return () => {
|
|
497
|
-
window.removeEventListener("error", handleError);
|
|
498
|
-
window.removeEventListener("unhandledrejection", handleRejection);
|
|
499
|
-
};
|
|
500
|
-
} catch (e) {
|
|
501
|
-
}
|
|
502
|
-
}, [token, baseUrl, onError, onReportSent]);
|
|
503
|
-
const report = (0, import_react.useCallback)(
|
|
504
|
-
async (type, description, metadata) => {
|
|
505
|
-
var _a;
|
|
506
|
-
try {
|
|
507
|
-
const context = captureContext(visitedPagesRef.current);
|
|
508
|
-
const payload = {
|
|
509
|
-
token,
|
|
510
|
-
source: "SDK_USER_REPORT",
|
|
511
|
-
type,
|
|
512
|
-
description,
|
|
513
|
-
pageUrl: context.url,
|
|
514
|
-
userAgent: context.userAgent,
|
|
515
|
-
breadcrumbs: context.breadcrumbs,
|
|
516
|
-
deviceInfo: (_a = context.deviceInfo) != null ? _a : void 0,
|
|
517
|
-
metadata: {
|
|
518
|
-
timestamp: context.timestamp,
|
|
519
|
-
visitedPages: JSON.stringify(context.visitedPages),
|
|
520
|
-
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
521
|
-
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
522
|
-
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
|
|
523
|
-
...(session == null ? void 0 : session.phone) ? { sessionUserPhone: String(session.phone) } : {},
|
|
524
|
-
...metadata
|
|
525
|
-
}
|
|
526
|
-
};
|
|
527
|
-
const result = await sendReport(payload, baseUrl);
|
|
528
|
-
if (result && onReportSent) onReportSent(result);
|
|
529
|
-
return result;
|
|
530
|
-
} catch (e) {
|
|
531
|
-
return null;
|
|
532
|
-
}
|
|
533
|
-
},
|
|
534
|
-
[token, baseUrl, onReportSent, session]
|
|
535
|
-
);
|
|
536
|
-
const reportBug = (0, import_react.useCallback)(
|
|
537
|
-
(description, metadata) => report("BUG", description, metadata),
|
|
538
|
-
[report]
|
|
539
|
-
);
|
|
540
|
-
const addBreadcrumb2 = (0, import_react.useCallback)(
|
|
541
|
-
(message, data) => {
|
|
542
|
-
addBreadcrumb("custom", message, data);
|
|
543
|
-
},
|
|
544
|
-
[]
|
|
545
|
-
);
|
|
546
|
-
const openReportDialog = (0, import_react.useCallback)((options) => {
|
|
547
|
-
if (typeof window !== "undefined") {
|
|
548
|
-
window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
|
|
549
|
-
}
|
|
550
|
-
}, []);
|
|
551
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
552
|
-
GlitchgrabContext.Provider,
|
|
553
|
-
{
|
|
554
|
-
value: {
|
|
555
|
-
token,
|
|
556
|
-
baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
|
|
557
|
-
reportBug,
|
|
558
|
-
report,
|
|
559
|
-
addBreadcrumb: addBreadcrumb2,
|
|
560
|
-
openReportDialog
|
|
561
|
-
},
|
|
562
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
563
|
-
GlitchgrabErrorBoundary,
|
|
564
|
-
{
|
|
565
|
-
token,
|
|
566
|
-
baseUrl,
|
|
567
|
-
onError,
|
|
568
|
-
fallback,
|
|
569
|
-
visitedPages: visitedPagesRef.current,
|
|
570
|
-
children
|
|
571
|
-
}
|
|
572
|
-
)
|
|
573
|
-
}
|
|
574
|
-
);
|
|
575
|
-
}
|
|
576
|
-
function GlitchgrabProvider(props) {
|
|
577
|
-
if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: props.children });
|
|
578
|
-
const resolvedProps = {
|
|
579
|
-
...props,
|
|
580
|
-
baseUrl: props.baseUrl || DEFAULT_BASE_URL2
|
|
581
|
-
};
|
|
582
|
-
try {
|
|
583
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
|
|
584
|
-
} catch (e) {
|
|
585
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: props.children });
|
|
586
|
-
}
|
|
587
|
-
}
|
|
588
|
-
|
|
589
|
-
// src/report-button.tsx
|
|
590
|
-
var import_react2 = require("react");
|
|
362
|
+
// src/report-dialog.tsx
|
|
363
|
+
var import_react = require("react");
|
|
591
364
|
var import_react_dom = require("react-dom");
|
|
592
|
-
var
|
|
593
|
-
function useGlitchgrabSafe() {
|
|
594
|
-
try {
|
|
595
|
-
return useGlitchgrab();
|
|
596
|
-
} catch (e) {
|
|
597
|
-
return null;
|
|
598
|
-
}
|
|
599
|
-
}
|
|
365
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
600
366
|
function useIsDark() {
|
|
601
367
|
if (typeof window === "undefined") return true;
|
|
602
368
|
try {
|
|
@@ -614,37 +380,32 @@ function useIsDark() {
|
|
|
614
380
|
function getTheme(dark) {
|
|
615
381
|
return dark ? { bg: "#1c1c1e", bgSecondary: "#27272a", border: "#2c2c2e", text: "#fafafa", textMuted: "#a1a1aa", accent: "#22d3ee", accentText: "#09090b", inputBg: "#27272a", inputBorder: "#3f3f46" } : { bg: "#ffffff", bgSecondary: "#f4f4f5", border: "#e4e4e7", text: "#18181b", textMuted: "#71717a", accent: "#0891b2", accentText: "#ffffff", inputBg: "#fafafa", inputBorder: "#d4d4d8" };
|
|
616
382
|
}
|
|
617
|
-
function
|
|
618
|
-
|
|
619
|
-
label = "Report Bug",
|
|
620
|
-
className,
|
|
621
|
-
variant = "classic",
|
|
622
|
-
showSeverity = true,
|
|
383
|
+
function ReportDialog({
|
|
384
|
+
report,
|
|
623
385
|
types,
|
|
624
|
-
|
|
386
|
+
showSeverity = true
|
|
625
387
|
}) {
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
const [
|
|
631
|
-
const [
|
|
632
|
-
const [
|
|
633
|
-
const [
|
|
634
|
-
const
|
|
635
|
-
const
|
|
636
|
-
const
|
|
637
|
-
const
|
|
638
|
-
const [
|
|
639
|
-
const [
|
|
388
|
+
const [mounted, setMounted] = (0, import_react.useState)(false);
|
|
389
|
+
(0, import_react.useEffect)(() => {
|
|
390
|
+
setMounted(true);
|
|
391
|
+
}, []);
|
|
392
|
+
const [isOpen, setIsOpen] = (0, import_react.useState)(false);
|
|
393
|
+
const [description, setDescription] = (0, import_react.useState)("");
|
|
394
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react.useState)(false);
|
|
395
|
+
const [submitted, setSubmitted] = (0, import_react.useState)(false);
|
|
396
|
+
const [screenshot, setScreenshot] = (0, import_react.useState)(null);
|
|
397
|
+
const [previewOpen, setPreviewOpen] = (0, import_react.useState)(false);
|
|
398
|
+
const fileInputRef = (0, import_react.useRef)(null);
|
|
399
|
+
const modalRef = (0, import_react.useRef)(null);
|
|
400
|
+
const [step, setStep] = (0, import_react.useState)(1);
|
|
401
|
+
const [reportType, setReportType] = (0, import_react.useState)("BUG");
|
|
402
|
+
const [severity, setSeverity] = (0, import_react.useState)("medium");
|
|
640
403
|
const availableTypes = types != null ? types : ["BUG", "FEATURE_REQUEST", "QUESTION", "OTHER"];
|
|
641
|
-
if (!glitchgrab) return null;
|
|
642
|
-
const { reportBug, report } = glitchgrab;
|
|
643
404
|
const isDark = useIsDark();
|
|
644
405
|
const t = getTheme(isDark);
|
|
645
406
|
const handleFileUpload = (e) => {
|
|
646
|
-
var
|
|
647
|
-
const file = (
|
|
407
|
+
var _a;
|
|
408
|
+
const file = (_a = e.target.files) == null ? void 0 : _a[0];
|
|
648
409
|
if (!file) return;
|
|
649
410
|
const reader = new FileReader();
|
|
650
411
|
reader.onload = () => {
|
|
@@ -672,9 +433,8 @@ function ReportButton({
|
|
|
672
433
|
setIsOpen(true);
|
|
673
434
|
};
|
|
674
435
|
const handleOpen = async () => {
|
|
675
|
-
setCapturing(true);
|
|
676
436
|
setSubmitted(false);
|
|
677
|
-
if (
|
|
437
|
+
if (availableTypes.length === 1) {
|
|
678
438
|
setReportType(availableTypes[0]);
|
|
679
439
|
setStep(2);
|
|
680
440
|
}
|
|
@@ -689,24 +449,23 @@ function ReportButton({
|
|
|
689
449
|
setScreenshot(canvas.toDataURL("image/jpeg", 0.6));
|
|
690
450
|
} catch (e) {
|
|
691
451
|
}
|
|
692
|
-
setCapturing(false);
|
|
693
452
|
setIsOpen(true);
|
|
694
453
|
};
|
|
695
|
-
(0,
|
|
454
|
+
(0, import_react.useEffect)(() => {
|
|
696
455
|
const handler = (e) => {
|
|
697
456
|
if (isOpen) return;
|
|
698
457
|
const detail = e.detail;
|
|
699
458
|
if (detail == null ? void 0 : detail.description) setDescription(detail.description);
|
|
700
459
|
if (detail == null ? void 0 : detail.type) {
|
|
701
460
|
setReportType(detail.type);
|
|
702
|
-
|
|
461
|
+
setStep(2);
|
|
703
462
|
}
|
|
704
463
|
handleOpen();
|
|
705
464
|
};
|
|
706
465
|
window.addEventListener("glitchgrab:open-report", handler);
|
|
707
466
|
return () => window.removeEventListener("glitchgrab:open-report", handler);
|
|
708
|
-
}, [isOpen, handleOpen
|
|
709
|
-
(0,
|
|
467
|
+
}, [isOpen, handleOpen]);
|
|
468
|
+
(0, import_react.useEffect)(() => {
|
|
710
469
|
if (!isOpen) return;
|
|
711
470
|
const handleEsc = (e) => {
|
|
712
471
|
if (e.key === "Escape") {
|
|
@@ -729,10 +488,10 @@ function ReportButton({
|
|
|
729
488
|
setIsSubmitting(true);
|
|
730
489
|
const metadata = {};
|
|
731
490
|
if (screenshot) metadata.screenshot = screenshot;
|
|
732
|
-
if (
|
|
491
|
+
if (showSeverity && reportType === "BUG") {
|
|
733
492
|
metadata.severity = severity;
|
|
734
493
|
}
|
|
735
|
-
const result =
|
|
494
|
+
const result = await report(reportType, description.trim(), Object.keys(metadata).length > 0 ? metadata : void 0);
|
|
736
495
|
if (result) {
|
|
737
496
|
setSubmitted(true);
|
|
738
497
|
setDescription("");
|
|
@@ -747,27 +506,10 @@ function ReportButton({
|
|
|
747
506
|
setIsSubmitting(false);
|
|
748
507
|
}
|
|
749
508
|
};
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
...isTop ? { top: "64px" } : { bottom: "64px" }
|
|
755
|
-
};
|
|
756
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
757
|
-
children ? children({ onClick: handleOpen, capturing }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
758
|
-
DefaultTrigger,
|
|
759
|
-
{
|
|
760
|
-
onClick: handleOpen,
|
|
761
|
-
capturing,
|
|
762
|
-
label,
|
|
763
|
-
className,
|
|
764
|
-
position,
|
|
765
|
-
isLeft,
|
|
766
|
-
isTop
|
|
767
|
-
}
|
|
768
|
-
),
|
|
769
|
-
isOpen && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
|
|
770
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
509
|
+
if (!mounted) return null;
|
|
510
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
511
|
+
isOpen && (0, import_react_dom.createPortal)(
|
|
512
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
771
513
|
"div",
|
|
772
514
|
{
|
|
773
515
|
style: {
|
|
@@ -783,14 +525,13 @@ function ReportButton({
|
|
|
783
525
|
onClick: () => {
|
|
784
526
|
if (!previewOpen) handleClose();
|
|
785
527
|
},
|
|
786
|
-
children: /* @__PURE__ */ (0,
|
|
528
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
787
529
|
"div",
|
|
788
530
|
{
|
|
789
531
|
ref: modalRef,
|
|
790
532
|
onClick: (e) => e.stopPropagation(),
|
|
791
533
|
style: {
|
|
792
|
-
position:
|
|
793
|
-
...modalPositionStyles,
|
|
534
|
+
position: "relative",
|
|
794
535
|
zIndex: 2147483647,
|
|
795
536
|
width: "340px",
|
|
796
537
|
maxWidth: "calc(100% - 32px)",
|
|
@@ -803,7 +544,7 @@ function ReportButton({
|
|
|
803
544
|
isolation: "isolate"
|
|
804
545
|
},
|
|
805
546
|
children: [
|
|
806
|
-
/* @__PURE__ */ (0,
|
|
547
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
807
548
|
"div",
|
|
808
549
|
{
|
|
809
550
|
style: {
|
|
@@ -811,7 +552,7 @@ function ReportButton({
|
|
|
811
552
|
borderBottom: `1px solid ${t.border}`
|
|
812
553
|
},
|
|
813
554
|
children: [
|
|
814
|
-
/* @__PURE__ */ (0,
|
|
555
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
815
556
|
"div",
|
|
816
557
|
{
|
|
817
558
|
style: {
|
|
@@ -820,8 +561,8 @@ function ReportButton({
|
|
|
820
561
|
alignItems: "center"
|
|
821
562
|
},
|
|
822
563
|
children: [
|
|
823
|
-
/* @__PURE__ */ (0,
|
|
824
|
-
|
|
564
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
565
|
+
step > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
825
566
|
"button",
|
|
826
567
|
{
|
|
827
568
|
type: "button",
|
|
@@ -835,10 +576,10 @@ function ReportButton({
|
|
|
835
576
|
alignItems: "center"
|
|
836
577
|
},
|
|
837
578
|
"aria-label": "Back",
|
|
838
|
-
children: /* @__PURE__ */ (0,
|
|
579
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M10 3L5 8L10 13", stroke: t.textMuted, strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
839
580
|
}
|
|
840
581
|
),
|
|
841
|
-
/* @__PURE__ */ (0,
|
|
582
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
842
583
|
"span",
|
|
843
584
|
{
|
|
844
585
|
style: {
|
|
@@ -846,11 +587,11 @@ function ReportButton({
|
|
|
846
587
|
fontWeight: 600,
|
|
847
588
|
color: t.text
|
|
848
589
|
},
|
|
849
|
-
children:
|
|
590
|
+
children: step === 1 ? "What's on your mind?" : step === 2 ? "Tell us more" : "Review & Send"
|
|
850
591
|
}
|
|
851
592
|
)
|
|
852
593
|
] }),
|
|
853
|
-
/* @__PURE__ */ (0,
|
|
594
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
854
595
|
"button",
|
|
855
596
|
{
|
|
856
597
|
type: "button",
|
|
@@ -865,21 +606,21 @@ function ReportButton({
|
|
|
865
606
|
justifyContent: "center"
|
|
866
607
|
},
|
|
867
608
|
"aria-label": "Close",
|
|
868
|
-
children: /* @__PURE__ */ (0,
|
|
609
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", style: { display: "block" }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M4 4L12 12M12 4L4 12", stroke: t.textMuted, strokeWidth: "2", strokeLinecap: "round" }) })
|
|
869
610
|
}
|
|
870
611
|
)
|
|
871
612
|
]
|
|
872
613
|
}
|
|
873
614
|
),
|
|
874
|
-
|
|
875
|
-
/* @__PURE__ */ (0,
|
|
615
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", alignItems: "center", justifyContent: "center", gap: "0", marginTop: "12px" }, children: [1, 2, 3].map((s, i) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center" }, children: [
|
|
616
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
876
617
|
width: "8px",
|
|
877
618
|
height: "8px",
|
|
878
619
|
borderRadius: "50%",
|
|
879
620
|
backgroundColor: s <= step ? t.accent : t.inputBorder,
|
|
880
621
|
transition: "background-color 0.2s ease"
|
|
881
622
|
} }),
|
|
882
|
-
i < 2 && /* @__PURE__ */ (0,
|
|
623
|
+
i < 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
883
624
|
width: "40px",
|
|
884
625
|
height: "2px",
|
|
885
626
|
backgroundColor: s < step ? t.accent : t.inputBorder,
|
|
@@ -889,7 +630,7 @@ function ReportButton({
|
|
|
889
630
|
]
|
|
890
631
|
}
|
|
891
632
|
),
|
|
892
|
-
/* @__PURE__ */ (0,
|
|
633
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "16px" }, children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
893
634
|
"div",
|
|
894
635
|
{
|
|
895
636
|
style: {
|
|
@@ -899,283 +640,172 @@ function ReportButton({
|
|
|
899
640
|
fontSize: "14px",
|
|
900
641
|
fontWeight: 500
|
|
901
642
|
},
|
|
902
|
-
children:
|
|
643
|
+
children: [
|
|
644
|
+
getTypeLabel(reportType),
|
|
645
|
+
" sent. Thank you!"
|
|
646
|
+
]
|
|
903
647
|
}
|
|
904
|
-
) :
|
|
905
|
-
/*
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
"button",
|
|
909
|
-
{
|
|
910
|
-
type
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
648
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
649
|
+
step === 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: "8px" }, children: availableTypes.map((type) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
650
|
+
"button",
|
|
651
|
+
{
|
|
652
|
+
type: "button",
|
|
653
|
+
onClick: () => {
|
|
654
|
+
setReportType(type);
|
|
655
|
+
setStep(2);
|
|
656
|
+
},
|
|
657
|
+
style: {
|
|
658
|
+
display: "flex",
|
|
659
|
+
flexDirection: "column",
|
|
660
|
+
alignItems: "center",
|
|
661
|
+
gap: "8px",
|
|
662
|
+
padding: "16px 8px",
|
|
663
|
+
borderRadius: "8px",
|
|
664
|
+
border: `1px solid ${t.inputBorder}`,
|
|
665
|
+
background: t.inputBg,
|
|
666
|
+
cursor: "pointer",
|
|
667
|
+
color: t.text,
|
|
668
|
+
fontFamily: "inherit",
|
|
669
|
+
transition: "border-color 0.15s ease"
|
|
670
|
+
},
|
|
671
|
+
onMouseEnter: (e) => {
|
|
672
|
+
e.currentTarget.style.borderColor = t.accent;
|
|
673
|
+
},
|
|
674
|
+
onMouseLeave: (e) => {
|
|
675
|
+
e.currentTarget.style.borderColor = t.inputBorder;
|
|
676
|
+
},
|
|
677
|
+
children: [
|
|
678
|
+
getTypeIcon(type, t.accent),
|
|
679
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
|
|
680
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "11px", color: t.textMuted, lineHeight: "1.3" }, children: getTypeSubtitle(type) })
|
|
681
|
+
]
|
|
682
|
+
},
|
|
683
|
+
type
|
|
684
|
+
)) }),
|
|
685
|
+
step === 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
686
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
687
|
+
"textarea",
|
|
688
|
+
{
|
|
689
|
+
value: description,
|
|
690
|
+
onChange: (e) => setDescription(e.target.value),
|
|
691
|
+
placeholder: getPlaceholder(reportType),
|
|
692
|
+
style: {
|
|
693
|
+
width: "100%",
|
|
694
|
+
minHeight: "100px",
|
|
695
|
+
padding: "10px 12px",
|
|
696
|
+
borderRadius: "8px",
|
|
697
|
+
border: `1px solid ${t.inputBorder}`,
|
|
698
|
+
fontSize: "14px",
|
|
699
|
+
fontFamily: "inherit",
|
|
700
|
+
resize: "vertical",
|
|
701
|
+
outline: "none",
|
|
702
|
+
boxSizing: "border-box",
|
|
703
|
+
color: t.text,
|
|
704
|
+
backgroundColor: t.inputBg
|
|
928
705
|
},
|
|
929
|
-
|
|
930
|
-
e.
|
|
706
|
+
onFocus: (e) => {
|
|
707
|
+
e.target.style.borderColor = t.accent;
|
|
931
708
|
},
|
|
932
|
-
|
|
933
|
-
e.
|
|
709
|
+
onBlur: (e) => {
|
|
710
|
+
e.target.style.borderColor = t.inputBorder;
|
|
934
711
|
},
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
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)(
|
|
712
|
+
autoFocus: true
|
|
713
|
+
}
|
|
714
|
+
),
|
|
715
|
+
showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "12px", color: t.textMuted, marginBottom: "6px", display: "block" }, children: "Severity" }),
|
|
717
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1000
718
|
"button",
|
|
1001
719
|
{
|
|
1002
720
|
type: "button",
|
|
1003
|
-
onClick: () =>
|
|
1004
|
-
disabled: !description.trim(),
|
|
721
|
+
onClick: () => setSeverity(s),
|
|
1005
722
|
style: {
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
fontSize: "14px",
|
|
723
|
+
flex: 1,
|
|
724
|
+
padding: "6px 0",
|
|
725
|
+
borderRadius: "6px",
|
|
726
|
+
border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,
|
|
727
|
+
background: severity === s ? t.accent : "transparent",
|
|
728
|
+
color: severity === s ? t.accentText : t.text,
|
|
729
|
+
fontSize: "12px",
|
|
1014
730
|
fontWeight: 600,
|
|
1015
|
-
cursor:
|
|
731
|
+
cursor: "pointer",
|
|
1016
732
|
fontFamily: "inherit",
|
|
1017
|
-
|
|
733
|
+
textTransform: "capitalize",
|
|
734
|
+
transition: "all 0.15s ease"
|
|
1018
735
|
},
|
|
1019
|
-
children:
|
|
1020
|
-
}
|
|
1021
|
-
|
|
736
|
+
children: s
|
|
737
|
+
},
|
|
738
|
+
s
|
|
739
|
+
)) })
|
|
1022
740
|
] }),
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
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",
|
|
741
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
742
|
+
"button",
|
|
743
|
+
{
|
|
744
|
+
type: "button",
|
|
745
|
+
onClick: () => setStep(3),
|
|
746
|
+
disabled: !description.trim(),
|
|
747
|
+
style: {
|
|
748
|
+
marginTop: "12px",
|
|
749
|
+
width: "100%",
|
|
750
|
+
padding: "10px",
|
|
751
|
+
borderRadius: "8px",
|
|
752
|
+
border: "none",
|
|
753
|
+
backgroundColor: !description.trim() ? t.bgSecondary : t.accent,
|
|
754
|
+
color: !description.trim() ? t.textMuted : t.accentText,
|
|
755
|
+
fontSize: "14px",
|
|
1046
756
|
fontWeight: 600,
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
757
|
+
cursor: !description.trim() ? "not-allowed" : "pointer",
|
|
758
|
+
fontFamily: "inherit",
|
|
759
|
+
transition: "background-color 0.15s ease"
|
|
760
|
+
},
|
|
761
|
+
children: "Next"
|
|
762
|
+
}
|
|
763
|
+
)
|
|
764
|
+
] }),
|
|
765
|
+
step === 3 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
766
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap", marginBottom: "12px" }, children: [
|
|
767
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: {
|
|
768
|
+
display: "inline-flex",
|
|
769
|
+
alignItems: "center",
|
|
770
|
+
gap: "4px",
|
|
771
|
+
padding: "4px 10px",
|
|
772
|
+
borderRadius: "12px",
|
|
773
|
+
fontSize: "12px",
|
|
774
|
+
fontWeight: 600,
|
|
775
|
+
backgroundColor: t.bgSecondary,
|
|
1059
776
|
color: t.text,
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
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"
|
|
1080
|
-
}
|
|
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
|
-
)
|
|
777
|
+
border: `1px solid ${t.border}`
|
|
778
|
+
}, children: [
|
|
779
|
+
getTypeIcon(reportType, t.accent, 12),
|
|
780
|
+
getTypeLabel(reportType)
|
|
1149
781
|
] }),
|
|
1150
|
-
/* @__PURE__ */ (0,
|
|
1151
|
-
"
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
screenshot && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { marginBottom: "10px", position: "relative" }, children: [
|
|
1178
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
782
|
+
showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: {
|
|
783
|
+
display: "inline-flex",
|
|
784
|
+
alignItems: "center",
|
|
785
|
+
padding: "4px 10px",
|
|
786
|
+
borderRadius: "12px",
|
|
787
|
+
fontSize: "12px",
|
|
788
|
+
fontWeight: 600,
|
|
789
|
+
backgroundColor: severity === "high" ? "#fef2f2" : severity === "medium" ? "#fffbeb" : "#f0fdf4",
|
|
790
|
+
color: severity === "high" ? "#dc2626" : severity === "medium" ? "#d97706" : "#16a34a",
|
|
791
|
+
border: `1px solid ${severity === "high" ? "#fecaca" : severity === "medium" ? "#fde68a" : "#bbf7d0"}`,
|
|
792
|
+
textTransform: "capitalize"
|
|
793
|
+
}, children: severity })
|
|
794
|
+
] }),
|
|
795
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
796
|
+
padding: "10px 12px",
|
|
797
|
+
borderRadius: "8px",
|
|
798
|
+
border: `1px solid ${t.inputBorder}`,
|
|
799
|
+
backgroundColor: t.inputBg,
|
|
800
|
+
fontSize: "13px",
|
|
801
|
+
color: t.text,
|
|
802
|
+
marginBottom: "10px",
|
|
803
|
+
maxHeight: "80px",
|
|
804
|
+
overflow: "hidden",
|
|
805
|
+
lineHeight: "1.4"
|
|
806
|
+
}, children: description.length > 200 ? description.slice(0, 200) + "..." : description }),
|
|
807
|
+
screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: "10px", position: "relative" }, children: [
|
|
808
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1179
809
|
"img",
|
|
1180
810
|
{
|
|
1181
811
|
src: screenshot,
|
|
@@ -1185,14 +815,14 @@ function ReportButton({
|
|
|
1185
815
|
width: "100%",
|
|
1186
816
|
borderRadius: "6px",
|
|
1187
817
|
border: `1px solid ${t.border}`,
|
|
1188
|
-
maxHeight: "
|
|
818
|
+
maxHeight: "80px",
|
|
1189
819
|
objectFit: "cover",
|
|
1190
820
|
objectPosition: "top",
|
|
1191
821
|
cursor: "pointer"
|
|
1192
822
|
}
|
|
1193
823
|
}
|
|
1194
824
|
),
|
|
1195
|
-
/* @__PURE__ */ (0,
|
|
825
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1196
826
|
"button",
|
|
1197
827
|
{
|
|
1198
828
|
type: "button",
|
|
@@ -1212,153 +842,69 @@ function ReportButton({
|
|
|
1212
842
|
justifyContent: "center"
|
|
1213
843
|
},
|
|
1214
844
|
"aria-label": "Remove screenshot",
|
|
1215
|
-
children: /* @__PURE__ */ (0,
|
|
845
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M1 1L9 9M9 1L1 9", stroke: "#fff", strokeWidth: "1.5", strokeLinecap: "round" }) })
|
|
846
|
+
}
|
|
847
|
+
)
|
|
848
|
+
] }),
|
|
849
|
+
!screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", marginBottom: "10px" }, children: [
|
|
850
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
851
|
+
"button",
|
|
852
|
+
{
|
|
853
|
+
type: "button",
|
|
854
|
+
onClick: () => {
|
|
855
|
+
var _a;
|
|
856
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
857
|
+
},
|
|
858
|
+
style: {
|
|
859
|
+
flex: 1,
|
|
860
|
+
padding: "8px",
|
|
861
|
+
borderRadius: "6px",
|
|
862
|
+
border: `1px dashed ${t.inputBorder}`,
|
|
863
|
+
textAlign: "center",
|
|
864
|
+
fontSize: "11px",
|
|
865
|
+
color: t.textMuted,
|
|
866
|
+
background: "none",
|
|
867
|
+
cursor: "pointer"
|
|
868
|
+
},
|
|
869
|
+
children: "Upload screenshot"
|
|
1216
870
|
}
|
|
1217
871
|
),
|
|
1218
|
-
/* @__PURE__ */ (0,
|
|
1219
|
-
"
|
|
872
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
873
|
+
"button",
|
|
1220
874
|
{
|
|
875
|
+
type: "button",
|
|
876
|
+
onClick: retakeScreenshot,
|
|
1221
877
|
style: {
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
878
|
+
flex: 1,
|
|
879
|
+
padding: "8px",
|
|
880
|
+
borderRadius: "6px",
|
|
881
|
+
border: `1px dashed ${t.inputBorder}`,
|
|
882
|
+
textAlign: "center",
|
|
883
|
+
fontSize: "11px",
|
|
884
|
+
color: t.textMuted,
|
|
885
|
+
background: "none",
|
|
886
|
+
cursor: "pointer"
|
|
1229
887
|
},
|
|
1230
|
-
children:
|
|
1231
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1232
|
-
"span",
|
|
1233
|
-
{
|
|
1234
|
-
style: {
|
|
1235
|
-
background: "rgba(0,0,0,0.6)",
|
|
1236
|
-
color: "#fff",
|
|
1237
|
-
fontSize: "10px",
|
|
1238
|
-
padding: "2px 6px",
|
|
1239
|
-
borderRadius: "4px"
|
|
1240
|
-
},
|
|
1241
|
-
children: [
|
|
1242
|
-
"Screenshot (",
|
|
1243
|
-
Math.round(screenshot.length * 0.75 / 1024),
|
|
1244
|
-
"KB) \u2014 click to preview"
|
|
1245
|
-
]
|
|
1246
|
-
}
|
|
1247
|
-
),
|
|
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
|
-
]
|
|
888
|
+
children: "Retake screenshot"
|
|
1290
889
|
}
|
|
1291
890
|
)
|
|
1292
891
|
] }),
|
|
1293
|
-
|
|
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)(
|
|
892
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1346
893
|
"button",
|
|
1347
894
|
{
|
|
1348
895
|
type: "button",
|
|
1349
896
|
onClick: handleSubmit,
|
|
1350
|
-
disabled:
|
|
897
|
+
disabled: isSubmitting,
|
|
1351
898
|
style: {
|
|
1352
|
-
marginTop: "12px",
|
|
1353
899
|
width: "100%",
|
|
1354
900
|
padding: "10px",
|
|
1355
901
|
borderRadius: "8px",
|
|
1356
902
|
border: "none",
|
|
1357
|
-
backgroundColor:
|
|
1358
|
-
color:
|
|
903
|
+
backgroundColor: isSubmitting ? t.bgSecondary : t.accent,
|
|
904
|
+
color: isSubmitting ? t.textMuted : t.accentText,
|
|
1359
905
|
fontSize: "14px",
|
|
1360
906
|
fontWeight: 600,
|
|
1361
|
-
cursor:
|
|
907
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
1362
908
|
fontFamily: "inherit",
|
|
1363
909
|
transition: "background-color 0.15s ease"
|
|
1364
910
|
},
|
|
@@ -1366,8 +912,8 @@ function ReportButton({
|
|
|
1366
912
|
}
|
|
1367
913
|
)
|
|
1368
914
|
] })
|
|
1369
|
-
) }),
|
|
1370
|
-
/* @__PURE__ */ (0,
|
|
915
|
+
] }) }),
|
|
916
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1371
917
|
"div",
|
|
1372
918
|
{
|
|
1373
919
|
style: {
|
|
@@ -1375,7 +921,7 @@ function ReportButton({
|
|
|
1375
921
|
borderTop: `1px solid ${t.border}`,
|
|
1376
922
|
textAlign: "center"
|
|
1377
923
|
},
|
|
1378
|
-
children: /* @__PURE__ */ (0,
|
|
924
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "11px", color: t.textMuted }, children: "Powered by Glitchgrab" })
|
|
1379
925
|
}
|
|
1380
926
|
)
|
|
1381
927
|
]
|
|
@@ -1385,7 +931,7 @@ function ReportButton({
|
|
|
1385
931
|
),
|
|
1386
932
|
document.body
|
|
1387
933
|
),
|
|
1388
|
-
/* @__PURE__ */ (0,
|
|
934
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1389
935
|
"input",
|
|
1390
936
|
{
|
|
1391
937
|
ref: fileInputRef,
|
|
@@ -1395,8 +941,8 @@ function ReportButton({
|
|
|
1395
941
|
style: { display: "none" }
|
|
1396
942
|
}
|
|
1397
943
|
),
|
|
1398
|
-
previewOpen && screenshot &&
|
|
1399
|
-
/* @__PURE__ */ (0,
|
|
944
|
+
previewOpen && screenshot && (0, import_react_dom.createPortal)(
|
|
945
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1400
946
|
"div",
|
|
1401
947
|
{
|
|
1402
948
|
style: {
|
|
@@ -1417,7 +963,7 @@ function ReportButton({
|
|
|
1417
963
|
},
|
|
1418
964
|
onMouseDown: (e) => e.stopPropagation(),
|
|
1419
965
|
children: [
|
|
1420
|
-
/* @__PURE__ */ (0,
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1421
967
|
"img",
|
|
1422
968
|
{
|
|
1423
969
|
src: screenshot,
|
|
@@ -1432,7 +978,7 @@ function ReportButton({
|
|
|
1432
978
|
}
|
|
1433
979
|
}
|
|
1434
980
|
),
|
|
1435
|
-
/* @__PURE__ */ (0,
|
|
981
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1436
982
|
"span",
|
|
1437
983
|
{
|
|
1438
984
|
style: {
|
|
@@ -1490,36 +1036,290 @@ function getTypeIcon(type, color, size = 24) {
|
|
|
1490
1036
|
const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 } };
|
|
1491
1037
|
switch (type) {
|
|
1492
1038
|
case "BUG":
|
|
1493
|
-
return /* @__PURE__ */ (0,
|
|
1039
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.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
1040
|
case "FEATURE_REQUEST":
|
|
1495
|
-
return /* @__PURE__ */ (0,
|
|
1041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.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
1042
|
case "QUESTION":
|
|
1497
|
-
return /* @__PURE__ */ (0,
|
|
1498
|
-
/* @__PURE__ */ (0,
|
|
1499
|
-
/* @__PURE__ */ (0,
|
|
1043
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
|
|
1044
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
|
|
1045
|
+
/* @__PURE__ */ (0, import_jsx_runtime.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
1046
|
] });
|
|
1501
1047
|
case "OTHER":
|
|
1502
|
-
return /* @__PURE__ */ (0,
|
|
1048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.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
1049
|
}
|
|
1504
1050
|
}
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1051
|
+
|
|
1052
|
+
// src/provider.tsx
|
|
1053
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1054
|
+
var DEFAULT_BASE_URL2 = "https://www.glitchgrab.dev";
|
|
1055
|
+
var GlitchgrabContext = (0, import_react2.createContext)(null);
|
|
1056
|
+
function useGlitchgrab() {
|
|
1057
|
+
const ctx = (0, import_react2.useContext)(GlitchgrabContext);
|
|
1058
|
+
if (!ctx) {
|
|
1059
|
+
throw new Error("useGlitchgrab must be used within a GlitchgrabProvider");
|
|
1060
|
+
}
|
|
1061
|
+
return ctx;
|
|
1062
|
+
}
|
|
1063
|
+
function GlitchgrabProviderInner({
|
|
1064
|
+
token,
|
|
1065
|
+
session,
|
|
1066
|
+
baseUrl,
|
|
1067
|
+
onError,
|
|
1068
|
+
onReportSent,
|
|
1069
|
+
breadcrumbs: enableBreadcrumbs = true,
|
|
1070
|
+
maxBreadcrumbs: maxBreadcrumbs2 = 50,
|
|
1071
|
+
children,
|
|
1072
|
+
fallback,
|
|
1073
|
+
types,
|
|
1074
|
+
showSeverity
|
|
1075
|
+
}) {
|
|
1076
|
+
const visitedPagesRef = (0, import_react2.useRef)([]);
|
|
1077
|
+
(0, import_react2.useEffect)(() => {
|
|
1078
|
+
if (enableBreadcrumbs) {
|
|
1079
|
+
initBreadcrumbs(maxBreadcrumbs2);
|
|
1080
|
+
}
|
|
1081
|
+
}, [enableBreadcrumbs, maxBreadcrumbs2]);
|
|
1082
|
+
(0, import_react2.useEffect)(() => {
|
|
1083
|
+
try {
|
|
1084
|
+
if (typeof window === "undefined") return;
|
|
1085
|
+
const trackPage = () => {
|
|
1086
|
+
try {
|
|
1087
|
+
const sanitized = sanitizeUrl(window.location.href);
|
|
1088
|
+
const pages = visitedPagesRef.current;
|
|
1089
|
+
if (pages[pages.length - 1] !== sanitized) {
|
|
1090
|
+
pages.push(sanitized);
|
|
1091
|
+
if (pages.length > 20) {
|
|
1092
|
+
pages.splice(0, pages.length - 20);
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
} catch (e) {
|
|
1096
|
+
}
|
|
1097
|
+
};
|
|
1098
|
+
trackPage();
|
|
1099
|
+
const handlePopState = () => trackPage();
|
|
1100
|
+
window.addEventListener("popstate", handlePopState);
|
|
1101
|
+
const origPushState = history.pushState.bind(history);
|
|
1102
|
+
const origReplaceState = history.replaceState.bind(history);
|
|
1103
|
+
history.pushState = function(...args) {
|
|
1104
|
+
origPushState(...args);
|
|
1105
|
+
trackPage();
|
|
1106
|
+
};
|
|
1107
|
+
history.replaceState = function(...args) {
|
|
1108
|
+
origReplaceState(...args);
|
|
1109
|
+
trackPage();
|
|
1110
|
+
};
|
|
1111
|
+
return () => {
|
|
1112
|
+
window.removeEventListener("popstate", handlePopState);
|
|
1113
|
+
history.pushState = origPushState;
|
|
1114
|
+
history.replaceState = origReplaceState;
|
|
1115
|
+
};
|
|
1116
|
+
} catch (e) {
|
|
1117
|
+
}
|
|
1118
|
+
}, []);
|
|
1119
|
+
(0, import_react2.useEffect)(() => {
|
|
1120
|
+
try {
|
|
1121
|
+
if (typeof window === "undefined") return;
|
|
1122
|
+
if (process.env.NODE_ENV === "development") return;
|
|
1123
|
+
const handleError = (event) => {
|
|
1124
|
+
var _a, _b, _c, _d, _e;
|
|
1125
|
+
try {
|
|
1126
|
+
const context = captureContext(visitedPagesRef.current);
|
|
1127
|
+
const payload = {
|
|
1128
|
+
token,
|
|
1129
|
+
source: "SDK_AUTO",
|
|
1130
|
+
type: "BUG",
|
|
1131
|
+
errorMessage: event.message,
|
|
1132
|
+
errorStack: (_a = event.error) == null ? void 0 : _a.stack,
|
|
1133
|
+
pageUrl: context.url,
|
|
1134
|
+
userAgent: context.userAgent,
|
|
1135
|
+
breadcrumbs: context.breadcrumbs,
|
|
1136
|
+
deviceInfo: (_b = context.deviceInfo) != null ? _b : void 0,
|
|
1137
|
+
metadata: {
|
|
1138
|
+
timestamp: context.timestamp,
|
|
1139
|
+
visitedPages: JSON.stringify(context.visitedPages),
|
|
1140
|
+
filename: (_c = event.filename) != null ? _c : "",
|
|
1141
|
+
lineno: String((_d = event.lineno) != null ? _d : ""),
|
|
1142
|
+
colno: String((_e = event.colno) != null ? _e : ""),
|
|
1143
|
+
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
1144
|
+
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
1145
|
+
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {}
|
|
1146
|
+
}
|
|
1147
|
+
};
|
|
1148
|
+
sendReport(payload, baseUrl).then((result) => {
|
|
1149
|
+
if (result && onReportSent) onReportSent(result);
|
|
1150
|
+
});
|
|
1151
|
+
if (onError && event.error) onError(event.error);
|
|
1152
|
+
} catch (e) {
|
|
1153
|
+
}
|
|
1154
|
+
};
|
|
1155
|
+
const handleRejection = (event) => {
|
|
1156
|
+
var _a;
|
|
1157
|
+
try {
|
|
1158
|
+
const context = captureContext(visitedPagesRef.current);
|
|
1159
|
+
const reason = event.reason;
|
|
1160
|
+
const payload = {
|
|
1161
|
+
token,
|
|
1162
|
+
source: "SDK_AUTO",
|
|
1163
|
+
type: "BUG",
|
|
1164
|
+
errorMessage: reason instanceof Error ? reason.message : String(reason),
|
|
1165
|
+
errorStack: reason instanceof Error ? reason.stack : void 0,
|
|
1166
|
+
pageUrl: context.url,
|
|
1167
|
+
userAgent: context.userAgent,
|
|
1168
|
+
breadcrumbs: context.breadcrumbs,
|
|
1169
|
+
deviceInfo: (_a = context.deviceInfo) != null ? _a : void 0,
|
|
1170
|
+
metadata: {
|
|
1171
|
+
timestamp: context.timestamp,
|
|
1172
|
+
visitedPages: JSON.stringify(context.visitedPages),
|
|
1173
|
+
type: "unhandledrejection",
|
|
1174
|
+
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
1175
|
+
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
1176
|
+
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {}
|
|
1177
|
+
}
|
|
1178
|
+
};
|
|
1179
|
+
sendReport(payload, baseUrl).then((result) => {
|
|
1180
|
+
if (result && onReportSent) onReportSent(result);
|
|
1181
|
+
});
|
|
1182
|
+
if (onError && reason instanceof Error) onError(reason);
|
|
1183
|
+
} catch (e) {
|
|
1184
|
+
}
|
|
1185
|
+
};
|
|
1186
|
+
window.addEventListener("error", handleError);
|
|
1187
|
+
window.addEventListener("unhandledrejection", handleRejection);
|
|
1188
|
+
return () => {
|
|
1189
|
+
window.removeEventListener("error", handleError);
|
|
1190
|
+
window.removeEventListener("unhandledrejection", handleRejection);
|
|
1191
|
+
};
|
|
1192
|
+
} catch (e) {
|
|
1193
|
+
}
|
|
1194
|
+
}, [token, baseUrl, onError, onReportSent]);
|
|
1195
|
+
const report = (0, import_react2.useCallback)(
|
|
1196
|
+
async (type, description, metadata) => {
|
|
1197
|
+
var _a;
|
|
1198
|
+
try {
|
|
1199
|
+
const context = captureContext(visitedPagesRef.current);
|
|
1200
|
+
const payload = {
|
|
1201
|
+
token,
|
|
1202
|
+
source: "SDK_USER_REPORT",
|
|
1203
|
+
type,
|
|
1204
|
+
description,
|
|
1205
|
+
pageUrl: context.url,
|
|
1206
|
+
userAgent: context.userAgent,
|
|
1207
|
+
breadcrumbs: context.breadcrumbs,
|
|
1208
|
+
deviceInfo: (_a = context.deviceInfo) != null ? _a : void 0,
|
|
1209
|
+
metadata: {
|
|
1210
|
+
timestamp: context.timestamp,
|
|
1211
|
+
visitedPages: JSON.stringify(context.visitedPages),
|
|
1212
|
+
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
1213
|
+
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
1214
|
+
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
|
|
1215
|
+
...(session == null ? void 0 : session.phone) ? { sessionUserPhone: String(session.phone) } : {},
|
|
1216
|
+
...metadata
|
|
1217
|
+
}
|
|
1218
|
+
};
|
|
1219
|
+
const result = await sendReport(payload, baseUrl);
|
|
1220
|
+
if (result && onReportSent) onReportSent(result);
|
|
1221
|
+
return result;
|
|
1222
|
+
} catch (e) {
|
|
1223
|
+
return null;
|
|
1224
|
+
}
|
|
1225
|
+
},
|
|
1226
|
+
[token, baseUrl, onReportSent, session]
|
|
1227
|
+
);
|
|
1228
|
+
const reportBug = (0, import_react2.useCallback)(
|
|
1229
|
+
(description, metadata) => report("BUG", description, metadata),
|
|
1230
|
+
[report]
|
|
1231
|
+
);
|
|
1232
|
+
const addBreadcrumb2 = (0, import_react2.useCallback)(
|
|
1233
|
+
(message, data) => {
|
|
1234
|
+
addBreadcrumb("custom", message, data);
|
|
1235
|
+
},
|
|
1236
|
+
[]
|
|
1237
|
+
);
|
|
1238
|
+
const openReportDialog = (0, import_react2.useCallback)((options) => {
|
|
1239
|
+
if (typeof window !== "undefined") {
|
|
1240
|
+
window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
|
|
1241
|
+
}
|
|
1242
|
+
}, []);
|
|
1243
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1244
|
+
GlitchgrabContext.Provider,
|
|
1245
|
+
{
|
|
1246
|
+
value: {
|
|
1247
|
+
token,
|
|
1248
|
+
baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
|
|
1249
|
+
reportBug,
|
|
1250
|
+
report,
|
|
1251
|
+
addBreadcrumb: addBreadcrumb2,
|
|
1252
|
+
openReportDialog
|
|
1253
|
+
},
|
|
1254
|
+
children: [
|
|
1255
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1256
|
+
GlitchgrabErrorBoundary,
|
|
1257
|
+
{
|
|
1258
|
+
token,
|
|
1259
|
+
baseUrl,
|
|
1260
|
+
onError,
|
|
1261
|
+
fallback,
|
|
1262
|
+
visitedPages: visitedPagesRef.current,
|
|
1263
|
+
children
|
|
1264
|
+
}
|
|
1265
|
+
),
|
|
1266
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportDialog, { report, types, showSeverity })
|
|
1267
|
+
]
|
|
1268
|
+
}
|
|
1269
|
+
);
|
|
1270
|
+
}
|
|
1271
|
+
function GlitchgrabProvider(props) {
|
|
1272
|
+
if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
|
|
1273
|
+
const resolvedProps = {
|
|
1274
|
+
...props,
|
|
1275
|
+
baseUrl: props.baseUrl || DEFAULT_BASE_URL2
|
|
1276
|
+
};
|
|
1277
|
+
try {
|
|
1278
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
|
|
1279
|
+
} catch (e) {
|
|
1280
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
|
|
1281
|
+
}
|
|
1282
|
+
}
|
|
1283
|
+
|
|
1284
|
+
// src/report-button.tsx
|
|
1285
|
+
var import_react3 = require("react");
|
|
1286
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1287
|
+
function useGlitchgrabSafe() {
|
|
1288
|
+
try {
|
|
1289
|
+
return useGlitchgrab();
|
|
1290
|
+
} catch (e) {
|
|
1291
|
+
return null;
|
|
1292
|
+
}
|
|
1293
|
+
}
|
|
1294
|
+
function ReportButton({
|
|
1295
|
+
position = "bottom-right",
|
|
1296
|
+
label = "Report Bug",
|
|
1509
1297
|
className,
|
|
1510
|
-
|
|
1511
|
-
isLeft,
|
|
1512
|
-
isTop
|
|
1298
|
+
children
|
|
1513
1299
|
}) {
|
|
1300
|
+
var _a, _b;
|
|
1301
|
+
const [capturing, setCapturing] = (0, import_react3.useState)(false);
|
|
1302
|
+
const glitchgrab = useGlitchgrabSafe();
|
|
1303
|
+
if (!glitchgrab) return null;
|
|
1304
|
+
const handleClick = async () => {
|
|
1305
|
+
setCapturing(true);
|
|
1306
|
+
glitchgrab.openReportDialog();
|
|
1307
|
+
setCapturing(false);
|
|
1308
|
+
};
|
|
1309
|
+
if (children) {
|
|
1310
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: children({ onClick: handleClick, capturing }) });
|
|
1311
|
+
}
|
|
1312
|
+
const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
|
|
1313
|
+
const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
|
|
1514
1314
|
const positionStyles = {
|
|
1515
1315
|
...isLeft ? { left: "16px" } : { right: "16px" },
|
|
1516
1316
|
...isTop ? { top: "16px" } : { bottom: "16px" }
|
|
1517
1317
|
};
|
|
1518
|
-
return /* @__PURE__ */ (0,
|
|
1318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1519
1319
|
"button",
|
|
1520
1320
|
{
|
|
1521
1321
|
type: "button",
|
|
1522
|
-
onClick,
|
|
1322
|
+
onClick: handleClick,
|
|
1523
1323
|
disabled: capturing,
|
|
1524
1324
|
className,
|
|
1525
1325
|
style: {
|
|
@@ -1550,7 +1350,7 @@ function DefaultTrigger({
|
|
|
1550
1350
|
},
|
|
1551
1351
|
"aria-label": label,
|
|
1552
1352
|
children: [
|
|
1553
|
-
/* @__PURE__ */ (0,
|
|
1353
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1554
1354
|
"svg",
|
|
1555
1355
|
{
|
|
1556
1356
|
width: "16",
|
|
@@ -1558,7 +1358,7 @@ function DefaultTrigger({
|
|
|
1558
1358
|
viewBox: "0 0 16 16",
|
|
1559
1359
|
fill: "none",
|
|
1560
1360
|
style: { flexShrink: 0 },
|
|
1561
|
-
children: /* @__PURE__ */ (0,
|
|
1361
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1562
1362
|
"path",
|
|
1563
1363
|
{
|
|
1564
1364
|
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",
|
|
@@ -1574,18 +1374,18 @@ function DefaultTrigger({
|
|
|
1574
1374
|
}
|
|
1575
1375
|
|
|
1576
1376
|
// src/use-reports.ts
|
|
1577
|
-
var
|
|
1377
|
+
var import_react4 = require("react");
|
|
1578
1378
|
var BASE_URL = "https://www.glitchgrab.dev";
|
|
1579
1379
|
function useGlitchgrabReports({
|
|
1580
1380
|
token,
|
|
1581
1381
|
userId,
|
|
1582
1382
|
limit = 100
|
|
1583
1383
|
}) {
|
|
1584
|
-
const [reports, setReports] = (0,
|
|
1585
|
-
const [isLoading, setIsLoading] = (0,
|
|
1586
|
-
const [isFetching, setIsFetching] = (0,
|
|
1587
|
-
const [error, setError] = (0,
|
|
1588
|
-
const fetchReports = (0,
|
|
1384
|
+
const [reports, setReports] = (0, import_react4.useState)([]);
|
|
1385
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
|
|
1386
|
+
const [isFetching, setIsFetching] = (0, import_react4.useState)(false);
|
|
1387
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1388
|
+
const fetchReports = (0, import_react4.useCallback)(async () => {
|
|
1589
1389
|
var _a, _b;
|
|
1590
1390
|
if (!token || !userId) {
|
|
1591
1391
|
setIsLoading(false);
|
|
@@ -1611,7 +1411,7 @@ function useGlitchgrabReports({
|
|
|
1611
1411
|
setIsFetching(false);
|
|
1612
1412
|
}
|
|
1613
1413
|
}, [token, userId, limit]);
|
|
1614
|
-
(0,
|
|
1414
|
+
(0, import_react4.useEffect)(() => {
|
|
1615
1415
|
fetchReports();
|
|
1616
1416
|
}, [fetchReports]);
|
|
1617
1417
|
return { reports, isLoading, isFetching, error, refetch: fetchReports };
|
|
@@ -1648,9 +1448,9 @@ function useGlitchgrabActions({
|
|
|
1648
1448
|
onSuccess,
|
|
1649
1449
|
onError
|
|
1650
1450
|
}) {
|
|
1651
|
-
const [isPending, setIsPending] = (0,
|
|
1652
|
-
const [error, setError] = (0,
|
|
1653
|
-
const run = (0,
|
|
1451
|
+
const [isPending, setIsPending] = (0, import_react4.useState)(false);
|
|
1452
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1453
|
+
const run = (0, import_react4.useCallback)(
|
|
1654
1454
|
async (reportId, body) => {
|
|
1655
1455
|
setIsPending(true);
|
|
1656
1456
|
setError(null);
|