glitchgrab 1.13.1 → 1.13.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +51 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +51 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -277,13 +277,14 @@ async function sendReport(payload, baseUrl) {
|
|
|
277
277
|
"Content-Type": "application/json",
|
|
278
278
|
Authorization: `Bearer ${payload.token}`
|
|
279
279
|
};
|
|
280
|
+
const useKeepalive = body.length < 6e4;
|
|
280
281
|
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
281
282
|
try {
|
|
282
283
|
const response = await fetch(url, {
|
|
283
284
|
method: "POST",
|
|
284
285
|
headers,
|
|
285
286
|
body,
|
|
286
|
-
keepalive: true
|
|
287
|
+
...useKeepalive ? { keepalive: true } : {}
|
|
287
288
|
});
|
|
288
289
|
if (response.ok) {
|
|
289
290
|
const data = await response.json();
|
|
@@ -380,6 +381,33 @@ function useIsDark() {
|
|
|
380
381
|
function getTheme(dark) {
|
|
381
382
|
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" };
|
|
382
383
|
}
|
|
384
|
+
function isLowQualityText(text) {
|
|
385
|
+
const trimmed = text.trim();
|
|
386
|
+
if (!trimmed) return null;
|
|
387
|
+
const throwaway = /^(done|ok|yes|no|hi|hello|hey|test|testing|asdf|qwerty|abc|xyz|foo|bar|baz|lol|lmao|idk|bruh|nice|cool|wow|sup|yo|nah|yep|nope|thanks|thx|ty|k|kk|hmm|hm|na|mm|mhm|aight|bet|gg|wp|rip|omg|pls|plz)$/i;
|
|
388
|
+
if (throwaway.test(trimmed)) {
|
|
389
|
+
return "Please describe the actual issue you're experiencing";
|
|
390
|
+
}
|
|
391
|
+
if (/(.)\1{4,}/.test(trimmed)) {
|
|
392
|
+
return "Please provide a meaningful description";
|
|
393
|
+
}
|
|
394
|
+
const letters = trimmed.replace(/[^a-zA-Z]/g, "");
|
|
395
|
+
if (letters.length >= 4) {
|
|
396
|
+
const vowels = letters.replace(/[^aeiouAEIOU]/g, "").length;
|
|
397
|
+
const vowelRatio = vowels / letters.length;
|
|
398
|
+
if (vowelRatio < 0.08) {
|
|
399
|
+
return "That doesn't look like a valid description";
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
const words = trimmed.split(/\s+/).filter((w) => w.length > 0);
|
|
403
|
+
if (words.length === 1 && trimmed.length < 10) {
|
|
404
|
+
const techTerms = /^(crash|error|bug|fail|broken|slow|freeze|lag|404|500|null|undefined|nan|timeout|overflow|leak|cors|oom)$/i;
|
|
405
|
+
if (!techTerms.test(trimmed)) {
|
|
406
|
+
return "Please provide more detail about the issue";
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
383
411
|
function ReportDialog({
|
|
384
412
|
report,
|
|
385
413
|
types,
|
|
@@ -400,6 +428,7 @@ function ReportDialog({
|
|
|
400
428
|
const [step, setStep] = (0, import_react.useState)(1);
|
|
401
429
|
const [reportType, setReportType] = (0, import_react.useState)("BUG");
|
|
402
430
|
const [severity, setSeverity] = (0, import_react.useState)("medium");
|
|
431
|
+
const [validationError, setValidationError] = (0, import_react.useState)(null);
|
|
403
432
|
const availableTypes = types != null ? types : ["BUG", "FEATURE_REQUEST", "QUESTION", "OTHER"];
|
|
404
433
|
const isDark = useIsDark();
|
|
405
434
|
const t = getTheme(isDark);
|
|
@@ -481,10 +510,17 @@ function ReportDialog({
|
|
|
481
510
|
setStep(1);
|
|
482
511
|
setReportType("BUG");
|
|
483
512
|
setSeverity("medium");
|
|
513
|
+
setValidationError(null);
|
|
484
514
|
};
|
|
485
515
|
const handleSubmit = async () => {
|
|
486
516
|
try {
|
|
487
517
|
if (!description.trim() || isSubmitting) return;
|
|
518
|
+
const qualityError = isLowQualityText(description);
|
|
519
|
+
if (qualityError) {
|
|
520
|
+
setValidationError(qualityError);
|
|
521
|
+
setStep(2);
|
|
522
|
+
return;
|
|
523
|
+
}
|
|
488
524
|
setIsSubmitting(true);
|
|
489
525
|
const metadata = {};
|
|
490
526
|
if (screenshot) metadata.screenshot = screenshot;
|
|
@@ -687,7 +723,10 @@ function ReportDialog({
|
|
|
687
723
|
"textarea",
|
|
688
724
|
{
|
|
689
725
|
value: description,
|
|
690
|
-
onChange: (e) =>
|
|
726
|
+
onChange: (e) => {
|
|
727
|
+
setDescription(e.target.value);
|
|
728
|
+
if (validationError) setValidationError(null);
|
|
729
|
+
},
|
|
691
730
|
placeholder: getPlaceholder(reportType),
|
|
692
731
|
style: {
|
|
693
732
|
width: "100%",
|
|
@@ -738,11 +777,20 @@ function ReportDialog({
|
|
|
738
777
|
s
|
|
739
778
|
)) })
|
|
740
779
|
] }),
|
|
780
|
+
validationError && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { style: { color: "#ef4444", fontSize: "12px", marginTop: "6px" }, children: validationError }),
|
|
741
781
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
742
782
|
"button",
|
|
743
783
|
{
|
|
744
784
|
type: "button",
|
|
745
|
-
onClick: () =>
|
|
785
|
+
onClick: () => {
|
|
786
|
+
const err = isLowQualityText(description);
|
|
787
|
+
if (err) {
|
|
788
|
+
setValidationError(err);
|
|
789
|
+
return;
|
|
790
|
+
}
|
|
791
|
+
setValidationError(null);
|
|
792
|
+
setStep(3);
|
|
793
|
+
},
|
|
746
794
|
disabled: !description.trim(),
|
|
747
795
|
style: {
|
|
748
796
|
marginTop: "12px",
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/error-boundary.tsx","../src/breadcrumbs.ts","../src/utils.ts","../src/report-dialog.tsx","../src/report-button.tsx","../src/use-reports.ts"],"sourcesContent":["\"use client\";\n\n// ─── Core (required) ─────────────────────────────────────\nexport { GlitchgrabProvider, useGlitchgrab } from \"./provider\";\n\n// ─── Optional Components ─────────────────────────────────\nexport { ReportButton } from \"./report-button\";\nexport { GlitchgrabErrorBoundary } from \"./error-boundary\";\n\n// ─── Hooks ──────────────────────────────────────────────\nexport { useGlitchgrabReports, fetchGlitchgrabReports, useGlitchgrabActions } from \"./use-reports\";\nexport type { GlitchgrabReport } from \"./use-reports\";\n\n// ─── Breadcrumbs ─────────────────────────────────────────\nexport {\n addBreadcrumb,\n getBreadcrumbs,\n clearBreadcrumbs,\n initBreadcrumbs,\n} from \"./breadcrumbs\";\n\n// ─── Utilities ───────────────────────────────────────────\nexport { sanitizeUrl, captureContext, captureDeviceInfo, sendReport } from \"./utils\";\n\n// ─── Types ───────────────────────────────────────────────\nexport type {\n GlitchgrabConfig,\n GlitchgrabProviderProps,\n ReportPayload,\n ReportResult,\n ReportType,\n ReportSeverity,\n CapturedContext,\n DeviceInfo,\n Breadcrumb,\n BreadcrumbType,\n UseGlitchgrabReturn,\n ReportButtonProps,\n GlitchgrabSession,\n} from \"./types\";\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useRef,\n useEffect,\n useCallback,\n useState,\n} from \"react\";\nimport type {\n GlitchgrabProviderProps,\n UseGlitchgrabReturn,\n ReportPayload,\n ReportResult,\n ReportType,\n} from \"./types\";\nimport { GlitchgrabErrorBoundary } from \"./error-boundary\";\nimport { ReportDialog } from \"./report-dialog\";\nimport { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\n\nconst GlitchgrabContext = createContext<UseGlitchgrabReturn | null>(null);\n\n/**\n * Hook to access Glitchgrab in your components.\n *\n * @example\n * ```tsx\n * const { reportBug, report, addBreadcrumb } = useGlitchgrab();\n *\n * // Report a bug\n * reportBug(\"Login button crashes on mobile\");\n *\n * // Report a feature request\n * report(\"FEATURE_REQUEST\", \"Add dark mode\");\n *\n * // Add a custom breadcrumb\n * addBreadcrumb(\"User clicked checkout\", { cartItems: \"3\" });\n * ```\n */\nexport function useGlitchgrab(): UseGlitchgrabReturn {\n const ctx = useContext(GlitchgrabContext);\n if (!ctx) {\n throw new Error(\"useGlitchgrab must be used within a GlitchgrabProvider\");\n }\n return ctx;\n}\n\nfunction GlitchgrabProviderInner({\n token,\n session,\n baseUrl,\n onError,\n onReportSent,\n breadcrumbs: enableBreadcrumbs = true,\n maxBreadcrumbs = 50,\n children,\n fallback,\n types,\n showSeverity,\n}: GlitchgrabProviderProps) {\n const visitedPagesRef = useRef<string[]>([]);\n\n // Initialize breadcrumbs\n useEffect(() => {\n if (enableBreadcrumbs) {\n initBreadcrumbs(maxBreadcrumbs);\n }\n }, [enableBreadcrumbs, maxBreadcrumbs]);\n\n // Track page visits\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n\n const trackPage = () => {\n try {\n const sanitized = sanitizeUrl(window.location.href);\n const pages = visitedPagesRef.current;\n if (pages[pages.length - 1] !== sanitized) {\n pages.push(sanitized);\n if (pages.length > 20) {\n pages.splice(0, pages.length - 20);\n }\n }\n } catch {\n // Silently fail\n }\n };\n\n trackPage();\n const handlePopState = () => trackPage();\n window.addEventListener(\"popstate\", handlePopState);\n\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPushState(...args);\n trackPage();\n };\n history.replaceState = function (...args) {\n origReplaceState(...args);\n trackPage();\n };\n\n return () => {\n window.removeEventListener(\"popstate\", handlePopState);\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n };\n } catch {\n // Never crash\n }\n }, []);\n\n // Unhandled errors and rejections — skip in development\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n if (process.env.NODE_ENV === \"development\") return;\n\n const handleError = (event: ErrorEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: event.message,\n errorStack: event.error?.stack,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n filename: event.filename ?? \"\",\n lineno: String(event.lineno ?? \"\"),\n colno: String(event.colno ?? \"\"),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && event.error) onError(event.error);\n } catch {\n // Silently fail\n }\n };\n\n const handleRejection = (event: PromiseRejectionEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const reason = event.reason;\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: reason instanceof Error ? reason.message : String(reason),\n errorStack: reason instanceof Error ? reason.stack : undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n type: \"unhandledrejection\",\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && reason instanceof Error) onError(reason);\n } catch {\n // Silently fail\n }\n };\n\n window.addEventListener(\"error\", handleError);\n window.addEventListener(\"unhandledrejection\", handleRejection);\n\n return () => {\n window.removeEventListener(\"error\", handleError);\n window.removeEventListener(\"unhandledrejection\", handleRejection);\n };\n } catch {\n // Never crash\n }\n }, [token, baseUrl, onError, onReportSent]);\n\n const report = useCallback(\n async (\n type: ReportType,\n description: string,\n metadata?: Record<string, string>\n ): Promise<ReportResult | null> => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_USER_REPORT\",\n type,\n description,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n ...(session?.phone ? { sessionUserPhone: String(session.phone) } : {}),\n ...metadata,\n },\n };\n const result = await sendReport(payload, baseUrl);\n if (result && onReportSent) onReportSent(result);\n return result;\n } catch {\n return null;\n }\n },\n [token, baseUrl, onReportSent, session]\n );\n\n const reportBug = useCallback(\n (description: string, metadata?: Record<string, string>) =>\n report(\"BUG\", description, metadata),\n [report]\n );\n\n const addBreadcrumb = useCallback(\n (message: string, data?: Record<string, string>) => {\n addBreadcrumbInternal(\"custom\", message, data);\n },\n []\n );\n\n const openReportDialog = useCallback((options?: { description?: string; type?: ReportType }) => {\n if (typeof window !== \"undefined\") {\n window.dispatchEvent(new CustomEvent(\"glitchgrab:open-report\", { detail: options }));\n }\n }, []);\n\n return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\n openReportDialog,\n }}\n >\n <GlitchgrabErrorBoundary\n token={token}\n baseUrl={baseUrl}\n onError={onError}\n fallback={fallback}\n visitedPages={visitedPagesRef.current}\n >\n {children}\n </GlitchgrabErrorBoundary>\n <ReportDialog report={report} types={types} showSeverity={showSeverity} />\n </GlitchgrabContext.Provider>\n );\n}\n\nexport function GlitchgrabProvider(props: GlitchgrabProviderProps) {\n // No token = passthrough (SDK disabled)\n if (!props.token) return <>{props.children}</>;\n\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || DEFAULT_BASE_URL,\n };\n\n try {\n return <GlitchgrabProviderInner {...resolvedProps} />;\n } catch {\n return <>{props.children}</>;\n }\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport type { ReportPayload } from \"./types\";\nimport { captureContext, sendReport } from \"./utils\";\n\ninterface ErrorBoundaryProps {\n token: string;\n baseUrl?: string;\n onError?: (error: Error) => void;\n fallback?: React.ReactNode;\n visitedPages: string[];\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n}\n\nexport class GlitchgrabErrorBoundary extends React.Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false };\n }\n\n static getDerivedStateFromError(): ErrorBoundaryState {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n try {\n const context = captureContext(this.props.visitedPages);\n\n const payload: ReportPayload = {\n token: this.props.token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: error.message,\n errorStack: error.stack,\n componentStack: errorInfo.componentStack ?? undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n },\n };\n\n sendReport(payload, this.props.baseUrl);\n\n if (this.props.onError) {\n this.props.onError(error);\n }\n } catch {\n // Never crash the host app\n }\n }\n\n render(): React.ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n // Re-render children — allows recovery from transient errors\n return this.props.children;\n }\n\n return this.props.children;\n }\n}\n","import type { Breadcrumb, BreadcrumbType } from \"./types\";\n\nconst MAX_DEFAULT = 50;\n\nlet breadcrumbs: Breadcrumb[] = [];\nlet maxBreadcrumbs = MAX_DEFAULT;\nlet initialized = false;\n\nexport function initBreadcrumbs(max?: number) {\n if (initialized) return;\n maxBreadcrumbs = max ?? MAX_DEFAULT;\n\n try {\n if (typeof window === \"undefined\") return;\n interceptConsole();\n interceptFetch();\n interceptNavigation();\n interceptClicks();\n initialized = true;\n } catch {\n // Never crash\n }\n}\n\nexport function addBreadcrumb(\n type: BreadcrumbType,\n message: string,\n data?: Record<string, string>\n) {\n try {\n breadcrumbs.push({\n type,\n message: message.slice(0, 200),\n timestamp: new Date().toISOString(),\n data,\n });\n if (breadcrumbs.length > maxBreadcrumbs) {\n breadcrumbs = breadcrumbs.slice(-maxBreadcrumbs);\n }\n } catch {\n // Never crash\n }\n}\n\nexport function getBreadcrumbs(): Breadcrumb[] {\n return [...breadcrumbs];\n}\n\nexport function clearBreadcrumbs() {\n breadcrumbs = [];\n}\n\n// ─── Console Interception ────────────────────────────────\n\nfunction interceptConsole() {\n const origLog = console.log;\n const origWarn = console.warn;\n const origError = console.error;\n\n console.log = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[log] ${argsToString(args)}`);\n origLog.apply(console, args);\n };\n\n console.warn = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[warn] ${argsToString(args)}`);\n origWarn.apply(console, args);\n };\n\n console.error = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[error] ${argsToString(args)}`);\n origError.apply(console, args);\n };\n}\n\nfunction argsToString(args: unknown[]): string {\n try {\n return args\n .map((a) => {\n if (typeof a === \"string\") return a;\n if (a instanceof Error) return a.message;\n try {\n return JSON.stringify(a);\n } catch {\n return String(a);\n }\n })\n .join(\" \")\n .slice(0, 200);\n } catch {\n return \"[unknown]\";\n }\n}\n\n// ─── Fetch Interception ──────────────────────────────────\n\nfunction interceptFetch() {\n const origFetch = window.fetch;\n\n window.fetch = async function (input, init) {\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input instanceof Request\n ? input.url\n : String(input);\n const method = init?.method ?? \"GET\";\n const start = Date.now();\n\n try {\n const response = await origFetch.apply(window, [input, init]);\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → ${response.status}`, {\n method,\n status: String(response.status),\n duration: `${Date.now() - start}ms`,\n });\n return response;\n } catch (err) {\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → FAILED`, {\n method,\n error: err instanceof Error ? err.message : \"unknown\",\n duration: `${Date.now() - start}ms`,\n });\n throw err;\n }\n };\n}\n\n// ─── Navigation Interception ─────────────────────────────\n\nfunction interceptNavigation() {\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPush(...args);\n addBreadcrumb(\"navigation\", `Navigate to ${window.location.pathname}`);\n };\n\n history.replaceState = function (...args) {\n origReplace(...args);\n addBreadcrumb(\"navigation\", `Replace to ${window.location.pathname}`);\n };\n\n window.addEventListener(\"popstate\", () => {\n addBreadcrumb(\"navigation\", `Back/Forward to ${window.location.pathname}`);\n });\n}\n\n// ─── Click Interception ──────────────────────────────────\n\nfunction interceptClicks() {\n document.addEventListener(\n \"click\",\n (e) => {\n try {\n const target = e.target as HTMLElement;\n const tag = target.tagName?.toLowerCase();\n const text = target.textContent?.trim().slice(0, 50) ?? \"\";\n const id = target.id ? `#${target.id}` : \"\";\n const cls = target.className && typeof target.className === \"string\"\n ? `.${target.className.split(\" \")[0]}`\n : \"\";\n\n addBreadcrumb(\"click\", `Click ${tag}${id}${cls} \"${text}\"`);\n } catch {\n // Never crash\n }\n },\n { capture: true }\n );\n}\n","import type { ReportPayload, ReportResult, CapturedContext, DeviceInfo } from \"./types\";\nimport { getBreadcrumbs } from \"./breadcrumbs\";\n\nconst SENSITIVE_PARAMS = [\n \"token\", \"key\", \"secret\", \"password\", \"passwd\", \"auth\", \"authorization\",\n \"session\", \"sessionid\", \"session_id\", \"api_key\", \"apikey\", \"access_token\",\n \"refresh_token\", \"client_secret\", \"code\", \"state\", \"nonce\", \"credential\", \"private\",\n];\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n const params = new URLSearchParams(parsed.search);\n let modified = false;\n for (const key of Array.from(params.keys())) {\n if (SENSITIVE_PARAMS.some((s) => key.toLowerCase().includes(s))) {\n params.set(key, \"[REDACTED]\");\n modified = true;\n }\n }\n if (modified) parsed.search = params.toString();\n return parsed.toString();\n } catch {\n return url.split(\"?\")[0] ?? url;\n }\n}\n\nexport function captureDeviceInfo(): DeviceInfo | null {\n try {\n if (typeof window === \"undefined\") return null;\n return {\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n platform: navigator.platform ?? \"unknown\",\n language: navigator.language ?? \"unknown\",\n online: navigator.onLine,\n colorScheme: window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\",\n devicePixelRatio: window.devicePixelRatio ?? 1,\n };\n } catch {\n return null;\n }\n}\n\nexport function captureContext(visitedPages: string[]): CapturedContext {\n try {\n return {\n url: sanitizeUrl(typeof window !== \"undefined\" ? window.location.href : \"\"),\n userAgent: typeof navigator !== \"undefined\" ? navigator.userAgent : \"\",\n timestamp: new Date().toISOString(),\n visitedPages: visitedPages.map(sanitizeUrl),\n breadcrumbs: getBreadcrumbs(),\n deviceInfo: captureDeviceInfo(),\n };\n } catch {\n return {\n url: \"\",\n userAgent: \"\",\n timestamp: new Date().toISOString(),\n visitedPages: [],\n breadcrumbs: [],\n deviceInfo: null,\n };\n }\n}\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\nconst MAX_RETRIES = 3;\nconst RETRY_BASE_MS = 500;\n\n/**\n * Send a report and return the result.\n * Never throws — returns null on failure.\n */\nexport async function sendReport(\n payload: ReportPayload,\n baseUrl?: string\n): Promise<ReportResult | null> {\n try {\n const url = `${baseUrl ?? DEFAULT_BASE_URL}/api/v1/sdk/report`;\n const body = JSON.stringify(payload);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${payload.token}`,\n };\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n keepalive: true,\n });\n\n if (response.ok) {\n const data = (await response.json()) as { success: boolean; data?: ReportResult };\n return data.data ?? { success: data.success };\n }\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n return null;\n }\n } catch {\n // Will retry\n }\n\n if (attempt < MAX_RETRIES - 1) {\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_BASE_MS * Math.pow(2, attempt))\n );\n }\n }\n\n // Fallback: sendBeacon (fire-and-forget, no result)\n if (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n try {\n navigator.sendBeacon(url, new Blob([body], { type: \"application/json\" }));\n } catch {\n // Silently fail\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect, type CSSProperties, type ReactNode } from \"react\";\n// @ts-expect-error react-dom types handled by host app\nimport { createPortal } from \"react-dom\";\nimport type { ReportType, ReportSeverity, UseGlitchgrabReturn } from \"./types\";\n\n/** Detect if the host page uses a dark or light theme */\nfunction useIsDark(): boolean {\n if (typeof window === \"undefined\") return true;\n try {\n const bg = getComputedStyle(document.body).backgroundColor;\n const match = bg.match(/\\d+/g);\n if (match && match.length >= 3) {\n const [r, g, b] = match.map(Number);\n return (r * 299 + g * 587 + b * 114) / 1000 < 128;\n }\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n } catch {\n return true;\n }\n}\n\nfunction getTheme(dark: boolean) {\n return dark\n ? { bg: \"#1c1c1e\", bgSecondary: \"#27272a\", border: \"#2c2c2e\", text: \"#fafafa\", textMuted: \"#a1a1aa\", accent: \"#22d3ee\", accentText: \"#09090b\", inputBg: \"#27272a\", inputBorder: \"#3f3f46\" }\n : { bg: \"#ffffff\", bgSecondary: \"#f4f4f5\", border: \"#e4e4e7\", text: \"#18181b\", textMuted: \"#71717a\", accent: \"#0891b2\", accentText: \"#ffffff\", inputBg: \"#fafafa\", inputBorder: \"#d4d4d8\" };\n}\n\ninterface ReportDialogProps {\n report: UseGlitchgrabReturn[\"report\"];\n types?: ReportType[];\n showSeverity?: boolean;\n}\n\n/**\n * The report dialog — rendered inside GlitchgrabProvider automatically.\n * Opens via the `glitchgrab:open-report` custom event (triggered by `openReportDialog()`).\n */\nexport function ReportDialog({\n report,\n types,\n showSeverity = true,\n}: ReportDialogProps) {\n // Prevent hydration mismatch — render nothing until after hydration\n const [mounted, setMounted] = useState(false);\n useEffect(() => { setMounted(true); }, []);\n\n const [isOpen, setIsOpen] = useState(false);\n const [description, setDescription] = useState(\"\");\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n const [screenshot, setScreenshot] = useState<string | null>(null);\n const [previewOpen, setPreviewOpen] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDivElement>(null);\n\n // Stepper state\n const [step, setStep] = useState(1);\n const [reportType, setReportType] = useState<ReportType>(\"BUG\");\n const [severity, setSeverity] = useState<ReportSeverity>(\"medium\");\n\n const availableTypes: ReportType[] = types ?? [\"BUG\", \"FEATURE_REQUEST\", \"QUESTION\", \"OTHER\"];\n\n const isDark = useIsDark();\n const t = getTheme(isDark);\n\n const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => {\n setScreenshot(reader.result as string);\n };\n reader.readAsDataURL(file);\n e.target.value = \"\";\n };\n\n const retakeScreenshot = async () => {\n setPreviewOpen(false);\n setIsOpen(false);\n setScreenshot(null);\n await new Promise((r) => setTimeout(r, 300));\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // silently fail\n }\n setIsOpen(true);\n };\n\n const handleOpen = async () => {\n setSubmitted(false);\n if (availableTypes.length === 1) {\n setReportType(availableTypes[0]);\n setStep(2);\n }\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // screenshot failed — open without it\n }\n setIsOpen(true);\n };\n\n // Listen for programmatic open via openReportDialog()\n useEffect(() => {\n const handler = (e: Event) => {\n if (isOpen) return;\n const detail = (e as CustomEvent).detail;\n if (detail?.description) setDescription(detail.description);\n if (detail?.type) {\n setReportType(detail.type);\n setStep(2);\n }\n handleOpen();\n };\n window.addEventListener(\"glitchgrab:open-report\", handler);\n return () => window.removeEventListener(\"glitchgrab:open-report\", handler);\n }, [isOpen, handleOpen]);\n\n // Close on Escape\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleClose = () => {\n setIsOpen(false);\n setStep(1);\n setReportType(\"BUG\");\n setSeverity(\"medium\");\n };\n\n const handleSubmit = async () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n setIsSubmitting(true);\n const metadata: Record<string, string> = {};\n if (screenshot) metadata.screenshot = screenshot;\n if (showSeverity && reportType === \"BUG\") {\n metadata.severity = severity;\n }\n\n const result = await report(reportType, description.trim(), Object.keys(metadata).length > 0 ? metadata : undefined);\n\n if (result) {\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n\n setTimeout(() => {\n setSubmitted(false);\n handleClose();\n }, 2000);\n }\n setIsSubmitting(false);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n if (!mounted) return null;\n\n return (\n <>\n {/* Report modal */}\n {isOpen && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n onClick={() => { if (!previewOpen) handleClose(); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: \"relative\",\n zIndex: 2147483647,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: t.bg,\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: t.text,\n isolation: \"isolate\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: `1px solid ${t.border}`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"8px\" }}>\n {step > 1 && (\n <button\n type=\"button\"\n onClick={() => setStep((s) => (s - 1) as 1 | 2 | 3)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n aria-label=\"Back\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M10 3L5 8L10 13\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n )}\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: t.text,\n }}\n >\n {step === 1 ? \"What's on your mind?\" : step === 2 ? \"Tell us more\" : \"Review & Send\"}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Close\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" style={{ display: \"block\" }}>\n <path d=\"M4 4L12 12M12 4L4 12\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"center\", gap: \"0\", marginTop: \"12px\" }}>\n {[1, 2, 3].map((s, i) => (\n <div key={s} style={{ display: \"flex\", alignItems: \"center\" }}>\n <div style={{\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: s <= step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n {i < 2 && (\n <div style={{\n width: \"40px\",\n height: \"2px\",\n backgroundColor: s < step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n )}\n </div>\n ))}\n </div>\n </div>\n\n {/* Body */}\n <div style={{ padding: \"16px\" }}>\n {submitted ? (\n <div\n style={{\n textAlign: \"center\",\n padding: \"20px 0\",\n color: t.accent,\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n {getTypeLabel(reportType)} sent. Thank you!\n </div>\n ) : (\n <>\n {/* Step 1: Category */}\n {step === 1 && (\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: \"8px\" }}>\n {availableTypes.map((type) => (\n <button\n key={type}\n type=\"button\"\n onClick={() => {\n setReportType(type);\n setStep(2);\n }}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"16px 8px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n background: t.inputBg,\n cursor: \"pointer\",\n color: t.text,\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s ease\",\n }}\n onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.accent; }}\n onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.inputBorder; }}\n >\n {getTypeIcon(type, t.accent)}\n <span style={{ fontSize: \"13px\", fontWeight: 600 }}>{getTypeLabel(type)}</span>\n <span style={{ fontSize: \"11px\", color: t.textMuted, lineHeight: \"1.3\" }}>{getTypeSubtitle(type)}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* Step 2: Details */}\n {step === 2 && (\n <>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={getPlaceholder(reportType)}\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: t.text,\n backgroundColor: t.inputBg,\n }}\n onFocus={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.accent; }}\n onBlur={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.inputBorder; }}\n autoFocus\n />\n {showSeverity && reportType === \"BUG\" && (\n <div style={{ marginTop: \"10px\" }}>\n <span style={{ fontSize: \"12px\", color: t.textMuted, marginBottom: \"6px\", display: \"block\" }}>Severity</span>\n <div style={{ display: \"flex\", gap: \"6px\" }}>\n {([\"low\", \"medium\", \"high\"] as ReportSeverity[]).map((s) => (\n <button\n key={s}\n type=\"button\"\n onClick={() => setSeverity(s)}\n style={{\n flex: 1,\n padding: \"6px 0\",\n borderRadius: \"6px\",\n border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,\n background: severity === s ? t.accent : \"transparent\",\n color: severity === s ? t.accentText : t.text,\n fontSize: \"12px\",\n fontWeight: 600,\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n textTransform: \"capitalize\",\n transition: \"all 0.15s ease\",\n }}\n >\n {s}\n </button>\n ))}\n </div>\n </div>\n )}\n <button\n type=\"button\"\n onClick={() => setStep(3)}\n disabled={!description.trim()}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: !description.trim() ? t.bgSecondary : t.accent,\n color: !description.trim() ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: !description.trim() ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n Next\n </button>\n </>\n )}\n\n {/* Step 3: Review & Send */}\n {step === 3 && (\n <>\n {/* Summary chips */}\n <div style={{ display: \"flex\", gap: \"6px\", flexWrap: \"wrap\", marginBottom: \"12px\" }}>\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"4px\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: t.bgSecondary,\n color: t.text,\n border: `1px solid ${t.border}`,\n }}>\n {getTypeIcon(reportType, t.accent, 12)}\n {getTypeLabel(reportType)}\n </span>\n {showSeverity && reportType === \"BUG\" && (\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: severity === \"high\" ? \"#fef2f2\" : severity === \"medium\" ? \"#fffbeb\" : \"#f0fdf4\",\n color: severity === \"high\" ? \"#dc2626\" : severity === \"medium\" ? \"#d97706\" : \"#16a34a\",\n border: `1px solid ${severity === \"high\" ? \"#fecaca\" : severity === \"medium\" ? \"#fde68a\" : \"#bbf7d0\"}`,\n textTransform: \"capitalize\",\n }}>\n {severity}\n </span>\n )}\n </div>\n\n {/* Description preview */}\n <div style={{\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n backgroundColor: t.inputBg,\n fontSize: \"13px\",\n color: t.text,\n marginBottom: \"10px\",\n maxHeight: \"80px\",\n overflow: \"hidden\",\n lineHeight: \"1.4\",\n }}>\n {description.length > 200 ? description.slice(0, 200) + \"...\" : description}\n </div>\n\n {/* Screenshot */}\n {screenshot && (\n <div style={{ marginBottom: \"10px\", position: \"relative\" }}>\n <img\n src={screenshot}\n alt=\"Page screenshot\"\n onClick={() => setPreviewOpen(true)}\n style={{\n width: \"100%\",\n borderRadius: \"6px\",\n border: `1px solid ${t.border}`,\n maxHeight: \"80px\",\n objectFit: \"cover\",\n objectPosition: \"top\",\n cursor: \"pointer\",\n }}\n />\n <button\n type=\"button\"\n onClick={() => setScreenshot(null)}\n style={{\n position: \"absolute\",\n top: \"4px\",\n right: \"4px\",\n background: \"rgba(0,0,0,0.6)\",\n border: \"none\",\n borderRadius: \"50%\",\n width: \"20px\",\n height: \"20px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Remove screenshot\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M1 1L9 9M9 1L1 9\" stroke=\"#fff\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n )}\n {!screenshot && (\n <div style={{ display: \"flex\", gap: \"6px\", marginBottom: \"10px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload screenshot\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake screenshot\n </button>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={isSubmitting}\n style={{\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: isSubmitting ? t.bgSecondary : t.accent,\n color: isSubmitting ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: isSubmitting ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: `1px solid ${t.border}`,\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: t.textMuted }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>,\n document.body\n )}\n\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileUpload}\n style={{ display: \"none\" }}\n />\n\n {/* Full-screen screenshot preview */}\n {previewOpen && screenshot && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n backgroundColor: \"rgba(0,0,0,0.85)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"16px\",\n cursor: \"pointer\",\n }}\n onClick={(e) => { e.stopPropagation(); setPreviewOpen(false); }}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <img\n src={screenshot}\n alt=\"Screenshot preview\"\n onClick={(e) => e.stopPropagation()}\n style={{\n maxWidth: \"100%\",\n maxHeight: \"calc(100vh - 80px)\",\n borderRadius: \"8px\",\n objectFit: \"contain\",\n cursor: \"default\",\n }}\n />\n <span\n style={{\n marginTop: \"12px\",\n color: t.textMuted,\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>,\n document.body\n )}\n </>\n );\n}\n\n/* ─── Helpers ─── */\n\nfunction getTypeLabel(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Bug Report\";\n case \"FEATURE_REQUEST\": return \"Feature Request\";\n case \"QUESTION\": return \"Question\";\n case \"OTHER\": return \"Other\";\n }\n}\n\nfunction getTypeSubtitle(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Something isn't working\";\n case \"FEATURE_REQUEST\": return \"Suggest an improvement\";\n case \"QUESTION\": return \"Ask a question\";\n case \"OTHER\": return \"General feedback\";\n }\n}\n\nfunction getPlaceholder(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"What went wrong?\";\n case \"FEATURE_REQUEST\": return \"Describe the feature you'd like...\";\n case \"QUESTION\": return \"What would you like to know?\";\n case \"OTHER\": return \"Tell us what's on your mind...\";\n }\n}\n\nfunction getTypeIcon(type: ReportType, color: string, size = 24): ReactNode {\n const props = { width: size, height: size, viewBox: \"0 0 24 24\", fill: \"none\", style: { flexShrink: 0 } as CSSProperties };\n switch (type) {\n case \"BUG\":\n return <svg {...props}><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\" /></svg>;\n case \"FEATURE_REQUEST\":\n return <svg {...props}><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\" /></svg>;\n case \"QUESTION\":\n return <svg {...props}><circle cx=\"12\" cy=\"12\" r=\"10\" stroke={color} strokeWidth=\"1.5\" /><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\" /></svg>;\n case \"OTHER\":\n return <svg {...props}><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\" /></svg>;\n }\n}\n","\"use client\";\n\nimport { useState, type CSSProperties, type ReactNode } from \"react\";\nimport type { ReportButtonProps } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\n/** Safe version of useGlitchgrab that returns null when outside provider */\nfunction useGlitchgrabSafe() {\n try {\n return useGlitchgrab();\n } catch {\n return null;\n }\n}\n\n/**\n * Optional trigger button for opening the report dialog.\n *\n * The dialog itself lives inside `GlitchgrabProvider` — you don't need this component\n * unless you want a visible trigger button. You can also open the dialog programmatically\n * via `useGlitchgrab().openReportDialog()`.\n *\n * @example\n * ```tsx\n * // Use the default floating button\n * <ReportButton />\n *\n * // Use your own trigger\n * <ReportButton>\n * {({ onClick }) => <button onClick={onClick}>Report</button>}\n * </ReportButton>\n *\n * // Or skip ReportButton entirely and use the hook\n * const { openReportDialog } = useGlitchgrab();\n * <button onClick={() => openReportDialog()}>Report</button>\n * ```\n */\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\n const glitchgrab = useGlitchgrabSafe();\n\n if (!glitchgrab) return null;\n\n const handleClick = async () => {\n setCapturing(true);\n glitchgrab.openReportDialog();\n setCapturing(false);\n };\n\n // Custom trigger via render prop\n if (children) {\n return <>{children({ onClick: handleClick, capturing })}</>;\n }\n\n // Default floating button\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const positionStyles: CSSProperties = {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"16px\" } : { bottom: \"16px\" }),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={capturing}\n className={className}\n style={{\n position: \"fixed\",\n ...positionStyles,\n zIndex: 99999,\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n backgroundColor: \"#18181b\",\n color: \"#fafafa\",\n fontSize: \"14px\",\n fontWeight: 500,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n cursor: capturing ? \"wait\" : \"pointer\",\n boxShadow:\n \"0 4px 12px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.1)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n opacity: capturing ? 0.7 : 1,\n }}\n onMouseEnter={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1)\";\n }}\n aria-label={label}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n style={{ flexShrink: 0 }}\n >\n <path\n 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\"\n fill=\"currentColor\"\n />\n </svg>\n {capturing ? \"Capturing...\" : label}\n </button>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\n\nexport interface GlitchgrabReport {\n id: string;\n source: string;\n status: string;\n rawInput: string | null;\n reporterPrimaryKey: string;\n reporterName: string;\n reporterEmail: string | null;\n reporterPhone: string | null;\n pageUrl: string | null;\n createdAt: string;\n /** Number of comments on the linked GitHub issue (0 if no issue) */\n commentCount: number;\n issue: {\n githubNumber: number;\n githubUrl: string;\n title: string;\n labels: string[];\n severity: string | null;\n githubState: string | null;\n } | null;\n}\n\nconst BASE_URL = \"https://www.glitchgrab.dev\";\n\n/**\n * Hook to fetch bug reports for a specific user.\n *\n * ```tsx\n * const { reports, isLoading, error, refetch } = useGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * });\n * ```\n */\nexport function useGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n /** Max results (default 100, max 100) */\n limit?: number;\n}): {\n reports: GlitchgrabReport[];\n isLoading: boolean;\n isFetching: boolean;\n error: string | null;\n refetch: () => Promise<void>;\n} {\n const [reports, setReports] = useState<GlitchgrabReport[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const fetchReports = useCallback(async () => {\n if (!token || !userId) {\n setIsLoading(false);\n return;\n }\n\n setIsFetching(true);\n setError(null);\n\n try {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n\n if (data.success) {\n setReports(data.data ?? []);\n } else {\n setError(data.error ?? \"Failed to fetch reports\");\n }\n } catch {\n setError(\"Network error\");\n } finally {\n setIsLoading(false);\n setIsFetching(false);\n }\n }, [token, userId, limit]);\n\n useEffect(() => {\n fetchReports();\n }, [fetchReports]);\n\n return { reports, isLoading, isFetching, error, refetch: fetchReports };\n}\n\n/**\n * Standalone fetcher — use with TanStack Query or any data fetching library.\n *\n * ```tsx\n * const { data } = useQuery({\n * queryKey: [\"glitchgrab-reports\", userId],\n * queryFn: () => fetchGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * }),\n * });\n * ```\n */\nexport async function fetchGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n limit?: number;\n}): Promise<GlitchgrabReport[]> {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n if (!data.success) throw new Error(data.error ?? \"Failed to fetch reports\");\n return data.data ?? [];\n}\n\n// ─── Report Actions ─────────────────────────────────────\n\nasync function reportAction(\n token: string,\n reportId: string,\n body: Record<string, string>\n): Promise<void> {\n const res = await fetch(`${BASE_URL}/api/v1/reports/${reportId}/actions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n const data = await res.json().catch(() => ({}));\n if (!res.ok || !data.success) throw new Error(data.error ?? \"Action failed\");\n}\n\n/**\n * Hook to manage report actions with loading/error states.\n *\n * ```tsx\n * const { approve, reject, close, isPending, error } = useGlitchgrabActions({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * onSuccess: () => refetch(),\n * onError: (err) => toast.error(err.message),\n * });\n *\n * <button onClick={() => approve(reportId)} disabled={isPending}>\n * {isPending ? \"...\" : \"Approve\"}\n * </button>\n * ```\n */\nexport function useGlitchgrabActions({\n token,\n onSuccess,\n onError,\n}: {\n token: string;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n}) {\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const run = useCallback(\n async (reportId: string, body: Record<string, string>) => {\n setIsPending(true);\n setError(null);\n try {\n await reportAction(token, reportId, body);\n onSuccess?.();\n } catch (e) {\n const err = e instanceof Error ? e : new Error(\"Action failed\");\n setError(err.message);\n onError?.(err);\n } finally {\n setIsPending(false);\n }\n },\n [token, onSuccess, onError]\n );\n\n return {\n approve: (reportId: string) => run(reportId, { action: \"label\", label: \"approved\" }),\n reject: (reportId: string) => run(reportId, { action: \"label\", label: \"rejected\" }),\n close: (reportId: string) => run(reportId, { action: \"close\" }),\n reopen: (reportId: string) => run(reportId, { action: \"reopen\" }),\n label: (reportId: string, label: string) => run(reportId, { action: \"label\", label }),\n unlabel: (reportId: string, label: string) => run(reportId, { action: \"unlabel\", label }),\n isPending,\n error,\n };\n}\n"],"mappings":"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","names":["import_react","e","import_jsx_runtime","DEFAULT_BASE_URL","maxBreadcrumbs","addBreadcrumb","import_react","import_jsx_runtime","import_react"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/error-boundary.tsx","../src/breadcrumbs.ts","../src/utils.ts","../src/report-dialog.tsx","../src/report-button.tsx","../src/use-reports.ts"],"sourcesContent":["\"use client\";\n\n// ─── Core (required) ─────────────────────────────────────\nexport { GlitchgrabProvider, useGlitchgrab } from \"./provider\";\n\n// ─── Optional Components ─────────────────────────────────\nexport { ReportButton } from \"./report-button\";\nexport { GlitchgrabErrorBoundary } from \"./error-boundary\";\n\n// ─── Hooks ──────────────────────────────────────────────\nexport { useGlitchgrabReports, fetchGlitchgrabReports, useGlitchgrabActions } from \"./use-reports\";\nexport type { GlitchgrabReport } from \"./use-reports\";\n\n// ─── Breadcrumbs ─────────────────────────────────────────\nexport {\n addBreadcrumb,\n getBreadcrumbs,\n clearBreadcrumbs,\n initBreadcrumbs,\n} from \"./breadcrumbs\";\n\n// ─── Utilities ───────────────────────────────────────────\nexport { sanitizeUrl, captureContext, captureDeviceInfo, sendReport } from \"./utils\";\n\n// ─── Types ───────────────────────────────────────────────\nexport type {\n GlitchgrabConfig,\n GlitchgrabProviderProps,\n ReportPayload,\n ReportResult,\n ReportType,\n ReportSeverity,\n CapturedContext,\n DeviceInfo,\n Breadcrumb,\n BreadcrumbType,\n UseGlitchgrabReturn,\n ReportButtonProps,\n GlitchgrabSession,\n} from \"./types\";\n","\"use client\";\n\nimport {\n createContext,\n useContext,\n useRef,\n useEffect,\n useCallback,\n useState,\n} from \"react\";\nimport type {\n GlitchgrabProviderProps,\n UseGlitchgrabReturn,\n ReportPayload,\n ReportResult,\n ReportType,\n} from \"./types\";\nimport { GlitchgrabErrorBoundary } from \"./error-boundary\";\nimport { ReportDialog } from \"./report-dialog\";\nimport { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\n\nconst GlitchgrabContext = createContext<UseGlitchgrabReturn | null>(null);\n\n/**\n * Hook to access Glitchgrab in your components.\n *\n * @example\n * ```tsx\n * const { reportBug, report, addBreadcrumb } = useGlitchgrab();\n *\n * // Report a bug\n * reportBug(\"Login button crashes on mobile\");\n *\n * // Report a feature request\n * report(\"FEATURE_REQUEST\", \"Add dark mode\");\n *\n * // Add a custom breadcrumb\n * addBreadcrumb(\"User clicked checkout\", { cartItems: \"3\" });\n * ```\n */\nexport function useGlitchgrab(): UseGlitchgrabReturn {\n const ctx = useContext(GlitchgrabContext);\n if (!ctx) {\n throw new Error(\"useGlitchgrab must be used within a GlitchgrabProvider\");\n }\n return ctx;\n}\n\nfunction GlitchgrabProviderInner({\n token,\n session,\n baseUrl,\n onError,\n onReportSent,\n breadcrumbs: enableBreadcrumbs = true,\n maxBreadcrumbs = 50,\n children,\n fallback,\n types,\n showSeverity,\n}: GlitchgrabProviderProps) {\n const visitedPagesRef = useRef<string[]>([]);\n\n // Initialize breadcrumbs\n useEffect(() => {\n if (enableBreadcrumbs) {\n initBreadcrumbs(maxBreadcrumbs);\n }\n }, [enableBreadcrumbs, maxBreadcrumbs]);\n\n // Track page visits\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n\n const trackPage = () => {\n try {\n const sanitized = sanitizeUrl(window.location.href);\n const pages = visitedPagesRef.current;\n if (pages[pages.length - 1] !== sanitized) {\n pages.push(sanitized);\n if (pages.length > 20) {\n pages.splice(0, pages.length - 20);\n }\n }\n } catch {\n // Silently fail\n }\n };\n\n trackPage();\n const handlePopState = () => trackPage();\n window.addEventListener(\"popstate\", handlePopState);\n\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPushState(...args);\n trackPage();\n };\n history.replaceState = function (...args) {\n origReplaceState(...args);\n trackPage();\n };\n\n return () => {\n window.removeEventListener(\"popstate\", handlePopState);\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n };\n } catch {\n // Never crash\n }\n }, []);\n\n // Unhandled errors and rejections — skip in development\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n if (process.env.NODE_ENV === \"development\") return;\n\n const handleError = (event: ErrorEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: event.message,\n errorStack: event.error?.stack,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n filename: event.filename ?? \"\",\n lineno: String(event.lineno ?? \"\"),\n colno: String(event.colno ?? \"\"),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && event.error) onError(event.error);\n } catch {\n // Silently fail\n }\n };\n\n const handleRejection = (event: PromiseRejectionEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const reason = event.reason;\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: reason instanceof Error ? reason.message : String(reason),\n errorStack: reason instanceof Error ? reason.stack : undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n type: \"unhandledrejection\",\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && reason instanceof Error) onError(reason);\n } catch {\n // Silently fail\n }\n };\n\n window.addEventListener(\"error\", handleError);\n window.addEventListener(\"unhandledrejection\", handleRejection);\n\n return () => {\n window.removeEventListener(\"error\", handleError);\n window.removeEventListener(\"unhandledrejection\", handleRejection);\n };\n } catch {\n // Never crash\n }\n }, [token, baseUrl, onError, onReportSent]);\n\n const report = useCallback(\n async (\n type: ReportType,\n description: string,\n metadata?: Record<string, string>\n ): Promise<ReportResult | null> => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_USER_REPORT\",\n type,\n description,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n ...(session?.phone ? { sessionUserPhone: String(session.phone) } : {}),\n ...metadata,\n },\n };\n const result = await sendReport(payload, baseUrl);\n if (result && onReportSent) onReportSent(result);\n return result;\n } catch {\n return null;\n }\n },\n [token, baseUrl, onReportSent, session]\n );\n\n const reportBug = useCallback(\n (description: string, metadata?: Record<string, string>) =>\n report(\"BUG\", description, metadata),\n [report]\n );\n\n const addBreadcrumb = useCallback(\n (message: string, data?: Record<string, string>) => {\n addBreadcrumbInternal(\"custom\", message, data);\n },\n []\n );\n\n const openReportDialog = useCallback((options?: { description?: string; type?: ReportType }) => {\n if (typeof window !== \"undefined\") {\n window.dispatchEvent(new CustomEvent(\"glitchgrab:open-report\", { detail: options }));\n }\n }, []);\n\n return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\n openReportDialog,\n }}\n >\n <GlitchgrabErrorBoundary\n token={token}\n baseUrl={baseUrl}\n onError={onError}\n fallback={fallback}\n visitedPages={visitedPagesRef.current}\n >\n {children}\n </GlitchgrabErrorBoundary>\n <ReportDialog report={report} types={types} showSeverity={showSeverity} />\n </GlitchgrabContext.Provider>\n );\n}\n\nexport function GlitchgrabProvider(props: GlitchgrabProviderProps) {\n // No token = passthrough (SDK disabled)\n if (!props.token) return <>{props.children}</>;\n\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || DEFAULT_BASE_URL,\n };\n\n try {\n return <GlitchgrabProviderInner {...resolvedProps} />;\n } catch {\n return <>{props.children}</>;\n }\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport type { ReportPayload } from \"./types\";\nimport { captureContext, sendReport } from \"./utils\";\n\ninterface ErrorBoundaryProps {\n token: string;\n baseUrl?: string;\n onError?: (error: Error) => void;\n fallback?: React.ReactNode;\n visitedPages: string[];\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n}\n\nexport class GlitchgrabErrorBoundary extends React.Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false };\n }\n\n static getDerivedStateFromError(): ErrorBoundaryState {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n try {\n const context = captureContext(this.props.visitedPages);\n\n const payload: ReportPayload = {\n token: this.props.token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: error.message,\n errorStack: error.stack,\n componentStack: errorInfo.componentStack ?? undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n },\n };\n\n sendReport(payload, this.props.baseUrl);\n\n if (this.props.onError) {\n this.props.onError(error);\n }\n } catch {\n // Never crash the host app\n }\n }\n\n render(): React.ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n // Re-render children — allows recovery from transient errors\n return this.props.children;\n }\n\n return this.props.children;\n }\n}\n","import type { Breadcrumb, BreadcrumbType } from \"./types\";\n\nconst MAX_DEFAULT = 50;\n\nlet breadcrumbs: Breadcrumb[] = [];\nlet maxBreadcrumbs = MAX_DEFAULT;\nlet initialized = false;\n\nexport function initBreadcrumbs(max?: number) {\n if (initialized) return;\n maxBreadcrumbs = max ?? MAX_DEFAULT;\n\n try {\n if (typeof window === \"undefined\") return;\n interceptConsole();\n interceptFetch();\n interceptNavigation();\n interceptClicks();\n initialized = true;\n } catch {\n // Never crash\n }\n}\n\nexport function addBreadcrumb(\n type: BreadcrumbType,\n message: string,\n data?: Record<string, string>\n) {\n try {\n breadcrumbs.push({\n type,\n message: message.slice(0, 200),\n timestamp: new Date().toISOString(),\n data,\n });\n if (breadcrumbs.length > maxBreadcrumbs) {\n breadcrumbs = breadcrumbs.slice(-maxBreadcrumbs);\n }\n } catch {\n // Never crash\n }\n}\n\nexport function getBreadcrumbs(): Breadcrumb[] {\n return [...breadcrumbs];\n}\n\nexport function clearBreadcrumbs() {\n breadcrumbs = [];\n}\n\n// ─── Console Interception ────────────────────────────────\n\nfunction interceptConsole() {\n const origLog = console.log;\n const origWarn = console.warn;\n const origError = console.error;\n\n console.log = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[log] ${argsToString(args)}`);\n origLog.apply(console, args);\n };\n\n console.warn = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[warn] ${argsToString(args)}`);\n origWarn.apply(console, args);\n };\n\n console.error = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[error] ${argsToString(args)}`);\n origError.apply(console, args);\n };\n}\n\nfunction argsToString(args: unknown[]): string {\n try {\n return args\n .map((a) => {\n if (typeof a === \"string\") return a;\n if (a instanceof Error) return a.message;\n try {\n return JSON.stringify(a);\n } catch {\n return String(a);\n }\n })\n .join(\" \")\n .slice(0, 200);\n } catch {\n return \"[unknown]\";\n }\n}\n\n// ─── Fetch Interception ──────────────────────────────────\n\nfunction interceptFetch() {\n const origFetch = window.fetch;\n\n window.fetch = async function (input, init) {\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input instanceof Request\n ? input.url\n : String(input);\n const method = init?.method ?? \"GET\";\n const start = Date.now();\n\n try {\n const response = await origFetch.apply(window, [input, init]);\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → ${response.status}`, {\n method,\n status: String(response.status),\n duration: `${Date.now() - start}ms`,\n });\n return response;\n } catch (err) {\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → FAILED`, {\n method,\n error: err instanceof Error ? err.message : \"unknown\",\n duration: `${Date.now() - start}ms`,\n });\n throw err;\n }\n };\n}\n\n// ─── Navigation Interception ─────────────────────────────\n\nfunction interceptNavigation() {\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPush(...args);\n addBreadcrumb(\"navigation\", `Navigate to ${window.location.pathname}`);\n };\n\n history.replaceState = function (...args) {\n origReplace(...args);\n addBreadcrumb(\"navigation\", `Replace to ${window.location.pathname}`);\n };\n\n window.addEventListener(\"popstate\", () => {\n addBreadcrumb(\"navigation\", `Back/Forward to ${window.location.pathname}`);\n });\n}\n\n// ─── Click Interception ──────────────────────────────────\n\nfunction interceptClicks() {\n document.addEventListener(\n \"click\",\n (e) => {\n try {\n const target = e.target as HTMLElement;\n const tag = target.tagName?.toLowerCase();\n const text = target.textContent?.trim().slice(0, 50) ?? \"\";\n const id = target.id ? `#${target.id}` : \"\";\n const cls = target.className && typeof target.className === \"string\"\n ? `.${target.className.split(\" \")[0]}`\n : \"\";\n\n addBreadcrumb(\"click\", `Click ${tag}${id}${cls} \"${text}\"`);\n } catch {\n // Never crash\n }\n },\n { capture: true }\n );\n}\n","import type { ReportPayload, ReportResult, CapturedContext, DeviceInfo } from \"./types\";\nimport { getBreadcrumbs } from \"./breadcrumbs\";\n\nconst SENSITIVE_PARAMS = [\n \"token\", \"key\", \"secret\", \"password\", \"passwd\", \"auth\", \"authorization\",\n \"session\", \"sessionid\", \"session_id\", \"api_key\", \"apikey\", \"access_token\",\n \"refresh_token\", \"client_secret\", \"code\", \"state\", \"nonce\", \"credential\", \"private\",\n];\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n const params = new URLSearchParams(parsed.search);\n let modified = false;\n for (const key of Array.from(params.keys())) {\n if (SENSITIVE_PARAMS.some((s) => key.toLowerCase().includes(s))) {\n params.set(key, \"[REDACTED]\");\n modified = true;\n }\n }\n if (modified) parsed.search = params.toString();\n return parsed.toString();\n } catch {\n return url.split(\"?\")[0] ?? url;\n }\n}\n\nexport function captureDeviceInfo(): DeviceInfo | null {\n try {\n if (typeof window === \"undefined\") return null;\n return {\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n platform: navigator.platform ?? \"unknown\",\n language: navigator.language ?? \"unknown\",\n online: navigator.onLine,\n colorScheme: window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\",\n devicePixelRatio: window.devicePixelRatio ?? 1,\n };\n } catch {\n return null;\n }\n}\n\nexport function captureContext(visitedPages: string[]): CapturedContext {\n try {\n return {\n url: sanitizeUrl(typeof window !== \"undefined\" ? window.location.href : \"\"),\n userAgent: typeof navigator !== \"undefined\" ? navigator.userAgent : \"\",\n timestamp: new Date().toISOString(),\n visitedPages: visitedPages.map(sanitizeUrl),\n breadcrumbs: getBreadcrumbs(),\n deviceInfo: captureDeviceInfo(),\n };\n } catch {\n return {\n url: \"\",\n userAgent: \"\",\n timestamp: new Date().toISOString(),\n visitedPages: [],\n breadcrumbs: [],\n deviceInfo: null,\n };\n }\n}\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\nconst MAX_RETRIES = 3;\nconst RETRY_BASE_MS = 500;\n\n/**\n * Send a report and return the result.\n * Never throws — returns null on failure.\n */\nexport async function sendReport(\n payload: ReportPayload,\n baseUrl?: string\n): Promise<ReportResult | null> {\n try {\n const url = `${baseUrl ?? DEFAULT_BASE_URL}/api/v1/sdk/report`;\n const body = JSON.stringify(payload);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${payload.token}`,\n };\n\n // keepalive has a 64KB body limit in browsers — skip it for large payloads (e.g., screenshots)\n const useKeepalive = body.length < 60_000;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n ...(useKeepalive ? { keepalive: true } : {}),\n });\n\n if (response.ok) {\n const data = (await response.json()) as { success: boolean; data?: ReportResult };\n return data.data ?? { success: data.success };\n }\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n return null;\n }\n } catch {\n // Will retry\n }\n\n if (attempt < MAX_RETRIES - 1) {\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_BASE_MS * Math.pow(2, attempt))\n );\n }\n }\n\n // Fallback: sendBeacon (fire-and-forget, no result)\n if (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n try {\n navigator.sendBeacon(url, new Blob([body], { type: \"application/json\" }));\n } catch {\n // Silently fail\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect, type CSSProperties, type ReactNode } from \"react\";\n// @ts-expect-error react-dom types handled by host app\nimport { createPortal } from \"react-dom\";\nimport type { ReportType, ReportSeverity, UseGlitchgrabReturn } from \"./types\";\n\n/** Detect if the host page uses a dark or light theme */\nfunction useIsDark(): boolean {\n if (typeof window === \"undefined\") return true;\n try {\n const bg = getComputedStyle(document.body).backgroundColor;\n const match = bg.match(/\\d+/g);\n if (match && match.length >= 3) {\n const [r, g, b] = match.map(Number);\n return (r * 299 + g * 587 + b * 114) / 1000 < 128;\n }\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n } catch {\n return true;\n }\n}\n\nfunction getTheme(dark: boolean) {\n return dark\n ? { bg: \"#1c1c1e\", bgSecondary: \"#27272a\", border: \"#2c2c2e\", text: \"#fafafa\", textMuted: \"#a1a1aa\", accent: \"#22d3ee\", accentText: \"#09090b\", inputBg: \"#27272a\", inputBorder: \"#3f3f46\" }\n : { bg: \"#ffffff\", bgSecondary: \"#f4f4f5\", border: \"#e4e4e7\", text: \"#18181b\", textMuted: \"#71717a\", accent: \"#0891b2\", accentText: \"#ffffff\", inputBg: \"#fafafa\", inputBorder: \"#d4d4d8\" };\n}\n\n/** Validate that report text is meaningful — rejects gibberish, throwaway words, random chars */\nfunction isLowQualityText(text: string): string | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n\n const throwaway =\n /^(done|ok|yes|no|hi|hello|hey|test|testing|asdf|qwerty|abc|xyz|foo|bar|baz|lol|lmao|idk|bruh|nice|cool|wow|sup|yo|nah|yep|nope|thanks|thx|ty|k|kk|hmm|hm|na|mm|mhm|aight|bet|gg|wp|rip|omg|pls|plz)$/i;\n if (throwaway.test(trimmed)) {\n return \"Please describe the actual issue you're experiencing\";\n }\n\n if (/(.)\\1{4,}/.test(trimmed)) {\n return \"Please provide a meaningful description\";\n }\n\n const letters = trimmed.replace(/[^a-zA-Z]/g, \"\");\n if (letters.length >= 4) {\n const vowels = letters.replace(/[^aeiouAEIOU]/g, \"\").length;\n const vowelRatio = vowels / letters.length;\n if (vowelRatio < 0.08) {\n return \"That doesn't look like a valid description\";\n }\n }\n\n const words = trimmed.split(/\\s+/).filter((w) => w.length > 0);\n if (words.length === 1 && trimmed.length < 10) {\n const techTerms =\n /^(crash|error|bug|fail|broken|slow|freeze|lag|404|500|null|undefined|nan|timeout|overflow|leak|cors|oom)$/i;\n if (!techTerms.test(trimmed)) {\n return \"Please provide more detail about the issue\";\n }\n }\n\n return null;\n}\n\ninterface ReportDialogProps {\n report: UseGlitchgrabReturn[\"report\"];\n types?: ReportType[];\n showSeverity?: boolean;\n}\n\n/**\n * The report dialog — rendered inside GlitchgrabProvider automatically.\n * Opens via the `glitchgrab:open-report` custom event (triggered by `openReportDialog()`).\n */\nexport function ReportDialog({\n report,\n types,\n showSeverity = true,\n}: ReportDialogProps) {\n // Prevent hydration mismatch — render nothing until after hydration\n const [mounted, setMounted] = useState(false);\n useEffect(() => { setMounted(true); }, []);\n\n const [isOpen, setIsOpen] = useState(false);\n const [description, setDescription] = useState(\"\");\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n const [screenshot, setScreenshot] = useState<string | null>(null);\n const [previewOpen, setPreviewOpen] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDivElement>(null);\n\n // Stepper state\n const [step, setStep] = useState(1);\n const [reportType, setReportType] = useState<ReportType>(\"BUG\");\n const [severity, setSeverity] = useState<ReportSeverity>(\"medium\");\n const [validationError, setValidationError] = useState<string | null>(null);\n\n const availableTypes: ReportType[] = types ?? [\"BUG\", \"FEATURE_REQUEST\", \"QUESTION\", \"OTHER\"];\n\n const isDark = useIsDark();\n const t = getTheme(isDark);\n\n const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => {\n setScreenshot(reader.result as string);\n };\n reader.readAsDataURL(file);\n e.target.value = \"\";\n };\n\n const retakeScreenshot = async () => {\n setPreviewOpen(false);\n setIsOpen(false);\n setScreenshot(null);\n await new Promise((r) => setTimeout(r, 300));\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // silently fail\n }\n setIsOpen(true);\n };\n\n const handleOpen = async () => {\n setSubmitted(false);\n if (availableTypes.length === 1) {\n setReportType(availableTypes[0]);\n setStep(2);\n }\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // screenshot failed — open without it\n }\n setIsOpen(true);\n };\n\n // Listen for programmatic open via openReportDialog()\n useEffect(() => {\n const handler = (e: Event) => {\n if (isOpen) return;\n const detail = (e as CustomEvent).detail;\n if (detail?.description) setDescription(detail.description);\n if (detail?.type) {\n setReportType(detail.type);\n setStep(2);\n }\n handleOpen();\n };\n window.addEventListener(\"glitchgrab:open-report\", handler);\n return () => window.removeEventListener(\"glitchgrab:open-report\", handler);\n }, [isOpen, handleOpen]);\n\n // Close on Escape\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleClose = () => {\n setIsOpen(false);\n setStep(1);\n setReportType(\"BUG\");\n setSeverity(\"medium\");\n setValidationError(null);\n };\n\n const handleSubmit = async () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n const qualityError = isLowQualityText(description);\n if (qualityError) {\n setValidationError(qualityError);\n setStep(2);\n return;\n }\n\n setIsSubmitting(true);\n const metadata: Record<string, string> = {};\n if (screenshot) metadata.screenshot = screenshot;\n if (showSeverity && reportType === \"BUG\") {\n metadata.severity = severity;\n }\n\n const result = await report(reportType, description.trim(), Object.keys(metadata).length > 0 ? metadata : undefined);\n\n if (result) {\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n\n setTimeout(() => {\n setSubmitted(false);\n handleClose();\n }, 2000);\n }\n setIsSubmitting(false);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n if (!mounted) return null;\n\n return (\n <>\n {/* Report modal */}\n {isOpen && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n onClick={() => { if (!previewOpen) handleClose(); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: \"relative\",\n zIndex: 2147483647,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: t.bg,\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: t.text,\n isolation: \"isolate\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: `1px solid ${t.border}`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"8px\" }}>\n {step > 1 && (\n <button\n type=\"button\"\n onClick={() => setStep((s) => (s - 1) as 1 | 2 | 3)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n aria-label=\"Back\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M10 3L5 8L10 13\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n )}\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: t.text,\n }}\n >\n {step === 1 ? \"What's on your mind?\" : step === 2 ? \"Tell us more\" : \"Review & Send\"}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Close\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" style={{ display: \"block\" }}>\n <path d=\"M4 4L12 12M12 4L4 12\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"center\", gap: \"0\", marginTop: \"12px\" }}>\n {[1, 2, 3].map((s, i) => (\n <div key={s} style={{ display: \"flex\", alignItems: \"center\" }}>\n <div style={{\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: s <= step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n {i < 2 && (\n <div style={{\n width: \"40px\",\n height: \"2px\",\n backgroundColor: s < step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n )}\n </div>\n ))}\n </div>\n </div>\n\n {/* Body */}\n <div style={{ padding: \"16px\" }}>\n {submitted ? (\n <div\n style={{\n textAlign: \"center\",\n padding: \"20px 0\",\n color: t.accent,\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n {getTypeLabel(reportType)} sent. Thank you!\n </div>\n ) : (\n <>\n {/* Step 1: Category */}\n {step === 1 && (\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: \"8px\" }}>\n {availableTypes.map((type) => (\n <button\n key={type}\n type=\"button\"\n onClick={() => {\n setReportType(type);\n setStep(2);\n }}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"16px 8px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n background: t.inputBg,\n cursor: \"pointer\",\n color: t.text,\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s ease\",\n }}\n onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.accent; }}\n onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.inputBorder; }}\n >\n {getTypeIcon(type, t.accent)}\n <span style={{ fontSize: \"13px\", fontWeight: 600 }}>{getTypeLabel(type)}</span>\n <span style={{ fontSize: \"11px\", color: t.textMuted, lineHeight: \"1.3\" }}>{getTypeSubtitle(type)}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* Step 2: Details */}\n {step === 2 && (\n <>\n <textarea\n value={description}\n onChange={(e) => { setDescription(e.target.value); if (validationError) setValidationError(null); }}\n placeholder={getPlaceholder(reportType)}\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: t.text,\n backgroundColor: t.inputBg,\n }}\n onFocus={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.accent; }}\n onBlur={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.inputBorder; }}\n autoFocus\n />\n {showSeverity && reportType === \"BUG\" && (\n <div style={{ marginTop: \"10px\" }}>\n <span style={{ fontSize: \"12px\", color: t.textMuted, marginBottom: \"6px\", display: \"block\" }}>Severity</span>\n <div style={{ display: \"flex\", gap: \"6px\" }}>\n {([\"low\", \"medium\", \"high\"] as ReportSeverity[]).map((s) => (\n <button\n key={s}\n type=\"button\"\n onClick={() => setSeverity(s)}\n style={{\n flex: 1,\n padding: \"6px 0\",\n borderRadius: \"6px\",\n border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,\n background: severity === s ? t.accent : \"transparent\",\n color: severity === s ? t.accentText : t.text,\n fontSize: \"12px\",\n fontWeight: 600,\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n textTransform: \"capitalize\",\n transition: \"all 0.15s ease\",\n }}\n >\n {s}\n </button>\n ))}\n </div>\n </div>\n )}\n {validationError && (\n <p style={{ color: \"#ef4444\", fontSize: \"12px\", marginTop: \"6px\" }}>\n {validationError}\n </p>\n )}\n <button\n type=\"button\"\n onClick={() => {\n const err = isLowQualityText(description);\n if (err) { setValidationError(err); return; }\n setValidationError(null);\n setStep(3);\n }}\n disabled={!description.trim()}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: !description.trim() ? t.bgSecondary : t.accent,\n color: !description.trim() ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: !description.trim() ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n Next\n </button>\n </>\n )}\n\n {/* Step 3: Review & Send */}\n {step === 3 && (\n <>\n {/* Summary chips */}\n <div style={{ display: \"flex\", gap: \"6px\", flexWrap: \"wrap\", marginBottom: \"12px\" }}>\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"4px\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: t.bgSecondary,\n color: t.text,\n border: `1px solid ${t.border}`,\n }}>\n {getTypeIcon(reportType, t.accent, 12)}\n {getTypeLabel(reportType)}\n </span>\n {showSeverity && reportType === \"BUG\" && (\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: severity === \"high\" ? \"#fef2f2\" : severity === \"medium\" ? \"#fffbeb\" : \"#f0fdf4\",\n color: severity === \"high\" ? \"#dc2626\" : severity === \"medium\" ? \"#d97706\" : \"#16a34a\",\n border: `1px solid ${severity === \"high\" ? \"#fecaca\" : severity === \"medium\" ? \"#fde68a\" : \"#bbf7d0\"}`,\n textTransform: \"capitalize\",\n }}>\n {severity}\n </span>\n )}\n </div>\n\n {/* Description preview */}\n <div style={{\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n backgroundColor: t.inputBg,\n fontSize: \"13px\",\n color: t.text,\n marginBottom: \"10px\",\n maxHeight: \"80px\",\n overflow: \"hidden\",\n lineHeight: \"1.4\",\n }}>\n {description.length > 200 ? description.slice(0, 200) + \"...\" : description}\n </div>\n\n {/* Screenshot */}\n {screenshot && (\n <div style={{ marginBottom: \"10px\", position: \"relative\" }}>\n <img\n src={screenshot}\n alt=\"Page screenshot\"\n onClick={() => setPreviewOpen(true)}\n style={{\n width: \"100%\",\n borderRadius: \"6px\",\n border: `1px solid ${t.border}`,\n maxHeight: \"80px\",\n objectFit: \"cover\",\n objectPosition: \"top\",\n cursor: \"pointer\",\n }}\n />\n <button\n type=\"button\"\n onClick={() => setScreenshot(null)}\n style={{\n position: \"absolute\",\n top: \"4px\",\n right: \"4px\",\n background: \"rgba(0,0,0,0.6)\",\n border: \"none\",\n borderRadius: \"50%\",\n width: \"20px\",\n height: \"20px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Remove screenshot\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M1 1L9 9M9 1L1 9\" stroke=\"#fff\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n )}\n {!screenshot && (\n <div style={{ display: \"flex\", gap: \"6px\", marginBottom: \"10px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload screenshot\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake screenshot\n </button>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={isSubmitting}\n style={{\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: isSubmitting ? t.bgSecondary : t.accent,\n color: isSubmitting ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: isSubmitting ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: `1px solid ${t.border}`,\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: t.textMuted }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>,\n document.body\n )}\n\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileUpload}\n style={{ display: \"none\" }}\n />\n\n {/* Full-screen screenshot preview */}\n {previewOpen && screenshot && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n backgroundColor: \"rgba(0,0,0,0.85)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"16px\",\n cursor: \"pointer\",\n }}\n onClick={(e) => { e.stopPropagation(); setPreviewOpen(false); }}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <img\n src={screenshot}\n alt=\"Screenshot preview\"\n onClick={(e) => e.stopPropagation()}\n style={{\n maxWidth: \"100%\",\n maxHeight: \"calc(100vh - 80px)\",\n borderRadius: \"8px\",\n objectFit: \"contain\",\n cursor: \"default\",\n }}\n />\n <span\n style={{\n marginTop: \"12px\",\n color: t.textMuted,\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>,\n document.body\n )}\n </>\n );\n}\n\n/* ─── Helpers ─── */\n\nfunction getTypeLabel(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Bug Report\";\n case \"FEATURE_REQUEST\": return \"Feature Request\";\n case \"QUESTION\": return \"Question\";\n case \"OTHER\": return \"Other\";\n }\n}\n\nfunction getTypeSubtitle(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Something isn't working\";\n case \"FEATURE_REQUEST\": return \"Suggest an improvement\";\n case \"QUESTION\": return \"Ask a question\";\n case \"OTHER\": return \"General feedback\";\n }\n}\n\nfunction getPlaceholder(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"What went wrong?\";\n case \"FEATURE_REQUEST\": return \"Describe the feature you'd like...\";\n case \"QUESTION\": return \"What would you like to know?\";\n case \"OTHER\": return \"Tell us what's on your mind...\";\n }\n}\n\nfunction getTypeIcon(type: ReportType, color: string, size = 24): ReactNode {\n const props = { width: size, height: size, viewBox: \"0 0 24 24\", fill: \"none\", style: { flexShrink: 0 } as CSSProperties };\n switch (type) {\n case \"BUG\":\n return <svg {...props}><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\" /></svg>;\n case \"FEATURE_REQUEST\":\n return <svg {...props}><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\" /></svg>;\n case \"QUESTION\":\n return <svg {...props}><circle cx=\"12\" cy=\"12\" r=\"10\" stroke={color} strokeWidth=\"1.5\" /><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\" /></svg>;\n case \"OTHER\":\n return <svg {...props}><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\" /></svg>;\n }\n}\n","\"use client\";\n\nimport { useState, type CSSProperties, type ReactNode } from \"react\";\nimport type { ReportButtonProps } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\n/** Safe version of useGlitchgrab that returns null when outside provider */\nfunction useGlitchgrabSafe() {\n try {\n return useGlitchgrab();\n } catch {\n return null;\n }\n}\n\n/**\n * Optional trigger button for opening the report dialog.\n *\n * The dialog itself lives inside `GlitchgrabProvider` — you don't need this component\n * unless you want a visible trigger button. You can also open the dialog programmatically\n * via `useGlitchgrab().openReportDialog()`.\n *\n * @example\n * ```tsx\n * // Use the default floating button\n * <ReportButton />\n *\n * // Use your own trigger\n * <ReportButton>\n * {({ onClick }) => <button onClick={onClick}>Report</button>}\n * </ReportButton>\n *\n * // Or skip ReportButton entirely and use the hook\n * const { openReportDialog } = useGlitchgrab();\n * <button onClick={() => openReportDialog()}>Report</button>\n * ```\n */\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\n const glitchgrab = useGlitchgrabSafe();\n\n if (!glitchgrab) return null;\n\n const handleClick = async () => {\n setCapturing(true);\n glitchgrab.openReportDialog();\n setCapturing(false);\n };\n\n // Custom trigger via render prop\n if (children) {\n return <>{children({ onClick: handleClick, capturing })}</>;\n }\n\n // Default floating button\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const positionStyles: CSSProperties = {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"16px\" } : { bottom: \"16px\" }),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={capturing}\n className={className}\n style={{\n position: \"fixed\",\n ...positionStyles,\n zIndex: 99999,\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n backgroundColor: \"#18181b\",\n color: \"#fafafa\",\n fontSize: \"14px\",\n fontWeight: 500,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n cursor: capturing ? \"wait\" : \"pointer\",\n boxShadow:\n \"0 4px 12px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.1)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n opacity: capturing ? 0.7 : 1,\n }}\n onMouseEnter={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1)\";\n }}\n aria-label={label}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n style={{ flexShrink: 0 }}\n >\n <path\n 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\"\n fill=\"currentColor\"\n />\n </svg>\n {capturing ? \"Capturing...\" : label}\n </button>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\n\nexport interface GlitchgrabReport {\n id: string;\n source: string;\n status: string;\n rawInput: string | null;\n reporterPrimaryKey: string;\n reporterName: string;\n reporterEmail: string | null;\n reporterPhone: string | null;\n pageUrl: string | null;\n createdAt: string;\n /** Number of comments on the linked GitHub issue (0 if no issue) */\n commentCount: number;\n issue: {\n githubNumber: number;\n githubUrl: string;\n title: string;\n labels: string[];\n severity: string | null;\n githubState: string | null;\n } | null;\n}\n\nconst BASE_URL = \"https://www.glitchgrab.dev\";\n\n/**\n * Hook to fetch bug reports for a specific user.\n *\n * ```tsx\n * const { reports, isLoading, error, refetch } = useGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * });\n * ```\n */\nexport function useGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n /** Max results (default 100, max 100) */\n limit?: number;\n}): {\n reports: GlitchgrabReport[];\n isLoading: boolean;\n isFetching: boolean;\n error: string | null;\n refetch: () => Promise<void>;\n} {\n const [reports, setReports] = useState<GlitchgrabReport[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const fetchReports = useCallback(async () => {\n if (!token || !userId) {\n setIsLoading(false);\n return;\n }\n\n setIsFetching(true);\n setError(null);\n\n try {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n\n if (data.success) {\n setReports(data.data ?? []);\n } else {\n setError(data.error ?? \"Failed to fetch reports\");\n }\n } catch {\n setError(\"Network error\");\n } finally {\n setIsLoading(false);\n setIsFetching(false);\n }\n }, [token, userId, limit]);\n\n useEffect(() => {\n fetchReports();\n }, [fetchReports]);\n\n return { reports, isLoading, isFetching, error, refetch: fetchReports };\n}\n\n/**\n * Standalone fetcher — use with TanStack Query or any data fetching library.\n *\n * ```tsx\n * const { data } = useQuery({\n * queryKey: [\"glitchgrab-reports\", userId],\n * queryFn: () => fetchGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * }),\n * });\n * ```\n */\nexport async function fetchGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n limit?: number;\n}): Promise<GlitchgrabReport[]> {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n if (!data.success) throw new Error(data.error ?? \"Failed to fetch reports\");\n return data.data ?? [];\n}\n\n// ─── Report Actions ─────────────────────────────────────\n\nasync function reportAction(\n token: string,\n reportId: string,\n body: Record<string, string>\n): Promise<void> {\n const res = await fetch(`${BASE_URL}/api/v1/reports/${reportId}/actions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n const data = await res.json().catch(() => ({}));\n if (!res.ok || !data.success) throw new Error(data.error ?? \"Action failed\");\n}\n\n/**\n * Hook to manage report actions with loading/error states.\n *\n * ```tsx\n * const { approve, reject, close, isPending, error } = useGlitchgrabActions({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * onSuccess: () => refetch(),\n * onError: (err) => toast.error(err.message),\n * });\n *\n * <button onClick={() => approve(reportId)} disabled={isPending}>\n * {isPending ? \"...\" : \"Approve\"}\n * </button>\n * ```\n */\nexport function useGlitchgrabActions({\n token,\n onSuccess,\n onError,\n}: {\n token: string;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n}) {\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const run = useCallback(\n async (reportId: string, body: Record<string, string>) => {\n setIsPending(true);\n setError(null);\n try {\n await reportAction(token, reportId, body);\n onSuccess?.();\n } catch (e) {\n const err = e instanceof Error ? e : new Error(\"Action failed\");\n setError(err.message);\n onError?.(err);\n } finally {\n setIsPending(false);\n }\n },\n [token, onSuccess, onError]\n );\n\n return {\n approve: (reportId: string) => run(reportId, { action: \"label\", label: \"approved\" }),\n reject: (reportId: string) => run(reportId, { action: \"label\", label: \"rejected\" }),\n close: (reportId: string) => run(reportId, { action: \"close\" }),\n reopen: (reportId: string) => run(reportId, { action: \"reopen\" }),\n label: (reportId: string, label: string) => run(reportId, { action: \"label\", label }),\n unlabel: (reportId: string, label: string) => run(reportId, { action: \"unlabel\", label }),\n isPending,\n error,\n };\n}\n"],"mappings":"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","names":["import_react","e","import_jsx_runtime","DEFAULT_BASE_URL","maxBreadcrumbs","addBreadcrumb","import_react","import_jsx_runtime","import_react"]}
|
package/dist/index.mjs
CHANGED
|
@@ -234,13 +234,14 @@ async function sendReport(payload, baseUrl) {
|
|
|
234
234
|
"Content-Type": "application/json",
|
|
235
235
|
Authorization: `Bearer ${payload.token}`
|
|
236
236
|
};
|
|
237
|
+
const useKeepalive = body.length < 6e4;
|
|
237
238
|
for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
|
|
238
239
|
try {
|
|
239
240
|
const response = await fetch(url, {
|
|
240
241
|
method: "POST",
|
|
241
242
|
headers,
|
|
242
243
|
body,
|
|
243
|
-
keepalive: true
|
|
244
|
+
...useKeepalive ? { keepalive: true } : {}
|
|
244
245
|
});
|
|
245
246
|
if (response.ok) {
|
|
246
247
|
const data = await response.json();
|
|
@@ -337,6 +338,33 @@ function useIsDark() {
|
|
|
337
338
|
function getTheme(dark) {
|
|
338
339
|
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" };
|
|
339
340
|
}
|
|
341
|
+
function isLowQualityText(text) {
|
|
342
|
+
const trimmed = text.trim();
|
|
343
|
+
if (!trimmed) return null;
|
|
344
|
+
const throwaway = /^(done|ok|yes|no|hi|hello|hey|test|testing|asdf|qwerty|abc|xyz|foo|bar|baz|lol|lmao|idk|bruh|nice|cool|wow|sup|yo|nah|yep|nope|thanks|thx|ty|k|kk|hmm|hm|na|mm|mhm|aight|bet|gg|wp|rip|omg|pls|plz)$/i;
|
|
345
|
+
if (throwaway.test(trimmed)) {
|
|
346
|
+
return "Please describe the actual issue you're experiencing";
|
|
347
|
+
}
|
|
348
|
+
if (/(.)\1{4,}/.test(trimmed)) {
|
|
349
|
+
return "Please provide a meaningful description";
|
|
350
|
+
}
|
|
351
|
+
const letters = trimmed.replace(/[^a-zA-Z]/g, "");
|
|
352
|
+
if (letters.length >= 4) {
|
|
353
|
+
const vowels = letters.replace(/[^aeiouAEIOU]/g, "").length;
|
|
354
|
+
const vowelRatio = vowels / letters.length;
|
|
355
|
+
if (vowelRatio < 0.08) {
|
|
356
|
+
return "That doesn't look like a valid description";
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const words = trimmed.split(/\s+/).filter((w) => w.length > 0);
|
|
360
|
+
if (words.length === 1 && trimmed.length < 10) {
|
|
361
|
+
const techTerms = /^(crash|error|bug|fail|broken|slow|freeze|lag|404|500|null|undefined|nan|timeout|overflow|leak|cors|oom)$/i;
|
|
362
|
+
if (!techTerms.test(trimmed)) {
|
|
363
|
+
return "Please provide more detail about the issue";
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
return null;
|
|
367
|
+
}
|
|
340
368
|
function ReportDialog({
|
|
341
369
|
report,
|
|
342
370
|
types,
|
|
@@ -357,6 +385,7 @@ function ReportDialog({
|
|
|
357
385
|
const [step, setStep] = useState(1);
|
|
358
386
|
const [reportType, setReportType] = useState("BUG");
|
|
359
387
|
const [severity, setSeverity] = useState("medium");
|
|
388
|
+
const [validationError, setValidationError] = useState(null);
|
|
360
389
|
const availableTypes = types != null ? types : ["BUG", "FEATURE_REQUEST", "QUESTION", "OTHER"];
|
|
361
390
|
const isDark = useIsDark();
|
|
362
391
|
const t = getTheme(isDark);
|
|
@@ -438,10 +467,17 @@ function ReportDialog({
|
|
|
438
467
|
setStep(1);
|
|
439
468
|
setReportType("BUG");
|
|
440
469
|
setSeverity("medium");
|
|
470
|
+
setValidationError(null);
|
|
441
471
|
};
|
|
442
472
|
const handleSubmit = async () => {
|
|
443
473
|
try {
|
|
444
474
|
if (!description.trim() || isSubmitting) return;
|
|
475
|
+
const qualityError = isLowQualityText(description);
|
|
476
|
+
if (qualityError) {
|
|
477
|
+
setValidationError(qualityError);
|
|
478
|
+
setStep(2);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
445
481
|
setIsSubmitting(true);
|
|
446
482
|
const metadata = {};
|
|
447
483
|
if (screenshot) metadata.screenshot = screenshot;
|
|
@@ -644,7 +680,10 @@ function ReportDialog({
|
|
|
644
680
|
"textarea",
|
|
645
681
|
{
|
|
646
682
|
value: description,
|
|
647
|
-
onChange: (e) =>
|
|
683
|
+
onChange: (e) => {
|
|
684
|
+
setDescription(e.target.value);
|
|
685
|
+
if (validationError) setValidationError(null);
|
|
686
|
+
},
|
|
648
687
|
placeholder: getPlaceholder(reportType),
|
|
649
688
|
style: {
|
|
650
689
|
width: "100%",
|
|
@@ -695,11 +734,20 @@ function ReportDialog({
|
|
|
695
734
|
s
|
|
696
735
|
)) })
|
|
697
736
|
] }),
|
|
737
|
+
validationError && /* @__PURE__ */ jsx("p", { style: { color: "#ef4444", fontSize: "12px", marginTop: "6px" }, children: validationError }),
|
|
698
738
|
/* @__PURE__ */ jsx(
|
|
699
739
|
"button",
|
|
700
740
|
{
|
|
701
741
|
type: "button",
|
|
702
|
-
onClick: () =>
|
|
742
|
+
onClick: () => {
|
|
743
|
+
const err = isLowQualityText(description);
|
|
744
|
+
if (err) {
|
|
745
|
+
setValidationError(err);
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
setValidationError(null);
|
|
749
|
+
setStep(3);
|
|
750
|
+
},
|
|
703
751
|
disabled: !description.trim(),
|
|
704
752
|
style: {
|
|
705
753
|
marginTop: "12px",
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.tsx","../src/error-boundary.tsx","../src/breadcrumbs.ts","../src/utils.ts","../src/report-dialog.tsx","../src/report-button.tsx","../src/use-reports.ts"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useRef,\n useEffect,\n useCallback,\n useState,\n} from \"react\";\nimport type {\n GlitchgrabProviderProps,\n UseGlitchgrabReturn,\n ReportPayload,\n ReportResult,\n ReportType,\n} from \"./types\";\nimport { GlitchgrabErrorBoundary } from \"./error-boundary\";\nimport { ReportDialog } from \"./report-dialog\";\nimport { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\n\nconst GlitchgrabContext = createContext<UseGlitchgrabReturn | null>(null);\n\n/**\n * Hook to access Glitchgrab in your components.\n *\n * @example\n * ```tsx\n * const { reportBug, report, addBreadcrumb } = useGlitchgrab();\n *\n * // Report a bug\n * reportBug(\"Login button crashes on mobile\");\n *\n * // Report a feature request\n * report(\"FEATURE_REQUEST\", \"Add dark mode\");\n *\n * // Add a custom breadcrumb\n * addBreadcrumb(\"User clicked checkout\", { cartItems: \"3\" });\n * ```\n */\nexport function useGlitchgrab(): UseGlitchgrabReturn {\n const ctx = useContext(GlitchgrabContext);\n if (!ctx) {\n throw new Error(\"useGlitchgrab must be used within a GlitchgrabProvider\");\n }\n return ctx;\n}\n\nfunction GlitchgrabProviderInner({\n token,\n session,\n baseUrl,\n onError,\n onReportSent,\n breadcrumbs: enableBreadcrumbs = true,\n maxBreadcrumbs = 50,\n children,\n fallback,\n types,\n showSeverity,\n}: GlitchgrabProviderProps) {\n const visitedPagesRef = useRef<string[]>([]);\n\n // Initialize breadcrumbs\n useEffect(() => {\n if (enableBreadcrumbs) {\n initBreadcrumbs(maxBreadcrumbs);\n }\n }, [enableBreadcrumbs, maxBreadcrumbs]);\n\n // Track page visits\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n\n const trackPage = () => {\n try {\n const sanitized = sanitizeUrl(window.location.href);\n const pages = visitedPagesRef.current;\n if (pages[pages.length - 1] !== sanitized) {\n pages.push(sanitized);\n if (pages.length > 20) {\n pages.splice(0, pages.length - 20);\n }\n }\n } catch {\n // Silently fail\n }\n };\n\n trackPage();\n const handlePopState = () => trackPage();\n window.addEventListener(\"popstate\", handlePopState);\n\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPushState(...args);\n trackPage();\n };\n history.replaceState = function (...args) {\n origReplaceState(...args);\n trackPage();\n };\n\n return () => {\n window.removeEventListener(\"popstate\", handlePopState);\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n };\n } catch {\n // Never crash\n }\n }, []);\n\n // Unhandled errors and rejections — skip in development\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n if (process.env.NODE_ENV === \"development\") return;\n\n const handleError = (event: ErrorEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: event.message,\n errorStack: event.error?.stack,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n filename: event.filename ?? \"\",\n lineno: String(event.lineno ?? \"\"),\n colno: String(event.colno ?? \"\"),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && event.error) onError(event.error);\n } catch {\n // Silently fail\n }\n };\n\n const handleRejection = (event: PromiseRejectionEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const reason = event.reason;\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: reason instanceof Error ? reason.message : String(reason),\n errorStack: reason instanceof Error ? reason.stack : undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n type: \"unhandledrejection\",\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && reason instanceof Error) onError(reason);\n } catch {\n // Silently fail\n }\n };\n\n window.addEventListener(\"error\", handleError);\n window.addEventListener(\"unhandledrejection\", handleRejection);\n\n return () => {\n window.removeEventListener(\"error\", handleError);\n window.removeEventListener(\"unhandledrejection\", handleRejection);\n };\n } catch {\n // Never crash\n }\n }, [token, baseUrl, onError, onReportSent]);\n\n const report = useCallback(\n async (\n type: ReportType,\n description: string,\n metadata?: Record<string, string>\n ): Promise<ReportResult | null> => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_USER_REPORT\",\n type,\n description,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n ...(session?.phone ? { sessionUserPhone: String(session.phone) } : {}),\n ...metadata,\n },\n };\n const result = await sendReport(payload, baseUrl);\n if (result && onReportSent) onReportSent(result);\n return result;\n } catch {\n return null;\n }\n },\n [token, baseUrl, onReportSent, session]\n );\n\n const reportBug = useCallback(\n (description: string, metadata?: Record<string, string>) =>\n report(\"BUG\", description, metadata),\n [report]\n );\n\n const addBreadcrumb = useCallback(\n (message: string, data?: Record<string, string>) => {\n addBreadcrumbInternal(\"custom\", message, data);\n },\n []\n );\n\n const openReportDialog = useCallback((options?: { description?: string; type?: ReportType }) => {\n if (typeof window !== \"undefined\") {\n window.dispatchEvent(new CustomEvent(\"glitchgrab:open-report\", { detail: options }));\n }\n }, []);\n\n return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\n openReportDialog,\n }}\n >\n <GlitchgrabErrorBoundary\n token={token}\n baseUrl={baseUrl}\n onError={onError}\n fallback={fallback}\n visitedPages={visitedPagesRef.current}\n >\n {children}\n </GlitchgrabErrorBoundary>\n <ReportDialog report={report} types={types} showSeverity={showSeverity} />\n </GlitchgrabContext.Provider>\n );\n}\n\nexport function GlitchgrabProvider(props: GlitchgrabProviderProps) {\n // No token = passthrough (SDK disabled)\n if (!props.token) return <>{props.children}</>;\n\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || DEFAULT_BASE_URL,\n };\n\n try {\n return <GlitchgrabProviderInner {...resolvedProps} />;\n } catch {\n return <>{props.children}</>;\n }\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport type { ReportPayload } from \"./types\";\nimport { captureContext, sendReport } from \"./utils\";\n\ninterface ErrorBoundaryProps {\n token: string;\n baseUrl?: string;\n onError?: (error: Error) => void;\n fallback?: React.ReactNode;\n visitedPages: string[];\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n}\n\nexport class GlitchgrabErrorBoundary extends React.Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false };\n }\n\n static getDerivedStateFromError(): ErrorBoundaryState {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n try {\n const context = captureContext(this.props.visitedPages);\n\n const payload: ReportPayload = {\n token: this.props.token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: error.message,\n errorStack: error.stack,\n componentStack: errorInfo.componentStack ?? undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n },\n };\n\n sendReport(payload, this.props.baseUrl);\n\n if (this.props.onError) {\n this.props.onError(error);\n }\n } catch {\n // Never crash the host app\n }\n }\n\n render(): React.ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n // Re-render children — allows recovery from transient errors\n return this.props.children;\n }\n\n return this.props.children;\n }\n}\n","import type { Breadcrumb, BreadcrumbType } from \"./types\";\n\nconst MAX_DEFAULT = 50;\n\nlet breadcrumbs: Breadcrumb[] = [];\nlet maxBreadcrumbs = MAX_DEFAULT;\nlet initialized = false;\n\nexport function initBreadcrumbs(max?: number) {\n if (initialized) return;\n maxBreadcrumbs = max ?? MAX_DEFAULT;\n\n try {\n if (typeof window === \"undefined\") return;\n interceptConsole();\n interceptFetch();\n interceptNavigation();\n interceptClicks();\n initialized = true;\n } catch {\n // Never crash\n }\n}\n\nexport function addBreadcrumb(\n type: BreadcrumbType,\n message: string,\n data?: Record<string, string>\n) {\n try {\n breadcrumbs.push({\n type,\n message: message.slice(0, 200),\n timestamp: new Date().toISOString(),\n data,\n });\n if (breadcrumbs.length > maxBreadcrumbs) {\n breadcrumbs = breadcrumbs.slice(-maxBreadcrumbs);\n }\n } catch {\n // Never crash\n }\n}\n\nexport function getBreadcrumbs(): Breadcrumb[] {\n return [...breadcrumbs];\n}\n\nexport function clearBreadcrumbs() {\n breadcrumbs = [];\n}\n\n// ─── Console Interception ────────────────────────────────\n\nfunction interceptConsole() {\n const origLog = console.log;\n const origWarn = console.warn;\n const origError = console.error;\n\n console.log = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[log] ${argsToString(args)}`);\n origLog.apply(console, args);\n };\n\n console.warn = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[warn] ${argsToString(args)}`);\n origWarn.apply(console, args);\n };\n\n console.error = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[error] ${argsToString(args)}`);\n origError.apply(console, args);\n };\n}\n\nfunction argsToString(args: unknown[]): string {\n try {\n return args\n .map((a) => {\n if (typeof a === \"string\") return a;\n if (a instanceof Error) return a.message;\n try {\n return JSON.stringify(a);\n } catch {\n return String(a);\n }\n })\n .join(\" \")\n .slice(0, 200);\n } catch {\n return \"[unknown]\";\n }\n}\n\n// ─── Fetch Interception ──────────────────────────────────\n\nfunction interceptFetch() {\n const origFetch = window.fetch;\n\n window.fetch = async function (input, init) {\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input instanceof Request\n ? input.url\n : String(input);\n const method = init?.method ?? \"GET\";\n const start = Date.now();\n\n try {\n const response = await origFetch.apply(window, [input, init]);\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → ${response.status}`, {\n method,\n status: String(response.status),\n duration: `${Date.now() - start}ms`,\n });\n return response;\n } catch (err) {\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → FAILED`, {\n method,\n error: err instanceof Error ? err.message : \"unknown\",\n duration: `${Date.now() - start}ms`,\n });\n throw err;\n }\n };\n}\n\n// ─── Navigation Interception ─────────────────────────────\n\nfunction interceptNavigation() {\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPush(...args);\n addBreadcrumb(\"navigation\", `Navigate to ${window.location.pathname}`);\n };\n\n history.replaceState = function (...args) {\n origReplace(...args);\n addBreadcrumb(\"navigation\", `Replace to ${window.location.pathname}`);\n };\n\n window.addEventListener(\"popstate\", () => {\n addBreadcrumb(\"navigation\", `Back/Forward to ${window.location.pathname}`);\n });\n}\n\n// ─── Click Interception ──────────────────────────────────\n\nfunction interceptClicks() {\n document.addEventListener(\n \"click\",\n (e) => {\n try {\n const target = e.target as HTMLElement;\n const tag = target.tagName?.toLowerCase();\n const text = target.textContent?.trim().slice(0, 50) ?? \"\";\n const id = target.id ? `#${target.id}` : \"\";\n const cls = target.className && typeof target.className === \"string\"\n ? `.${target.className.split(\" \")[0]}`\n : \"\";\n\n addBreadcrumb(\"click\", `Click ${tag}${id}${cls} \"${text}\"`);\n } catch {\n // Never crash\n }\n },\n { capture: true }\n );\n}\n","import type { ReportPayload, ReportResult, CapturedContext, DeviceInfo } from \"./types\";\nimport { getBreadcrumbs } from \"./breadcrumbs\";\n\nconst SENSITIVE_PARAMS = [\n \"token\", \"key\", \"secret\", \"password\", \"passwd\", \"auth\", \"authorization\",\n \"session\", \"sessionid\", \"session_id\", \"api_key\", \"apikey\", \"access_token\",\n \"refresh_token\", \"client_secret\", \"code\", \"state\", \"nonce\", \"credential\", \"private\",\n];\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n const params = new URLSearchParams(parsed.search);\n let modified = false;\n for (const key of Array.from(params.keys())) {\n if (SENSITIVE_PARAMS.some((s) => key.toLowerCase().includes(s))) {\n params.set(key, \"[REDACTED]\");\n modified = true;\n }\n }\n if (modified) parsed.search = params.toString();\n return parsed.toString();\n } catch {\n return url.split(\"?\")[0] ?? url;\n }\n}\n\nexport function captureDeviceInfo(): DeviceInfo | null {\n try {\n if (typeof window === \"undefined\") return null;\n return {\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n platform: navigator.platform ?? \"unknown\",\n language: navigator.language ?? \"unknown\",\n online: navigator.onLine,\n colorScheme: window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\",\n devicePixelRatio: window.devicePixelRatio ?? 1,\n };\n } catch {\n return null;\n }\n}\n\nexport function captureContext(visitedPages: string[]): CapturedContext {\n try {\n return {\n url: sanitizeUrl(typeof window !== \"undefined\" ? window.location.href : \"\"),\n userAgent: typeof navigator !== \"undefined\" ? navigator.userAgent : \"\",\n timestamp: new Date().toISOString(),\n visitedPages: visitedPages.map(sanitizeUrl),\n breadcrumbs: getBreadcrumbs(),\n deviceInfo: captureDeviceInfo(),\n };\n } catch {\n return {\n url: \"\",\n userAgent: \"\",\n timestamp: new Date().toISOString(),\n visitedPages: [],\n breadcrumbs: [],\n deviceInfo: null,\n };\n }\n}\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\nconst MAX_RETRIES = 3;\nconst RETRY_BASE_MS = 500;\n\n/**\n * Send a report and return the result.\n * Never throws — returns null on failure.\n */\nexport async function sendReport(\n payload: ReportPayload,\n baseUrl?: string\n): Promise<ReportResult | null> {\n try {\n const url = `${baseUrl ?? DEFAULT_BASE_URL}/api/v1/sdk/report`;\n const body = JSON.stringify(payload);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${payload.token}`,\n };\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n keepalive: true,\n });\n\n if (response.ok) {\n const data = (await response.json()) as { success: boolean; data?: ReportResult };\n return data.data ?? { success: data.success };\n }\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n return null;\n }\n } catch {\n // Will retry\n }\n\n if (attempt < MAX_RETRIES - 1) {\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_BASE_MS * Math.pow(2, attempt))\n );\n }\n }\n\n // Fallback: sendBeacon (fire-and-forget, no result)\n if (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n try {\n navigator.sendBeacon(url, new Blob([body], { type: \"application/json\" }));\n } catch {\n // Silently fail\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect, type CSSProperties, type ReactNode } from \"react\";\n// @ts-expect-error react-dom types handled by host app\nimport { createPortal } from \"react-dom\";\nimport type { ReportType, ReportSeverity, UseGlitchgrabReturn } from \"./types\";\n\n/** Detect if the host page uses a dark or light theme */\nfunction useIsDark(): boolean {\n if (typeof window === \"undefined\") return true;\n try {\n const bg = getComputedStyle(document.body).backgroundColor;\n const match = bg.match(/\\d+/g);\n if (match && match.length >= 3) {\n const [r, g, b] = match.map(Number);\n return (r * 299 + g * 587 + b * 114) / 1000 < 128;\n }\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n } catch {\n return true;\n }\n}\n\nfunction getTheme(dark: boolean) {\n return dark\n ? { bg: \"#1c1c1e\", bgSecondary: \"#27272a\", border: \"#2c2c2e\", text: \"#fafafa\", textMuted: \"#a1a1aa\", accent: \"#22d3ee\", accentText: \"#09090b\", inputBg: \"#27272a\", inputBorder: \"#3f3f46\" }\n : { bg: \"#ffffff\", bgSecondary: \"#f4f4f5\", border: \"#e4e4e7\", text: \"#18181b\", textMuted: \"#71717a\", accent: \"#0891b2\", accentText: \"#ffffff\", inputBg: \"#fafafa\", inputBorder: \"#d4d4d8\" };\n}\n\ninterface ReportDialogProps {\n report: UseGlitchgrabReturn[\"report\"];\n types?: ReportType[];\n showSeverity?: boolean;\n}\n\n/**\n * The report dialog — rendered inside GlitchgrabProvider automatically.\n * Opens via the `glitchgrab:open-report` custom event (triggered by `openReportDialog()`).\n */\nexport function ReportDialog({\n report,\n types,\n showSeverity = true,\n}: ReportDialogProps) {\n // Prevent hydration mismatch — render nothing until after hydration\n const [mounted, setMounted] = useState(false);\n useEffect(() => { setMounted(true); }, []);\n\n const [isOpen, setIsOpen] = useState(false);\n const [description, setDescription] = useState(\"\");\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n const [screenshot, setScreenshot] = useState<string | null>(null);\n const [previewOpen, setPreviewOpen] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDivElement>(null);\n\n // Stepper state\n const [step, setStep] = useState(1);\n const [reportType, setReportType] = useState<ReportType>(\"BUG\");\n const [severity, setSeverity] = useState<ReportSeverity>(\"medium\");\n\n const availableTypes: ReportType[] = types ?? [\"BUG\", \"FEATURE_REQUEST\", \"QUESTION\", \"OTHER\"];\n\n const isDark = useIsDark();\n const t = getTheme(isDark);\n\n const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => {\n setScreenshot(reader.result as string);\n };\n reader.readAsDataURL(file);\n e.target.value = \"\";\n };\n\n const retakeScreenshot = async () => {\n setPreviewOpen(false);\n setIsOpen(false);\n setScreenshot(null);\n await new Promise((r) => setTimeout(r, 300));\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // silently fail\n }\n setIsOpen(true);\n };\n\n const handleOpen = async () => {\n setSubmitted(false);\n if (availableTypes.length === 1) {\n setReportType(availableTypes[0]);\n setStep(2);\n }\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // screenshot failed — open without it\n }\n setIsOpen(true);\n };\n\n // Listen for programmatic open via openReportDialog()\n useEffect(() => {\n const handler = (e: Event) => {\n if (isOpen) return;\n const detail = (e as CustomEvent).detail;\n if (detail?.description) setDescription(detail.description);\n if (detail?.type) {\n setReportType(detail.type);\n setStep(2);\n }\n handleOpen();\n };\n window.addEventListener(\"glitchgrab:open-report\", handler);\n return () => window.removeEventListener(\"glitchgrab:open-report\", handler);\n }, [isOpen, handleOpen]);\n\n // Close on Escape\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleClose = () => {\n setIsOpen(false);\n setStep(1);\n setReportType(\"BUG\");\n setSeverity(\"medium\");\n };\n\n const handleSubmit = async () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n setIsSubmitting(true);\n const metadata: Record<string, string> = {};\n if (screenshot) metadata.screenshot = screenshot;\n if (showSeverity && reportType === \"BUG\") {\n metadata.severity = severity;\n }\n\n const result = await report(reportType, description.trim(), Object.keys(metadata).length > 0 ? metadata : undefined);\n\n if (result) {\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n\n setTimeout(() => {\n setSubmitted(false);\n handleClose();\n }, 2000);\n }\n setIsSubmitting(false);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n if (!mounted) return null;\n\n return (\n <>\n {/* Report modal */}\n {isOpen && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n onClick={() => { if (!previewOpen) handleClose(); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: \"relative\",\n zIndex: 2147483647,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: t.bg,\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: t.text,\n isolation: \"isolate\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: `1px solid ${t.border}`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"8px\" }}>\n {step > 1 && (\n <button\n type=\"button\"\n onClick={() => setStep((s) => (s - 1) as 1 | 2 | 3)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n aria-label=\"Back\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M10 3L5 8L10 13\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n )}\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: t.text,\n }}\n >\n {step === 1 ? \"What's on your mind?\" : step === 2 ? \"Tell us more\" : \"Review & Send\"}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Close\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" style={{ display: \"block\" }}>\n <path d=\"M4 4L12 12M12 4L4 12\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"center\", gap: \"0\", marginTop: \"12px\" }}>\n {[1, 2, 3].map((s, i) => (\n <div key={s} style={{ display: \"flex\", alignItems: \"center\" }}>\n <div style={{\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: s <= step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n {i < 2 && (\n <div style={{\n width: \"40px\",\n height: \"2px\",\n backgroundColor: s < step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n )}\n </div>\n ))}\n </div>\n </div>\n\n {/* Body */}\n <div style={{ padding: \"16px\" }}>\n {submitted ? (\n <div\n style={{\n textAlign: \"center\",\n padding: \"20px 0\",\n color: t.accent,\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n {getTypeLabel(reportType)} sent. Thank you!\n </div>\n ) : (\n <>\n {/* Step 1: Category */}\n {step === 1 && (\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: \"8px\" }}>\n {availableTypes.map((type) => (\n <button\n key={type}\n type=\"button\"\n onClick={() => {\n setReportType(type);\n setStep(2);\n }}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"16px 8px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n background: t.inputBg,\n cursor: \"pointer\",\n color: t.text,\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s ease\",\n }}\n onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.accent; }}\n onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.inputBorder; }}\n >\n {getTypeIcon(type, t.accent)}\n <span style={{ fontSize: \"13px\", fontWeight: 600 }}>{getTypeLabel(type)}</span>\n <span style={{ fontSize: \"11px\", color: t.textMuted, lineHeight: \"1.3\" }}>{getTypeSubtitle(type)}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* Step 2: Details */}\n {step === 2 && (\n <>\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder={getPlaceholder(reportType)}\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: t.text,\n backgroundColor: t.inputBg,\n }}\n onFocus={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.accent; }}\n onBlur={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.inputBorder; }}\n autoFocus\n />\n {showSeverity && reportType === \"BUG\" && (\n <div style={{ marginTop: \"10px\" }}>\n <span style={{ fontSize: \"12px\", color: t.textMuted, marginBottom: \"6px\", display: \"block\" }}>Severity</span>\n <div style={{ display: \"flex\", gap: \"6px\" }}>\n {([\"low\", \"medium\", \"high\"] as ReportSeverity[]).map((s) => (\n <button\n key={s}\n type=\"button\"\n onClick={() => setSeverity(s)}\n style={{\n flex: 1,\n padding: \"6px 0\",\n borderRadius: \"6px\",\n border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,\n background: severity === s ? t.accent : \"transparent\",\n color: severity === s ? t.accentText : t.text,\n fontSize: \"12px\",\n fontWeight: 600,\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n textTransform: \"capitalize\",\n transition: \"all 0.15s ease\",\n }}\n >\n {s}\n </button>\n ))}\n </div>\n </div>\n )}\n <button\n type=\"button\"\n onClick={() => setStep(3)}\n disabled={!description.trim()}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: !description.trim() ? t.bgSecondary : t.accent,\n color: !description.trim() ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: !description.trim() ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n Next\n </button>\n </>\n )}\n\n {/* Step 3: Review & Send */}\n {step === 3 && (\n <>\n {/* Summary chips */}\n <div style={{ display: \"flex\", gap: \"6px\", flexWrap: \"wrap\", marginBottom: \"12px\" }}>\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"4px\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: t.bgSecondary,\n color: t.text,\n border: `1px solid ${t.border}`,\n }}>\n {getTypeIcon(reportType, t.accent, 12)}\n {getTypeLabel(reportType)}\n </span>\n {showSeverity && reportType === \"BUG\" && (\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: severity === \"high\" ? \"#fef2f2\" : severity === \"medium\" ? \"#fffbeb\" : \"#f0fdf4\",\n color: severity === \"high\" ? \"#dc2626\" : severity === \"medium\" ? \"#d97706\" : \"#16a34a\",\n border: `1px solid ${severity === \"high\" ? \"#fecaca\" : severity === \"medium\" ? \"#fde68a\" : \"#bbf7d0\"}`,\n textTransform: \"capitalize\",\n }}>\n {severity}\n </span>\n )}\n </div>\n\n {/* Description preview */}\n <div style={{\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n backgroundColor: t.inputBg,\n fontSize: \"13px\",\n color: t.text,\n marginBottom: \"10px\",\n maxHeight: \"80px\",\n overflow: \"hidden\",\n lineHeight: \"1.4\",\n }}>\n {description.length > 200 ? description.slice(0, 200) + \"...\" : description}\n </div>\n\n {/* Screenshot */}\n {screenshot && (\n <div style={{ marginBottom: \"10px\", position: \"relative\" }}>\n <img\n src={screenshot}\n alt=\"Page screenshot\"\n onClick={() => setPreviewOpen(true)}\n style={{\n width: \"100%\",\n borderRadius: \"6px\",\n border: `1px solid ${t.border}`,\n maxHeight: \"80px\",\n objectFit: \"cover\",\n objectPosition: \"top\",\n cursor: \"pointer\",\n }}\n />\n <button\n type=\"button\"\n onClick={() => setScreenshot(null)}\n style={{\n position: \"absolute\",\n top: \"4px\",\n right: \"4px\",\n background: \"rgba(0,0,0,0.6)\",\n border: \"none\",\n borderRadius: \"50%\",\n width: \"20px\",\n height: \"20px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Remove screenshot\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M1 1L9 9M9 1L1 9\" stroke=\"#fff\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n )}\n {!screenshot && (\n <div style={{ display: \"flex\", gap: \"6px\", marginBottom: \"10px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload screenshot\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake screenshot\n </button>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={isSubmitting}\n style={{\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: isSubmitting ? t.bgSecondary : t.accent,\n color: isSubmitting ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: isSubmitting ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: `1px solid ${t.border}`,\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: t.textMuted }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>,\n document.body\n )}\n\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileUpload}\n style={{ display: \"none\" }}\n />\n\n {/* Full-screen screenshot preview */}\n {previewOpen && screenshot && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n backgroundColor: \"rgba(0,0,0,0.85)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"16px\",\n cursor: \"pointer\",\n }}\n onClick={(e) => { e.stopPropagation(); setPreviewOpen(false); }}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <img\n src={screenshot}\n alt=\"Screenshot preview\"\n onClick={(e) => e.stopPropagation()}\n style={{\n maxWidth: \"100%\",\n maxHeight: \"calc(100vh - 80px)\",\n borderRadius: \"8px\",\n objectFit: \"contain\",\n cursor: \"default\",\n }}\n />\n <span\n style={{\n marginTop: \"12px\",\n color: t.textMuted,\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>,\n document.body\n )}\n </>\n );\n}\n\n/* ─── Helpers ─── */\n\nfunction getTypeLabel(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Bug Report\";\n case \"FEATURE_REQUEST\": return \"Feature Request\";\n case \"QUESTION\": return \"Question\";\n case \"OTHER\": return \"Other\";\n }\n}\n\nfunction getTypeSubtitle(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Something isn't working\";\n case \"FEATURE_REQUEST\": return \"Suggest an improvement\";\n case \"QUESTION\": return \"Ask a question\";\n case \"OTHER\": return \"General feedback\";\n }\n}\n\nfunction getPlaceholder(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"What went wrong?\";\n case \"FEATURE_REQUEST\": return \"Describe the feature you'd like...\";\n case \"QUESTION\": return \"What would you like to know?\";\n case \"OTHER\": return \"Tell us what's on your mind...\";\n }\n}\n\nfunction getTypeIcon(type: ReportType, color: string, size = 24): ReactNode {\n const props = { width: size, height: size, viewBox: \"0 0 24 24\", fill: \"none\", style: { flexShrink: 0 } as CSSProperties };\n switch (type) {\n case \"BUG\":\n return <svg {...props}><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\" /></svg>;\n case \"FEATURE_REQUEST\":\n return <svg {...props}><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\" /></svg>;\n case \"QUESTION\":\n return <svg {...props}><circle cx=\"12\" cy=\"12\" r=\"10\" stroke={color} strokeWidth=\"1.5\" /><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\" /></svg>;\n case \"OTHER\":\n return <svg {...props}><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\" /></svg>;\n }\n}\n","\"use client\";\n\nimport { useState, type CSSProperties, type ReactNode } from \"react\";\nimport type { ReportButtonProps } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\n/** Safe version of useGlitchgrab that returns null when outside provider */\nfunction useGlitchgrabSafe() {\n try {\n return useGlitchgrab();\n } catch {\n return null;\n }\n}\n\n/**\n * Optional trigger button for opening the report dialog.\n *\n * The dialog itself lives inside `GlitchgrabProvider` — you don't need this component\n * unless you want a visible trigger button. You can also open the dialog programmatically\n * via `useGlitchgrab().openReportDialog()`.\n *\n * @example\n * ```tsx\n * // Use the default floating button\n * <ReportButton />\n *\n * // Use your own trigger\n * <ReportButton>\n * {({ onClick }) => <button onClick={onClick}>Report</button>}\n * </ReportButton>\n *\n * // Or skip ReportButton entirely and use the hook\n * const { openReportDialog } = useGlitchgrab();\n * <button onClick={() => openReportDialog()}>Report</button>\n * ```\n */\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\n const glitchgrab = useGlitchgrabSafe();\n\n if (!glitchgrab) return null;\n\n const handleClick = async () => {\n setCapturing(true);\n glitchgrab.openReportDialog();\n setCapturing(false);\n };\n\n // Custom trigger via render prop\n if (children) {\n return <>{children({ onClick: handleClick, capturing })}</>;\n }\n\n // Default floating button\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const positionStyles: CSSProperties = {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"16px\" } : { bottom: \"16px\" }),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={capturing}\n className={className}\n style={{\n position: \"fixed\",\n ...positionStyles,\n zIndex: 99999,\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n backgroundColor: \"#18181b\",\n color: \"#fafafa\",\n fontSize: \"14px\",\n fontWeight: 500,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n cursor: capturing ? \"wait\" : \"pointer\",\n boxShadow:\n \"0 4px 12px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.1)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n opacity: capturing ? 0.7 : 1,\n }}\n onMouseEnter={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1)\";\n }}\n aria-label={label}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n style={{ flexShrink: 0 }}\n >\n <path\n 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\"\n fill=\"currentColor\"\n />\n </svg>\n {capturing ? \"Capturing...\" : label}\n </button>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\n\nexport interface GlitchgrabReport {\n id: string;\n source: string;\n status: string;\n rawInput: string | null;\n reporterPrimaryKey: string;\n reporterName: string;\n reporterEmail: string | null;\n reporterPhone: string | null;\n pageUrl: string | null;\n createdAt: string;\n /** Number of comments on the linked GitHub issue (0 if no issue) */\n commentCount: number;\n issue: {\n githubNumber: number;\n githubUrl: string;\n title: string;\n labels: string[];\n severity: string | null;\n githubState: string | null;\n } | null;\n}\n\nconst BASE_URL = \"https://www.glitchgrab.dev\";\n\n/**\n * Hook to fetch bug reports for a specific user.\n *\n * ```tsx\n * const { reports, isLoading, error, refetch } = useGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * });\n * ```\n */\nexport function useGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n /** Max results (default 100, max 100) */\n limit?: number;\n}): {\n reports: GlitchgrabReport[];\n isLoading: boolean;\n isFetching: boolean;\n error: string | null;\n refetch: () => Promise<void>;\n} {\n const [reports, setReports] = useState<GlitchgrabReport[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const fetchReports = useCallback(async () => {\n if (!token || !userId) {\n setIsLoading(false);\n return;\n }\n\n setIsFetching(true);\n setError(null);\n\n try {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n\n if (data.success) {\n setReports(data.data ?? []);\n } else {\n setError(data.error ?? \"Failed to fetch reports\");\n }\n } catch {\n setError(\"Network error\");\n } finally {\n setIsLoading(false);\n setIsFetching(false);\n }\n }, [token, userId, limit]);\n\n useEffect(() => {\n fetchReports();\n }, [fetchReports]);\n\n return { reports, isLoading, isFetching, error, refetch: fetchReports };\n}\n\n/**\n * Standalone fetcher — use with TanStack Query or any data fetching library.\n *\n * ```tsx\n * const { data } = useQuery({\n * queryKey: [\"glitchgrab-reports\", userId],\n * queryFn: () => fetchGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * }),\n * });\n * ```\n */\nexport async function fetchGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n limit?: number;\n}): Promise<GlitchgrabReport[]> {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n if (!data.success) throw new Error(data.error ?? \"Failed to fetch reports\");\n return data.data ?? [];\n}\n\n// ─── Report Actions ─────────────────────────────────────\n\nasync function reportAction(\n token: string,\n reportId: string,\n body: Record<string, string>\n): Promise<void> {\n const res = await fetch(`${BASE_URL}/api/v1/reports/${reportId}/actions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n const data = await res.json().catch(() => ({}));\n if (!res.ok || !data.success) throw new Error(data.error ?? \"Action failed\");\n}\n\n/**\n * Hook to manage report actions with loading/error states.\n *\n * ```tsx\n * const { approve, reject, close, isPending, error } = useGlitchgrabActions({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * onSuccess: () => refetch(),\n * onError: (err) => toast.error(err.message),\n * });\n *\n * <button onClick={() => approve(reportId)} disabled={isPending}>\n * {isPending ? \"...\" : \"Approve\"}\n * </button>\n * ```\n */\nexport function useGlitchgrabActions({\n token,\n onSuccess,\n onError,\n}: {\n token: string;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n}) {\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const run = useCallback(\n async (reportId: string, body: Record<string, string>) => {\n setIsPending(true);\n setError(null);\n try {\n await reportAction(token, reportId, body);\n onSuccess?.();\n } catch (e) {\n const err = e instanceof Error ? e : new Error(\"Action failed\");\n setError(err.message);\n onError?.(err);\n } finally {\n setIsPending(false);\n }\n },\n [token, onSuccess, onError]\n );\n\n return {\n approve: (reportId: string) => run(reportId, { action: \"label\", label: \"approved\" }),\n reject: (reportId: string) => run(reportId, { action: \"label\", label: \"rejected\" }),\n close: (reportId: string) => run(reportId, { action: \"close\" }),\n reopen: (reportId: string) => run(reportId, { action: \"reopen\" }),\n label: (reportId: string, label: string) => run(reportId, { action: \"label\", label }),\n unlabel: (reportId: string, label: string) => run(reportId, { action: \"unlabel\", label }),\n isPending,\n error,\n };\n}\n"],"mappings":"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","names":["useRef","useEffect","e","Fragment","jsx","jsxs","DEFAULT_BASE_URL","maxBreadcrumbs","useRef","useEffect","addBreadcrumb","useState","Fragment","jsx","jsxs","useState","useState","useEffect","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/error-boundary.tsx","../src/breadcrumbs.ts","../src/utils.ts","../src/report-dialog.tsx","../src/report-button.tsx","../src/use-reports.ts"],"sourcesContent":["\"use client\";\n\nimport {\n createContext,\n useContext,\n useRef,\n useEffect,\n useCallback,\n useState,\n} from \"react\";\nimport type {\n GlitchgrabProviderProps,\n UseGlitchgrabReturn,\n ReportPayload,\n ReportResult,\n ReportType,\n} from \"./types\";\nimport { GlitchgrabErrorBoundary } from \"./error-boundary\";\nimport { ReportDialog } from \"./report-dialog\";\nimport { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\n\nconst GlitchgrabContext = createContext<UseGlitchgrabReturn | null>(null);\n\n/**\n * Hook to access Glitchgrab in your components.\n *\n * @example\n * ```tsx\n * const { reportBug, report, addBreadcrumb } = useGlitchgrab();\n *\n * // Report a bug\n * reportBug(\"Login button crashes on mobile\");\n *\n * // Report a feature request\n * report(\"FEATURE_REQUEST\", \"Add dark mode\");\n *\n * // Add a custom breadcrumb\n * addBreadcrumb(\"User clicked checkout\", { cartItems: \"3\" });\n * ```\n */\nexport function useGlitchgrab(): UseGlitchgrabReturn {\n const ctx = useContext(GlitchgrabContext);\n if (!ctx) {\n throw new Error(\"useGlitchgrab must be used within a GlitchgrabProvider\");\n }\n return ctx;\n}\n\nfunction GlitchgrabProviderInner({\n token,\n session,\n baseUrl,\n onError,\n onReportSent,\n breadcrumbs: enableBreadcrumbs = true,\n maxBreadcrumbs = 50,\n children,\n fallback,\n types,\n showSeverity,\n}: GlitchgrabProviderProps) {\n const visitedPagesRef = useRef<string[]>([]);\n\n // Initialize breadcrumbs\n useEffect(() => {\n if (enableBreadcrumbs) {\n initBreadcrumbs(maxBreadcrumbs);\n }\n }, [enableBreadcrumbs, maxBreadcrumbs]);\n\n // Track page visits\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n\n const trackPage = () => {\n try {\n const sanitized = sanitizeUrl(window.location.href);\n const pages = visitedPagesRef.current;\n if (pages[pages.length - 1] !== sanitized) {\n pages.push(sanitized);\n if (pages.length > 20) {\n pages.splice(0, pages.length - 20);\n }\n }\n } catch {\n // Silently fail\n }\n };\n\n trackPage();\n const handlePopState = () => trackPage();\n window.addEventListener(\"popstate\", handlePopState);\n\n const origPushState = history.pushState.bind(history);\n const origReplaceState = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPushState(...args);\n trackPage();\n };\n history.replaceState = function (...args) {\n origReplaceState(...args);\n trackPage();\n };\n\n return () => {\n window.removeEventListener(\"popstate\", handlePopState);\n history.pushState = origPushState;\n history.replaceState = origReplaceState;\n };\n } catch {\n // Never crash\n }\n }, []);\n\n // Unhandled errors and rejections — skip in development\n useEffect(() => {\n try {\n if (typeof window === \"undefined\") return;\n if (process.env.NODE_ENV === \"development\") return;\n\n const handleError = (event: ErrorEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: event.message,\n errorStack: event.error?.stack,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n filename: event.filename ?? \"\",\n lineno: String(event.lineno ?? \"\"),\n colno: String(event.colno ?? \"\"),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && event.error) onError(event.error);\n } catch {\n // Silently fail\n }\n };\n\n const handleRejection = (event: PromiseRejectionEvent) => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const reason = event.reason;\n const payload: ReportPayload = {\n token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: reason instanceof Error ? reason.message : String(reason),\n errorStack: reason instanceof Error ? reason.stack : undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n type: \"unhandledrejection\",\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n },\n };\n sendReport(payload, baseUrl).then((result) => {\n if (result && onReportSent) onReportSent(result);\n });\n if (onError && reason instanceof Error) onError(reason);\n } catch {\n // Silently fail\n }\n };\n\n window.addEventListener(\"error\", handleError);\n window.addEventListener(\"unhandledrejection\", handleRejection);\n\n return () => {\n window.removeEventListener(\"error\", handleError);\n window.removeEventListener(\"unhandledrejection\", handleRejection);\n };\n } catch {\n // Never crash\n }\n }, [token, baseUrl, onError, onReportSent]);\n\n const report = useCallback(\n async (\n type: ReportType,\n description: string,\n metadata?: Record<string, string>\n ): Promise<ReportResult | null> => {\n try {\n const context = captureContext(visitedPagesRef.current);\n const payload: ReportPayload = {\n token,\n source: \"SDK_USER_REPORT\",\n type,\n description,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n ...(session?.userId ? { sessionUserId: session.userId } : {}),\n ...(session?.name ? { sessionUserName: String(session.name) } : {}),\n ...(session?.email ? { sessionUserEmail: String(session.email) } : {}),\n ...(session?.phone ? { sessionUserPhone: String(session.phone) } : {}),\n ...metadata,\n },\n };\n const result = await sendReport(payload, baseUrl);\n if (result && onReportSent) onReportSent(result);\n return result;\n } catch {\n return null;\n }\n },\n [token, baseUrl, onReportSent, session]\n );\n\n const reportBug = useCallback(\n (description: string, metadata?: Record<string, string>) =>\n report(\"BUG\", description, metadata),\n [report]\n );\n\n const addBreadcrumb = useCallback(\n (message: string, data?: Record<string, string>) => {\n addBreadcrumbInternal(\"custom\", message, data);\n },\n []\n );\n\n const openReportDialog = useCallback((options?: { description?: string; type?: ReportType }) => {\n if (typeof window !== \"undefined\") {\n window.dispatchEvent(new CustomEvent(\"glitchgrab:open-report\", { detail: options }));\n }\n }, []);\n\n return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\n openReportDialog,\n }}\n >\n <GlitchgrabErrorBoundary\n token={token}\n baseUrl={baseUrl}\n onError={onError}\n fallback={fallback}\n visitedPages={visitedPagesRef.current}\n >\n {children}\n </GlitchgrabErrorBoundary>\n <ReportDialog report={report} types={types} showSeverity={showSeverity} />\n </GlitchgrabContext.Provider>\n );\n}\n\nexport function GlitchgrabProvider(props: GlitchgrabProviderProps) {\n // No token = passthrough (SDK disabled)\n if (!props.token) return <>{props.children}</>;\n\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || DEFAULT_BASE_URL,\n };\n\n try {\n return <GlitchgrabProviderInner {...resolvedProps} />;\n } catch {\n return <>{props.children}</>;\n }\n}\n","\"use client\";\n\nimport * as React from \"react\";\nimport type { ReportPayload } from \"./types\";\nimport { captureContext, sendReport } from \"./utils\";\n\ninterface ErrorBoundaryProps {\n token: string;\n baseUrl?: string;\n onError?: (error: Error) => void;\n fallback?: React.ReactNode;\n visitedPages: string[];\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n}\n\nexport class GlitchgrabErrorBoundary extends React.Component<\n ErrorBoundaryProps,\n ErrorBoundaryState\n> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false };\n }\n\n static getDerivedStateFromError(): ErrorBoundaryState {\n return { hasError: true };\n }\n\n componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void {\n try {\n const context = captureContext(this.props.visitedPages);\n\n const payload: ReportPayload = {\n token: this.props.token,\n source: \"SDK_AUTO\",\n type: \"BUG\",\n errorMessage: error.message,\n errorStack: error.stack,\n componentStack: errorInfo.componentStack ?? undefined,\n pageUrl: context.url,\n userAgent: context.userAgent,\n breadcrumbs: context.breadcrumbs,\n deviceInfo: context.deviceInfo ?? undefined,\n metadata: {\n timestamp: context.timestamp,\n visitedPages: JSON.stringify(context.visitedPages),\n },\n };\n\n sendReport(payload, this.props.baseUrl);\n\n if (this.props.onError) {\n this.props.onError(error);\n }\n } catch {\n // Never crash the host app\n }\n }\n\n render(): React.ReactNode {\n if (this.state.hasError) {\n if (this.props.fallback) {\n return this.props.fallback;\n }\n\n // Re-render children — allows recovery from transient errors\n return this.props.children;\n }\n\n return this.props.children;\n }\n}\n","import type { Breadcrumb, BreadcrumbType } from \"./types\";\n\nconst MAX_DEFAULT = 50;\n\nlet breadcrumbs: Breadcrumb[] = [];\nlet maxBreadcrumbs = MAX_DEFAULT;\nlet initialized = false;\n\nexport function initBreadcrumbs(max?: number) {\n if (initialized) return;\n maxBreadcrumbs = max ?? MAX_DEFAULT;\n\n try {\n if (typeof window === \"undefined\") return;\n interceptConsole();\n interceptFetch();\n interceptNavigation();\n interceptClicks();\n initialized = true;\n } catch {\n // Never crash\n }\n}\n\nexport function addBreadcrumb(\n type: BreadcrumbType,\n message: string,\n data?: Record<string, string>\n) {\n try {\n breadcrumbs.push({\n type,\n message: message.slice(0, 200),\n timestamp: new Date().toISOString(),\n data,\n });\n if (breadcrumbs.length > maxBreadcrumbs) {\n breadcrumbs = breadcrumbs.slice(-maxBreadcrumbs);\n }\n } catch {\n // Never crash\n }\n}\n\nexport function getBreadcrumbs(): Breadcrumb[] {\n return [...breadcrumbs];\n}\n\nexport function clearBreadcrumbs() {\n breadcrumbs = [];\n}\n\n// ─── Console Interception ────────────────────────────────\n\nfunction interceptConsole() {\n const origLog = console.log;\n const origWarn = console.warn;\n const origError = console.error;\n\n console.log = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[log] ${argsToString(args)}`);\n origLog.apply(console, args);\n };\n\n console.warn = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[warn] ${argsToString(args)}`);\n origWarn.apply(console, args);\n };\n\n console.error = function (...args: unknown[]) {\n addBreadcrumb(\"console\", `[error] ${argsToString(args)}`);\n origError.apply(console, args);\n };\n}\n\nfunction argsToString(args: unknown[]): string {\n try {\n return args\n .map((a) => {\n if (typeof a === \"string\") return a;\n if (a instanceof Error) return a.message;\n try {\n return JSON.stringify(a);\n } catch {\n return String(a);\n }\n })\n .join(\" \")\n .slice(0, 200);\n } catch {\n return \"[unknown]\";\n }\n}\n\n// ─── Fetch Interception ──────────────────────────────────\n\nfunction interceptFetch() {\n const origFetch = window.fetch;\n\n window.fetch = async function (input, init) {\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input instanceof Request\n ? input.url\n : String(input);\n const method = init?.method ?? \"GET\";\n const start = Date.now();\n\n try {\n const response = await origFetch.apply(window, [input, init]);\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → ${response.status}`, {\n method,\n status: String(response.status),\n duration: `${Date.now() - start}ms`,\n });\n return response;\n } catch (err) {\n addBreadcrumb(\"api\", `${method} ${url.slice(0, 100)} → FAILED`, {\n method,\n error: err instanceof Error ? err.message : \"unknown\",\n duration: `${Date.now() - start}ms`,\n });\n throw err;\n }\n };\n}\n\n// ─── Navigation Interception ─────────────────────────────\n\nfunction interceptNavigation() {\n const origPush = history.pushState.bind(history);\n const origReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n origPush(...args);\n addBreadcrumb(\"navigation\", `Navigate to ${window.location.pathname}`);\n };\n\n history.replaceState = function (...args) {\n origReplace(...args);\n addBreadcrumb(\"navigation\", `Replace to ${window.location.pathname}`);\n };\n\n window.addEventListener(\"popstate\", () => {\n addBreadcrumb(\"navigation\", `Back/Forward to ${window.location.pathname}`);\n });\n}\n\n// ─── Click Interception ──────────────────────────────────\n\nfunction interceptClicks() {\n document.addEventListener(\n \"click\",\n (e) => {\n try {\n const target = e.target as HTMLElement;\n const tag = target.tagName?.toLowerCase();\n const text = target.textContent?.trim().slice(0, 50) ?? \"\";\n const id = target.id ? `#${target.id}` : \"\";\n const cls = target.className && typeof target.className === \"string\"\n ? `.${target.className.split(\" \")[0]}`\n : \"\";\n\n addBreadcrumb(\"click\", `Click ${tag}${id}${cls} \"${text}\"`);\n } catch {\n // Never crash\n }\n },\n { capture: true }\n );\n}\n","import type { ReportPayload, ReportResult, CapturedContext, DeviceInfo } from \"./types\";\nimport { getBreadcrumbs } from \"./breadcrumbs\";\n\nconst SENSITIVE_PARAMS = [\n \"token\", \"key\", \"secret\", \"password\", \"passwd\", \"auth\", \"authorization\",\n \"session\", \"sessionid\", \"session_id\", \"api_key\", \"apikey\", \"access_token\",\n \"refresh_token\", \"client_secret\", \"code\", \"state\", \"nonce\", \"credential\", \"private\",\n];\n\nexport function sanitizeUrl(url: string): string {\n try {\n const parsed = new URL(url);\n const params = new URLSearchParams(parsed.search);\n let modified = false;\n for (const key of Array.from(params.keys())) {\n if (SENSITIVE_PARAMS.some((s) => key.toLowerCase().includes(s))) {\n params.set(key, \"[REDACTED]\");\n modified = true;\n }\n }\n if (modified) parsed.search = params.toString();\n return parsed.toString();\n } catch {\n return url.split(\"?\")[0] ?? url;\n }\n}\n\nexport function captureDeviceInfo(): DeviceInfo | null {\n try {\n if (typeof window === \"undefined\") return null;\n return {\n screenWidth: screen.width,\n screenHeight: screen.height,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n platform: navigator.platform ?? \"unknown\",\n language: navigator.language ?? \"unknown\",\n online: navigator.onLine,\n colorScheme: window.matchMedia(\"(prefers-color-scheme: dark)\").matches ? \"dark\" : \"light\",\n devicePixelRatio: window.devicePixelRatio ?? 1,\n };\n } catch {\n return null;\n }\n}\n\nexport function captureContext(visitedPages: string[]): CapturedContext {\n try {\n return {\n url: sanitizeUrl(typeof window !== \"undefined\" ? window.location.href : \"\"),\n userAgent: typeof navigator !== \"undefined\" ? navigator.userAgent : \"\",\n timestamp: new Date().toISOString(),\n visitedPages: visitedPages.map(sanitizeUrl),\n breadcrumbs: getBreadcrumbs(),\n deviceInfo: captureDeviceInfo(),\n };\n } catch {\n return {\n url: \"\",\n userAgent: \"\",\n timestamp: new Date().toISOString(),\n visitedPages: [],\n breadcrumbs: [],\n deviceInfo: null,\n };\n }\n}\n\nconst DEFAULT_BASE_URL = \"https://www.glitchgrab.dev\";\nconst MAX_RETRIES = 3;\nconst RETRY_BASE_MS = 500;\n\n/**\n * Send a report and return the result.\n * Never throws — returns null on failure.\n */\nexport async function sendReport(\n payload: ReportPayload,\n baseUrl?: string\n): Promise<ReportResult | null> {\n try {\n const url = `${baseUrl ?? DEFAULT_BASE_URL}/api/v1/sdk/report`;\n const body = JSON.stringify(payload);\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${payload.token}`,\n };\n\n // keepalive has a 64KB body limit in browsers — skip it for large payloads (e.g., screenshots)\n const useKeepalive = body.length < 60_000;\n\n for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {\n try {\n const response = await fetch(url, {\n method: \"POST\",\n headers,\n body,\n ...(useKeepalive ? { keepalive: true } : {}),\n });\n\n if (response.ok) {\n const data = (await response.json()) as { success: boolean; data?: ReportResult };\n return data.data ?? { success: data.success };\n }\n\n if (response.status >= 400 && response.status < 500 && response.status !== 429) {\n return null;\n }\n } catch {\n // Will retry\n }\n\n if (attempt < MAX_RETRIES - 1) {\n await new Promise((resolve) =>\n setTimeout(resolve, RETRY_BASE_MS * Math.pow(2, attempt))\n );\n }\n }\n\n // Fallback: sendBeacon (fire-and-forget, no result)\n if (typeof navigator !== \"undefined\" && navigator.sendBeacon) {\n try {\n navigator.sendBeacon(url, new Blob([body], { type: \"application/json\" }));\n } catch {\n // Silently fail\n }\n }\n\n return null;\n } catch {\n return null;\n }\n}\n","\"use client\";\n\nimport { useState, useRef, useEffect, type CSSProperties, type ReactNode } from \"react\";\n// @ts-expect-error react-dom types handled by host app\nimport { createPortal } from \"react-dom\";\nimport type { ReportType, ReportSeverity, UseGlitchgrabReturn } from \"./types\";\n\n/** Detect if the host page uses a dark or light theme */\nfunction useIsDark(): boolean {\n if (typeof window === \"undefined\") return true;\n try {\n const bg = getComputedStyle(document.body).backgroundColor;\n const match = bg.match(/\\d+/g);\n if (match && match.length >= 3) {\n const [r, g, b] = match.map(Number);\n return (r * 299 + g * 587 + b * 114) / 1000 < 128;\n }\n return window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n } catch {\n return true;\n }\n}\n\nfunction getTheme(dark: boolean) {\n return dark\n ? { bg: \"#1c1c1e\", bgSecondary: \"#27272a\", border: \"#2c2c2e\", text: \"#fafafa\", textMuted: \"#a1a1aa\", accent: \"#22d3ee\", accentText: \"#09090b\", inputBg: \"#27272a\", inputBorder: \"#3f3f46\" }\n : { bg: \"#ffffff\", bgSecondary: \"#f4f4f5\", border: \"#e4e4e7\", text: \"#18181b\", textMuted: \"#71717a\", accent: \"#0891b2\", accentText: \"#ffffff\", inputBg: \"#fafafa\", inputBorder: \"#d4d4d8\" };\n}\n\n/** Validate that report text is meaningful — rejects gibberish, throwaway words, random chars */\nfunction isLowQualityText(text: string): string | null {\n const trimmed = text.trim();\n if (!trimmed) return null;\n\n const throwaway =\n /^(done|ok|yes|no|hi|hello|hey|test|testing|asdf|qwerty|abc|xyz|foo|bar|baz|lol|lmao|idk|bruh|nice|cool|wow|sup|yo|nah|yep|nope|thanks|thx|ty|k|kk|hmm|hm|na|mm|mhm|aight|bet|gg|wp|rip|omg|pls|plz)$/i;\n if (throwaway.test(trimmed)) {\n return \"Please describe the actual issue you're experiencing\";\n }\n\n if (/(.)\\1{4,}/.test(trimmed)) {\n return \"Please provide a meaningful description\";\n }\n\n const letters = trimmed.replace(/[^a-zA-Z]/g, \"\");\n if (letters.length >= 4) {\n const vowels = letters.replace(/[^aeiouAEIOU]/g, \"\").length;\n const vowelRatio = vowels / letters.length;\n if (vowelRatio < 0.08) {\n return \"That doesn't look like a valid description\";\n }\n }\n\n const words = trimmed.split(/\\s+/).filter((w) => w.length > 0);\n if (words.length === 1 && trimmed.length < 10) {\n const techTerms =\n /^(crash|error|bug|fail|broken|slow|freeze|lag|404|500|null|undefined|nan|timeout|overflow|leak|cors|oom)$/i;\n if (!techTerms.test(trimmed)) {\n return \"Please provide more detail about the issue\";\n }\n }\n\n return null;\n}\n\ninterface ReportDialogProps {\n report: UseGlitchgrabReturn[\"report\"];\n types?: ReportType[];\n showSeverity?: boolean;\n}\n\n/**\n * The report dialog — rendered inside GlitchgrabProvider automatically.\n * Opens via the `glitchgrab:open-report` custom event (triggered by `openReportDialog()`).\n */\nexport function ReportDialog({\n report,\n types,\n showSeverity = true,\n}: ReportDialogProps) {\n // Prevent hydration mismatch — render nothing until after hydration\n const [mounted, setMounted] = useState(false);\n useEffect(() => { setMounted(true); }, []);\n\n const [isOpen, setIsOpen] = useState(false);\n const [description, setDescription] = useState(\"\");\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [submitted, setSubmitted] = useState(false);\n const [screenshot, setScreenshot] = useState<string | null>(null);\n const [previewOpen, setPreviewOpen] = useState(false);\n const fileInputRef = useRef<HTMLInputElement>(null);\n const modalRef = useRef<HTMLDivElement>(null);\n\n // Stepper state\n const [step, setStep] = useState(1);\n const [reportType, setReportType] = useState<ReportType>(\"BUG\");\n const [severity, setSeverity] = useState<ReportSeverity>(\"medium\");\n const [validationError, setValidationError] = useState<string | null>(null);\n\n const availableTypes: ReportType[] = types ?? [\"BUG\", \"FEATURE_REQUEST\", \"QUESTION\", \"OTHER\"];\n\n const isDark = useIsDark();\n const t = getTheme(isDark);\n\n const handleFileUpload = (e: React.ChangeEvent<HTMLInputElement>) => {\n const file = e.target.files?.[0];\n if (!file) return;\n const reader = new FileReader();\n reader.onload = () => {\n setScreenshot(reader.result as string);\n };\n reader.readAsDataURL(file);\n e.target.value = \"\";\n };\n\n const retakeScreenshot = async () => {\n setPreviewOpen(false);\n setIsOpen(false);\n setScreenshot(null);\n await new Promise((r) => setTimeout(r, 300));\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // silently fail\n }\n setIsOpen(true);\n };\n\n const handleOpen = async () => {\n setSubmitted(false);\n if (availableTypes.length === 1) {\n setReportType(availableTypes[0]);\n setStep(2);\n }\n try {\n const { default: html2canvas } = await import(\"html2canvas-pro\");\n const canvas = await html2canvas(document.body, {\n scale: 0.5,\n logging: false,\n useCORS: true,\n allowTaint: true,\n });\n setScreenshot(canvas.toDataURL(\"image/jpeg\", 0.6));\n } catch {\n // screenshot failed — open without it\n }\n setIsOpen(true);\n };\n\n // Listen for programmatic open via openReportDialog()\n useEffect(() => {\n const handler = (e: Event) => {\n if (isOpen) return;\n const detail = (e as CustomEvent).detail;\n if (detail?.description) setDescription(detail.description);\n if (detail?.type) {\n setReportType(detail.type);\n setStep(2);\n }\n handleOpen();\n };\n window.addEventListener(\"glitchgrab:open-report\", handler);\n return () => window.removeEventListener(\"glitchgrab:open-report\", handler);\n }, [isOpen, handleOpen]);\n\n // Close on Escape\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleClose = () => {\n setIsOpen(false);\n setStep(1);\n setReportType(\"BUG\");\n setSeverity(\"medium\");\n setValidationError(null);\n };\n\n const handleSubmit = async () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n const qualityError = isLowQualityText(description);\n if (qualityError) {\n setValidationError(qualityError);\n setStep(2);\n return;\n }\n\n setIsSubmitting(true);\n const metadata: Record<string, string> = {};\n if (screenshot) metadata.screenshot = screenshot;\n if (showSeverity && reportType === \"BUG\") {\n metadata.severity = severity;\n }\n\n const result = await report(reportType, description.trim(), Object.keys(metadata).length > 0 ? metadata : undefined);\n\n if (result) {\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n\n setTimeout(() => {\n setSubmitted(false);\n handleClose();\n }, 2000);\n }\n setIsSubmitting(false);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n if (!mounted) return null;\n\n return (\n <>\n {/* Report modal */}\n {isOpen && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n }}\n onClick={() => { if (!previewOpen) handleClose(); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: \"relative\",\n zIndex: 2147483647,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: t.bg,\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.2), 0 4px 16px rgba(0, 0, 0, 0.1)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: t.text,\n isolation: \"isolate\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: `1px solid ${t.border}`,\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <div style={{ display: \"flex\", alignItems: \"center\", gap: \"8px\" }}>\n {step > 1 && (\n <button\n type=\"button\"\n onClick={() => setStep((s) => (s - 1) as 1 | 2 | 3)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"2px\",\n display: \"flex\",\n alignItems: \"center\",\n }}\n aria-label=\"Back\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\">\n <path d=\"M10 3L5 8L10 13\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </button>\n )}\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: t.text,\n }}\n >\n {step === 1 ? \"What's on your mind?\" : step === 2 ? \"Tell us more\" : \"Review & Send\"}\n </span>\n </div>\n <button\n type=\"button\"\n onClick={handleClose}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Close\"\n >\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" style={{ display: \"block\" }}>\n <path d=\"M4 4L12 12M12 4L4 12\" stroke={t.textMuted} strokeWidth=\"2\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n <div style={{ display: \"flex\", alignItems: \"center\", justifyContent: \"center\", gap: \"0\", marginTop: \"12px\" }}>\n {[1, 2, 3].map((s, i) => (\n <div key={s} style={{ display: \"flex\", alignItems: \"center\" }}>\n <div style={{\n width: \"8px\",\n height: \"8px\",\n borderRadius: \"50%\",\n backgroundColor: s <= step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n {i < 2 && (\n <div style={{\n width: \"40px\",\n height: \"2px\",\n backgroundColor: s < step ? t.accent : t.inputBorder,\n transition: \"background-color 0.2s ease\",\n }} />\n )}\n </div>\n ))}\n </div>\n </div>\n\n {/* Body */}\n <div style={{ padding: \"16px\" }}>\n {submitted ? (\n <div\n style={{\n textAlign: \"center\",\n padding: \"20px 0\",\n color: t.accent,\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n {getTypeLabel(reportType)} sent. Thank you!\n </div>\n ) : (\n <>\n {/* Step 1: Category */}\n {step === 1 && (\n <div style={{ display: \"grid\", gridTemplateColumns: \"1fr 1fr\", gap: \"8px\" }}>\n {availableTypes.map((type) => (\n <button\n key={type}\n type=\"button\"\n onClick={() => {\n setReportType(type);\n setStep(2);\n }}\n style={{\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n gap: \"8px\",\n padding: \"16px 8px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n background: t.inputBg,\n cursor: \"pointer\",\n color: t.text,\n fontFamily: \"inherit\",\n transition: \"border-color 0.15s ease\",\n }}\n onMouseEnter={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.accent; }}\n onMouseLeave={(e) => { (e.currentTarget as HTMLElement).style.borderColor = t.inputBorder; }}\n >\n {getTypeIcon(type, t.accent)}\n <span style={{ fontSize: \"13px\", fontWeight: 600 }}>{getTypeLabel(type)}</span>\n <span style={{ fontSize: \"11px\", color: t.textMuted, lineHeight: \"1.3\" }}>{getTypeSubtitle(type)}</span>\n </button>\n ))}\n </div>\n )}\n\n {/* Step 2: Details */}\n {step === 2 && (\n <>\n <textarea\n value={description}\n onChange={(e) => { setDescription(e.target.value); if (validationError) setValidationError(null); }}\n placeholder={getPlaceholder(reportType)}\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: t.text,\n backgroundColor: t.inputBg,\n }}\n onFocus={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.accent; }}\n onBlur={(e) => { (e.target as HTMLTextAreaElement).style.borderColor = t.inputBorder; }}\n autoFocus\n />\n {showSeverity && reportType === \"BUG\" && (\n <div style={{ marginTop: \"10px\" }}>\n <span style={{ fontSize: \"12px\", color: t.textMuted, marginBottom: \"6px\", display: \"block\" }}>Severity</span>\n <div style={{ display: \"flex\", gap: \"6px\" }}>\n {([\"low\", \"medium\", \"high\"] as ReportSeverity[]).map((s) => (\n <button\n key={s}\n type=\"button\"\n onClick={() => setSeverity(s)}\n style={{\n flex: 1,\n padding: \"6px 0\",\n borderRadius: \"6px\",\n border: `1px solid ${severity === s ? t.accent : t.inputBorder}`,\n background: severity === s ? t.accent : \"transparent\",\n color: severity === s ? t.accentText : t.text,\n fontSize: \"12px\",\n fontWeight: 600,\n cursor: \"pointer\",\n fontFamily: \"inherit\",\n textTransform: \"capitalize\",\n transition: \"all 0.15s ease\",\n }}\n >\n {s}\n </button>\n ))}\n </div>\n </div>\n )}\n {validationError && (\n <p style={{ color: \"#ef4444\", fontSize: \"12px\", marginTop: \"6px\" }}>\n {validationError}\n </p>\n )}\n <button\n type=\"button\"\n onClick={() => {\n const err = isLowQualityText(description);\n if (err) { setValidationError(err); return; }\n setValidationError(null);\n setStep(3);\n }}\n disabled={!description.trim()}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: !description.trim() ? t.bgSecondary : t.accent,\n color: !description.trim() ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: !description.trim() ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n Next\n </button>\n </>\n )}\n\n {/* Step 3: Review & Send */}\n {step === 3 && (\n <>\n {/* Summary chips */}\n <div style={{ display: \"flex\", gap: \"6px\", flexWrap: \"wrap\", marginBottom: \"12px\" }}>\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n gap: \"4px\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: t.bgSecondary,\n color: t.text,\n border: `1px solid ${t.border}`,\n }}>\n {getTypeIcon(reportType, t.accent, 12)}\n {getTypeLabel(reportType)}\n </span>\n {showSeverity && reportType === \"BUG\" && (\n <span style={{\n display: \"inline-flex\",\n alignItems: \"center\",\n padding: \"4px 10px\",\n borderRadius: \"12px\",\n fontSize: \"12px\",\n fontWeight: 600,\n backgroundColor: severity === \"high\" ? \"#fef2f2\" : severity === \"medium\" ? \"#fffbeb\" : \"#f0fdf4\",\n color: severity === \"high\" ? \"#dc2626\" : severity === \"medium\" ? \"#d97706\" : \"#16a34a\",\n border: `1px solid ${severity === \"high\" ? \"#fecaca\" : severity === \"medium\" ? \"#fde68a\" : \"#bbf7d0\"}`,\n textTransform: \"capitalize\",\n }}>\n {severity}\n </span>\n )}\n </div>\n\n {/* Description preview */}\n <div style={{\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: `1px solid ${t.inputBorder}`,\n backgroundColor: t.inputBg,\n fontSize: \"13px\",\n color: t.text,\n marginBottom: \"10px\",\n maxHeight: \"80px\",\n overflow: \"hidden\",\n lineHeight: \"1.4\",\n }}>\n {description.length > 200 ? description.slice(0, 200) + \"...\" : description}\n </div>\n\n {/* Screenshot */}\n {screenshot && (\n <div style={{ marginBottom: \"10px\", position: \"relative\" }}>\n <img\n src={screenshot}\n alt=\"Page screenshot\"\n onClick={() => setPreviewOpen(true)}\n style={{\n width: \"100%\",\n borderRadius: \"6px\",\n border: `1px solid ${t.border}`,\n maxHeight: \"80px\",\n objectFit: \"cover\",\n objectPosition: \"top\",\n cursor: \"pointer\",\n }}\n />\n <button\n type=\"button\"\n onClick={() => setScreenshot(null)}\n style={{\n position: \"absolute\",\n top: \"4px\",\n right: \"4px\",\n background: \"rgba(0,0,0,0.6)\",\n border: \"none\",\n borderRadius: \"50%\",\n width: \"20px\",\n height: \"20px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n }}\n aria-label=\"Remove screenshot\"\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path d=\"M1 1L9 9M9 1L1 9\" stroke=\"#fff\" strokeWidth=\"1.5\" strokeLinecap=\"round\" />\n </svg>\n </button>\n </div>\n )}\n {!screenshot && (\n <div style={{ display: \"flex\", gap: \"6px\", marginBottom: \"10px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload screenshot\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n flex: 1,\n padding: \"8px\",\n borderRadius: \"6px\",\n border: `1px dashed ${t.inputBorder}`,\n textAlign: \"center\",\n fontSize: \"11px\",\n color: t.textMuted,\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake screenshot\n </button>\n </div>\n )}\n\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={isSubmitting}\n style={{\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor: isSubmitting ? t.bgSecondary : t.accent,\n color: isSubmitting ? t.textMuted : t.accentText,\n fontSize: \"14px\",\n fontWeight: 600,\n cursor: isSubmitting ? \"not-allowed\" : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: `1px solid ${t.border}`,\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: t.textMuted }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>,\n document.body\n )}\n\n {/* Hidden file input */}\n <input\n ref={fileInputRef}\n type=\"file\"\n accept=\"image/*\"\n onChange={handleFileUpload}\n style={{ display: \"none\" }}\n />\n\n {/* Full-screen screenshot preview */}\n {previewOpen && screenshot && createPortal(\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 2147483647,\n backgroundColor: \"rgba(0,0,0,0.85)\",\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n padding: \"16px\",\n cursor: \"pointer\",\n }}\n onClick={(e) => { e.stopPropagation(); setPreviewOpen(false); }}\n onMouseDown={(e) => e.stopPropagation()}\n >\n <img\n src={screenshot}\n alt=\"Screenshot preview\"\n onClick={(e) => e.stopPropagation()}\n style={{\n maxWidth: \"100%\",\n maxHeight: \"calc(100vh - 80px)\",\n borderRadius: \"8px\",\n objectFit: \"contain\",\n cursor: \"default\",\n }}\n />\n <span\n style={{\n marginTop: \"12px\",\n color: t.textMuted,\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>,\n document.body\n )}\n </>\n );\n}\n\n/* ─── Helpers ─── */\n\nfunction getTypeLabel(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Bug Report\";\n case \"FEATURE_REQUEST\": return \"Feature Request\";\n case \"QUESTION\": return \"Question\";\n case \"OTHER\": return \"Other\";\n }\n}\n\nfunction getTypeSubtitle(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"Something isn't working\";\n case \"FEATURE_REQUEST\": return \"Suggest an improvement\";\n case \"QUESTION\": return \"Ask a question\";\n case \"OTHER\": return \"General feedback\";\n }\n}\n\nfunction getPlaceholder(type: ReportType): string {\n switch (type) {\n case \"BUG\": return \"What went wrong?\";\n case \"FEATURE_REQUEST\": return \"Describe the feature you'd like...\";\n case \"QUESTION\": return \"What would you like to know?\";\n case \"OTHER\": return \"Tell us what's on your mind...\";\n }\n}\n\nfunction getTypeIcon(type: ReportType, color: string, size = 24): ReactNode {\n const props = { width: size, height: size, viewBox: \"0 0 24 24\", fill: \"none\", style: { flexShrink: 0 } as CSSProperties };\n switch (type) {\n case \"BUG\":\n return <svg {...props}><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\" /></svg>;\n case \"FEATURE_REQUEST\":\n return <svg {...props}><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\" /></svg>;\n case \"QUESTION\":\n return <svg {...props}><circle cx=\"12\" cy=\"12\" r=\"10\" stroke={color} strokeWidth=\"1.5\" /><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\" /></svg>;\n case \"OTHER\":\n return <svg {...props}><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\" /></svg>;\n }\n}\n","\"use client\";\n\nimport { useState, type CSSProperties, type ReactNode } from \"react\";\nimport type { ReportButtonProps } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\n/** Safe version of useGlitchgrab that returns null when outside provider */\nfunction useGlitchgrabSafe() {\n try {\n return useGlitchgrab();\n } catch {\n return null;\n }\n}\n\n/**\n * Optional trigger button for opening the report dialog.\n *\n * The dialog itself lives inside `GlitchgrabProvider` — you don't need this component\n * unless you want a visible trigger button. You can also open the dialog programmatically\n * via `useGlitchgrab().openReportDialog()`.\n *\n * @example\n * ```tsx\n * // Use the default floating button\n * <ReportButton />\n *\n * // Use your own trigger\n * <ReportButton>\n * {({ onClick }) => <button onClick={onClick}>Report</button>}\n * </ReportButton>\n *\n * // Or skip ReportButton entirely and use the hook\n * const { openReportDialog } = useGlitchgrab();\n * <button onClick={() => openReportDialog()}>Report</button>\n * ```\n */\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\n const glitchgrab = useGlitchgrabSafe();\n\n if (!glitchgrab) return null;\n\n const handleClick = async () => {\n setCapturing(true);\n glitchgrab.openReportDialog();\n setCapturing(false);\n };\n\n // Custom trigger via render prop\n if (children) {\n return <>{children({ onClick: handleClick, capturing })}</>;\n }\n\n // Default floating button\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const positionStyles: CSSProperties = {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"16px\" } : { bottom: \"16px\" }),\n };\n\n return (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={capturing}\n className={className}\n style={{\n position: \"fixed\",\n ...positionStyles,\n zIndex: 99999,\n padding: \"10px 18px\",\n borderRadius: \"24px\",\n border: \"none\",\n backgroundColor: \"#18181b\",\n color: \"#fafafa\",\n fontSize: \"14px\",\n fontWeight: 500,\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n cursor: capturing ? \"wait\" : \"pointer\",\n boxShadow:\n \"0 4px 12px rgba(0, 0, 0, 0.15), 0 1px 3px rgba(0, 0, 0, 0.1)\",\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n display: \"flex\",\n alignItems: \"center\",\n gap: \"6px\",\n opacity: capturing ? 0.7 : 1,\n }}\n onMouseEnter={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1.05)\";\n }}\n onMouseLeave={(e) => {\n (e.target as HTMLElement).style.transform = \"scale(1)\";\n }}\n aria-label={label}\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n style={{ flexShrink: 0 }}\n >\n <path\n 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\"\n fill=\"currentColor\"\n />\n </svg>\n {capturing ? \"Capturing...\" : label}\n </button>\n );\n}\n","\"use client\";\n\nimport { useState, useEffect, useCallback } from \"react\";\n\nexport interface GlitchgrabReport {\n id: string;\n source: string;\n status: string;\n rawInput: string | null;\n reporterPrimaryKey: string;\n reporterName: string;\n reporterEmail: string | null;\n reporterPhone: string | null;\n pageUrl: string | null;\n createdAt: string;\n /** Number of comments on the linked GitHub issue (0 if no issue) */\n commentCount: number;\n issue: {\n githubNumber: number;\n githubUrl: string;\n title: string;\n labels: string[];\n severity: string | null;\n githubState: string | null;\n } | null;\n}\n\nconst BASE_URL = \"https://www.glitchgrab.dev\";\n\n/**\n * Hook to fetch bug reports for a specific user.\n *\n * ```tsx\n * const { reports, isLoading, error, refetch } = useGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * });\n * ```\n */\nexport function useGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n /** Max results (default 100, max 100) */\n limit?: number;\n}): {\n reports: GlitchgrabReport[];\n isLoading: boolean;\n isFetching: boolean;\n error: string | null;\n refetch: () => Promise<void>;\n} {\n const [reports, setReports] = useState<GlitchgrabReport[]>([]);\n const [isLoading, setIsLoading] = useState(true);\n const [isFetching, setIsFetching] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const fetchReports = useCallback(async () => {\n if (!token || !userId) {\n setIsLoading(false);\n return;\n }\n\n setIsFetching(true);\n setError(null);\n\n try {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n\n if (data.success) {\n setReports(data.data ?? []);\n } else {\n setError(data.error ?? \"Failed to fetch reports\");\n }\n } catch {\n setError(\"Network error\");\n } finally {\n setIsLoading(false);\n setIsFetching(false);\n }\n }, [token, userId, limit]);\n\n useEffect(() => {\n fetchReports();\n }, [fetchReports]);\n\n return { reports, isLoading, isFetching, error, refetch: fetchReports };\n}\n\n/**\n * Standalone fetcher — use with TanStack Query or any data fetching library.\n *\n * ```tsx\n * const { data } = useQuery({\n * queryKey: [\"glitchgrab-reports\", userId],\n * queryFn: () => fetchGlitchgrabReports({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * userId: session.user.id,\n * }),\n * });\n * ```\n */\nexport async function fetchGlitchgrabReports({\n token,\n userId,\n limit = 100,\n}: {\n token: string;\n userId: string;\n limit?: number;\n}): Promise<GlitchgrabReport[]> {\n const res = await fetch(\n `${BASE_URL}/api/v1/sdk/reports?reporterPrimaryKey=${encodeURIComponent(userId)}&limit=${limit}`,\n { headers: { Authorization: `Bearer ${token}` } }\n );\n const data = await res.json();\n if (!data.success) throw new Error(data.error ?? \"Failed to fetch reports\");\n return data.data ?? [];\n}\n\n// ─── Report Actions ─────────────────────────────────────\n\nasync function reportAction(\n token: string,\n reportId: string,\n body: Record<string, string>\n): Promise<void> {\n const res = await fetch(`${BASE_URL}/api/v1/reports/${reportId}/actions`, {\n method: \"POST\",\n headers: {\n Authorization: `Bearer ${token}`,\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify(body),\n });\n const data = await res.json().catch(() => ({}));\n if (!res.ok || !data.success) throw new Error(data.error ?? \"Action failed\");\n}\n\n/**\n * Hook to manage report actions with loading/error states.\n *\n * ```tsx\n * const { approve, reject, close, isPending, error } = useGlitchgrabActions({\n * token: process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!,\n * onSuccess: () => refetch(),\n * onError: (err) => toast.error(err.message),\n * });\n *\n * <button onClick={() => approve(reportId)} disabled={isPending}>\n * {isPending ? \"...\" : \"Approve\"}\n * </button>\n * ```\n */\nexport function useGlitchgrabActions({\n token,\n onSuccess,\n onError,\n}: {\n token: string;\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n}) {\n const [isPending, setIsPending] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const run = useCallback(\n async (reportId: string, body: Record<string, string>) => {\n setIsPending(true);\n setError(null);\n try {\n await reportAction(token, reportId, body);\n onSuccess?.();\n } catch (e) {\n const err = e instanceof Error ? e : new Error(\"Action failed\");\n setError(err.message);\n onError?.(err);\n } finally {\n setIsPending(false);\n }\n },\n [token, onSuccess, onError]\n );\n\n return {\n approve: (reportId: string) => run(reportId, { action: \"label\", label: \"approved\" }),\n reject: (reportId: string) => run(reportId, { action: \"label\", label: \"rejected\" }),\n close: (reportId: string) => run(reportId, { action: \"close\" }),\n reopen: (reportId: string) => run(reportId, { action: \"reopen\" }),\n label: (reportId: string, label: string) => run(reportId, { action: \"label\", label }),\n unlabel: (reportId: string, label: string) => run(reportId, { action: \"unlabel\", label }),\n isPending,\n error,\n };\n}\n"],"mappings":"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","names":["useRef","useEffect","e","Fragment","jsx","jsxs","DEFAULT_BASE_URL","maxBreadcrumbs","useRef","useEffect","addBreadcrumb","useState","Fragment","jsx","jsxs","useState","useState","useEffect","useCallback"]}
|