@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.
@@ -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,4BAkX7D;AAED,eAAe,UAAU,CAAC"}
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;AAkFD,wBAAgB,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,aAAa,qBAMjD;AAED,eAAe,QAAQ,CAAC"}
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,EAAe,MAAM,OAAO,CAAC;AAC7F,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"}
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
- exportAnnotatedScreenshot(baseScreenshot: string): Promise<string>;
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;;IAiB1G,YAAY,IAAI,iBAAiB;IAkCjC,OAAO,CAAC,gBAAgB;IA8BxB,IAAI,CAAC,IAAI,GAAE,UAAU,GAAG,UAAuB,GAAG,IAAI;IAgCtD,IAAI,IAAI,IAAI;IAUZ,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI;IAInC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAI7B,OAAO,CAAC,eAAe;IA4BvB,OAAO,CAAC,eAAe;IAwBvB,OAAO,CAAC,aAAa;IA0CrB,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;IA+DvB,OAAO,CAAC,kBAAkB;IAkB1B,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,eAAe;IAkBvB,OAAO,CAAC,mBAAmB;IAwB3B,OAAO,CAAC,QAAQ;IAuBhB,OAAO,CAAC,MAAM;IAmBd,IAAI,IAAI,IAAI;IAOZ,KAAK,IAAI,IAAI;IAKP,yBAAyB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IA0BxE,OAAO,IAAI,IAAI;CAOhB;AAED,eAAe,iBAAiB,CAAC"}
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;IAKjC,YAAY,CAAC,SAAS,EAAE,aAAa,GAAG,MAAM;IAsB9C,OAAO,CAAC,SAAS;IAmBjB,OAAO,CAAC,eAAe;IAUvB,cAAc,IAAI,UAAU,EAAE;IAI9B,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAKvC,gBAAgB,IAAI,IAAI;IAKxB,eAAe,IAAI,IAAI;IAiBvB;;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"}
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 = this.loadSavedIssues();
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
- const blob = new Blob([json], {
307
- type: 'application/json'
308
- });
309
- const url = URL.createObjectURL(blob);
310
- // Create download link
311
- const link = document.createElement('a');
312
- link.href = url;
313
- link.download = `issue-${Date.now()}.json`;
314
- document.body.appendChild(link);
315
- link.click();
316
- document.body.removeChild(link);
317
- // Clean up
318
- URL.revokeObjectURL(url);
319
- // Save to localStorage
320
- this.saveIssue(issueData);
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
- localStorage.setItem('uxbert-saved-issues', JSON.stringify(this.savedIssues));
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
- localStorage.removeItem('uxbert-saved-issues');
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
- openModal
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: openModal,
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: closeModal,
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
- // Set canvas to full page dimensions
13626
- this.updateCanvasSize();
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
- this.textInput.style.position = 'absolute';
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
- async exportAnnotatedScreenshot(baseScreenshot) {
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
- // Draw annotations on top
14023
- tempCtx.drawImage(this.canvas, 0, 0);
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
- console.log('Showing canvas in mode:', state.captureMode);
14070
- annotationRef.current.show(state.captureMode);
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, state.captureMode]);
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 || !state.screenshot) return;
14298
+ if (!annotationRef.current) return;
14085
14299
  try {
14086
- const annotatedScreenshot = await annotationRef.current.exportAnnotatedScreenshot(state.screenshot);
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 process annotations. Please try again.');
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 = () => {