@uxbertlabs/reportly 1.0.5 → 1.0.7
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/core/init.d.ts +1 -0
- package/dist/core/init.d.ts.map +1 -1
- package/dist/core/state.d.ts +3 -0
- package/dist/core/state.d.ts.map +1 -1
- package/dist/features/annotation.d.ts +1 -1
- package/dist/features/annotation.d.ts.map +1 -1
- package/dist/features/screenshot.d.ts +1 -1
- package/dist/features/screenshot.d.ts.map +1 -1
- package/dist/reportly.cjs.js +191 -39
- package/dist/reportly.cjs.js.map +1 -1
- package/dist/reportly.esm.js +191 -39
- package/dist/reportly.esm.js.map +1 -1
- package/dist/reportly.js +191 -39
- package/dist/reportly.js.map +1 -1
- package/dist/reportly.min.js +2 -2
- package/dist/reportly.min.js.map +1 -1
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/ui/modal.d.ts +1 -0
- package/dist/ui/modal.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/reportly.esm.js
CHANGED
@@ -80,6 +80,7 @@ class State {
|
|
80
80
|
this.screenshot = null;
|
81
81
|
this.annotations = [];
|
82
82
|
this.listeners = {};
|
83
|
+
this.captureMode = 'viewport';
|
83
84
|
}
|
84
85
|
setState(newState) {
|
85
86
|
this.currentState = newState;
|
@@ -109,11 +110,18 @@ class State {
|
|
109
110
|
clearAnnotations() {
|
110
111
|
this.annotations = [];
|
111
112
|
}
|
113
|
+
setCaptureMode(mode) {
|
114
|
+
this.captureMode = mode;
|
115
|
+
}
|
116
|
+
getCaptureMode() {
|
117
|
+
return this.captureMode;
|
118
|
+
}
|
112
119
|
reset() {
|
113
120
|
this.currentState = STATE.IDLE;
|
114
121
|
this.currentIssue = null;
|
115
122
|
this.screenshot = null;
|
116
123
|
this.annotations = [];
|
124
|
+
this.captureMode = 'viewport';
|
117
125
|
}
|
118
126
|
// Event system
|
119
127
|
on(event, callback) {
|
@@ -187,6 +195,20 @@ class Modal {
|
|
187
195
|
</div>
|
188
196
|
|
189
197
|
<form class="uxbert-form" id="uxbert-issue-form">
|
198
|
+
<div class="uxbert-form-group">
|
199
|
+
<label class="uxbert-form-label">Capture Mode</label>
|
200
|
+
<div class="uxbert-capture-mode">
|
201
|
+
<label class="uxbert-radio-label">
|
202
|
+
<input type="radio" name="capture-mode" value="viewport" id="uxbert-capture-viewport" checked />
|
203
|
+
<span>Current View</span>
|
204
|
+
</label>
|
205
|
+
<label class="uxbert-radio-label">
|
206
|
+
<input type="radio" name="capture-mode" value="fullpage" id="uxbert-capture-fullpage" />
|
207
|
+
<span>Full Page</span>
|
208
|
+
</label>
|
209
|
+
</div>
|
210
|
+
</div>
|
211
|
+
|
190
212
|
<div class="uxbert-form-group">
|
191
213
|
<label class="uxbert-form-label" for="uxbert-title">Issue Title *</label>
|
192
214
|
<input
|
@@ -217,6 +239,12 @@ class Modal {
|
|
217
239
|
</select>
|
218
240
|
</div>
|
219
241
|
|
242
|
+
<div class="uxbert-capture-action" id="uxbert-capture-action">
|
243
|
+
<button type="button" class="uxbert-btn uxbert-btn-primary" id="uxbert-capture-btn">
|
244
|
+
📸 Take Screenshot
|
245
|
+
</button>
|
246
|
+
</div>
|
247
|
+
|
220
248
|
<div class="uxbert-screenshot-preview" id="uxbert-screenshot-container" style="display: none;">
|
221
249
|
<img id="uxbert-screenshot-img" src="" alt="Screenshot" />
|
222
250
|
<div class="uxbert-screenshot-actions">
|
@@ -233,7 +261,7 @@ class Modal {
|
|
233
261
|
<button type="button" class="uxbert-btn uxbert-btn-secondary" id="uxbert-cancel-btn">
|
234
262
|
Cancel
|
235
263
|
</button>
|
236
|
-
<button type="submit" class="uxbert-btn uxbert-btn-primary">
|
264
|
+
<button type="submit" class="uxbert-btn uxbert-btn-primary" id="uxbert-submit-btn">
|
237
265
|
📥 Download JSON
|
238
266
|
</button>
|
239
267
|
</div>
|
@@ -266,6 +294,13 @@ class Modal {
|
|
266
294
|
e.preventDefault();
|
267
295
|
this.handleSubmit();
|
268
296
|
});
|
297
|
+
// Capture button
|
298
|
+
const captureBtn = this.modal.querySelector('#uxbert-capture-btn');
|
299
|
+
captureBtn.addEventListener('click', () => {
|
300
|
+
if (this.callbacks.onCapture) {
|
301
|
+
this.callbacks.onCapture();
|
302
|
+
}
|
303
|
+
});
|
269
304
|
// Annotate button
|
270
305
|
const annotateBtn = this.modal.querySelector('#uxbert-annotate-btn');
|
271
306
|
annotateBtn.addEventListener('click', () => {
|
@@ -318,14 +353,26 @@ class Modal {
|
|
318
353
|
return;
|
319
354
|
const container = this.modal.querySelector('#uxbert-screenshot-container');
|
320
355
|
const img = this.modal.querySelector('#uxbert-screenshot-img');
|
356
|
+
const captureAction = this.modal.querySelector('#uxbert-capture-action');
|
357
|
+
const submitBtn = this.modal.querySelector('#uxbert-submit-btn');
|
321
358
|
if (screenshot) {
|
322
359
|
img.src = screenshot;
|
323
360
|
container.style.display = 'block';
|
361
|
+
captureAction.style.display = 'none';
|
362
|
+
submitBtn.disabled = false;
|
324
363
|
}
|
325
364
|
else {
|
326
365
|
container.style.display = 'none';
|
366
|
+
captureAction.style.display = 'block';
|
367
|
+
submitBtn.disabled = true;
|
327
368
|
}
|
328
369
|
}
|
370
|
+
getCaptureMode() {
|
371
|
+
if (!this.modal)
|
372
|
+
return 'viewport';
|
373
|
+
const viewportRadio = this.modal.querySelector('#uxbert-capture-viewport');
|
374
|
+
return viewportRadio.checked ? 'viewport' : 'fullpage';
|
375
|
+
}
|
329
376
|
reset() {
|
330
377
|
if (!this.modal)
|
331
378
|
return;
|
@@ -9400,26 +9447,87 @@ class Screenshot {
|
|
9400
9447
|
constructor() {
|
9401
9448
|
this.currentScreenshot = null;
|
9402
9449
|
}
|
9403
|
-
async capture() {
|
9450
|
+
async capture(mode = 'fullpage') {
|
9404
9451
|
try {
|
9405
9452
|
// Hide UXbert UI elements before capturing
|
9406
9453
|
this.hideUXbertElements();
|
9407
|
-
// Scroll to top to capture full page
|
9408
9454
|
const originalScrollY = window.scrollY;
|
9409
|
-
|
9410
|
-
|
9411
|
-
|
9412
|
-
|
9413
|
-
|
9414
|
-
|
9415
|
-
|
9416
|
-
|
9417
|
-
|
9418
|
-
|
9419
|
-
|
9420
|
-
|
9421
|
-
|
9422
|
-
|
9455
|
+
let canvas;
|
9456
|
+
if (mode === 'viewport') {
|
9457
|
+
// Capture only the current viewport
|
9458
|
+
canvas = await html2canvas(document.body, {
|
9459
|
+
useCORS: true,
|
9460
|
+
allowTaint: false,
|
9461
|
+
logging: false,
|
9462
|
+
width: window.innerWidth,
|
9463
|
+
height: window.innerHeight,
|
9464
|
+
windowWidth: window.innerWidth,
|
9465
|
+
windowHeight: window.innerHeight,
|
9466
|
+
x: window.scrollX,
|
9467
|
+
y: window.scrollY,
|
9468
|
+
ignoreElements: (element) => {
|
9469
|
+
// Skip cross-origin images that might cause issues
|
9470
|
+
if (element.tagName === 'IMG') {
|
9471
|
+
const img = element;
|
9472
|
+
try {
|
9473
|
+
// Test if image is accessible
|
9474
|
+
const canvas = document.createElement('canvas');
|
9475
|
+
const ctx = canvas.getContext('2d');
|
9476
|
+
canvas.width = 1;
|
9477
|
+
canvas.height = 1;
|
9478
|
+
ctx?.drawImage(img, 0, 0, 1, 1);
|
9479
|
+
canvas.toDataURL(); // This will throw if tainted
|
9480
|
+
return false; // Include the image
|
9481
|
+
}
|
9482
|
+
catch (e) {
|
9483
|
+
// Image is tainted, skip it
|
9484
|
+
console.warn('Skipping cross-origin image:', img.src);
|
9485
|
+
return true;
|
9486
|
+
}
|
9487
|
+
}
|
9488
|
+
return false;
|
9489
|
+
},
|
9490
|
+
});
|
9491
|
+
}
|
9492
|
+
else {
|
9493
|
+
// Scroll to top to capture full page
|
9494
|
+
window.scrollTo(0, 0);
|
9495
|
+
// Get full page dimensions
|
9496
|
+
const fullPageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
|
9497
|
+
const fullPageWidth = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
|
9498
|
+
// Capture the full page
|
9499
|
+
canvas = await html2canvas(document.body, {
|
9500
|
+
useCORS: true,
|
9501
|
+
allowTaint: false,
|
9502
|
+
logging: false,
|
9503
|
+
width: fullPageWidth,
|
9504
|
+
height: fullPageHeight,
|
9505
|
+
ignoreElements: (element) => {
|
9506
|
+
// Skip cross-origin images that might cause issues
|
9507
|
+
if (element.tagName === 'IMG') {
|
9508
|
+
const img = element;
|
9509
|
+
try {
|
9510
|
+
// Test if image is accessible
|
9511
|
+
const canvas = document.createElement('canvas');
|
9512
|
+
const ctx = canvas.getContext('2d');
|
9513
|
+
canvas.width = 1;
|
9514
|
+
canvas.height = 1;
|
9515
|
+
ctx?.drawImage(img, 0, 0, 1, 1);
|
9516
|
+
canvas.toDataURL(); // This will throw if tainted
|
9517
|
+
return false; // Include the image
|
9518
|
+
}
|
9519
|
+
catch (e) {
|
9520
|
+
// Image is tainted, skip it
|
9521
|
+
console.warn('Skipping cross-origin image:', img.src);
|
9522
|
+
return true;
|
9523
|
+
}
|
9524
|
+
}
|
9525
|
+
return false;
|
9526
|
+
},
|
9527
|
+
});
|
9528
|
+
// Restore scroll position
|
9529
|
+
window.scrollTo(0, originalScrollY);
|
9530
|
+
}
|
9423
9531
|
// Show UXbert UI elements again
|
9424
9532
|
this.showUXbertElements();
|
9425
9533
|
// Convert to base64
|
@@ -9495,29 +9603,46 @@ class AnnotationManager {
|
|
9495
9603
|
document.body.appendChild(this.canvas);
|
9496
9604
|
return this.canvas;
|
9497
9605
|
}
|
9498
|
-
updateCanvasSize() {
|
9606
|
+
updateCanvasSize(mode = 'fullpage') {
|
9499
9607
|
if (!this.canvas)
|
9500
9608
|
return;
|
9501
|
-
|
9502
|
-
|
9503
|
-
|
9504
|
-
|
9505
|
-
|
9609
|
+
if (mode === 'viewport') {
|
9610
|
+
// Set canvas to viewport dimensions
|
9611
|
+
this.canvas.width = window.innerWidth;
|
9612
|
+
this.canvas.height = window.innerHeight;
|
9613
|
+
}
|
9614
|
+
else {
|
9615
|
+
// Get full page dimensions
|
9616
|
+
const fullPageHeight = Math.max(document.body.scrollHeight, document.body.offsetHeight, document.documentElement.clientHeight, document.documentElement.scrollHeight, document.documentElement.offsetHeight);
|
9617
|
+
const fullPageWidth = Math.max(document.body.scrollWidth, document.body.offsetWidth, document.documentElement.clientWidth, document.documentElement.scrollWidth, document.documentElement.offsetWidth);
|
9618
|
+
this.canvas.width = fullPageWidth;
|
9619
|
+
this.canvas.height = fullPageHeight;
|
9620
|
+
}
|
9506
9621
|
}
|
9507
|
-
show() {
|
9622
|
+
show(mode = 'fullpage') {
|
9508
9623
|
if (this.canvas && this.ctx) {
|
9509
9624
|
// Update canvas size to match current page dimensions
|
9510
|
-
this.updateCanvasSize();
|
9625
|
+
this.updateCanvasSize(mode);
|
9511
9626
|
// Reset context properties after resize
|
9512
9627
|
this.ctx.lineCap = 'round';
|
9513
9628
|
this.ctx.lineJoin = 'round';
|
9514
9629
|
this.canvas.classList.add('active');
|
9630
|
+
// If viewport mode, add viewport-mode class
|
9631
|
+
if (mode === 'viewport') {
|
9632
|
+
this.canvas.classList.add('viewport-mode');
|
9633
|
+
// Note: We don't disable scrolling in viewport mode to allow users to scroll
|
9634
|
+
// and annotate different parts of the viewport
|
9635
|
+
}
|
9636
|
+
else {
|
9637
|
+
this.canvas.classList.remove('viewport-mode');
|
9638
|
+
}
|
9515
9639
|
this.redraw();
|
9516
9640
|
}
|
9517
9641
|
}
|
9518
9642
|
hide() {
|
9519
9643
|
if (this.canvas) {
|
9520
9644
|
this.canvas.classList.remove('active');
|
9645
|
+
this.canvas.classList.remove('viewport-mode');
|
9521
9646
|
}
|
9522
9647
|
// Clean up any active text input
|
9523
9648
|
this.removeTextInput();
|
@@ -9530,10 +9655,13 @@ class AnnotationManager {
|
|
9530
9655
|
this.currentColor = color;
|
9531
9656
|
}
|
9532
9657
|
handleMouseDown(e) {
|
9658
|
+
const isViewportMode = this.canvas?.classList.contains('viewport-mode');
|
9659
|
+
const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
|
9660
|
+
const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
|
9533
9661
|
// Handle text tool separately
|
9534
9662
|
if (this.currentTool === 'text') {
|
9535
|
-
const x = e.clientX +
|
9536
|
-
const y = e.clientY +
|
9663
|
+
const x = e.clientX + scrollOffsetX;
|
9664
|
+
const y = e.clientY + scrollOffsetY;
|
9537
9665
|
// Check if clicking on existing text to edit
|
9538
9666
|
const clickedText = this.getTextAnnotationAt(x, y);
|
9539
9667
|
if (clickedText) {
|
@@ -9545,15 +9673,18 @@ class AnnotationManager {
|
|
9545
9673
|
return;
|
9546
9674
|
}
|
9547
9675
|
this.isDrawing = true;
|
9548
|
-
this.startX = e.clientX +
|
9549
|
-
this.startY = e.clientY +
|
9676
|
+
this.startX = e.clientX + scrollOffsetX;
|
9677
|
+
this.startY = e.clientY + scrollOffsetY;
|
9550
9678
|
this.currentPath = [{ x: this.startX, y: this.startY }];
|
9551
9679
|
}
|
9552
9680
|
handleMouseMove(e) {
|
9553
9681
|
if (!this.isDrawing || !this.ctx)
|
9554
9682
|
return;
|
9555
|
-
const
|
9556
|
-
const
|
9683
|
+
const isViewportMode = this.canvas?.classList.contains('viewport-mode');
|
9684
|
+
const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
|
9685
|
+
const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
|
9686
|
+
const x = e.clientX + scrollOffsetX;
|
9687
|
+
const y = e.clientY + scrollOffsetY;
|
9557
9688
|
if (this.currentTool === 'pen') {
|
9558
9689
|
this.currentPath.push({ x, y });
|
9559
9690
|
this.redraw();
|
@@ -9573,8 +9704,11 @@ class AnnotationManager {
|
|
9573
9704
|
if (!this.isDrawing)
|
9574
9705
|
return;
|
9575
9706
|
this.isDrawing = false;
|
9576
|
-
const
|
9577
|
-
const
|
9707
|
+
const isViewportMode = this.canvas?.classList.contains('viewport-mode');
|
9708
|
+
const scrollOffsetX = isViewportMode ? 0 : window.scrollX;
|
9709
|
+
const scrollOffsetY = isViewportMode ? 0 : window.scrollY;
|
9710
|
+
const x = e.clientX + scrollOffsetX;
|
9711
|
+
const y = e.clientY + scrollOffsetY;
|
9578
9712
|
// Save the annotation
|
9579
9713
|
if (this.currentTool === 'pen') {
|
9580
9714
|
this.annotations.push({
|
@@ -10047,7 +10181,7 @@ function styleInject(css, ref) {
|
|
10047
10181
|
}
|
10048
10182
|
}
|
10049
10183
|
|
10050
|
-
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}}";
|
10184
|
+
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}}";
|
10051
10185
|
styleInject(css_248z);
|
10052
10186
|
|
10053
10187
|
// Main initialization file
|
@@ -10089,6 +10223,7 @@ class Reportly {
|
|
10089
10223
|
onClose: () => this.handleModalClose(),
|
10090
10224
|
onAnnotate: () => this.startAnnotation(),
|
10091
10225
|
onRetake: () => this.retakeScreenshot(),
|
10226
|
+
onCapture: () => this.captureWithMode(),
|
10092
10227
|
});
|
10093
10228
|
this.toolbar = new Toolbar({
|
10094
10229
|
onToolChange: (tool) => this.annotation?.setTool(tool),
|
@@ -10119,14 +10254,27 @@ class Reportly {
|
|
10119
10254
|
});
|
10120
10255
|
}
|
10121
10256
|
async handleButtonClick() {
|
10257
|
+
try {
|
10258
|
+
// Open modal first to let user choose capture mode
|
10259
|
+
this.modal?.open();
|
10260
|
+
}
|
10261
|
+
catch (error) {
|
10262
|
+
console.error("Failed to open modal:", error);
|
10263
|
+
alert("Failed to open modal. Please try again.");
|
10264
|
+
}
|
10265
|
+
}
|
10266
|
+
async captureWithMode() {
|
10122
10267
|
try {
|
10123
10268
|
this.state?.setState(STATE.CAPTURING);
|
10269
|
+
// Get capture mode from modal
|
10270
|
+
const captureMode = this.modal?.getCaptureMode() || 'viewport';
|
10271
|
+
// Save capture mode in state
|
10272
|
+
this.state?.setCaptureMode(captureMode);
|
10124
10273
|
// Capture screenshot
|
10125
|
-
const screenshot = await this.screenshot.capture();
|
10274
|
+
const screenshot = await this.screenshot.capture(captureMode);
|
10126
10275
|
this.state?.setScreenshot(screenshot);
|
10127
10276
|
// Show modal with screenshot
|
10128
10277
|
this.modal?.setScreenshot(screenshot);
|
10129
|
-
this.modal?.open();
|
10130
10278
|
this.state?.setState(STATE.IDLE);
|
10131
10279
|
}
|
10132
10280
|
catch (error) {
|
@@ -10139,7 +10287,8 @@ class Reportly {
|
|
10139
10287
|
this.state?.setState(STATE.ANNOTATING);
|
10140
10288
|
this.modal?.close();
|
10141
10289
|
this.button?.hide();
|
10142
|
-
this.
|
10290
|
+
const captureMode = this.state?.getCaptureMode() || 'viewport';
|
10291
|
+
this.annotation?.show(captureMode);
|
10143
10292
|
this.toolbar?.show();
|
10144
10293
|
}
|
10145
10294
|
exitAnnotation() {
|
@@ -10175,13 +10324,16 @@ class Reportly {
|
|
10175
10324
|
}
|
10176
10325
|
async retakeScreenshot() {
|
10177
10326
|
try {
|
10327
|
+
// Get the current capture mode from modal before closing
|
10328
|
+
const captureMode = this.modal?.getCaptureMode() || 'viewport';
|
10178
10329
|
this.modal?.close();
|
10179
10330
|
this.state?.setState(STATE.CAPTURING);
|
10180
10331
|
// Clear previous annotations
|
10181
10332
|
this.annotation?.clear();
|
10182
|
-
// Capture new screenshot
|
10183
|
-
const screenshot = await this.screenshot.capture();
|
10333
|
+
// Capture new screenshot with the same mode
|
10334
|
+
const screenshot = await this.screenshot.capture(captureMode);
|
10184
10335
|
this.state?.setScreenshot(screenshot);
|
10336
|
+
this.state?.setCaptureMode(captureMode);
|
10185
10337
|
// Show modal with new screenshot
|
10186
10338
|
this.modal?.setScreenshot(screenshot);
|
10187
10339
|
this.modal?.open();
|