@bugdump/sdk 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +154 -0
- package/dist/index.cjs +517 -0
- package/dist/index.d.cts +270 -0
- package/dist/index.d.ts +270 -0
- package/dist/index.global.js +576 -0
- package/dist/index.js +517 -0
- package/package.json +58 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
import {record}from'@rrweb/record';import {toBlob}from'html-to-image';var K="https://api.bugdump.io";function H(n){return {projectKey:n.projectKey,endpoint:(n.endpoint||K).replace(/\/+$/,"")}}function k(){return {initialized:false,config:null,user:null,customContext:{},widgetOpen:false}}var m=class{endpoint;apiKey;constructor(t,e){this.endpoint=t,this.apiKey=e;}async submitReport(t){return this.post("/api/widget/v1/reports",t)}async requestUpload(t){return this.post("/api/widget/v1/reports/upload",t)}async uploadFileToS3(t,e,o){let r=new FormData;for(let[a,l]of Object.entries(e))r.append(a,l);r.append("file",o);let i=await fetch(t,{method:"POST",body:r});if(!i.ok)throw new h("S3_UPLOAD_FAILED",i.status)}async post(t,e){let o=`${this.endpoint}${t}`,r=await fetch(o,{method:"POST",headers:{"Content-Type":"application/json","Bugdump-API-Key":this.apiKey},body:JSON.stringify(e)});if(!r.ok){let i;try{i=await r.json();}catch{}throw new h(i?.error||`HTTP_${r.status}`,r.status,i?.details)}return await r.json()}},h=class extends Error{code;statusCode;details;constructor(t,e,o){super(`Bugdump API error: ${t} (${e})`),this.name="BugdumpApiError",this.code=t,this.statusCode=e,this.details=o;}};var B=["log","warn","error","info","debug"],f=class{buffer=[];originals=new Map;active=false;start(){if(!this.active){this.active=true;for(let t of B)this.originals.set(t,console[t].bind(console)),console[t]=(...e)=>{this.push({level:t,args:this.serializeArgs(e),timestamp:Date.now()}),this.originals.get(t)(...e);};}}stop(){if(this.active){this.active=false;for(let t of B){let e=this.originals.get(t);e&&(console[t]=e);}this.originals.clear();}}flush(){let t=[...this.buffer];return this.buffer=[],t}push(t){this.buffer.push(t),this.buffer.length>50&&this.buffer.shift();}serializeArgs(t){return t.map(e=>{if(e==null||typeof e=="string"||typeof e=="number"||typeof e=="boolean")return e;try{return JSON.parse(JSON.stringify(e,this.circularReplacer()))}catch{return String(e)}})}circularReplacer(){let t=new WeakSet;return (e,o)=>{if(typeof o=="object"&&o!==null){if(t.has(o))return "[Circular]";t.add(o);}return o}}};var g=class{buffer=[];originalFetch=null;originalXhrOpen=null;originalXhrSend=null;active=false;start(){this.active||(this.active=true,this.patchFetch(),this.patchXhr());}stop(){this.active&&(this.active=false,this.restoreFetch(),this.restoreXhr());}flush(){let t=[...this.buffer];return this.buffer=[],t}push(t){this.buffer.push(t),this.buffer.length>30&&this.buffer.shift();}patchFetch(){this.originalFetch=window.fetch;let t=this;window.fetch=async function(e,o){let r=o?.method?.toUpperCase()||"GET",i=typeof e=="string"?e:e instanceof URL?e.href:e.url,a=Date.now(),l=t.extractHeaders(o?.headers);try{let d=await t.originalFetch.call(window,e,o);return t.push({method:r,url:i,status:d.status,statusText:d.statusText,requestHeaders:l,responseHeaders:t.extractHeaders(d.headers),duration:Date.now()-a,startedAt:a,error:null}),d}catch(d){throw t.push({method:r,url:i,status:null,statusText:null,requestHeaders:l,responseHeaders:{},duration:Date.now()-a,startedAt:a,error:d instanceof Error?d.message:String(d)}),d}};}restoreFetch(){this.originalFetch&&(window.fetch=this.originalFetch,this.originalFetch=null);}patchXhr(){this.originalXhrOpen=XMLHttpRequest.prototype.open,this.originalXhrSend=XMLHttpRequest.prototype.send;let t=this;XMLHttpRequest.prototype.open=function(e,o){return this.__bd_method=e.toUpperCase(),this.__bd_url=typeof o=="string"?o:o.href,t.originalXhrOpen.apply(this,arguments)},XMLHttpRequest.prototype.send=function(e){let o=Date.now(),r=this.__bd_method||"GET",i=this.__bd_url||"",a=()=>{t.push({method:r,url:i,status:this.status||null,statusText:this.statusText||null,requestHeaders:{},responseHeaders:t.parseXhrResponseHeaders(this.getAllResponseHeaders()),duration:Date.now()-o,startedAt:o,error:this.status===0?"Network error":null}),this.removeEventListener("loadend",a);};return this.addEventListener("loadend",a),t.originalXhrSend.call(this,e)};}restoreXhr(){this.originalXhrOpen&&(XMLHttpRequest.prototype.open=this.originalXhrOpen,this.originalXhrOpen=null),this.originalXhrSend&&(XMLHttpRequest.prototype.send=this.originalXhrSend,this.originalXhrSend=null);}extractHeaders(t){let e={};if(!t)return e;if(t instanceof Headers)t.forEach((o,r)=>{e[r]=o;});else if(Array.isArray(t))for(let[o,r]of t)e[o]=r;else for(let[o,r]of Object.entries(t))e[o]=r;return e}parseXhrResponseHeaders(t){let e={};if(!t)return e;for(let o of t.trim().split(/[\r\n]+/)){let r=o.indexOf(":");if(r===-1)continue;let i=o.slice(0,r).trim().toLowerCase(),a=o.slice(r+1).trim();e[i]=a;}return e}};var Z=3e4,b=class{buffer=[];stopFn=null;active=false;start(){if(this.active)return;this.active=true;let t=record({emit:e=>{this.buffer.push(e),this.pruneOldEvents();},sampling:{mousemove:true,mouseInteraction:true,scroll:150,input:"last"},blockClass:"bugdump-block",maskAllInputs:true});t&&(this.stopFn=t);}stop(){this.active&&(this.active=false,this.stopFn&&(this.stopFn(),this.stopFn=null));}flush(){this.pruneOldEvents();let t=[...this.buffer];return this.buffer=[],t}pruneOldEvents(){let t=Date.now()-Z,e=this.buffer.findIndex(o=>o.timestamp>=t);e===-1?this.buffer=[]:e>0&&(this.buffer=this.buffer.slice(e));}};function _(){return {timing:Q(),memory:tt(),resources:et()}}function Q(){let n=performance.getEntriesByType("navigation");if(n.length===0)return null;let t=n[0],e=performance.getEntriesByType("paint"),o=e.find(i=>i.name==="first-paint"),r=e.find(i=>i.name==="first-contentful-paint");return {domContentLoaded:t.domContentLoadedEventEnd>0?Math.round(t.domContentLoadedEventEnd):null,loadComplete:t.loadEventEnd>0?Math.round(t.loadEventEnd):null,firstPaint:o?Math.round(o.startTime):null,firstContentfulPaint:r?Math.round(r.startTime):null,ttfb:t.responseStart>0?Math.round(t.responseStart):null}}function tt(){let n=performance;return n.memory?{usedJSHeapSize:n.memory.usedJSHeapSize,totalJSHeapSize:n.memory.totalJSHeapSize,jsHeapSizeLimit:n.memory.jsHeapSizeLimit}:null}function et(){return performance.getEntriesByType("resource").slice(-20).map(t=>({name:t.name,type:t.initiatorType,duration:Math.round(t.duration),size:t.transferSize||0}))}function D(){return {userAgent:navigator.userAgent,language:navigator.language,platform:navigator.platform,viewport:{width:window.innerWidth,height:window.innerHeight},screenResolution:{width:screen.width,height:screen.height},devicePixelRatio:window.devicePixelRatio||1,url:window.location.href,referrer:document.referrer,timestamp:Date.now()}}var s={primary:"#6366f1",primaryHover:"#4f46e5",primaryText:"#ffffff",bg:"#ffffff",bgSecondary:"#f9fafb",bgHover:"#f3f4f6",border:"#e5e7eb",borderFocus:"#6366f1",text:"#111827",textSecondary:"#6b7280",textMuted:"#9ca3af",danger:"#ef4444",dangerHover:"#dc2626",overlay:"rgba(0, 0, 0, 0.5)",shadow:"rgba(0, 0, 0, 0.15)",shadowLight:"rgba(0, 0, 0, 0.08)"};function O(){return `
|
|
2
|
+
* {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
margin: 0;
|
|
5
|
+
padding: 0;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.bd-trigger {
|
|
9
|
+
position: fixed;
|
|
10
|
+
bottom: 20px;
|
|
11
|
+
right: 20px;
|
|
12
|
+
width: 56px;
|
|
13
|
+
height: 56px;
|
|
14
|
+
border-radius: 50%;
|
|
15
|
+
background: ${s.primary};
|
|
16
|
+
color: ${s.primaryText};
|
|
17
|
+
border: none;
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
display: flex;
|
|
20
|
+
align-items: center;
|
|
21
|
+
justify-content: center;
|
|
22
|
+
box-shadow: 0 4px 12px ${s.shadow};
|
|
23
|
+
transition: background-color 0.2s, transform 0.2s, box-shadow 0.2s;
|
|
24
|
+
z-index: 2147483647;
|
|
25
|
+
outline: none;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.bd-trigger:hover {
|
|
29
|
+
background: ${s.primaryHover};
|
|
30
|
+
transform: scale(1.05);
|
|
31
|
+
box-shadow: 0 6px 16px ${s.shadow};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.bd-trigger:active {
|
|
35
|
+
transform: scale(0.97);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.bd-trigger svg {
|
|
39
|
+
width: 24px;
|
|
40
|
+
height: 24px;
|
|
41
|
+
fill: currentColor;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.bd-trigger--open svg {
|
|
45
|
+
transition: transform 0.2s;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.bd-panel {
|
|
49
|
+
position: fixed;
|
|
50
|
+
bottom: 88px;
|
|
51
|
+
right: 20px;
|
|
52
|
+
width: 380px;
|
|
53
|
+
max-height: calc(100vh - 120px);
|
|
54
|
+
background: ${s.bg};
|
|
55
|
+
border-radius: 16px;
|
|
56
|
+
box-shadow: 0 8px 32px ${s.shadow}, 0 2px 8px ${s.shadowLight};
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
overflow: hidden;
|
|
60
|
+
transform: translateY(10px);
|
|
61
|
+
opacity: 0;
|
|
62
|
+
transition: transform 0.25s ease-out, opacity 0.25s ease-out;
|
|
63
|
+
pointer-events: none;
|
|
64
|
+
z-index: 2147483646;
|
|
65
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
|
|
66
|
+
font-size: 14px;
|
|
67
|
+
line-height: 1.5;
|
|
68
|
+
color: ${s.text};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
.bd-panel--visible {
|
|
72
|
+
transform: translateY(0);
|
|
73
|
+
opacity: 1;
|
|
74
|
+
pointer-events: auto;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.bd-panel__header {
|
|
78
|
+
display: flex;
|
|
79
|
+
align-items: center;
|
|
80
|
+
justify-content: space-between;
|
|
81
|
+
padding: 16px 20px;
|
|
82
|
+
border-bottom: 1px solid ${s.border};
|
|
83
|
+
background: ${s.bgSecondary};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.bd-panel__title {
|
|
87
|
+
font-size: 16px;
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
color: ${s.text};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.bd-panel__close {
|
|
93
|
+
background: none;
|
|
94
|
+
border: none;
|
|
95
|
+
cursor: pointer;
|
|
96
|
+
color: ${s.textSecondary};
|
|
97
|
+
padding: 4px;
|
|
98
|
+
border-radius: 6px;
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
justify-content: center;
|
|
102
|
+
transition: color 0.15s, background-color 0.15s;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.bd-panel__close:hover {
|
|
106
|
+
color: ${s.text};
|
|
107
|
+
background: ${s.bgHover};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.bd-panel__close svg {
|
|
111
|
+
width: 18px;
|
|
112
|
+
height: 18px;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.bd-panel__body {
|
|
116
|
+
flex: 1;
|
|
117
|
+
overflow-y: auto;
|
|
118
|
+
padding: 16px 20px;
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-direction: column;
|
|
121
|
+
gap: 12px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.bd-textarea {
|
|
125
|
+
width: 100%;
|
|
126
|
+
min-height: 100px;
|
|
127
|
+
padding: 10px 12px;
|
|
128
|
+
border: 1px solid ${s.border};
|
|
129
|
+
border-radius: 8px;
|
|
130
|
+
resize: vertical;
|
|
131
|
+
font-family: inherit;
|
|
132
|
+
font-size: 14px;
|
|
133
|
+
line-height: 1.5;
|
|
134
|
+
color: ${s.text};
|
|
135
|
+
background: ${s.bg};
|
|
136
|
+
outline: none;
|
|
137
|
+
transition: border-color 0.15s;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.bd-textarea::placeholder {
|
|
141
|
+
color: ${s.textMuted};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.bd-textarea:focus {
|
|
145
|
+
border-color: ${s.borderFocus};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
.bd-action-bar {
|
|
149
|
+
display: flex;
|
|
150
|
+
gap: 4px;
|
|
151
|
+
flex-wrap: wrap;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
.bd-action-btn {
|
|
155
|
+
display: inline-flex;
|
|
156
|
+
align-items: center;
|
|
157
|
+
gap: 6px;
|
|
158
|
+
padding: 6px 10px;
|
|
159
|
+
border: 1px solid ${s.border};
|
|
160
|
+
border-radius: 6px;
|
|
161
|
+
background: ${s.bg};
|
|
162
|
+
color: ${s.textSecondary};
|
|
163
|
+
font-size: 13px;
|
|
164
|
+
font-family: inherit;
|
|
165
|
+
cursor: pointer;
|
|
166
|
+
transition: color 0.15s, border-color 0.15s, background-color 0.15s;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.bd-action-btn:hover {
|
|
170
|
+
color: ${s.text};
|
|
171
|
+
border-color: ${s.textSecondary};
|
|
172
|
+
background: ${s.bgSecondary};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.bd-action-btn:disabled {
|
|
176
|
+
opacity: 0.5;
|
|
177
|
+
cursor: not-allowed;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.bd-action-btn svg {
|
|
181
|
+
width: 16px;
|
|
182
|
+
height: 16px;
|
|
183
|
+
flex-shrink: 0;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.bd-attachments {
|
|
187
|
+
display: flex;
|
|
188
|
+
gap: 8px;
|
|
189
|
+
flex-wrap: wrap;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
.bd-attachment {
|
|
193
|
+
position: relative;
|
|
194
|
+
width: 64px;
|
|
195
|
+
height: 64px;
|
|
196
|
+
border-radius: 8px;
|
|
197
|
+
overflow: hidden;
|
|
198
|
+
border: 1px solid ${s.border};
|
|
199
|
+
background: ${s.bgSecondary};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.bd-attachment img,
|
|
203
|
+
.bd-attachment video {
|
|
204
|
+
width: 100%;
|
|
205
|
+
height: 100%;
|
|
206
|
+
object-fit: cover;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.bd-attachment__icon {
|
|
210
|
+
width: 100%;
|
|
211
|
+
height: 100%;
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
justify-content: center;
|
|
215
|
+
color: ${s.textSecondary};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.bd-attachment__icon svg {
|
|
219
|
+
width: 24px;
|
|
220
|
+
height: 24px;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.bd-attachment__remove {
|
|
224
|
+
position: absolute;
|
|
225
|
+
top: -4px;
|
|
226
|
+
right: -4px;
|
|
227
|
+
width: 20px;
|
|
228
|
+
height: 20px;
|
|
229
|
+
border-radius: 50%;
|
|
230
|
+
background: ${s.danger};
|
|
231
|
+
color: ${s.primaryText};
|
|
232
|
+
border: 2px solid ${s.bg};
|
|
233
|
+
cursor: pointer;
|
|
234
|
+
display: flex;
|
|
235
|
+
align-items: center;
|
|
236
|
+
justify-content: center;
|
|
237
|
+
font-size: 10px;
|
|
238
|
+
line-height: 1;
|
|
239
|
+
padding: 0;
|
|
240
|
+
transition: background-color 0.15s;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.bd-attachment__remove:hover {
|
|
244
|
+
background: ${s.dangerHover};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.bd-attachment__remove svg {
|
|
248
|
+
width: 10px;
|
|
249
|
+
height: 10px;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
.bd-reporter-toggle {
|
|
253
|
+
display: flex;
|
|
254
|
+
align-items: center;
|
|
255
|
+
gap: 6px;
|
|
256
|
+
background: none;
|
|
257
|
+
border: none;
|
|
258
|
+
cursor: pointer;
|
|
259
|
+
font-size: 13px;
|
|
260
|
+
font-family: inherit;
|
|
261
|
+
color: ${s.textSecondary};
|
|
262
|
+
padding: 0;
|
|
263
|
+
transition: color 0.15s;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
.bd-reporter-toggle:hover {
|
|
267
|
+
color: ${s.text};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.bd-reporter-toggle svg {
|
|
271
|
+
width: 14px;
|
|
272
|
+
height: 14px;
|
|
273
|
+
transition: transform 0.2s;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
.bd-reporter-toggle--open svg {
|
|
277
|
+
transform: rotate(90deg);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
.bd-reporter-fields {
|
|
281
|
+
display: none;
|
|
282
|
+
flex-direction: column;
|
|
283
|
+
gap: 8px;
|
|
284
|
+
padding-top: 4px;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
.bd-reporter-fields--visible {
|
|
288
|
+
display: flex;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
.bd-input {
|
|
292
|
+
width: 100%;
|
|
293
|
+
padding: 8px 12px;
|
|
294
|
+
border: 1px solid ${s.border};
|
|
295
|
+
border-radius: 8px;
|
|
296
|
+
font-family: inherit;
|
|
297
|
+
font-size: 14px;
|
|
298
|
+
color: ${s.text};
|
|
299
|
+
background: ${s.bg};
|
|
300
|
+
outline: none;
|
|
301
|
+
transition: border-color 0.15s;
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
.bd-input::placeholder {
|
|
305
|
+
color: ${s.textMuted};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.bd-input:focus {
|
|
309
|
+
border-color: ${s.borderFocus};
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
.bd-panel__footer {
|
|
313
|
+
padding: 12px 20px;
|
|
314
|
+
border-top: 1px solid ${s.border};
|
|
315
|
+
display: flex;
|
|
316
|
+
justify-content: flex-end;
|
|
317
|
+
gap: 8px;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
.bd-send-btn {
|
|
321
|
+
display: inline-flex;
|
|
322
|
+
align-items: center;
|
|
323
|
+
gap: 6px;
|
|
324
|
+
padding: 8px 20px;
|
|
325
|
+
background: ${s.primary};
|
|
326
|
+
color: ${s.primaryText};
|
|
327
|
+
border: none;
|
|
328
|
+
border-radius: 8px;
|
|
329
|
+
font-size: 14px;
|
|
330
|
+
font-weight: 500;
|
|
331
|
+
font-family: inherit;
|
|
332
|
+
cursor: pointer;
|
|
333
|
+
transition: background-color 0.15s, opacity 0.15s;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.bd-send-btn:hover {
|
|
337
|
+
background: ${s.primaryHover};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
.bd-send-btn:disabled {
|
|
341
|
+
opacity: 0.5;
|
|
342
|
+
cursor: not-allowed;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
.bd-send-btn svg {
|
|
346
|
+
width: 16px;
|
|
347
|
+
height: 16px;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.bd-success {
|
|
351
|
+
display: flex;
|
|
352
|
+
flex-direction: column;
|
|
353
|
+
align-items: center;
|
|
354
|
+
justify-content: center;
|
|
355
|
+
gap: 12px;
|
|
356
|
+
padding: 40px 20px;
|
|
357
|
+
text-align: center;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.bd-success svg {
|
|
361
|
+
width: 48px;
|
|
362
|
+
height: 48px;
|
|
363
|
+
color: #22c55e;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
.bd-success__title {
|
|
367
|
+
font-size: 16px;
|
|
368
|
+
font-weight: 600;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
.bd-success__subtitle {
|
|
372
|
+
font-size: 14px;
|
|
373
|
+
color: ${s.textSecondary};
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.bd-annotation-overlay {
|
|
377
|
+
position: fixed;
|
|
378
|
+
top: 0;
|
|
379
|
+
left: 0;
|
|
380
|
+
width: 100%;
|
|
381
|
+
height: 100%;
|
|
382
|
+
z-index: 2147483647;
|
|
383
|
+
background: ${s.overlay};
|
|
384
|
+
display: flex;
|
|
385
|
+
flex-direction: column;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
.bd-annotation-toolbar {
|
|
389
|
+
display: flex;
|
|
390
|
+
align-items: center;
|
|
391
|
+
gap: 4px;
|
|
392
|
+
padding: 8px 12px;
|
|
393
|
+
background: rgba(0, 0, 0, 0.85);
|
|
394
|
+
color: ${s.primaryText};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
.bd-annotation-toolbar button {
|
|
398
|
+
padding: 6px 10px;
|
|
399
|
+
background: transparent;
|
|
400
|
+
color: ${s.primaryText};
|
|
401
|
+
border: 1px solid transparent;
|
|
402
|
+
border-radius: 6px;
|
|
403
|
+
font-size: 13px;
|
|
404
|
+
font-family: inherit;
|
|
405
|
+
cursor: pointer;
|
|
406
|
+
transition: background-color 0.15s, border-color 0.15s;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
.bd-annotation-toolbar button:hover {
|
|
410
|
+
background: rgba(255, 255, 255, 0.1);
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
.bd-annotation-toolbar button.active {
|
|
414
|
+
background: rgba(255, 255, 255, 0.2);
|
|
415
|
+
border-color: rgba(255, 255, 255, 0.3);
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
.bd-annotation-toolbar__spacer {
|
|
419
|
+
flex: 1;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.bd-annotation-toolbar__confirm {
|
|
423
|
+
background: #22c55e !important;
|
|
424
|
+
color: ${s.primaryText} !important;
|
|
425
|
+
font-weight: 500;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
.bd-annotation-toolbar__confirm:hover {
|
|
429
|
+
background: #16a34a !important;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
.bd-annotation-toolbar__cancel {
|
|
433
|
+
color: ${s.textMuted} !important;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.bd-annotation-canvas-wrap {
|
|
437
|
+
flex: 1;
|
|
438
|
+
display: flex;
|
|
439
|
+
align-items: center;
|
|
440
|
+
justify-content: center;
|
|
441
|
+
overflow: hidden;
|
|
442
|
+
position: relative;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
.bd-spinner {
|
|
446
|
+
width: 20px;
|
|
447
|
+
height: 20px;
|
|
448
|
+
border: 2px solid ${s.primaryText};
|
|
449
|
+
border-top-color: transparent;
|
|
450
|
+
border-radius: 50%;
|
|
451
|
+
animation: bd-spin 0.6s linear infinite;
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
@keyframes bd-spin {
|
|
455
|
+
to { transform: rotate(360deg); }
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
.bd-file-input {
|
|
459
|
+
display: none;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
@media (max-width: 440px) {
|
|
463
|
+
.bd-panel {
|
|
464
|
+
right: 0;
|
|
465
|
+
left: 0;
|
|
466
|
+
bottom: 76px;
|
|
467
|
+
width: 100%;
|
|
468
|
+
max-height: calc(100vh - 100px);
|
|
469
|
+
border-radius: 16px 16px 0 0;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
`}function S(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M8 2l1.88 1.88"/><path d="M14.12 3.88 16 2"/><path d="M9 7.13v-1a3.003 3.003 0 1 1 6 0v1"/><path d="M12 20c-3.3 0-6-2.7-6-6v-3a4 4 0 0 1 4-4h4a4 4 0 0 1 4 4v3c0 3.3-2.7 6-6 6"/><path d="M12 20v-9"/><path d="M6.53 9C4.6 8.8 3 7.1 3 5"/><path d="M6 13H2"/><path d="M3 21c0-2.1 1.7-3.9 3.8-4"/><path d="M20.97 5c0 2.1-1.6 3.8-3.5 4"/><path d="M22 13h-4"/><path d="M17.2 17c2.1.1 3.8 1.9 3.8 4"/></svg>'}function v(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>'}function I(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"/></svg>'}function A(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>'}function E(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m16 13 5.223 3.482a.5.5 0 0 0 .777-.416V7.87a.5.5 0 0 0-.752-.432L16 10.5"/><rect x="2" y="6" width="14" height="12" rx="2"/></svg>'}function L(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m22 2-7 20-4-9-9-4z"/><path d="M22 2 11 13"/></svg>'}function $(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m9 18 6-6-6-6"/></svg>'}function U(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="m9 11 3 3L22 4"/></svg>'}function z(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/></svg>'}function W(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg>'}function F(){return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>'}var ot=.85,rt="image/jpeg";async function x(n={}){let{quality:t=ot,target:e=document.body,filter:o}=n,r=e.scrollWidth,i=e.scrollHeight,a=await toBlob(e,{quality:t,type:rt,filter:o,cacheBust:true});if(!a)throw new Error("Screenshot capture failed: no blob produced");return {blob:a,width:r,height:i}}var w=Math.PI/6,it="#ff0000",st=3,at=16,lt=10,dt=0;function u(){return `ann_${Date.now()}_${++dt}`}function j(n,t,e,o,r){let i=Math.atan2(e.y-t.y,e.x-t.x);n.save(),n.strokeStyle=o,n.fillStyle=o,n.lineWidth=r,n.lineCap="round",n.lineJoin="round",n.beginPath(),n.moveTo(t.x,t.y),n.lineTo(e.x,e.y),n.stroke(),n.beginPath(),n.moveTo(e.x,e.y),n.lineTo(e.x-15*Math.cos(i-w),e.y-15*Math.sin(i-w)),n.lineTo(e.x-15*Math.cos(i+w),e.y-15*Math.sin(i+w)),n.closePath(),n.fill(),n.restore();}function q(n,t,e,o,r){n.save(),n.strokeStyle=o,n.lineWidth=r,n.lineCap="round",n.lineJoin="round",n.strokeRect(t.x,t.y,e.x-t.x,e.y-t.y),n.restore();}function pt(n,t,e,o,r){n.save(),n.font=`${r}px sans-serif`,n.textBaseline="top";let i=4,a=n.measureText(e),l=r*1.2;n.fillStyle="rgba(0, 0, 0, 0.6)",n.fillRect(t.x-i,t.y-i,a.width+i*2,l+i*2),n.fillStyle=o,n.fillText(e,t.x,t.y),n.restore();}function N(n,t,e,o,r){let i=Math.min(e.x,o.x),a=Math.min(e.y,o.y),l=Math.abs(o.x-e.x),d=Math.abs(o.y-e.y);l===0||d===0||(n.save(),n.filter=`blur(${r}px)`,n.drawImage(t,i,a,l,d,i,a,l,d),n.filter="none",n.strokeStyle="rgba(128, 128, 128, 0.5)",n.lineWidth=1,n.setLineDash([4,4]),n.strokeRect(i,a,l,d),n.setLineDash([]),n.restore());}function X(n,t,e,o){if(t.length<2)return;n.save(),n.strokeStyle=e,n.lineWidth=o,n.lineCap="round",n.lineJoin="round";let r=t[0];n.beginPath(),n.moveTo(r.x,r.y);for(let i=1;i<t.length;i++){let a=t[i];n.lineTo(a.x,a.y);}n.stroke(),n.restore();}function V(n,t,e){switch(e.tool){case "arrow":j(n,e.start,e.end,e.color,e.lineWidth);break;case "box":q(n,e.start,e.end,e.color,e.lineWidth);break;case "text":pt(n,e.position,e.text,e.color,e.fontSize);break;case "blur":N(n,t,e.start,e.end,e.blurRadius);break;case "freehand":X(n,e.points,e.color,e.lineWidth);break}}function J(n,t){for(let e of t)V(n,n.canvas,e);}var c=class{constructor(t,e,o){this.container=t;this.width=e;this.height=o;this.canvas=document.createElement("canvas"),this.canvas.width=e,this.canvas.height=o,this.canvas.style.cssText="position:absolute;top:0;left:0;width:100%;height:100%;cursor:crosshair;touch-action:none;";let r=this.canvas.getContext("2d");if(!r)throw new Error("Failed to get 2D canvas context");this.ctx=r,this.onPointerDownBound=this.onPointerDown.bind(this),this.onPointerMoveBound=this.onPointerMove.bind(this),this.onPointerUpBound=this.onPointerUp.bind(this),this.canvas.addEventListener("pointerdown",this.onPointerDownBound),this.canvas.addEventListener("pointermove",this.onPointerMoveBound),this.canvas.addEventListener("pointerup",this.onPointerUpBound),this.container.appendChild(this.canvas);}canvas;ctx;operations=[];currentTool="arrow";color=it;lineWidth=st;fontSize=at;blurRadius=lt;isDrawing=false;startPoint=null;currentPoints=[];screenshotImage=null;onPointerDownBound;onPointerMoveBound;onPointerUpBound;setScreenshotImage(t){this.screenshotImage=t,this.redraw();}setTool(t){this.currentTool=t;}getTool(){return this.currentTool}setColor(t){this.color=t;}setLineWidth(t){this.lineWidth=t;}setFontSize(t){this.fontSize=t;}setBlurRadius(t){this.blurRadius=t;}getOperations(){return [...this.operations]}undo(){this.operations.pop(),this.redraw();}clear(){this.operations=[],this.redraw();}addTextAtPosition(t,e){let o={id:u(),tool:"text",color:this.color,lineWidth:this.lineWidth,position:t,text:e,fontSize:this.fontSize,timestamp:Date.now()};this.operations.push(o),this.redraw();}destroy(){this.canvas.removeEventListener("pointerdown",this.onPointerDownBound),this.canvas.removeEventListener("pointermove",this.onPointerMoveBound),this.canvas.removeEventListener("pointerup",this.onPointerUpBound),this.canvas.remove();}getCanvasPoint(t){let e=this.canvas.getBoundingClientRect();return {x:(t.clientX-e.left)/e.width*this.width,y:(t.clientY-e.top)/e.height*this.height}}onPointerDown(t){t.preventDefault(),this.canvas.setPointerCapture(t.pointerId);let e=this.getCanvasPoint(t);if(this.startPoint=e,this.currentTool==="text"){this.promptTextInput(e);return}this.isDrawing=true,this.currentTool==="freehand"&&(this.currentPoints=[e]);}onPointerMove(t){if(!this.isDrawing||!this.startPoint)return;t.preventDefault();let e=this.getCanvasPoint(t);this.currentTool==="freehand"&&this.currentPoints.push(e),this.redraw(),this.drawPreview(e);}onPointerUp(t){if(!this.isDrawing||!this.startPoint)return;t.preventDefault();let e=this.getCanvasPoint(t);switch(this.currentTool){case "arrow":this.operations.push({id:u(),tool:"arrow",color:this.color,lineWidth:this.lineWidth,start:this.startPoint,end:e,timestamp:Date.now()});break;case "box":this.operations.push({id:u(),tool:"box",color:this.color,lineWidth:this.lineWidth,start:this.startPoint,end:e,timestamp:Date.now()});break;case "blur":this.operations.push({id:u(),tool:"blur",color:this.color,lineWidth:this.lineWidth,start:this.startPoint,end:e,blurRadius:this.blurRadius,timestamp:Date.now()});break;case "freehand":this.currentPoints.push(e),this.operations.push({id:u(),tool:"freehand",color:this.color,lineWidth:this.lineWidth,points:[...this.currentPoints],timestamp:Date.now()}),this.currentPoints=[];break;}this.isDrawing=false,this.startPoint=null,this.redraw();}promptTextInput(t){let e=prompt("Enter annotation text:");e&&this.addTextAtPosition(t,e);}drawPreview(t){if(this.startPoint)switch(this.currentTool){case "arrow":j(this.ctx,this.startPoint,t,this.color,this.lineWidth);break;case "box":q(this.ctx,this.startPoint,t,this.color,this.lineWidth);break;case "blur":N(this.ctx,this.canvas,this.startPoint,t,this.blurRadius);break;case "freehand":X(this.ctx,this.currentPoints,this.color,this.lineWidth);break;}}redraw(){this.ctx.clearRect(0,0,this.width,this.height),this.screenshotImage&&this.ctx.drawImage(this.screenshotImage,0,0,this.width,this.height);for(let t of this.operations)V(this.ctx,this.canvas,t);}};var ct=0;function C(){return `att_${Date.now()}_${++ct}`}var y=class{constructor(t){this.shadowRoot=t;this.elements=this.createDOM(),this.bindEvents();}elements;attachments=[];visible=false;submitting=false;recording=false;mediaRecorder=null;mediaStream=null;recordedChunks=[];reporterVisible=false;annotationOverlay=null;annotationContainer=null;onSubmit=null;onClose=null;setOnSubmit(t){this.onSubmit=t;}setOnClose(t){this.onClose=t;}show(){this.visible=true,this.elements.root.classList.add("bd-panel--visible"),this.elements.textarea.focus();}hide(){this.visible=false,this.elements.root.classList.remove("bd-panel--visible");}isVisible(){return this.visible}reset(){this.elements.textarea.value="",this.elements.nameInput.value="",this.elements.emailInput.value="",this.revokeAttachmentUrls(),this.attachments=[],this.renderAttachments(),this.showFormView(),this.setSubmitting(false);}setReporterInfo(t,e){this.elements.nameInput.value=t,this.elements.emailInput.value=e;}getElement(){return this.elements.root}destroy(){this.stopRecording(),this.destroyAnnotation(),this.revokeAttachmentUrls(),this.elements.root.remove();}createDOM(){let t=document.createElement("div");t.className="bd-panel",t.innerHTML=`
|
|
473
|
+
<div class="bd-panel__header">
|
|
474
|
+
<span class="bd-panel__title">Report a bug</span>
|
|
475
|
+
<button class="bd-panel__close" aria-label="Close">${v()}</button>
|
|
476
|
+
</div>
|
|
477
|
+
<div class="bd-panel__body" data-role="body">
|
|
478
|
+
<textarea class="bd-textarea" placeholder="Describe the bug you found..." rows="4"></textarea>
|
|
479
|
+
<div class="bd-action-bar">
|
|
480
|
+
<button class="bd-action-btn" data-action="attach">${I()} Attach</button>
|
|
481
|
+
<button class="bd-action-btn" data-action="screenshot">${A()} Screenshot</button>
|
|
482
|
+
<button class="bd-action-btn" data-action="record">${E()} Record</button>
|
|
483
|
+
</div>
|
|
484
|
+
<div class="bd-attachments" data-role="attachments"></div>
|
|
485
|
+
<button class="bd-reporter-toggle" data-action="toggle-reporter">
|
|
486
|
+
${$()} Reporter info
|
|
487
|
+
</button>
|
|
488
|
+
<div class="bd-reporter-fields" data-role="reporter-fields">
|
|
489
|
+
<input class="bd-input" type="text" placeholder="Your name" data-role="name" />
|
|
490
|
+
<input class="bd-input" type="email" placeholder="Your email" data-role="email" />
|
|
491
|
+
</div>
|
|
492
|
+
<input class="bd-file-input" type="file" multiple data-role="file-input" />
|
|
493
|
+
</div>
|
|
494
|
+
<div class="bd-success" data-role="success" style="display:none">
|
|
495
|
+
${U()}
|
|
496
|
+
<div class="bd-success__title">Bug report sent!</div>
|
|
497
|
+
<div class="bd-success__subtitle">Thank you for your feedback.</div>
|
|
498
|
+
</div>
|
|
499
|
+
<div class="bd-panel__footer">
|
|
500
|
+
<button class="bd-send-btn" data-action="send">${L()} Send report</button>
|
|
501
|
+
</div>
|
|
502
|
+
`;let e=r=>t.querySelector(r);return {root:t,textarea:e(".bd-textarea"),nameInput:e('[data-role="name"]'),emailInput:e('[data-role="email"]'),sendBtn:e('[data-action="send"]'),screenshotBtn:e('[data-action="screenshot"]'),recordBtn:e('[data-action="record"]'),attachBtn:e('[data-action="attach"]'),fileInput:e('[data-role="file-input"]'),attachmentsList:e('[data-role="attachments"]'),reporterToggle:e('[data-action="toggle-reporter"]'),reporterFields:e('[data-role="reporter-fields"]'),body:e('[data-role="body"]'),successView:e('[data-role="success"]')}}bindEvents(){this.elements.root.querySelector(".bd-panel__close").addEventListener("click",()=>this.handleClose()),this.elements.sendBtn.addEventListener("click",()=>this.handleSubmit()),this.elements.screenshotBtn.addEventListener("click",()=>this.handleScreenshot()),this.elements.recordBtn.addEventListener("click",()=>this.handleRecord()),this.elements.attachBtn.addEventListener("click",()=>this.elements.fileInput.click()),this.elements.fileInput.addEventListener("change",()=>this.handleFileSelect()),this.elements.reporterToggle.addEventListener("click",()=>this.toggleReporter()),this.elements.attachmentsList.addEventListener("click",e=>{let r=e.target.closest("[data-remove-id]");if(r){let i=r.dataset.removeId;this.removeAttachment(i);}});}handleClose(){this.onClose?.();}async handleSubmit(){let t=this.elements.textarea.value.trim();if(!t){this.elements.textarea.focus();return}if(!(this.submitting||!this.onSubmit)){this.setSubmitting(true);try{await this.onSubmit({description:t,reporterName:this.elements.nameInput.value.trim(),reporterEmail:this.elements.emailInput.value.trim(),attachments:[...this.attachments]}),this.showSuccessView(),setTimeout(()=>{this.reset(),this.handleClose();},2e3);}catch{this.setSubmitting(false);}}}async handleScreenshot(){this.elements.screenshotBtn.disabled=true;try{this.hide(),await ht(100);let t=await x({filter:r=>!(r instanceof HTMLElement&&r.tagName.toLowerCase()==="bugdump-widget")}),e=URL.createObjectURL(t.blob),o=await ut(e);this.showAnnotationOverlay(o,t.blob,t.width,t.height);}catch{this.show();}finally{this.elements.screenshotBtn.disabled=false;}}showAnnotationOverlay(t,e,o,r){this.annotationContainer=document.createElement("div"),this.annotationContainer.className="bd-annotation-overlay";let i=document.createElement("div");i.className="bd-annotation-toolbar",i.innerHTML=`
|
|
503
|
+
<button class="active" data-tool="arrow">Arrow</button>
|
|
504
|
+
<button data-tool="box">Box</button>
|
|
505
|
+
<button data-tool="freehand">Draw</button>
|
|
506
|
+
<button data-tool="text">Text</button>
|
|
507
|
+
<button data-tool="blur">Blur</button>
|
|
508
|
+
<div class="bd-annotation-toolbar__spacer"></div>
|
|
509
|
+
<button data-annotation-action="undo">Undo</button>
|
|
510
|
+
<button class="bd-annotation-toolbar__cancel" data-annotation-action="cancel">Cancel</button>
|
|
511
|
+
<button class="bd-annotation-toolbar__confirm" data-annotation-action="confirm">Done</button>
|
|
512
|
+
`;let a=document.createElement("div");a.className="bd-annotation-canvas-wrap",this.annotationContainer.appendChild(i),this.annotationContainer.appendChild(a),document.body.appendChild(this.annotationContainer),this.annotationOverlay=new c(a,o,r),this.annotationOverlay.setScreenshotImage(t),i.addEventListener("click",l=>{let p=l.target.closest("button");if(!p)return;let M=p.dataset.tool;if(M){this.annotationOverlay?.setTool(M),i.querySelectorAll("[data-tool]").forEach(G=>G.classList.remove("active")),p.classList.add("active");return}let T=p.dataset.annotationAction;T==="undo"?this.annotationOverlay?.undo():T==="cancel"?(URL.revokeObjectURL(t.src),this.destroyAnnotation(),this.show()):T==="confirm"&&this.finishAnnotation(e,t);});}finishAnnotation(t,e){let o=this.annotationOverlay?.getOperations()??[],r=URL.createObjectURL(t);this.addAttachment({id:C(),type:"screenshot",blob:t,name:`screenshot-${Date.now()}.jpg`,thumbnailUrl:r,annotations:o.length>0?o:void 0}),URL.revokeObjectURL(e.src),this.destroyAnnotation(),this.show();}destroyAnnotation(){this.annotationOverlay?.destroy(),this.annotationOverlay=null,this.annotationContainer?.remove(),this.annotationContainer=null;}async handleRecord(){if(this.recording){this.stopRecording();return}try{this.mediaStream=await navigator.mediaDevices.getDisplayMedia({video:!0,audio:!1}),this.recordedChunks=[],this.mediaRecorder=new MediaRecorder(this.mediaStream,{mimeType:mt()}),this.mediaRecorder.ondataavailable=t=>{t.data.size>0&&this.recordedChunks.push(t.data);},this.mediaRecorder.onstop=()=>{let t=new Blob(this.recordedChunks,{type:this.mediaRecorder?.mimeType||"video/webm"}),e=URL.createObjectURL(t);this.addAttachment({id:C(),type:"recording",blob:t,name:`recording-${Date.now()}.webm`,thumbnailUrl:e}),this.cleanupMediaStream(),this.setRecordingState(!1);},this.mediaStream.getVideoTracks()[0]?.addEventListener("ended",()=>{this.stopRecording();}),this.mediaRecorder.start(),this.setRecordingState(!0);}catch{this.cleanupMediaStream(),this.setRecordingState(false);}}stopRecording(){this.mediaRecorder&&this.mediaRecorder.state!=="inactive"&&this.mediaRecorder.stop(),this.cleanupMediaStream();}cleanupMediaStream(){this.mediaStream&&(this.mediaStream.getTracks().forEach(t=>t.stop()),this.mediaStream=null);}setRecordingState(t){this.recording=t,t?(this.elements.recordBtn.innerHTML=`${F()} Stop`,this.elements.recordBtn.style.color="#ef4444"):(this.elements.recordBtn.innerHTML=`${E()} Record`,this.elements.recordBtn.style.color="");}handleFileSelect(){let t=this.elements.fileInput.files;if(t){for(let e=0;e<t.length;e++){let o=t[e],i=o.type.startsWith("image/")?URL.createObjectURL(o):void 0;this.addAttachment({id:C(),type:"file",blob:o,name:o.name,thumbnailUrl:i});}this.elements.fileInput.value="";}}addAttachment(t){this.attachments.push(t),this.renderAttachments();}removeAttachment(t){let e=this.attachments.findIndex(r=>r.id===t);if(e===-1)return;let o=this.attachments[e];o.thumbnailUrl&&URL.revokeObjectURL(o.thumbnailUrl),this.attachments.splice(e,1),this.renderAttachments();}renderAttachments(){let t=this.elements.attachmentsList;if(t.innerHTML="",this.attachments.length===0){t.style.display="none";return}t.style.display="flex";for(let e of this.attachments){let o=document.createElement("div");o.className="bd-attachment";let r;e.thumbnailUrl&&e.type!=="recording"?r=`<img src="${e.thumbnailUrl}" alt="${e.name}" />`:e.type==="recording"&&e.thumbnailUrl?r=`<video src="${e.thumbnailUrl}" muted></video>`:r=`<div class="bd-attachment__icon">${z()}</div>`,o.innerHTML=`
|
|
513
|
+
${r}
|
|
514
|
+
<button class="bd-attachment__remove" data-remove-id="${e.id}" aria-label="Remove">
|
|
515
|
+
${W()}
|
|
516
|
+
</button>
|
|
517
|
+
`,t.appendChild(o);}}toggleReporter(){this.reporterVisible=!this.reporterVisible,this.elements.reporterToggle.classList.toggle("bd-reporter-toggle--open",this.reporterVisible),this.elements.reporterFields.classList.toggle("bd-reporter-fields--visible",this.reporterVisible);}setSubmitting(t){this.submitting=t,this.elements.sendBtn.disabled=t,t?this.elements.sendBtn.innerHTML='<span class="bd-spinner"></span> Sending...':this.elements.sendBtn.innerHTML=`${L()} Send report`;}showSuccessView(){this.elements.body.style.display="none",this.elements.successView.style.display="flex";let t=this.elements.root.querySelector(".bd-panel__footer");t.style.display="none";}showFormView(){this.elements.body.style.display="flex",this.elements.successView.style.display="none";let t=this.elements.root.querySelector(".bd-panel__footer");t.style.display="flex";}revokeAttachmentUrls(){for(let t of this.attachments)t.thumbnailUrl&&URL.revokeObjectURL(t.thumbnailUrl);}};function ht(n){return new Promise(t=>setTimeout(t,n))}function ut(n){return new Promise((t,e)=>{let o=new Image;o.onload=()=>t(o),o.onerror=e,o.src=n;})}function mt(){let n=["video/webm;codecs=vp9","video/webm;codecs=vp8","video/webm","video/mp4"];for(let t of n)if(MediaRecorder.isTypeSupported(t))return t;return "video/webm"}var R=class{host;shadowRoot;triggerBtn;panel;open=false;onSubmit=null;constructor(){this.host=document.createElement("bugdump-widget"),this.host.style.cssText="all:initial;position:fixed;z-index:2147483647;",this.shadowRoot=this.host.attachShadow({mode:"closed"});let t=document.createElement("style");t.textContent=O(),this.shadowRoot.appendChild(t),this.triggerBtn=this.createTriggerButton(),this.shadowRoot.appendChild(this.triggerBtn),this.panel=new y(this.shadowRoot),this.shadowRoot.appendChild(this.panel.getElement()),this.panel.setOnClose(()=>this.close()),document.body.appendChild(this.host);}setOnSubmit(t){this.onSubmit=t,this.panel.setOnSubmit(t);}setReporterInfo(t,e){this.panel.setReporterInfo(t,e);}toggle(){this.open?this.close():this.openPanel();}openPanel(){this.open||(this.open=true,this.triggerBtn.classList.add("bd-trigger--open"),this.triggerBtn.innerHTML=v(),this.panel.show());}close(){this.open&&(this.open=false,this.triggerBtn.classList.remove("bd-trigger--open"),this.triggerBtn.innerHTML=S(),this.panel.hide());}isOpen(){return this.open}destroy(){this.panel.destroy(),this.host.remove();}createTriggerButton(){let t=document.createElement("button");return t.className="bd-trigger",t.setAttribute("aria-label","Report a bug"),t.innerHTML=S(),t.addEventListener("click",()=>this.toggle()),t}};var P=class n{static instance=null;state;httpClient=null;consoleCollector;networkCollector;sessionReplayCollector;widget=null;constructor(){this.state=k(),this.consoleCollector=new f,this.networkCollector=new g,this.sessionReplayCollector=new b;}static init(t){if(n.instance)return n.instance;let e=new n,o=H(t);return e.state.config=o,e.state.initialized=true,e.httpClient=new m(o.endpoint,o.projectKey),e.consoleCollector.start(),e.networkCollector.start(),e.sessionReplayCollector.start(),e.mountWidget(),n.instance=e,e}static getInstance(){return n.instance}identify(t){this.ensureInitialized(),this.state.user=t,this.widget&&this.widget.setReporterInfo(t.name||"",t.email||"");}setContext(t){this.ensureInitialized(),this.state.customContext={...this.state.customContext,...t};}open(){this.ensureInitialized(),this.state.widgetOpen=true,this.widget?.openPanel();}close(){this.ensureInitialized(),this.state.widgetOpen=false,this.widget?.close();}collectTelemetry(){return this.ensureInitialized(),{consoleLogs:this.consoleCollector.flush(),networkRequests:this.networkCollector.flush(),sessionReplayEvents:this.sessionReplayCollector.flush(),performance:_(),metadata:D()}}destroy(){this.widget?.destroy(),this.widget=null,this.consoleCollector.stop(),this.networkCollector.stop(),this.sessionReplayCollector.stop(),this.state=k(),this.httpClient=null,n.instance=null;}getConfig(){return this.state.config}getUser(){return this.state.user}getContext(){return this.state.customContext}getHttpClient(){return this.ensureInitialized(),this.httpClient}isWidgetOpen(){return this.state.widgetOpen}mountWidget(){typeof document>"u"||(this.widget=new R,this.widget.setOnSubmit(t=>this.handleSubmit(t)));}async handleSubmit(t){let e=this.httpClient,o=this.collectTelemetry(),r=o.metadata,i=[];for(let l of t.attachments){let d=await e.requestUpload({originalName:l.name,mimeType:l.blob.type,size:l.blob.size});await e.uploadFileToS3(d.url,d.fields,l.blob);let p=l.type==="file"?"screenshot":l.type;i.push({fileId:d.fileId,type:p,metadata:l.annotations?{annotations:l.annotations}:void 0});}let a={description:t.description,reporterName:t.reporterName||this.state.user?.name||void 0,reporterEmail:t.reporterEmail||this.state.user?.email||void 0,reporterExternalId:this.state.user?.id||void 0,pageUrl:r.url,referrerUrl:r.referrer||void 0,userAgent:r.userAgent,viewport:r.viewport,consoleLogs:o.consoleLogs,networkRequests:o.networkRequests,performance:o.performance,customContext:Object.keys(this.state.customContext).length>0?this.state.customContext:void 0,attachments:i.length>0?i:void 0};await e.submitReport(a);}ensureInitialized(){if(!this.state.initialized)throw new Error("Bugdump SDK is not initialized. Call Bugdump.init() first.")}};export{c as AnnotationOverlay,P as Bugdump,h as BugdumpApiError,x as captureScreenshot,J as renderOperationsToCanvas};
|
package/package.json
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bugdump/sdk",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Official Bugdump SDK - Embed bug reporting widget on your website",
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"require": "./dist/index.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md"
|
|
18
|
+
],
|
|
19
|
+
"keywords": [
|
|
20
|
+
"bugdump",
|
|
21
|
+
"sdk",
|
|
22
|
+
"bug-reporting",
|
|
23
|
+
"widget",
|
|
24
|
+
"feedback"
|
|
25
|
+
],
|
|
26
|
+
"author": "Bugdump",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"repository": {
|
|
29
|
+
"type": "git",
|
|
30
|
+
"url": "https://github.com/bugdump-app/bugdump-ts-sdk"
|
|
31
|
+
},
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/bugdump-app/bugdump-ts-sdk/issues"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://bugdump.com",
|
|
36
|
+
"sideEffects": false,
|
|
37
|
+
"dependencies": {
|
|
38
|
+
"@rrweb/record": "2.0.0-alpha.20",
|
|
39
|
+
"@rrweb/types": "2.0.0-alpha.20",
|
|
40
|
+
"html-to-image": "^1.11.13"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"@types/node": "^22.10.2",
|
|
44
|
+
"eslint": "^9.17.0",
|
|
45
|
+
"tsup": "^8.3.5",
|
|
46
|
+
"typescript": "^5.7.2",
|
|
47
|
+
"typescript-eslint": "^8.18.2"
|
|
48
|
+
},
|
|
49
|
+
"publishConfig": {
|
|
50
|
+
"access": "public"
|
|
51
|
+
},
|
|
52
|
+
"type": "module",
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsup",
|
|
55
|
+
"dev": "tsup --watch",
|
|
56
|
+
"lint": "tsc --noEmit && eslint ."
|
|
57
|
+
}
|
|
58
|
+
}
|