@uxbertlabs/reportly 1.0.21 → 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"}
@@ -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"}
package/dist/index.cjs.js CHANGED
@@ -9497,6 +9497,11 @@ class Screenshot {
9497
9497
  }
9498
9498
  }
9499
9499
 
9500
+ var screenshot = /*#__PURE__*/Object.freeze({
9501
+ __proto__: null,
9502
+ default: Screenshot
9503
+ });
9504
+
9500
9505
  const initialState = {
9501
9506
  isOpen: false,
9502
9507
  isAnnotating: false,
@@ -13107,7 +13112,7 @@ function FloatingButton({
13107
13112
  }) {
13108
13113
  const {
13109
13114
  state,
13110
- openModal
13115
+ startAnnotation
13111
13116
  } = useReportly();
13112
13117
  const {
13113
13118
  config
@@ -13126,7 +13131,7 @@ function FloatingButton({
13126
13131
  style: {
13127
13132
  zIndex: "var(--uxbert-z-button)"
13128
13133
  },
13129
- onClick: openModal,
13134
+ onClick: startAnnotation,
13130
13135
  title: "Report an issue",
13131
13136
  "aria-label": "Report an issue"
13132
13137
  }, /*#__PURE__*/React.createElement(Bug, {
@@ -13163,7 +13168,8 @@ function IssueModal({
13163
13168
  retakeScreenshot,
13164
13169
  startAnnotation,
13165
13170
  submitIssue,
13166
- submitToN8n
13171
+ submitToN8n,
13172
+ reset
13167
13173
  } = useReportly();
13168
13174
  const [formData, setFormData] = React.useState({
13169
13175
  title: "",
@@ -13180,6 +13186,27 @@ function IssueModal({
13180
13186
  [field]: value
13181
13187
  }));
13182
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]);
13183
13210
  const handleCapture = React.useCallback(async () => {
13184
13211
  try {
13185
13212
  await captureScreenshot(captureMode);
@@ -13209,6 +13236,7 @@ function IssueModal({
13209
13236
  try {
13210
13237
  setIsSubmitting(true);
13211
13238
  submitIssue(formData);
13239
+ // Form data is cleared by the submitIssue function which calls reset()
13212
13240
  setFormData({
13213
13241
  title: "",
13214
13242
  description: "",
@@ -13278,7 +13306,7 @@ function IssueModal({
13278
13306
  })), /*#__PURE__*/React.createElement("h2", {
13279
13307
  className: "text-xl font-semibold"
13280
13308
  }, "Report Issue")), /*#__PURE__*/React.createElement("button", {
13281
- onClick: closeModal,
13309
+ onClick: handleClose,
13282
13310
  className: "p-2 rounded-md hover:bg-muted transition-colors cursor-pointer",
13283
13311
  "aria-label": "Close"
13284
13312
  }, /*#__PURE__*/React.createElement(X, {
@@ -13643,12 +13671,20 @@ class AnnotationManager {
13643
13671
  this.currentPath = [];
13644
13672
  this.textInput = null;
13645
13673
  this.currentTextAnnotation = null;
13674
+ this.drawingBounds = null;
13675
+ this.currentMode = 'fullpage';
13676
+ this.scrollListener = null;
13677
+ this.initialScrollPosition = null;
13646
13678
  }
13647
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
13648
13684
  this.canvas = document.createElement('canvas');
13649
13685
  this.canvas.className = 'uxbert-canvas-overlay';
13650
- // Set canvas to full page dimensions
13651
- this.updateCanvasSize();
13686
+ this.canvas.width = fullPageWidth;
13687
+ this.canvas.height = fullPageHeight;
13652
13688
  this.ctx = this.canvas.getContext('2d');
13653
13689
  if (this.ctx) {
13654
13690
  // Set canvas styles
@@ -13668,6 +13704,8 @@ class AnnotationManager {
13668
13704
  className: this.canvas.className,
13669
13705
  width: this.canvas.width,
13670
13706
  height: this.canvas.height,
13707
+ fullPageHeight: fullPageHeight,
13708
+ fullPageWidth: fullPageWidth,
13671
13709
  inDOM: document.body.contains(this.canvas)
13672
13710
  });
13673
13711
  return this.canvas;
@@ -13686,8 +13724,80 @@ class AnnotationManager {
13686
13724
  this.canvas.height = fullPageHeight;
13687
13725
  }
13688
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
+ }
13689
13786
  show(mode = 'fullpage') {
13690
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
+ });
13691
13801
  // Update canvas size to match current page dimensions
13692
13802
  this.updateCanvasSize(mode);
13693
13803
  // Reset context properties after resize
@@ -13714,11 +13824,51 @@ class AnnotationManager {
13714
13824
  this.redraw();
13715
13825
  }
13716
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
+ }
13717
13861
  hide() {
13718
13862
  if (this.canvas) {
13719
13863
  this.canvas.classList.remove('active');
13720
13864
  this.canvas.classList.remove('viewport-mode');
13721
13865
  }
13866
+ // Remove scroll listener
13867
+ if (this.scrollListener) {
13868
+ window.removeEventListener('scroll', this.scrollListener);
13869
+ this.scrollListener = null;
13870
+ }
13871
+ this.initialScrollPosition = null;
13722
13872
  // Clean up any active text input
13723
13873
  this.removeTextInput();
13724
13874
  this.currentTextAnnotation = null;
@@ -13731,12 +13881,16 @@ class AnnotationManager {
13731
13881
  }
13732
13882
  handleMouseDown(e) {
13733
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
13734
13886
  const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
13735
13887
  const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
13736
13888
  // Handle text tool separately
13737
13889
  if (this.currentTool === 'text') {
13738
13890
  const x = e.clientX + scrollOffsetX;
13739
13891
  const y = e.clientY + scrollOffsetY;
13892
+ // Update drawing bounds for text
13893
+ this.updateDrawingBounds(x, y);
13740
13894
  // Check if clicking on existing text to edit
13741
13895
  const clickedText = this.getTextAnnotationAt(x, y);
13742
13896
  if (clickedText) {
@@ -13754,6 +13908,8 @@ class AnnotationManager {
13754
13908
  x: this.startX,
13755
13909
  y: this.startY
13756
13910
  }];
13911
+ // Update drawing bounds with start position
13912
+ this.updateDrawingBounds(this.startX, this.startY);
13757
13913
  }
13758
13914
  handleMouseMove(e) {
13759
13915
  if (!this.isDrawing || !this.ctx) return;
@@ -13762,6 +13918,8 @@ class AnnotationManager {
13762
13918
  const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
13763
13919
  const x = e.clientX + scrollOffsetX;
13764
13920
  const y = e.clientY + scrollOffsetY;
13921
+ // Update drawing bounds with current position
13922
+ this.updateDrawingBounds(x, y);
13765
13923
  if (this.currentTool === 'pen') {
13766
13924
  this.currentPath.push({
13767
13925
  x,
@@ -13786,6 +13944,8 @@ class AnnotationManager {
13786
13944
  const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
13787
13945
  const x = e.clientX + scrollOffsetX;
13788
13946
  const y = e.clientY + scrollOffsetY;
13947
+ // Update drawing bounds with final position
13948
+ this.updateDrawingBounds(x, y);
13789
13949
  // Save the annotation
13790
13950
  if (this.currentTool === 'pen') {
13791
13951
  this.annotations.push({
@@ -13813,6 +13973,8 @@ class AnnotationManager {
13813
13973
  color: this.currentColor
13814
13974
  });
13815
13975
  }
13976
+ // Check if we need to adjust canvas mode based on drawing location
13977
+ this.checkAndAdjustCanvasMode();
13816
13978
  this.redraw();
13817
13979
  }
13818
13980
  handleTouchStart(e) {
@@ -13883,8 +14045,7 @@ class AnnotationManager {
13883
14045
  this.textInput = document.createElement('input');
13884
14046
  this.textInput.type = 'text';
13885
14047
  this.textInput.className = 'uxbert-text-input';
13886
- this.textInput.style.position = 'absolute';
13887
- // Position relative to the document, accounting for scroll
14048
+ // Position relative to the document (absolute positioning)
13888
14049
  this.textInput.style.left = `${x}px`;
13889
14050
  this.textInput.style.top = `${y}px`;
13890
14051
  this.textInput.style.transform = 'translate(0, 0)';
@@ -13948,6 +14109,8 @@ class AnnotationManager {
13948
14109
  if (text) {
13949
14110
  this.currentTextAnnotation.text = text;
13950
14111
  this.annotations.push(this.currentTextAnnotation);
14112
+ // Check if we need to adjust canvas mode based on drawing location
14113
+ this.checkAndAdjustCanvasMode();
13951
14114
  this.redraw();
13952
14115
  }
13953
14116
  }
@@ -14028,9 +14191,13 @@ class AnnotationManager {
14028
14191
  }
14029
14192
  clear() {
14030
14193
  this.annotations = [];
14194
+ this.drawingBounds = null;
14031
14195
  this.redraw();
14032
14196
  }
14033
- async exportAnnotatedScreenshot(baseScreenshot) {
14197
+ getCurrentMode() {
14198
+ return this.currentMode;
14199
+ }
14200
+ async exportAnnotatedScreenshot(baseScreenshot, mode) {
14034
14201
  // Create a temporary canvas to combine screenshot + annotations
14035
14202
  const tempCanvas = document.createElement('canvas');
14036
14203
  const img = new Image();
@@ -14044,8 +14211,29 @@ class AnnotationManager {
14044
14211
  if (tempCtx && this.canvas) {
14045
14212
  // Draw the base screenshot
14046
14213
  tempCtx.drawImage(img, 0, 0);
14047
- // Draw annotations on top
14048
- 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
+ }
14049
14237
  resolve(tempCanvas.toDataURL('image/png'));
14050
14238
  }
14051
14239
  };
@@ -14091,14 +14279,15 @@ function ReportlyInner() {
14091
14279
  React.useEffect(() => {
14092
14280
  if (annotationRef.current) {
14093
14281
  if (state.isAnnotating) {
14094
- console.log('Showing canvas in mode:', state.captureMode);
14095
- 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');
14096
14285
  } else {
14097
14286
  console.log('Hiding canvas');
14098
14287
  annotationRef.current.hide();
14099
14288
  }
14100
14289
  }
14101
- }, [state.isAnnotating, state.captureMode]);
14290
+ }, [state.isAnnotating]);
14102
14291
  const handleUndo = () => {
14103
14292
  annotationRef.current?.undo();
14104
14293
  };
@@ -14106,14 +14295,31 @@ function ReportlyInner() {
14106
14295
  annotationRef.current?.clear();
14107
14296
  };
14108
14297
  const handleDone = async () => {
14109
- if (!annotationRef.current || !state.screenshot) return;
14298
+ if (!annotationRef.current) return;
14110
14299
  try {
14111
- 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
14112
14313
  updateScreenshot(annotatedScreenshot);
14314
+ // End annotation mode and show the modal
14113
14315
  endAnnotation();
14114
14316
  } catch (error) {
14115
14317
  console.error('Failed to finish annotation:', error);
14116
- 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
+ }
14117
14323
  }
14118
14324
  };
14119
14325
  const handleExit = () => {