@uxbertlabs/reportly 1.0.20 → 1.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/IssueModal.d.ts.map +1 -1
- package/dist/components/Reportly.d.ts.map +1 -1
- package/dist/components/ReportlyProvider.d.ts.map +1 -1
- package/dist/features/annotation.d.ts +9 -1
- package/dist/features/annotation.d.ts.map +1 -1
- package/dist/features/export.d.ts.map +1 -1
- package/dist/index.cjs.js +270 -39
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.esm.js +271 -40
- package/dist/index.esm.js.map +1 -1
- package/dist/index.min.js +6 -6
- package/dist/index.min.js.map +1 -1
- package/dist/lib/utils.d.ts +6 -0
- package/dist/lib/utils.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IssueModal.d.ts","sourceRoot":"","sources":["../../src/components/IssueModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAOrD,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAc,EAAE,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"IssueModal.d.ts","sourceRoot":"","sources":["../../src/components/IssueModal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAOrD,UAAU,eAAe;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,UAAU,CAAC,EAAE,SAAc,EAAE,EAAE,eAAe,4BA2Y7D;AAED,eAAe,UAAU,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Reportly.d.ts","sourceRoot":"","sources":["../../src/components/Reportly.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAMjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CAClC;
|
|
1
|
+
{"version":3,"file":"Reportly.d.ts","sourceRoot":"","sources":["../../src/components/Reportly.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA4B,MAAM,OAAO,CAAC;AAMjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,UAAU,aAAa;IACrB,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CAClC;AA0GD,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,aAAa,qBAMjD;AAED,eAAe,QAAQ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReportlyProvider.d.ts","sourceRoot":"","sources":["../../src/components/ReportlyProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAyC,SAAS,
|
|
1
|
+
{"version":3,"file":"ReportlyProvider.d.ts","sourceRoot":"","sources":["../../src/components/ReportlyProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAyC,SAAS,EAAwB,MAAM,OAAO,CAAC;AACtG,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AACzF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAI/D,OAAO,iBAAiB,MAAM,wBAAwB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;IACtB,WAAW,EAAE,OAAO,CAAC;IACrB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,UAAU,GAAG,UAAU,CAAC;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,cAAc,CAAC;CACxB;AAmED,UAAU,mBAAmB;IAC3B,KAAK,EAAE,aAAa,CAAC;IACrB,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAC;IAC5C,oBAAoB,EAAE,CAAC,OAAO,EAAE,iBAAiB,GAAG,IAAI,KAAK,IAAI,CAAC;IAClE,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,eAAe,EAAE,MAAM,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,iBAAiB,EAAE,CAAC,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrE,gBAAgB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,OAAO,EAAE,CAAC,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,IAAI,CAAC;IAC5C,WAAW,EAAE,CAAC,SAAS,EAAE,SAAS,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;IAC5D,YAAY,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC7C,YAAY,EAAE,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,KAAK,IAAI,CAAC;IACxD,gBAAgB,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAID,UAAU,qBAAqB;IAC7B,QAAQ,EAAE,SAAS,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;CAClC;AAED,wBAAgB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,MAAW,EAAE,EAAE,qBAAqB,qBA0KhF;AAED,wBAAgB,WAAW,IAAI,mBAAmB,CAMjD"}
|
|
@@ -12,10 +12,17 @@ declare class AnnotationManager {
|
|
|
12
12
|
private currentPath;
|
|
13
13
|
private textInput;
|
|
14
14
|
private currentTextAnnotation;
|
|
15
|
+
private drawingBounds;
|
|
16
|
+
private currentMode;
|
|
17
|
+
private scrollListener;
|
|
18
|
+
private initialScrollPosition;
|
|
15
19
|
constructor();
|
|
16
20
|
createCanvas(): HTMLCanvasElement;
|
|
17
21
|
private updateCanvasSize;
|
|
22
|
+
private updateDrawingBounds;
|
|
23
|
+
private checkAndAdjustCanvasMode;
|
|
18
24
|
show(mode?: 'viewport' | 'fullpage'): void;
|
|
25
|
+
private handleScroll;
|
|
19
26
|
hide(): void;
|
|
20
27
|
setTool(tool: AnnotationTool): void;
|
|
21
28
|
setColor(color: string): void;
|
|
@@ -37,7 +44,8 @@ declare class AnnotationManager {
|
|
|
37
44
|
private redraw;
|
|
38
45
|
undo(): void;
|
|
39
46
|
clear(): void;
|
|
40
|
-
|
|
47
|
+
getCurrentMode(): 'viewport' | 'fullpage';
|
|
48
|
+
exportAnnotatedScreenshot(baseScreenshot: string, mode?: 'viewport' | 'fullpage'): Promise<string>;
|
|
41
49
|
destroy(): void;
|
|
42
50
|
}
|
|
43
51
|
export default AnnotationManager;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"annotation.d.ts","sourceRoot":"","sources":["../../src/features/annotation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,UAAU,CAAC;AAElE,cAAM,iBAAiB;IACrB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,GAAG,CAAkC;IAC7C,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,qBAAqB,CAA6E;;
|
|
1
|
+
{"version":3,"file":"annotation.d.ts","sourceRoot":"","sources":["../../src/features/annotation.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAqB,MAAM,UAAU,CAAC;AAElE,cAAM,iBAAiB;IACrB,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,GAAG,CAAkC;IAC7C,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,WAAW,CAAiB;IACpC,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,SAAS,CAA0B;IAC3C,OAAO,CAAC,qBAAqB,CAA6E;IAC1G,OAAO,CAAC,aAAa,CAAoE;IACzF,OAAO,CAAC,WAAW,CAA0B;IAC7C,OAAO,CAAC,cAAc,CAAsB;IAC5C,OAAO,CAAC,qBAAqB,CAAkC;;IAqB/D,YAAY,IAAI,iBAAiB;IAqDjC,OAAO,CAAC,gBAAgB;IA8BxB,OAAO,CAAC,mBAAmB;IAW3B,OAAO,CAAC,wBAAwB;IAwDhC,IAAI,CAAC,IAAI,GAAE,UAAU,GAAG,UAAuB,GAAG,IAAI;IA8CtD,OAAO,CAAC,YAAY;IAmCpB,IAAI,IAAI,IAAI;IAkBZ,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAInC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,OAAO,CAAC,eAAe;IAqCvB,OAAO,CAAC,eAAe;IA2BvB,OAAO,CAAC,aAAa;IAgDrB,OAAO,CAAC,gBAAgB;IASxB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,cAAc;IAStB,OAAO,CAAC,QAAQ;IAehB,OAAO,CAAC,SAAS;IA8BjB,OAAO,CAAC,aAAa;IAQrB,OAAO,CAAC,eAAe;IA8DvB,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,mBAAmB;IAwB3B,OAAO,CAAC,QAAQ;IAuBhB,OAAO,CAAC,MAAM;IAmBd,IAAI,IAAI,IAAI;IAOZ,KAAK,IAAI,IAAI;IAMb,cAAc,IAAI,UAAU,GAAG,UAAU;IAInC,yBAAyB,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,UAAU,GAAG,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAkDxG,OAAO,IAAI,IAAI;CAOhB;AAED,eAAe,iBAAiB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/features/export.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAuB,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErF,cAAM,MAAM;IACV,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,SAAS,CAAC,EAAE,SAAS;
|
|
1
|
+
{"version":3,"file":"export.d.ts","sourceRoot":"","sources":["../../src/features/export.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAC1D,OAAuB,EAAE,KAAK,SAAS,EAAE,KAAK,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErF,cAAM,MAAM;IACV,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,cAAc,CAAiB;gBAE3B,SAAS,CAAC,EAAE,SAAS;IASjC,YAAY,CAAC,SAAS,EAAE,aAAa,GAAG,MAAM;IA0B9C,OAAO,CAAC,SAAS;IAwBjB,OAAO,CAAC,eAAe;IAevB,cAAc,IAAI,UAAU,EAAE;IAI9B,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IASvC,gBAAgB,IAAI,IAAI;IASxB,eAAe,IAAI,IAAI;IAsBvB;;OAEG;IACG,SAAS,CAAC,SAAS,EAAE,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC;IAW/D;;OAEG;IACH,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI;IAIrC;;OAEG;IACH,YAAY,IAAI,OAAO;IAIvB;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,WAAW,CAAC;IAI/C;;OAEG;IACH,YAAY,IAAI,SAAS,GAAG,IAAI;IAIhC;;OAEG;IACH,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAIrC;;OAEG;IACH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;CAGpC;AAED,eAAe,MAAM,CAAC"}
|
package/dist/index.cjs.js
CHANGED
|
@@ -298,29 +298,40 @@ class N8nIntegration {
|
|
|
298
298
|
|
|
299
299
|
class Export {
|
|
300
300
|
constructor(n8nConfig) {
|
|
301
|
-
this.savedIssues =
|
|
301
|
+
this.savedIssues = [];
|
|
302
302
|
this.n8nIntegration = new N8nIntegration(n8nConfig);
|
|
303
|
+
// Defer localStorage access to avoid SSR issues
|
|
304
|
+
if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') {
|
|
305
|
+
this.savedIssues = this.loadSavedIssues();
|
|
306
|
+
}
|
|
303
307
|
}
|
|
304
308
|
exportToJSON(issueData) {
|
|
305
309
|
const json = JSON.stringify(issueData, null, 2);
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
310
|
+
// Check if we're in a browser environment
|
|
311
|
+
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
|
|
312
|
+
const blob = new Blob([json], {
|
|
313
|
+
type: 'application/json'
|
|
314
|
+
});
|
|
315
|
+
const url = URL.createObjectURL(blob);
|
|
316
|
+
// Create download link
|
|
317
|
+
const link = document.createElement('a');
|
|
318
|
+
link.href = url;
|
|
319
|
+
link.download = `issue-${Date.now()}.json`;
|
|
320
|
+
document.body.appendChild(link);
|
|
321
|
+
link.click();
|
|
322
|
+
document.body.removeChild(link);
|
|
323
|
+
// Clean up
|
|
324
|
+
URL.revokeObjectURL(url);
|
|
325
|
+
// Save to localStorage
|
|
326
|
+
this.saveIssue(issueData);
|
|
327
|
+
}
|
|
321
328
|
return json;
|
|
322
329
|
}
|
|
323
330
|
saveIssue(issueData) {
|
|
331
|
+
// Check if we're in a browser environment
|
|
332
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
324
335
|
try {
|
|
325
336
|
this.savedIssues.push({
|
|
326
337
|
...issueData,
|
|
@@ -337,6 +348,10 @@ class Export {
|
|
|
337
348
|
}
|
|
338
349
|
}
|
|
339
350
|
loadSavedIssues() {
|
|
351
|
+
// Check if we're in a browser environment
|
|
352
|
+
if (typeof window === 'undefined' || typeof localStorage === 'undefined') {
|
|
353
|
+
return [];
|
|
354
|
+
}
|
|
340
355
|
try {
|
|
341
356
|
const saved = localStorage.getItem('uxbert-saved-issues');
|
|
342
357
|
return saved ? JSON.parse(saved) : [];
|
|
@@ -350,13 +365,23 @@ class Export {
|
|
|
350
365
|
}
|
|
351
366
|
deleteSavedIssue(issueId) {
|
|
352
367
|
this.savedIssues = this.savedIssues.filter(issue => issue.id !== issueId);
|
|
353
|
-
|
|
368
|
+
// Check if we're in a browser environment
|
|
369
|
+
if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') {
|
|
370
|
+
localStorage.setItem('uxbert-saved-issues', JSON.stringify(this.savedIssues));
|
|
371
|
+
}
|
|
354
372
|
}
|
|
355
373
|
clearSavedIssues() {
|
|
356
374
|
this.savedIssues = [];
|
|
357
|
-
|
|
375
|
+
// Check if we're in a browser environment
|
|
376
|
+
if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') {
|
|
377
|
+
localStorage.removeItem('uxbert-saved-issues');
|
|
378
|
+
}
|
|
358
379
|
}
|
|
359
380
|
exportAllIssues() {
|
|
381
|
+
// Check if we're in a browser environment
|
|
382
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') {
|
|
383
|
+
return;
|
|
384
|
+
}
|
|
360
385
|
const json = JSON.stringify(this.savedIssues, null, 2);
|
|
361
386
|
const blob = new Blob([json], {
|
|
362
387
|
type: 'application/json'
|
|
@@ -9472,6 +9497,11 @@ class Screenshot {
|
|
|
9472
9497
|
}
|
|
9473
9498
|
}
|
|
9474
9499
|
|
|
9500
|
+
var screenshot = /*#__PURE__*/Object.freeze({
|
|
9501
|
+
__proto__: null,
|
|
9502
|
+
default: Screenshot
|
|
9503
|
+
});
|
|
9504
|
+
|
|
9475
9505
|
const initialState = {
|
|
9476
9506
|
isOpen: false,
|
|
9477
9507
|
isAnnotating: false,
|
|
@@ -9579,10 +9609,10 @@ function ReportlyProvider({
|
|
|
9579
9609
|
});
|
|
9580
9610
|
// Annotation manager state - will be set by Reportly component
|
|
9581
9611
|
const [annotationManager, setAnnotationManagerState] = React.useState(null);
|
|
9582
|
-
// Initialize services
|
|
9583
|
-
const deviceInfo = new DeviceInfo();
|
|
9584
|
-
const exportService = new Export(config.integrations?.n8n);
|
|
9585
|
-
const screenshot = new Screenshot();
|
|
9612
|
+
// Initialize services with useMemo to ensure they're only created once and support SSR
|
|
9613
|
+
const deviceInfo = React.useMemo(() => new DeviceInfo(), []);
|
|
9614
|
+
const exportService = React.useMemo(() => new Export(config.integrations?.n8n), [config.integrations?.n8n]);
|
|
9615
|
+
const screenshot = React.useMemo(() => new Screenshot(), []);
|
|
9586
9616
|
const openModal = React.useCallback(() => {
|
|
9587
9617
|
dispatch({
|
|
9588
9618
|
type: 'OPEN_MODAL'
|
|
@@ -13082,7 +13112,7 @@ function FloatingButton({
|
|
|
13082
13112
|
}) {
|
|
13083
13113
|
const {
|
|
13084
13114
|
state,
|
|
13085
|
-
|
|
13115
|
+
startAnnotation
|
|
13086
13116
|
} = useReportly();
|
|
13087
13117
|
const {
|
|
13088
13118
|
config
|
|
@@ -13101,7 +13131,7 @@ function FloatingButton({
|
|
|
13101
13131
|
style: {
|
|
13102
13132
|
zIndex: "var(--uxbert-z-button)"
|
|
13103
13133
|
},
|
|
13104
|
-
onClick:
|
|
13134
|
+
onClick: startAnnotation,
|
|
13105
13135
|
title: "Report an issue",
|
|
13106
13136
|
"aria-label": "Report an issue"
|
|
13107
13137
|
}, /*#__PURE__*/React.createElement(Bug, {
|
|
@@ -13138,7 +13168,8 @@ function IssueModal({
|
|
|
13138
13168
|
retakeScreenshot,
|
|
13139
13169
|
startAnnotation,
|
|
13140
13170
|
submitIssue,
|
|
13141
|
-
submitToN8n
|
|
13171
|
+
submitToN8n,
|
|
13172
|
+
reset
|
|
13142
13173
|
} = useReportly();
|
|
13143
13174
|
const [formData, setFormData] = React.useState({
|
|
13144
13175
|
title: "",
|
|
@@ -13155,6 +13186,27 @@ function IssueModal({
|
|
|
13155
13186
|
[field]: value
|
|
13156
13187
|
}));
|
|
13157
13188
|
}, []);
|
|
13189
|
+
const handleClose = React.useCallback(() => {
|
|
13190
|
+
// Check if there's any data that would be lost
|
|
13191
|
+
const hasData = state.screenshot !== null || formData.title.trim() !== "" || formData.description.trim() !== "";
|
|
13192
|
+
if (hasData) {
|
|
13193
|
+
const confirmed = window.confirm("Are you sure you want to close? All unsaved data (screenshot, title, description) will be lost.");
|
|
13194
|
+
if (confirmed) {
|
|
13195
|
+
// Clear all data
|
|
13196
|
+
reset();
|
|
13197
|
+
setFormData({
|
|
13198
|
+
title: "",
|
|
13199
|
+
description: "",
|
|
13200
|
+
priority: "Medium",
|
|
13201
|
+
deviceType: "desktop"
|
|
13202
|
+
});
|
|
13203
|
+
closeModal();
|
|
13204
|
+
}
|
|
13205
|
+
} else {
|
|
13206
|
+
// No data to lose, just close
|
|
13207
|
+
closeModal();
|
|
13208
|
+
}
|
|
13209
|
+
}, [state.screenshot, formData.title, formData.description, reset, closeModal]);
|
|
13158
13210
|
const handleCapture = React.useCallback(async () => {
|
|
13159
13211
|
try {
|
|
13160
13212
|
await captureScreenshot(captureMode);
|
|
@@ -13184,6 +13236,7 @@ function IssueModal({
|
|
|
13184
13236
|
try {
|
|
13185
13237
|
setIsSubmitting(true);
|
|
13186
13238
|
submitIssue(formData);
|
|
13239
|
+
// Form data is cleared by the submitIssue function which calls reset()
|
|
13187
13240
|
setFormData({
|
|
13188
13241
|
title: "",
|
|
13189
13242
|
description: "",
|
|
@@ -13253,7 +13306,7 @@ function IssueModal({
|
|
|
13253
13306
|
})), /*#__PURE__*/React.createElement("h2", {
|
|
13254
13307
|
className: "text-xl font-semibold"
|
|
13255
13308
|
}, "Report Issue")), /*#__PURE__*/React.createElement("button", {
|
|
13256
|
-
onClick:
|
|
13309
|
+
onClick: handleClose,
|
|
13257
13310
|
className: "p-2 rounded-md hover:bg-muted transition-colors cursor-pointer",
|
|
13258
13311
|
"aria-label": "Close"
|
|
13259
13312
|
}, /*#__PURE__*/React.createElement(X, {
|
|
@@ -13618,12 +13671,20 @@ class AnnotationManager {
|
|
|
13618
13671
|
this.currentPath = [];
|
|
13619
13672
|
this.textInput = null;
|
|
13620
13673
|
this.currentTextAnnotation = null;
|
|
13674
|
+
this.drawingBounds = null;
|
|
13675
|
+
this.currentMode = 'fullpage';
|
|
13676
|
+
this.scrollListener = null;
|
|
13677
|
+
this.initialScrollPosition = null;
|
|
13621
13678
|
}
|
|
13622
13679
|
createCanvas() {
|
|
13680
|
+
// Calculate page dimensions BEFORE creating canvas
|
|
13681
|
+
const fullPageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
|
|
13682
|
+
const fullPageWidth = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
|
|
13683
|
+
// Create canvas with calculated dimensions
|
|
13623
13684
|
this.canvas = document.createElement('canvas');
|
|
13624
13685
|
this.canvas.className = 'uxbert-canvas-overlay';
|
|
13625
|
-
|
|
13626
|
-
this.
|
|
13686
|
+
this.canvas.width = fullPageWidth;
|
|
13687
|
+
this.canvas.height = fullPageHeight;
|
|
13627
13688
|
this.ctx = this.canvas.getContext('2d');
|
|
13628
13689
|
if (this.ctx) {
|
|
13629
13690
|
// Set canvas styles
|
|
@@ -13643,6 +13704,8 @@ class AnnotationManager {
|
|
|
13643
13704
|
className: this.canvas.className,
|
|
13644
13705
|
width: this.canvas.width,
|
|
13645
13706
|
height: this.canvas.height,
|
|
13707
|
+
fullPageHeight: fullPageHeight,
|
|
13708
|
+
fullPageWidth: fullPageWidth,
|
|
13646
13709
|
inDOM: document.body.contains(this.canvas)
|
|
13647
13710
|
});
|
|
13648
13711
|
return this.canvas;
|
|
@@ -13661,8 +13724,80 @@ class AnnotationManager {
|
|
|
13661
13724
|
this.canvas.height = fullPageHeight;
|
|
13662
13725
|
}
|
|
13663
13726
|
}
|
|
13727
|
+
updateDrawingBounds(x, y) {
|
|
13728
|
+
if (!this.drawingBounds) {
|
|
13729
|
+
this.drawingBounds = {
|
|
13730
|
+
minX: x,
|
|
13731
|
+
minY: y,
|
|
13732
|
+
maxX: x,
|
|
13733
|
+
maxY: y
|
|
13734
|
+
};
|
|
13735
|
+
} else {
|
|
13736
|
+
this.drawingBounds.minX = Math.min(this.drawingBounds.minX, x);
|
|
13737
|
+
this.drawingBounds.minY = Math.min(this.drawingBounds.minY, y);
|
|
13738
|
+
this.drawingBounds.maxX = Math.max(this.drawingBounds.maxX, x);
|
|
13739
|
+
this.drawingBounds.maxY = Math.max(this.drawingBounds.maxY, y);
|
|
13740
|
+
}
|
|
13741
|
+
}
|
|
13742
|
+
checkAndAdjustCanvasMode() {
|
|
13743
|
+
if (!this.drawingBounds || !this.canvas) return;
|
|
13744
|
+
// Get current viewport bounds (accounting for scroll position)
|
|
13745
|
+
const viewportBounds = {
|
|
13746
|
+
minX: window.scrollX,
|
|
13747
|
+
minY: window.scrollY,
|
|
13748
|
+
maxX: window.scrollX + window.innerWidth,
|
|
13749
|
+
maxY: window.scrollY + window.innerHeight
|
|
13750
|
+
};
|
|
13751
|
+
// Check if all drawings are within viewport
|
|
13752
|
+
const isWithinViewport = this.drawingBounds.minX >= viewportBounds.minX && this.drawingBounds.maxX <= viewportBounds.maxX && this.drawingBounds.minY >= viewportBounds.minY && this.drawingBounds.maxY <= viewportBounds.maxY;
|
|
13753
|
+
// If currently in fullpage mode and drawings are within viewport, switch to viewport mode
|
|
13754
|
+
if (this.currentMode === 'fullpage' && isWithinViewport && this.annotations.length > 0) {
|
|
13755
|
+
console.log('🔄 Switching to viewport mode - all drawings within viewport', {
|
|
13756
|
+
drawingBounds: this.drawingBounds,
|
|
13757
|
+
viewportBounds
|
|
13758
|
+
});
|
|
13759
|
+
this.currentMode = 'viewport';
|
|
13760
|
+
this.updateCanvasSize('viewport');
|
|
13761
|
+
this.canvas.classList.add('viewport-mode');
|
|
13762
|
+
// Reset context properties after resize
|
|
13763
|
+
if (this.ctx) {
|
|
13764
|
+
this.ctx.lineCap = 'round';
|
|
13765
|
+
this.ctx.lineJoin = 'round';
|
|
13766
|
+
}
|
|
13767
|
+
this.redraw();
|
|
13768
|
+
}
|
|
13769
|
+
// If currently in viewport mode but drawings extend beyond, switch to fullpage mode
|
|
13770
|
+
else if (this.currentMode === 'viewport' && !isWithinViewport) {
|
|
13771
|
+
console.log('🔄 Switching to fullpage mode - drawings extend beyond viewport', {
|
|
13772
|
+
drawingBounds: this.drawingBounds,
|
|
13773
|
+
viewportBounds
|
|
13774
|
+
});
|
|
13775
|
+
this.currentMode = 'fullpage';
|
|
13776
|
+
this.updateCanvasSize('fullpage');
|
|
13777
|
+
this.canvas.classList.remove('viewport-mode');
|
|
13778
|
+
// Reset context properties after resize
|
|
13779
|
+
if (this.ctx) {
|
|
13780
|
+
this.ctx.lineCap = 'round';
|
|
13781
|
+
this.ctx.lineJoin = 'round';
|
|
13782
|
+
}
|
|
13783
|
+
this.redraw();
|
|
13784
|
+
}
|
|
13785
|
+
}
|
|
13664
13786
|
show(mode = 'fullpage') {
|
|
13665
13787
|
if (this.canvas && this.ctx) {
|
|
13788
|
+
// Set the current mode and reset drawing bounds for new annotation session
|
|
13789
|
+
this.currentMode = mode;
|
|
13790
|
+
this.drawingBounds = null;
|
|
13791
|
+
// Store initial scroll position
|
|
13792
|
+
this.initialScrollPosition = {
|
|
13793
|
+
x: window.scrollX,
|
|
13794
|
+
y: window.scrollY
|
|
13795
|
+
};
|
|
13796
|
+
// Add scroll listener to detect scrolling
|
|
13797
|
+
this.scrollListener = this.handleScroll.bind(this);
|
|
13798
|
+
window.addEventListener('scroll', this.scrollListener, {
|
|
13799
|
+
passive: true
|
|
13800
|
+
});
|
|
13666
13801
|
// Update canvas size to match current page dimensions
|
|
13667
13802
|
this.updateCanvasSize(mode);
|
|
13668
13803
|
// Reset context properties after resize
|
|
@@ -13689,11 +13824,51 @@ class AnnotationManager {
|
|
|
13689
13824
|
this.redraw();
|
|
13690
13825
|
}
|
|
13691
13826
|
}
|
|
13827
|
+
handleScroll() {
|
|
13828
|
+
if (!this.initialScrollPosition) return;
|
|
13829
|
+
// Check if user has scrolled significantly (more than 10 pixels)
|
|
13830
|
+
const scrollThreshold = 10;
|
|
13831
|
+
const scrollDeltaX = Math.abs(window.scrollX - this.initialScrollPosition.x);
|
|
13832
|
+
const scrollDeltaY = Math.abs(window.scrollY - this.initialScrollPosition.y);
|
|
13833
|
+
if (scrollDeltaX > scrollThreshold || scrollDeltaY > scrollThreshold) {
|
|
13834
|
+
// User scrolled - switch to fullpage mode if not already
|
|
13835
|
+
if (this.currentMode === 'viewport') {
|
|
13836
|
+
console.log('📜 User scrolled - switching to fullpage mode', {
|
|
13837
|
+
scrollDelta: {
|
|
13838
|
+
x: scrollDeltaX,
|
|
13839
|
+
y: scrollDeltaY
|
|
13840
|
+
},
|
|
13841
|
+
initialScroll: this.initialScrollPosition,
|
|
13842
|
+
currentScroll: {
|
|
13843
|
+
x: window.scrollX,
|
|
13844
|
+
y: window.scrollY
|
|
13845
|
+
}
|
|
13846
|
+
});
|
|
13847
|
+
this.currentMode = 'fullpage';
|
|
13848
|
+
this.updateCanvasSize('fullpage');
|
|
13849
|
+
if (this.canvas) {
|
|
13850
|
+
this.canvas.classList.remove('viewport-mode');
|
|
13851
|
+
}
|
|
13852
|
+
// Reset context properties after resize
|
|
13853
|
+
if (this.ctx) {
|
|
13854
|
+
this.ctx.lineCap = 'round';
|
|
13855
|
+
this.ctx.lineJoin = 'round';
|
|
13856
|
+
}
|
|
13857
|
+
this.redraw();
|
|
13858
|
+
}
|
|
13859
|
+
}
|
|
13860
|
+
}
|
|
13692
13861
|
hide() {
|
|
13693
13862
|
if (this.canvas) {
|
|
13694
13863
|
this.canvas.classList.remove('active');
|
|
13695
13864
|
this.canvas.classList.remove('viewport-mode');
|
|
13696
13865
|
}
|
|
13866
|
+
// Remove scroll listener
|
|
13867
|
+
if (this.scrollListener) {
|
|
13868
|
+
window.removeEventListener('scroll', this.scrollListener);
|
|
13869
|
+
this.scrollListener = null;
|
|
13870
|
+
}
|
|
13871
|
+
this.initialScrollPosition = null;
|
|
13697
13872
|
// Clean up any active text input
|
|
13698
13873
|
this.removeTextInput();
|
|
13699
13874
|
this.currentTextAnnotation = null;
|
|
@@ -13706,12 +13881,16 @@ class AnnotationManager {
|
|
|
13706
13881
|
}
|
|
13707
13882
|
handleMouseDown(e) {
|
|
13708
13883
|
const isViewportMode = this.canvas?.classList.contains('viewport-mode');
|
|
13884
|
+
// For fullpage mode (absolute positioning), we need to add scroll offset
|
|
13885
|
+
// For viewport mode (fixed positioning), we don't need scroll offset
|
|
13709
13886
|
const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
|
|
13710
13887
|
const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
|
|
13711
13888
|
// Handle text tool separately
|
|
13712
13889
|
if (this.currentTool === 'text') {
|
|
13713
13890
|
const x = e.clientX + scrollOffsetX;
|
|
13714
13891
|
const y = e.clientY + scrollOffsetY;
|
|
13892
|
+
// Update drawing bounds for text
|
|
13893
|
+
this.updateDrawingBounds(x, y);
|
|
13715
13894
|
// Check if clicking on existing text to edit
|
|
13716
13895
|
const clickedText = this.getTextAnnotationAt(x, y);
|
|
13717
13896
|
if (clickedText) {
|
|
@@ -13729,6 +13908,8 @@ class AnnotationManager {
|
|
|
13729
13908
|
x: this.startX,
|
|
13730
13909
|
y: this.startY
|
|
13731
13910
|
}];
|
|
13911
|
+
// Update drawing bounds with start position
|
|
13912
|
+
this.updateDrawingBounds(this.startX, this.startY);
|
|
13732
13913
|
}
|
|
13733
13914
|
handleMouseMove(e) {
|
|
13734
13915
|
if (!this.isDrawing || !this.ctx) return;
|
|
@@ -13737,6 +13918,8 @@ class AnnotationManager {
|
|
|
13737
13918
|
const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
|
|
13738
13919
|
const x = e.clientX + scrollOffsetX;
|
|
13739
13920
|
const y = e.clientY + scrollOffsetY;
|
|
13921
|
+
// Update drawing bounds with current position
|
|
13922
|
+
this.updateDrawingBounds(x, y);
|
|
13740
13923
|
if (this.currentTool === 'pen') {
|
|
13741
13924
|
this.currentPath.push({
|
|
13742
13925
|
x,
|
|
@@ -13761,6 +13944,8 @@ class AnnotationManager {
|
|
|
13761
13944
|
const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
|
|
13762
13945
|
const x = e.clientX + scrollOffsetX;
|
|
13763
13946
|
const y = e.clientY + scrollOffsetY;
|
|
13947
|
+
// Update drawing bounds with final position
|
|
13948
|
+
this.updateDrawingBounds(x, y);
|
|
13764
13949
|
// Save the annotation
|
|
13765
13950
|
if (this.currentTool === 'pen') {
|
|
13766
13951
|
this.annotations.push({
|
|
@@ -13788,6 +13973,8 @@ class AnnotationManager {
|
|
|
13788
13973
|
color: this.currentColor
|
|
13789
13974
|
});
|
|
13790
13975
|
}
|
|
13976
|
+
// Check if we need to adjust canvas mode based on drawing location
|
|
13977
|
+
this.checkAndAdjustCanvasMode();
|
|
13791
13978
|
this.redraw();
|
|
13792
13979
|
}
|
|
13793
13980
|
handleTouchStart(e) {
|
|
@@ -13858,8 +14045,7 @@ class AnnotationManager {
|
|
|
13858
14045
|
this.textInput = document.createElement('input');
|
|
13859
14046
|
this.textInput.type = 'text';
|
|
13860
14047
|
this.textInput.className = 'uxbert-text-input';
|
|
13861
|
-
|
|
13862
|
-
// Position relative to the document, accounting for scroll
|
|
14048
|
+
// Position relative to the document (absolute positioning)
|
|
13863
14049
|
this.textInput.style.left = `${x}px`;
|
|
13864
14050
|
this.textInput.style.top = `${y}px`;
|
|
13865
14051
|
this.textInput.style.transform = 'translate(0, 0)';
|
|
@@ -13923,6 +14109,8 @@ class AnnotationManager {
|
|
|
13923
14109
|
if (text) {
|
|
13924
14110
|
this.currentTextAnnotation.text = text;
|
|
13925
14111
|
this.annotations.push(this.currentTextAnnotation);
|
|
14112
|
+
// Check if we need to adjust canvas mode based on drawing location
|
|
14113
|
+
this.checkAndAdjustCanvasMode();
|
|
13926
14114
|
this.redraw();
|
|
13927
14115
|
}
|
|
13928
14116
|
}
|
|
@@ -14003,9 +14191,13 @@ class AnnotationManager {
|
|
|
14003
14191
|
}
|
|
14004
14192
|
clear() {
|
|
14005
14193
|
this.annotations = [];
|
|
14194
|
+
this.drawingBounds = null;
|
|
14006
14195
|
this.redraw();
|
|
14007
14196
|
}
|
|
14008
|
-
|
|
14197
|
+
getCurrentMode() {
|
|
14198
|
+
return this.currentMode;
|
|
14199
|
+
}
|
|
14200
|
+
async exportAnnotatedScreenshot(baseScreenshot, mode) {
|
|
14009
14201
|
// Create a temporary canvas to combine screenshot + annotations
|
|
14010
14202
|
const tempCanvas = document.createElement('canvas');
|
|
14011
14203
|
const img = new Image();
|
|
@@ -14019,8 +14211,29 @@ class AnnotationManager {
|
|
|
14019
14211
|
if (tempCtx && this.canvas) {
|
|
14020
14212
|
// Draw the base screenshot
|
|
14021
14213
|
tempCtx.drawImage(img, 0, 0);
|
|
14022
|
-
//
|
|
14023
|
-
|
|
14214
|
+
// If mode is specified and different from current canvas mode, we need to adjust
|
|
14215
|
+
const isCanvasInViewportMode = this.canvas.classList.contains('viewport-mode');
|
|
14216
|
+
const isTargetFullpage = mode === 'fullpage';
|
|
14217
|
+
if (isCanvasInViewportMode && isTargetFullpage) {
|
|
14218
|
+
// User drew in viewport mode, but we're capturing fullpage
|
|
14219
|
+
// Need to offset annotations by current scroll position
|
|
14220
|
+
const scrollOffsetX = window.scrollX;
|
|
14221
|
+
const scrollOffsetY = window.scrollY;
|
|
14222
|
+
// Create a temporary canvas for adjusted annotations
|
|
14223
|
+
const adjustedCanvas = document.createElement('canvas');
|
|
14224
|
+
adjustedCanvas.width = tempCanvas.width;
|
|
14225
|
+
adjustedCanvas.height = tempCanvas.height;
|
|
14226
|
+
const adjustedCtx = adjustedCanvas.getContext('2d');
|
|
14227
|
+
if (adjustedCtx) {
|
|
14228
|
+
// Draw annotations with scroll offset
|
|
14229
|
+
adjustedCtx.drawImage(this.canvas, scrollOffsetX, scrollOffsetY);
|
|
14230
|
+
// Draw the adjusted annotations on top of screenshot
|
|
14231
|
+
tempCtx.drawImage(adjustedCanvas, 0, 0);
|
|
14232
|
+
}
|
|
14233
|
+
} else {
|
|
14234
|
+
// Draw annotations directly on top
|
|
14235
|
+
tempCtx.drawImage(this.canvas, 0, 0);
|
|
14236
|
+
}
|
|
14024
14237
|
resolve(tempCanvas.toDataURL('image/png'));
|
|
14025
14238
|
}
|
|
14026
14239
|
};
|
|
@@ -14066,14 +14279,15 @@ function ReportlyInner() {
|
|
|
14066
14279
|
React.useEffect(() => {
|
|
14067
14280
|
if (annotationRef.current) {
|
|
14068
14281
|
if (state.isAnnotating) {
|
|
14069
|
-
|
|
14070
|
-
|
|
14282
|
+
// Start in fullpage mode - it will auto-switch to viewport if drawings stay within viewport
|
|
14283
|
+
console.log('Showing canvas in fullpage mode (will auto-adjust based on drawing location)');
|
|
14284
|
+
annotationRef.current.show('fullpage');
|
|
14071
14285
|
} else {
|
|
14072
14286
|
console.log('Hiding canvas');
|
|
14073
14287
|
annotationRef.current.hide();
|
|
14074
14288
|
}
|
|
14075
14289
|
}
|
|
14076
|
-
}, [state.isAnnotating
|
|
14290
|
+
}, [state.isAnnotating]);
|
|
14077
14291
|
const handleUndo = () => {
|
|
14078
14292
|
annotationRef.current?.undo();
|
|
14079
14293
|
};
|
|
@@ -14081,14 +14295,31 @@ function ReportlyInner() {
|
|
|
14081
14295
|
annotationRef.current?.clear();
|
|
14082
14296
|
};
|
|
14083
14297
|
const handleDone = async () => {
|
|
14084
|
-
if (!annotationRef.current
|
|
14298
|
+
if (!annotationRef.current) return;
|
|
14085
14299
|
try {
|
|
14086
|
-
const
|
|
14300
|
+
const Screenshot = (await Promise.resolve().then(function () { return screenshot; })).default;
|
|
14301
|
+
// Use the current mode from annotation manager (it has auto-adjusted based on drawing location)
|
|
14302
|
+
const captureMode = annotationRef.current.getCurrentMode();
|
|
14303
|
+
console.log('Using capture mode from annotation manager:', captureMode);
|
|
14304
|
+
// Hide the annotation canvas temporarily
|
|
14305
|
+
annotationRef.current.hide();
|
|
14306
|
+
// Capture the screenshot
|
|
14307
|
+
const screenshotService = new Screenshot();
|
|
14308
|
+
const baseScreenshot = await screenshotService.capture(captureMode);
|
|
14309
|
+
// Export the annotated screenshot (combine base screenshot + annotations)
|
|
14310
|
+
// Pass the capture mode so annotations can be positioned correctly
|
|
14311
|
+
const annotatedScreenshot = await annotationRef.current.exportAnnotatedScreenshot(baseScreenshot, captureMode);
|
|
14312
|
+
// Update the screenshot in state
|
|
14087
14313
|
updateScreenshot(annotatedScreenshot);
|
|
14314
|
+
// End annotation mode and show the modal
|
|
14088
14315
|
endAnnotation();
|
|
14089
14316
|
} catch (error) {
|
|
14090
14317
|
console.error('Failed to finish annotation:', error);
|
|
14091
|
-
alert('Failed to
|
|
14318
|
+
alert('Failed to capture screenshot. Please try again.');
|
|
14319
|
+
// Show canvas again in case of error
|
|
14320
|
+
if (annotationRef.current) {
|
|
14321
|
+
annotationRef.current.show('fullpage'); // Default back to fullpage mode on error
|
|
14322
|
+
}
|
|
14092
14323
|
}
|
|
14093
14324
|
};
|
|
14094
14325
|
const handleExit = () => {
|