bug-widget-library 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +176 -2
- package/dist/bug-widget-library.cjs +2 -0
- package/dist/bug-widget-library.cjs.map +1 -0
- package/dist/bug-widget-library.css +2 -0
- package/dist/bug-widget-library.js +1043 -0
- package/dist/bug-widget-library.js.map +1 -0
- package/dist/components/Form.d.ts +16 -0
- package/dist/components/Form.d.ts.map +1 -0
- package/dist/components/KonvaEditor.d.ts +10 -0
- package/dist/components/KonvaEditor.d.ts.map +1 -0
- package/dist/components/Widget.d.ts +4 -0
- package/dist/components/Widget.d.ts.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/types.d.ts +112 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +68 -3
package/README.md
CHANGED
|
@@ -1,3 +1,177 @@
|
|
|
1
|
-
#
|
|
1
|
+
# bug-widget-library
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Embeddable React bug-reporting widget with screenshot capture and Konva annotation.
|
|
4
|
+
|
|
5
|
+
You provide a **submit handler** (`onSubmit`) to decide where the report data is sent. The widget collects the form fields and screenshots, then calls your handler.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install bug-widget-library
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
**Peer dependencies** (must already be in your app):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install react react-dom
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`react` and `react-dom` >= 18 are required.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { Widget } from 'bug-widget-library';
|
|
29
|
+
import type { BugReportData } from 'bug-widget-library';
|
|
30
|
+
import 'bug-widget-library/style.css';
|
|
31
|
+
|
|
32
|
+
export function App() {
|
|
33
|
+
const handleSubmit = async (data: BugReportData) => {
|
|
34
|
+
const response = await fetch(data.projectUrl, {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
headers: { 'Content-Type': 'application/json' },
|
|
37
|
+
body: JSON.stringify(data),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (!response.ok) {
|
|
41
|
+
throw new Error('Failed to submit bug report');
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
return (
|
|
46
|
+
<Widget
|
|
47
|
+
projectUrl="https://api.example.com/projects/abc123/bugs"
|
|
48
|
+
onSubmit={handleSubmit}
|
|
49
|
+
uiSettings={{
|
|
50
|
+
position: 'bottom-right',
|
|
51
|
+
primaryColor: '#2563eb',
|
|
52
|
+
buttonText: 'Report Bug',
|
|
53
|
+
}}
|
|
54
|
+
/>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
> Always import the stylesheet: `import 'bug-widget-library/style.css'`.
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## How it works
|
|
64
|
+
|
|
65
|
+
1. User opens the floating widget and fills in title + description.
|
|
66
|
+
2. Optionally captures and annotates up to 3 screenshots.
|
|
67
|
+
3. On submit, the widget builds a `BugReportData` object and calls your `onSubmit` handler.
|
|
68
|
+
4. You send that data to your backend (or any service).
|
|
69
|
+
5. If `onSubmit` throws / rejects, the form shows an error. If it resolves, the success screen is shown.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Props
|
|
74
|
+
|
|
75
|
+
### `Widget`
|
|
76
|
+
|
|
77
|
+
| Prop | Type | Required | Default | Description |
|
|
78
|
+
|------|------|----------|---------|-------------|
|
|
79
|
+
| `projectUrl` | `string` | Yes | — | Project URL included in the report payload (and shown as a label in the form). |
|
|
80
|
+
| `onSubmit` | `(data: BugReportData) => Promise<void> \| void` | Yes | — | **Submit handler.** Send the report wherever you want. Throw/reject to fail the submit. |
|
|
81
|
+
| `uiSettings` | `WidgetUiSettings` | No | `{}` | Appearance and placement options. |
|
|
82
|
+
| `onSuccess` | `(data: BugReportData) => void` | No | — | Called after `onSubmit` resolves. |
|
|
83
|
+
| `onError` | `(error: Error) => void` | No | — | Called when `onSubmit` throws or rejects. |
|
|
84
|
+
| `isOpen` | `boolean` | No | — | Controlled open state for the drawer. |
|
|
85
|
+
| `onToggle` | `(open: boolean) => void` | No | — | Fired when open state changes. |
|
|
86
|
+
| `className` | `string` | No | `''` | Extra class on the floating button wrapper. |
|
|
87
|
+
|
|
88
|
+
### `uiSettings` (`WidgetUiSettings`)
|
|
89
|
+
|
|
90
|
+
| Option | Type | Default | Description |
|
|
91
|
+
|--------|------|---------|-------------|
|
|
92
|
+
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left' \| 'right' \| 'left'` | `'bottom-right'` | Button position; form slides from the same side. |
|
|
93
|
+
| `primaryColor` | `string` | `'#2563eb'` | Accent color for button and actions. |
|
|
94
|
+
| `buttonSize` | `'sm' \| 'md' \| 'lg'` | `'md'` | Floating button size. |
|
|
95
|
+
| `buttonText` | `string` | — | Optional label next to the icon. |
|
|
96
|
+
| `buttonIcon` | `ReactNode` | Bug icon | Custom trigger icon. |
|
|
97
|
+
| `title` | `string` | `'Report a Bug'` | Form header title. |
|
|
98
|
+
| `subtitle` | `string` | `'Found an issue? ...'` | Form header subtitle. |
|
|
99
|
+
| `placeholderTitle` | `string` | — | Title input placeholder. |
|
|
100
|
+
| `placeholderDescription` | `string` | — | Description textarea placeholder. |
|
|
101
|
+
| `zIndex` | `number` | `99990` | Base z-index for overlays. |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Submit payload (`BugReportData`)
|
|
106
|
+
|
|
107
|
+
Your `onSubmit` receives:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
{
|
|
111
|
+
projectUrl: string;
|
|
112
|
+
title: string;
|
|
113
|
+
description: string;
|
|
114
|
+
screenshots: Array<{
|
|
115
|
+
id: string;
|
|
116
|
+
dataUrl: string; // PNG data URL
|
|
117
|
+
createdAt: number;
|
|
118
|
+
}>;
|
|
119
|
+
timestamp: string; // ISO string
|
|
120
|
+
meta: {
|
|
121
|
+
url: string; // page URL where the report was filed
|
|
122
|
+
userAgent: string;
|
|
123
|
+
timestamp?: string;
|
|
124
|
+
screenSize: { width: number; height: number };
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
### Example: POST to your API
|
|
130
|
+
|
|
131
|
+
```tsx
|
|
132
|
+
<Widget
|
|
133
|
+
projectUrl="https://api.example.com/bugs"
|
|
134
|
+
onSubmit={async (data) => {
|
|
135
|
+
await fetch('https://api.example.com/bugs', {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
headers: { 'Content-Type': 'application/json' },
|
|
138
|
+
body: JSON.stringify(data),
|
|
139
|
+
}).then((res) => {
|
|
140
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
141
|
+
});
|
|
142
|
+
}}
|
|
143
|
+
onSuccess={() => console.log('Bug report sent')}
|
|
144
|
+
onError={(err) => console.error(err)}
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Exports
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { Widget } from 'bug-widget-library';
|
|
154
|
+
import type {
|
|
155
|
+
WidgetProps,
|
|
156
|
+
WidgetUiSettings,
|
|
157
|
+
WidgetPosition,
|
|
158
|
+
WidgetButtonSize,
|
|
159
|
+
BugReportData,
|
|
160
|
+
BugReportMetadata,
|
|
161
|
+
ScreenshotItem,
|
|
162
|
+
} from 'bug-widget-library';
|
|
163
|
+
import 'bug-widget-library/style.css';
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
Only `Widget` and the types above are public. Form UI and the annotation editor are internal.
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
## Local development (this repo)
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
npm install
|
|
174
|
+
npm run typecheck
|
|
175
|
+
npm run lint
|
|
176
|
+
npm run build
|
|
177
|
+
```
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,s)=>(s=n==null?{}:e(i(n)),o(r||!n||!n.__esModule||!a.call(n,`default`)?t(s,`default`,{value:n,enumerable:!0}):s,n));let c=require("react");c=s(c,1);let l=require("html2canvas");l=s(l,1);let u=require("lucide-react"),d=require("react/jsx-runtime");function f(e){try{return new URL(e).hostname}catch{return`project`}}var p=({projectUrl:e,isOpen:t,onClose:n,uiSettings:r={},screenshots:i,onTriggerScreenshot:a,onEditScreenshot:o,onDeleteScreenshot:s,onSubmitReport:l})=>{let{position:p=`bottom-right`,primaryColor:m=`#2563eb`,title:h=`Report a Bug`,subtitle:g=`Found an issue? Let us know with details and screenshots.`,placeholderTitle:_=`e.g. Broken checkout button on cart page`,placeholderDescription:v=`Describe what happened, steps to reproduce, and expected result...`}=r,y=(e=>e===`bottom-left`||e===`top-left`||e===`left`)(p),[b,x]=(0,c.useState)(``),[S,C]=(0,c.useState)(``),[w,T]=(0,c.useState)(!1),[E,D]=(0,c.useState)(!1),[O,k]=(0,c.useState)(null),[A,j]=(0,c.useState)({}),[M,N]=(0,c.useState)(null),P=f(e),F=()=>{let e={};return b.trim()||(e.title=`Title / bug name is required.`),S.trim()||(e.description=`Description is required.`),j(e),Object.keys(e).length===0};return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(`div`,{"data-bugdrop-widget":`true`,onClick:n,className:`fixed inset-0 z-[99990] bg-slate-900/40 backdrop-blur-sm transition-opacity duration-300 ${t?`opacity-100 pointer-events-auto`:`opacity-0 pointer-events-none`}`}),(0,d.jsxs)(`aside`,{"data-bugdrop-widget":`true`,className:`fixed top-0 z-[99995] flex h-full w-full max-w-md flex-col bg-white shadow-2xl transition-all duration-300 ease-out sm:max-w-lg ${y?`left-0 border-r border-slate-200`:`right-0 border-l border-slate-200`} ${y?t?`translate-x-0 opacity-100 pointer-events-auto`:`-translate-x-full opacity-0 pointer-events-none`:t?`translate-x-0 opacity-100 pointer-events-auto`:`translate-x-full opacity-0 pointer-events-none`}`,role:`dialog`,"aria-modal":`true`,"aria-label":h,children:[(0,d.jsxs)(`div`,{className:`flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-5`,children:[(0,d.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,d.jsx)(`div`,{className:`flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-md font-bold`,style:{backgroundColor:m},children:(0,d.jsx)(u.Sparkles,{className:`h-5 w-5`})}),(0,d.jsxs)(`div`,{children:[(0,d.jsxs)(`div`,{className:`flex items-center gap-2`,children:[(0,d.jsx)(`h2`,{className:`text-lg font-bold text-slate-800`,children:h}),(0,d.jsx)(`span`,{className:`rounded-md bg-slate-100 px-2 py-0.5 text-[11px] font-semibold tracking-wider text-slate-500`,title:e,children:P})]}),(0,d.jsx)(`p`,{className:`mt-0.5 text-xs text-slate-500`,children:g})]})]}),(0,d.jsx)(`button`,{type:`button`,onClick:n,className:`flex h-8 w-8 items-center justify-center rounded-lg text-slate-400 transition hover:bg-slate-100 hover:text-slate-600`,children:(0,d.jsx)(u.X,{className:`h-5 w-5`})})]}),(0,d.jsx)(`div`,{className:`flex-1 overflow-y-auto px-6 py-5`,children:E?(0,d.jsxs)(`div`,{className:`flex h-full flex-col items-center justify-center text-center py-10 animate-fadeIn`,children:[(0,d.jsx)(`div`,{className:`flex h-16 w-16 items-center justify-center rounded-full text-white shadow-lg mb-4`,style:{backgroundColor:m},children:(0,d.jsx)(u.CheckCircle2,{className:`h-9 w-9`})}),(0,d.jsx)(`h3`,{className:`text-xl font-bold text-slate-800`,children:`Bug Report Submitted!`}),(0,d.jsxs)(`p`,{className:`mt-2 text-sm text-slate-500 max-w-xs`,children:[`Thank you! Your bug report with `,i.length,` screenshot`,i.length===1?``:`s`,` has been captured and logged.`]}),(0,d.jsxs)(`div`,{className:`mt-8 flex flex-col sm:flex-row gap-3 w-full`,children:[(0,d.jsx)(`button`,{type:`button`,onClick:()=>{x(``),C(``),j({}),k(null),D(!1)},className:`flex-1 rounded-xl border border-slate-200 bg-white py-2.5 text-sm font-semibold text-slate-700 shadow-sm transition hover:bg-slate-50`,children:`Report Another Bug`}),(0,d.jsx)(`button`,{type:`button`,onClick:n,style:{backgroundColor:m},className:`flex-1 rounded-xl py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110`,children:`Close`})]})]}):(0,d.jsxs)(`form`,{onSubmit:async t=>{if(t.preventDefault(),F()){T(!0),k(null);try{await l({projectUrl:e,title:b.trim(),description:S.trim(),screenshots:i,timestamp:new Date().toISOString(),meta:{url:window.location.href,userAgent:navigator.userAgent,timestamp:new Date().toISOString(),screenSize:{width:window.innerWidth,height:window.innerHeight}}}),D(!0)}catch(e){console.error(`Failed to submit bug report:`,e),k(e instanceof Error?e.message:`Failed to submit bug report. Please try again.`)}finally{T(!1)}}},className:`space-y-5`,children:[(0,d.jsxs)(`div`,{children:[(0,d.jsxs)(`label`,{className:`block text-xs font-bold tracking-wide uppercase text-slate-700`,children:[`Bug Title / Name `,(0,d.jsx)(`span`,{className:`text-red-500`,children:`*`})]}),(0,d.jsx)(`input`,{type:`text`,value:b,onChange:e=>{x(e.target.value),A.title&&j(e=>({...e,title:void 0}))},placeholder:_,className:`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${A.title?`border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400`:`border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500`}`}),A.title&&(0,d.jsxs)(`p`,{className:`mt-1.5 flex items-center gap-1 text-xs text-red-600`,children:[(0,d.jsx)(u.AlertCircle,{className:`h-3.5 w-3.5`}),(0,d.jsx)(`span`,{children:A.title})]})]}),(0,d.jsxs)(`div`,{children:[(0,d.jsxs)(`label`,{className:`block text-xs font-bold tracking-wide uppercase text-slate-700`,children:[`Description `,(0,d.jsx)(`span`,{className:`text-red-500`,children:`*`})]}),(0,d.jsx)(`textarea`,{rows:4,value:S,onChange:e=>{C(e.target.value),A.description&&j(e=>({...e,description:void 0}))},placeholder:v,className:`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${A.description?`border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400`:`border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500`}`}),A.description&&(0,d.jsxs)(`p`,{className:`mt-1.5 flex items-center gap-1 text-xs text-red-600`,children:[(0,d.jsx)(u.AlertCircle,{className:`h-3.5 w-3.5`}),(0,d.jsx)(`span`,{children:A.description})]})]}),(0,d.jsxs)(`div`,{children:[(0,d.jsxs)(`div`,{className:`flex items-center justify-between`,children:[(0,d.jsxs)(`label`,{className:`block text-xs font-bold tracking-wide uppercase text-slate-700`,children:[`Screenshots `,(0,d.jsx)(`span`,{className:`text-slate-400 font-normal lowercase`,children:`(optional)`})]}),(0,d.jsxs)(`span`,{className:`rounded-full bg-slate-100 px-2 py-0.5 text-xs font-semibold text-slate-600`,children:[i.length,` / 3`]})]}),(0,d.jsx)(`p`,{className:`mt-1 text-xs text-slate-500`,children:`Capture your screen and annotate with pencil, shapes, or arrows.`}),i.length>0&&(0,d.jsx)(`div`,{className:`mt-3 grid grid-cols-3 gap-2.5`,children:i.map((e,t)=>(0,d.jsxs)(`div`,{className:`group relative aspect-video overflow-hidden rounded-lg border border-slate-200 bg-slate-100 shadow-sm`,children:[(0,d.jsx)(`img`,{src:e.dataUrl,alt:`Screenshot ${t+1}`,className:`h-full w-full object-cover transition duration-200 group-hover:scale-105`}),(0,d.jsxs)(`span`,{className:`absolute top-1 left-1 rounded bg-black/60 px-1 py-0.2 text-[10px] font-semibold text-white`,children:[`#`,t+1]}),(0,d.jsxs)(`div`,{className:`absolute inset-0 flex items-center justify-center gap-1.5 bg-black/50 opacity-0 backdrop-blur-[1px] transition-opacity duration-200 group-hover:opacity-100`,children:[(0,d.jsx)(`button`,{type:`button`,onClick:()=>N(e.dataUrl),title:`Preview screenshot`,className:`flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600`,children:(0,d.jsx)(u.Eye,{className:`h-3.5 w-3.5`})}),(0,d.jsx)(`button`,{type:`button`,onClick:()=>o(e),title:`Re-edit / annotate`,className:`flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600`,children:(0,d.jsx)(u.Edit3,{className:`h-3.5 w-3.5`})}),(0,d.jsx)(`button`,{type:`button`,onClick:()=>s(e.id),title:`Delete screenshot`,className:`flex h-7 w-7 items-center justify-center rounded-md bg-red-600 text-white shadow transition hover:bg-red-700`,children:(0,d.jsx)(u.Trash2,{className:`h-3.5 w-3.5`})})]})]},e.id))}),(0,d.jsx)(`div`,{className:`mt-3`,children:i.length<3?(0,d.jsxs)(`button`,{type:`button`,onClick:a,className:`flex w-full items-center justify-center gap-2 rounded-xl border-2 border-dashed border-slate-300 bg-slate-50/70 py-3 text-xs font-semibold text-slate-600 transition hover:border-blue-400 hover:bg-blue-50/50 hover:text-blue-600`,children:[(0,d.jsx)(u.Camera,{className:`h-4 w-4 text-slate-500`}),(0,d.jsx)(`span`,{children:i.length===0?`Capture Screen & Annotate`:`Capture Another Screenshot (${3-i.length} left)`})]}):(0,d.jsx)(`div`,{className:`rounded-lg bg-amber-50 p-2.5 text-center text-xs text-amber-700 border border-amber-200`,children:`Maximum 3 screenshots attached. Delete one to take a new one.`})})]}),O&&(0,d.jsxs)(`div`,{className:`rounded-xl border border-red-200 bg-red-50 px-3.5 py-2.5 text-xs text-red-700 flex items-start gap-2`,children:[(0,d.jsx)(u.AlertCircle,{className:`h-4 w-4 shrink-0 mt-0.5`}),(0,d.jsx)(`span`,{children:O})]}),(0,d.jsxs)(`div`,{className:`pt-4 border-t border-slate-100 flex items-center justify-end gap-3`,children:[(0,d.jsx)(`button`,{type:`button`,onClick:n,className:`rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-600 transition hover:bg-slate-50`,children:`Cancel`}),(0,d.jsx)(`button`,{type:`submit`,disabled:w,style:{backgroundColor:m},className:`flex items-center gap-2 rounded-xl px-5 py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95 disabled:opacity-60`,children:w?(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(u.Loader2,{className:`h-4 w-4 animate-spin`}),(0,d.jsx)(`span`,{children:`Submitting...`})]}):(0,d.jsx)(`span`,{children:`Submit Bug Report`})})]})]})})]}),M&&(0,d.jsx)(`div`,{"data-bugdrop-widget":`true`,onClick:()=>N(null),className:`fixed inset-0 z-[100001] flex items-center justify-center bg-black/80 p-4 backdrop-blur-sm animate-fadeIn`,children:(0,d.jsxs)(`div`,{className:`relative max-h-[90vh] max-w-[90vw] overflow-hidden rounded-xl bg-slate-900 shadow-2xl`,onClick:e=>e.stopPropagation(),children:[(0,d.jsx)(`img`,{src:M,alt:`Screenshot Preview`,className:`max-h-[85vh] w-auto rounded-xl object-contain`}),(0,d.jsx)(`button`,{type:`button`,onClick:()=>N(null),className:`absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-black/60 text-white shadow hover:bg-black/90`,children:(0,d.jsx)(u.X,{className:`h-4 w-4`})})]})})]})},m=null;function h(){return m||=import(`konva`).then(e=>{let t=e;return t.default??t}).catch(e=>{throw m=null,e}),m}var g=typeof window<`u`?c.useLayoutEffect:c.useEffect;function _(e){let t=e,n={stroke:e.stroke,strokeWidth:e.strokeWidth,rotation:t.rotation??0};switch(e.type){case`line`:return{...n,x:t.x??0,y:t.y??0,points:e.points,tension:.5,lineCap:`round`,lineJoin:`round`,globalCompositeOperation:e.tool===`eraser`?`destination-out`:`source-over`};case`rectangle`:return{...n,x:e.x,y:e.y,width:e.width,height:e.height};case`circle`:return{...n,x:e.x,y:e.y,radius:e.radius};case`arrow`:return{...n,x:t.x??0,y:t.y??0,points:e.points,fill:e.fill,pointerLength:14,pointerWidth:14};default:return n}}function v(e,t,n){let r={..._(t),...n};switch(t.type){case`line`:return new e.Line(r);case`rectangle`:return new e.Rect(r);case`circle`:return new e.Circle(r);case`arrow`:return new e.Arrow(r);default:return null}}var y=[`#ef4444`,`#f97316`,`#eab308`,`#10b981`,`#3b82f6`,`#8b5cf6`,`#ec4899`,`#000000`,`#ffffff`],b=[{label:`S`,value:3},{label:`M`,value:6},{label:`L`,value:10},{label:`XL`,value:16}],x=[{id:`select`,title:`Select & Move / Resize`,Icon:u.MousePointer},{id:`pencil`,title:`Pencil / Draw`,Icon:u.Pencil},{id:`eraser`,title:`Eraser (click or drag to erase)`,Icon:u.Eraser},{id:`rectangle`,title:`Rectangle (Resizable)`,Icon:u.Square},{id:`circle`,title:`Circle (Resizable)`,Icon:u.Circle},{id:`arrow`,title:`Arrow (Resizable)`,Icon:u.ArrowUpRight}],S=[`top-left`,`top-right`,`bottom-left`,`bottom-right`,`middle-left`,`middle-right`,`top-center`,`bottom-center`],C=({imageSrc:e,onSave:t,onCancel:n,primaryColor:r=`#2563eb`})=>{let i=(0,c.useRef)(null),a=(0,c.useRef)(null),o=(0,c.useRef)(null),s=(0,c.useRef)(null),l=(0,c.useRef)(null),f=(0,c.useRef)(null),p=(0,c.useRef)(null),m=(0,c.useRef)(null),[C,w]=(0,c.useState)(null),[T,E]=(0,c.useState)(null),[D,O]=(0,c.useState)(null),[k,A]=(0,c.useState)(1),[j,M]=(0,c.useState)({width:800,height:600}),[N,P]=(0,c.useState)(`pencil`),[F,I]=(0,c.useState)(`#ef4444`),[L,R]=(0,c.useState)(6),[z,B]=(0,c.useState)(null),[V,H]=(0,c.useState)([]),[U,W]=(0,c.useState)([[]]),[G,K]=(0,c.useState)(0);(0,c.useEffect)(()=>{let e=!1;return h().then(t=>{e||w(()=>t)}).catch(()=>{e||E(`The annotation editor could not load. Check your connection and try again.`)}),()=>{e=!0}},[]),(0,c.useEffect)(()=>{let t=new window.Image;return t.crossOrigin=`anonymous`,t.onload=()=>O(t),t.src=e,()=>{t.onload=null}},[e]);let q=(0,c.useCallback)(()=>{if(!i.current||!D)return;let e=Math.max(300,i.current.clientWidth-48),t=Math.max(300,i.current.clientHeight-120),n=Math.min(e/D.naturalWidth,t/D.naturalHeight,1);A(n),M({width:Math.round(D.naturalWidth*n),height:Math.round(D.naturalHeight*n)})},[D]);(0,c.useEffect)(()=>(q(),window.addEventListener(`resize`,q),()=>window.removeEventListener(`resize`,q)),[q]),(0,c.useEffect)(()=>{let e=a.current;if(!C||!D||!e)return;let t=C,n=new t.Stage({container:e,width:1,height:1}),r=new t.Layer({listening:!1});r.add(new t.Image({name:`bg-image`,image:D,width:D.naturalWidth,height:D.naturalHeight}));let i=new t.Layer,c=new t.Transformer({rotateEnabled:!0,enabledAnchors:S,borderStroke:`#3b82f6`,borderDash:[4,4],anchorFill:`#ffffff`,anchorStroke:`#3b82f6`,anchorSize:9,anchorCornerRadius:2,boundBoxFunc:(e,t)=>Math.abs(t.width)<10||Math.abs(t.height)<10?e:t});i.add(c),n.add(r),n.add(i),n.on(`pointerdown`,e=>m.current?.pointerDown(e)),n.on(`pointermove`,()=>m.current?.pointerMove()),n.on(`pointerup`,()=>m.current?.pointerUp());let u=()=>m.current?.pointerUp();return window.addEventListener(`pointerup`,u),window.addEventListener(`pointercancel`,u),o.current=n,s.current=i,l.current=c,()=>{window.removeEventListener(`pointerup`,u),window.removeEventListener(`pointercancel`,u),p.current=null,f.current=null,n.destroy(),o.current=null,s.current=null,l.current=null}},[C,D]),(0,c.useEffect)(()=>{let e=o.current;e&&(e.size(j),e.scale({x:k,y:k}))},[C,D,k,j]),(0,c.useEffect)(()=>{let e=C,t=s.current,n=l.current;if(!e||!t||!n)return;n.nodes([]),t.find(`.annotation`).forEach(e=>e.destroy());let r=N===`select`;V.forEach(n=>{let i=n.type===`line`&&n.tool===`eraser`,a=v(e,n,{id:n.id,name:`annotation`,draggable:r&&!i,hitStrokeWidth:Math.max(n.strokeWidth,12)});a&&(a.on(`dragend`,()=>m.current?.dragEnd(a,n.id)),a.on(`transformend`,()=>m.current?.transformEnd(a,n.id)),t.add(a))}),n.moveToTop()},[C,D,V,N]),(0,c.useEffect)(()=>{let e=s.current,t=l.current;if(!e||!t)return;let n=z?e.findOne(`#`+z):void 0;if(!n){t.nodes([]);return}let r=n.getClassName()===`Line`;t.resizeEnabled(!r),t.rotateEnabled(!r),t.nodes([n])},[C,D,V,N,z]);let J=e=>{H(e),W([...U.slice(0,G+1),e]),K(G+1)},Y=()=>{if(G<=0)return;let e=G-1;K(e),H(U[e]),B(null)},X=()=>{if(G>=U.length-1)return;let e=G+1;K(e),H(U[e]),B(null)},ee=()=>{V.length!==0&&(J([]),B(null))},Z=()=>{z&&(J(V.filter(e=>e.id!==z)),B(null))},Q=()=>{let e=o.current?.getPointerPosition();return e?{x:e.x/k,y:e.y/k}:null},te=e=>{let t=o.current,n=s.current,r=C;if(!t||!n||!r||p.current)return;let i=Q();if(!i)return;let{x:a,y:c}=i,l=e.target,u=l===t?``:l.id(),d=u?V.find(e=>e.id===u):void 0;if(N===`select`){d?(d.type!==`line`||d.tool!==`eraser`)&&B(d.id):(l===t||l.hasName(`bg-image`))&&B(null);return}if(N===`eraser`&&d){J(V.filter(e=>e.id!==d.id)),B(null);return}B(null);let m=`shape_${Date.now()}_${Math.random().toString(36).substring(2,7)}`,h;h=N===`pencil`||N===`eraser`?{id:m,type:`line`,tool:N,points:[a,c],stroke:N===`eraser`?`#ffffff`:F,strokeWidth:N===`eraser`?L*2.5:L}:N===`rectangle`?{id:m,type:`rectangle`,x:a,y:c,width:0,height:0,stroke:F,strokeWidth:L}:N===`circle`?{id:m,type:`circle`,x:a,y:c,radius:0,stroke:F,strokeWidth:L}:{id:m,type:`arrow`,points:[a,c,a,c],stroke:F,fill:F,strokeWidth:L};let g=v(r,h,{listening:!1,dash:h.type===`line`?void 0:[6,4]});g&&(n.add(g),f.current=g,p.current={start:{x:a,y:c},data:h})},ne=()=>{let e=p.current;if(!e)return;let t=Q();if(!t)return;let{x:n,y:r}=t,{start:i,data:a}=e,o=a;a.type===`line`?o={...a,points:[...a.points,n,r]}:a.type===`rectangle`?o={...a,x:Math.min(i.x,n),y:Math.min(i.y,r),width:Math.abs(n-i.x),height:Math.abs(r-i.y)}:a.type===`circle`?o={...a,radius:Math.hypot(n-i.x,r-i.y)}:a.type===`arrow`&&(o={...a,points:[i.x,i.y,n,r]}),e.data=o,f.current?.setAttrs(_(o))},re=()=>{let e=p.current;if(!e)return;p.current=null,f.current?.destroy(),f.current=null;let t=e.data,n=!1;if(t.type===`line`)n=t.points.length>=2;else if(t.type===`rectangle`)n=t.width>6&&t.height>6;else if(t.type===`circle`)n=t.radius>5;else if(t.type===`arrow`){let[e,r,i,a]=t.points;n=Math.hypot(i-e,a-r)>10}n&&(J([...V,t]),(t.type===`rectangle`||t.type===`circle`||t.type===`arrow`)&&(B(t.id),P(`select`)))},ie=(e,t)=>{V.some(e=>e.id===t)&&J(V.map(n=>n.id===t?{...n,x:e.x(),y:e.y()}:n))},ae=(e,t)=>{let n=V.find(e=>e.id===t);if(!n)return;let r=e.scaleX(),i=e.scaleY();e.scaleX(1),e.scaleY(1);let a=null;if(n.type===`rectangle`)a={...n,x:e.x(),y:e.y(),width:Math.max(10,e.width()*r),height:Math.max(10,e.height()*i),rotation:e.rotation()};else if(n.type===`circle`)a={...n,x:e.x(),y:e.y(),radius:Math.max(6,n.radius*r),rotation:e.rotation()};else if(n.type===`arrow`){let[t,o,s,c]=n.points;a={...n,x:e.x(),y:e.y(),points:[t,o,t+(s-t)*r,o+(c-o)*i],rotation:e.rotation()}}if(!a)return;let o=a;J(V.map(e=>e.id===t?o:e))};g(()=>{m.current={pointerDown:te,pointerMove:ne,pointerUp:re,dragEnd:ie,transformEnd:ae,undo:Y,redo:X,deleteSelected:Z,hasSelection:()=>z!==null,clearSelection:()=>B(null)}}),(0,c.useEffect)(()=>{let e=e=>{let t=m.current;if(!t||e.target instanceof HTMLInputElement||e.target instanceof HTMLTextAreaElement)return;let n=e.ctrlKey||e.metaKey,r=e.key.toLowerCase();n&&r===`z`?(e.shiftKey?t.redo():t.undo(),e.preventDefault()):n&&r===`y`?(t.redo(),e.preventDefault()):(e.key===`Delete`||e.key===`Backspace`)&&t.hasSelection()?(t.deleteSelected(),e.preventDefault()):e.key===`Escape`&&(t.clearSelection(),e.preventDefault())};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]);let oe=()=>{let e=o.current;e&&(l.current?.nodes([]),B(null),t(e.toDataURL({pixelRatio:1/k,mimeType:`image/png`})))},se=e=>{P(e),e!==`select`&&B(null)},$=!!(D&&C);return(0,d.jsxs)(`div`,{ref:i,className:`fixed inset-0 z-[100000] flex flex-col bg-slate-950/90 backdrop-blur-md select-none text-white overflow-hidden animate-fadeIn`,style:{touchAction:`none`},children:[(0,d.jsxs)(`div`,{className:`flex h-16 shrink-0 items-center justify-between border-b border-slate-800 bg-slate-900/90 px-4 sm:px-6`,children:[(0,d.jsxs)(`div`,{className:`flex items-center gap-3`,children:[(0,d.jsx)(`div`,{className:`flex h-8 w-8 items-center justify-center rounded-lg text-white font-bold text-sm shadow`,style:{backgroundColor:r},children:`BD`}),(0,d.jsxs)(`div`,{children:[(0,d.jsx)(`h1`,{className:`text-sm sm:text-base font-semibold leading-tight text-slate-100`,children:`Screenshot Editor`}),(0,d.jsx)(`p`,{className:`text-xs text-slate-400 hidden sm:block`,children:`Highlight issues with pencil, arrows, circles, and boxes`})]})]}),(0,d.jsxs)(`div`,{className:`flex items-center gap-2 sm:gap-3`,children:[(0,d.jsx)(`button`,{type:`button`,onClick:Y,disabled:G<=0,title:`Undo (Ctrl+Z)`,className:`flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none`,children:(0,d.jsx)(u.Undo2,{className:`h-4 w-4`})}),(0,d.jsx)(`button`,{type:`button`,onClick:X,disabled:G>=U.length-1,title:`Redo (Ctrl+Y)`,className:`flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none`,children:(0,d.jsx)(u.Redo2,{className:`h-4 w-4`})}),(0,d.jsxs)(`button`,{type:`button`,onClick:ee,disabled:V.length===0,title:`Clear all annotations`,className:`flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-2.5 text-xs font-medium text-slate-300 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none`,children:[(0,d.jsx)(u.Trash2,{className:`h-3.5 w-3.5`}),(0,d.jsx)(`span`,{className:`hidden md:inline`,children:`Clear All`})]}),(0,d.jsx)(`div`,{className:`h-5 w-px bg-slate-700 mx-1`}),(0,d.jsxs)(`button`,{type:`button`,onClick:n,className:`flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-3 text-xs sm:text-sm font-medium text-slate-200 transition hover:bg-slate-700 hover:text-white`,children:[(0,d.jsx)(u.X,{className:`h-4 w-4`}),(0,d.jsx)(`span`,{children:`Cancel`})]}),(0,d.jsxs)(`button`,{type:`button`,onClick:oe,disabled:!$,style:{backgroundColor:r},className:`flex h-9 items-center gap-1.5 rounded-lg px-4 text-xs sm:text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95 disabled:opacity-50 disabled:pointer-events-none`,children:[(0,d.jsx)(u.Check,{className:`h-4 w-4`}),(0,d.jsx)(`span`,{children:`Add to Report`})]})]})]}),(0,d.jsxs)(`div`,{className:`absolute top-20 left-1/2 -translate-x-1/2 z-20 flex flex-wrap items-center justify-center gap-2 rounded-2xl border border-slate-700/80 bg-slate-900/95 p-2 shadow-2xl backdrop-blur-md`,children:[(0,d.jsx)(`div`,{className:`flex items-center gap-1`,children:x.map(({id:e,title:t,Icon:n})=>(0,d.jsx)(`button`,{type:`button`,onClick:()=>se(e),title:t,"aria-pressed":N===e,className:`flex h-9 w-9 items-center justify-center rounded-xl transition ${N===e?`bg-blue-600 text-white shadow-inner`:`text-slate-300 hover:bg-slate-800 hover:text-white`}`,children:(0,d.jsx)(n,{className:`h-4 w-4`})},e))}),(0,d.jsx)(`div`,{className:`h-5 w-px bg-slate-700`}),(0,d.jsxs)(`div`,{className:`flex items-center gap-1.5 px-1`,children:[y.map(e=>(0,d.jsx)(`button`,{type:`button`,onClick:()=>I(e),title:e,"aria-label":`Color ${e}`,style:{backgroundColor:e},className:`h-5 w-5 rounded-full border border-slate-700 transition-transform ${F===e?`scale-125 ring-2 ring-white ring-offset-1 ring-offset-slate-900`:`hover:scale-110`}`},e)),(0,d.jsxs)(`label`,{title:`Custom Color`,className:`relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-full border border-slate-600 bg-slate-800 text-slate-300 hover:text-white transition`,children:[(0,d.jsx)(u.Palette,{className:`h-3.5 w-3.5`}),(0,d.jsx)(`input`,{type:`color`,value:F,onChange:e=>I(e.target.value),className:`absolute inset-0 opacity-0 cursor-pointer`})]})]}),(0,d.jsx)(`div`,{className:`h-5 w-px bg-slate-700`}),(0,d.jsx)(`div`,{className:`flex items-center gap-1`,children:b.map(e=>(0,d.jsx)(`button`,{type:`button`,onClick:()=>R(e.value),className:`flex h-7 w-7 items-center justify-center rounded-lg text-xs font-semibold transition ${L===e.value?`bg-slate-700 text-white ring-1 ring-slate-400`:`text-slate-400 hover:bg-slate-800 hover:text-white`}`,children:e.label},e.value))}),z&&(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(`div`,{className:`h-5 w-px bg-slate-700`}),(0,d.jsxs)(`button`,{type:`button`,onClick:Z,title:`Delete Selected Shape (Del / Backspace)`,className:`flex h-8 items-center gap-1.5 rounded-xl bg-red-600/90 px-3 text-xs font-semibold text-white shadow hover:bg-red-600`,children:[(0,d.jsx)(u.Trash2,{className:`h-3.5 w-3.5`}),(0,d.jsx)(`span`,{children:`Delete`})]})]})]}),(0,d.jsx)(`div`,{className:`relative flex flex-1 items-center justify-center p-4 overflow-hidden`,children:T?(0,d.jsx)(`p`,{className:`text-sm text-red-300`,children:T}):$?(0,d.jsx)(`div`,{className:`relative shadow-2xl rounded-md overflow-hidden border border-slate-700 bg-slate-900`,style:{width:j.width,height:j.height,cursor:N===`select`?`default`:N===`eraser`?`cell`:`crosshair`},children:(0,d.jsx)(`div`,{ref:a})}):(0,d.jsxs)(`div`,{className:`flex flex-col items-center gap-2 text-slate-400`,children:[(0,d.jsx)(`div`,{className:`h-8 w-8 animate-spin rounded-full border-2 border-blue-500 border-t-transparent`}),(0,d.jsx)(`p`,{className:`text-sm`,children:`Loading screenshot...`})]})}),(0,d.jsxs)(`div`,{className:`flex h-10 shrink-0 items-center justify-between border-t border-slate-800 bg-slate-900/80 px-4 text-xs text-slate-400`,children:[(0,d.jsxs)(`div`,{className:`flex items-center gap-4`,children:[(0,d.jsxs)(`span`,{children:[`Active tool: `,(0,d.jsx)(`strong`,{className:`text-slate-200 capitalize`,children:N})]}),(0,d.jsxs)(`span`,{className:`hidden sm:inline`,children:[`Use `,(0,d.jsx)(`kbd`,{className:`rounded bg-slate-800 px-1 py-0.5 text-slate-300`,children:`Ctrl+Z`}),` to undo,`,` `,(0,d.jsx)(`kbd`,{className:`rounded bg-slate-800 px-1 py-0.5 text-slate-300`,children:`Del`}),` to remove selected shape`]})]}),(0,d.jsx)(`div`,{children:D&&(0,d.jsxs)(`span`,{children:[`Original Resolution: `,D.naturalWidth,` x `,D.naturalHeight,`px`]})})]})]})},w=({projectUrl:e,onSubmit:t,uiSettings:n={},onSuccess:r,onError:i,isOpen:a,onToggle:o,className:s=``})=>{let{position:f=`bottom-right`,primaryColor:m=`#2563eb`,buttonSize:h=`md`,buttonText:g,buttonIcon:_,zIndex:v=99990}=n,[y,b]=(0,c.useState)(!1),x=a===void 0?y:a,S=e=>{a===void 0&&b(e),o?.(e)},[w,T]=(0,c.useState)([]),[E,D]=(0,c.useState)(!1),[O,k]=(0,c.useState)(!1),[A,j]=(0,c.useState)(null),M=e=>{switch(e){case`bottom-left`:return`bottom-6 left-6`;case`top-left`:return`top-6 left-6`;case`top-right`:return`top-6 right-6`;case`left`:return`top-1/2 -translate-y-1/2 left-4`;case`right`:return`top-1/2 -translate-y-1/2 right-4`;default:return`bottom-6 right-6`}},N=(e=>{switch(e){case`sm`:return{button:`h-10 px-3.5 gap-2 text-xs font-semibold rounded-full shadow-md`,icon:`h-4 w-4`};case`lg`:return{button:`h-14 px-5 gap-3 text-base font-bold rounded-full shadow-xl`,icon:`h-6 w-6`};default:return{button:`h-12 px-4 gap-2.5 text-sm font-semibold rounded-full shadow-lg`,icon:`h-5 w-5`}}})(h);return E?null:(0,d.jsxs)(d.Fragment,{children:[!O&&(0,d.jsx)(`div`,{"data-bugdrop-widget":`true`,className:`fixed ${M(f)} ${s}`,style:{zIndex:v},children:(0,d.jsxs)(`button`,{type:`button`,onClick:()=>S(!x),style:{backgroundColor:m},className:`group flex items-center justify-center text-white transition-all duration-200 hover:brightness-110 active:scale-95 ${N.button}`,"aria-label":x?`Close bug report form`:`Open bug report form`,title:x?`Close Bug Report`:`Report a Bug`,children:[x?(0,d.jsx)(u.X,{className:N.icon}):_||(0,d.jsx)(u.Bug,{className:N.icon}),g&&(0,d.jsx)(`span`,{children:g}),w.length>0&&!x&&(0,d.jsx)(`span`,{className:`flex h-5 w-5 items-center justify-center rounded-full bg-white text-[11px] font-bold text-slate-900 shadow`,children:w.length})]})}),!O&&(0,d.jsx)(p,{projectUrl:e,isOpen:x,onClose:()=>S(!1),uiSettings:n,screenshots:w,onTriggerScreenshot:async()=>{D(!0);try{await new Promise(e=>setTimeout(e,180));let e=(await(0,l.default)(document.documentElement,{useCORS:!0,allowTaint:!0,logging:!1,scrollX:0,scrollY:-window.scrollY,windowWidth:document.documentElement.offsetWidth,windowHeight:document.documentElement.offsetHeight,ignoreElements:e=>e.getAttribute(`data-bugdrop-widget`)===`true`||e.classList.contains(`bugdrop-ignore`)})).toDataURL(`image/png`);j({dataUrl:e,isNew:!0}),k(!0)}catch(e){console.error(`Error taking screenshot:`,e),alert(`Could not capture screenshot. Please try again.`)}finally{D(!1)}},onEditScreenshot:e=>{j({id:e.id,dataUrl:e.dataUrl,isNew:!1}),k(!0)},onDeleteScreenshot:e=>{T(t=>t.filter(t=>t.id!==e))},onSubmitReport:async e=>{try{await t(e),r?.(e)}catch(e){let t=e instanceof Error?e:Error(`Failed to submit bug report`);throw i?.(t),t}}}),O&&A&&(0,d.jsx)(C,{imageSrc:A.dataUrl,onSave:e=>{if(A?.isNew){if(w.length<3){let t={id:`ss_${Date.now()}_${Math.random().toString(36).substring(2,6)}`,dataUrl:e,createdAt:Date.now()};T(e=>[...e,t])}}else A?.id&&T(t=>t.map(t=>t.id===A.id?{...t,dataUrl:e}:t));k(!1),j(null),S(!0)},onCancel:()=>{k(!1),j(null),S(!0)},primaryColor:m})]})};exports.Widget=w;
|
|
2
|
+
//# sourceMappingURL=bug-widget-library.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bug-widget-library.cjs","names":["useState","_Fragment","Sparkles","X","CheckCircle2","AlertCircle","Eye","Edit3","Trash2","Camera","Loader2","useLayoutEffect","useEffect","MousePointer","Pencil","Eraser","Square","CircleIcon","ArrowUpRight","useRef","useState","useCallback","Undo2","Redo2","Trash2","X","Check","Palette","_Fragment","useState","_Fragment","X","Bug","__create","__defProp","__getOwnPropDesc","__getOwnPropNames","__getProtoOf","__hasOwnProp","__copyProps","from","keys","i","n","key","to","except","k","desc","__toESM","mod","isNodeMode","target","react","html2canvas","lucide_react","react_jsx_runtime","getProjectLabel","projectUrl","Form","uiSettings","isLeft","pos","position","reportTitle","setReportTitle","description","setDescription","isSubmitting","setIsSubmitting","isSuccess","setIsSuccess","submitError","setSubmitError","errors","setErrors","previewImage","setPreviewImage","projectLabel","validate","errs","onClose","isOpen","title","primaryColor","subtitle","screenshots","e","onSubmitReport","err","prev","placeholderTitle","placeholderDescription","s","idx","onEditScreenshot","onDeleteScreenshot","onTriggerScreenshot","konvaPromise","loadKonva","m","useIsomorphicLayoutEffect","shapeAttrs","p","shape","base","createNode","attrs","extra","K","PRESET_COLORS","STROKE_WIDTHS","TOOLS","TRANSFORMER_ANCHORS","KonvaEditor","containerRef","stageHostRef","stageRef","layerRef","transformerRef","draftNodeRef","drawingRef","handlersRef","konvaLib","setKonvaLib","loadError","setLoadError","image","setImage","scale","setScale","stageDimensions","setStageDimensions","tool","setTool","color","setColor","strokeWidth","setStrokeWidth","selectedId","setSelectedId","shapes","setShapes","history","setHistory","historyStep","setHistoryStep","cancelled","img","imageSrc","updateDimensions","availWidth","availHeight","fitScale","host","stage","bgLayer","layer","transformer","newBox","oldBox","endStroke","node","isSelectable","isEraserStroke","isLine","commit","nextShapes","handleUndo","newStep","handleRedo","handleClearAll","handleDeleteSelected","getPointer","pointer","handlePointerDown","point","hitId","hitShape","id","data","x","y","draftNode","handlePointerMove","drawing","next","start","handlePointerUp","draft","isValid","x1","y1","x2","y2","handleDragEnd","handleTransformEnd","scaleX","scaleY","updated","result","handleKeyDown","h","handleExport","onSave","selectTool","isReady","onCancel","Icon","c","sw","Widget","controlledIsOpen","internalIsOpen","setInternalIsOpen","setOpen","open","onToggle","setScreenshots","isCapturing","setIsCapturing","isEditorOpen","setIsEditorOpen","editingScreenshot","setEditingScreenshot","getPositionClasses","sizeClasses","size","buttonSize","className","buttonIcon","buttonText","resolve","dataUrl","element","item","onSubmit","reportData","onSuccess","error","onError","newItem","editedDataUrl"],"sources":["../src/components/Form.tsx","../src/components/KonvaEditor.tsx","../src/components/Widget.tsx"],"sourcesContent":["import React, { useState } from 'react';\nimport {\n Camera,\n X,\n Trash2,\n Edit3,\n Eye,\n CheckCircle2,\n AlertCircle,\n Loader2,\n Sparkles,\n} from 'lucide-react';\nimport type {\n BugReportData,\n ScreenshotItem,\n WidgetUiSettings,\n WidgetPosition,\n} from '../types';\n\ninterface FormProps {\n projectUrl: string;\n isOpen: boolean;\n onClose: () => void;\n uiSettings?: WidgetUiSettings;\n screenshots: ScreenshotItem[];\n onTriggerScreenshot: () => void;\n onEditScreenshot: (screenshot: ScreenshotItem) => void;\n onDeleteScreenshot: (id: string) => void;\n onSubmitReport: (data: BugReportData) => Promise<void> | void;\n}\n\nfunction getProjectLabel(projectUrl: string): string {\n try {\n return new URL(projectUrl).hostname;\n } catch {\n return 'project';\n }\n}\n\nexport const Form: React.FC<FormProps> = ({\n projectUrl,\n isOpen,\n onClose,\n uiSettings = {},\n screenshots,\n onTriggerScreenshot,\n onEditScreenshot,\n onDeleteScreenshot,\n onSubmitReport,\n}) => {\n const {\n position = 'bottom-right',\n primaryColor = '#2563eb',\n title = 'Report a Bug',\n subtitle = 'Found an issue? Let us know with details and screenshots.',\n placeholderTitle = 'e.g. Broken checkout button on cart page',\n placeholderDescription = 'Describe what happened, steps to reproduce, and expected result...',\n } = uiSettings;\n\n const isLeftPosition = (pos: WidgetPosition) =>\n pos === 'bottom-left' || pos === 'top-left' || pos === 'left';\n\n const isLeft = isLeftPosition(position);\n\n // Form input states\n const [reportTitle, setReportTitle] = useState('');\n const [description, setDescription] = useState('');\n const [isSubmitting, setIsSubmitting] = useState(false);\n const [isSuccess, setIsSuccess] = useState(false);\n const [submitError, setSubmitError] = useState<string | null>(null);\n const [errors, setErrors] = useState<{ title?: string; description?: string }>({});\n const [previewImage, setPreviewImage] = useState<string | null>(null);\n const projectLabel = getProjectLabel(projectUrl);\n\n // Form validation\n const validate = () => {\n const errs: { title?: string; description?: string } = {};\n if (!reportTitle.trim()) {\n errs.title = 'Title / bug name is required.';\n }\n if (!description.trim()) {\n errs.description = 'Description is required.';\n }\n setErrors(errs);\n return Object.keys(errs).length === 0;\n };\n\n const handleSubmit = async (e: React.FormEvent) => {\n e.preventDefault();\n if (!validate()) return;\n\n setIsSubmitting(true);\n setSubmitError(null);\n try {\n const reportData: BugReportData = {\n projectUrl,\n title: reportTitle.trim(),\n description: description.trim(),\n screenshots,\n timestamp: new Date().toISOString(),\n meta: {\n url: window.location.href,\n userAgent: navigator.userAgent,\n timestamp: new Date().toISOString(),\n screenSize: {\n width: window.innerWidth,\n height: window.innerHeight,\n },\n },\n };\n\n await onSubmitReport(reportData);\n setIsSuccess(true);\n } catch (err) {\n console.error('Failed to submit bug report:', err);\n setSubmitError(\n err instanceof Error ? err.message : 'Failed to submit bug report. Please try again.'\n );\n } finally {\n setIsSubmitting(false);\n }\n };\n\n const handleReset = () => {\n setReportTitle('');\n setDescription('');\n setErrors({});\n setSubmitError(null);\n setIsSuccess(false);\n };\n\n // Determine slide animation direction\n const slideClass = isLeft\n ? isOpen\n ? 'translate-x-0 opacity-100 pointer-events-auto'\n : '-translate-x-full opacity-0 pointer-events-none'\n : isOpen\n ? 'translate-x-0 opacity-100 pointer-events-auto'\n : 'translate-x-full opacity-0 pointer-events-none';\n\n return (\n <>\n {/* Subtle backdrop overlay */}\n <div\n data-bugdrop-widget=\"true\"\n onClick={onClose}\n className={`fixed inset-0 z-[99990] bg-slate-900/40 backdrop-blur-sm transition-opacity duration-300 ${\n isOpen ? 'opacity-100 pointer-events-auto' : 'opacity-0 pointer-events-none'\n }`}\n />\n\n {/* Slide-in Drawer Container */}\n <aside\n data-bugdrop-widget=\"true\"\n className={`fixed top-0 z-[99995] flex h-full w-full max-w-md flex-col bg-white shadow-2xl transition-all duration-300 ease-out sm:max-w-lg ${\n isLeft ? 'left-0 border-r border-slate-200' : 'right-0 border-l border-slate-200'\n } ${slideClass}`}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={title}\n >\n {/* Header */}\n <div className=\"flex shrink-0 items-center justify-between border-b border-slate-100 px-6 py-5\">\n <div className=\"flex items-center gap-3\">\n <div\n className=\"flex h-10 w-10 items-center justify-center rounded-xl text-white shadow-md font-bold\"\n style={{ backgroundColor: primaryColor }}\n >\n <Sparkles className=\"h-5 w-5\" />\n </div>\n <div>\n <div className=\"flex items-center gap-2\">\n <h2 className=\"text-lg font-bold text-slate-800\">{title}</h2>\n <span\n className=\"rounded-md bg-slate-100 px-2 py-0.5 text-[11px] font-semibold tracking-wider text-slate-500\"\n title={projectUrl}\n >\n {projectLabel}\n </span>\n </div>\n <p className=\"mt-0.5 text-xs text-slate-500\">{subtitle}</p>\n </div>\n </div>\n\n <button\n type=\"button\"\n onClick={onClose}\n className=\"flex h-8 w-8 items-center justify-center rounded-lg text-slate-400 transition hover:bg-slate-100 hover:text-slate-600\"\n >\n <X className=\"h-5 w-5\" />\n </button>\n </div>\n\n {/* Content Area */}\n <div className=\"flex-1 overflow-y-auto px-6 py-5\">\n {isSuccess ? (\n <div className=\"flex h-full flex-col items-center justify-center text-center py-10 animate-fadeIn\">\n <div\n className=\"flex h-16 w-16 items-center justify-center rounded-full text-white shadow-lg mb-4\"\n style={{ backgroundColor: primaryColor }}\n >\n <CheckCircle2 className=\"h-9 w-9\" />\n </div>\n <h3 className=\"text-xl font-bold text-slate-800\">\n Bug Report Submitted!\n </h3>\n <p className=\"mt-2 text-sm text-slate-500 max-w-xs\">\n Thank you! Your bug report with {screenshots.length} screenshot{screenshots.length !== 1 ? 's' : ''} has been captured and logged.\n </p>\n\n <div className=\"mt-8 flex flex-col sm:flex-row gap-3 w-full\">\n <button\n type=\"button\"\n onClick={handleReset}\n className=\"flex-1 rounded-xl border border-slate-200 bg-white py-2.5 text-sm font-semibold text-slate-700 shadow-sm transition hover:bg-slate-50\"\n >\n Report Another Bug\n </button>\n <button\n type=\"button\"\n onClick={onClose}\n style={{ backgroundColor: primaryColor }}\n className=\"flex-1 rounded-xl py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110\"\n >\n Close\n </button>\n </div>\n </div>\n ) : (\n <form onSubmit={handleSubmit} className=\"space-y-5\">\n {/* Bug Title / Name (Required) */}\n <div>\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Bug Title / Name <span className=\"text-red-500\">*</span>\n </label>\n <input\n type=\"text\"\n value={reportTitle}\n onChange={(e) => {\n setReportTitle(e.target.value);\n if (errors.title) setErrors((prev) => ({ ...prev, title: undefined }));\n }}\n placeholder={placeholderTitle}\n className={`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${\n errors.title\n ? 'border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400'\n : 'border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500'\n }`}\n />\n {errors.title && (\n <p className=\"mt-1.5 flex items-center gap-1 text-xs text-red-600\">\n <AlertCircle className=\"h-3.5 w-3.5\" />\n <span>{errors.title}</span>\n </p>\n )}\n </div>\n\n {/* Bug Description (Required) */}\n <div>\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Description <span className=\"text-red-500\">*</span>\n </label>\n <textarea\n rows={4}\n value={description}\n onChange={(e) => {\n setDescription(e.target.value);\n if (errors.description) {\n setErrors((prev) => ({ ...prev, description: undefined }));\n }\n }}\n placeholder={placeholderDescription}\n className={`mt-1.5 w-full rounded-xl border px-3.5 py-2.5 text-sm transition focus:outline-none focus:ring-2 ${\n errors.description\n ? 'border-red-300 bg-red-50/50 text-red-900 focus:ring-red-400'\n : 'border-slate-200 bg-white text-slate-800 focus:border-transparent focus:ring-blue-500'\n }`}\n />\n {errors.description && (\n <p className=\"mt-1.5 flex items-center gap-1 text-xs text-red-600\">\n <AlertCircle className=\"h-3.5 w-3.5\" />\n <span>{errors.description}</span>\n </p>\n )}\n </div>\n\n {/* Screenshots Section (Max 3, Optional) */}\n <div>\n <div className=\"flex items-center justify-between\">\n <label className=\"block text-xs font-bold tracking-wide uppercase text-slate-700\">\n Screenshots <span className=\"text-slate-400 font-normal lowercase\">(optional)</span>\n </label>\n <span className=\"rounded-full bg-slate-100 px-2 py-0.5 text-xs font-semibold text-slate-600\">\n {screenshots.length} / 3\n </span>\n </div>\n <p className=\"mt-1 text-xs text-slate-500\">\n Capture your screen and annotate with pencil, shapes, or arrows.\n </p>\n\n {/* Screenshot Thumbnails Grid */}\n {screenshots.length > 0 && (\n <div className=\"mt-3 grid grid-cols-3 gap-2.5\">\n {screenshots.map((s, idx) => (\n <div\n key={s.id}\n className=\"group relative aspect-video overflow-hidden rounded-lg border border-slate-200 bg-slate-100 shadow-sm\"\n >\n <img\n src={s.dataUrl}\n alt={`Screenshot ${idx + 1}`}\n className=\"h-full w-full object-cover transition duration-200 group-hover:scale-105\"\n />\n\n {/* Top badge */}\n <span className=\"absolute top-1 left-1 rounded bg-black/60 px-1 py-0.2 text-[10px] font-semibold text-white\">\n #{idx + 1}\n </span>\n\n {/* Hover Overlay with actions */}\n <div className=\"absolute inset-0 flex items-center justify-center gap-1.5 bg-black/50 opacity-0 backdrop-blur-[1px] transition-opacity duration-200 group-hover:opacity-100\">\n <button\n type=\"button\"\n onClick={() => setPreviewImage(s.dataUrl)}\n title=\"Preview screenshot\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600\"\n >\n <Eye className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onEditScreenshot(s)}\n title=\"Re-edit / annotate\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-white/90 text-slate-700 shadow transition hover:bg-white hover:text-blue-600\"\n >\n <Edit3 className=\"h-3.5 w-3.5\" />\n </button>\n <button\n type=\"button\"\n onClick={() => onDeleteScreenshot(s.id)}\n title=\"Delete screenshot\"\n className=\"flex h-7 w-7 items-center justify-center rounded-md bg-red-600 text-white shadow transition hover:bg-red-700\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n </button>\n </div>\n </div>\n ))}\n </div>\n )}\n\n {/* Add Screenshot Trigger Button */}\n <div className=\"mt-3\">\n {screenshots.length < 3 ? (\n <button\n type=\"button\"\n onClick={onTriggerScreenshot}\n className=\"flex w-full items-center justify-center gap-2 rounded-xl border-2 border-dashed border-slate-300 bg-slate-50/70 py-3 text-xs font-semibold text-slate-600 transition hover:border-blue-400 hover:bg-blue-50/50 hover:text-blue-600\"\n >\n <Camera className=\"h-4 w-4 text-slate-500\" />\n <span>\n {screenshots.length === 0\n ? 'Capture Screen & Annotate'\n : `Capture Another Screenshot (${3 - screenshots.length} left)`}\n </span>\n </button>\n ) : (\n <div className=\"rounded-lg bg-amber-50 p-2.5 text-center text-xs text-amber-700 border border-amber-200\">\n Maximum 3 screenshots attached. Delete one to take a new one.\n </div>\n )}\n </div>\n </div>\n\n {submitError && (\n <div className=\"rounded-xl border border-red-200 bg-red-50 px-3.5 py-2.5 text-xs text-red-700 flex items-start gap-2\">\n <AlertCircle className=\"h-4 w-4 shrink-0 mt-0.5\" />\n <span>{submitError}</span>\n </div>\n )}\n\n {/* Form Actions */}\n <div className=\"pt-4 border-t border-slate-100 flex items-center justify-end gap-3\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"rounded-xl border border-slate-200 bg-white px-4 py-2.5 text-sm font-semibold text-slate-600 transition hover:bg-slate-50\"\n >\n Cancel\n </button>\n\n <button\n type=\"submit\"\n disabled={isSubmitting}\n style={{ backgroundColor: primaryColor }}\n className=\"flex items-center gap-2 rounded-xl px-5 py-2.5 text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95 disabled:opacity-60\"\n >\n {isSubmitting ? (\n <>\n <Loader2 className=\"h-4 w-4 animate-spin\" />\n <span>Submitting...</span>\n </>\n ) : (\n <span>Submit Bug Report</span>\n )}\n </button>\n </div>\n </form>\n )}\n </div>\n </aside>\n\n {/* Lightbox Preview Modal for zoomed screenshot */}\n {previewImage && (\n <div\n data-bugdrop-widget=\"true\"\n onClick={() => setPreviewImage(null)}\n className=\"fixed inset-0 z-[100001] flex items-center justify-center bg-black/80 p-4 backdrop-blur-sm animate-fadeIn\"\n >\n <div\n className=\"relative max-h-[90vh] max-w-[90vw] overflow-hidden rounded-xl bg-slate-900 shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n >\n <img\n src={previewImage}\n alt=\"Screenshot Preview\"\n className=\"max-h-[85vh] w-auto rounded-xl object-contain\"\n />\n <button\n type=\"button\"\n onClick={() => setPreviewImage(null)}\n className=\"absolute top-3 right-3 flex h-8 w-8 items-center justify-center rounded-full bg-black/60 text-white shadow hover:bg-black/90\"\n >\n <X className=\"h-4 w-4\" />\n </button>\n </div>\n </div>\n )}\n </>\n );\n};","import React, { useState, useRef, useEffect, useLayoutEffect, useCallback } from 'react';\nimport type Konva from 'konva';\nimport {\n Pencil,\n Eraser,\n Square,\n Circle as CircleIcon,\n ArrowUpRight,\n MousePointer,\n Undo2,\n Redo2,\n Trash2,\n Check,\n X,\n Palette,\n} from 'lucide-react';\nimport type {\n EditorTool,\n AnnotationShape,\n LineAnnotation,\n RectAnnotation,\n CircleAnnotation,\n ArrowAnnotation,\n} from '../types';\n\ntype KonvaModule = typeof Konva;\ntype ConfigOf<K extends keyof KonvaModule> = KonvaModule[K] extends new (config?: infer C) => unknown\n ? NonNullable<C>\n : never;\n\nlet konvaPromise: Promise<KonvaModule> | null = null;\n\nfunction loadKonva(): Promise<KonvaModule> {\n if (!konvaPromise) {\n konvaPromise = import('konva')\n .then((mod) => {\n const m = mod as unknown as KonvaModule & { default?: KonvaModule };\n return m.default ?? m;\n })\n .catch((err: unknown) => {\n konvaPromise = null; // allow a retry on next mount\n throw err;\n });\n }\n return konvaPromise;\n}\n\n// useLayoutEffect warns during SSR on React 18; fall back to useEffect on the server.\nconst useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;\n\n\ntype Positioned = { x?: number; y?: number; rotation?: number };\n\n/** Konva attributes for a shape, used both to create nodes and to update the live draft. */\nfunction shapeAttrs(shape: AnnotationShape) {\n const p = shape as Positioned;\n const base = { stroke: shape.stroke, strokeWidth: shape.strokeWidth, rotation: p.rotation ?? 0 };\n\n switch (shape.type) {\n case 'line':\n return {\n ...base,\n x: p.x ?? 0,\n y: p.y ?? 0,\n points: shape.points,\n tension: 0.5,\n lineCap: 'round' as const,\n lineJoin: 'round' as const,\n globalCompositeOperation:\n shape.tool === 'eraser' ? ('destination-out' as const) : ('source-over' as const),\n };\n case 'rectangle':\n return { ...base, x: shape.x, y: shape.y, width: shape.width, height: shape.height };\n case 'circle':\n return { ...base, x: shape.x, y: shape.y, radius: shape.radius };\n case 'arrow':\n return {\n ...base,\n x: p.x ?? 0,\n y: p.y ?? 0,\n points: shape.points,\n fill: shape.fill,\n pointerLength: 14,\n pointerWidth: 14,\n };\n default:\n return base;\n }\n}\n\nfunction createNode(\n K: KonvaModule,\n shape: AnnotationShape,\n extra: Record<string, unknown>\n): Konva.Shape | null {\n const attrs = { ...shapeAttrs(shape), ...extra };\n switch (shape.type) {\n case 'line':\n return new K.Line(attrs as ConfigOf<'Line'>);\n case 'rectangle':\n return new K.Rect(attrs as ConfigOf<'Rect'>);\n case 'circle':\n return new K.Circle(attrs as ConfigOf<'Circle'>);\n case 'arrow':\n return new K.Arrow(attrs as ConfigOf<'Arrow'>);\n default:\n return null;\n }\n}\n\n\ninterface KonvaEditorProps {\n imageSrc: string;\n onSave: (editedDataUrl: string) => void;\n onCancel: () => void;\n primaryColor?: string;\n}\n\nconst PRESET_COLORS = [\n '#ef4444', // Red\n '#f97316', // Orange\n '#eab308', // Yellow\n '#10b981', // Green\n '#3b82f6', // Blue\n '#8b5cf6', // Purple\n '#ec4899', // Pink\n '#000000', // Black\n '#ffffff', // White\n];\n\nconst STROKE_WIDTHS = [\n { label: 'S', value: 3 },\n { label: 'M', value: 6 },\n { label: 'L', value: 10 },\n { label: 'XL', value: 16 },\n];\n\nconst TOOLS: { id: EditorTool; title: string; Icon: React.ComponentType<{ className?: string }> }[] = [\n { id: 'select', title: 'Select & Move / Resize', Icon: MousePointer },\n { id: 'pencil', title: 'Pencil / Draw', Icon: Pencil },\n { id: 'eraser', title: 'Eraser (click or drag to erase)', Icon: Eraser },\n { id: 'rectangle', title: 'Rectangle (Resizable)', Icon: Square },\n { id: 'circle', title: 'Circle (Resizable)', Icon: CircleIcon },\n { id: 'arrow', title: 'Arrow (Resizable)', Icon: ArrowUpRight },\n];\n\nconst TRANSFORMER_ANCHORS = [\n 'top-left',\n 'top-right',\n 'bottom-left',\n 'bottom-right',\n 'middle-left',\n 'middle-right',\n 'top-center',\n 'bottom-center',\n];\n\ninterface Handlers {\n pointerDown: (e: Konva.KonvaEventObject<PointerEvent>) => void;\n pointerMove: () => void;\n pointerUp: () => void;\n dragEnd: (node: Konva.Node, id: string) => void;\n transformEnd: (node: Konva.Node, id: string) => void;\n undo: () => void;\n redo: () => void;\n deleteSelected: () => void;\n hasSelection: () => boolean;\n clearSelection: () => void;\n}\n\ninterface DrawingState {\n start: { x: number; y: number };\n data: AnnotationShape;\n}\n\n\nexport const KonvaEditor: React.FC<KonvaEditorProps> = ({\n imageSrc,\n onSave,\n onCancel,\n primaryColor = '#2563eb',\n}) => {\n const containerRef = useRef<HTMLDivElement>(null);\n const stageHostRef = useRef<HTMLDivElement>(null);\n\n // Imperative Konva objects\n const stageRef = useRef<Konva.Stage | null>(null);\n const layerRef = useRef<Konva.Layer | null>(null);\n const transformerRef = useRef<Konva.Transformer | null>(null);\n const draftNodeRef = useRef<Konva.Shape | null>(null);\n const drawingRef = useRef<DrawingState | null>(null);\n\n // Always points at the latest handlers, so Konva listeners never use stale state\n const handlersRef = useRef<Handlers | null>(null);\n\n const [konvaLib, setKonvaLib] = useState<KonvaModule | null>(null);\n const [loadError, setLoadError] = useState<string | null>(null);\n const [image, setImage] = useState<HTMLImageElement | null>(null);\n const [scale, setScale] = useState<number>(1);\n const [stageDimensions, setStageDimensions] = useState({ width: 800, height: 600 });\n\n // Tool state\n const [tool, setTool] = useState<EditorTool>('pencil');\n const [color, setColor] = useState<string>('#ef4444');\n const [strokeWidth, setStrokeWidth] = useState<number>(6);\n const [selectedId, setSelectedId] = useState<string | null>(null);\n\n // Shapes & history\n const [shapes, setShapes] = useState<AnnotationShape[]>([]);\n const [history, setHistory] = useState<AnnotationShape[][]>([[]]);\n const [historyStep, setHistoryStep] = useState<number>(0);\n\n\n\n useEffect(() => {\n let cancelled = false;\n loadKonva()\n .then((K) => {\n if (!cancelled) setKonvaLib(() => K);\n })\n .catch(() => {\n if (!cancelled) setLoadError('The annotation editor could not load. Check your connection and try again.');\n });\n return () => {\n cancelled = true;\n };\n }, []);\n\n useEffect(() => {\n const img = new window.Image();\n img.crossOrigin = 'anonymous';\n img.onload = () => setImage(img);\n img.src = imageSrc;\n return () => {\n img.onload = null;\n };\n }, [imageSrc]);\n\n // Responsive sizing \n\n const updateDimensions = useCallback(() => {\n if (!containerRef.current || !image) return;\n const paddingX = 48;\n const paddingY = 120;\n const availWidth = Math.max(300, containerRef.current.clientWidth - paddingX);\n const availHeight = Math.max(300, containerRef.current.clientHeight - paddingY);\n\n const fitScale = Math.min(availWidth / image.naturalWidth, availHeight / image.naturalHeight, 1);\n\n setScale(fitScale);\n setStageDimensions({\n width: Math.round(image.naturalWidth * fitScale),\n height: Math.round(image.naturalHeight * fitScale),\n });\n }, [image]);\n\n useEffect(() => {\n updateDimensions();\n window.addEventListener('resize', updateDimensions);\n return () => window.removeEventListener('resize', updateDimensions);\n }, [updateDimensions]);\n\n // Effects below run in declaration order, so the stage always exists\n // before the size / shape / selection effects that depend on it.\n\n useEffect(() => {\n const host = stageHostRef.current;\n if (!konvaLib || !image || !host) return;\n const K = konvaLib;\n\n const stage = new K.Stage({ container: host, width: 1, height: 1 });\n\n const bgLayer = new K.Layer({ listening: false });\n bgLayer.add(\n new K.Image({\n name: 'bg-image',\n image,\n width: image.naturalWidth,\n height: image.naturalHeight,\n })\n );\n\n const layer = new K.Layer();\n const transformer = new K.Transformer({\n rotateEnabled: true,\n enabledAnchors: TRANSFORMER_ANCHORS,\n borderStroke: '#3b82f6',\n borderDash: [4, 4],\n anchorFill: '#ffffff',\n anchorStroke: '#3b82f6',\n anchorSize: 9,\n anchorCornerRadius: 2,\n boundBoxFunc: (oldBox, newBox) =>\n Math.abs(newBox.width) < 10 || Math.abs(newBox.height) < 10 ? oldBox : newBox,\n });\n layer.add(transformer);\n stage.add(bgLayer);\n stage.add(layer);\n\n stage.on('pointerdown', (e) => handlersRef.current?.pointerDown(e));\n stage.on('pointermove', () => handlersRef.current?.pointerMove());\n stage.on('pointerup', () => handlersRef.current?.pointerUp());\n\n // Finish a stroke even if the pointer is released outside the canvas\n const endStroke = () => handlersRef.current?.pointerUp();\n window.addEventListener('pointerup', endStroke);\n window.addEventListener('pointercancel', endStroke);\n\n stageRef.current = stage;\n layerRef.current = layer;\n transformerRef.current = transformer;\n\n return () => {\n window.removeEventListener('pointerup', endStroke);\n window.removeEventListener('pointercancel', endStroke);\n drawingRef.current = null;\n draftNodeRef.current = null;\n stage.destroy();\n stageRef.current = null;\n layerRef.current = null;\n transformerRef.current = null;\n };\n }, [konvaLib, image]);\n\n useEffect(() => {\n const stage = stageRef.current;\n if (!stage) return;\n stage.size(stageDimensions);\n stage.scale({ x: scale, y: scale });\n }, [konvaLib, image, scale, stageDimensions]);\n\n // Rebuild annotation nodes whenever the shape list or tool changes\n useEffect(() => {\n const K = konvaLib;\n const layer = layerRef.current;\n const transformer = transformerRef.current;\n if (!K || !layer || !transformer) return;\n\n transformer.nodes([]);\n layer.find('.annotation').forEach((node) => node.destroy());\n\n const isSelectable = tool === 'select';\n shapes.forEach((shape) => {\n const isEraserStroke = shape.type === 'line' && shape.tool === 'eraser';\n const node = createNode(K, shape, {\n id: shape.id,\n name: 'annotation',\n draggable: isSelectable && !isEraserStroke,\n hitStrokeWidth: Math.max(shape.strokeWidth, 12), // easier to click thin strokes\n });\n if (!node) return;\n node.on('dragend', () => handlersRef.current?.dragEnd(node, shape.id));\n node.on('transformend', () => handlersRef.current?.transformEnd(node, shape.id));\n layer.add(node);\n });\n\n transformer.moveToTop();\n }, [konvaLib, image, shapes, tool]);\n\n // Attach the transformer to the selected shape\n useEffect(() => {\n const layer = layerRef.current;\n const transformer = transformerRef.current;\n if (!layer || !transformer) return;\n\n const node = selectedId ? layer.findOne('#' + selectedId) : undefined;\n if (!node) {\n transformer.nodes([]);\n return;\n }\n // Free-hand lines can be moved but not resized or rotated\n const isLine = node.getClassName() === 'Line';\n transformer.resizeEnabled(!isLine);\n transformer.rotateEnabled(!isLine);\n transformer.nodes([node]);\n }, [konvaLib, image, shapes, tool, selectedId]);\n\n\n const commit = (nextShapes: AnnotationShape[]) => {\n setShapes(nextShapes);\n setHistory([...history.slice(0, historyStep + 1), nextShapes]);\n setHistoryStep(historyStep + 1);\n };\n\n const handleUndo = () => {\n if (historyStep <= 0) return;\n const newStep = historyStep - 1;\n setHistoryStep(newStep);\n setShapes(history[newStep]);\n setSelectedId(null);\n };\n\n const handleRedo = () => {\n if (historyStep >= history.length - 1) return;\n const newStep = historyStep + 1;\n setHistoryStep(newStep);\n setShapes(history[newStep]);\n setSelectedId(null);\n };\n\n const handleClearAll = () => {\n if (shapes.length === 0) return;\n commit([]);\n setSelectedId(null);\n };\n\n const handleDeleteSelected = () => {\n if (!selectedId) return;\n commit(shapes.filter((s) => s.id !== selectedId));\n setSelectedId(null);\n };\n\n // Drawing \n\n const getPointer = () => {\n const pointer = stageRef.current?.getPointerPosition();\n return pointer ? { x: pointer.x / scale, y: pointer.y / scale } : null;\n };\n\n const handlePointerDown = (e: Konva.KonvaEventObject<PointerEvent>) => {\n const stage = stageRef.current;\n const layer = layerRef.current;\n const K = konvaLib;\n if (!stage || !layer || !K || drawingRef.current) return;\n\n const point = getPointer();\n if (!point) return;\n const { x, y } = point;\n\n const target = e.target;\n const hitId = target !== stage ? target.id() : '';\n const hitShape = hitId ? shapes.find((s) => s.id === hitId) : undefined;\n\n if (tool === 'select') {\n if (hitShape) {\n if (!(hitShape.type === 'line' && hitShape.tool === 'eraser')) setSelectedId(hitShape.id);\n } else if (target === stage || target.hasName('bg-image')) {\n setSelectedId(null);\n }\n return;\n }\n\n // Eraser click on an existing annotation removes it\n if (tool === 'eraser' && hitShape) {\n commit(shapes.filter((s) => s.id !== hitShape.id));\n setSelectedId(null);\n return;\n }\n\n setSelectedId(null);\n\n const id = `shape_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n let data: AnnotationShape;\n\n if (tool === 'pencil' || tool === 'eraser') {\n data = {\n id,\n type: 'line',\n tool,\n points: [x, y],\n stroke: tool === 'eraser' ? '#ffffff' : color,\n strokeWidth: tool === 'eraser' ? strokeWidth * 2.5 : strokeWidth,\n } satisfies LineAnnotation;\n } else if (tool === 'rectangle') {\n data = { id, type: 'rectangle', x, y, width: 0, height: 0, stroke: color, strokeWidth } satisfies RectAnnotation;\n } else if (tool === 'circle') {\n data = { id, type: 'circle', x, y, radius: 0, stroke: color, strokeWidth } satisfies CircleAnnotation;\n } else {\n data = {\n id,\n type: 'arrow',\n points: [x, y, x, y],\n stroke: color,\n fill: color,\n strokeWidth,\n } satisfies ArrowAnnotation;\n }\n\n const draftNode = createNode(K, data, {\n listening: false,\n dash: data.type === 'line' ? undefined : [6, 4],\n });\n if (!draftNode) return;\n layer.add(draftNode);\n draftNodeRef.current = draftNode;\n drawingRef.current = { start: { x, y }, data };\n };\n\n const handlePointerMove = () => {\n const drawing = drawingRef.current;\n if (!drawing) return;\n const point = getPointer();\n if (!point) return;\n const { x, y } = point;\n const { start, data } = drawing;\n\n let next: AnnotationShape = data;\n if (data.type === 'line') {\n next = { ...data, points: [...data.points, x, y] };\n } else if (data.type === 'rectangle') {\n next = {\n ...data,\n x: Math.min(start.x, x),\n y: Math.min(start.y, y),\n width: Math.abs(x - start.x),\n height: Math.abs(y - start.y),\n };\n } else if (data.type === 'circle') {\n next = { ...data, radius: Math.hypot(x - start.x, y - start.y) };\n } else if (data.type === 'arrow') {\n next = { ...data, points: [start.x, start.y, x, y] };\n }\n\n drawing.data = next;\n // Update the canvas directly: no React re-render on every pointer move\n draftNodeRef.current?.setAttrs(shapeAttrs(next));\n };\n\n const handlePointerUp = () => {\n const drawing = drawingRef.current;\n if (!drawing) return;\n drawingRef.current = null;\n draftNodeRef.current?.destroy();\n draftNodeRef.current = null;\n\n const draft = drawing.data;\n let isValid = false;\n if (draft.type === 'line') {\n isValid = draft.points.length >= 2;\n } else if (draft.type === 'rectangle') {\n isValid = draft.width > 6 && draft.height > 6;\n } else if (draft.type === 'circle') {\n isValid = draft.radius > 5;\n } else if (draft.type === 'arrow') {\n const [x1, y1, x2, y2] = draft.points;\n isValid = Math.hypot(x2 - x1, y2 - y1) > 10;\n }\n if (!isValid) return;\n\n commit([...shapes, draft]);\n\n // Select new boxes, circles and arrows right away so they can be resized\n if (draft.type === 'rectangle' || draft.type === 'circle' || draft.type === 'arrow') {\n setSelectedId(draft.id);\n setTool('select');\n }\n };\n\n // Drag & transform \n\n const handleDragEnd = (node: Konva.Node, id: string) => {\n if (!shapes.some((s) => s.id === id)) return;\n commit(shapes.map((s) => (s.id === id ? { ...s, x: node.x(), y: node.y() } : s)));\n };\n\n const handleTransformEnd = (node: Konva.Node, id: string) => {\n const target = shapes.find((s) => s.id === id);\n if (!target) return;\n\n const scaleX = node.scaleX();\n const scaleY = node.scaleY();\n node.scaleX(1);\n node.scaleY(1);\n\n let updated: AnnotationShape | null = null;\n if (target.type === 'rectangle') {\n updated = {\n ...target,\n x: node.x(),\n y: node.y(),\n width: Math.max(10, node.width() * scaleX),\n height: Math.max(10, node.height() * scaleY),\n rotation: node.rotation(),\n };\n } else if (target.type === 'circle') {\n updated = {\n ...target,\n x: node.x(),\n y: node.y(),\n radius: Math.max(6, target.radius * scaleX),\n rotation: node.rotation(),\n };\n } else if (target.type === 'arrow') {\n const [x1, y1, x2, y2] = target.points;\n updated = {\n ...target,\n x: node.x(),\n y: node.y(),\n points: [x1, y1, x1 + (x2 - x1) * scaleX, y1 + (y2 - y1) * scaleY],\n rotation: node.rotation(),\n };\n }\n if (!updated) return;\n const result = updated;\n commit(shapes.map((s) => (s.id === id ? result : s)));\n };\n\n // Keep Konva listeners and the keyboard handler pointed at the latest closures\n useIsomorphicLayoutEffect(() => {\n handlersRef.current = {\n pointerDown: handlePointerDown,\n pointerMove: handlePointerMove,\n pointerUp: handlePointerUp,\n dragEnd: handleDragEnd,\n transformEnd: handleTransformEnd,\n undo: handleUndo,\n redo: handleRedo,\n deleteSelected: handleDeleteSelected,\n hasSelection: () => selectedId !== null,\n clearSelection: () => setSelectedId(null),\n };\n });\n\n // Keyboard shortcuts\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n const h = handlersRef.current;\n if (!h) return;\n if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;\n\n const mod = e.ctrlKey || e.metaKey;\n const key = e.key.toLowerCase();\n if (mod && key === 'z') {\n if (e.shiftKey) h.redo();\n else h.undo();\n e.preventDefault();\n } else if (mod && key === 'y') {\n h.redo();\n e.preventDefault();\n } else if ((e.key === 'Delete' || e.key === 'Backspace') && h.hasSelection()) {\n h.deleteSelected();\n e.preventDefault();\n } else if (e.key === 'Escape') {\n h.clearSelection();\n e.preventDefault();\n }\n };\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, []);\n\n // Export\n\n const handleExport = () => {\n const stage = stageRef.current;\n if (!stage) return;\n // Detach transformer handles synchronously so they never appear in the export\n transformerRef.current?.nodes([]);\n setSelectedId(null);\n const exportedDataUrl = stage.toDataURL({ pixelRatio: 1 / scale, mimeType: 'image/png' });\n onSave(exportedDataUrl);\n };\n\n // Render\n\n const selectTool = (next: EditorTool) => {\n setTool(next);\n if (next !== 'select') setSelectedId(null);\n };\n\n const isReady = Boolean(image && konvaLib);\n\n return (\n <div\n ref={containerRef}\n className=\"fixed inset-0 z-[100000] flex flex-col bg-slate-950/90 backdrop-blur-md select-none text-white overflow-hidden animate-fadeIn\"\n style={{ touchAction: 'none' }}\n >\n {/* Top Header Bar */}\n <div className=\"flex h-16 shrink-0 items-center justify-between border-b border-slate-800 bg-slate-900/90 px-4 sm:px-6\">\n <div className=\"flex items-center gap-3\">\n <div\n className=\"flex h-8 w-8 items-center justify-center rounded-lg text-white font-bold text-sm shadow\"\n style={{ backgroundColor: primaryColor }}\n >\n BD\n </div>\n <div>\n <h1 className=\"text-sm sm:text-base font-semibold leading-tight text-slate-100\">Screenshot Editor</h1>\n <p className=\"text-xs text-slate-400 hidden sm:block\">\n Highlight issues with pencil, arrows, circles, and boxes\n </p>\n </div>\n </div>\n\n {/* Top Actions: Undo, Redo, Clear, Cancel, Save */}\n <div className=\"flex items-center gap-2 sm:gap-3\">\n <button\n type=\"button\"\n onClick={handleUndo}\n disabled={historyStep <= 0}\n title=\"Undo (Ctrl+Z)\"\n className=\"flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Undo2 className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={handleRedo}\n disabled={historyStep >= history.length - 1}\n title=\"Redo (Ctrl+Y)\"\n className=\"flex h-9 w-9 items-center justify-center rounded-lg border border-slate-700 bg-slate-800 text-slate-200 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Redo2 className=\"h-4 w-4\" />\n </button>\n <button\n type=\"button\"\n onClick={handleClearAll}\n disabled={shapes.length === 0}\n title=\"Clear all annotations\"\n className=\"flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-2.5 text-xs font-medium text-slate-300 transition hover:bg-slate-700 hover:text-white disabled:opacity-40 disabled:pointer-events-none\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n <span className=\"hidden md:inline\">Clear All</span>\n </button>\n\n <div className=\"h-5 w-px bg-slate-700 mx-1\" />\n\n <button\n type=\"button\"\n onClick={onCancel}\n className=\"flex h-9 items-center gap-1.5 rounded-lg border border-slate-700 bg-slate-800 px-3 text-xs sm:text-sm font-medium text-slate-200 transition hover:bg-slate-700 hover:text-white\"\n >\n <X className=\"h-4 w-4\" />\n <span>Cancel</span>\n </button>\n\n <button\n type=\"button\"\n onClick={handleExport}\n disabled={!isReady}\n style={{ backgroundColor: primaryColor }}\n className=\"flex h-9 items-center gap-1.5 rounded-lg px-4 text-xs sm:text-sm font-semibold text-white shadow-md transition hover:brightness-110 active:scale-95 disabled:opacity-50 disabled:pointer-events-none\"\n >\n <Check className=\"h-4 w-4\" />\n <span>Add to Report</span>\n </button>\n </div>\n </div>\n\n {/* Floating Toolbar */}\n <div className=\"absolute top-20 left-1/2 -translate-x-1/2 z-20 flex flex-wrap items-center justify-center gap-2 rounded-2xl border border-slate-700/80 bg-slate-900/95 p-2 shadow-2xl backdrop-blur-md\">\n {/* Tool selector buttons */}\n <div className=\"flex items-center gap-1\">\n {TOOLS.map(({ id, title, Icon }) => (\n <button\n key={id}\n type=\"button\"\n onClick={() => selectTool(id)}\n title={title}\n aria-pressed={tool === id}\n className={`flex h-9 w-9 items-center justify-center rounded-xl transition ${\n tool === id ? 'bg-blue-600 text-white shadow-inner' : 'text-slate-300 hover:bg-slate-800 hover:text-white'\n }`}\n >\n <Icon className=\"h-4 w-4\" />\n </button>\n ))}\n </div>\n\n <div className=\"h-5 w-px bg-slate-700\" />\n\n {/* Color Palette Switcher */}\n <div className=\"flex items-center gap-1.5 px-1\">\n {PRESET_COLORS.map((c) => (\n <button\n key={c}\n type=\"button\"\n onClick={() => setColor(c)}\n title={c}\n aria-label={`Color ${c}`}\n style={{ backgroundColor: c }}\n className={`h-5 w-5 rounded-full border border-slate-700 transition-transform ${\n color === c ? 'scale-125 ring-2 ring-white ring-offset-1 ring-offset-slate-900' : 'hover:scale-110'\n }`}\n />\n ))}\n\n {/* Custom color input */}\n <label\n title=\"Custom Color\"\n className=\"relative flex h-6 w-6 cursor-pointer items-center justify-center rounded-full border border-slate-600 bg-slate-800 text-slate-300 hover:text-white transition\"\n >\n <Palette className=\"h-3.5 w-3.5\" />\n <input\n type=\"color\"\n value={color}\n onChange={(e) => setColor(e.target.value)}\n className=\"absolute inset-0 opacity-0 cursor-pointer\"\n />\n </label>\n </div>\n\n <div className=\"h-5 w-px bg-slate-700\" />\n\n {/* Stroke Width Selector */}\n <div className=\"flex items-center gap-1\">\n {STROKE_WIDTHS.map((sw) => (\n <button\n key={sw.value}\n type=\"button\"\n onClick={() => setStrokeWidth(sw.value)}\n className={`flex h-7 w-7 items-center justify-center rounded-lg text-xs font-semibold transition ${\n strokeWidth === sw.value\n ? 'bg-slate-700 text-white ring-1 ring-slate-400'\n : 'text-slate-400 hover:bg-slate-800 hover:text-white'\n }`}\n >\n {sw.label}\n </button>\n ))}\n </div>\n\n {/* Delete button if a shape is selected */}\n {selectedId && (\n <>\n <div className=\"h-5 w-px bg-slate-700\" />\n <button\n type=\"button\"\n onClick={handleDeleteSelected}\n title=\"Delete Selected Shape (Del / Backspace)\"\n className=\"flex h-8 items-center gap-1.5 rounded-xl bg-red-600/90 px-3 text-xs font-semibold text-white shadow hover:bg-red-600\"\n >\n <Trash2 className=\"h-3.5 w-3.5\" />\n <span>Delete</span>\n </button>\n </>\n )}\n </div>\n\n {/* Main Canvas Workspace */}\n <div className=\"relative flex flex-1 items-center justify-center p-4 overflow-hidden\">\n {loadError ? (\n <p className=\"text-sm text-red-300\">{loadError}</p>\n ) : !isReady ? (\n <div className=\"flex flex-col items-center gap-2 text-slate-400\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-blue-500 border-t-transparent\" />\n <p className=\"text-sm\">Loading screenshot...</p>\n </div>\n ) : (\n <div\n className=\"relative shadow-2xl rounded-md overflow-hidden border border-slate-700 bg-slate-900\"\n style={{\n width: stageDimensions.width,\n height: stageDimensions.height,\n cursor: tool === 'select' ? 'default' : tool === 'eraser' ? 'cell' : 'crosshair',\n }}\n >\n <div ref={stageHostRef} />\n </div>\n )}\n </div>\n\n {/* Bottom helper hints bar */}\n <div className=\"flex h-10 shrink-0 items-center justify-between border-t border-slate-800 bg-slate-900/80 px-4 text-xs text-slate-400\">\n <div className=\"flex items-center gap-4\">\n <span>\n Active tool: <strong className=\"text-slate-200 capitalize\">{tool}</strong>\n </span>\n <span className=\"hidden sm:inline\">\n Use <kbd className=\"rounded bg-slate-800 px-1 py-0.5 text-slate-300\">Ctrl+Z</kbd> to undo,{' '}\n <kbd className=\"rounded bg-slate-800 px-1 py-0.5 text-slate-300\">Del</kbd> to remove selected shape\n </span>\n </div>\n <div>\n {image && (\n <span>\n Original Resolution: {image.naturalWidth} x {image.naturalHeight}px\n </span>\n )}\n </div>\n </div>\n </div>\n );\n};","import React, { useState } from 'react';\nimport html2canvas from 'html2canvas';\nimport { Bug, X } from 'lucide-react';\nimport { Form } from './Form';\nimport { KonvaEditor } from './KonvaEditor';\nimport type {\n WidgetProps,\n WidgetPosition,\n WidgetButtonSize,\n ScreenshotItem,\n BugReportData,\n} from '../types';\n\nexport const Widget: React.FC<WidgetProps> = ({\n projectUrl,\n onSubmit,\n uiSettings = {},\n onSuccess,\n onError,\n isOpen: controlledIsOpen,\n onToggle,\n className = '',\n}) => {\n const {\n position = 'bottom-right',\n primaryColor = '#2563eb',\n buttonSize = 'md',\n buttonText,\n buttonIcon,\n zIndex = 99990,\n } = uiSettings;\n\n // Uncontrolled or controlled open state\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n\n const setOpen = (open: boolean) => {\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(open);\n }\n onToggle?.(open);\n };\n\n // Screenshots state (max 3)\n const [screenshots, setScreenshots] = useState<ScreenshotItem[]>([]);\n\n // Screenshot capture & Konva editor state\n const [isCapturing, setIsCapturing] = useState(false);\n const [isEditorOpen, setIsEditorOpen] = useState(false);\n const [editingScreenshot, setEditingScreenshot] = useState<{\n id?: string;\n dataUrl: string;\n isNew: boolean;\n } | null>(null);\n\n // Position CSS classes for the trigger button\n const getPositionClasses = (pos: WidgetPosition): string => {\n switch (pos) {\n case 'bottom-left':\n return 'bottom-6 left-6';\n case 'top-left':\n return 'top-6 left-6';\n case 'top-right':\n return 'top-6 right-6';\n case 'left':\n return 'top-1/2 -translate-y-1/2 left-4';\n case 'right':\n return 'top-1/2 -translate-y-1/2 right-4';\n case 'bottom-right':\n default:\n return 'bottom-6 right-6';\n }\n };\n\n // Size CSS classes for the trigger button\n const getSizeClasses = (size: WidgetButtonSize): { button: string; icon: string } => {\n switch (size) {\n case 'sm':\n return {\n button: 'h-10 px-3.5 gap-2 text-xs font-semibold rounded-full shadow-md',\n icon: 'h-4 w-4',\n };\n case 'lg':\n return {\n button: 'h-14 px-5 gap-3 text-base font-bold rounded-full shadow-xl',\n icon: 'h-6 w-6',\n };\n case 'md':\n default:\n return {\n button: 'h-12 px-4 gap-2.5 text-sm font-semibold rounded-full shadow-lg',\n icon: 'h-5 w-5',\n };\n }\n };\n\n const sizeClasses = getSizeClasses(buttonSize);\n\n // Take screenshot flow\n const handleTriggerScreenshot = async () => {\n // 1. Mark as capturing to immediately hide all widget UI (button and form)\n setIsCapturing(true);\n\n try {\n // 2. Wait for DOM to repaint without widget elements\n await new Promise((resolve) => setTimeout(resolve, 180));\n\n // 3. Capture screen using html2canvas\n const canvas = await html2canvas(document.documentElement, {\n useCORS: true,\n allowTaint: true,\n logging: false,\n scrollX: 0,\n scrollY: -window.scrollY,\n windowWidth: document.documentElement.offsetWidth,\n windowHeight: document.documentElement.offsetHeight,\n ignoreElements: (element) => {\n return (\n element.getAttribute('data-bugdrop-widget') === 'true' ||\n element.classList.contains('bugdrop-ignore')\n );\n },\n });\n\n const dataUrl = canvas.toDataURL('image/png');\n\n // 4. Open Konva editor with captured screenshot\n setEditingScreenshot({\n dataUrl,\n isNew: true,\n });\n setIsEditorOpen(true);\n } catch (err) {\n console.error('Error taking screenshot:', err);\n alert('Could not capture screenshot. Please try again.');\n } finally {\n setIsCapturing(false);\n }\n };\n\n // Re-edit an existing screenshot from the form\n const handleEditExistingScreenshot = (item: ScreenshotItem) => {\n setEditingScreenshot({\n id: item.id,\n dataUrl: item.dataUrl,\n isNew: false,\n });\n setIsEditorOpen(true);\n };\n\n // Delete a screenshot\n const handleDeleteScreenshot = (id: string) => {\n setScreenshots((prev) => prev.filter((s) => s.id !== id));\n };\n\n // Save edited screenshot from Konva editor\n const handleSaveEditor = (editedDataUrl: string) => {\n if (editingScreenshot?.isNew) {\n if (screenshots.length < 3) {\n const newItem: ScreenshotItem = {\n id: `ss_${Date.now()}_${Math.random().toString(36).substring(2, 6)}`,\n dataUrl: editedDataUrl,\n createdAt: Date.now(),\n };\n setScreenshots((prev) => [...prev, newItem]);\n }\n } else if (editingScreenshot?.id) {\n // Update existing\n setScreenshots((prev) =>\n prev.map((s) =>\n s.id === editingScreenshot.id ? { ...s, dataUrl: editedDataUrl } : s\n )\n );\n }\n\n setIsEditorOpen(false);\n setEditingScreenshot(null);\n setOpen(true); // Return to form\n };\n\n // Cancel Konva editor\n const handleCancelEditor = () => {\n setIsEditorOpen(false);\n setEditingScreenshot(null);\n setOpen(true); // Return to form\n };\n\n // Hand off the report to the consumer's onSubmit handler\n const handleSubmitReport = async (reportData: BugReportData) => {\n try {\n await onSubmit(reportData);\n onSuccess?.(reportData);\n } catch (err) {\n const error = err instanceof Error ? err : new Error('Failed to submit bug report');\n onError?.(error);\n throw error;\n }\n };\n\n // If capturing screenshot, completely hide widget elements from DOM/render\n if (isCapturing) {\n return null;\n }\n\n return (\n <>\n {/* Floating Widget Trigger Button */}\n {!isEditorOpen && (\n <div\n data-bugdrop-widget=\"true\"\n className={`fixed ${getPositionClasses(position)} ${className}`}\n style={{ zIndex }}\n >\n <button\n type=\"button\"\n onClick={() => setOpen(!isOpen)}\n style={{ backgroundColor: primaryColor }}\n className={`group flex items-center justify-center text-white transition-all duration-200 hover:brightness-110 active:scale-95 ${sizeClasses.button}`}\n aria-label={isOpen ? 'Close bug report form' : 'Open bug report form'}\n title={isOpen ? 'Close Bug Report' : 'Report a Bug'}\n >\n {isOpen ? (\n <X className={sizeClasses.icon} />\n ) : buttonIcon ? (\n buttonIcon\n ) : (\n <Bug className={sizeClasses.icon} />\n )}\n\n {buttonText && <span>{buttonText}</span>}\n\n {/* Notification Badge if screenshots are attached */}\n {screenshots.length > 0 && !isOpen && (\n <span className=\"flex h-5 w-5 items-center justify-center rounded-full bg-white text-[11px] font-bold text-slate-900 shadow\">\n {screenshots.length}\n </span>\n )}\n </button>\n </div>\n )}\n\n {/* Slide-in Form Drawer */}\n {!isEditorOpen && (\n <Form\n projectUrl={projectUrl}\n isOpen={isOpen}\n onClose={() => setOpen(false)}\n uiSettings={uiSettings}\n screenshots={screenshots}\n onTriggerScreenshot={handleTriggerScreenshot}\n onEditScreenshot={handleEditExistingScreenshot}\n onDeleteScreenshot={handleDeleteScreenshot}\n onSubmitReport={handleSubmitReport}\n />\n )}\n\n {/* Konva Annotation Editor Modal */}\n {isEditorOpen && editingScreenshot && (\n <KonvaEditor\n imageSrc={editingScreenshot.dataUrl}\n onSave={handleSaveEditor}\n onCancel={handleCancelEditor}\n primaryColor={primaryColor}\n />\n )}\n </>\n );\n};"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:""}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (width>=640px){.container{max-width:640px}}@media (width>=768px){.container{max-width:768px}}@media (width>=1024px){.container{max-width:1024px}}@media (width>=1280px){.container{max-width:1280px}}@media (width>=1536px){.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.pointer-events-auto{pointer-events:auto}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.bottom-6{bottom:1.5rem}.left-0{left:0}.left-1{left:.25rem}.left-1\/2{left:50%}.left-4{left:1rem}.left-6{left:1.5rem}.right-0{right:0}.right-3{right:.75rem}.right-4{right:1rem}.right-6{right:1.5rem}.top-0{top:0}.top-1{top:.25rem}.top-1\/2{top:50%}.top-20{top:5rem}.top-3{top:.75rem}.top-6{top:1.5rem}.z-20{z-index:20}.z-\[100000\]{z-index:100000}.z-\[100001\]{z-index:100001}.z-\[99990\]{z-index:99990}.z-\[99995\]{z-index:99995}.mx-1{margin-left:.25rem;margin-right:.25rem}.mb-4{margin-bottom:1rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-1\.5{margin-top:.375rem}.mt-2{margin-top:.5rem}.mt-3{margin-top:.75rem}.mt-8{margin-top:2rem}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.aspect-video{aspect-ratio:16/9}.h-10{height:2.5rem}.h-12{height:3rem}.h-14{height:3.5rem}.h-16{height:4rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-full{height:100%}.max-h-\[85vh\]{max-height:85vh}.max-h-\[90vh\]{max-height:90vh}.w-10{width:2.5rem}.w-16{width:4rem}.w-3\.5{width:.875rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-auto{width:auto}.w-full{width:100%}.w-px{width:1px}.max-w-\[90vw\]{max-width:90vw}.max-w-md{max-width:28rem}.max-w-xs{max-width:20rem}.flex-1{flex:1}.shrink-0{flex-shrink:0}.-translate-x-1\/2{--tw-translate-x:-50%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-x-full{--tw-translate-x:-100%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.-translate-y-1\/2{--tw-translate-y:-50%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-0{--tw-translate-x:0px;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.translate-x-full{--tw-translate-x:100%;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.scale-125{--tw-scale-x:1.25;--tw-scale-y:1.25;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:1s linear infinite spin}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;user-select:none}.resize{resize:both}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-end{justify-content:flex-end}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-2\.5{gap:.625rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-5>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.25rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:1rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-r{border-right-width:1px}.border-t{border-top-width:1px}.border-dashed{border-style:dashed}.border-amber-200{--tw-border-opacity:1;border-color:rgb(253 230 138/var(--tw-border-opacity,1))}.border-blue-500{--tw-border-opacity:1;border-color:rgb(59 130 246/var(--tw-border-opacity,1))}.border-red-200{--tw-border-opacity:1;border-color:rgb(254 202 202/var(--tw-border-opacity,1))}.border-red-300{--tw-border-opacity:1;border-color:rgb(252 165 165/var(--tw-border-opacity,1))}.border-slate-100{--tw-border-opacity:1;border-color:rgb(241 245 249/var(--tw-border-opacity,1))}.border-slate-200{--tw-border-opacity:1;border-color:rgb(226 232 240/var(--tw-border-opacity,1))}.border-slate-300{--tw-border-opacity:1;border-color:rgb(203 213 225/var(--tw-border-opacity,1))}.border-slate-600{--tw-border-opacity:1;border-color:rgb(71 85 105/var(--tw-border-opacity,1))}.border-slate-700{--tw-border-opacity:1;border-color:rgb(51 65 85/var(--tw-border-opacity,1))}.border-slate-700\/80{border-color:#334155cc}.border-slate-800{--tw-border-opacity:1;border-color:rgb(30 41 59/var(--tw-border-opacity,1))}.border-t-transparent{border-top-color:#0000}.bg-amber-50{--tw-bg-opacity:1;background-color:rgb(255 251 235/var(--tw-bg-opacity,1))}.bg-black\/50{background-color:#00000080}.bg-black\/60{background-color:#0009}.bg-black\/80{background-color:#000c}.bg-blue-600{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity,1))}.bg-red-50{--tw-bg-opacity:1;background-color:rgb(254 242 242/var(--tw-bg-opacity,1))}.bg-red-50\/50{background-color:#fef2f280}.bg-red-600{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.bg-red-600\/90{background-color:#dc2626e6}.bg-slate-100{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.bg-slate-50\/70{background-color:#f8fafcb3}.bg-slate-700{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.bg-slate-800{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.bg-slate-900{--tw-bg-opacity:1;background-color:rgb(15 23 42/var(--tw-bg-opacity,1))}.bg-slate-900\/40{background-color:#0f172a66}.bg-slate-900\/80{background-color:#0f172acc}.bg-slate-900\/90{background-color:#0f172ae6}.bg-slate-900\/95{background-color:#0f172af2}.bg-slate-950\/90{background-color:#020617e6}.bg-white{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.bg-white\/90{background-color:#ffffffe6}.object-contain{-o-object-fit:contain;object-fit:contain}.object-cover{-o-object-fit:cover;object-fit:cover}.p-2{padding:.5rem}.p-2\.5{padding:.625rem}.p-4{padding:1rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-3\.5{padding-left:.875rem;padding-right:.875rem}.px-4{padding-left:1rem;padding-right:1rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-10{padding-top:2.5rem;padding-bottom:2.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-5{padding-top:1.25rem;padding-bottom:1.25rem}.pt-4{padding-top:1rem}.text-center{text-align:center}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-base{font-size:1rem;line-height:1.5rem}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.font-normal{font-weight:400}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.lowercase{text-transform:lowercase}.capitalize{text-transform:capitalize}.leading-tight{line-height:1.25}.tracking-wide{letter-spacing:.025em}.tracking-wider{letter-spacing:.05em}.text-amber-700{--tw-text-opacity:1;color:rgb(180 83 9/var(--tw-text-opacity,1))}.text-red-300{--tw-text-opacity:1;color:rgb(252 165 165/var(--tw-text-opacity,1))}.text-red-500{--tw-text-opacity:1;color:rgb(239 68 68/var(--tw-text-opacity,1))}.text-red-600{--tw-text-opacity:1;color:rgb(220 38 38/var(--tw-text-opacity,1))}.text-red-700{--tw-text-opacity:1;color:rgb(185 28 28/var(--tw-text-opacity,1))}.text-red-900{--tw-text-opacity:1;color:rgb(127 29 29/var(--tw-text-opacity,1))}.text-slate-100{--tw-text-opacity:1;color:rgb(241 245 249/var(--tw-text-opacity,1))}.text-slate-200{--tw-text-opacity:1;color:rgb(226 232 240/var(--tw-text-opacity,1))}.text-slate-300{--tw-text-opacity:1;color:rgb(203 213 225/var(--tw-text-opacity,1))}.text-slate-400{--tw-text-opacity:1;color:rgb(148 163 184/var(--tw-text-opacity,1))}.text-slate-500{--tw-text-opacity:1;color:rgb(100 116 139/var(--tw-text-opacity,1))}.text-slate-600{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.text-slate-700{--tw-text-opacity:1;color:rgb(51 65 85/var(--tw-text-opacity,1))}.text-slate-800{--tw-text-opacity:1;color:rgb(30 41 59/var(--tw-text-opacity,1))}.text-slate-900{--tw-text-opacity:1;color:rgb(15 23 42/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.opacity-0{opacity:0}.opacity-100{opacity:1}.shadow{--tw-shadow:0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-2xl{--tw-shadow:0 25px 50px -12px #00000040;--tw-shadow-colored:0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-inner{--tw-shadow:inset 0 2px 4px 0 #0000000d;--tw-shadow-colored:inset 0 2px 4px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px #0000001a, 0 4px 6px -4px #0000001a;--tw-shadow-colored:0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-md{--tw-shadow:0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;--tw-shadow-colored:0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px #0000001a, 0 8px 10px -6px #0000001a;--tw-shadow-colored:0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000), var(--tw-ring-shadow,0 0 #0000), var(--tw-shadow)}.ring-1{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow,0 0 #0000)}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow,0 0 #0000)}.ring-slate-400{--tw-ring-opacity:1;--tw-ring-color:rgb(148 163 184/var(--tw-ring-opacity,1))}.ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity,1))}.ring-offset-1{--tw-ring-offset-width:1px}.ring-offset-slate-900{--tw-ring-offset-color:#0f172a}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-\[1px\]{--tw-backdrop-blur:blur(1px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-md{--tw-backdrop-blur:blur(12px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.backdrop-blur-sm{--tw-backdrop-blur:blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,-webkit-backdrop-filter,backdrop-filter;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-all{transition-property:all;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-opacity{transition-property:opacity;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-transform{transition-property:transform;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-200{transition-duration:.2s}.duration-300{transition-duration:.3s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}.hover\:scale-110:hover{--tw-scale-x:1.1;--tw-scale-y:1.1;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.hover\:border-blue-400:hover{--tw-border-opacity:1;border-color:rgb(96 165 250/var(--tw-border-opacity,1))}.hover\:bg-black\/90:hover{background-color:#000000e6}.hover\:bg-blue-50\/50:hover{background-color:#eff6ff80}.hover\:bg-red-600:hover{--tw-bg-opacity:1;background-color:rgb(220 38 38/var(--tw-bg-opacity,1))}.hover\:bg-red-700:hover{--tw-bg-opacity:1;background-color:rgb(185 28 28/var(--tw-bg-opacity,1))}.hover\:bg-slate-100:hover{--tw-bg-opacity:1;background-color:rgb(241 245 249/var(--tw-bg-opacity,1))}.hover\:bg-slate-50:hover{--tw-bg-opacity:1;background-color:rgb(248 250 252/var(--tw-bg-opacity,1))}.hover\:bg-slate-700:hover{--tw-bg-opacity:1;background-color:rgb(51 65 85/var(--tw-bg-opacity,1))}.hover\:bg-slate-800:hover{--tw-bg-opacity:1;background-color:rgb(30 41 59/var(--tw-bg-opacity,1))}.hover\:bg-white:hover{--tw-bg-opacity:1;background-color:rgb(255 255 255/var(--tw-bg-opacity,1))}.hover\:text-blue-600:hover{--tw-text-opacity:1;color:rgb(37 99 235/var(--tw-text-opacity,1))}.hover\:text-slate-600:hover{--tw-text-opacity:1;color:rgb(71 85 105/var(--tw-text-opacity,1))}.hover\:text-white:hover{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.hover\:brightness-110:hover{--tw-brightness:brightness(1.1);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:border-transparent:focus{border-color:#0000}.focus\:outline-none:focus{outline-offset:2px;outline:2px solid #0000}.focus\:ring-2:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow,0 0 #0000)}.focus\:ring-blue-500:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(59 130 246/var(--tw-ring-opacity,1))}.focus\:ring-red-400:focus{--tw-ring-opacity:1;--tw-ring-color:rgb(248 113 113/var(--tw-ring-opacity,1))}.active\:scale-95:active{--tw-scale-x:.95;--tw-scale-y:.95;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-40:disabled{opacity:.4}.disabled\:opacity-50:disabled{opacity:.5}.disabled\:opacity-60:disabled{opacity:.6}.group:hover .group-hover\:scale-105{--tw-scale-x:1.05;--tw-scale-y:1.05;transform:translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.group:hover .group-hover\:opacity-100{opacity:1}@media (width>=640px){.sm\:block{display:block}.sm\:inline{display:inline}.sm\:max-w-lg{max-width:32rem}.sm\:flex-row{flex-direction:row}.sm\:gap-3{gap:.75rem}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:text-base{font-size:1rem;line-height:1.5rem}.sm\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (width>=768px){.md\:inline{display:inline}}
|
|
2
|
+
/*$vite$:1*/
|