glitchgrab 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +153 -102
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +10 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# glitchgrab
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Turn messy bugs into structured GitHub issues with AI. Drop-in SDK for Next.js apps.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -12,7 +12,7 @@ bun add glitchgrab
|
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
|
-
Wrap your app with `GlitchgrabProvider
|
|
15
|
+
Wrap your app with `GlitchgrabProvider`:
|
|
16
16
|
|
|
17
17
|
```tsx
|
|
18
18
|
// app/layout.tsx
|
|
@@ -20,148 +20,199 @@ import { GlitchgrabProvider } from "glitchgrab";
|
|
|
20
20
|
|
|
21
21
|
export default function RootLayout({ children }) {
|
|
22
22
|
return (
|
|
23
|
-
<GlitchgrabProvider token=
|
|
23
|
+
<GlitchgrabProvider token={process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!}>
|
|
24
|
+
{children}
|
|
25
|
+
</GlitchgrabProvider>
|
|
24
26
|
);
|
|
25
27
|
}
|
|
26
28
|
```
|
|
27
29
|
|
|
28
|
-
|
|
30
|
+
## Session (User Tracking)
|
|
29
31
|
|
|
30
|
-
|
|
31
|
-
- Error boundary around your entire app
|
|
32
|
-
- Page visit tracking for reproduction context
|
|
33
|
-
- URL sanitization (strips tokens, keys, passwords)
|
|
34
|
-
|
|
35
|
-
## Get a Token
|
|
36
|
-
|
|
37
|
-
1. Go to [glitchgrab.dev](https://glitchgrab.dev)
|
|
38
|
-
2. Sign in with GitHub
|
|
39
|
-
3. Connect a repo
|
|
40
|
-
4. Generate an API token
|
|
41
|
-
|
|
42
|
-
## Usage
|
|
43
|
-
|
|
44
|
-
### 1. Auto-Capture (zero config)
|
|
45
|
-
|
|
46
|
-
Just add the provider. Production errors are captured automatically with:
|
|
47
|
-
|
|
48
|
-
- Error message and stack trace
|
|
49
|
-
- Current URL (sanitized)
|
|
50
|
-
- User agent
|
|
51
|
-
- Visited pages history
|
|
52
|
-
|
|
53
|
-
### 2. Manual Bug Reporting (`useGlitchgrab` hook)
|
|
54
|
-
|
|
55
|
-
Build your own report button or trigger:
|
|
32
|
+
Pass a `session` prop so bug reports include the reporter's identity. This lets you trace which user reported each bug.
|
|
56
33
|
|
|
57
34
|
```tsx
|
|
58
|
-
|
|
59
|
-
import {
|
|
60
|
-
|
|
61
|
-
function
|
|
62
|
-
const {
|
|
35
|
+
import { GlitchgrabProvider, type GlitchgrabSession } from "glitchgrab";
|
|
36
|
+
import { useSession } from "next-auth/react"; // or your auth library
|
|
37
|
+
|
|
38
|
+
function Providers({ children }) {
|
|
39
|
+
const { data: authSession } = useSession();
|
|
40
|
+
|
|
41
|
+
// Map your auth session to GlitchgrabSession
|
|
42
|
+
const session: GlitchgrabSession | null = authSession?.user
|
|
43
|
+
? {
|
|
44
|
+
userId: authSession.user.id, // required - your DB primary key
|
|
45
|
+
name: authSession.user.name, // required - display name
|
|
46
|
+
email: authSession.user.email, // optional
|
|
47
|
+
phone: authSession.user.phone, // optional
|
|
48
|
+
}
|
|
49
|
+
: null;
|
|
63
50
|
|
|
64
51
|
return (
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
52
|
+
<GlitchgrabProvider
|
|
53
|
+
token={process.env.NEXT_PUBLIC_GLITCHGRAB_TOKEN!}
|
|
54
|
+
session={session}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</GlitchgrabProvider>
|
|
68
58
|
);
|
|
69
59
|
}
|
|
70
60
|
```
|
|
71
61
|
|
|
72
|
-
|
|
62
|
+
### GlitchgrabSession type
|
|
73
63
|
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
userId:
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
64
|
+
```ts
|
|
65
|
+
interface GlitchgrabSession {
|
|
66
|
+
userId: string; // required - primary key from your database
|
|
67
|
+
name: string; // required - reporter's display name
|
|
68
|
+
email?: string | null; // optional
|
|
69
|
+
phone?: string | null; // optional
|
|
70
|
+
[key: string]: unknown; // any extra fields
|
|
71
|
+
}
|
|
80
72
|
```
|
|
81
73
|
|
|
82
|
-
|
|
74
|
+
The `userId` is stored with every report. Use it to look up which user reported a bug in your own database.
|
|
83
75
|
|
|
84
|
-
|
|
76
|
+
## Report Button
|
|
77
|
+
|
|
78
|
+
### Default floating button
|
|
85
79
|
|
|
86
80
|
```tsx
|
|
87
|
-
import {
|
|
81
|
+
import { ReportButton } from "glitchgrab";
|
|
88
82
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
<ReportButton />
|
|
92
|
-
</GlitchgrabProvider>;
|
|
83
|
+
// Floating button at bottom-right (default)
|
|
84
|
+
<ReportButton position="bottom-right" label="Report Bug" />
|
|
93
85
|
```
|
|
94
86
|
|
|
95
|
-
|
|
87
|
+
### Custom trigger (headless)
|
|
88
|
+
|
|
89
|
+
Use the render prop to bring your own button UI:
|
|
96
90
|
|
|
97
91
|
```tsx
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
import { ReportButton } from "glitchgrab";
|
|
93
|
+
|
|
94
|
+
<ReportButton>
|
|
95
|
+
{({ onClick, capturing }) => (
|
|
96
|
+
<button onClick={onClick} disabled={capturing}>
|
|
97
|
+
{capturing ? "Capturing..." : "Report a Bug"}
|
|
98
|
+
</button>
|
|
99
|
+
)}
|
|
100
|
+
</ReportButton>
|
|
102
101
|
```
|
|
103
102
|
|
|
104
|
-
|
|
103
|
+
The modal handles screenshot capture, preview, upload, retake, and submission. Your custom button just triggers it.
|
|
105
104
|
|
|
106
|
-
|
|
105
|
+
## Programmatic Reporting
|
|
106
|
+
|
|
107
|
+
Use the `useGlitchgrab` hook to report bugs from code:
|
|
107
108
|
|
|
108
109
|
```tsx
|
|
109
|
-
import {
|
|
110
|
+
import { useGlitchgrab } from "glitchgrab";
|
|
110
111
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
fallback={<div>Something went wrong in this section</div>}
|
|
114
|
-
>
|
|
115
|
-
<DangerousComponent />
|
|
116
|
-
</GlitchgrabErrorBoundary>;
|
|
117
|
-
```
|
|
112
|
+
function MyComponent() {
|
|
113
|
+
const { reportBug, report, addBreadcrumb } = useGlitchgrab();
|
|
118
114
|
|
|
119
|
-
|
|
115
|
+
// Report a bug
|
|
116
|
+
await reportBug("Button not working on mobile");
|
|
120
117
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
console.log("Captured:", error.message);
|
|
128
|
-
}}
|
|
129
|
-
fallback={<ErrorPage />} // Optional — what to show when the app crashes
|
|
130
|
-
>
|
|
131
|
-
{children}
|
|
132
|
-
</GlitchgrabProvider>
|
|
118
|
+
// Report with a specific type
|
|
119
|
+
await report("FEATURE_REQUEST", "Add dark mode support");
|
|
120
|
+
|
|
121
|
+
// Add custom breadcrumbs for debugging context
|
|
122
|
+
addBreadcrumb("User clicked checkout", { cartSize: "3" });
|
|
123
|
+
}
|
|
133
124
|
```
|
|
134
125
|
|
|
135
|
-
##
|
|
126
|
+
## Fetching Reports by User
|
|
127
|
+
|
|
128
|
+
Use the REST API to fetch reports for a specific user by their primary key:
|
|
136
129
|
|
|
137
|
-
|
|
130
|
+
```bash
|
|
131
|
+
# Fetch all reports
|
|
132
|
+
curl -H "Authorization: Bearer gg_your_token" \
|
|
133
|
+
https://glitchgrab.dev/api/v1/sdk/reports
|
|
134
|
+
|
|
135
|
+
# Fetch reports by a specific user
|
|
136
|
+
curl -H "Authorization: Bearer gg_your_token" \
|
|
137
|
+
"https://glitchgrab.dev/api/v1/sdk/reports?reporterPrimaryKey=user_123"
|
|
138
138
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
| `GlitchgrabErrorBoundary` | Standalone error boundary for specific sections. |
|
|
139
|
+
# Filter by status
|
|
140
|
+
curl -H "Authorization: Bearer gg_your_token" \
|
|
141
|
+
"https://glitchgrab.dev/api/v1/sdk/reports?status=CREATED&limit=20"
|
|
142
|
+
```
|
|
144
143
|
|
|
145
|
-
###
|
|
144
|
+
### Response
|
|
145
|
+
|
|
146
|
+
```json
|
|
147
|
+
{
|
|
148
|
+
"success": true,
|
|
149
|
+
"data": [
|
|
150
|
+
{
|
|
151
|
+
"id": "cmn7abc123",
|
|
152
|
+
"source": "SDK_USER_REPORT",
|
|
153
|
+
"status": "CREATED",
|
|
154
|
+
"rawInput": "Button not working",
|
|
155
|
+
"reporterPrimaryKey": "user_123",
|
|
156
|
+
"reporterName": "John Doe",
|
|
157
|
+
"reporterEmail": "john@example.com",
|
|
158
|
+
"reporterPhone": null,
|
|
159
|
+
"pageUrl": "/dashboard/settings",
|
|
160
|
+
"createdAt": "2026-03-26T12:00:00.000Z",
|
|
161
|
+
"issue": {
|
|
162
|
+
"githubNumber": 42,
|
|
163
|
+
"githubUrl": "https://github.com/your/repo/issues/42",
|
|
164
|
+
"title": "Button not working"
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
```
|
|
146
170
|
|
|
147
|
-
|
|
148
|
-
| ----------------- | ------------------------------- | -------------------------------------- |
|
|
149
|
-
| `useGlitchgrab()` | `{ reportBug, token, baseUrl }` | Access bug reporting in any component. |
|
|
171
|
+
## Error Boundary
|
|
150
172
|
|
|
151
|
-
|
|
173
|
+
Wrap components to auto-capture React errors:
|
|
152
174
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
| `sanitizeUrl(url)` | Strips sensitive query params from URLs. |
|
|
156
|
-
| `captureContext(pages)` | Returns current URL, user agent, timestamp. |
|
|
157
|
-
| `sendReport(payload, baseUrl)` | Low-level function to send a report. |
|
|
175
|
+
```tsx
|
|
176
|
+
import { GlitchgrabErrorBoundary } from "glitchgrab";
|
|
158
177
|
|
|
159
|
-
|
|
178
|
+
<GlitchgrabErrorBoundary fallback={<p>Something went wrong</p>}>
|
|
179
|
+
<MyComponent />
|
|
180
|
+
</GlitchgrabErrorBoundary>
|
|
181
|
+
```
|
|
160
182
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
183
|
+
## Configuration
|
|
184
|
+
|
|
185
|
+
| Prop | Type | Default | Description |
|
|
186
|
+
|------|------|---------|-------------|
|
|
187
|
+
| `token` | `string` | required | Your Glitchgrab API token (`gg_...`) |
|
|
188
|
+
| `session` | `GlitchgrabSession \| null` | `null` | Logged-in user info for report attribution |
|
|
189
|
+
| `baseUrl` | `string` | `https://glitchgrab.dev` | API base URL |
|
|
190
|
+
| `breadcrumbs` | `boolean` | `true` | Enable automatic breadcrumb tracking |
|
|
191
|
+
| `maxBreadcrumbs` | `number` | `50` | Max breadcrumbs to keep |
|
|
192
|
+
| `onError` | `(error: Error) => void` | - | Called on unhandled errors |
|
|
193
|
+
| `onReportSent` | `(result: ReportResult) => void` | - | Called after a report is sent |
|
|
194
|
+
| `fallback` | `ReactNode` | - | Error boundary fallback UI |
|
|
195
|
+
|
|
196
|
+
## Auto-Capture
|
|
197
|
+
|
|
198
|
+
In production (`NODE_ENV=production`), the SDK automatically captures:
|
|
199
|
+
- Unhandled JavaScript errors
|
|
200
|
+
- Unhandled promise rejections
|
|
201
|
+
- Console errors (as breadcrumbs)
|
|
202
|
+
- Navigation events (as breadcrumbs)
|
|
203
|
+
- API calls (as breadcrumbs)
|
|
204
|
+
|
|
205
|
+
Auto-capture is **disabled in development** to avoid noisy issues.
|
|
206
|
+
|
|
207
|
+
## What gets included in each report
|
|
208
|
+
|
|
209
|
+
- Description from the user
|
|
210
|
+
- Screenshot (auto-captured or uploaded)
|
|
211
|
+
- Page URL and user agent
|
|
212
|
+
- Device info (screen size, viewport, platform, language, color scheme)
|
|
213
|
+
- Page navigation history
|
|
214
|
+
- Activity log (last 15 breadcrumbs)
|
|
215
|
+
- Session info (userId, name, email, phone)
|
|
165
216
|
|
|
166
217
|
## License
|
|
167
218
|
|
package/dist/index.d.mts
CHANGED
|
@@ -133,7 +133,7 @@ declare function ReportButton({ position, label, className, children, }: ReportB
|
|
|
133
133
|
onClick: () => void;
|
|
134
134
|
capturing: boolean;
|
|
135
135
|
}) => ReactNode;
|
|
136
|
-
}): react_jsx_runtime.JSX.Element;
|
|
136
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
137
137
|
|
|
138
138
|
interface ErrorBoundaryProps {
|
|
139
139
|
token: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -133,7 +133,7 @@ declare function ReportButton({ position, label, className, children, }: ReportB
|
|
|
133
133
|
onClick: () => void;
|
|
134
134
|
capturing: boolean;
|
|
135
135
|
}) => ReactNode;
|
|
136
|
-
}): react_jsx_runtime.JSX.Element;
|
|
136
|
+
}): react_jsx_runtime.JSX.Element | null;
|
|
137
137
|
|
|
138
138
|
interface ErrorBoundaryProps {
|
|
139
139
|
token: string;
|
package/dist/index.js
CHANGED
|
@@ -580,6 +580,13 @@ function GlitchgrabProvider(props) {
|
|
|
580
580
|
// src/report-button.tsx
|
|
581
581
|
var import_react2 = require("react");
|
|
582
582
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
583
|
+
function useGlitchgrabSafe() {
|
|
584
|
+
try {
|
|
585
|
+
return useGlitchgrab();
|
|
586
|
+
} catch (e) {
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
583
590
|
function ReportButton({
|
|
584
591
|
position = "bottom-right",
|
|
585
592
|
label = "Report Bug",
|
|
@@ -596,7 +603,9 @@ function ReportButton({
|
|
|
596
603
|
const [previewOpen, setPreviewOpen] = (0, import_react2.useState)(false);
|
|
597
604
|
const fileInputRef = (0, import_react2.useRef)(null);
|
|
598
605
|
const modalRef = (0, import_react2.useRef)(null);
|
|
599
|
-
const
|
|
606
|
+
const glitchgrab = useGlitchgrabSafe();
|
|
607
|
+
if (!glitchgrab) return null;
|
|
608
|
+
const { reportBug } = glitchgrab;
|
|
600
609
|
const handleFileUpload = (e) => {
|
|
601
610
|
var _a2;
|
|
602
611
|
const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
|
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-button.tsx"],"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// ─── 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 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 { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://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}: 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]\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 return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\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 </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 // Auto-detect baseUrl from window.location if not provided\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || (typeof window !== \"undefined\" ? window.location.origin : 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://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\";\nimport type { ReportButtonProps } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n /** Render prop — receives { onClick, capturing } so you can use your own trigger button */\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\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 const { reportBug } = useGlitchgrab();\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 // Small delay so the modal is gone before capture\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 setCapturing(true);\n setSubmitted(false);\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 setCapturing(false);\n setIsOpen(true);\n };\n\n // Close modal on Escape key\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else setIsOpen(false);\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleSubmit = () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n setIsSubmitting(true);\n reportBug(description.trim(), screenshot ? { screenshot } : undefined);\n\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n setIsSubmitting(false);\n\n setTimeout(() => {\n setSubmitted(false);\n setIsOpen(false);\n }, 2000);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const modalPositionStyles: CSSProperties = children\n ? {} // user controls positioning\n : {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"64px\" } : { bottom: \"64px\" }),\n };\n\n return (\n <>\n {/* Trigger: user's custom button OR default floating button */}\n {children ? (\n children({ onClick: handleOpen, capturing })\n ) : (\n <DefaultTrigger\n onClick={handleOpen}\n capturing={capturing}\n label={label}\n className={className}\n position={position}\n isLeft={isLeft}\n isTop={isTop}\n />\n )}\n\n {/* Report modal */}\n {isOpen && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 99999,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n }}\n onClick={() => { if (!previewOpen) setIsOpen(false); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: children ? \"relative\" : \"fixed\",\n ...modalPositionStyles,\n zIndex: 100000,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: \"#1c1c1e\",\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: \"#fafafa\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: \"1px solid #2c2c2e\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: \"#fafafa\",\n }}\n >\n Report a Bug\n </span>\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n color: \"#a1a1aa\",\n fontSize: \"18px\",\n lineHeight: 1,\n }}\n aria-label=\"Close\"\n >\n ×\n </button>\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: \"#22d3ee\",\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n Bug report sent. Thank you!\n </div>\n ) : (\n <>\n {/* Screenshot preview */}\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 #2c2c2e\",\n maxHeight: \"120px\",\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 color: \"#fff\",\n width: \"20px\",\n height: \"20px\",\n fontSize: \"12px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n lineHeight: 1,\n }}\n aria-label=\"Remove screenshot\"\n >\n ×\n </button>\n <div\n style={{\n position: \"absolute\",\n bottom: \"4px\",\n left: \"6px\",\n right: \"6px\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#fff\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n }}\n >\n Screenshot ({Math.round(screenshot.length * 0.75 / 1024)}KB) — click to preview\n </span>\n <div style={{ display: \"flex\", gap: \"4px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake\n </button>\n </div>\n </div>\n </div>\n )}\n {!screenshot && !submitted && (\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n marginBottom: \"10px\",\n padding: \"10px\",\n borderRadius: \"6px\",\n border: \"1px dashed #3f3f46\",\n textAlign: \"center\",\n fontSize: \"11px\",\n color: \"#71717a\",\n width: \"100%\",\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Click to upload a screenshot\n </button>\n )}\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Describe what went wrong...\"\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: \"1px solid #3f3f46\",\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: \"#fafafa\",\n backgroundColor: \"#27272a\",\n }}\n onFocus={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#22d3ee\";\n }}\n onBlur={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#3f3f46\";\n }}\n autoFocus\n />\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!description.trim() || isSubmitting}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor:\n !description.trim() || isSubmitting\n ? \"#3f3f46\"\n : \"#22d3ee\",\n color:\n !description.trim() || isSubmitting\n ? \"#71717a\"\n : \"#09090b\",\n fontSize: \"14px\",\n fontWeight: 600,\n cursor:\n !description.trim() || isSubmitting\n ? \"not-allowed\"\n : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: \"1px solid #2c2c2e\",\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: \"#52525b\" }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Hidden file input for screenshot upload */}\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 && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 200000,\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: \"#a1a1aa\",\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>\n )}\n </>\n );\n}\n\n/** Default floating trigger button (used when no children provided) */\nfunction DefaultTrigger({\n onClick,\n capturing,\n label,\n className,\n position,\n isLeft,\n isTop,\n}: {\n onClick: () => void;\n capturing: boolean;\n label: string;\n className?: string;\n position?: string;\n isLeft: boolean;\n isTop: boolean;\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={onClick}\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"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACEA,mBAOO;;;ACPP,YAAuB;;;ACAvB,IAAM,cAAc;AAEpB,IAAI,cAA4B,CAAC;AACjC,IAAI,iBAAiB;AACrB,IAAI,cAAc;AAEX,SAAS,gBAAgB,KAAc;AAC5C,MAAI,YAAa;AACjB,mBAAiB,oBAAO;AAExB,MAAI;AACF,QAAI,OAAO,WAAW,YAAa;AACnC,qBAAiB;AACjB,mBAAe;AACf,wBAAoB;AACpB,oBAAgB;AAChB,kBAAc;AAAA,EAChB,SAAQ;AAAA,EAER;AACF;AAEO,SAAS,cACd,MACA,SACA,MACA;AACA,MAAI;AACF,gBAAY,KAAK;AAAA,MACf;AAAA,MACA,SAAS,QAAQ,MAAM,GAAG,GAAG;AAAA,MAC7B,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC;AAAA,IACF,CAAC;AACD,QAAI,YAAY,SAAS,gBAAgB;AACvC,oBAAc,YAAY,MAAM,CAAC,cAAc;AAAA,IACjD;AAAA,EACF,SAAQ;AAAA,EAER;AACF;AAEO,SAAS,iBAA+B;AAC7C,SAAO,CAAC,GAAG,WAAW;AACxB;AAEO,SAAS,mBAAmB;AACjC,gBAAc,CAAC;AACjB;AAIA,SAAS,mBAAmB;AAC1B,QAAM,UAAU,QAAQ;AACxB,QAAM,WAAW,QAAQ;AACzB,QAAM,YAAY,QAAQ;AAE1B,UAAQ,MAAM,YAAa,MAAiB;AAC1C,kBAAc,WAAW,SAAS,aAAa,IAAI,CAAC,EAAE;AACtD,YAAQ,MAAM,SAAS,IAAI;AAAA,EAC7B;AAEA,UAAQ,OAAO,YAAa,MAAiB;AAC3C,kBAAc,WAAW,UAAU,aAAa,IAAI,CAAC,EAAE;AACvD,aAAS,MAAM,SAAS,IAAI;AAAA,EAC9B;AAEA,UAAQ,QAAQ,YAAa,MAAiB;AAC5C,kBAAc,WAAW,WAAW,aAAa,IAAI,CAAC,EAAE;AACxD,cAAU,MAAM,SAAS,IAAI;AAAA,EAC/B;AACF;AAEA,SAAS,aAAa,MAAyB;AAC7C,MAAI;AACF,WAAO,KACJ,IAAI,CAAC,MAAM;AACV,UAAI,OAAO,MAAM,SAAU,QAAO;AAClC,UAAI,aAAa,MAAO,QAAO,EAAE;AACjC,UAAI;AACF,eAAO,KAAK,UAAU,CAAC;AAAA,MACzB,SAAQ;AACN,eAAO,OAAO,CAAC;AAAA,MACjB;AAAA,IACF,CAAC,EACA,KAAK,GAAG,EACR,MAAM,GAAG,GAAG;AAAA,EACjB,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAIA,SAAS,iBAAiB;AACxB,QAAM,YAAY,OAAO;AAEzB,SAAO,QAAQ,eAAgB,OAAO,MAAM;AAnG9C;AAoGI,UAAM,MACJ,OAAO,UAAU,WACb,QACA,iBAAiB,MACf,MAAM,SAAS,IACf,iBAAiB,UACf,MAAM,MACN,OAAO,KAAK;AACtB,UAAM,UAAS,kCAAM,WAAN,YAAgB;AAC/B,UAAM,QAAQ,KAAK,IAAI;AAEvB,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,MAAM,QAAQ,CAAC,OAAO,IAAI,CAAC;AAC5D,oBAAc,OAAO,GAAG,MAAM,IAAI,IAAI,MAAM,GAAG,GAAG,CAAC,WAAM,SAAS,MAAM,IAAI;AAAA,QAC1E;AAAA,QACA,QAAQ,OAAO,SAAS,MAAM;AAAA,QAC9B,UAAU,GAAG,KAAK,IAAI,IAAI,KAAK;AAAA,MACjC,CAAC;AACD,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,oBAAc,OAAO,GAAG,MAAM,IAAI,IAAI,MAAM,GAAG,GAAG,CAAC,kBAAa;AAAA,QAC9D;AAAA,QACA,OAAO,eAAe,QAAQ,IAAI,UAAU;AAAA,QAC5C,UAAU,GAAG,KAAK,IAAI,IAAI,KAAK;AAAA,MACjC,CAAC;AACD,YAAM;AAAA,IACR;AAAA,EACF;AACF;AAIA,SAAS,sBAAsB;AAC7B,QAAM,WAAW,QAAQ,UAAU,KAAK,OAAO;AAC/C,QAAM,cAAc,QAAQ,aAAa,KAAK,OAAO;AAErD,UAAQ,YAAY,YAAa,MAAM;AACrC,aAAS,GAAG,IAAI;AAChB,kBAAc,cAAc,eAAe,OAAO,SAAS,QAAQ,EAAE;AAAA,EACvE;AAEA,UAAQ,eAAe,YAAa,MAAM;AACxC,gBAAY,GAAG,IAAI;AACnB,kBAAc,cAAc,cAAc,OAAO,SAAS,QAAQ,EAAE;AAAA,EACtE;AAEA,SAAO,iBAAiB,YAAY,MAAM;AACxC,kBAAc,cAAc,mBAAmB,OAAO,SAAS,QAAQ,EAAE;AAAA,EAC3E,CAAC;AACH;AAIA,SAAS,kBAAkB;AACzB,WAAS;AAAA,IACP;AAAA,IACA,CAAC,MAAM;AA5JX;AA6JM,UAAI;AACF,cAAM,SAAS,EAAE;AACjB,cAAM,OAAM,YAAO,YAAP,mBAAgB;AAC5B,cAAM,QAAO,kBAAO,gBAAP,mBAAoB,OAAO,MAAM,GAAG,QAApC,YAA2C;AACxD,cAAM,KAAK,OAAO,KAAK,IAAI,OAAO,EAAE,KAAK;AACzC,cAAM,MAAM,OAAO,aAAa,OAAO,OAAO,cAAc,WACxD,IAAI,OAAO,UAAU,MAAM,GAAG,EAAE,CAAC,CAAC,KAClC;AAEJ,sBAAc,SAAS,SAAS,GAAG,GAAG,EAAE,GAAG,GAAG,KAAK,IAAI,GAAG;AAAA,MAC5D,SAAQA,IAAA;AAAA,MAER;AAAA,IACF;AAAA,IACA,EAAE,SAAS,KAAK;AAAA,EAClB;AACF;;;AC1KA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EAAS;AAAA,EAAO;AAAA,EAAU;AAAA,EAAY;AAAA,EAAU;AAAA,EAAQ;AAAA,EACxD;AAAA,EAAW;AAAA,EAAa;AAAA,EAAc;AAAA,EAAW;AAAA,EAAU;AAAA,EAC3D;AAAA,EAAiB;AAAA,EAAiB;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAS;AAAA,EAAc;AAC5E;AAEO,SAAS,YAAY,KAAqB;AATjD;AAUE,MAAI;AACF,UAAM,SAAS,IAAI,IAAI,GAAG;AAC1B,UAAM,SAAS,IAAI,gBAAgB,OAAO,MAAM;AAChD,QAAI,WAAW;AACf,eAAW,OAAO,MAAM,KAAK,OAAO,KAAK,CAAC,GAAG;AAC3C,UAAI,iBAAiB,KAAK,CAAC,MAAM,IAAI,YAAY,EAAE,SAAS,CAAC,CAAC,GAAG;AAC/D,eAAO,IAAI,KAAK,YAAY;AAC5B,mBAAW;AAAA,MACb;AAAA,IACF;AACA,QAAI,SAAU,QAAO,SAAS,OAAO,SAAS;AAC9C,WAAO,OAAO,SAAS;AAAA,EACzB,SAAQ;AACN,YAAO,SAAI,MAAM,GAAG,EAAE,CAAC,MAAhB,YAAqB;AAAA,EAC9B;AACF;AAEO,SAAS,oBAAuC;AA3BvD;AA4BE,MAAI;AACF,QAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,WAAO;AAAA,MACL,aAAa,OAAO;AAAA,MACpB,cAAc,OAAO;AAAA,MACrB,eAAe,OAAO;AAAA,MACtB,gBAAgB,OAAO;AAAA,MACvB,WAAU,eAAU,aAAV,YAAsB;AAAA,MAChC,WAAU,eAAU,aAAV,YAAsB;AAAA,MAChC,QAAQ,UAAU;AAAA,MAClB,aAAa,OAAO,WAAW,8BAA8B,EAAE,UAAU,SAAS;AAAA,MAClF,mBAAkB,YAAO,qBAAP,YAA2B;AAAA,IAC/C;AAAA,EACF,SAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,eAAe,cAAyC;AACtE,MAAI;AACF,WAAO;AAAA,MACL,KAAK,YAAY,OAAO,WAAW,cAAc,OAAO,SAAS,OAAO,EAAE;AAAA,MAC1E,WAAW,OAAO,cAAc,cAAc,UAAU,YAAY;AAAA,MACpE,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,cAAc,aAAa,IAAI,WAAW;AAAA,MAC1C,aAAa,eAAe;AAAA,MAC5B,YAAY,kBAAkB;AAAA,IAChC;AAAA,EACF,SAAQ;AACN,WAAO;AAAA,MACL,KAAK;AAAA,MACL,WAAW;AAAA,MACX,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,MAClC,cAAc,CAAC;AAAA,MACf,aAAa,CAAC;AAAA,MACd,YAAY;AAAA,IACd;AAAA,EACF;AACF;AAEA,IAAM,mBAAmB;AACzB,IAAM,cAAc;AACpB,IAAM,gBAAgB;AAMtB,eAAsB,WACpB,SACA,SAC8B;AA/EhC;AAgFE,MAAI;AACF,UAAM,MAAM,GAAG,4BAAW,gBAAgB;AAC1C,UAAM,OAAO,KAAK,UAAU,OAAO;AACnC,UAAM,UAAkC;AAAA,MACtC,gBAAgB;AAAA,MAChB,eAAe,UAAU,QAAQ,KAAK;AAAA,IACxC;AAEA,aAAS,UAAU,GAAG,UAAU,aAAa,WAAW;AACtD,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,KAAK;AAAA,UAChC,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,WAAW;AAAA,QACb,CAAC;AAED,YAAI,SAAS,IAAI;AACf,gBAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,kBAAO,UAAK,SAAL,YAAa,EAAE,SAAS,KAAK,QAAQ;AAAA,QAC9C;AAEA,YAAI,SAAS,UAAU,OAAO,SAAS,SAAS,OAAO,SAAS,WAAW,KAAK;AAC9E,iBAAO;AAAA,QACT;AAAA,MACF,SAAQ;AAAA,MAER;AAEA,UAAI,UAAU,cAAc,GAAG;AAC7B,cAAM,IAAI;AAAA,UAAQ,CAAC,YACjB,WAAW,SAAS,gBAAgB,KAAK,IAAI,GAAG,OAAO,CAAC;AAAA,QAC1D;AAAA,MACF;AAAA,IACF;AAGA,QAAI,OAAO,cAAc,eAAe,UAAU,YAAY;AAC5D,UAAI;AACF,kBAAU,WAAW,KAAK,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,MAAM,mBAAmB,CAAC,CAAC;AAAA,MAC1E,SAAQ;AAAA,MAER;AAAA,IACF;AAEA,WAAO;AAAA,EACT,SAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AF9GO,IAAM,0BAAN,cAA4C,gBAGjD;AAAA,EACA,YAAY,OAA2B;AACrC,UAAM,KAAK;AACX,SAAK,QAAQ,EAAE,UAAU,MAAM;AAAA,EACjC;AAAA,EAEA,OAAO,2BAA+C;AACpD,WAAO,EAAE,UAAU,KAAK;AAAA,EAC1B;AAAA,EAEA,kBAAkB,OAAc,WAAkC;AAhCpE;AAiCI,QAAI;AACF,YAAM,UAAU,eAAe,KAAK,MAAM,YAAY;AAEtD,YAAM,UAAyB;AAAA,QAC7B,OAAO,KAAK,MAAM;AAAA,QAClB,QAAQ;AAAA,QACR,MAAM;AAAA,QACN,cAAc,MAAM;AAAA,QACpB,YAAY,MAAM;AAAA,QAClB,iBAAgB,eAAU,mBAAV,YAA4B;AAAA,QAC5C,SAAS,QAAQ;AAAA,QACjB,WAAW,QAAQ;AAAA,QACnB,aAAa,QAAQ;AAAA,QACrB,aAAY,aAAQ,eAAR,YAAsB;AAAA,QAClC,UAAU;AAAA,UACR,WAAW,QAAQ;AAAA,UACnB,cAAc,KAAK,UAAU,QAAQ,YAAY;AAAA,QACnD;AAAA,MACF;AAEA,iBAAW,SAAS,KAAK,MAAM,OAAO;AAEtC,UAAI,KAAK,MAAM,SAAS;AACtB,aAAK,MAAM,QAAQ,KAAK;AAAA,MAC1B;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEA,SAA0B;AACxB,QAAI,KAAK,MAAM,UAAU;AACvB,UAAI,KAAK,MAAM,UAAU;AACvB,eAAO,KAAK,MAAM;AAAA,MACpB;AAGA,aAAO,KAAK,MAAM;AAAA,IACpB;AAEA,WAAO,KAAK,MAAM;AAAA,EACpB;AACF;;;AD4LM;AA9ON,IAAMC,oBAAmB;AAEzB,IAAM,wBAAoB,4BAA0C,IAAI;AAmBjE,SAAS,gBAAqC;AACnD,QAAM,UAAM,yBAAW,iBAAiB;AACxC,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,wDAAwD;AAAA,EAC1E;AACA,SAAO;AACT;AAEA,SAAS,wBAAwB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa,oBAAoB;AAAA,EACjC,gBAAAC,kBAAiB;AAAA,EACjB;AAAA,EACA;AACF,GAA4B;AAC1B,QAAM,sBAAkB,qBAAiB,CAAC,CAAC;AAG3C,8BAAU,MAAM;AACd,QAAI,mBAAmB;AACrB,sBAAgBA,eAAc;AAAA,IAChC;AAAA,EACF,GAAG,CAAC,mBAAmBA,eAAc,CAAC;AAGtC,8BAAU,MAAM;AACd,QAAI;AACF,UAAI,OAAO,WAAW,YAAa;AAEnC,YAAM,YAAY,MAAM;AACtB,YAAI;AACF,gBAAM,YAAY,YAAY,OAAO,SAAS,IAAI;AAClD,gBAAM,QAAQ,gBAAgB;AAC9B,cAAI,MAAM,MAAM,SAAS,CAAC,MAAM,WAAW;AACzC,kBAAM,KAAK,SAAS;AACpB,gBAAI,MAAM,SAAS,IAAI;AACrB,oBAAM,OAAO,GAAG,MAAM,SAAS,EAAE;AAAA,YACnC;AAAA,UACF;AAAA,QACF,SAAQ;AAAA,QAER;AAAA,MACF;AAEA,gBAAU;AACV,YAAM,iBAAiB,MAAM,UAAU;AACvC,aAAO,iBAAiB,YAAY,cAAc;AAElD,YAAM,gBAAgB,QAAQ,UAAU,KAAK,OAAO;AACpD,YAAM,mBAAmB,QAAQ,aAAa,KAAK,OAAO;AAE1D,cAAQ,YAAY,YAAa,MAAM;AACrC,sBAAc,GAAG,IAAI;AACrB,kBAAU;AAAA,MACZ;AACA,cAAQ,eAAe,YAAa,MAAM;AACxC,yBAAiB,GAAG,IAAI;AACxB,kBAAU;AAAA,MACZ;AAEA,aAAO,MAAM;AACX,eAAO,oBAAoB,YAAY,cAAc;AACrD,gBAAQ,YAAY;AACpB,gBAAQ,eAAe;AAAA,MACzB;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,CAAC;AAGL,8BAAU,MAAM;AACd,QAAI;AACF,UAAI,OAAO,WAAW,YAAa;AACnC,UAAI,QAAQ,IAAI,aAAa,cAAe;AAE5C,YAAM,cAAc,CAAC,UAAsB;AA9HjD;AA+HQ,YAAI;AACF,gBAAM,UAAU,eAAe,gBAAgB,OAAO;AACtD,gBAAM,UAAyB;AAAA,YAC7B;AAAA,YACA,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,cAAc,MAAM;AAAA,YACpB,aAAY,WAAM,UAAN,mBAAa;AAAA,YACzB,SAAS,QAAQ;AAAA,YACjB,WAAW,QAAQ;AAAA,YACnB,aAAa,QAAQ;AAAA,YACrB,aAAY,aAAQ,eAAR,YAAsB;AAAA,YAClC,UAAU;AAAA,cACR,WAAW,QAAQ;AAAA,cACnB,cAAc,KAAK,UAAU,QAAQ,YAAY;AAAA,cACjD,WAAU,WAAM,aAAN,YAAkB;AAAA,cAC5B,QAAQ,QAAO,WAAM,WAAN,YAAgB,EAAE;AAAA,cACjC,OAAO,QAAO,WAAM,UAAN,YAAe,EAAE;AAAA,cAC/B,IAAI,mCAAS,UAAS,EAAE,eAAe,QAAQ,OAAO,IAAI,CAAC;AAAA,cAC3D,IAAI,mCAAS,QAAO,EAAE,iBAAiB,OAAO,QAAQ,IAAI,EAAE,IAAI,CAAC;AAAA,cACjE,IAAI,mCAAS,SAAQ,EAAE,kBAAkB,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC;AAAA,YACtE;AAAA,UACF;AACA,qBAAW,SAAS,OAAO,EAAE,KAAK,CAAC,WAAW;AAC5C,gBAAI,UAAU,aAAc,cAAa,MAAM;AAAA,UACjD,CAAC;AACD,cAAI,WAAW,MAAM,MAAO,SAAQ,MAAM,KAAK;AAAA,QACjD,SAAQ;AAAA,QAER;AAAA,MACF;AAEA,YAAM,kBAAkB,CAAC,UAAiC;AA/JhE;AAgKQ,YAAI;AACF,gBAAM,UAAU,eAAe,gBAAgB,OAAO;AACtD,gBAAM,SAAS,MAAM;AACrB,gBAAM,UAAyB;AAAA,YAC7B;AAAA,YACA,QAAQ;AAAA,YACR,MAAM;AAAA,YACN,cAAc,kBAAkB,QAAQ,OAAO,UAAU,OAAO,MAAM;AAAA,YACtE,YAAY,kBAAkB,QAAQ,OAAO,QAAQ;AAAA,YACrD,SAAS,QAAQ;AAAA,YACjB,WAAW,QAAQ;AAAA,YACnB,aAAa,QAAQ;AAAA,YACrB,aAAY,aAAQ,eAAR,YAAsB;AAAA,YAClC,UAAU;AAAA,cACR,WAAW,QAAQ;AAAA,cACnB,cAAc,KAAK,UAAU,QAAQ,YAAY;AAAA,cACjD,MAAM;AAAA,cACN,IAAI,mCAAS,UAAS,EAAE,eAAe,QAAQ,OAAO,IAAI,CAAC;AAAA,cAC3D,IAAI,mCAAS,QAAO,EAAE,iBAAiB,OAAO,QAAQ,IAAI,EAAE,IAAI,CAAC;AAAA,cACjE,IAAI,mCAAS,SAAQ,EAAE,kBAAkB,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC;AAAA,YACtE;AAAA,UACF;AACA,qBAAW,SAAS,OAAO,EAAE,KAAK,CAAC,WAAW;AAC5C,gBAAI,UAAU,aAAc,cAAa,MAAM;AAAA,UACjD,CAAC;AACD,cAAI,WAAW,kBAAkB,MAAO,SAAQ,MAAM;AAAA,QACxD,SAAQ;AAAA,QAER;AAAA,MACF;AAEA,aAAO,iBAAiB,SAAS,WAAW;AAC5C,aAAO,iBAAiB,sBAAsB,eAAe;AAE7D,aAAO,MAAM;AACX,eAAO,oBAAoB,SAAS,WAAW;AAC/C,eAAO,oBAAoB,sBAAsB,eAAe;AAAA,MAClE;AAAA,IACF,SAAQ;AAAA,IAER;AAAA,EACF,GAAG,CAAC,OAAO,SAAS,SAAS,YAAY,CAAC;AAE1C,QAAM,aAAS;AAAA,IACb,OACE,MACA,aACA,aACiC;AAhNvC;AAiNM,UAAI;AACF,cAAM,UAAU,eAAe,gBAAgB,OAAO;AACtD,cAAM,UAAyB;AAAA,UAC7B;AAAA,UACA,QAAQ;AAAA,UACR;AAAA,UACA;AAAA,UACA,SAAS,QAAQ;AAAA,UACjB,WAAW,QAAQ;AAAA,UACnB,aAAa,QAAQ;AAAA,UACrB,aAAY,aAAQ,eAAR,YAAsB;AAAA,UAClC,UAAU;AAAA,YACR,WAAW,QAAQ;AAAA,YACnB,cAAc,KAAK,UAAU,QAAQ,YAAY;AAAA,YACjD,IAAI,mCAAS,UAAS,EAAE,eAAe,QAAQ,OAAO,IAAI,CAAC;AAAA,YAC3D,IAAI,mCAAS,QAAO,EAAE,iBAAiB,OAAO,QAAQ,IAAI,EAAE,IAAI,CAAC;AAAA,YACjE,IAAI,mCAAS,SAAQ,EAAE,kBAAkB,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC;AAAA,YACpE,IAAI,mCAAS,SAAQ,EAAE,kBAAkB,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC;AAAA,YACpE,GAAG;AAAA,UACL;AAAA,QACF;AACA,cAAM,SAAS,MAAM,WAAW,SAAS,OAAO;AAChD,YAAI,UAAU,aAAc,cAAa,MAAM;AAC/C,eAAO;AAAA,MACT,SAAQ;AACN,eAAO;AAAA,MACT;AAAA,IACF;AAAA,IACA,CAAC,OAAO,SAAS,YAAY;AAAA,EAC/B;AAEA,QAAM,gBAAY;AAAA,IAChB,CAAC,aAAqB,aACpB,OAAO,OAAO,aAAa,QAAQ;AAAA,IACrC,CAAC,MAAM;AAAA,EACT;AAEA,QAAMC,qBAAgB;AAAA,IACpB,CAAC,SAAiB,SAAkC;AAClD,oBAAsB,UAAU,SAAS,IAAI;AAAA,IAC/C;AAAA,IACA,CAAC;AAAA,EACH;AAEA,SACE;AAAA,IAAC,kBAAkB;AAAA,IAAlB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA,SAAS,4BAAWF;AAAA,QACpB;AAAA,QACA;AAAA,QACA,eAAAE;AAAA,MACF;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA,cAAc,gBAAgB;AAAA,UAE7B;AAAA;AAAA,MACH;AAAA;AAAA,EACF;AAEJ;AAEO,SAAS,mBAAmB,OAAgC;AAEjE,MAAI,CAAC,MAAM,MAAO,QAAO,2EAAG,gBAAM,UAAS;AAG3C,QAAM,gBAAgB;AAAA,IACpB,GAAG;AAAA,IACH,SAAS,MAAM,YAAY,OAAO,WAAW,cAAc,OAAO,SAAS,SAASF;AAAA,EACtF;AAEA,MAAI;AACF,WAAO,4CAAC,2BAAyB,GAAG,eAAe;AAAA,EACrD,SAAQ;AACN,WAAO,2EAAG,gBAAM,UAAS;AAAA,EAC3B;AACF;;;AIjSA,IAAAG,gBAAgF;AA6HxE,IAAAC,sBAAA;AAzHD,SAAS,aAAa;AAAA,EAC3B,WAAW;AAAA,EACX,QAAQ;AAAA,EACR;AAAA,EACA;AACF,GAGG;AAdH;AAeE,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,KAAK;AAChD,QAAM,CAAC,QAAQ,SAAS,QAAI,wBAAS,KAAK;AAC1C,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,EAAE;AACjD,QAAM,CAAC,cAAc,eAAe,QAAI,wBAAS,KAAK;AACtD,QAAM,CAAC,WAAW,YAAY,QAAI,wBAAS,KAAK;AAChD,QAAM,CAAC,YAAY,aAAa,QAAI,wBAAwB,IAAI;AAChE,QAAM,CAAC,aAAa,cAAc,QAAI,wBAAS,KAAK;AACpD,QAAM,mBAAe,sBAAyB,IAAI;AAClD,QAAM,eAAW,sBAAuB,IAAI;AAC5C,QAAM,EAAE,UAAU,IAAI,cAAc;AAEpC,QAAM,mBAAmB,CAAC,MAA2C;AA1BvE,QAAAC;AA2BI,UAAM,QAAOA,MAAA,EAAE,OAAO,UAAT,gBAAAA,IAAiB;AAC9B,QAAI,CAAC,KAAM;AACX,UAAM,SAAS,IAAI,WAAW;AAC9B,WAAO,SAAS,MAAM;AACpB,oBAAc,OAAO,MAAgB;AAAA,IACvC;AACA,WAAO,cAAc,IAAI;AACzB,MAAE,OAAO,QAAQ;AAAA,EACnB;AAEA,QAAM,mBAAmB,YAAY;AACnC,mBAAe,KAAK;AACpB,cAAU,KAAK;AACf,kBAAc,IAAI;AAElB,UAAM,IAAI,QAAQ,CAAC,MAAM,WAAW,GAAG,GAAG,CAAC;AAC3C,QAAI;AACF,YAAM,EAAE,SAAS,YAAY,IAAI,MAAM,OAAO,iBAAiB;AAC/D,YAAM,SAAS,MAAM,YAAY,SAAS,MAAM;AAAA,QAC9C,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,YAAY;AAAA,MACd,CAAC;AACD,oBAAc,OAAO,UAAU,cAAc,GAAG,CAAC;AAAA,IACnD,SAAQ;AAAA,IAER;AACA,cAAU,IAAI;AAAA,EAChB;AAEA,QAAM,aAAa,YAAY;AAC7B,iBAAa,IAAI;AACjB,iBAAa,KAAK;AAClB,QAAI;AACF,YAAM,EAAE,SAAS,YAAY,IAAI,MAAM,OAAO,iBAAiB;AAC/D,YAAM,SAAS,MAAM,YAAY,SAAS,MAAM;AAAA,QAC9C,OAAO;AAAA,QACP,SAAS;AAAA,QACT,SAAS;AAAA,QACT,YAAY;AAAA,MACd,CAAC;AACD,oBAAc,OAAO,UAAU,cAAc,GAAG,CAAC;AAAA,IACnD,SAAQ;AAAA,IAER;AACA,iBAAa,KAAK;AAClB,cAAU,IAAI;AAAA,EAChB;AAGA,+BAAU,MAAM;AACd,QAAI,CAAC,OAAQ;AACb,UAAM,YAAY,CAAC,MAAqB;AACtC,UAAI,EAAE,QAAQ,UAAU;AACtB,YAAI,YAAa,gBAAe,KAAK;AAAA,YAChC,WAAU,KAAK;AAAA,MACtB;AAAA,IACF;AACA,aAAS,iBAAiB,WAAW,SAAS;AAC9C,WAAO,MAAM,SAAS,oBAAoB,WAAW,SAAS;AAAA,EAChE,GAAG,CAAC,QAAQ,WAAW,CAAC;AAExB,QAAM,eAAe,MAAM;AACzB,QAAI;AACF,UAAI,CAAC,YAAY,KAAK,KAAK,aAAc;AAEzC,sBAAgB,IAAI;AACpB,gBAAU,YAAY,KAAK,GAAG,aAAa,EAAE,WAAW,IAAI,MAAS;AAErE,mBAAa,IAAI;AACjB,qBAAe,EAAE;AACjB,oBAAc,IAAI;AAClB,sBAAgB,KAAK;AAErB,iBAAW,MAAM;AACf,qBAAa,KAAK;AAClB,kBAAU,KAAK;AAAA,MACjB,GAAG,GAAI;AAAA,IACT,SAAQ;AACN,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,SAAQ,0CAAU,WAAW,WAArB,YAA+B;AAC7C,QAAM,UAAS,0CAAU,SAAS,YAAnB,YAA8B;AAE7C,QAAM,sBAAqC,WACvC,CAAC,IACD;AAAA,IACE,GAAI,SAAS,EAAE,MAAM,OAAO,IAAI,EAAE,OAAO,OAAO;AAAA,IAChD,GAAI,QAAQ,EAAE,KAAK,OAAO,IAAI,EAAE,QAAQ,OAAO;AAAA,EACjD;AAEJ,SACE,8EAEG;AAAA,eACC,SAAS,EAAE,SAAS,YAAY,UAAU,CAAC,IAE3C;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA;AAAA,IACF;AAAA,IAID,UACC;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,SAAS;AAAA,UACT,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,iBAAiB;AAAA,QACnB;AAAA,QACA,SAAS,MAAM;AAAE,cAAI,CAAC,YAAa,WAAU,KAAK;AAAA,QAAG;AAAA,QAErD;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,YAClC,OAAO;AAAA,cACL,UAAU,WAAW,aAAa;AAAA,cAClC,GAAG;AAAA,cACH,QAAQ;AAAA,cACR,OAAO;AAAA,cACP,UAAU;AAAA,cACV,iBAAiB;AAAA,cACjB,cAAc;AAAA,cACd,WACE;AAAA,cACF,YACE;AAAA,cACF,UAAU;AAAA,cACV,OAAO;AAAA,YACT;AAAA,YAGA;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,SAAS;AAAA,oBACT,cAAc;AAAA,kBAChB;AAAA,kBAEA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,SAAS;AAAA,wBACT,gBAAgB;AAAA,wBAChB,YAAY;AAAA,sBACd;AAAA,sBAEA;AAAA;AAAA,0BAAC;AAAA;AAAA,4BACC,OAAO;AAAA,8BACL,UAAU;AAAA,8BACV,YAAY;AAAA,8BACZ,OAAO;AAAA,4BACT;AAAA,4BACD;AAAA;AAAA,wBAED;AAAA,wBACA;AAAA,0BAAC;AAAA;AAAA,4BACC,MAAK;AAAA,4BACL,SAAS,MAAM,UAAU,KAAK;AAAA,4BAC9B,OAAO;AAAA,8BACL,YAAY;AAAA,8BACZ,QAAQ;AAAA,8BACR,QAAQ;AAAA,8BACR,SAAS;AAAA,8BACT,OAAO;AAAA,8BACP,UAAU;AAAA,8BACV,YAAY;AAAA,4BACd;AAAA,4BACA,cAAW;AAAA,4BACZ;AAAA;AAAA,wBAED;AAAA;AAAA;AAAA,kBACF;AAAA;AAAA,cACF;AAAA,cAGA,6CAAC,SAAI,OAAO,EAAE,SAAS,OAAO,GAC3B,sBACC;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,WAAW;AAAA,oBACX,SAAS;AAAA,oBACT,OAAO;AAAA,oBACP,UAAU;AAAA,oBACV,YAAY;AAAA,kBACd;AAAA,kBACD;AAAA;AAAA,cAED,IAEA,8EAEG;AAAA,8BACC,8CAAC,SAAI,OAAO,EAAE,cAAc,QAAQ,UAAU,WAAW,GACvD;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,KAAK;AAAA,sBACL,KAAI;AAAA,sBACJ,SAAS,MAAM,eAAe,IAAI;AAAA,sBAClC,OAAO;AAAA,wBACL,OAAO;AAAA,wBACP,cAAc;AAAA,wBACd,QAAQ;AAAA,wBACR,WAAW;AAAA,wBACX,WAAW;AAAA,wBACX,gBAAgB;AAAA,wBAChB,QAAQ;AAAA,sBACV;AAAA;AAAA,kBACF;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,MAAK;AAAA,sBACL,SAAS,MAAM,cAAc,IAAI;AAAA,sBACjC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,KAAK;AAAA,wBACL,OAAO;AAAA,wBACP,YAAY;AAAA,wBACZ,QAAQ;AAAA,wBACR,cAAc;AAAA,wBACd,OAAO;AAAA,wBACP,OAAO;AAAA,wBACP,QAAQ;AAAA,wBACR,UAAU;AAAA,wBACV,QAAQ;AAAA,wBACR,SAAS;AAAA,wBACT,YAAY;AAAA,wBACZ,gBAAgB;AAAA,wBAChB,YAAY;AAAA,sBACd;AAAA,sBACA,cAAW;AAAA,sBACZ;AAAA;AAAA,kBAED;AAAA,kBACA;AAAA,oBAAC;AAAA;AAAA,sBACC,OAAO;AAAA,wBACL,UAAU;AAAA,wBACV,QAAQ;AAAA,wBACR,MAAM;AAAA,wBACN,OAAO;AAAA,wBACP,SAAS;AAAA,wBACT,gBAAgB;AAAA,wBAChB,YAAY;AAAA,sBACd;AAAA,sBAEA;AAAA;AAAA,0BAAC;AAAA;AAAA,4BACC,OAAO;AAAA,8BACL,YAAY;AAAA,8BACZ,OAAO;AAAA,8BACP,UAAU;AAAA,8BACV,SAAS;AAAA,8BACT,cAAc;AAAA,4BAChB;AAAA,4BACD;AAAA;AAAA,8BACc,KAAK,MAAM,WAAW,SAAS,OAAO,IAAI;AAAA,8BAAE;AAAA;AAAA;AAAA,wBAC3D;AAAA,wBACA,8CAAC,SAAI,OAAO,EAAE,SAAS,QAAQ,KAAK,MAAM,GACxC;AAAA;AAAA,4BAAC;AAAA;AAAA,8BACC,MAAK;AAAA,8BACL,SAAS,MAAG;AAvSxC,oCAAAA;AAuS2C,wCAAAA,MAAA,aAAa,YAAb,gBAAAA,IAAsB;AAAA;AAAA,8BACrC,OAAO;AAAA,gCACL,YAAY;AAAA,gCACZ,OAAO;AAAA,gCACP,UAAU;AAAA,gCACV,SAAS;AAAA,gCACT,cAAc;AAAA,gCACd,QAAQ;AAAA,gCACR,QAAQ;AAAA,8BACV;AAAA,8BACD;AAAA;AAAA,0BAED;AAAA,0BACA;AAAA,4BAAC;AAAA;AAAA,8BACC,MAAK;AAAA,8BACL,SAAS;AAAA,8BACT,OAAO;AAAA,gCACL,YAAY;AAAA,gCACZ,OAAO;AAAA,gCACP,UAAU;AAAA,gCACV,SAAS;AAAA,gCACT,cAAc;AAAA,gCACd,QAAQ;AAAA,gCACR,QAAQ;AAAA,8BACV;AAAA,8BACD;AAAA;AAAA,0BAED;AAAA,2BACF;AAAA;AAAA;AAAA,kBACF;AAAA,mBACF;AAAA,gBAED,CAAC,cAAc,CAAC,aACf;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS,MAAG;AA1UlC,0BAAAA;AA0UqC,8BAAAA,MAAA,aAAa,YAAb,gBAAAA,IAAsB;AAAA;AAAA,oBACrC,OAAO;AAAA,sBACL,cAAc;AAAA,sBACd,SAAS;AAAA,sBACT,cAAc;AAAA,sBACd,QAAQ;AAAA,sBACR,WAAW;AAAA,sBACX,UAAU;AAAA,sBACV,OAAO;AAAA,sBACP,OAAO;AAAA,sBACP,YAAY;AAAA,sBACZ,QAAQ;AAAA,oBACV;AAAA,oBACD;AAAA;AAAA,gBAED;AAAA,gBAEF;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO;AAAA,oBACP,UAAU,CAAC,MAAM,eAAe,EAAE,OAAO,KAAK;AAAA,oBAC9C,aAAY;AAAA,oBACZ,OAAO;AAAA,sBACL,OAAO;AAAA,sBACP,WAAW;AAAA,sBACX,SAAS;AAAA,sBACT,cAAc;AAAA,sBACd,QAAQ;AAAA,sBACR,UAAU;AAAA,sBACV,YAAY;AAAA,sBACZ,QAAQ;AAAA,sBACR,SAAS;AAAA,sBACT,WAAW;AAAA,sBACX,OAAO;AAAA,sBACP,iBAAiB;AAAA,oBACnB;AAAA,oBACA,SAAS,CAAC,MAAM;AACd,sBAAC,EAAE,OAA+B,MAAM,cACtC;AAAA,oBACJ;AAAA,oBACA,QAAQ,CAAC,MAAM;AACb,sBAAC,EAAE,OAA+B,MAAM,cACtC;AAAA,oBACJ;AAAA,oBACA,WAAS;AAAA;AAAA,gBACX;AAAA,gBACA;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAK;AAAA,oBACL,SAAS;AAAA,oBACT,UAAU,CAAC,YAAY,KAAK,KAAK;AAAA,oBACjC,OAAO;AAAA,sBACL,WAAW;AAAA,sBACX,OAAO;AAAA,sBACP,SAAS;AAAA,sBACT,cAAc;AAAA,sBACd,QAAQ;AAAA,sBACR,iBACE,CAAC,YAAY,KAAK,KAAK,eACnB,YACA;AAAA,sBACN,OACE,CAAC,YAAY,KAAK,KAAK,eACnB,YACA;AAAA,sBACN,UAAU;AAAA,sBACV,YAAY;AAAA,sBACZ,QACE,CAAC,YAAY,KAAK,KAAK,eACnB,gBACA;AAAA,sBACN,YAAY;AAAA,sBACZ,YAAY;AAAA,oBACd;AAAA,oBAEC,yBAAe,eAAe;AAAA;AAAA,gBACjC;AAAA,iBACF,GAEJ;AAAA,cAGA;AAAA,gBAAC;AAAA;AAAA,kBACC,OAAO;AAAA,oBACL,SAAS;AAAA,oBACT,WAAW;AAAA,oBACX,WAAW;AAAA,kBACb;AAAA,kBAEA,uDAAC,UAAK,OAAO,EAAE,UAAU,QAAQ,OAAO,UAAU,GAAG,mCAErD;AAAA;AAAA,cACF;AAAA;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,IAIF;AAAA,MAAC;AAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,QAAO;AAAA,QACP,UAAU;AAAA,QACV,OAAO,EAAE,SAAS,OAAO;AAAA;AAAA,IAC3B;AAAA,IAGC,eAAe,cACd;AAAA,MAAC;AAAA;AAAA,QACC,OAAO;AAAA,UACL,UAAU;AAAA,UACV,OAAO;AAAA,UACP,QAAQ;AAAA,UACR,iBAAiB;AAAA,UACjB,SAAS;AAAA,UACT,eAAe;AAAA,UACf,YAAY;AAAA,UACZ,gBAAgB;AAAA,UAChB,SAAS;AAAA,UACT,QAAQ;AAAA,QACV;AAAA,QACA,SAAS,CAAC,MAAM;AAAE,YAAE,gBAAgB;AAAG,yBAAe,KAAK;AAAA,QAAG;AAAA,QAC9D,aAAa,CAAC,MAAM,EAAE,gBAAgB;AAAA,QAEtC;AAAA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL,KAAI;AAAA,cACJ,SAAS,CAAC,MAAM,EAAE,gBAAgB;AAAA,cAClC,OAAO;AAAA,gBACL,UAAU;AAAA,gBACV,WAAW;AAAA,gBACX,cAAc;AAAA,gBACd,WAAW;AAAA,gBACX,QAAQ;AAAA,cACV;AAAA;AAAA,UACF;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,OAAO;AAAA,gBACL,WAAW;AAAA,gBACX,OAAO;AAAA,gBACP,UAAU;AAAA,cACZ;AAAA,cACD;AAAA;AAAA,UAED;AAAA;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;AAGA,SAAS,eAAe;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAQG;AACD,QAAM,iBAAgC;AAAA,IACpC,GAAI,SAAS,EAAE,MAAM,OAAO,IAAI,EAAE,OAAO,OAAO;AAAA,IAChD,GAAI,QAAQ,EAAE,KAAK,OAAO,IAAI,EAAE,QAAQ,OAAO;AAAA,EACjD;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,MAAK;AAAA,MACL;AAAA,MACA,UAAU;AAAA,MACV;AAAA,MACA,OAAO;AAAA,QACL,UAAU;AAAA,QACV,GAAG;AAAA,QACH,QAAQ;AAAA,QACR,SAAS;AAAA,QACT,cAAc;AAAA,QACd,QAAQ;AAAA,QACR,iBAAiB;AAAA,QACjB,OAAO;AAAA,QACP,UAAU;AAAA,QACV,YAAY;AAAA,QACZ,YACE;AAAA,QACF,QAAQ,YAAY,SAAS;AAAA,QAC7B,WACE;AAAA,QACF,YAAY;AAAA,QACZ,SAAS;AAAA,QACT,YAAY;AAAA,QACZ,KAAK;AAAA,QACL,SAAS,YAAY,MAAM;AAAA,MAC7B;AAAA,MACA,cAAc,CAAC,MAAM;AACnB,QAAC,EAAE,OAAuB,MAAM,YAAY;AAAA,MAC9C;AAAA,MACA,cAAc,CAAC,MAAM;AACnB,QAAC,EAAE,OAAuB,MAAM,YAAY;AAAA,MAC9C;AAAA,MACA,cAAY;AAAA,MAEZ;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,OAAO,EAAE,YAAY,EAAE;AAAA,YAEvB;AAAA,cAAC;AAAA;AAAA,gBACC,GAAE;AAAA,gBACF,MAAK;AAAA;AAAA,YACP;AAAA;AAAA,QACF;AAAA,QACC,YAAY,iBAAiB;AAAA;AAAA;AAAA,EAChC;AAEJ;","names":["e","DEFAULT_BASE_URL","maxBreadcrumbs","addBreadcrumb","import_react","import_jsx_runtime","_a"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/provider.tsx","../src/error-boundary.tsx","../src/breadcrumbs.ts","../src/utils.ts","../src/report-button.tsx"],"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// ─── 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 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 { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://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}: 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]\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 return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\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 </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 // Auto-detect baseUrl from window.location if not provided\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || (typeof window !== \"undefined\" ? window.location.origin : 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://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\";\nimport type { ReportButtonProps, UseGlitchgrabReturn } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\n/** Safe version of useGlitchgrab that returns null when outside provider */\nfunction useGlitchgrabSafe(): UseGlitchgrabReturn | null {\n try {\n return useGlitchgrab();\n } catch {\n return null;\n }\n}\n\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n /** Render prop — receives { onClick, capturing } so you can use your own trigger button */\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\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 const glitchgrab = useGlitchgrabSafe();\n\n // If no provider context, render nothing\n if (!glitchgrab) return null;\n\n const { reportBug } = glitchgrab;\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 // Small delay so the modal is gone before capture\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 setCapturing(true);\n setSubmitted(false);\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 setCapturing(false);\n setIsOpen(true);\n };\n\n // Close modal on Escape key\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else setIsOpen(false);\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleSubmit = () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n setIsSubmitting(true);\n reportBug(description.trim(), screenshot ? { screenshot } : undefined);\n\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n setIsSubmitting(false);\n\n setTimeout(() => {\n setSubmitted(false);\n setIsOpen(false);\n }, 2000);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const modalPositionStyles: CSSProperties = children\n ? {} // user controls positioning\n : {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"64px\" } : { bottom: \"64px\" }),\n };\n\n return (\n <>\n {/* Trigger: user's custom button OR default floating button */}\n {children ? (\n children({ onClick: handleOpen, capturing })\n ) : (\n <DefaultTrigger\n onClick={handleOpen}\n capturing={capturing}\n label={label}\n className={className}\n position={position}\n isLeft={isLeft}\n isTop={isTop}\n />\n )}\n\n {/* Report modal */}\n {isOpen && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 99999,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n }}\n onClick={() => { if (!previewOpen) setIsOpen(false); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: children ? \"relative\" : \"fixed\",\n ...modalPositionStyles,\n zIndex: 100000,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: \"#1c1c1e\",\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: \"#fafafa\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: \"1px solid #2c2c2e\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: \"#fafafa\",\n }}\n >\n Report a Bug\n </span>\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n color: \"#a1a1aa\",\n fontSize: \"18px\",\n lineHeight: 1,\n }}\n aria-label=\"Close\"\n >\n ×\n </button>\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: \"#22d3ee\",\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n Bug report sent. Thank you!\n </div>\n ) : (\n <>\n {/* Screenshot preview */}\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 #2c2c2e\",\n maxHeight: \"120px\",\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 color: \"#fff\",\n width: \"20px\",\n height: \"20px\",\n fontSize: \"12px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n lineHeight: 1,\n }}\n aria-label=\"Remove screenshot\"\n >\n ×\n </button>\n <div\n style={{\n position: \"absolute\",\n bottom: \"4px\",\n left: \"6px\",\n right: \"6px\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#fff\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n }}\n >\n Screenshot ({Math.round(screenshot.length * 0.75 / 1024)}KB) — click to preview\n </span>\n <div style={{ display: \"flex\", gap: \"4px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake\n </button>\n </div>\n </div>\n </div>\n )}\n {!screenshot && !submitted && (\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n marginBottom: \"10px\",\n padding: \"10px\",\n borderRadius: \"6px\",\n border: \"1px dashed #3f3f46\",\n textAlign: \"center\",\n fontSize: \"11px\",\n color: \"#71717a\",\n width: \"100%\",\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Click to upload a screenshot\n </button>\n )}\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Describe what went wrong...\"\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: \"1px solid #3f3f46\",\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: \"#fafafa\",\n backgroundColor: \"#27272a\",\n }}\n onFocus={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#22d3ee\";\n }}\n onBlur={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#3f3f46\";\n }}\n autoFocus\n />\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!description.trim() || isSubmitting}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor:\n !description.trim() || isSubmitting\n ? \"#3f3f46\"\n : \"#22d3ee\",\n color:\n !description.trim() || isSubmitting\n ? \"#71717a\"\n : \"#09090b\",\n fontSize: \"14px\",\n fontWeight: 600,\n cursor:\n !description.trim() || isSubmitting\n ? \"not-allowed\"\n : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: \"1px solid #2c2c2e\",\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: \"#52525b\" }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Hidden file input for screenshot upload */}\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 && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 200000,\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: \"#a1a1aa\",\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>\n )}\n </>\n );\n}\n\n/** Default floating trigger button (used when no children provided) */\nfunction DefaultTrigger({\n onClick,\n capturing,\n label,\n className,\n position,\n isLeft,\n isTop,\n}: {\n onClick: () => void;\n capturing: boolean;\n label: string;\n className?: string;\n position?: string;\n isLeft: boolean;\n isTop: boolean;\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={onClick}\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"],"mappings":"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","names":["e","DEFAULT_BASE_URL","maxBreadcrumbs","addBreadcrumb","import_react","import_jsx_runtime","_a"]}
|
package/dist/index.mjs
CHANGED
|
@@ -540,6 +540,13 @@ function GlitchgrabProvider(props) {
|
|
|
540
540
|
// src/report-button.tsx
|
|
541
541
|
import { useState as useState2, useRef as useRef2, useEffect as useEffect2 } from "react";
|
|
542
542
|
import { Fragment as Fragment2, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
543
|
+
function useGlitchgrabSafe() {
|
|
544
|
+
try {
|
|
545
|
+
return useGlitchgrab();
|
|
546
|
+
} catch (e) {
|
|
547
|
+
return null;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
543
550
|
function ReportButton({
|
|
544
551
|
position = "bottom-right",
|
|
545
552
|
label = "Report Bug",
|
|
@@ -556,7 +563,9 @@ function ReportButton({
|
|
|
556
563
|
const [previewOpen, setPreviewOpen] = useState2(false);
|
|
557
564
|
const fileInputRef = useRef2(null);
|
|
558
565
|
const modalRef = useRef2(null);
|
|
559
|
-
const
|
|
566
|
+
const glitchgrab = useGlitchgrabSafe();
|
|
567
|
+
if (!glitchgrab) return null;
|
|
568
|
+
const { reportBug } = glitchgrab;
|
|
560
569
|
const handleFileUpload = (e) => {
|
|
561
570
|
var _a2;
|
|
562
571
|
const file = (_a2 = e.target.files) == null ? void 0 : _a2[0];
|
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-button.tsx"],"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 { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://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}: 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]\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 return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\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 </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 // Auto-detect baseUrl from window.location if not provided\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || (typeof window !== \"undefined\" ? window.location.origin : 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://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\";\nimport type { ReportButtonProps } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n /** Render prop — receives { onClick, capturing } so you can use your own trigger button */\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\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 const { reportBug } = useGlitchgrab();\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 // Small delay so the modal is gone before capture\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 setCapturing(true);\n setSubmitted(false);\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 setCapturing(false);\n setIsOpen(true);\n };\n\n // Close modal on Escape key\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else setIsOpen(false);\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleSubmit = () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n setIsSubmitting(true);\n reportBug(description.trim(), screenshot ? { screenshot } : undefined);\n\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n setIsSubmitting(false);\n\n setTimeout(() => {\n setSubmitted(false);\n setIsOpen(false);\n }, 2000);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const modalPositionStyles: CSSProperties = children\n ? {} // user controls positioning\n : {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"64px\" } : { bottom: \"64px\" }),\n };\n\n return (\n <>\n {/* Trigger: user's custom button OR default floating button */}\n {children ? (\n children({ onClick: handleOpen, capturing })\n ) : (\n <DefaultTrigger\n onClick={handleOpen}\n capturing={capturing}\n label={label}\n className={className}\n position={position}\n isLeft={isLeft}\n isTop={isTop}\n />\n )}\n\n {/* Report modal */}\n {isOpen && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 99999,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n }}\n onClick={() => { if (!previewOpen) setIsOpen(false); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: children ? \"relative\" : \"fixed\",\n ...modalPositionStyles,\n zIndex: 100000,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: \"#1c1c1e\",\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: \"#fafafa\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: \"1px solid #2c2c2e\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: \"#fafafa\",\n }}\n >\n Report a Bug\n </span>\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n color: \"#a1a1aa\",\n fontSize: \"18px\",\n lineHeight: 1,\n }}\n aria-label=\"Close\"\n >\n ×\n </button>\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: \"#22d3ee\",\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n Bug report sent. Thank you!\n </div>\n ) : (\n <>\n {/* Screenshot preview */}\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 #2c2c2e\",\n maxHeight: \"120px\",\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 color: \"#fff\",\n width: \"20px\",\n height: \"20px\",\n fontSize: \"12px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n lineHeight: 1,\n }}\n aria-label=\"Remove screenshot\"\n >\n ×\n </button>\n <div\n style={{\n position: \"absolute\",\n bottom: \"4px\",\n left: \"6px\",\n right: \"6px\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#fff\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n }}\n >\n Screenshot ({Math.round(screenshot.length * 0.75 / 1024)}KB) — click to preview\n </span>\n <div style={{ display: \"flex\", gap: \"4px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake\n </button>\n </div>\n </div>\n </div>\n )}\n {!screenshot && !submitted && (\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n marginBottom: \"10px\",\n padding: \"10px\",\n borderRadius: \"6px\",\n border: \"1px dashed #3f3f46\",\n textAlign: \"center\",\n fontSize: \"11px\",\n color: \"#71717a\",\n width: \"100%\",\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Click to upload a screenshot\n </button>\n )}\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Describe what went wrong...\"\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: \"1px solid #3f3f46\",\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: \"#fafafa\",\n backgroundColor: \"#27272a\",\n }}\n onFocus={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#22d3ee\";\n }}\n onBlur={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#3f3f46\";\n }}\n autoFocus\n />\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!description.trim() || isSubmitting}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor:\n !description.trim() || isSubmitting\n ? \"#3f3f46\"\n : \"#22d3ee\",\n color:\n !description.trim() || isSubmitting\n ? \"#71717a\"\n : \"#09090b\",\n fontSize: \"14px\",\n fontWeight: 600,\n cursor:\n !description.trim() || isSubmitting\n ? \"not-allowed\"\n : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: \"1px solid #2c2c2e\",\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: \"#52525b\" }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Hidden file input for screenshot upload */}\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 && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 200000,\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: \"#a1a1aa\",\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>\n )}\n </>\n );\n}\n\n/** Default floating trigger button (used when no children provided) */\nfunction DefaultTrigger({\n onClick,\n capturing,\n label,\n className,\n position,\n isLeft,\n isTop,\n}: {\n onClick: () => void;\n capturing: boolean;\n label: string;\n className?: string;\n position?: string;\n isLeft: boolean;\n isTop: boolean;\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={onClick}\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"],"mappings":"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","names":["e","DEFAULT_BASE_URL","maxBreadcrumbs","addBreadcrumb","useState","useRef","useEffect","Fragment","jsx","useState","useRef","_a","useEffect"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.tsx","../src/error-boundary.tsx","../src/breadcrumbs.ts","../src/utils.ts","../src/report-button.tsx"],"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 { sanitizeUrl, captureContext, sendReport, captureDeviceInfo } from \"./utils\";\nimport {\n initBreadcrumbs,\n addBreadcrumb as addBreadcrumbInternal,\n getBreadcrumbs,\n} from \"./breadcrumbs\";\n\nconst DEFAULT_BASE_URL = \"https://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}: 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]\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 return (\n <GlitchgrabContext.Provider\n value={{\n token,\n baseUrl: baseUrl ?? DEFAULT_BASE_URL,\n reportBug,\n report,\n addBreadcrumb,\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 </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 // Auto-detect baseUrl from window.location if not provided\n const resolvedProps = {\n ...props,\n baseUrl: props.baseUrl || (typeof window !== \"undefined\" ? window.location.origin : 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://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\";\nimport type { ReportButtonProps, UseGlitchgrabReturn } from \"./types\";\nimport { useGlitchgrab } from \"./provider\";\n\n/** Safe version of useGlitchgrab that returns null when outside provider */\nfunction useGlitchgrabSafe(): UseGlitchgrabReturn | null {\n try {\n return useGlitchgrab();\n } catch {\n return null;\n }\n}\n\nexport function ReportButton({\n position = \"bottom-right\",\n label = \"Report Bug\",\n className,\n children,\n}: ReportButtonProps & {\n /** Render prop — receives { onClick, capturing } so you can use your own trigger button */\n children?: (props: { onClick: () => void; capturing: boolean }) => ReactNode;\n}) {\n const [capturing, setCapturing] = useState(false);\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 const glitchgrab = useGlitchgrabSafe();\n\n // If no provider context, render nothing\n if (!glitchgrab) return null;\n\n const { reportBug } = glitchgrab;\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 // Small delay so the modal is gone before capture\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 setCapturing(true);\n setSubmitted(false);\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 setCapturing(false);\n setIsOpen(true);\n };\n\n // Close modal on Escape key\n useEffect(() => {\n if (!isOpen) return;\n const handleEsc = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n if (previewOpen) setPreviewOpen(false);\n else setIsOpen(false);\n }\n };\n document.addEventListener(\"keydown\", handleEsc);\n return () => document.removeEventListener(\"keydown\", handleEsc);\n }, [isOpen, previewOpen]);\n\n const handleSubmit = () => {\n try {\n if (!description.trim() || isSubmitting) return;\n\n setIsSubmitting(true);\n reportBug(description.trim(), screenshot ? { screenshot } : undefined);\n\n setSubmitted(true);\n setDescription(\"\");\n setScreenshot(null);\n setIsSubmitting(false);\n\n setTimeout(() => {\n setSubmitted(false);\n setIsOpen(false);\n }, 2000);\n } catch {\n setIsSubmitting(false);\n }\n };\n\n const isTop = position?.startsWith(\"top\") ?? false;\n const isLeft = position?.endsWith(\"left\") ?? false;\n\n const modalPositionStyles: CSSProperties = children\n ? {} // user controls positioning\n : {\n ...(isLeft ? { left: \"16px\" } : { right: \"16px\" }),\n ...(isTop ? { top: \"64px\" } : { bottom: \"64px\" }),\n };\n\n return (\n <>\n {/* Trigger: user's custom button OR default floating button */}\n {children ? (\n children({ onClick: handleOpen, capturing })\n ) : (\n <DefaultTrigger\n onClick={handleOpen}\n capturing={capturing}\n label={label}\n className={className}\n position={position}\n isLeft={isLeft}\n isTop={isTop}\n />\n )}\n\n {/* Report modal */}\n {isOpen && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 99999,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n backgroundColor: \"rgba(0,0,0,0.5)\",\n }}\n onClick={() => { if (!previewOpen) setIsOpen(false); }}\n >\n <div\n ref={modalRef}\n onClick={(e) => e.stopPropagation()}\n style={{\n position: children ? \"relative\" : \"fixed\",\n ...modalPositionStyles,\n zIndex: 100000,\n width: \"340px\",\n maxWidth: \"calc(100% - 32px)\",\n backgroundColor: \"#1c1c1e\",\n borderRadius: \"12px\",\n boxShadow:\n \"0 20px 60px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.3)\",\n fontFamily:\n '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n overflow: \"hidden\",\n color: \"#fafafa\",\n }}\n >\n {/* Header */}\n <div\n style={{\n padding: \"16px 16px 12px\",\n borderBottom: \"1px solid #2c2c2e\",\n }}\n >\n <div\n style={{\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n fontSize: \"15px\",\n fontWeight: 600,\n color: \"#fafafa\",\n }}\n >\n Report a Bug\n </span>\n <button\n type=\"button\"\n onClick={() => setIsOpen(false)}\n style={{\n background: \"none\",\n border: \"none\",\n cursor: \"pointer\",\n padding: \"4px\",\n color: \"#a1a1aa\",\n fontSize: \"18px\",\n lineHeight: 1,\n }}\n aria-label=\"Close\"\n >\n ×\n </button>\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: \"#22d3ee\",\n fontSize: \"14px\",\n fontWeight: 500,\n }}\n >\n Bug report sent. Thank you!\n </div>\n ) : (\n <>\n {/* Screenshot preview */}\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 #2c2c2e\",\n maxHeight: \"120px\",\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 color: \"#fff\",\n width: \"20px\",\n height: \"20px\",\n fontSize: \"12px\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n lineHeight: 1,\n }}\n aria-label=\"Remove screenshot\"\n >\n ×\n </button>\n <div\n style={{\n position: \"absolute\",\n bottom: \"4px\",\n left: \"6px\",\n right: \"6px\",\n display: \"flex\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n }}\n >\n <span\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#fff\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n }}\n >\n Screenshot ({Math.round(screenshot.length * 0.75 / 1024)}KB) — click to preview\n </span>\n <div style={{ display: \"flex\", gap: \"4px\" }}>\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Upload\n </button>\n <button\n type=\"button\"\n onClick={retakeScreenshot}\n style={{\n background: \"rgba(0,0,0,0.6)\",\n color: \"#22d3ee\",\n fontSize: \"10px\",\n padding: \"2px 6px\",\n borderRadius: \"4px\",\n border: \"none\",\n cursor: \"pointer\",\n }}\n >\n Retake\n </button>\n </div>\n </div>\n </div>\n )}\n {!screenshot && !submitted && (\n <button\n type=\"button\"\n onClick={() => fileInputRef.current?.click()}\n style={{\n marginBottom: \"10px\",\n padding: \"10px\",\n borderRadius: \"6px\",\n border: \"1px dashed #3f3f46\",\n textAlign: \"center\",\n fontSize: \"11px\",\n color: \"#71717a\",\n width: \"100%\",\n background: \"none\",\n cursor: \"pointer\",\n }}\n >\n Click to upload a screenshot\n </button>\n )}\n <textarea\n value={description}\n onChange={(e) => setDescription(e.target.value)}\n placeholder=\"Describe what went wrong...\"\n style={{\n width: \"100%\",\n minHeight: \"100px\",\n padding: \"10px 12px\",\n borderRadius: \"8px\",\n border: \"1px solid #3f3f46\",\n fontSize: \"14px\",\n fontFamily: \"inherit\",\n resize: \"vertical\",\n outline: \"none\",\n boxSizing: \"border-box\",\n color: \"#fafafa\",\n backgroundColor: \"#27272a\",\n }}\n onFocus={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#22d3ee\";\n }}\n onBlur={(e) => {\n (e.target as HTMLTextAreaElement).style.borderColor =\n \"#3f3f46\";\n }}\n autoFocus\n />\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={!description.trim() || isSubmitting}\n style={{\n marginTop: \"12px\",\n width: \"100%\",\n padding: \"10px\",\n borderRadius: \"8px\",\n border: \"none\",\n backgroundColor:\n !description.trim() || isSubmitting\n ? \"#3f3f46\"\n : \"#22d3ee\",\n color:\n !description.trim() || isSubmitting\n ? \"#71717a\"\n : \"#09090b\",\n fontSize: \"14px\",\n fontWeight: 600,\n cursor:\n !description.trim() || isSubmitting\n ? \"not-allowed\"\n : \"pointer\",\n fontFamily: \"inherit\",\n transition: \"background-color 0.15s ease\",\n }}\n >\n {isSubmitting ? \"Sending...\" : \"Send Report\"}\n </button>\n </>\n )}\n </div>\n\n {/* Footer */}\n <div\n style={{\n padding: \"8px 16px 10px\",\n borderTop: \"1px solid #2c2c2e\",\n textAlign: \"center\",\n }}\n >\n <span style={{ fontSize: \"11px\", color: \"#52525b\" }}>\n Powered by Glitchgrab\n </span>\n </div>\n </div>\n </div>\n )}\n\n {/* Hidden file input for screenshot upload */}\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 && (\n <div\n style={{\n position: \"fixed\",\n inset: 0,\n zIndex: 200000,\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: \"#a1a1aa\",\n fontSize: \"12px\",\n }}\n >\n Click outside to close\n </span>\n </div>\n )}\n </>\n );\n}\n\n/** Default floating trigger button (used when no children provided) */\nfunction DefaultTrigger({\n onClick,\n capturing,\n label,\n className,\n position,\n isLeft,\n isTop,\n}: {\n onClick: () => void;\n capturing: boolean;\n label: string;\n className?: string;\n position?: string;\n isLeft: boolean;\n isTop: boolean;\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={onClick}\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"],"mappings":"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","names":["e","DEFAULT_BASE_URL","maxBreadcrumbs","addBreadcrumb","useState","useRef","useEffect","Fragment","jsx","useState","useRef","_a","useEffect"]}
|