pushfeedback 0.1.70 → 0.1.71

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.
Files changed (43) hide show
  1. package/dist/cjs/canvas-editor_3.cjs.entry.js +1367 -0
  2. package/dist/cjs/index-9a8f4784.js +1584 -0
  3. package/dist/cjs/index.cjs.js +2 -0
  4. package/dist/cjs/loader.cjs.js +22 -0
  5. package/dist/cjs/pushfeedback.cjs.js +23 -0
  6. package/dist/collection/collection-manifest.json +14 -0
  7. package/dist/collection/components/canvas-editor/canvas-editor.css +404 -0
  8. package/dist/collection/components/canvas-editor/canvas-editor.js +1282 -0
  9. package/dist/collection/components/feedback-button/feedback-button.css +81 -0
  10. package/dist/collection/components/feedback-button/feedback-button.js +1169 -0
  11. package/dist/collection/components/feedback-modal/feedback-modal.css +547 -0
  12. package/dist/collection/components/feedback-modal/feedback-modal.js +1257 -0
  13. package/dist/collection/index.js +1 -0
  14. package/dist/components/canvas-editor.js +6 -0
  15. package/dist/{pushfeedback/canvas-editor.entry.js → components/canvas-editor2.js} +64 -7
  16. package/dist/{pushfeedback/feedback-button.entry.js → components/feedback-button.js} +90 -8
  17. package/dist/components/feedback-modal.js +6 -0
  18. package/dist/{pushfeedback/feedback-modal.entry.js → components/feedback-modal2.js} +97 -7
  19. package/dist/components/index.js +4 -0
  20. package/dist/esm/canvas-editor_3.entry.js +1361 -0
  21. package/dist/esm/index-f65e9124.js +1555 -0
  22. package/dist/esm/index.js +1 -0
  23. package/dist/esm/loader.js +18 -0
  24. package/dist/esm/polyfills/core-js.js +11 -0
  25. package/dist/esm/polyfills/css-shim.js +1 -0
  26. package/dist/esm/polyfills/dom.js +79 -0
  27. package/dist/esm/polyfills/es5-html-element.js +1 -0
  28. package/dist/esm/polyfills/index.js +34 -0
  29. package/dist/esm/polyfills/system.js +6 -0
  30. package/dist/esm/pushfeedback.js +18 -0
  31. package/dist/index.cjs.js +1 -0
  32. package/dist/index.js +1 -0
  33. package/dist/pushfeedback/index.esm.js +0 -1
  34. package/dist/pushfeedback/p-2c39091c.entry.js +1 -0
  35. package/dist/pushfeedback/p-af2a1f7f.js +2 -0
  36. package/dist/pushfeedback/pushfeedback.css +1 -146
  37. package/dist/pushfeedback/pushfeedback.esm.js +1 -148
  38. package/package.json +1 -1
  39. package/dist/pushfeedback/app-globals-0f993ce5.js +0 -3
  40. package/dist/pushfeedback/css-shim-b7d3d95f.js +0 -4
  41. package/dist/pushfeedback/dom-64053c71.js +0 -73
  42. package/dist/pushfeedback/index-36434da0.js +0 -3371
  43. package/dist/pushfeedback/shadow-css-98135883.js +0 -387
