glitchgrab 1.11.0 → 1.13.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.d.mts +31 -4
- package/dist/index.d.ts +31 -4
- package/dist/index.js +723 -540
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +720 -537
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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,30 +380,28 @@ 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
|
-
|
|
620
|
-
|
|
621
|
-
children
|
|
383
|
+
function ReportDialog({
|
|
384
|
+
report,
|
|
385
|
+
types,
|
|
386
|
+
showSeverity = true
|
|
622
387
|
}) {
|
|
623
|
-
|
|
624
|
-
const [
|
|
625
|
-
const [
|
|
626
|
-
const [
|
|
627
|
-
const [
|
|
628
|
-
const [
|
|
629
|
-
const
|
|
630
|
-
const
|
|
631
|
-
const
|
|
632
|
-
const
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
const { reportBug } = glitchgrab;
|
|
388
|
+
const [isOpen, setIsOpen] = (0, import_react.useState)(false);
|
|
389
|
+
const [description, setDescription] = (0, import_react.useState)("");
|
|
390
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react.useState)(false);
|
|
391
|
+
const [submitted, setSubmitted] = (0, import_react.useState)(false);
|
|
392
|
+
const [screenshot, setScreenshot] = (0, import_react.useState)(null);
|
|
393
|
+
const [previewOpen, setPreviewOpen] = (0, import_react.useState)(false);
|
|
394
|
+
const fileInputRef = (0, import_react.useRef)(null);
|
|
395
|
+
const modalRef = (0, import_react.useRef)(null);
|
|
396
|
+
const [step, setStep] = (0, import_react.useState)(1);
|
|
397
|
+
const [reportType, setReportType] = (0, import_react.useState)("BUG");
|
|
398
|
+
const [severity, setSeverity] = (0, import_react.useState)("medium");
|
|
399
|
+
const availableTypes = types != null ? types : ["BUG", "FEATURE_REQUEST", "QUESTION", "OTHER"];
|
|
636
400
|
const isDark = useIsDark();
|
|
637
401
|
const t = getTheme(isDark);
|
|
638
402
|
const handleFileUpload = (e) => {
|
|
639
|
-
var
|
|
640
|
-
const file = (
|
|
403
|
+
var _a;
|
|
404
|
+
const file = (_a = e.target.files) == null ? void 0 : _a[0];
|
|
641
405
|
if (!file) return;
|
|
642
406
|
const reader = new FileReader();
|
|
643
407
|
reader.onload = () => {
|
|
@@ -665,8 +429,11 @@ function ReportButton({
|
|
|
665
429
|
setIsOpen(true);
|
|
666
430
|
};
|
|
667
431
|
const handleOpen = async () => {
|
|
668
|
-
setCapturing(true);
|
|
669
432
|
setSubmitted(false);
|
|
433
|
+
if (availableTypes.length === 1) {
|
|
434
|
+
setReportType(availableTypes[0]);
|
|
435
|
+
setStep(2);
|
|
436
|
+
}
|
|
670
437
|
try {
|
|
671
438
|
const { default: html2canvas } = await import("html2canvas-pro");
|
|
672
439
|
const canvas = await html2canvas(document.body, {
|
|
@@ -678,42 +445,56 @@ function ReportButton({
|
|
|
678
445
|
setScreenshot(canvas.toDataURL("image/jpeg", 0.6));
|
|
679
446
|
} catch (e) {
|
|
680
447
|
}
|
|
681
|
-
setCapturing(false);
|
|
682
448
|
setIsOpen(true);
|
|
683
449
|
};
|
|
684
|
-
(0,
|
|
450
|
+
(0, import_react.useEffect)(() => {
|
|
685
451
|
const handler = (e) => {
|
|
686
452
|
if (isOpen) return;
|
|
687
453
|
const detail = e.detail;
|
|
688
454
|
if (detail == null ? void 0 : detail.description) setDescription(detail.description);
|
|
455
|
+
if (detail == null ? void 0 : detail.type) {
|
|
456
|
+
setReportType(detail.type);
|
|
457
|
+
setStep(2);
|
|
458
|
+
}
|
|
689
459
|
handleOpen();
|
|
690
460
|
};
|
|
691
461
|
window.addEventListener("glitchgrab:open-report", handler);
|
|
692
462
|
return () => window.removeEventListener("glitchgrab:open-report", handler);
|
|
693
463
|
}, [isOpen, handleOpen]);
|
|
694
|
-
(0,
|
|
464
|
+
(0, import_react.useEffect)(() => {
|
|
695
465
|
if (!isOpen) return;
|
|
696
466
|
const handleEsc = (e) => {
|
|
697
467
|
if (e.key === "Escape") {
|
|
698
468
|
if (previewOpen) setPreviewOpen(false);
|
|
699
|
-
else
|
|
469
|
+
else handleClose();
|
|
700
470
|
}
|
|
701
471
|
};
|
|
702
472
|
document.addEventListener("keydown", handleEsc);
|
|
703
473
|
return () => document.removeEventListener("keydown", handleEsc);
|
|
704
474
|
}, [isOpen, previewOpen]);
|
|
475
|
+
const handleClose = () => {
|
|
476
|
+
setIsOpen(false);
|
|
477
|
+
setStep(1);
|
|
478
|
+
setReportType("BUG");
|
|
479
|
+
setSeverity("medium");
|
|
480
|
+
};
|
|
705
481
|
const handleSubmit = async () => {
|
|
706
482
|
try {
|
|
707
483
|
if (!description.trim() || isSubmitting) return;
|
|
708
484
|
setIsSubmitting(true);
|
|
709
|
-
const
|
|
485
|
+
const metadata = {};
|
|
486
|
+
if (screenshot) metadata.screenshot = screenshot;
|
|
487
|
+
if (showSeverity && reportType === "BUG") {
|
|
488
|
+
metadata.severity = severity;
|
|
489
|
+
}
|
|
490
|
+
const result = await report(reportType, description.trim(), Object.keys(metadata).length > 0 ? metadata : void 0);
|
|
710
491
|
if (result) {
|
|
711
492
|
setSubmitted(true);
|
|
712
493
|
setDescription("");
|
|
713
494
|
setScreenshot(null);
|
|
714
495
|
setTimeout(() => {
|
|
715
496
|
setSubmitted(false);
|
|
716
|
-
|
|
497
|
+
handleClose();
|
|
717
498
|
}, 2e3);
|
|
718
499
|
}
|
|
719
500
|
setIsSubmitting(false);
|
|
@@ -721,27 +502,10 @@ function ReportButton({
|
|
|
721
502
|
setIsSubmitting(false);
|
|
722
503
|
}
|
|
723
504
|
};
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
...isTop ? { top: "64px" } : { bottom: "64px" }
|
|
729
|
-
};
|
|
730
|
-
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
731
|
-
children ? children({ onClick: handleOpen, capturing }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
732
|
-
DefaultTrigger,
|
|
733
|
-
{
|
|
734
|
-
onClick: handleOpen,
|
|
735
|
-
capturing,
|
|
736
|
-
label,
|
|
737
|
-
className,
|
|
738
|
-
position,
|
|
739
|
-
isLeft,
|
|
740
|
-
isTop
|
|
741
|
-
}
|
|
742
|
-
),
|
|
743
|
-
isOpen && typeof document !== "undefined" && (0, import_react_dom.createPortal)(
|
|
744
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
505
|
+
if (typeof document === "undefined") return null;
|
|
506
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
507
|
+
isOpen && (0, import_react_dom.createPortal)(
|
|
508
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
745
509
|
"div",
|
|
746
510
|
{
|
|
747
511
|
style: {
|
|
@@ -755,16 +519,15 @@ function ReportButton({
|
|
|
755
519
|
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
|
|
756
520
|
},
|
|
757
521
|
onClick: () => {
|
|
758
|
-
if (!previewOpen)
|
|
522
|
+
if (!previewOpen) handleClose();
|
|
759
523
|
},
|
|
760
|
-
children: /* @__PURE__ */ (0,
|
|
524
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
761
525
|
"div",
|
|
762
526
|
{
|
|
763
527
|
ref: modalRef,
|
|
764
528
|
onClick: (e) => e.stopPropagation(),
|
|
765
529
|
style: {
|
|
766
|
-
position:
|
|
767
|
-
...modalPositionStyles,
|
|
530
|
+
position: "relative",
|
|
768
531
|
zIndex: 2147483647,
|
|
769
532
|
width: "340px",
|
|
770
533
|
maxWidth: "calc(100% - 32px)",
|
|
@@ -777,58 +540,94 @@ function ReportButton({
|
|
|
777
540
|
isolation: "isolate"
|
|
778
541
|
},
|
|
779
542
|
children: [
|
|
780
|
-
/* @__PURE__ */ (0,
|
|
543
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
781
544
|
"div",
|
|
782
545
|
{
|
|
783
546
|
style: {
|
|
784
547
|
padding: "16px 16px 12px",
|
|
785
548
|
borderBottom: `1px solid ${t.border}`
|
|
786
549
|
},
|
|
787
|
-
children:
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
"
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
550
|
+
children: [
|
|
551
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
552
|
+
"div",
|
|
553
|
+
{
|
|
554
|
+
style: {
|
|
555
|
+
display: "flex",
|
|
556
|
+
justifyContent: "space-between",
|
|
557
|
+
alignItems: "center"
|
|
558
|
+
},
|
|
559
|
+
children: [
|
|
560
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px" }, children: [
|
|
561
|
+
step > 1 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
562
|
+
"button",
|
|
563
|
+
{
|
|
564
|
+
type: "button",
|
|
565
|
+
onClick: () => setStep((s) => s - 1),
|
|
566
|
+
style: {
|
|
567
|
+
background: "none",
|
|
568
|
+
border: "none",
|
|
569
|
+
cursor: "pointer",
|
|
570
|
+
padding: "2px",
|
|
571
|
+
display: "flex",
|
|
572
|
+
alignItems: "center"
|
|
573
|
+
},
|
|
574
|
+
"aria-label": "Back",
|
|
575
|
+
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" }) })
|
|
576
|
+
}
|
|
577
|
+
),
|
|
578
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
579
|
+
"span",
|
|
580
|
+
{
|
|
581
|
+
style: {
|
|
582
|
+
fontSize: "15px",
|
|
583
|
+
fontWeight: 600,
|
|
584
|
+
color: t.text
|
|
585
|
+
},
|
|
586
|
+
children: step === 1 ? "What's on your mind?" : step === 2 ? "Tell us more" : "Review & Send"
|
|
587
|
+
}
|
|
588
|
+
)
|
|
589
|
+
] }),
|
|
590
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
591
|
+
"button",
|
|
592
|
+
{
|
|
593
|
+
type: "button",
|
|
594
|
+
onClick: handleClose,
|
|
595
|
+
style: {
|
|
596
|
+
background: "none",
|
|
597
|
+
border: "none",
|
|
598
|
+
cursor: "pointer",
|
|
599
|
+
padding: "4px",
|
|
600
|
+
display: "flex",
|
|
601
|
+
alignItems: "center",
|
|
602
|
+
justifyContent: "center"
|
|
603
|
+
},
|
|
604
|
+
"aria-label": "Close",
|
|
605
|
+
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" }) })
|
|
606
|
+
}
|
|
607
|
+
)
|
|
608
|
+
]
|
|
609
|
+
}
|
|
610
|
+
),
|
|
611
|
+
/* @__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: [
|
|
612
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
613
|
+
width: "8px",
|
|
614
|
+
height: "8px",
|
|
615
|
+
borderRadius: "50%",
|
|
616
|
+
backgroundColor: s <= step ? t.accent : t.inputBorder,
|
|
617
|
+
transition: "background-color 0.2s ease"
|
|
618
|
+
} }),
|
|
619
|
+
i < 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
620
|
+
width: "40px",
|
|
621
|
+
height: "2px",
|
|
622
|
+
backgroundColor: s < step ? t.accent : t.inputBorder,
|
|
623
|
+
transition: "background-color 0.2s ease"
|
|
624
|
+
} })
|
|
625
|
+
] }, s)) })
|
|
626
|
+
]
|
|
627
|
+
}
|
|
628
|
+
),
|
|
629
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { padding: "16px" }, children: submitted ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
630
|
+
"div",
|
|
832
631
|
{
|
|
833
632
|
style: {
|
|
834
633
|
textAlign: "center",
|
|
@@ -837,202 +636,280 @@ function ReportButton({
|
|
|
837
636
|
fontSize: "14px",
|
|
838
637
|
fontWeight: 500
|
|
839
638
|
},
|
|
840
|
-
children:
|
|
639
|
+
children: [
|
|
640
|
+
getTypeLabel(reportType),
|
|
641
|
+
" sent. Thank you!"
|
|
642
|
+
]
|
|
841
643
|
}
|
|
842
|
-
) : /* @__PURE__ */ (0,
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
644
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
645
|
+
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)(
|
|
646
|
+
"button",
|
|
647
|
+
{
|
|
648
|
+
type: "button",
|
|
649
|
+
onClick: () => {
|
|
650
|
+
setReportType(type);
|
|
651
|
+
setStep(2);
|
|
652
|
+
},
|
|
653
|
+
style: {
|
|
654
|
+
display: "flex",
|
|
655
|
+
flexDirection: "column",
|
|
656
|
+
alignItems: "center",
|
|
657
|
+
gap: "8px",
|
|
658
|
+
padding: "16px 8px",
|
|
659
|
+
borderRadius: "8px",
|
|
660
|
+
border: `1px solid ${t.inputBorder}`,
|
|
661
|
+
background: t.inputBg,
|
|
662
|
+
cursor: "pointer",
|
|
663
|
+
color: t.text,
|
|
664
|
+
fontFamily: "inherit",
|
|
665
|
+
transition: "border-color 0.15s ease"
|
|
666
|
+
},
|
|
667
|
+
onMouseEnter: (e) => {
|
|
668
|
+
e.currentTarget.style.borderColor = t.accent;
|
|
669
|
+
},
|
|
670
|
+
onMouseLeave: (e) => {
|
|
671
|
+
e.currentTarget.style.borderColor = t.inputBorder;
|
|
672
|
+
},
|
|
673
|
+
children: [
|
|
674
|
+
getTypeIcon(type, t.accent),
|
|
675
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "13px", fontWeight: 600 }, children: getTypeLabel(type) }),
|
|
676
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "11px", color: t.textMuted, lineHeight: "1.3" }, children: getTypeSubtitle(type) })
|
|
677
|
+
]
|
|
678
|
+
},
|
|
679
|
+
type
|
|
680
|
+
)) }),
|
|
681
|
+
step === 2 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
682
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
683
|
+
"textarea",
|
|
846
684
|
{
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
685
|
+
value: description,
|
|
686
|
+
onChange: (e) => setDescription(e.target.value),
|
|
687
|
+
placeholder: getPlaceholder(reportType),
|
|
850
688
|
style: {
|
|
851
689
|
width: "100%",
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
690
|
+
minHeight: "100px",
|
|
691
|
+
padding: "10px 12px",
|
|
692
|
+
borderRadius: "8px",
|
|
693
|
+
border: `1px solid ${t.inputBorder}`,
|
|
694
|
+
fontSize: "14px",
|
|
695
|
+
fontFamily: "inherit",
|
|
696
|
+
resize: "vertical",
|
|
697
|
+
outline: "none",
|
|
698
|
+
boxSizing: "border-box",
|
|
699
|
+
color: t.text,
|
|
700
|
+
backgroundColor: t.inputBg
|
|
701
|
+
},
|
|
702
|
+
onFocus: (e) => {
|
|
703
|
+
e.target.style.borderColor = t.accent;
|
|
704
|
+
},
|
|
705
|
+
onBlur: (e) => {
|
|
706
|
+
e.target.style.borderColor = t.inputBorder;
|
|
707
|
+
},
|
|
708
|
+
autoFocus: true
|
|
859
709
|
}
|
|
860
710
|
),
|
|
861
|
-
/* @__PURE__ */ (0,
|
|
711
|
+
showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginTop: "10px" }, children: [
|
|
712
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "12px", color: t.textMuted, marginBottom: "6px", display: "block" }, children: "Severity" }),
|
|
713
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: { display: "flex", gap: "6px" }, children: ["low", "medium", "high"].map((s) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
714
|
+
"button",
|
|
715
|
+
{
|
|
716
|
+
type: "button",
|
|
717
|
+
onClick: () => setSeverity(s),
|
|
718
|
+
style: {
|
|
719
|
+
flex: 1,
|
|
720
|
+
padding: "6px 0",
|
|
721
|
+
borderRadius: "6px",
|
|
722
|
+
border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,
|
|
723
|
+
background: severity === s ? t.accent : "transparent",
|
|
724
|
+
color: severity === s ? t.accentText : t.text,
|
|
725
|
+
fontSize: "12px",
|
|
726
|
+
fontWeight: 600,
|
|
727
|
+
cursor: "pointer",
|
|
728
|
+
fontFamily: "inherit",
|
|
729
|
+
textTransform: "capitalize",
|
|
730
|
+
transition: "all 0.15s ease"
|
|
731
|
+
},
|
|
732
|
+
children: s
|
|
733
|
+
},
|
|
734
|
+
s
|
|
735
|
+
)) })
|
|
736
|
+
] }),
|
|
737
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
862
738
|
"button",
|
|
863
739
|
{
|
|
864
740
|
type: "button",
|
|
865
|
-
onClick: () =>
|
|
741
|
+
onClick: () => setStep(3),
|
|
742
|
+
disabled: !description.trim(),
|
|
866
743
|
style: {
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
744
|
+
marginTop: "12px",
|
|
745
|
+
width: "100%",
|
|
746
|
+
padding: "10px",
|
|
747
|
+
borderRadius: "8px",
|
|
871
748
|
border: "none",
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
749
|
+
backgroundColor: !description.trim() ? t.bgSecondary : t.accent,
|
|
750
|
+
color: !description.trim() ? t.textMuted : t.accentText,
|
|
751
|
+
fontSize: "14px",
|
|
752
|
+
fontWeight: 600,
|
|
753
|
+
cursor: !description.trim() ? "not-allowed" : "pointer",
|
|
754
|
+
fontFamily: "inherit",
|
|
755
|
+
transition: "background-color 0.15s ease"
|
|
879
756
|
},
|
|
880
|
-
|
|
881
|
-
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" }) })
|
|
757
|
+
children: "Next"
|
|
882
758
|
}
|
|
883
|
-
)
|
|
884
|
-
|
|
885
|
-
|
|
759
|
+
)
|
|
760
|
+
] }),
|
|
761
|
+
step === 3 && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
762
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", flexWrap: "wrap", marginBottom: "12px" }, children: [
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { style: {
|
|
764
|
+
display: "inline-flex",
|
|
765
|
+
alignItems: "center",
|
|
766
|
+
gap: "4px",
|
|
767
|
+
padding: "4px 10px",
|
|
768
|
+
borderRadius: "12px",
|
|
769
|
+
fontSize: "12px",
|
|
770
|
+
fontWeight: 600,
|
|
771
|
+
backgroundColor: t.bgSecondary,
|
|
772
|
+
color: t.text,
|
|
773
|
+
border: `1px solid ${t.border}`
|
|
774
|
+
}, children: [
|
|
775
|
+
getTypeIcon(reportType, t.accent, 12),
|
|
776
|
+
getTypeLabel(reportType)
|
|
777
|
+
] }),
|
|
778
|
+
showSeverity && reportType === "BUG" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: {
|
|
779
|
+
display: "inline-flex",
|
|
780
|
+
alignItems: "center",
|
|
781
|
+
padding: "4px 10px",
|
|
782
|
+
borderRadius: "12px",
|
|
783
|
+
fontSize: "12px",
|
|
784
|
+
fontWeight: 600,
|
|
785
|
+
backgroundColor: severity === "high" ? "#fef2f2" : severity === "medium" ? "#fffbeb" : "#f0fdf4",
|
|
786
|
+
color: severity === "high" ? "#dc2626" : severity === "medium" ? "#d97706" : "#16a34a",
|
|
787
|
+
border: `1px solid ${severity === "high" ? "#fecaca" : severity === "medium" ? "#fde68a" : "#bbf7d0"}`,
|
|
788
|
+
textTransform: "capitalize"
|
|
789
|
+
}, children: severity })
|
|
790
|
+
] }),
|
|
791
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: {
|
|
792
|
+
padding: "10px 12px",
|
|
793
|
+
borderRadius: "8px",
|
|
794
|
+
border: `1px solid ${t.inputBorder}`,
|
|
795
|
+
backgroundColor: t.inputBg,
|
|
796
|
+
fontSize: "13px",
|
|
797
|
+
color: t.text,
|
|
798
|
+
marginBottom: "10px",
|
|
799
|
+
maxHeight: "80px",
|
|
800
|
+
overflow: "hidden",
|
|
801
|
+
lineHeight: "1.4"
|
|
802
|
+
}, children: description.length > 200 ? description.slice(0, 200) + "..." : description }),
|
|
803
|
+
screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { marginBottom: "10px", position: "relative" }, children: [
|
|
804
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
805
|
+
"img",
|
|
806
|
+
{
|
|
807
|
+
src: screenshot,
|
|
808
|
+
alt: "Page screenshot",
|
|
809
|
+
onClick: () => setPreviewOpen(true),
|
|
810
|
+
style: {
|
|
811
|
+
width: "100%",
|
|
812
|
+
borderRadius: "6px",
|
|
813
|
+
border: `1px solid ${t.border}`,
|
|
814
|
+
maxHeight: "80px",
|
|
815
|
+
objectFit: "cover",
|
|
816
|
+
objectPosition: "top",
|
|
817
|
+
cursor: "pointer"
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
),
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
822
|
+
"button",
|
|
823
|
+
{
|
|
824
|
+
type: "button",
|
|
825
|
+
onClick: () => setScreenshot(null),
|
|
826
|
+
style: {
|
|
827
|
+
position: "absolute",
|
|
828
|
+
top: "4px",
|
|
829
|
+
right: "4px",
|
|
830
|
+
background: "rgba(0,0,0,0.6)",
|
|
831
|
+
border: "none",
|
|
832
|
+
borderRadius: "50%",
|
|
833
|
+
width: "20px",
|
|
834
|
+
height: "20px",
|
|
835
|
+
cursor: "pointer",
|
|
836
|
+
display: "flex",
|
|
837
|
+
alignItems: "center",
|
|
838
|
+
justifyContent: "center"
|
|
839
|
+
},
|
|
840
|
+
"aria-label": "Remove screenshot",
|
|
841
|
+
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" }) })
|
|
842
|
+
}
|
|
843
|
+
)
|
|
844
|
+
] }),
|
|
845
|
+
!screenshot && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: { display: "flex", gap: "6px", marginBottom: "10px" }, children: [
|
|
846
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
847
|
+
"button",
|
|
848
|
+
{
|
|
849
|
+
type: "button",
|
|
850
|
+
onClick: () => {
|
|
851
|
+
var _a;
|
|
852
|
+
return (_a = fileInputRef.current) == null ? void 0 : _a.click();
|
|
853
|
+
},
|
|
854
|
+
style: {
|
|
855
|
+
flex: 1,
|
|
856
|
+
padding: "8px",
|
|
857
|
+
borderRadius: "6px",
|
|
858
|
+
border: `1px dashed ${t.inputBorder}`,
|
|
859
|
+
textAlign: "center",
|
|
860
|
+
fontSize: "11px",
|
|
861
|
+
color: t.textMuted,
|
|
862
|
+
background: "none",
|
|
863
|
+
cursor: "pointer"
|
|
864
|
+
},
|
|
865
|
+
children: "Upload screenshot"
|
|
866
|
+
}
|
|
867
|
+
),
|
|
868
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
869
|
+
"button",
|
|
870
|
+
{
|
|
871
|
+
type: "button",
|
|
872
|
+
onClick: retakeScreenshot,
|
|
873
|
+
style: {
|
|
874
|
+
flex: 1,
|
|
875
|
+
padding: "8px",
|
|
876
|
+
borderRadius: "6px",
|
|
877
|
+
border: `1px dashed ${t.inputBorder}`,
|
|
878
|
+
textAlign: "center",
|
|
879
|
+
fontSize: "11px",
|
|
880
|
+
color: t.textMuted,
|
|
881
|
+
background: "none",
|
|
882
|
+
cursor: "pointer"
|
|
883
|
+
},
|
|
884
|
+
children: "Retake screenshot"
|
|
885
|
+
}
|
|
886
|
+
)
|
|
887
|
+
] }),
|
|
888
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
889
|
+
"button",
|
|
886
890
|
{
|
|
891
|
+
type: "button",
|
|
892
|
+
onClick: handleSubmit,
|
|
893
|
+
disabled: isSubmitting,
|
|
887
894
|
style: {
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
+
width: "100%",
|
|
896
|
+
padding: "10px",
|
|
897
|
+
borderRadius: "8px",
|
|
898
|
+
border: "none",
|
|
899
|
+
backgroundColor: isSubmitting ? t.bgSecondary : t.accent,
|
|
900
|
+
color: isSubmitting ? t.textMuted : t.accentText,
|
|
901
|
+
fontSize: "14px",
|
|
902
|
+
fontWeight: 600,
|
|
903
|
+
cursor: isSubmitting ? "not-allowed" : "pointer",
|
|
904
|
+
fontFamily: "inherit",
|
|
905
|
+
transition: "background-color 0.15s ease"
|
|
895
906
|
},
|
|
896
|
-
children:
|
|
897
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
898
|
-
"span",
|
|
899
|
-
{
|
|
900
|
-
style: {
|
|
901
|
-
background: "rgba(0,0,0,0.6)",
|
|
902
|
-
color: "#fff",
|
|
903
|
-
fontSize: "10px",
|
|
904
|
-
padding: "2px 6px",
|
|
905
|
-
borderRadius: "4px"
|
|
906
|
-
},
|
|
907
|
-
children: [
|
|
908
|
-
"Screenshot (",
|
|
909
|
-
Math.round(screenshot.length * 0.75 / 1024),
|
|
910
|
-
"KB) \u2014 click to preview"
|
|
911
|
-
]
|
|
912
|
-
}
|
|
913
|
-
),
|
|
914
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "4px" }, children: [
|
|
915
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
916
|
-
"button",
|
|
917
|
-
{
|
|
918
|
-
type: "button",
|
|
919
|
-
onClick: () => {
|
|
920
|
-
var _a2;
|
|
921
|
-
return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
|
|
922
|
-
},
|
|
923
|
-
style: {
|
|
924
|
-
background: t.accent,
|
|
925
|
-
color: t.accentText,
|
|
926
|
-
fontSize: "10px",
|
|
927
|
-
padding: "3px 8px",
|
|
928
|
-
borderRadius: "4px",
|
|
929
|
-
border: "none",
|
|
930
|
-
cursor: "pointer",
|
|
931
|
-
fontWeight: 600
|
|
932
|
-
},
|
|
933
|
-
children: "Upload"
|
|
934
|
-
}
|
|
935
|
-
),
|
|
936
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
937
|
-
"button",
|
|
938
|
-
{
|
|
939
|
-
type: "button",
|
|
940
|
-
onClick: retakeScreenshot,
|
|
941
|
-
style: {
|
|
942
|
-
background: t.accent,
|
|
943
|
-
color: t.accentText,
|
|
944
|
-
fontSize: "10px",
|
|
945
|
-
padding: "3px 8px",
|
|
946
|
-
borderRadius: "4px",
|
|
947
|
-
border: "none",
|
|
948
|
-
cursor: "pointer",
|
|
949
|
-
fontWeight: 600
|
|
950
|
-
},
|
|
951
|
-
children: "Retake"
|
|
952
|
-
}
|
|
953
|
-
)
|
|
954
|
-
] })
|
|
955
|
-
]
|
|
907
|
+
children: isSubmitting ? "Sending..." : "Send Report"
|
|
956
908
|
}
|
|
957
909
|
)
|
|
958
|
-
] })
|
|
959
|
-
!screenshot && !submitted && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
960
|
-
"button",
|
|
961
|
-
{
|
|
962
|
-
type: "button",
|
|
963
|
-
onClick: () => {
|
|
964
|
-
var _a2;
|
|
965
|
-
return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
|
|
966
|
-
},
|
|
967
|
-
style: {
|
|
968
|
-
marginBottom: "10px",
|
|
969
|
-
padding: "10px",
|
|
970
|
-
borderRadius: "6px",
|
|
971
|
-
border: `1px dashed ${t.inputBorder}`,
|
|
972
|
-
textAlign: "center",
|
|
973
|
-
fontSize: "11px",
|
|
974
|
-
color: t.textMuted,
|
|
975
|
-
width: "100%",
|
|
976
|
-
background: "none",
|
|
977
|
-
cursor: "pointer"
|
|
978
|
-
},
|
|
979
|
-
children: "Click to upload a screenshot"
|
|
980
|
-
}
|
|
981
|
-
),
|
|
982
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
983
|
-
"textarea",
|
|
984
|
-
{
|
|
985
|
-
value: description,
|
|
986
|
-
onChange: (e) => setDescription(e.target.value),
|
|
987
|
-
placeholder: "Describe what went wrong...",
|
|
988
|
-
style: {
|
|
989
|
-
width: "100%",
|
|
990
|
-
minHeight: "100px",
|
|
991
|
-
padding: "10px 12px",
|
|
992
|
-
borderRadius: "8px",
|
|
993
|
-
border: `1px solid ${t.inputBorder}`,
|
|
994
|
-
fontSize: "14px",
|
|
995
|
-
fontFamily: "inherit",
|
|
996
|
-
resize: "vertical",
|
|
997
|
-
outline: "none",
|
|
998
|
-
boxSizing: "border-box",
|
|
999
|
-
color: t.text,
|
|
1000
|
-
backgroundColor: t.inputBg
|
|
1001
|
-
},
|
|
1002
|
-
onFocus: (e) => {
|
|
1003
|
-
e.target.style.borderColor = t.accent;
|
|
1004
|
-
},
|
|
1005
|
-
onBlur: (e) => {
|
|
1006
|
-
e.target.style.borderColor = t.inputBorder;
|
|
1007
|
-
},
|
|
1008
|
-
autoFocus: true
|
|
1009
|
-
}
|
|
1010
|
-
),
|
|
1011
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1012
|
-
"button",
|
|
1013
|
-
{
|
|
1014
|
-
type: "button",
|
|
1015
|
-
onClick: handleSubmit,
|
|
1016
|
-
disabled: !description.trim() || isSubmitting,
|
|
1017
|
-
style: {
|
|
1018
|
-
marginTop: "12px",
|
|
1019
|
-
width: "100%",
|
|
1020
|
-
padding: "10px",
|
|
1021
|
-
borderRadius: "8px",
|
|
1022
|
-
border: "none",
|
|
1023
|
-
backgroundColor: !description.trim() || isSubmitting ? t.bgSecondary : t.accent,
|
|
1024
|
-
color: !description.trim() || isSubmitting ? t.textMuted : t.accentText,
|
|
1025
|
-
fontSize: "14px",
|
|
1026
|
-
fontWeight: 600,
|
|
1027
|
-
cursor: !description.trim() || isSubmitting ? "not-allowed" : "pointer",
|
|
1028
|
-
fontFamily: "inherit",
|
|
1029
|
-
transition: "background-color 0.15s ease"
|
|
1030
|
-
},
|
|
1031
|
-
children: isSubmitting ? "Sending..." : "Send Report"
|
|
1032
|
-
}
|
|
1033
|
-
)
|
|
910
|
+
] })
|
|
1034
911
|
] }) }),
|
|
1035
|
-
/* @__PURE__ */ (0,
|
|
912
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1036
913
|
"div",
|
|
1037
914
|
{
|
|
1038
915
|
style: {
|
|
@@ -1040,7 +917,7 @@ function ReportButton({
|
|
|
1040
917
|
borderTop: `1px solid ${t.border}`,
|
|
1041
918
|
textAlign: "center"
|
|
1042
919
|
},
|
|
1043
|
-
children: /* @__PURE__ */ (0,
|
|
920
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { style: { fontSize: "11px", color: t.textMuted }, children: "Powered by Glitchgrab" })
|
|
1044
921
|
}
|
|
1045
922
|
)
|
|
1046
923
|
]
|
|
@@ -1050,7 +927,7 @@ function ReportButton({
|
|
|
1050
927
|
),
|
|
1051
928
|
document.body
|
|
1052
929
|
),
|
|
1053
|
-
/* @__PURE__ */ (0,
|
|
930
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1054
931
|
"input",
|
|
1055
932
|
{
|
|
1056
933
|
ref: fileInputRef,
|
|
@@ -1060,8 +937,8 @@ function ReportButton({
|
|
|
1060
937
|
style: { display: "none" }
|
|
1061
938
|
}
|
|
1062
939
|
),
|
|
1063
|
-
previewOpen && screenshot &&
|
|
1064
|
-
/* @__PURE__ */ (0,
|
|
940
|
+
previewOpen && screenshot && (0, import_react_dom.createPortal)(
|
|
941
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
1065
942
|
"div",
|
|
1066
943
|
{
|
|
1067
944
|
style: {
|
|
@@ -1082,7 +959,7 @@ function ReportButton({
|
|
|
1082
959
|
},
|
|
1083
960
|
onMouseDown: (e) => e.stopPropagation(),
|
|
1084
961
|
children: [
|
|
1085
|
-
/* @__PURE__ */ (0,
|
|
962
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1086
963
|
"img",
|
|
1087
964
|
{
|
|
1088
965
|
src: screenshot,
|
|
@@ -1097,7 +974,7 @@ function ReportButton({
|
|
|
1097
974
|
}
|
|
1098
975
|
}
|
|
1099
976
|
),
|
|
1100
|
-
/* @__PURE__ */ (0,
|
|
977
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1101
978
|
"span",
|
|
1102
979
|
{
|
|
1103
980
|
style: {
|
|
@@ -1115,24 +992,330 @@ function ReportButton({
|
|
|
1115
992
|
)
|
|
1116
993
|
] });
|
|
1117
994
|
}
|
|
1118
|
-
function
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
995
|
+
function getTypeLabel(type) {
|
|
996
|
+
switch (type) {
|
|
997
|
+
case "BUG":
|
|
998
|
+
return "Bug Report";
|
|
999
|
+
case "FEATURE_REQUEST":
|
|
1000
|
+
return "Feature Request";
|
|
1001
|
+
case "QUESTION":
|
|
1002
|
+
return "Question";
|
|
1003
|
+
case "OTHER":
|
|
1004
|
+
return "Other";
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
function getTypeSubtitle(type) {
|
|
1008
|
+
switch (type) {
|
|
1009
|
+
case "BUG":
|
|
1010
|
+
return "Something isn't working";
|
|
1011
|
+
case "FEATURE_REQUEST":
|
|
1012
|
+
return "Suggest an improvement";
|
|
1013
|
+
case "QUESTION":
|
|
1014
|
+
return "Ask a question";
|
|
1015
|
+
case "OTHER":
|
|
1016
|
+
return "General feedback";
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
function getPlaceholder(type) {
|
|
1020
|
+
switch (type) {
|
|
1021
|
+
case "BUG":
|
|
1022
|
+
return "What went wrong?";
|
|
1023
|
+
case "FEATURE_REQUEST":
|
|
1024
|
+
return "Describe the feature you'd like...";
|
|
1025
|
+
case "QUESTION":
|
|
1026
|
+
return "What would you like to know?";
|
|
1027
|
+
case "OTHER":
|
|
1028
|
+
return "Tell us what's on your mind...";
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
function getTypeIcon(type, color, size = 24) {
|
|
1032
|
+
const props = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", style: { flexShrink: 0 } };
|
|
1033
|
+
switch (type) {
|
|
1034
|
+
case "BUG":
|
|
1035
|
+
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" }) });
|
|
1036
|
+
case "FEATURE_REQUEST":
|
|
1037
|
+
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" }) });
|
|
1038
|
+
case "QUESTION":
|
|
1039
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("svg", { ...props, children: [
|
|
1040
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("circle", { cx: "12", cy: "12", r: "10", stroke: color, strokeWidth: "1.5" }),
|
|
1041
|
+
/* @__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" })
|
|
1042
|
+
] });
|
|
1043
|
+
case "OTHER":
|
|
1044
|
+
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" }) });
|
|
1045
|
+
}
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
// src/provider.tsx
|
|
1049
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1050
|
+
var DEFAULT_BASE_URL2 = "https://www.glitchgrab.dev";
|
|
1051
|
+
var GlitchgrabContext = (0, import_react2.createContext)(null);
|
|
1052
|
+
function useGlitchgrab() {
|
|
1053
|
+
const ctx = (0, import_react2.useContext)(GlitchgrabContext);
|
|
1054
|
+
if (!ctx) {
|
|
1055
|
+
throw new Error("useGlitchgrab must be used within a GlitchgrabProvider");
|
|
1056
|
+
}
|
|
1057
|
+
return ctx;
|
|
1058
|
+
}
|
|
1059
|
+
function GlitchgrabProviderInner({
|
|
1060
|
+
token,
|
|
1061
|
+
session,
|
|
1062
|
+
baseUrl,
|
|
1063
|
+
onError,
|
|
1064
|
+
onReportSent,
|
|
1065
|
+
breadcrumbs: enableBreadcrumbs = true,
|
|
1066
|
+
maxBreadcrumbs: maxBreadcrumbs2 = 50,
|
|
1067
|
+
children,
|
|
1068
|
+
fallback,
|
|
1069
|
+
types,
|
|
1070
|
+
showSeverity
|
|
1071
|
+
}) {
|
|
1072
|
+
const visitedPagesRef = (0, import_react2.useRef)([]);
|
|
1073
|
+
(0, import_react2.useEffect)(() => {
|
|
1074
|
+
if (enableBreadcrumbs) {
|
|
1075
|
+
initBreadcrumbs(maxBreadcrumbs2);
|
|
1076
|
+
}
|
|
1077
|
+
}, [enableBreadcrumbs, maxBreadcrumbs2]);
|
|
1078
|
+
(0, import_react2.useEffect)(() => {
|
|
1079
|
+
try {
|
|
1080
|
+
if (typeof window === "undefined") return;
|
|
1081
|
+
const trackPage = () => {
|
|
1082
|
+
try {
|
|
1083
|
+
const sanitized = sanitizeUrl(window.location.href);
|
|
1084
|
+
const pages = visitedPagesRef.current;
|
|
1085
|
+
if (pages[pages.length - 1] !== sanitized) {
|
|
1086
|
+
pages.push(sanitized);
|
|
1087
|
+
if (pages.length > 20) {
|
|
1088
|
+
pages.splice(0, pages.length - 20);
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
} catch (e) {
|
|
1092
|
+
}
|
|
1093
|
+
};
|
|
1094
|
+
trackPage();
|
|
1095
|
+
const handlePopState = () => trackPage();
|
|
1096
|
+
window.addEventListener("popstate", handlePopState);
|
|
1097
|
+
const origPushState = history.pushState.bind(history);
|
|
1098
|
+
const origReplaceState = history.replaceState.bind(history);
|
|
1099
|
+
history.pushState = function(...args) {
|
|
1100
|
+
origPushState(...args);
|
|
1101
|
+
trackPage();
|
|
1102
|
+
};
|
|
1103
|
+
history.replaceState = function(...args) {
|
|
1104
|
+
origReplaceState(...args);
|
|
1105
|
+
trackPage();
|
|
1106
|
+
};
|
|
1107
|
+
return () => {
|
|
1108
|
+
window.removeEventListener("popstate", handlePopState);
|
|
1109
|
+
history.pushState = origPushState;
|
|
1110
|
+
history.replaceState = origReplaceState;
|
|
1111
|
+
};
|
|
1112
|
+
} catch (e) {
|
|
1113
|
+
}
|
|
1114
|
+
}, []);
|
|
1115
|
+
(0, import_react2.useEffect)(() => {
|
|
1116
|
+
try {
|
|
1117
|
+
if (typeof window === "undefined") return;
|
|
1118
|
+
if (process.env.NODE_ENV === "development") return;
|
|
1119
|
+
const handleError = (event) => {
|
|
1120
|
+
var _a, _b, _c, _d, _e;
|
|
1121
|
+
try {
|
|
1122
|
+
const context = captureContext(visitedPagesRef.current);
|
|
1123
|
+
const payload = {
|
|
1124
|
+
token,
|
|
1125
|
+
source: "SDK_AUTO",
|
|
1126
|
+
type: "BUG",
|
|
1127
|
+
errorMessage: event.message,
|
|
1128
|
+
errorStack: (_a = event.error) == null ? void 0 : _a.stack,
|
|
1129
|
+
pageUrl: context.url,
|
|
1130
|
+
userAgent: context.userAgent,
|
|
1131
|
+
breadcrumbs: context.breadcrumbs,
|
|
1132
|
+
deviceInfo: (_b = context.deviceInfo) != null ? _b : void 0,
|
|
1133
|
+
metadata: {
|
|
1134
|
+
timestamp: context.timestamp,
|
|
1135
|
+
visitedPages: JSON.stringify(context.visitedPages),
|
|
1136
|
+
filename: (_c = event.filename) != null ? _c : "",
|
|
1137
|
+
lineno: String((_d = event.lineno) != null ? _d : ""),
|
|
1138
|
+
colno: String((_e = event.colno) != null ? _e : ""),
|
|
1139
|
+
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
1140
|
+
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
1141
|
+
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {}
|
|
1142
|
+
}
|
|
1143
|
+
};
|
|
1144
|
+
sendReport(payload, baseUrl).then((result) => {
|
|
1145
|
+
if (result && onReportSent) onReportSent(result);
|
|
1146
|
+
});
|
|
1147
|
+
if (onError && event.error) onError(event.error);
|
|
1148
|
+
} catch (e) {
|
|
1149
|
+
}
|
|
1150
|
+
};
|
|
1151
|
+
const handleRejection = (event) => {
|
|
1152
|
+
var _a;
|
|
1153
|
+
try {
|
|
1154
|
+
const context = captureContext(visitedPagesRef.current);
|
|
1155
|
+
const reason = event.reason;
|
|
1156
|
+
const payload = {
|
|
1157
|
+
token,
|
|
1158
|
+
source: "SDK_AUTO",
|
|
1159
|
+
type: "BUG",
|
|
1160
|
+
errorMessage: reason instanceof Error ? reason.message : String(reason),
|
|
1161
|
+
errorStack: reason instanceof Error ? reason.stack : void 0,
|
|
1162
|
+
pageUrl: context.url,
|
|
1163
|
+
userAgent: context.userAgent,
|
|
1164
|
+
breadcrumbs: context.breadcrumbs,
|
|
1165
|
+
deviceInfo: (_a = context.deviceInfo) != null ? _a : void 0,
|
|
1166
|
+
metadata: {
|
|
1167
|
+
timestamp: context.timestamp,
|
|
1168
|
+
visitedPages: JSON.stringify(context.visitedPages),
|
|
1169
|
+
type: "unhandledrejection",
|
|
1170
|
+
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
1171
|
+
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
1172
|
+
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {}
|
|
1173
|
+
}
|
|
1174
|
+
};
|
|
1175
|
+
sendReport(payload, baseUrl).then((result) => {
|
|
1176
|
+
if (result && onReportSent) onReportSent(result);
|
|
1177
|
+
});
|
|
1178
|
+
if (onError && reason instanceof Error) onError(reason);
|
|
1179
|
+
} catch (e) {
|
|
1180
|
+
}
|
|
1181
|
+
};
|
|
1182
|
+
window.addEventListener("error", handleError);
|
|
1183
|
+
window.addEventListener("unhandledrejection", handleRejection);
|
|
1184
|
+
return () => {
|
|
1185
|
+
window.removeEventListener("error", handleError);
|
|
1186
|
+
window.removeEventListener("unhandledrejection", handleRejection);
|
|
1187
|
+
};
|
|
1188
|
+
} catch (e) {
|
|
1189
|
+
}
|
|
1190
|
+
}, [token, baseUrl, onError, onReportSent]);
|
|
1191
|
+
const report = (0, import_react2.useCallback)(
|
|
1192
|
+
async (type, description, metadata) => {
|
|
1193
|
+
var _a;
|
|
1194
|
+
try {
|
|
1195
|
+
const context = captureContext(visitedPagesRef.current);
|
|
1196
|
+
const payload = {
|
|
1197
|
+
token,
|
|
1198
|
+
source: "SDK_USER_REPORT",
|
|
1199
|
+
type,
|
|
1200
|
+
description,
|
|
1201
|
+
pageUrl: context.url,
|
|
1202
|
+
userAgent: context.userAgent,
|
|
1203
|
+
breadcrumbs: context.breadcrumbs,
|
|
1204
|
+
deviceInfo: (_a = context.deviceInfo) != null ? _a : void 0,
|
|
1205
|
+
metadata: {
|
|
1206
|
+
timestamp: context.timestamp,
|
|
1207
|
+
visitedPages: JSON.stringify(context.visitedPages),
|
|
1208
|
+
...(session == null ? void 0 : session.userId) ? { sessionUserId: session.userId } : {},
|
|
1209
|
+
...(session == null ? void 0 : session.name) ? { sessionUserName: String(session.name) } : {},
|
|
1210
|
+
...(session == null ? void 0 : session.email) ? { sessionUserEmail: String(session.email) } : {},
|
|
1211
|
+
...(session == null ? void 0 : session.phone) ? { sessionUserPhone: String(session.phone) } : {},
|
|
1212
|
+
...metadata
|
|
1213
|
+
}
|
|
1214
|
+
};
|
|
1215
|
+
const result = await sendReport(payload, baseUrl);
|
|
1216
|
+
if (result && onReportSent) onReportSent(result);
|
|
1217
|
+
return result;
|
|
1218
|
+
} catch (e) {
|
|
1219
|
+
return null;
|
|
1220
|
+
}
|
|
1221
|
+
},
|
|
1222
|
+
[token, baseUrl, onReportSent, session]
|
|
1223
|
+
);
|
|
1224
|
+
const reportBug = (0, import_react2.useCallback)(
|
|
1225
|
+
(description, metadata) => report("BUG", description, metadata),
|
|
1226
|
+
[report]
|
|
1227
|
+
);
|
|
1228
|
+
const addBreadcrumb2 = (0, import_react2.useCallback)(
|
|
1229
|
+
(message, data) => {
|
|
1230
|
+
addBreadcrumb("custom", message, data);
|
|
1231
|
+
},
|
|
1232
|
+
[]
|
|
1233
|
+
);
|
|
1234
|
+
const openReportDialog = (0, import_react2.useCallback)((options) => {
|
|
1235
|
+
if (typeof window !== "undefined") {
|
|
1236
|
+
window.dispatchEvent(new CustomEvent("glitchgrab:open-report", { detail: options }));
|
|
1237
|
+
}
|
|
1238
|
+
}, []);
|
|
1239
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1240
|
+
GlitchgrabContext.Provider,
|
|
1241
|
+
{
|
|
1242
|
+
value: {
|
|
1243
|
+
token,
|
|
1244
|
+
baseUrl: baseUrl != null ? baseUrl : DEFAULT_BASE_URL2,
|
|
1245
|
+
reportBug,
|
|
1246
|
+
report,
|
|
1247
|
+
addBreadcrumb: addBreadcrumb2,
|
|
1248
|
+
openReportDialog
|
|
1249
|
+
},
|
|
1250
|
+
children: [
|
|
1251
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1252
|
+
GlitchgrabErrorBoundary,
|
|
1253
|
+
{
|
|
1254
|
+
token,
|
|
1255
|
+
baseUrl,
|
|
1256
|
+
onError,
|
|
1257
|
+
fallback,
|
|
1258
|
+
visitedPages: visitedPagesRef.current,
|
|
1259
|
+
children
|
|
1260
|
+
}
|
|
1261
|
+
),
|
|
1262
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ReportDialog, { report, types, showSeverity })
|
|
1263
|
+
]
|
|
1264
|
+
}
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
function GlitchgrabProvider(props) {
|
|
1268
|
+
if (!props.token) return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
|
|
1269
|
+
const resolvedProps = {
|
|
1270
|
+
...props,
|
|
1271
|
+
baseUrl: props.baseUrl || DEFAULT_BASE_URL2
|
|
1272
|
+
};
|
|
1273
|
+
try {
|
|
1274
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(GlitchgrabProviderInner, { ...resolvedProps });
|
|
1275
|
+
} catch (e) {
|
|
1276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_jsx_runtime2.Fragment, { children: props.children });
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
// src/report-button.tsx
|
|
1281
|
+
var import_react3 = require("react");
|
|
1282
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1283
|
+
function useGlitchgrabSafe() {
|
|
1284
|
+
try {
|
|
1285
|
+
return useGlitchgrab();
|
|
1286
|
+
} catch (e) {
|
|
1287
|
+
return null;
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
function ReportButton({
|
|
1291
|
+
position = "bottom-right",
|
|
1292
|
+
label = "Report Bug",
|
|
1122
1293
|
className,
|
|
1123
|
-
|
|
1124
|
-
isLeft,
|
|
1125
|
-
isTop
|
|
1294
|
+
children
|
|
1126
1295
|
}) {
|
|
1296
|
+
var _a, _b;
|
|
1297
|
+
const [capturing, setCapturing] = (0, import_react3.useState)(false);
|
|
1298
|
+
const glitchgrab = useGlitchgrabSafe();
|
|
1299
|
+
if (!glitchgrab) return null;
|
|
1300
|
+
const handleClick = async () => {
|
|
1301
|
+
setCapturing(true);
|
|
1302
|
+
glitchgrab.openReportDialog();
|
|
1303
|
+
setCapturing(false);
|
|
1304
|
+
};
|
|
1305
|
+
if (children) {
|
|
1306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: children({ onClick: handleClick, capturing }) });
|
|
1307
|
+
}
|
|
1308
|
+
const isTop = (_a = position == null ? void 0 : position.startsWith("top")) != null ? _a : false;
|
|
1309
|
+
const isLeft = (_b = position == null ? void 0 : position.endsWith("left")) != null ? _b : false;
|
|
1127
1310
|
const positionStyles = {
|
|
1128
1311
|
...isLeft ? { left: "16px" } : { right: "16px" },
|
|
1129
1312
|
...isTop ? { top: "16px" } : { bottom: "16px" }
|
|
1130
1313
|
};
|
|
1131
|
-
return /* @__PURE__ */ (0,
|
|
1314
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1132
1315
|
"button",
|
|
1133
1316
|
{
|
|
1134
1317
|
type: "button",
|
|
1135
|
-
onClick,
|
|
1318
|
+
onClick: handleClick,
|
|
1136
1319
|
disabled: capturing,
|
|
1137
1320
|
className,
|
|
1138
1321
|
style: {
|
|
@@ -1163,7 +1346,7 @@ function DefaultTrigger({
|
|
|
1163
1346
|
},
|
|
1164
1347
|
"aria-label": label,
|
|
1165
1348
|
children: [
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1349
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1167
1350
|
"svg",
|
|
1168
1351
|
{
|
|
1169
1352
|
width: "16",
|
|
@@ -1171,7 +1354,7 @@ function DefaultTrigger({
|
|
|
1171
1354
|
viewBox: "0 0 16 16",
|
|
1172
1355
|
fill: "none",
|
|
1173
1356
|
style: { flexShrink: 0 },
|
|
1174
|
-
children: /* @__PURE__ */ (0,
|
|
1357
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1175
1358
|
"path",
|
|
1176
1359
|
{
|
|
1177
1360
|
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",
|
|
@@ -1187,18 +1370,18 @@ function DefaultTrigger({
|
|
|
1187
1370
|
}
|
|
1188
1371
|
|
|
1189
1372
|
// src/use-reports.ts
|
|
1190
|
-
var
|
|
1373
|
+
var import_react4 = require("react");
|
|
1191
1374
|
var BASE_URL = "https://www.glitchgrab.dev";
|
|
1192
1375
|
function useGlitchgrabReports({
|
|
1193
1376
|
token,
|
|
1194
1377
|
userId,
|
|
1195
1378
|
limit = 100
|
|
1196
1379
|
}) {
|
|
1197
|
-
const [reports, setReports] = (0,
|
|
1198
|
-
const [isLoading, setIsLoading] = (0,
|
|
1199
|
-
const [isFetching, setIsFetching] = (0,
|
|
1200
|
-
const [error, setError] = (0,
|
|
1201
|
-
const fetchReports = (0,
|
|
1380
|
+
const [reports, setReports] = (0, import_react4.useState)([]);
|
|
1381
|
+
const [isLoading, setIsLoading] = (0, import_react4.useState)(true);
|
|
1382
|
+
const [isFetching, setIsFetching] = (0, import_react4.useState)(false);
|
|
1383
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1384
|
+
const fetchReports = (0, import_react4.useCallback)(async () => {
|
|
1202
1385
|
var _a, _b;
|
|
1203
1386
|
if (!token || !userId) {
|
|
1204
1387
|
setIsLoading(false);
|
|
@@ -1224,7 +1407,7 @@ function useGlitchgrabReports({
|
|
|
1224
1407
|
setIsFetching(false);
|
|
1225
1408
|
}
|
|
1226
1409
|
}, [token, userId, limit]);
|
|
1227
|
-
(0,
|
|
1410
|
+
(0, import_react4.useEffect)(() => {
|
|
1228
1411
|
fetchReports();
|
|
1229
1412
|
}, [fetchReports]);
|
|
1230
1413
|
return { reports, isLoading, isFetching, error, refetch: fetchReports };
|
|
@@ -1261,9 +1444,9 @@ function useGlitchgrabActions({
|
|
|
1261
1444
|
onSuccess,
|
|
1262
1445
|
onError
|
|
1263
1446
|
}) {
|
|
1264
|
-
const [isPending, setIsPending] = (0,
|
|
1265
|
-
const [error, setError] = (0,
|
|
1266
|
-
const run = (0,
|
|
1447
|
+
const [isPending, setIsPending] = (0, import_react4.useState)(false);
|
|
1448
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1449
|
+
const run = (0, import_react4.useCallback)(
|
|
1267
1450
|
async (reportId, body) => {
|
|
1268
1451
|
setIsPending(true);
|
|
1269
1452
|
setError(null);
|