@uxbertlabs/reportly 1.0.5 → 1.0.6

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/reportly.js CHANGED
@@ -83,6 +83,7 @@ var Reportly = (function () {
83
83
  this.screenshot = null;
84
84
  this.annotations = [];
85
85
  this.listeners = {};
86
+ this.captureMode = 'viewport';
86
87
  }
87
88
  setState(newState) {
88
89
  this.currentState = newState;
@@ -112,11 +113,18 @@ var Reportly = (function () {
112
113
  clearAnnotations() {
113
114
  this.annotations = [];
114
115
  }
116
+ setCaptureMode(mode) {
117
+ this.captureMode = mode;
118
+ }
119
+ getCaptureMode() {
120
+ return this.captureMode;
121
+ }
115
122
  reset() {
116
123
  this.currentState = STATE.IDLE;
117
124
  this.currentIssue = null;
118
125
  this.screenshot = null;
119
126
  this.annotations = [];
127
+ this.captureMode = 'viewport';
120
128
  }
121
129
  // Event system
122
130
  on(event, callback) {
@@ -190,6 +198,20 @@ var Reportly = (function () {
190
198
  </div>
191
199
 
192
200
  <form class="uxbert-form" id="uxbert-issue-form">
201
+ <div class="uxbert-form-group">
202
+ <label class="uxbert-form-label">Capture Mode</label>
203
+ <div class="uxbert-capture-mode">
204
+ <label class="uxbert-radio-label">
205
+ <input type="radio" name="capture-mode" value="viewport" id="uxbert-capture-viewport" checked />
206
+ <span>Current View</span>
207
+ </label>
208
+ <label class="uxbert-radio-label">
209
+ <input type="radio" name="capture-mode" value="fullpage" id="uxbert-capture-fullpage" />
210
+ <span>Full Page</span>
211
+ </label>
212
+ </div>
213
+ </div>
214
+
193
215
  <div class="uxbert-form-group">
194
216
  <label class="uxbert-form-label" for="uxbert-title">Issue Title *</label>
195
217
  <input
@@ -220,6 +242,12 @@ var Reportly = (function () {
220
242
  </select>
221
243
  </div>
222
244
 
245
+ <div class="uxbert-capture-action" id="uxbert-capture-action">
246
+ <button type="button" class="uxbert-btn uxbert-btn-primary" id="uxbert-capture-btn">
247
+ 📸 Take Screenshot
248
+ </button>
249
+ </div>
250
+
223
251
  <div class="uxbert-screenshot-preview" id="uxbert-screenshot-container" style="display: none;">
224
252
  <img id="uxbert-screenshot-img" src="" alt="Screenshot" />
225
253
  <div class="uxbert-screenshot-actions">
@@ -236,7 +264,7 @@ var Reportly = (function () {
236
264
  <button type="button" class="uxbert-btn uxbert-btn-secondary" id="uxbert-cancel-btn">
237
265
  Cancel
238
266
  </button>
239
- <button type="submit" class="uxbert-btn uxbert-btn-primary">
267
+ <button type="submit" class="uxbert-btn uxbert-btn-primary" id="uxbert-submit-btn">
240
268
  📥 Download JSON
241
269
  </button>
242
270
  </div>
@@ -269,6 +297,13 @@ var Reportly = (function () {
269
297
  e.preventDefault();
270
298
  this.handleSubmit();
271
299
  });
300
+ // Capture button
301
+ const captureBtn = this.modal.querySelector('#uxbert-capture-btn');
302
+ captureBtn.addEventListener('click', () => {
303
+ if (this.callbacks.onCapture) {
304
+ this.callbacks.onCapture();
305
+ }
306
+ });
272
307
  // Annotate button
273
308
  const annotateBtn = this.modal.querySelector('#uxbert-annotate-btn');
274
309
  annotateBtn.addEventListener('click', () => {
@@ -321,14 +356,26 @@ var Reportly = (function () {
321
356
  return;
322
357
  const container = this.modal.querySelector('#uxbert-screenshot-container');
323
358
  const img = this.modal.querySelector('#uxbert-screenshot-img');
359
+ const captureAction = this.modal.querySelector('#uxbert-capture-action');
360
+ const submitBtn = this.modal.querySelector('#uxbert-submit-btn');
324
361
  if (screenshot) {
325
362
  img.src = screenshot;
326
363
  container.style.display = 'block';
364
+ captureAction.style.display = 'none';
365
+ submitBtn.disabled = false;
327
366
  }
328
367
  else {
329
368
  container.style.display = 'none';
369
+ captureAction.style.display = 'block';
370
+ submitBtn.disabled = true;
330
371
  }
331
372
  }
373
+ getCaptureMode() {
374
+ if (!this.modal)
375
+ return 'viewport';
376
+ const viewportRadio = this.modal.querySelector('#uxbert-capture-viewport');
377
+ return viewportRadio.checked ? 'viewport' : 'fullpage';
378
+ }
332
379
  reset() {
333
380
  if (!this.modal)
334
381
  return;
@@ -9403,26 +9450,43 @@ var Reportly = (function () {
9403
9450
  constructor() {
9404
9451
  this.currentScreenshot = null;
9405
9452
  }
9406
- async capture() {
9453
+ async capture(mode = 'fullpage') {
9407
9454
  try {
9408
9455
  // Hide UXbert UI elements before capturing
9409
9456
  this.hideUXbertElements();
9410
- // Scroll to top to capture full page
9411
9457
  const originalScrollY = window.scrollY;
9412
- window.scrollTo(0, 0);
9413
- // Get full page dimensions
9414
- const fullPageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
9415
- const fullPageWidth = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
9416
- // Capture the full page
9417
- const canvas = await html2canvas(document.body, {
9418
- allowTaint: true,
9419
- useCORS: true,
9420
- logging: false,
9421
- width: fullPageWidth,
9422
- height: fullPageHeight,
9423
- });
9424
- // Restore scroll position
9425
- window.scrollTo(0, originalScrollY);
9458
+ let canvas;
9459
+ if (mode === 'viewport') {
9460
+ // Capture only the current viewport
9461
+ canvas = await html2canvas(document.body, {
9462
+ allowTaint: true,
9463
+ useCORS: true,
9464
+ logging: false,
9465
+ width: window.innerWidth,
9466
+ height: window.innerHeight,
9467
+ windowWidth: window.innerWidth,
9468
+ windowHeight: window.innerHeight,
9469
+ x: window.scrollX,
9470
+ y: window.scrollY,
9471
+ });
9472
+ }
9473
+ else {
9474
+ // Scroll to top to capture full page
9475
+ window.scrollTo(0, 0);
9476
+ // Get full page dimensions
9477
+ const fullPageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
9478
+ const fullPageWidth = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
9479
+ // Capture the full page
9480
+ canvas = await html2canvas(document.body, {
9481
+ allowTaint: true,
9482
+ useCORS: true,
9483
+ logging: false,
9484
+ width: fullPageWidth,
9485
+ height: fullPageHeight,
9486
+ });
9487
+ // Restore scroll position
9488
+ window.scrollTo(0, originalScrollY);
9489
+ }
9426
9490
  // Show UXbert UI elements again
9427
9491
  this.showUXbertElements();
9428
9492
  // Convert to base64
@@ -9498,29 +9562,46 @@ var Reportly = (function () {
9498
9562
  document.body.appendChild(this.canvas);
9499
9563
  return this.canvas;
9500
9564
  }
9501
- updateCanvasSize() {
9565
+ updateCanvasSize(mode = 'fullpage') {
9502
9566
  if (!this.canvas)
9503
9567
  return;
9504
- // Get full page dimensions
9505
- const fullPageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
9506
- const fullPageWidth = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
9507
- this.canvas.width = fullPageWidth;
9508
- this.canvas.height = fullPageHeight;
9568
+ if (mode === 'viewport') {
9569
+ // Set canvas to viewport dimensions
9570
+ this.canvas.width = window.innerWidth;
9571
+ this.canvas.height = window.innerHeight;
9572
+ }
9573
+ else {
9574
+ // Get full page dimensions
9575
+ const fullPageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
9576
+ const fullPageWidth = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
9577
+ this.canvas.width = fullPageWidth;
9578
+ this.canvas.height = fullPageHeight;
9579
+ }
9509
9580
  }
9510
- show() {
9581
+ show(mode = 'fullpage') {
9511
9582
  if (this.canvas && this.ctx) {
9512
9583
  // Update canvas size to match current page dimensions
9513
- this.updateCanvasSize();
9584
+ this.updateCanvasSize(mode);
9514
9585
  // Reset context properties after resize
9515
9586
  this.ctx.lineCap = 'round';
9516
9587
  this.ctx.lineJoin = 'round';
9517
9588
  this.canvas.classList.add('active');
9589
+ // If viewport mode, add viewport-mode class
9590
+ if (mode === 'viewport') {
9591
+ this.canvas.classList.add('viewport-mode');
9592
+ // Note: We don't disable scrolling in viewport mode to allow users to scroll
9593
+ // and annotate different parts of the viewport
9594
+ }
9595
+ else {
9596
+ this.canvas.classList.remove('viewport-mode');
9597
+ }
9518
9598
  this.redraw();
9519
9599
  }
9520
9600
  }
9521
9601
  hide() {
9522
9602
  if (this.canvas) {
9523
9603
  this.canvas.classList.remove('active');
9604
+ this.canvas.classList.remove('viewport-mode');
9524
9605
  }
9525
9606
  // Clean up any active text input
9526
9607
  this.removeTextInput();
@@ -9533,10 +9614,13 @@ var Reportly = (function () {
9533
9614
  this.currentColor = color;
9534
9615
  }
9535
9616
  handleMouseDown(e) {
9617
+ const isViewportMode = this.canvas?.classList.contains('viewport-mode');
9618
+ const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
9619
+ const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
9536
9620
  // Handle text tool separately
9537
9621
  if (this.currentTool === 'text') {
9538
- const x = e.clientX + window.scrollX;
9539
- const y = e.clientY + window.scrollY;
9622
+ const x = e.clientX + scrollOffsetX;
9623
+ const y = e.clientY + scrollOffsetY;
9540
9624
  // Check if clicking on existing text to edit
9541
9625
  const clickedText = this.getTextAnnotationAt(x, y);
9542
9626
  if (clickedText) {
@@ -9548,15 +9632,18 @@ var Reportly = (function () {
9548
9632
  return;
9549
9633
  }
9550
9634
  this.isDrawing = true;
9551
- this.startX = e.clientX + window.scrollX;
9552
- this.startY = e.clientY + window.scrollY;
9635
+ this.startX = e.clientX + scrollOffsetX;
9636
+ this.startY = e.clientY + scrollOffsetY;
9553
9637
  this.currentPath = [{ x: this.startX, y: this.startY }];
9554
9638
  }
9555
9639
  handleMouseMove(e) {
9556
9640
  if (!this.isDrawing || !this.ctx)
9557
9641
  return;
9558
- const x = e.clientX + window.scrollX;
9559
- const y = e.clientY + window.scrollY;
9642
+ const isViewportMode = this.canvas?.classList.contains('viewport-mode');
9643
+ const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
9644
+ const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
9645
+ const x = e.clientX + scrollOffsetX;
9646
+ const y = e.clientY + scrollOffsetY;
9560
9647
  if (this.currentTool === 'pen') {
9561
9648
  this.currentPath.push({ x, y });
9562
9649
  this.redraw();
@@ -9576,8 +9663,11 @@ var Reportly = (function () {
9576
9663
  if (!this.isDrawing)
9577
9664
  return;
9578
9665
  this.isDrawing = false;
9579
- const x = e.clientX + window.scrollX;
9580
- const y = e.clientY + window.scrollY;
9666
+ const isViewportMode = this.canvas?.classList.contains('viewport-mode');
9667
+ const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
9668
+ const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
9669
+ const x = e.clientX + scrollOffsetX;
9670
+ const y = e.clientY + scrollOffsetY;
9581
9671
  // Save the annotation
9582
9672
  if (this.currentTool === 'pen') {
9583
9673
  this.annotations.push({
@@ -10050,7 +10140,7 @@ var Reportly = (function () {
10050
10140
  }
10051
10141
  }
10052
10142
 
10053
- var css_248z = ":root{--uxbert-primary:#4f46e5;--uxbert-primary-hover:#4338ca;--uxbert-danger:#ef4444;--uxbert-success:#10b981;--uxbert-bg:#fff;--uxbert-text:#1f2937;--uxbert-border:#e5e7eb;--uxbert-shadow:0 10px 25px rgba(0,0,0,.1);--uxbert-z-button:999999;--uxbert-z-modal:1000000;--uxbert-z-canvas:1000001;--uxbert-z-toolbar:1000002}[data-theme=dark]{--uxbert-bg:#1f2937;--uxbert-text:#f9fafb;--uxbert-border:#374151}.uxbert-fab{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:flex;font-size:24px;height:56px;justify-content:center;position:fixed;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-button)}.uxbert-fab:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-fab.bottom-right{bottom:24px;right:24px}.uxbert-fab.bottom-left{bottom:24px;left:24px}.uxbert-fab.top-right{right:24px;top:24px}.uxbert-fab.top-left{left:24px;top:24px}.uxbert-overlay{align-items:center;animation:fadeIn .3s ease;background:rgba(0,0,0,.5);display:none;height:100%;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:var(--uxbert-z-modal)}.uxbert-overlay.active{display:flex}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.uxbert-modal{animation:slideUp .3s ease;background:var(--uxbert-bg);border-radius:12px;box-shadow:var(--uxbert-shadow);color:var(--uxbert-text);max-height:90vh;max-width:600px;overflow-y:auto;padding:24px;width:90%}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.uxbert-modal-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.uxbert-modal-title{font-size:20px;font-weight:600;margin:0}.uxbert-modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:24px;height:32px;justify-content:center;padding:0;width:32px}.uxbert-modal-close:hover{background:var(--uxbert-border)}.uxbert-form-group{margin-bottom:16px}.uxbert-form-label{display:block;font-size:14px;font-weight:500;margin-bottom:8px}.uxbert-form-input,.uxbert-form-select,.uxbert-form-textarea{background:var(--uxbert-bg);border:1px solid var(--uxbert-border);border-radius:6px;box-sizing:border-box;color:var(--uxbert-text);font-family:inherit;font-size:14px;padding:10px;width:100%}.uxbert-form-textarea{min-height:100px;resize:vertical}.uxbert-form-input:focus,.uxbert-form-select:focus,.uxbert-form-textarea:focus{border-color:var(--uxbert-primary);outline:none}.uxbert-screenshot-preview{border:1px solid var(--uxbert-border);border-radius:8px;margin:16px 0;overflow:hidden}.uxbert-screenshot-preview img{display:block;width:100%}.uxbert-screenshot-actions{background:var(--uxbert-border);display:flex;gap:8px;padding:12px}.uxbert-btn{align-items:center;border:none;border-radius:6px;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:8px;padding:10px 20px;transition:all .2s ease}.uxbert-btn-primary{background:var(--uxbert-primary);color:#fff}.uxbert-btn-primary:hover{background:var(--uxbert-primary-hover)}.uxbert-btn-secondary{background:var(--uxbert-border);color:var(--uxbert-text)}.uxbert-btn-secondary:hover{background:#d1d5db}.uxbert-btn-danger{background:var(--uxbert-danger);color:#fff}.uxbert-btn-danger:hover{background:#dc2626}.uxbert-modal-actions{display:flex;gap:12px;justify-content:flex-end;margin-top:20px}.uxbert-toolbar-toggle{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;bottom:24px;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:none;font-size:24px;height:56px;justify-content:center;position:fixed;right:24px;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar-toggle.active{display:flex}.uxbert-toolbar-toggle.hidden{opacity:0;pointer-events:none;transform:scale(.8)}.uxbert-toolbar-toggle:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-toolbar{background:var(--uxbert-bg);border-radius:12px;bottom:24px;box-shadow:var(--uxbert-shadow);display:none;flex-direction:column;gap:8px;max-height:80vh;opacity:0;overflow-y:auto;padding:16px;pointer-events:none;position:fixed;right:24px;transform:translateY(20px);transition:all .3s ease;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar.active{display:flex}.uxbert-toolbar.expanded{opacity:1;pointer-events:all;transform:translateY(0)}.uxbert-toolbar-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:8px}.uxbert-toolbar-title{flex:1;font-size:14px;font-weight:600}.uxbert-toolbar-exit,.uxbert-toolbar-minimize{align-items:center;background:var(--uxbert-border);border:none;border-radius:6px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:20px;font-weight:700;height:32px;justify-content:center;transition:all .2s ease;width:32px}.uxbert-toolbar-exit{background:var(--uxbert-danger);color:#fff}.uxbert-toolbar-minimize:hover{background:#d1d5db;transform:scale(1.1)}.uxbert-toolbar-exit:hover{background:#dc2626;transform:scale(1.1)}.uxbert-toolbar-tools{display:flex;flex-wrap:wrap;gap:8px}.uxbert-tool-btn{align-items:center;background:var(--uxbert-bg);border:2px solid var(--uxbert-border);border-radius:6px;cursor:pointer;display:flex;font-family:Arial,sans-serif;font-size:18px;font-weight:700;height:40px;justify-content:center;transition:all .2s ease;width:40px}.uxbert-tool-btn.active,.uxbert-tool-btn:hover{background:var(--uxbert-primary);border-color:var(--uxbert-primary);color:#fff}.uxbert-color-picker{display:flex;gap:6px;margin:8px 0}.uxbert-color-option{border:2px solid var(--uxbert-border);border-radius:50%;cursor:pointer;height:32px;transition:transform .2s ease;width:32px}.uxbert-color-option:hover{transform:scale(1.1)}.uxbert-color-option.active{border:3px solid var(--uxbert-text)}.uxbert-canvas-overlay{cursor:crosshair;display:none;left:0;position:absolute;top:0;z-index:var(--uxbert-z-canvas)}.uxbert-canvas-overlay.active{display:block}.uxbert-text-input{background:hsla(0,0%,100%,.95);border:2px solid var(--uxbert-primary);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--uxbert-text);font-family:Arial,sans-serif;font-size:16px;font-weight:700;min-width:200px;outline:none;padding:8px 12px;z-index:var(--uxbert-z-toolbar)}.uxbert-text-input:focus{border-color:var(--uxbert-primary-hover);box-shadow:0 4px 16px rgba(79,70,229,.3)}.uxbert-text-input::placeholder{color:#9ca3af;font-weight:400}@media (max-width:768px){.uxbert-modal{max-height:95vh;padding:16px;width:95%}.uxbert-toolbar{bottom:90px;left:16px;max-height:60vh;right:16px;width:auto}.uxbert-toolbar-toggle{bottom:16px;height:56px;right:16px;width:56px}.uxbert-fab{font-size:20px;height:48px;width:48px}.uxbert-color-picker,.uxbert-toolbar-tools{justify-content:center}}";
10143
+ var css_248z = ":root{--uxbert-primary:#4f46e5;--uxbert-primary-hover:#4338ca;--uxbert-danger:#ef4444;--uxbert-success:#10b981;--uxbert-bg:#fff;--uxbert-text:#1f2937;--uxbert-border:#e5e7eb;--uxbert-shadow:0 10px 25px rgba(0,0,0,.1);--uxbert-z-button:999999;--uxbert-z-modal:1000000;--uxbert-z-canvas:1000001;--uxbert-z-toolbar:1000002}[data-theme=dark]{--uxbert-bg:#1f2937;--uxbert-text:#f9fafb;--uxbert-border:#374151}.uxbert-fab{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:flex;font-size:24px;height:56px;justify-content:center;position:fixed;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-button)}.uxbert-fab:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-fab.bottom-right{bottom:24px;right:24px}.uxbert-fab.bottom-left{bottom:24px;left:24px}.uxbert-fab.top-right{right:24px;top:24px}.uxbert-fab.top-left{left:24px;top:24px}.uxbert-overlay{align-items:center;animation:fadeIn .3s ease;background:rgba(0,0,0,.5);display:none;height:100%;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:var(--uxbert-z-modal)}.uxbert-overlay.active{display:flex}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}.uxbert-modal{animation:slideUp .3s ease;background:var(--uxbert-bg);border-radius:12px;box-shadow:var(--uxbert-shadow);color:var(--uxbert-text);max-height:90vh;max-width:600px;overflow-y:auto;padding:24px;width:90%}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}.uxbert-modal-header{align-items:center;display:flex;justify-content:space-between;margin-bottom:20px}.uxbert-modal-title{font-size:20px;font-weight:600;margin:0}.uxbert-modal-close{align-items:center;background:none;border:none;border-radius:4px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:24px;height:32px;justify-content:center;padding:0;width:32px}.uxbert-modal-close:hover{background:var(--uxbert-border)}.uxbert-form-group{margin-bottom:16px}.uxbert-form-label{display:block;font-size:14px;font-weight:500;margin-bottom:8px}.uxbert-capture-mode{display:flex;flex-wrap:wrap;gap:12px}.uxbert-radio-label{align-items:center;border:2px solid var(--uxbert-border);border-radius:8px;cursor:pointer;display:flex;flex:1;gap:8px;min-width:140px;padding:10px 16px;transition:all .2s ease}.uxbert-radio-label:hover{background:rgba(79,70,229,.05);border-color:var(--uxbert-primary)}.uxbert-radio-label input[type=radio]{cursor:pointer;height:18px;margin:0;width:18px}.uxbert-radio-label input[type=radio]:checked{accent-color:var(--uxbert-primary)}.uxbert-radio-label:has(input[type=radio]:checked){background:rgba(79,70,229,.1);border-color:var(--uxbert-primary)}.uxbert-radio-label span{flex:1;font-size:14px;font-weight:500}.uxbert-form-input,.uxbert-form-select,.uxbert-form-textarea{background:var(--uxbert-bg);border:1px solid var(--uxbert-border);border-radius:6px;box-sizing:border-box;color:var(--uxbert-text);font-family:inherit;font-size:14px;padding:10px;width:100%}.uxbert-form-textarea{min-height:100px;resize:vertical}.uxbert-form-input:focus,.uxbert-form-select:focus,.uxbert-form-textarea:focus{border-color:var(--uxbert-primary);outline:none}.uxbert-capture-action{margin:16px 0;text-align:center}.uxbert-capture-action .uxbert-btn{min-width:200px}.uxbert-screenshot-preview{border:1px solid var(--uxbert-border);border-radius:8px;margin:16px 0;overflow:hidden}.uxbert-screenshot-preview img{display:block;width:100%}.uxbert-screenshot-actions{background:var(--uxbert-border);display:flex;gap:8px;padding:12px}.uxbert-btn{align-items:center;border:none;border-radius:6px;cursor:pointer;display:inline-flex;font-size:14px;font-weight:500;gap:8px;padding:10px 20px;transition:all .2s ease}.uxbert-btn-primary{background:var(--uxbert-primary);color:#fff}.uxbert-btn-primary:hover{background:var(--uxbert-primary-hover)}.uxbert-btn-secondary{background:var(--uxbert-border);color:var(--uxbert-text)}.uxbert-btn-secondary:hover{background:#d1d5db}.uxbert-btn-danger{background:var(--uxbert-danger);color:#fff}.uxbert-btn-danger:hover{background:#dc2626}.uxbert-modal-actions{display:flex;gap:12px;justify-content:flex-end;margin-top:20px}.uxbert-toolbar-toggle{align-items:center;background:var(--uxbert-primary);border:none;border-radius:50%;bottom:24px;box-shadow:var(--uxbert-shadow);color:#fff;cursor:pointer;display:none;font-size:24px;height:56px;justify-content:center;position:fixed;right:24px;transition:all .3s ease;width:56px;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar-toggle.active{display:flex}.uxbert-toolbar-toggle.hidden{opacity:0;pointer-events:none;transform:scale(.8)}.uxbert-toolbar-toggle:hover{background:var(--uxbert-primary-hover);transform:scale(1.1)}.uxbert-toolbar{background:var(--uxbert-bg);border-radius:12px;bottom:24px;box-shadow:var(--uxbert-shadow);display:none;flex-direction:column;gap:8px;max-height:80vh;opacity:0;overflow-y:auto;padding:16px;pointer-events:none;position:fixed;right:24px;transform:translateY(20px);transition:all .3s ease;z-index:var(--uxbert-z-toolbar)}.uxbert-toolbar.active{display:flex}.uxbert-toolbar.expanded{opacity:1;pointer-events:all;transform:translateY(0)}.uxbert-toolbar-header{align-items:center;display:flex;gap:8px;justify-content:space-between;margin-bottom:8px}.uxbert-toolbar-title{flex:1;font-size:14px;font-weight:600}.uxbert-toolbar-exit,.uxbert-toolbar-minimize{align-items:center;background:var(--uxbert-border);border:none;border-radius:6px;color:var(--uxbert-text);cursor:pointer;display:flex;font-size:20px;font-weight:700;height:32px;justify-content:center;transition:all .2s ease;width:32px}.uxbert-toolbar-exit{background:var(--uxbert-danger);color:#fff}.uxbert-toolbar-minimize:hover{background:#d1d5db;transform:scale(1.1)}.uxbert-toolbar-exit:hover{background:#dc2626;transform:scale(1.1)}.uxbert-toolbar-tools{display:flex;flex-wrap:wrap;gap:8px}.uxbert-tool-btn{align-items:center;background:var(--uxbert-bg);border:2px solid var(--uxbert-border);border-radius:6px;cursor:pointer;display:flex;font-family:Arial,sans-serif;font-size:18px;font-weight:700;height:40px;justify-content:center;transition:all .2s ease;width:40px}.uxbert-tool-btn.active,.uxbert-tool-btn:hover{background:var(--uxbert-primary);border-color:var(--uxbert-primary);color:#fff}.uxbert-color-picker{display:flex;gap:6px;margin:8px 0}.uxbert-color-option{border:2px solid var(--uxbert-border);border-radius:50%;cursor:pointer;height:32px;transition:transform .2s ease;width:32px}.uxbert-color-option:hover{transform:scale(1.1)}.uxbert-color-option.active{border:3px solid var(--uxbert-text)}.uxbert-canvas-overlay{cursor:crosshair;display:none;left:0;position:absolute;top:0;z-index:var(--uxbert-z-canvas)}.uxbert-canvas-overlay.active{display:block}.uxbert-canvas-overlay.viewport-mode{left:0;position:fixed;top:0}.uxbert-text-input{background:hsla(0,0%,100%,.95);border:2px solid var(--uxbert-primary);border-radius:6px;box-shadow:0 4px 12px rgba(0,0,0,.15);color:var(--uxbert-text);font-family:Arial,sans-serif;font-size:16px;font-weight:700;min-width:200px;outline:none;padding:8px 12px;z-index:var(--uxbert-z-toolbar)}.uxbert-text-input:focus{border-color:var(--uxbert-primary-hover);box-shadow:0 4px 16px rgba(79,70,229,.3)}.uxbert-text-input::placeholder{color:#9ca3af;font-weight:400}@media (max-width:768px){.uxbert-modal{max-height:95vh;padding:16px;width:95%}.uxbert-toolbar{bottom:90px;left:16px;max-height:60vh;right:16px;width:auto}.uxbert-toolbar-toggle{bottom:16px;height:56px;right:16px;width:56px}.uxbert-fab{font-size:20px;height:48px;width:48px}.uxbert-color-picker,.uxbert-toolbar-tools{justify-content:center}}";
10054
10144
  styleInject(css_248z);
10055
10145
 
10056
10146
  // Main initialization file
@@ -10092,6 +10182,7 @@ var Reportly = (function () {
10092
10182
  onClose: () => this.handleModalClose(),
10093
10183
  onAnnotate: () => this.startAnnotation(),
10094
10184
  onRetake: () => this.retakeScreenshot(),
10185
+ onCapture: () => this.captureWithMode(),
10095
10186
  });
10096
10187
  this.toolbar = new Toolbar({
10097
10188
  onToolChange: (tool) => this.annotation?.setTool(tool),
@@ -10122,14 +10213,27 @@ var Reportly = (function () {
10122
10213
  });
10123
10214
  }
10124
10215
  async handleButtonClick() {
10216
+ try {
10217
+ // Open modal first to let user choose capture mode
10218
+ this.modal?.open();
10219
+ }
10220
+ catch (error) {
10221
+ console.error("Failed to open modal:", error);
10222
+ alert("Failed to open modal. Please try again.");
10223
+ }
10224
+ }
10225
+ async captureWithMode() {
10125
10226
  try {
10126
10227
  this.state?.setState(STATE.CAPTURING);
10228
+ // Get capture mode from modal
10229
+ const captureMode = this.modal?.getCaptureMode() || 'viewport';
10230
+ // Save capture mode in state
10231
+ this.state?.setCaptureMode(captureMode);
10127
10232
  // Capture screenshot
10128
- const screenshot = await this.screenshot.capture();
10233
+ const screenshot = await this.screenshot.capture(captureMode);
10129
10234
  this.state?.setScreenshot(screenshot);
10130
10235
  // Show modal with screenshot
10131
10236
  this.modal?.setScreenshot(screenshot);
10132
- this.modal?.open();
10133
10237
  this.state?.setState(STATE.IDLE);
10134
10238
  }
10135
10239
  catch (error) {
@@ -10142,7 +10246,8 @@ var Reportly = (function () {
10142
10246
  this.state?.setState(STATE.ANNOTATING);
10143
10247
  this.modal?.close();
10144
10248
  this.button?.hide();
10145
- this.annotation?.show();
10249
+ const captureMode = this.state?.getCaptureMode() || 'viewport';
10250
+ this.annotation?.show(captureMode);
10146
10251
  this.toolbar?.show();
10147
10252
  }
10148
10253
  exitAnnotation() {
@@ -10178,13 +10283,16 @@ var Reportly = (function () {
10178
10283
  }
10179
10284
  async retakeScreenshot() {
10180
10285
  try {
10286
+ // Get the current capture mode from modal before closing
10287
+ const captureMode = this.modal?.getCaptureMode() || 'viewport';
10181
10288
  this.modal?.close();
10182
10289
  this.state?.setState(STATE.CAPTURING);
10183
10290
  // Clear previous annotations
10184
10291
  this.annotation?.clear();
10185
- // Capture new screenshot
10186
- const screenshot = await this.screenshot.capture();
10292
+ // Capture new screenshot with the same mode
10293
+ const screenshot = await this.screenshot.capture(captureMode);
10187
10294
  this.state?.setScreenshot(screenshot);
10295
+ this.state?.setCaptureMode(captureMode);
10188
10296
  // Show modal with new screenshot
10189
10297
  this.modal?.setScreenshot(screenshot);
10190
10298
  this.modal?.open();