@@ -0,0 +1,1282 @@
1
+ import { h } from '@stencil/core';
2
+ export class CanvasEditor {
3
+ constructor() {
4
+ this.openScreenShot = async () => {
5
+ // Show loading state immediately
6
+ this.takingScreenshot = true;
7
+ // Clear any previous annotations when taking a new screenshot
8
+ this.annotations = [];
9
+ this.currentAnnotation = null;
10
+ this.isDrawing = false;
11
+ this.hoveredAnnotation = null;
12
+ // Hide any feedback buttons on the page
13
+ this.hideAllFeedbackElements();
14
+ try {
15
+ // Wait a moment for UI to update before capturing
16
+ await new Promise(resolve => setTimeout(resolve, 100));
17
+ // Capture viewport screenshot using browser API
18
+ const dataUrl = await this.captureViewportScreenshot();
19
+ this.originalImageData = dataUrl;
20
+ // Reset loading state
21
+ this.takingScreenshot = false;
22
+ // Go directly to canvas editor
23
+ this.showCanvasEditor = true;
24
+ // Restore feedback elements visibility
25
+ this.showAllFeedbackElements();
26
+ // Initialize canvas after a short delay to ensure DOM is ready
27
+ setTimeout(() => {
28
+ this.initializeCanvas();
29
+ }, 100);
30
+ }
31
+ catch (error) {
32
+ console.error('Failed to capture screenshot:', error);
33
+ // Reset loading state on error
34
+ this.takingScreenshot = false;
35
+ // Restore feedback elements on error
36
+ this.showAllFeedbackElements();
37
+ // Show error message to user
38
+ this.handleScreenshotError(error);
39
+ }
40
+ };
41
+ this.hideAllFeedbackElements = () => {
42
+ // Hide all feedback buttons and modals on the page
43
+ const feedbackElements = document.querySelectorAll('feedback-button, feedback-modal');
44
+ feedbackElements.forEach(element => {
45
+ element.style.visibility = 'hidden';
46
+ });
47
+ };
48
+ this.showAllFeedbackElements = () => {
49
+ // Show all feedback buttons and modals on the page
50
+ const feedbackElements = document.querySelectorAll('feedback-button, feedback-modal');
51
+ feedbackElements.forEach(element => {
52
+ element.style.visibility = 'visible';
53
+ });
54
+ };
55
+ this.handleScreenshotError = (error) => {
56
+ let errorMessage = this.screenshotErrorGeneral;
57
+ if (error.name === 'NotAllowedError') {
58
+ errorMessage += ' ' + this.screenshotErrorPermission;
59
+ }
60
+ else if (error.name === 'NotSupportedError') {
61
+ errorMessage += ' ' + this.screenshotErrorNotSupported;
62
+ }
63
+ else if (error.name === 'NotFoundError') {
64
+ errorMessage += ' ' + this.screenshotErrorNotFound;
65
+ }
66
+ else if (error.name === 'AbortError') {
67
+ errorMessage += ' ' + this.screenshotErrorCancelled;
68
+ }
69
+ else if (error.message && error.message.includes('not supported')) {
70
+ errorMessage += ' ' + this.screenshotErrorBrowserNotSupported;
71
+ }
72
+ else {
73
+ errorMessage += ' ' + this.screenshotErrorUnexpected;
74
+ }
75
+ // Just emit the error to parent - don't show internal notification
76
+ this.screenshotFailed.emit({ error: errorMessage });
77
+ };
78
+ this.closeCanvasEditor = () => {
79
+ this.showCanvasEditor = false;
80
+ this.screenshotCancelled.emit();
81
+ };
82
+ this.saveAnnotations = () => {
83
+ if (this.canvasRef) {
84
+ // Create final image with annotations
85
+ const finalDataUrl = this.canvasRef.toDataURL('image/png');
86
+ this.screenshotReady.emit({ screenshot: finalDataUrl });
87
+ }
88
+ this.showCanvasEditor = false;
89
+ };
90
+ this.initializeCanvas = () => {
91
+ if (!this.canvasRef || !this.originalImageData)
92
+ return;
93
+ this.canvasContext = this.canvasRef.getContext('2d');
94
+ const img = new Image();
95
+ img.onload = () => {
96
+ // Set canvas to original image dimensions
97
+ this.canvasRef.width = img.width;
98
+ this.canvasRef.height = img.height;
99
+ // Get available container dimensions
100
+ const containerWidth = this.canvasRef.parentElement.clientWidth - 32;
101
+ const containerHeight = this.canvasRef.parentElement.clientHeight - 32;
102
+ // Calculate scale factors for both dimensions
103
+ const scaleX = containerWidth / img.width;
104
+ const scaleY = containerHeight / img.height;
105
+ // Use the smaller scale to ensure complete image fits
106
+ const scale = Math.min(scaleX, scaleY, 1);
107
+ // Calculate final display dimensions
108
+ const displayWidth = img.width * scale;
109
+ const displayHeight = img.height * scale;
110
+ // Set CSS size for display
111
+ this.canvasRef.style.width = `${displayWidth}px`;
112
+ this.canvasRef.style.height = `${displayHeight}px`;
113
+ // Draw the original image at full resolution
114
+ this.canvasContext.drawImage(img, 0, 0);
115
+ // Redraw existing annotations
116
+ this.redrawAnnotations();
117
+ };
118
+ img.src = this.originalImageData;
119
+ };
120
+ this.redrawAnnotations = () => {
121
+ if (!this.canvasContext)
122
+ return;
123
+ // Clear and redraw background image
124
+ const img = new Image();
125
+ img.onload = () => {
126
+ this.canvasContext.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
127
+ this.canvasContext.drawImage(img, 0, 0);
128
+ // Draw all annotations
129
+ this.annotations.forEach(annotation => {
130
+ this.drawAnnotation(annotation);
131
+ });
132
+ };
133
+ img.src = this.originalImageData;
134
+ };
135
+ this.drawAnnotation = (annotation) => {
136
+ if (!this.canvasContext)
137
+ return;
138
+ this.canvasContext.strokeStyle = annotation.color;
139
+ this.canvasContext.lineWidth = annotation.lineWidth;
140
+ this.canvasContext.lineCap = 'round';
141
+ this.canvasContext.lineJoin = 'round';
142
+ switch (annotation.type) {
143
+ case 'rectangle':
144
+ this.canvasContext.strokeRect(annotation.startX, annotation.startY, annotation.width, annotation.height);
145
+ // Draw selection indicator if this annotation is selected
146
+ if (this.selectedAnnotation === annotation) {
147
+ this.drawSelectionIndicator(annotation);
148
+ }
149
+ // Draw resize handles if this annotation is hovered
150
+ if (this.hoveredAnnotation === annotation) {
151
+ this.drawRectangleResizeHandles(annotation);
152
+ }
153
+ break;
154
+ case 'line':
155
+ this.canvasContext.beginPath();
156
+ this.canvasContext.moveTo(annotation.startX, annotation.startY);
157
+ this.canvasContext.lineTo(annotation.endX, annotation.endY);
158
+ this.canvasContext.stroke();
159
+ // Draw selection indicator if this annotation is selected
160
+ if (this.selectedAnnotation === annotation) {
161
+ this.drawSelectionIndicator(annotation);
162
+ }
163
+ // Draw resize handles if this annotation is hovered
164
+ if (this.hoveredAnnotation === annotation) {
165
+ this.drawLineResizeHandles(annotation);
166
+ }
167
+ break;
168
+ case 'arrow':
169
+ this.drawArrow(annotation.startX, annotation.startY, annotation.endX, annotation.endY);
170
+ // Draw selection indicator if this annotation is selected
171
+ if (this.selectedAnnotation === annotation) {
172
+ this.drawSelectionIndicator(annotation);
173
+ }
174
+ // Draw resize handles if this annotation is hovered
175
+ if (this.hoveredAnnotation === annotation) {
176
+ this.drawLineResizeHandles(annotation);
177
+ }
178
+ break;
179
+ case 'text':
180
+ const fontSize = annotation.fontSize || 24;
181
+ this.canvasContext.fillStyle = annotation.color;
182
+ this.canvasContext.font = `${fontSize}px Arial`;
183
+ this.canvasContext.fillText(annotation.text, annotation.x, annotation.y);
184
+ // Draw selection indicator if this annotation is selected
185
+ if (this.selectedAnnotation === annotation) {
186
+ this.drawTextSelectionIndicator(annotation);
187
+ }
188
+ break;
189
+ }
190
+ };
191
+ // Draw selection indicator for shapes
192
+ this.drawSelectionIndicator = (annotation) => {
193
+ if (!this.canvasContext)
194
+ return;
195
+ // Save current context
196
+ const originalStrokeStyle = this.canvasContext.strokeStyle;
197
+ const originalLineWidth = this.canvasContext.lineWidth;
198
+ // Draw selection outline
199
+ this.canvasContext.strokeStyle = '#0070F4';
200
+ this.canvasContext.lineWidth = 2;
201
+ this.canvasContext.setLineDash([5, 5]);
202
+ switch (annotation.type) {
203
+ case 'rectangle':
204
+ this.canvasContext.strokeRect(annotation.startX - 2, annotation.startY - 2, annotation.width + 4, annotation.height + 4);
205
+ break;
206
+ case 'line':
207
+ case 'arrow':
208
+ this.canvasContext.beginPath();
209
+ this.canvasContext.moveTo(annotation.startX, annotation.startY);
210
+ this.canvasContext.lineTo(annotation.endX, annotation.endY);
211
+ this.canvasContext.stroke();
212
+ break;
213
+ }
214
+ // Restore context
215
+ this.canvasContext.setLineDash([]);
216
+ this.canvasContext.strokeStyle = originalStrokeStyle;
217
+ this.canvasContext.lineWidth = originalLineWidth;
218
+ };
219
+ // Draw selection indicator for text
220
+ this.drawTextSelectionIndicator = (annotation) => {
221
+ if (!this.canvasContext)
222
+ return;
223
+ const fontSize = annotation.fontSize || 24;
224
+ const textWidth = this.getTextWidth(annotation.text, fontSize);
225
+ // Save current context
226
+ const originalStrokeStyle = this.canvasContext.strokeStyle;
227
+ const originalLineWidth = this.canvasContext.lineWidth;
228
+ // Draw selection outline around text
229
+ this.canvasContext.strokeStyle = '#0070F4';
230
+ this.canvasContext.lineWidth = 2;
231
+ this.canvasContext.setLineDash([3, 3]);
232
+ this.canvasContext.strokeRect(annotation.x - 4, annotation.y - fontSize - 4, textWidth + 8, fontSize + 8);
233
+ // Restore context
234
+ this.canvasContext.setLineDash([]);
235
+ this.canvasContext.strokeStyle = originalStrokeStyle;
236
+ this.canvasContext.lineWidth = originalLineWidth;
237
+ };
238
+ this.drawArrow = (fromX, fromY, toX, toY) => {
239
+ const headlen = 15; // Arrow head length
240
+ const angle = Math.atan2(toY - fromY, toX - fromX);
241
+ // Draw line
242
+ this.canvasContext.beginPath();
243
+ this.canvasContext.moveTo(fromX, fromY);
244
+ this.canvasContext.lineTo(toX, toY);
245
+ this.canvasContext.stroke();
246
+ // Draw arrow head
247
+ this.canvasContext.beginPath();
248
+ this.canvasContext.moveTo(toX, toY);
249
+ this.canvasContext.lineTo(toX - headlen * Math.cos(angle - Math.PI / 6), toY - headlen * Math.sin(angle - Math.PI / 6));
250
+ this.canvasContext.moveTo(toX, toY);
251
+ this.canvasContext.lineTo(toX - headlen * Math.cos(angle + Math.PI / 6), toY - headlen * Math.sin(angle + Math.PI / 6));
252
+ this.canvasContext.stroke();
253
+ };
254
+ this.undoLastAnnotation = () => {
255
+ this.annotations = this.annotations.slice(0, -1);
256
+ this.redrawAnnotations();
257
+ };
258
+ // Handle color slot editing
259
+ this.handleColorSlotClick = (colorIndex) => {
260
+ if (this.editingColorIndex === colorIndex) {
261
+ // If already editing this slot, just select the color
262
+ this.canvasDrawingColor = this.defaultColors[colorIndex];
263
+ this.showColorPicker = false;
264
+ this.editingColorIndex = -1;
265
+ }
266
+ else {
267
+ // Start editing this color slot
268
+ this.editingColorIndex = colorIndex;
269
+ this.showColorPicker = true;
270
+ this.canvasDrawingColor = this.defaultColors[colorIndex];
271
+ }
272
+ };
273
+ // Update color in slot
274
+ this.updateColorSlot = (newColor) => {
275
+ if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
276
+ this.defaultColors[this.editingColorIndex] = newColor;
277
+ this.canvasDrawingColor = newColor;
278
+ this.showColorPicker = false;
279
+ this.editingColorIndex = -1;
280
+ // Force reactivity
281
+ this.defaultColors = [...this.defaultColors];
282
+ }
283
+ };
284
+ // Handle color picker input without closing
285
+ this.handleColorPickerInput = (event) => {
286
+ event.stopPropagation();
287
+ const newColor = event.target.value;
288
+ if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
289
+ this.defaultColors[this.editingColorIndex] = newColor;
290
+ this.canvasDrawingColor = newColor;
291
+ // Force reactivity
292
+ this.defaultColors = [...this.defaultColors];
293
+ }
294
+ };
295
+ // Handle color picker click to prevent closing
296
+ this.handleColorPickerClick = (event) => {
297
+ event.stopPropagation();
298
+ };
299
+ // Close color picker
300
+ this.closeColorPicker = () => {
301
+ this.showColorPicker = false;
302
+ this.editingColorIndex = -1;
303
+ };
304
+ // Get text width for resize handle positioning
305
+ this.getTextWidth = (text, fontSize) => {
306
+ // Better text width calculation
307
+ if (!this.canvasContext) {
308
+ return text.length * fontSize * 0.6; // Fallback
309
+ }
310
+ // Use actual canvas measurement for accuracy
311
+ const originalFont = this.canvasContext.font;
312
+ this.canvasContext.font = `${fontSize}px Arial`;
313
+ const width = this.canvasContext.measureText(text).width;
314
+ this.canvasContext.font = originalFont;
315
+ return width;
316
+ };
317
+ // Check if point is in resize handle for shapes (not text)
318
+ this.isPointInResizeHandle = (x, y, annotation) => {
319
+ const handleSize = 8;
320
+ switch (annotation.type) {
321
+ case 'rectangle':
322
+ const right = annotation.startX + annotation.width;
323
+ const bottom = annotation.startY + annotation.height;
324
+ // Only check bottom-right corner handle
325
+ return x >= right - handleSize / 2 && x <= right + handleSize / 2 &&
326
+ y >= bottom - handleSize / 2 && y <= bottom + handleSize / 2;
327
+ case 'line':
328
+ case 'arrow':
329
+ // Check both endpoint handles
330
+ const lineHandles = [
331
+ { x: annotation.startX, y: annotation.startY, point: 'start' },
332
+ { x: annotation.endX, y: annotation.endY, point: 'end' }
333
+ ];
334
+ for (const handle of lineHandles) {
335
+ if (x >= handle.x - handleSize / 2 && x <= handle.x + handleSize / 2 &&
336
+ y >= handle.y - handleSize / 2 && y <= handle.y + handleSize / 2) {
337
+ return handle.point; // Return which endpoint was clicked
338
+ }
339
+ }
340
+ return false;
341
+ default:
342
+ return false;
343
+ }
344
+ };
345
+ // Draw resize handles for rectangle annotation (only bottom-right corner)
346
+ this.drawRectangleResizeHandles = (annotation) => {
347
+ if (!this.canvasContext || annotation.type !== 'rectangle')
348
+ return;
349
+ const handleSize = 8;
350
+ const right = annotation.startX + annotation.width;
351
+ const bottom = annotation.startY + annotation.height;
352
+ // Only draw bottom-right corner handle
353
+ const handle = { x: right, y: bottom };
354
+ // Draw the handle
355
+ this.canvasContext.fillStyle = '#0070F4'; // Primary color
356
+ this.canvasContext.strokeStyle = '#ffffff';
357
+ this.canvasContext.lineWidth = 2;
358
+ this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
359
+ this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
360
+ };
361
+ // Draw resize handles for line/arrow annotation
362
+ this.drawLineResizeHandles = (annotation) => {
363
+ if (!this.canvasContext || (annotation.type !== 'line' && annotation.type !== 'arrow'))
364
+ return;
365
+ const handleSize = 8;
366
+ // Define handle positions (2 endpoints)
367
+ const handles = [
368
+ { x: annotation.startX, y: annotation.startY },
369
+ { x: annotation.endX, y: annotation.endY } // End point
370
+ ];
371
+ // Draw each handle
372
+ this.canvasContext.fillStyle = '#0070F4'; // Primary color
373
+ this.canvasContext.strokeStyle = '#ffffff';
374
+ this.canvasContext.lineWidth = 2;
375
+ handles.forEach(handle => {
376
+ this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
377
+ this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
378
+ });
379
+ };
380
+ // Start resize for shapes
381
+ this.startResize = (annotation, handle, startPos) => {
382
+ this.isResizing = true;
383
+ this.resizingAnnotation = annotation;
384
+ this.resizeHandle = handle;
385
+ this.dragStartPos = startPos;
386
+ // Store original values for different annotation types
387
+ if (annotation.type === 'rectangle') {
388
+ this.resizeStartDimensions = { width: annotation.width, height: annotation.height };
389
+ }
390
+ };
391
+ // Handle resize for different annotation types
392
+ this.handleResize = (currentPos) => {
393
+ if (!this.resizingAnnotation || !this.dragStartPos)
394
+ return;
395
+ const annotation = this.resizingAnnotation;
396
+ const index = this.annotations.findIndex(a => a === annotation);
397
+ if (index === -1)
398
+ return;
399
+ let updatedAnnotation = Object.assign({}, annotation);
400
+ switch (annotation.type) {
401
+ case 'rectangle':
402
+ // Rectangle resize logic - only bottom-right corner
403
+ const rectDeltaX = currentPos.x - this.dragStartPos.x;
404
+ const rectDeltaY = currentPos.y - this.dragStartPos.y;
405
+ // Update width and height based on original dimensions plus delta
406
+ updatedAnnotation.width = Math.max(10, this.resizeStartDimensions.width + rectDeltaX);
407
+ updatedAnnotation.height = Math.max(10, this.resizeStartDimensions.height + rectDeltaY);
408
+ break;
409
+ case 'line':
410
+ case 'arrow':
411
+ // Line/arrow resize logic - move endpoints
412
+ if (this.resizeHandle === 'start') {
413
+ updatedAnnotation.startX = currentPos.x;
414
+ updatedAnnotation.startY = currentPos.y;
415
+ }
416
+ else if (this.resizeHandle === 'end') {
417
+ updatedAnnotation.endX = currentPos.x;
418
+ updatedAnnotation.endY = currentPos.y;
419
+ }
420
+ break;
421
+ }
422
+ // Update annotation in array
423
+ this.annotations[index] = updatedAnnotation;
424
+ this.resizingAnnotation = updatedAnnotation;
425
+ this.redrawAnnotations();
426
+ };
427
+ // Text editing methods
428
+ this.startTextEditing = (annotation) => {
429
+ const newText = prompt(this.editTextPromptText, annotation.text);
430
+ if (newText !== null && newText.trim()) {
431
+ const index = this.annotations.findIndex(a => a === annotation);
432
+ if (index !== -1) {
433
+ this.annotations[index] = Object.assign(Object.assign({}, annotation), { text: newText.trim() });
434
+ this.selectedAnnotation = this.annotations[index];
435
+ this.redrawAnnotations();
436
+ }
437
+ }
438
+ };
439
+ // Update selected annotation font size
440
+ this.updateSelectedTextSize = (newSize) => {
441
+ if (this.selectedAnnotation && this.selectedAnnotation.type === 'text') {
442
+ const index = this.annotations.findIndex(a => a === this.selectedAnnotation);
443
+ if (index !== -1) {
444
+ this.annotations[index] = Object.assign(Object.assign({}, this.selectedAnnotation), { fontSize: Math.max(8, Math.min(72, newSize)) });
445
+ this.selectedAnnotation = this.annotations[index];
446
+ this.redrawAnnotations();
447
+ }
448
+ }
449
+ };
450
+ // Update selected annotation border width
451
+ this.updateSelectedBorderWidth = (newWidth) => {
452
+ if (this.selectedAnnotation && ['rectangle', 'line', 'arrow'].includes(this.selectedAnnotation.type)) {
453
+ const index = this.annotations.findIndex(a => a === this.selectedAnnotation);
454
+ if (index !== -1) {
455
+ this.annotations[index] = Object.assign(Object.assign({}, this.selectedAnnotation), { lineWidth: Math.max(1, Math.min(20, newWidth)) });
456
+ this.selectedAnnotation = this.annotations[index];
457
+ this.redrawAnnotations();
458
+ }
459
+ }
460
+ };
461
+ // Enhanced mouse down handler with resize support
462
+ this.handleCanvasMouseDown = (event) => {
463
+ if (!this.canvasRef)
464
+ return;
465
+ // Disable drawing on mobile devices
466
+ if (window.innerWidth <= 768)
467
+ return;
468
+ // Close color picker if open
469
+ if (this.showColorPicker) {
470
+ this.closeColorPicker();
471
+ }
472
+ const coords = this.getCanvasCoordinates(event);
473
+ // Check if clicking on existing annotation first
474
+ const found = this.findAnnotationAt(coords.x, coords.y);
475
+ if (found) {
476
+ // Select the annotation
477
+ this.selectedAnnotation = found.annotation;
478
+ // Check if clicking on resize handle for shapes (not text)
479
+ if (found.annotation.type !== 'text') {
480
+ const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
481
+ if (handle) {
482
+ this.startResize(found.annotation, handle, coords);
483
+ this.canvasRef.style.cursor = 'nw-resize';
484
+ return;
485
+ }
486
+ }
487
+ // Check for double-click to edit text
488
+ if (found.annotation.type === 'text' && event.detail === 2) {
489
+ this.startTextEditing(found.annotation);
490
+ return;
491
+ }
492
+ // Start dragging existing annotation
493
+ if (!this.isDrawing) {
494
+ this.isDragging = true;
495
+ this.draggedAnnotation = found.annotation;
496
+ this.dragStartPos = coords;
497
+ this.canvasRef.style.cursor = 'grabbing';
498
+ return;
499
+ }
500
+ }
501
+ else {
502
+ // Clear selection if clicking on empty space
503
+ this.selectedAnnotation = null;
504
+ }
505
+ // Original drawing logic
506
+ this.isDrawing = true;
507
+ if (this.canvasDrawingTool === 'text') {
508
+ const text = prompt(this.editTextPromptText);
509
+ if (text) {
510
+ const annotation = {
511
+ type: 'text',
512
+ x: coords.x,
513
+ y: coords.y,
514
+ text,
515
+ color: this.canvasDrawingColor,
516
+ fontSize: this.canvasTextSize
517
+ };
518
+ this.annotations = [...this.annotations, annotation];
519
+ this.redrawAnnotations();
520
+ }
521
+ this.isDrawing = false;
522
+ }
523
+ else {
524
+ this.currentAnnotation = {
525
+ type: this.canvasDrawingTool,
526
+ startX: coords.x,
527
+ startY: coords.y,
528
+ color: this.canvasDrawingColor,
529
+ lineWidth: this.canvasLineWidth
530
+ };
531
+ }
532
+ };
533
+ this.handleCanvasMouseMove = (event) => {
534
+ if (!this.canvasRef)
535
+ return;
536
+ // Disable drawing on mobile devices
537
+ if (window.innerWidth <= 768)
538
+ return;
539
+ const coords = this.getCanvasCoordinates(event);
540
+ // Handle resizing for shapes
541
+ if (this.isResizing && this.resizingAnnotation) {
542
+ this.handleResize(coords);
543
+ return;
544
+ }
545
+ // Handle dragging existing annotation
546
+ if (this.isDragging && this.draggedAnnotation && this.dragStartPos) {
547
+ const deltaX = coords.x - this.dragStartPos.x;
548
+ const deltaY = coords.y - this.dragStartPos.y;
549
+ // Update annotation position
550
+ const updatedAnnotation = Object.assign({}, this.draggedAnnotation);
551
+ switch (updatedAnnotation.type) {
552
+ case 'rectangle':
553
+ updatedAnnotation.startX += deltaX;
554
+ updatedAnnotation.startY += deltaY;
555
+ break;
556
+ case 'line':
557
+ case 'arrow':
558
+ updatedAnnotation.startX += deltaX;
559
+ updatedAnnotation.startY += deltaY;
560
+ updatedAnnotation.endX += deltaX;
561
+ updatedAnnotation.endY += deltaY;
562
+ break;
563
+ case 'text':
564
+ updatedAnnotation.x += deltaX;
565
+ updatedAnnotation.y += deltaY;
566
+ break;
567
+ }
568
+ // Update annotation in array
569
+ const index = this.annotations.findIndex(a => a === this.draggedAnnotation);
570
+ if (index !== -1) {
571
+ this.annotations[index] = updatedAnnotation;
572
+ this.draggedAnnotation = updatedAnnotation;
573
+ }
574
+ this.dragStartPos = coords;
575
+ this.redrawAnnotations();
576
+ return;
577
+ }
578
+ // Handle drawing new annotation
579
+ if (this.isDrawing && this.currentAnnotation) {
580
+ if (this.canvasDrawingTool === 'rectangle') {
581
+ this.currentAnnotation.width = coords.x - this.currentAnnotation.startX;
582
+ this.currentAnnotation.height = coords.y - this.currentAnnotation.startY;
583
+ }
584
+ else {
585
+ this.currentAnnotation.endX = coords.x;
586
+ this.currentAnnotation.endY = coords.y;
587
+ }
588
+ this.redrawAnnotations();
589
+ this.drawAnnotation(this.currentAnnotation);
590
+ return;
591
+ }
592
+ // Handle hover states and cursor changes
593
+ const found = this.findAnnotationAt(coords.x, coords.y);
594
+ if (found) {
595
+ // Check if hovering over resize handle for shapes (not text)
596
+ if (found.annotation.type !== 'text') {
597
+ const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
598
+ if (handle) {
599
+ this.canvasRef.style.cursor = 'nw-resize';
600
+ this.hoveredAnnotation = found.annotation;
601
+ this.redrawAnnotations();
602
+ return;
603
+ }
604
+ }
605
+ // Regular hover over annotation
606
+ this.canvasRef.style.cursor = 'grab';
607
+ if (this.hoveredAnnotation !== found.annotation) {
608
+ this.hoveredAnnotation = found.annotation;
609
+ this.redrawAnnotations();
610
+ }
611
+ }
612
+ else {
613
+ // No annotation under cursor
614
+ this.canvasRef.style.cursor = 'crosshair';
615
+ if (this.hoveredAnnotation) {
616
+ this.hoveredAnnotation = null;
617
+ this.redrawAnnotations();
618
+ }
619
+ }
620
+ };
621
+ this.handleCanvasMouseUp = () => {
622
+ // Disable drawing on mobile devices
623
+ if (window.innerWidth <= 768)
624
+ return;
625
+ // Handle end of resizing
626
+ if (this.isResizing) {
627
+ this.isResizing = false;
628
+ this.resizingAnnotation = null;
629
+ this.dragStartPos = null;
630
+ this.resizeHandle = false;
631
+ this.resizeStartDimensions = null;
632
+ if (this.canvasRef) {
633
+ this.canvasRef.style.cursor = 'crosshair';
634
+ }
635
+ return;
636
+ }
637
+ // Handle end of dragging
638
+ if (this.isDragging) {
639
+ this.isDragging = false;
640
+ this.draggedAnnotation = null;
641
+ this.dragStartPos = null;
642
+ if (this.canvasRef) {
643
+ this.canvasRef.style.cursor = 'crosshair';
644
+ }
645
+ return;
646
+ }
647
+ // Handle end of drawing
648
+ if (!this.isDrawing || !this.currentAnnotation)
649
+ return;
650
+ this.isDrawing = false;
651
+ this.annotations = [...this.annotations, this.currentAnnotation];
652
+ this.currentAnnotation = null;
653
+ this.redrawAnnotations();
654
+ };
655
+ // Convert screen coordinates to canvas coordinates
656
+ this.getCanvasCoordinates = (event) => {
657
+ if (!this.canvasRef)
658
+ return { x: 0, y: 0 };
659
+ const rect = this.canvasRef.getBoundingClientRect();
660
+ // Calculate the scale factor between display size and actual canvas size
661
+ const scaleX = this.canvasRef.width / rect.width;
662
+ const scaleY = this.canvasRef.height / rect.height;
663
+ const x = (event.clientX - rect.left) * scaleX;
664
+ const y = (event.clientY - rect.top) * scaleY;
665
+ return { x, y };
666
+ };
667
+ // Find annotation under mouse cursor
668
+ this.findAnnotationAt = (x, y) => {
669
+ // Check in reverse order (top to bottom)
670
+ for (let i = this.annotations.length - 1; i >= 0; i--) {
671
+ const annotation = this.annotations[i];
672
+ if (this.isPointInAnnotation(x, y, annotation)) {
673
+ return { annotation, index: i };
674
+ }
675
+ }
676
+ return null;
677
+ };
678
+ // Check if point is within annotation bounds
679
+ this.isPointInAnnotation = (x, y, annotation) => {
680
+ const tolerance = 10; // Click tolerance
681
+ switch (annotation.type) {
682
+ case 'rectangle':
683
+ const left = Math.min(annotation.startX, annotation.startX + annotation.width);
684
+ const right = Math.max(annotation.startX, annotation.startX + annotation.width);
685
+ const top = Math.min(annotation.startY, annotation.startY + annotation.height);
686
+ const bottom = Math.max(annotation.startY, annotation.startY + annotation.height);
687
+ return x >= left - tolerance && x <= right + tolerance &&
688
+ y >= top - tolerance && y <= bottom + tolerance;
689
+ case 'line':
690
+ case 'arrow':
691
+ // Distance from point to line
692
+ const A = annotation.endY - annotation.startY;
693
+ const B = annotation.startX - annotation.endX;
694
+ const C = annotation.endX * annotation.startY - annotation.startX * annotation.endY;
695
+ const distance = Math.abs(A * x + B * y + C) / Math.sqrt(A * A + B * B);
696
+ return distance <= tolerance;
697
+ case 'text':
698
+ // Use actual text dimensions for better dragging
699
+ const fontSize = annotation.fontSize || 24;
700
+ const textWidth = this.getTextWidth(annotation.text, fontSize);
701
+ const textHeight = fontSize;
702
+ // Text bounding box (y coordinate is baseline, so subtract font size for top)
703
+ const textLeft = annotation.x - tolerance;
704
+ const textRight = annotation.x + textWidth + tolerance;
705
+ const textTop = annotation.y - textHeight - tolerance;
706
+ const textBottom = annotation.y + tolerance;
707
+ return x >= textLeft && x <= textRight &&
708
+ y >= textTop && y <= textBottom;
709
+ default:
710
+ return false;
711
+ }
712
+ };
713
+ this.canvasEditorTitle = 'Edit screenshot';
714
+ this.canvasEditorCancelText = 'Cancel';
715
+ this.canvasEditorSaveText = 'Save';
716
+ this.screenshotTakingText = 'Taking screenshot...';
717
+ this.screenshotAttachedText = 'Screenshot attached';
718
+ this.screenshotButtonText = 'Add a screenshot';
719
+ this.autoStartScreenshot = false;
720
+ this.existingScreenshot = '';
721
+ this.editTextButtonText = 'Edit Text';
722
+ this.sizeLabelText = 'Size:';
723
+ this.borderLabelText = 'Border:';
724
+ this.editTextPromptText = 'Edit text:';
725
+ this.screenshotErrorGeneral = 'Failed to capture screenshot.';
726
+ this.screenshotErrorPermission = 'Permission denied. Please allow screen sharing to take screenshots.';
727
+ this.screenshotErrorNotSupported = 'Screen capture is not supported in this browser.';
728
+ this.screenshotErrorNotFound = 'No screen sources available for capture.';
729
+ this.screenshotErrorCancelled = 'Screenshot capture was cancelled.';
730
+ this.screenshotErrorBrowserNotSupported = 'Your browser does not support screen capture. Please use a browser like Chrome, Firefox, or Safari on desktop.';
731
+ this.screenshotErrorUnexpected = 'An unexpected error occurred. Please try again.';
732
+ this.takingScreenshot = false;
733
+ this.showCanvasEditor = false;
734
+ this.canvasDrawingTool = 'rectangle';
735
+ this.canvasDrawingColor = '#ff0000';
736
+ this.canvasLineWidth = 3;
737
+ this.canvasTextSize = 24;
738
+ this.isDrawing = false;
739
+ this.annotations = [];
740
+ this.currentAnnotation = null;
741
+ this.isDragging = false;
742
+ this.draggedAnnotation = null;
743
+ this.dragStartPos = null;
744
+ this.showColorPicker = false;
745
+ this.editingColorIndex = -1;
746
+ this.selectedAnnotation = null;
747
+ this.isResizing = false;
748
+ this.resizingAnnotation = null;
749
+ this.resizeStartSize = 24;
750
+ this.resizeStartDimensions = null;
751
+ this.hoveredAnnotation = null;
752
+ this.resizeHandle = false;
753
+ this.defaultColors = ['#ff0000', '#00ff00', '#0000ff', '#000000'];
754
+ }
755
+ componentDidLoad() {
756
+ if (this.autoStartScreenshot) {
757
+ // Show the editor UI and start screenshot capture
758
+ this.showCanvasEditor = true;
759
+ setTimeout(() => {
760
+ this.openScreenShot();
761
+ }, 100); // Small delay to ensure component is fully rendered
762
+ }
763
+ else if (this.existingScreenshot) {
764
+ // Show editor with existing screenshot data
765
+ this.originalImageData = this.existingScreenshot;
766
+ this.showCanvasEditor = true;
767
+ setTimeout(() => {
768
+ this.initializeCanvas();
769
+ }, 100);
770
+ }
771
+ }
772
+ async captureViewportScreenshot() {
773
+ try {
774
+ // Check if Screen Capture API is supported
775
+ if (!navigator.mediaDevices || !navigator.mediaDevices.getDisplayMedia) {
776
+ throw new Error('Screen Capture API is not supported in this browser');
777
+ }
778
+ // Request screen capture with preference for current tab
779
+ const stream = await navigator.mediaDevices.getDisplayMedia({
780
+ video: {
781
+ mediaSource: 'screen',
782
+ width: { ideal: window.innerWidth },
783
+ height: { ideal: window.innerHeight }
784
+ },
785
+ audio: false,
786
+ preferCurrentTab: true
787
+ });
788
+ // Create video element to capture frame
789
+ const video = document.createElement('video');
790
+ video.srcObject = stream;
791
+ video.autoplay = true;
792
+ video.muted = true;
793
+ return new Promise((resolve, reject) => {
794
+ video.onloadedmetadata = () => {
795
+ video.play();
796
+ // Wait a moment for video to stabilize
797
+ setTimeout(() => {
798
+ try {
799
+ // Create canvas to capture frame
800
+ const canvas = document.createElement('canvas');
801
+ canvas.width = video.videoWidth;
802
+ canvas.height = video.videoHeight;
803
+ const ctx = canvas.getContext('2d');
804
+ ctx.drawImage(video, 0, 0);
805
+ // Stop the stream
806
+ stream.getTracks().forEach(track => track.stop());
807
+ // Convert to data URL
808
+ const dataUrl = canvas.toDataURL('image/png');
809
+ console.log('Screenshot captured successfully using Screen Capture API');
810
+ resolve(dataUrl);
811
+ }
812
+ catch (error) {
813
+ stream.getTracks().forEach(track => track.stop());
814
+ reject(error);
815
+ }
816
+ }, 100);
817
+ };
818
+ video.onerror = () => {
819
+ stream.getTracks().forEach(track => track.stop());
820
+ reject(new Error('Failed to load video for screenshot capture'));
821
+ };
822
+ });
823
+ }
824
+ catch (error) {
825
+ console.error('Screen capture failed:', error);
826
+ throw error;
827
+ }
828
+ }
829
+ render() {
830
+ var _a, _b, _c, _d, _e, _f;
831
+ return (h("div", { class: "canvas-editor-wrapper" }, this.showCanvasEditor && (h("div", { class: "canvas-editor-overlay" }, h("div", { class: "canvas-editor-modal" }, h("div", { class: "canvas-editor-header" }, h("div", { class: "canvas-editor-title" }, h("h3", null, this.canvasEditorTitle)), h("div", { class: "canvas-editor-toolbar" }, h("div", { class: "toolbar-section" }, h("div", { class: "tool-group" }, h("button", { class: `tool-btn ${this.canvasDrawingTool === 'rectangle' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'rectangle', title: "Rectangle" }, h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'line' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'line', title: "Line" }, h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("line", { x1: "5", y1: "12", x2: "19", y2: "12" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'arrow' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'arrow', title: "Arrow" }, h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("line", { x1: "7", y1: "17", x2: "17", y2: "7" }), h("polyline", { points: "7,7 17,7 17,17" }))), h("button", { class: `tool-btn ${this.canvasDrawingTool === 'text' ? 'active' : ''}`, onClick: () => this.canvasDrawingTool = 'text', title: "Text" }, h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("polyline", { points: "4,7 4,4 20,4 20,7" }), h("line", { x1: "9", y1: "20", x2: "15", y2: "20" }), h("line", { x1: "12", y1: "4", x2: "12", y2: "20" }))), h("div", { class: "toolbar-divider" }), h("button", { class: "tool-btn undo-btn", onClick: this.undoLastAnnotation, disabled: this.annotations.length === 0, title: "Undo" }, h("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("polyline", { points: "1,4 1,10 7,10" }), h("path", { d: "M3.51,15a9,9,0,0,0,14.85-3.36,9,9,0,0,0-9.19-10.15L1.83,10" }))))), h("div", { class: "toolbar-section" }, h("div", { class: "color-palette" }, this.defaultColors.map((color, index) => (h("div", { class: "color-slot-wrapper" }, h("button", { class: `color-btn ${this.canvasDrawingColor === color ? 'active' : ''} ${this.editingColorIndex === index ? 'editing' : ''}`, style: { backgroundColor: color }, onClick: () => this.handleColorSlotClick(index), title: `Color ${index + 1} - Click to customize` }, this.editingColorIndex === index && (h("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "white", "stroke-width": "2" }, h("path", { d: "M21.174 6.812a1 1 0 0 0-3.986-3.987L3.842 16.174a2 2 0 0 0-.5.83l-1.321 4.352a.5.5 0 0 0 .623.622l4.353-1.32a2 2 0 0 0 .83-.497z" })))), this.editingColorIndex === index && this.showColorPicker && (h("div", { class: "color-picker-dropdown" }, h("input", { type: "color", value: color, onInput: (e) => this.handleColorPickerInput(e), onClick: (e) => this.handleColorPickerClick(e) })))))))), (this.selectedAnnotation || this.canvasDrawingTool) && (h("div", { class: "toolbar-section selected-annotation-controls" }, (((_a = this.selectedAnnotation) === null || _a === void 0 ? void 0 : _a.type) === 'text' || (!this.selectedAnnotation && this.canvasDrawingTool === 'text')) && (h("div", { class: "text-controls" }, h("div", { class: "font-size-control" }, h("label", null, this.sizeLabelText), h("input", { type: "range", min: "8", max: "72", value: ((_b = this.selectedAnnotation) === null || _b === void 0 ? void 0 : _b.fontSize) || this.canvasTextSize, onInput: (e) => {
832
+ const newSize = parseInt(e.target.value);
833
+ if (this.selectedAnnotation) {
834
+ this.updateSelectedTextSize(newSize);
835
+ }
836
+ else {
837
+ this.canvasTextSize = newSize;
838
+ }
839
+ }, class: "size-slider" }), h("span", { class: "size-value" }, ((_c = this.selectedAnnotation) === null || _c === void 0 ? void 0 : _c.fontSize) || this.canvasTextSize, "px")), this.selectedAnnotation && (h("button", { class: "action-btn small", onClick: () => this.startTextEditing(this.selectedAnnotation) }, this.editTextButtonText)))), ((['rectangle', 'line', 'arrow'].includes((_d = this.selectedAnnotation) === null || _d === void 0 ? void 0 : _d.type)) ||
840
+ (!this.selectedAnnotation && ['rectangle', 'line', 'arrow'].includes(this.canvasDrawingTool))) && (h("div", { class: "shape-controls" }, h("div", { class: "border-width-control" }, h("label", null, this.borderLabelText), h("input", { type: "range", min: "1", max: "20", value: ((_e = this.selectedAnnotation) === null || _e === void 0 ? void 0 : _e.lineWidth) || this.canvasLineWidth, onInput: (e) => {
841
+ const newWidth = parseInt(e.target.value);
842
+ if (this.selectedAnnotation) {
843
+ this.updateSelectedBorderWidth(newWidth);
844
+ }
845
+ else {
846
+ this.canvasLineWidth = newWidth;
847
+ }
848
+ }, class: "size-slider" }), h("span", { class: "size-value" }, ((_f = this.selectedAnnotation) === null || _f === void 0 ? void 0 : _f.lineWidth) || this.canvasLineWidth, "px")))))), h("div", { class: "toolbar-section" }, h("button", { class: "action-btn secondary", onClick: this.closeCanvasEditor }, this.canvasEditorCancelText), h("button", { class: "action-btn primary", onClick: this.saveAnnotations }, this.canvasEditorSaveText))), h("div", { class: "canvas-editor-content" }, h("canvas", { ref: (el) => this.canvasRef = el, class: "annotation-canvas", onMouseDown: this.handleCanvasMouseDown, onMouseMove: this.handleCanvasMouseMove, onMouseUp: this.handleCanvasMouseUp, onMouseLeave: this.handleCanvasMouseUp }))))))));
849
+ }
850
+ static get is() { return "canvas-editor"; }
851
+ static get encapsulation() { return "shadow"; }
852
+ static get originalStyleUrls() {
853
+ return {
854
+ "$": ["canvas-editor.css"]
855
+ };
856
+ }
857
+ static get styleUrls() {
858
+ return {
859
+ "$": ["canvas-editor.css"]
860
+ };
861
+ }
862
+ static get properties() {
863
+ return {
864
+ "canvasEditorTitle": {
865
+ "type": "string",
866
+ "mutable": false,
867
+ "complexType": {
868
+ "original": "string",
869
+ "resolved": "string",
870
+ "references": {}
871
+ },
872
+ "required": false,
873
+ "optional": false,
874
+ "docs": {
875
+ "tags": [],
876
+ "text": ""
877
+ },
878
+ "attribute": "canvas-editor-title",
879
+ "reflect": false,
880
+ "defaultValue": "'Edit screenshot'"
881
+ },
882
+ "canvasEditorCancelText": {
883
+ "type": "string",
884
+ "mutable": false,
885
+ "complexType": {
886
+ "original": "string",
887
+ "resolved": "string",
888
+ "references": {}
889
+ },
890
+ "required": false,
891
+ "optional": false,
892
+ "docs": {
893
+ "tags": [],
894
+ "text": ""
895
+ },
896
+ "attribute": "canvas-editor-cancel-text",
897
+ "reflect": false,
898
+ "defaultValue": "'Cancel'"
899
+ },
900
+ "canvasEditorSaveText": {
901
+ "type": "string",
902
+ "mutable": false,
903
+ "complexType": {
904
+ "original": "string",
905
+ "resolved": "string",
906
+ "references": {}
907
+ },
908
+ "required": false,
909
+ "optional": false,
910
+ "docs": {
911
+ "tags": [],
912
+ "text": ""
913
+ },
914
+ "attribute": "canvas-editor-save-text",
915
+ "reflect": false,
916
+ "defaultValue": "'Save'"
917
+ },
918
+ "screenshotTakingText": {
919
+ "type": "string",
920
+ "mutable": false,
921
+ "complexType": {
922
+ "original": "string",
923
+ "resolved": "string",
924
+ "references": {}
925
+ },
926
+ "required": false,
927
+ "optional": false,
928
+ "docs": {
929
+ "tags": [],
930
+ "text": ""
931
+ },
932
+ "attribute": "screenshot-taking-text",
933
+ "reflect": false,
934
+ "defaultValue": "'Taking screenshot...'"
935
+ },
936
+ "screenshotAttachedText": {
937
+ "type": "string",
938
+ "mutable": false,
939
+ "complexType": {
940
+ "original": "string",
941
+ "resolved": "string",
942
+ "references": {}
943
+ },
944
+ "required": false,
945
+ "optional": false,
946
+ "docs": {
947
+ "tags": [],
948
+ "text": ""
949
+ },
950
+ "attribute": "screenshot-attached-text",
951
+ "reflect": false,
952
+ "defaultValue": "'Screenshot attached'"
953
+ },
954
+ "screenshotButtonText": {
955
+ "type": "string",
956
+ "mutable": false,
957
+ "complexType": {
958
+ "original": "string",
959
+ "resolved": "string",
960
+ "references": {}
961
+ },
962
+ "required": false,
963
+ "optional": false,
964
+ "docs": {
965
+ "tags": [],
966
+ "text": ""
967
+ },
968
+ "attribute": "screenshot-button-text",
969
+ "reflect": false,
970
+ "defaultValue": "'Add a screenshot'"
971
+ },
972
+ "autoStartScreenshot": {
973
+ "type": "boolean",
974
+ "mutable": false,
975
+ "complexType": {
976
+ "original": "boolean",
977
+ "resolved": "boolean",
978
+ "references": {}
979
+ },
980
+ "required": false,
981
+ "optional": false,
982
+ "docs": {
983
+ "tags": [],
984
+ "text": ""
985
+ },
986
+ "attribute": "auto-start-screenshot",
987
+ "reflect": false,
988
+ "defaultValue": "false"
989
+ },
990
+ "existingScreenshot": {
991
+ "type": "string",
992
+ "mutable": false,
993
+ "complexType": {
994
+ "original": "string",
995
+ "resolved": "string",
996
+ "references": {}
997
+ },
998
+ "required": false,
999
+ "optional": false,
1000
+ "docs": {
1001
+ "tags": [],
1002
+ "text": ""
1003
+ },
1004
+ "attribute": "existing-screenshot",
1005
+ "reflect": false,
1006
+ "defaultValue": "''"
1007
+ },
1008
+ "editTextButtonText": {
1009
+ "type": "string",
1010
+ "mutable": false,
1011
+ "complexType": {
1012
+ "original": "string",
1013
+ "resolved": "string",
1014
+ "references": {}
1015
+ },
1016
+ "required": false,
1017
+ "optional": false,
1018
+ "docs": {
1019
+ "tags": [],
1020
+ "text": ""
1021
+ },
1022
+ "attribute": "edit-text-button-text",
1023
+ "reflect": false,
1024
+ "defaultValue": "'Edit Text'"
1025
+ },
1026
+ "sizeLabelText": {
1027
+ "type": "string",
1028
+ "mutable": false,
1029
+ "complexType": {
1030
+ "original": "string",
1031
+ "resolved": "string",
1032
+ "references": {}
1033
+ },
1034
+ "required": false,
1035
+ "optional": false,
1036
+ "docs": {
1037
+ "tags": [],
1038
+ "text": ""
1039
+ },
1040
+ "attribute": "size-label-text",
1041
+ "reflect": false,
1042
+ "defaultValue": "'Size:'"
1043
+ },
1044
+ "borderLabelText": {
1045
+ "type": "string",
1046
+ "mutable": false,
1047
+ "complexType": {
1048
+ "original": "string",
1049
+ "resolved": "string",
1050
+ "references": {}
1051
+ },
1052
+ "required": false,
1053
+ "optional": false,
1054
+ "docs": {
1055
+ "tags": [],
1056
+ "text": ""
1057
+ },
1058
+ "attribute": "border-label-text",
1059
+ "reflect": false,
1060
+ "defaultValue": "'Border:'"
1061
+ },
1062
+ "editTextPromptText": {
1063
+ "type": "string",
1064
+ "mutable": false,
1065
+ "complexType": {
1066
+ "original": "string",
1067
+ "resolved": "string",
1068
+ "references": {}
1069
+ },
1070
+ "required": false,
1071
+ "optional": false,
1072
+ "docs": {
1073
+ "tags": [],
1074
+ "text": ""
1075
+ },
1076
+ "attribute": "edit-text-prompt-text",
1077
+ "reflect": false,
1078
+ "defaultValue": "'Edit text:'"
1079
+ },
1080
+ "screenshotErrorGeneral": {
1081
+ "type": "string",
1082
+ "mutable": false,
1083
+ "complexType": {
1084
+ "original": "string",
1085
+ "resolved": "string",
1086
+ "references": {}
1087
+ },
1088
+ "required": false,
1089
+ "optional": false,
1090
+ "docs": {
1091
+ "tags": [],
1092
+ "text": ""
1093
+ },
1094
+ "attribute": "screenshot-error-general",
1095
+ "reflect": false,
1096
+ "defaultValue": "'Failed to capture screenshot.'"
1097
+ },
1098
+ "screenshotErrorPermission": {
1099
+ "type": "string",
1100
+ "mutable": false,
1101
+ "complexType": {
1102
+ "original": "string",
1103
+ "resolved": "string",
1104
+ "references": {}
1105
+ },
1106
+ "required": false,
1107
+ "optional": false,
1108
+ "docs": {
1109
+ "tags": [],
1110
+ "text": ""
1111
+ },
1112
+ "attribute": "screenshot-error-permission",
1113
+ "reflect": false,
1114
+ "defaultValue": "'Permission denied. Please allow screen sharing to take screenshots.'"
1115
+ },
1116
+ "screenshotErrorNotSupported": {
1117
+ "type": "string",
1118
+ "mutable": false,
1119
+ "complexType": {
1120
+ "original": "string",
1121
+ "resolved": "string",
1122
+ "references": {}
1123
+ },
1124
+ "required": false,
1125
+ "optional": false,
1126
+ "docs": {
1127
+ "tags": [],
1128
+ "text": ""
1129
+ },
1130
+ "attribute": "screenshot-error-not-supported",
1131
+ "reflect": false,
1132
+ "defaultValue": "'Screen capture is not supported in this browser.'"
1133
+ },
1134
+ "screenshotErrorNotFound": {
1135
+ "type": "string",
1136
+ "mutable": false,
1137
+ "complexType": {
1138
+ "original": "string",
1139
+ "resolved": "string",
1140
+ "references": {}
1141
+ },
1142
+ "required": false,
1143
+ "optional": false,
1144
+ "docs": {
1145
+ "tags": [],
1146
+ "text": ""
1147
+ },
1148
+ "attribute": "screenshot-error-not-found",
1149
+ "reflect": false,
1150
+ "defaultValue": "'No screen sources available for capture.'"
1151
+ },
1152
+ "screenshotErrorCancelled": {
1153
+ "type": "string",
1154
+ "mutable": false,
1155
+ "complexType": {
1156
+ "original": "string",
1157
+ "resolved": "string",
1158
+ "references": {}
1159
+ },
1160
+ "required": false,
1161
+ "optional": false,
1162
+ "docs": {
1163
+ "tags": [],
1164
+ "text": ""
1165
+ },
1166
+ "attribute": "screenshot-error-cancelled",
1167
+ "reflect": false,
1168
+ "defaultValue": "'Screenshot capture was cancelled.'"
1169
+ },
1170
+ "screenshotErrorBrowserNotSupported": {
1171
+ "type": "string",
1172
+ "mutable": false,
1173
+ "complexType": {
1174
+ "original": "string",
1175
+ "resolved": "string",
1176
+ "references": {}
1177
+ },
1178
+ "required": false,
1179
+ "optional": false,
1180
+ "docs": {
1181
+ "tags": [],
1182
+ "text": ""
1183
+ },
1184
+ "attribute": "screenshot-error-browser-not-supported",
1185
+ "reflect": false,
1186
+ "defaultValue": "'Your browser does not support screen capture. Please use a browser like Chrome, Firefox, or Safari on desktop.'"
1187
+ },
1188
+ "screenshotErrorUnexpected": {
1189
+ "type": "string",
1190
+ "mutable": false,
1191
+ "complexType": {
1192
+ "original": "string",
1193
+ "resolved": "string",
1194
+ "references": {}
1195
+ },
1196
+ "required": false,
1197
+ "optional": false,
1198
+ "docs": {
1199
+ "tags": [],
1200
+ "text": ""
1201
+ },
1202
+ "attribute": "screenshot-error-unexpected",
1203
+ "reflect": false,
1204
+ "defaultValue": "'An unexpected error occurred. Please try again.'"
1205
+ }
1206
+ };
1207
+ }
1208
+ static get states() {
1209
+ return {
1210
+ "takingScreenshot": {},
1211
+ "showCanvasEditor": {},
1212
+ "canvasDrawingTool": {},
1213
+ "canvasDrawingColor": {},
1214
+ "canvasLineWidth": {},
1215
+ "canvasTextSize": {},
1216
+ "isDrawing": {},
1217
+ "annotations": {},
1218
+ "currentAnnotation": {},
1219
+ "isDragging": {},
1220
+ "draggedAnnotation": {},
1221
+ "dragStartPos": {},
1222
+ "showColorPicker": {},
1223
+ "editingColorIndex": {},
1224
+ "selectedAnnotation": {},
1225
+ "isResizing": {},
1226
+ "resizingAnnotation": {},
1227
+ "resizeStartSize": {},
1228
+ "resizeStartDimensions": {},
1229
+ "hoveredAnnotation": {},
1230
+ "resizeHandle": {},
1231
+ "defaultColors": {}
1232
+ };
1233
+ }
1234
+ static get events() {
1235
+ return [{
1236
+ "method": "screenshotReady",
1237
+ "name": "screenshotReady",
1238
+ "bubbles": true,
1239
+ "cancelable": true,
1240
+ "composed": true,
1241
+ "docs": {
1242
+ "tags": [],
1243
+ "text": ""
1244
+ },
1245
+ "complexType": {
1246
+ "original": "{ screenshot: string }",
1247
+ "resolved": "{ screenshot: string; }",
1248
+ "references": {}
1249
+ }
1250
+ }, {
1251
+ "method": "screenshotCancelled",
1252
+ "name": "screenshotCancelled",
1253
+ "bubbles": true,
1254
+ "cancelable": true,
1255
+ "composed": true,
1256
+ "docs": {
1257
+ "tags": [],
1258
+ "text": ""
1259
+ },
1260
+ "complexType": {
1261
+ "original": "void",
1262
+ "resolved": "void",
1263
+ "references": {}
1264
+ }
1265
+ }, {
1266
+ "method": "screenshotFailed",
1267
+ "name": "screenshotFailed",
1268
+ "bubbles": true,
1269
+ "cancelable": true,
1270
+ "composed": true,
1271
+ "docs": {
1272
+ "tags": [],
1273
+ "text": ""
1274
+ },
1275
+ "complexType": {
1276
+ "original": "{ error: string }",
1277
+ "resolved": "{ error: string; }",
1278
+ "references": {}
1279
+ }
1280
+ }];
1281
+ }
1282
+ }