pushfeedback 0.1.66 → 0.1.68

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.
@@ -18,14 +18,14 @@ function commonjsRequire () {
18
18
 
19
19
  var html2canvasPro = createCommonjsModule(function (module, exports) {
20
20
  /*!
21
- * html2canvas-pro 1.5.8 <https://yorickshan.github.io/html2canvas-pro/>
22
- * Copyright (c) 2024 yorickshan <https://github.com/yorickshan>
21
+ * html2canvas-pro 1.5.11 <https://yorickshan.github.io/html2canvas-pro/>
22
+ * Copyright (c) 2024-present yorickshan and html2canvas-pro contributors
23
23
  * Released under MIT License
24
24
  */
25
25
  (function (global, factory) {
26
26
  module.exports = factory() ;
27
27
  })(commonjsGlobal, (function () {
28
- /*! *****************************************************************************
28
+ /******************************************************************************
29
29
  Copyright (c) Microsoft Corporation.
30
30
 
31
31
  Permission to use, copy, modify, and/or distribute this software for any
@@ -39,7 +39,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
39
39
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
40
40
  PERFORMANCE OF THIS SOFTWARE.
41
41
  ***************************************************************************** */
42
- /* global Reflect, Promise */
42
+ /* global Reflect, Promise, SuppressedError, Symbol */
43
43
 
44
44
  var extendStatics = function(d, b) {
45
45
  extendStatics = Object.setPrototypeOf ||
@@ -83,7 +83,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
83
83
  function verb(n) { return function (v) { return step([n, v]); }; }
84
84
  function step(op) {
85
85
  if (f) throw new TypeError("Generator is already executing.");
86
- while (_) try {
86
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
87
87
  if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
88
88
  if (y = 0, t) op = [op[0] & 2, t.value];
89
89
  switch (op[0]) {
@@ -112,8 +112,13 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
112
112
  ar[i] = from[i];
113
113
  }
114
114
  }
115
- return to.concat(ar || from);
116
- }
115
+ return to.concat(ar || Array.prototype.slice.call(from));
116
+ }
117
+
118
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
119
+ var e = new Error(message);
120
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
121
+ };
117
122
 
118
123
  var Bounds = /** @class */ (function () {
119
124
  function Bounds(left, top, width, height) {
@@ -3748,7 +3753,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
3748
3753
  case 'gurmukhi':
3749
3754
  return 22 /* LIST_STYLE_TYPE.GURMUKHI */;
3750
3755
  case 'hebrew':
3751
- return 22 /* LIST_STYLE_TYPE.HEBREW */;
3756
+ return 52 /* LIST_STYLE_TYPE.HEBREW */;
3752
3757
  case 'hiragana':
3753
3758
  return 23 /* LIST_STYLE_TYPE.HIRAGANA */;
3754
3759
  case 'hiragana-iroha':
@@ -6024,7 +6029,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
6024
6029
  return createCounterStyleFromRange(value, 0xae6, 0xaef, true, defaultSuffix);
6025
6030
  case 22 /* LIST_STYLE_TYPE.GURMUKHI */:
6026
6031
  return createCounterStyleFromRange(value, 0xa66, 0xa6f, true, defaultSuffix);
6027
- case 22 /* LIST_STYLE_TYPE.HEBREW */:
6032
+ case 52 /* LIST_STYLE_TYPE.HEBREW */:
6028
6033
  return createAdditiveCounter(value, 1, 10999, HEBREW, 3 /* LIST_STYLE_TYPE.DECIMAL */, defaultSuffix);
6029
6034
  case 23 /* LIST_STYLE_TYPE.HIRAGANA */:
6030
6035
  return createCounterStyleFromSymbols(value, 'あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよらりるれろわゐゑをん');
@@ -6483,8 +6488,8 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
6483
6488
  });
6484
6489
  };
6485
6490
  var ignoredStyleProperties = [
6486
- 'all',
6487
- 'd',
6491
+ 'all', // #2476
6492
+ 'd', // #2483
6488
6493
  'content' // Safari shows pseudoelements if content is set
6489
6494
  ];
6490
6495
  var copyCSSStyles = function (style, target) {
@@ -6601,12 +6606,21 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
6601
6606
  };
6602
6607
  Cache.prototype.loadImage = function (key) {
6603
6608
  return __awaiter(this, void 0, void 0, function () {
6604
- var isSameOrigin, useCORS, useProxy, src;
6609
+ var isSameOrigin, _a, useCORS, useProxy, src;
6605
6610
  var _this = this;
6606
- return __generator(this, function (_a) {
6607
- switch (_a.label) {
6611
+ return __generator(this, function (_b) {
6612
+ switch (_b.label) {
6608
6613
  case 0:
6609
- isSameOrigin = CacheStorage.isSameOrigin(key);
6614
+ if (!(typeof this._options.customIsSameOrigin === 'function')) return [3 /*break*/, 2];
6615
+ return [4 /*yield*/, this._options.customIsSameOrigin(key, CacheStorage.isSameOrigin)];
6616
+ case 1:
6617
+ _a = _b.sent();
6618
+ return [3 /*break*/, 3];
6619
+ case 2:
6620
+ _a = CacheStorage.isSameOrigin(key);
6621
+ _b.label = 3;
6622
+ case 3:
6623
+ isSameOrigin = _a;
6610
6624
  useCORS = !isInlineImage(key) && this._options.useCORS === true && FEATURES.SUPPORT_CORS_IMAGES && !isSameOrigin;
6611
6625
  useProxy = !isInlineImage(key) &&
6612
6626
  !isSameOrigin &&
@@ -6623,12 +6637,12 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
6623
6637
  return [2 /*return*/];
6624
6638
  }
6625
6639
  src = key;
6626
- if (!useProxy) return [3 /*break*/, 2];
6640
+ if (!useProxy) return [3 /*break*/, 5];
6627
6641
  return [4 /*yield*/, this.proxy(src)];
6628
- case 1:
6629
- src = _a.sent();
6630
- _a.label = 2;
6631
- case 2:
6642
+ case 4:
6643
+ src = _b.sent();
6644
+ _b.label = 5;
6645
+ case 5:
6632
6646
  this.context.logger.debug("Added image ".concat(key.substring(0, 256)));
6633
6647
  return [4 /*yield*/, new Promise(function (resolve, reject) {
6634
6648
  var img = new Image();
@@ -6647,7 +6661,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
6647
6661
  setTimeout(function () { return reject("Timed out (".concat(_this._options.imageTimeout, "ms) loading image")); }, _this._options.imageTimeout);
6648
6662
  }
6649
6663
  })];
6650
- case 3: return [2 /*return*/, _a.sent()];
6664
+ case 6: return [2 /*return*/, _b.sent()];
6651
6665
  }
6652
6666
  });
6653
6667
  });
@@ -7773,7 +7787,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
7773
7787
  };
7774
7788
  CanvasRenderer.prototype.renderNodeContent = function (paint) {
7775
7789
  return __awaiter(this, void 0, void 0, function () {
7776
- var container, curves, styles, _i, _a, child, image, image, iframeRenderer, canvas, size, _b, fontFamily, fontSize, baseline, bounds, x, textBounds, img, image, url, fontFamily, bounds;
7790
+ var container, curves, styles, _i, _a, child, image, image, iframeRenderer, canvas, size, _b, font, fontFamily, fontSize, baseline, bounds, x, textBounds, img, image, url, font, bounds;
7777
7791
  return __generator(this, function (_c) {
7778
7792
  switch (_c.label) {
7779
7793
  case 0:
@@ -7873,9 +7887,9 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
7873
7887
  }
7874
7888
  }
7875
7889
  if (isTextInputElement(container) && container.value.length) {
7876
- _b = this.createFontStyle(styles), fontFamily = _b[0], fontSize = _b[1];
7890
+ _b = this.createFontStyle(styles), font = _b[0], fontFamily = _b[1], fontSize = _b[2];
7877
7891
  baseline = this.fontMetrics.getMetrics(fontFamily, fontSize).baseline;
7878
- this.ctx.font = fontFamily;
7892
+ this.ctx.font = font;
7879
7893
  this.ctx.fillStyle = asString(styles.color);
7880
7894
  this.ctx.textBaseline = 'alphabetic';
7881
7895
  this.ctx.textAlign = canvasTextAlign(container.styles.textAlign);
@@ -7924,8 +7938,8 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
7924
7938
  case 18: return [3 /*break*/, 20];
7925
7939
  case 19:
7926
7940
  if (paint.listValue && container.styles.listStyleType !== -1 /* LIST_STYLE_TYPE.NONE */) {
7927
- fontFamily = this.createFontStyle(styles)[0];
7928
- this.ctx.font = fontFamily;
7941
+ font = this.createFontStyle(styles)[0];
7942
+ this.ctx.font = font;
7929
7943
  this.ctx.fillStyle = asString(styles.color);
7930
7944
  this.ctx.textBaseline = 'middle';
7931
7945
  this.ctx.textAlign = 'right';
@@ -8155,7 +8169,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
8155
8169
  canvas.height = height;
8156
8170
  ctx = canvas.getContext('2d');
8157
8171
  gradient_1 = ctx.createLinearGradient(x0, y0, x1, y1);
8158
- processColorStops(backgroundImage.stops, lineLength).forEach(function (colorStop) {
8172
+ processColorStops(backgroundImage.stops, lineLength || 1).forEach(function (colorStop) {
8159
8173
  return gradient_1.addColorStop(colorStop.stop, asString(colorStop.color));
8160
8174
  });
8161
8175
  ctx.fillStyle = gradient_1;
@@ -8690,7 +8704,8 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
8690
8704
  allowTaint: (_b = opts.allowTaint) !== null && _b !== void 0 ? _b : false,
8691
8705
  imageTimeout: (_c = opts.imageTimeout) !== null && _c !== void 0 ? _c : 15000,
8692
8706
  proxy: opts.proxy,
8693
- useCORS: (_d = opts.useCORS) !== null && _d !== void 0 ? _d : false
8707
+ useCORS: (_d = opts.useCORS) !== null && _d !== void 0 ? _d : false,
8708
+ customIsSameOrigin: opts.customIsSameOrigin
8694
8709
  };
8695
8710
  contextOptions = __assign({ logging: (_e = opts.logging) !== null && _e !== void 0 ? _e : true, cache: opts.cache }, resourceOptions);
8696
8711
  windowOptions = {
@@ -8791,7 +8806,7 @@ var html2canvasPro = createCommonjsModule(function (module, exports) {
8791
8806
  //# sourceMappingURL=html2canvas-pro.js.map
8792
8807
  });
8793
8808
 
8794
- const feedbackModalCss = ".text-center{flex-grow:1;text-align:center}.feedback-modal-wrapper *{font-family:var(--feedback-font-family)}.feedback-modal-wrapper--custom-font *{font-family:inherit}.feedback-modal-wrapper{position:absolute;z-index:var(--feedback-modal-modal-wrapper-z-index)}.feedback-overlay{background-color:var(--feedback-modal-screenshot-bg-color);height:100%;left:0;opacity:0;position:fixed;top:0;width:100%;z-index:var(--feedback-modal-screnshot-z-index);transition:opacity 0.2s ease-out}.feedback-overlay--visible{opacity:1}.feedback-modal{display:inline-block;position:relative}.feedback-modal-content{background-color:var(--feedback-modal-content-bg-color);border-color:1px solid var(--feedback-modal-header-text-color);border-radius:var(--feedback-modal-content-border-radius);box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);box-sizing:border-box;color:var(--feedback-modal-content-text-color);display:flex;flex-direction:column;left:50%;max-width:90%;padding:20px;position:fixed;top:50%;transform:translate(-50%, -50%) scale(0.95);opacity:0;width:100%;z-index:var(--feedback-modal-content-z-index);transition:transform 0.2s ease-out, opacity 0.2s ease-out}.feedback-modal-content--open{transform:translate(-50%, -50%) scale(1);opacity:1}.feedback-modal-header{align-items:center;color:var(--feedback-modal-header-text-color);display:flex;font-size:var(--feedback-header-font-size);font-weight:var(--feedback-modal-header-font-weight);justify-content:space-between;margin-bottom:20px}.feedback-modal-rating-buttons{width:100%;margin-bottom:20px}.feedback-modal-rating-button{padding:0;background-color:transparent;border:transparent;margin-right:5px;cursor:pointer}.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button{border:1px solid var(--feedback-modal-button-border-color);border-radius:var(--feedback-modal-button-border-radius);color:var(--feedback-modal-button-text-color);font-size:var(--feedback-modal-button-font-size);font-weight:500;margin-right:10px;justify-content:center;padding:5px 10px}.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button:hover,.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button--selected{background-color:var(--feedback-modal-button-bg-color-active);border:1px solid var(--feedback-modal-button-border-color-active);color:var(--feedback-modal-button-text-color-active)}.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button:hover svg,.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button--selected svg{stroke:var(--feedback-modal-rating-button-selected-color)}.feedback-modal-rating-buttons svg{stroke:var(--feedback-modal-rating-button-color);cursor:pointer}.feedback-modal-rating-buttons--stars .feedback-modal-rating-button--selected svg{fill:var(--feedback-modal-rating-button-stars-selected-color);stroke:var(--feedback-modal-rating-button-stars-selected-color)}.feedback-modal-text textarea{background-color:var(--feedback-modal-input-bg-color);border:1px solid var(--feedback-modal-input-border-color);border-radius:var(--feedback-modal-input-border-radius);box-sizing:border-box;color:var(--feedback-modal-input-text-color);font-size:var(--feedback-modal-input-font-size);margin-bottom:20px;height:100px;min-height:100px;padding:10px;resize:vertical;width:100%}.feedback-modal-email input{background-color:var(--feedback-modal-input-bg-color);border:1px solid var(--feedback-modal-input-border-color);border-radius:var(--feedback-modal-input-border-radius);box-sizing:border-box;color:var(--feedback-modal-input-text-color);font-size:var(--feedback-modal-input-font-size);margin-bottom:20px;height:40px;padding:10px;width:100%;margin-bottom:20px}.feedback-modal-privacy{font-size:var(--feedback-modal-input-font-size);margin-bottom:20px}.feedback-modal-text textarea:focus,.feedback-modal-email input:focus{border:1px solid var(--feedback-modal-input-border-color-focused);outline:none}.feedback-modal-buttons{display:flex;flex-direction:column}.feedback-modal-buttons .feedback-modal-button{margin-bottom:20px}.feedback-modal-button{align-items:center;background-color:transparent;border:1px solid var(--feedback-modal-button-border-color);border-radius:var(--feedback-modal-button-border-radius);color:var(--feedback-modal-button-text-color);cursor:pointer;display:flex;font-size:var(--feedback-modal-button-font-size);font-weight:500;justify-content:center;min-height:40px;padding:5px 10px}.feedback-modal-button svg{margin-right:6px}.feedback-modal-button path{fill:var(--feedback-modal-button-icon-color)}.feedback-modal-button:hover path,.feedback-modal-button--active path{fill:var(--feedback-modal-button-icon-color-active)}.feedback-modal-button--submit{background-color:var(--feedback-modal-button-submit-bg-color);border:1px solid var(--feedback-modal-button-border-color-active);color:var(--feedback-modal-button-submit-text-color)}.feedback-modal-button:hover,.feedback-modal-button--active{background-color:var(--feedback-modal-button-bg-color-active);border:1px solid var(--feedback-modal-button-border-color-active);color:var(--feedback-modal-button-text-color-active)}.feedback-modal-button--submit:hover{background-color:var(--feedback-modal-button-submit-bg-color-hover);border:1px solid var(--feedback-modal-button-submit-border-color-hover);color:var(--feedback-modal-button-submit-text-color-hover)}.feedback-modal-input-heading{display:block;font-size:14px;font-weight:300;padding-bottom:10px}.feedback-modal-footer{font-size:12px;text-align:center}.feedback-modal-footer a{color:var(--feedback-modal-footer-link);font-weight:500;text-decoration:none}.feedback-logo,.feedback-footer-text{display:block;text-align:center;margin-top:5px}.feedback-footer-text{margin-top:10px;line-height:1.5}.feedback-modal-close{background-color:var(--feedback-modal-close-bg-color);border:0;border-radius:50%;cursor:pointer;height:22px;margin-left:auto;padding:0;width:22px}.feedback-modal-close svg{stroke:var(--feedback-modal-close-color)}.feedback-modal-screenshot{background-color:var(--feedback-modal-screenshot-bg-color);height:100%;left:0;position:fixed;top:0;width:100%;z-index:var(--feedback-modal-screnshot-z-index)}.feedback-modal-screenshot-header{align-items:center;background-color:var(--feedback-modal-screenshot-header-bg-color);border-radius:var(--feedback-modal-content-border-radius);box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);box-sizing:border-box;color:var(--feedback-modal-screenshot-header-text-color);cursor:pointer;display:flex;left:50%;top:20px;transform:translateX(-50%);padding:10px;position:fixed;width:max-content;z-index:var(--feedback-modal-screenshot-header-z-index)}.feedback-modal-screenshot-close{height:24px;padding-left:10px;width:24px}.feedback-modal-screenshot-close svg{stroke:var(--feedback-modal-close-color)}.feedback-modal-message{font-size:var(--feedback-modal-message-font-size);margin-top:0}.feedback-modal-element-hover{background-color:transparent;cursor:pointer;border:1px solid var(--feedback-modal-element-hover-border-color)}.feedback-modal-element-selected{background-color:transparent;border:1px solid var(--feedback-modal-element-selected-border-color)}.screenshot-preview{display:inline-block;width:30px;height:30px;overflow:hidden;border-radius:4px;margin-right:10px;box-shadow:0 2px 4px rgba(0, 0, 0, 0.1);cursor:pointer}.screenshot-preview img{width:100%;height:100%;object-fit:cover}.preview-modal{position:fixed;top:50%;left:50%;transform:translate(-50%, -50%);background-color:rgba(0, 0, 0, 0.8);padding:20px;border-radius:8px;z-index:1000}.preview-modal img{max-width:90vw;max-height:90vh}@media screen and (min-width: 768px){.feedback-modal-content{max-width:var(--feedback-modal-content-max-width)}.feedback-modal-content.feedback-modal-content--bottom-right{bottom:var(--feedback-modal-content-position-bottom);left:initial;right:var(--feedback-modal-content-position-right);top:initial;transform:initial}.feedback-modal-content.feedback-modal-content--bottom-left{bottom:var(--feedback-modal-content-position-bottom);left:var(--feedback-modal-content-position-left);top:initial;transform:initial}.feedback-modal-content.feedback-modal-content--top-right{right:var(--feedback-modal-content-position-right);top:var(--feedback-modal-content-position-top);transform:initial}.feedback-modal-content.feedback-modal-content--top-left{left:var(--feedback-modal-content-position-left);top:var(--feedback-modal-content-position-top);transform:initial}.feedback-modal-content.feedback-modal-content--center-left{left:5px;right:auto;top:50%;transform:translateY(-50%)}.feedback-modal-content.feedback-modal-content--center-right{left:auto;right:5px;top:50%;transform:translateY(-50%)}.feedback-modal-content.feedback-modal-content--sidebar-left.feedback-modal-content--open,.feedback-modal-content.feedback-modal-content--sidebar-right.feedback-modal-content--open{transform:translateX(0)}.feedback-modal-content.feedback-modal-content--sidebar-left{max-width:var(--feedback-modal-content-sidebar-max-width);left:0;right:auto;height:100vh;top:0;transform:translateX(-100%);transition:transform 0.5s ease-in-out;border-radius:0}.feedback-modal-content.feedback-modal-content--sidebar-right{max-width:var(--feedback-modal-content-sidebar-max-width);left:auto;right:0;height:100vh;top:0;transform:translateX(100%);transition:transform 0.5s ease-in-out;border-radius:0}.feedback-modal-text textarea{height:150px;min-height:150px}.feedback-modal-content.feedback-modal-content--bottom-right{transform:translateY(20px)}.feedback-modal-content.feedback-modal-content--bottom-right.feedback-modal-content--open{transform:translateY(0)}.feedback-modal-content.feedback-modal-content--bottom-left{transform:translateY(20px)}.feedback-modal-content.feedback-modal-content--bottom-left.feedback-modal-content--open{transform:translateY(0)}.feedback-modal-content.feedback-modal-content--top-right{transform:translateY(-20px)}.feedback-modal-content.feedback-modal-content--top-right.feedback-modal-content--open{transform:translateY(0)}.feedback-modal-content.feedback-modal-content--top-left{transform:translateY(-20px)}.feedback-modal-content.feedback-modal-content--top-left.feedback-modal-content--open{transform:translateY(0)}}";
8809
+ const feedbackModalCss = ".text-center{flex-grow:1;text-align:center}.feedback-modal-wrapper *{font-family:var(--feedback-font-family)}.feedback-modal-wrapper--custom-font *{font-family:inherit}.feedback-modal-wrapper{position:absolute;z-index:var(--feedback-modal-modal-wrapper-z-index)}.feedback-overlay{background-color:var(--feedback-modal-screenshot-bg-color);height:100%;left:0;opacity:0;position:fixed;top:0;width:100%;z-index:var(--feedback-modal-screnshot-z-index);transition:opacity 0.2s ease-out}.feedback-overlay--visible{opacity:1}.feedback-modal{display:inline-block;position:relative}.feedback-modal-content{background-color:var(--feedback-modal-content-bg-color);border-color:1px solid var(--feedback-modal-header-text-color);border-radius:var(--feedback-modal-content-border-radius);box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);box-sizing:border-box;color:var(--feedback-modal-content-text-color);display:flex;flex-direction:column;left:50%;max-width:90%;padding:20px;position:fixed;top:50%;transform:translate(-50%, -50%) scale(0.95);opacity:0;width:100%;z-index:var(--feedback-modal-content-z-index);transition:transform 0.2s ease-out, opacity 0.2s ease-out}.feedback-modal-content--open{transform:translate(-50%, -50%) scale(1);opacity:1}.feedback-modal-header{align-items:center;color:var(--feedback-modal-header-text-color);display:flex;font-size:var(--feedback-header-font-size);font-weight:var(--feedback-modal-header-font-weight);justify-content:space-between;margin-bottom:20px}.feedback-modal-rating-buttons{width:100%;margin-bottom:20px}.feedback-modal-rating-button{padding:0;background-color:transparent;border:transparent;margin-right:5px;cursor:pointer}.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button{border:1px solid var(--feedback-modal-button-border-color);border-radius:var(--feedback-modal-button-border-radius);color:var(--feedback-modal-button-text-color);font-size:var(--feedback-modal-button-font-size);font-weight:500;margin-right:10px;justify-content:center;padding:5px 10px}.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button:hover,.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button--selected{background-color:var(--feedback-modal-button-bg-color-active);border:1px solid var(--feedback-modal-button-border-color-active);color:var(--feedback-modal-button-text-color-active)}.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button:hover svg,.feedback-modal-rating-buttons--thumbs .feedback-modal-rating-button--selected svg{stroke:var(--feedback-modal-rating-button-selected-color)}.feedback-modal-rating-buttons svg{stroke:var(--feedback-modal-rating-button-color);cursor:pointer}.feedback-modal-rating-buttons--stars .feedback-modal-rating-button--selected svg{fill:var(--feedback-modal-rating-button-stars-selected-color);stroke:var(--feedback-modal-rating-button-stars-selected-color)}.feedback-modal-text textarea{background-color:var(--feedback-modal-input-bg-color);border:1px solid var(--feedback-modal-input-border-color);border-radius:var(--feedback-modal-input-border-radius);box-sizing:border-box;color:var(--feedback-modal-input-text-color);font-size:var(--feedback-modal-input-font-size);margin-bottom:20px;height:100px;min-height:100px;padding:10px;resize:vertical;width:100%}.feedback-modal-email input{background-color:var(--feedback-modal-input-bg-color);border:1px solid var(--feedback-modal-input-border-color);border-radius:var(--feedback-modal-input-border-radius);box-sizing:border-box;color:var(--feedback-modal-input-text-color);font-size:var(--feedback-modal-input-font-size);margin-bottom:20px;height:40px;padding:10px;width:100%;margin-bottom:20px}.feedback-modal-privacy{font-size:var(--feedback-modal-input-font-size);margin-bottom:20px}.feedback-modal-text textarea:focus,.feedback-modal-email input:focus{border:1px solid var(--feedback-modal-input-border-color-focused);outline:none}.feedback-modal-buttons{display:flex;flex-direction:column}.feedback-modal-buttons .feedback-modal-button{margin-bottom:20px}.feedback-modal-button{align-items:center;background-color:transparent;border:1px solid var(--feedback-modal-button-border-color);border-radius:var(--feedback-modal-button-border-radius);color:var(--feedback-modal-button-text-color);cursor:pointer;display:flex;font-size:var(--feedback-modal-button-font-size);font-weight:500;justify-content:center;min-height:40px;padding:5px 10px}.feedback-modal-button svg{margin-right:6px}.feedback-modal-button path{fill:var(--feedback-modal-button-icon-color)}.feedback-modal-button:hover path,.feedback-modal-button--active path{fill:var(--feedback-modal-button-icon-color-active)}.feedback-modal-button--submit{background-color:var(--feedback-modal-button-submit-bg-color);border:1px solid var(--feedback-modal-button-border-color-active);color:var(--feedback-modal-button-submit-text-color)}.feedback-modal-button:hover,.feedback-modal-button--active{background-color:var(--feedback-modal-button-bg-color-active);border:1px solid var(--feedback-modal-button-border-color-active);color:var(--feedback-modal-button-text-color-active)}.feedback-modal-button--submit:hover{background-color:var(--feedback-modal-button-submit-bg-color-hover);border:1px solid var(--feedback-modal-button-submit-border-color-hover);color:var(--feedback-modal-button-submit-text-color-hover)}.feedback-modal-input-heading{display:block;font-size:14px;font-weight:300;padding-bottom:10px}.feedback-modal-footer{font-size:12px;text-align:center}.feedback-modal-footer a{color:var(--feedback-modal-footer-link);font-weight:500;text-decoration:none}.feedback-logo,.feedback-footer-text{display:block;text-align:center;margin-top:5px}.feedback-footer-text{margin-top:10px;line-height:1.5}.feedback-modal-close{background-color:var(--feedback-modal-close-bg-color);border:0;border-radius:50%;cursor:pointer;height:22px;margin-left:auto;padding:0;width:22px}.feedback-modal-close svg{stroke:var(--feedback-modal-close-color)}.feedback-modal-screenshot{background-color:var(--feedback-modal-screenshot-bg-color);height:100%;left:0;position:fixed;top:0;width:100%;z-index:var(--feedback-modal-screnshot-z-index)}.feedback-modal-screenshot-header{align-items:center;background-color:var(--feedback-modal-screenshot-header-bg-color);border-radius:var(--feedback-modal-content-border-radius);box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);box-sizing:border-box;color:var(--feedback-modal-screenshot-header-text-color);cursor:pointer;display:flex;left:50%;top:20px;transform:translateX(-50%);padding:10px;position:fixed;width:max-content;z-index:var(--feedback-modal-screenshot-header-z-index)}.feedback-modal-screenshot-close{height:24px;padding-left:10px;width:24px}.feedback-modal-screenshot-close svg{stroke:var(--feedback-modal-close-color)}.feedback-modal-message{font-size:var(--feedback-modal-message-font-size);margin-top:0}.feedback-modal-element-hover{background-color:transparent;cursor:pointer;border:1px solid var(--feedback-modal-element-hover-border-color)}.feedback-modal-element-selected{background-color:transparent;border:3px solid var(--feedback-modal-element-selected-border-color) !important;box-shadow:0 0 0 2px rgba(0, 123, 255, 0.3) !important}.screenshot-preview{display:inline-block;width:30px;height:30px;overflow:hidden;border-radius:4px;margin-right:10px;box-shadow:0 2px 4px rgba(0, 0, 0, 0.1);cursor:pointer;transition:transform 0.2s ease}.screenshot-preview:hover{transform:scale(1.1)}.screenshot-preview img{width:100%;height:100%;object-fit:cover}.screenshot-loading{display:inline-flex;align-items:center;margin-right:8px}.canvas-editor-overlay{position:fixed;top:0;left:0;right:0;bottom:0;background-color:var(--feedback-modal-screenshot-bg-color);z-index:10001;display:flex;align-items:center;justify-content:center}.canvas-editor-modal{width:95vw;height:98vh;background:var(--feedback-canvas-editor-bg-color);border-radius:var(--feedback-modal-content-border-radius);display:flex;flex-direction:column;overflow:hidden;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15)}.canvas-editor-header{background:var(--feedback-canvas-editor-header-bg-color);border-bottom:1px solid var(--feedback-canvas-editor-border-color);padding:12px 16px;display:flex;flex-direction:column;gap:12px;flex-shrink:0}.canvas-editor-title h3{margin:0;font-size:var(--feedback-modal-header-font-size);font-weight:var(--feedback-modal-header-font-weight);color:var(--feedback-modal-header-text-color);font-family:var(--feedback-modal-header-font-family)}.canvas-editor-toolbar{display:flex;align-items:center;gap:20px;flex-wrap:wrap}.toolbar-section{display:flex;align-items:center}.toolbar-section:last-child{margin-left:auto;gap:10px}.tool-group{display:flex;align-items:center;background:var(--feedback-canvas-editor-tool-bg-color);border:1px solid var(--feedback-canvas-editor-border-color);border-radius:var(--feedback-modal-button-border-radius);padding:4px;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .10)}.tool-btn{display:flex;align-items:center;justify-content:center;width:36px;height:36px;border:none;background:none;border-radius:var(--feedback-modal-button-border-radius);cursor:pointer;color:var(--feedback-canvas-editor-tool-text-color);transition:all 0.2s ease;position:relative}.tool-btn:hover{background:var(--feedback-canvas-editor-tool-bg-hover);color:var(--feedback-modal-button-text-color-active)}.tool-btn.active{background:var(--feedback-canvas-editor-tool-bg-active);color:var(--feedback-canvas-editor-tool-text-active)}.tool-btn:disabled{opacity:0.4;cursor:not-allowed}.tool-btn:disabled:hover{background:none;color:var(--feedback-canvas-editor-tool-text-color)}.toolbar-divider{width:1px;height:20px;background:var(--feedback-canvas-editor-divider-color);margin:0 6px}.undo-btn{background:var(--feedback-canvas-editor-tool-bg-color) !important;border:1px solid var(--feedback-canvas-editor-border-color) !important}.undo-btn:hover:not(:disabled){background:var(--feedback-canvas-editor-tool-bg-hover) !important}.color-palette{display:flex;align-items:center;gap:6px;background:var(--feedback-canvas-editor-tool-bg-color);border:1px solid var(--feedback-canvas-editor-border-color);border-radius:var(--feedback-modal-button-border-radius);padding:6px;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .10)}.color-slot-wrapper{position:relative}.color-btn{width:28px;height:28px;border-radius:var(--feedback-modal-button-border-radius);border:2px solid transparent;cursor:pointer;transition:all 0.2s ease;position:relative;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .15);display:flex;align-items:center;justify-content:center}.color-btn:hover{transform:scale(1.05);box-shadow:0px 2px 4px 0px rgba(60, 64, 67, .25)}.color-btn.active{border-color:var(--feedback-primary-color);transform:scale(1.1);box-shadow:0 0 0 2px rgba(0, 112, 244, 0.2)}.color-btn.editing{border-color:var(--feedback-highlight-color);box-shadow:0 0 0 2px rgba(255, 180, 34, 0.3)}.color-btn.editing:hover{border-color:var(--feedback-highlight-color);box-shadow:0 0 0 2px rgba(255, 180, 34, 0.4)}.color-picker-dropdown{position:absolute;top:100%;left:50%;transform:translateX(-50%);margin-top:6px;background:var(--feedback-canvas-editor-tool-bg-color);border:1px solid var(--feedback-canvas-editor-border-color);border-radius:var(--feedback-modal-button-border-radius);padding:6px;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);z-index:1000}.color-picker-dropdown input[type=\"color\"]{width:50px;height:32px;border:none;border-radius:var(--feedback-modal-button-border-radius);cursor:pointer}.size-control{display:flex;align-items:center;gap:10px;background:var(--feedback-canvas-editor-tool-bg-color);border:1px solid var(--feedback-canvas-editor-border-color);border-radius:var(--feedback-modal-button-border-radius);padding:6px 12px;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .10)}.size-slider{width:70px;height:4px;border-radius:2px;background:var(--feedback-canvas-editor-slider-track);outline:none;-webkit-appearance:none;-moz-appearance:none;appearance:none;cursor:pointer;border:none}.size-slider::-webkit-slider-track{width:100%;height:4px;cursor:pointer;background:var(--feedback-canvas-editor-slider-track);border-radius:2px;border:none;box-shadow:none}.size-slider::-webkit-slider-thumb{-webkit-appearance:none;width:14px;height:14px;border-radius:50%;background:var(--feedback-primary-color);cursor:pointer;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .20);border:none;margin-top:-5px;}.size-slider::-moz-range-track{width:100%;height:4px;cursor:pointer;background:var(--feedback-canvas-editor-slider-track);border-radius:2px;border:none;box-shadow:none}.size-slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;background:var(--feedback-primary-color);cursor:pointer;border:none;box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .20)}.size-slider::-moz-range-progress{background:var(--feedback-canvas-editor-slider-track);height:4px;border-radius:2px}.size-slider::-ms-track{width:100%;height:4px;cursor:pointer;background:transparent;border-color:transparent;color:transparent}.size-slider::-ms-fill-lower{background:var(--feedback-canvas-editor-slider-track);border-radius:2px}.size-slider::-ms-fill-upper{background:var(--feedback-canvas-editor-slider-track);border-radius:2px}.size-slider::-ms-thumb{width:14px;height:14px;border-radius:50%;background:var(--feedback-primary-color);cursor:pointer;border:none}.size-value{font-weight:500;color:var(--feedback-canvas-editor-tool-text-color);font-size:var(--feedback-text-font-size);min-width:30px}.action-btn{display:flex;align-items:center;gap:6px;padding:5px 12px;border:1px solid var(--feedback-canvas-editor-action-secondary-border);border-radius:var(--feedback-modal-button-border-radius);cursor:pointer;font-size:var(--feedback-modal-button-font-size);font-weight:500;transition:all 0.2s ease;min-width:65px;justify-content:center;height:36px;font-family:var(--feedback-font-family)}.action-btn.secondary{background:var(--feedback-canvas-editor-action-secondary-bg);color:var(--feedback-canvas-editor-action-secondary-text);border-color:var(--feedback-canvas-editor-action-secondary-border)}.action-btn.secondary:hover{background:var(--feedback-canvas-editor-tool-bg-hover);color:var(--feedback-modal-button-text-color-active);border-color:var(--feedback-modal-button-border-color-active)}.action-btn.primary{background:var(--feedback-canvas-editor-action-primary-bg);color:var(--feedback-canvas-editor-action-primary-text);border-color:var(--feedback-modal-button-border-color-active)}.action-btn.primary:hover{background:var(--feedback-modal-button-submit-bg-color-hover);border-color:var(--feedback-modal-button-submit-border-color-hover)}.canvas-editor-content{flex:1;display:flex;align-items:center;justify-content:center;padding:16px;background:var(--feedback-canvas-editor-content-bg);overflow:hidden;min-height:0;min-width:0}.annotation-canvas{max-width:100%;max-height:100%;width:auto;height:auto;cursor:crosshair;border-radius:var(--feedback-modal-content-border-radius);box-shadow:0px 1px 2px 0px rgba(60, 64, 67, .30), 0px 2px 6px 2px rgba(60, 64, 67, .15);background:var(--feedback-white-color);transition:box-shadow 0.3s ease;object-fit:contain;display:block}.annotation-canvas:hover{box-shadow:0px 2px 4px 0px rgba(60, 64, 67, .35), 0px 4px 12px 4px rgba(60, 64, 67, .20)}@media screen and (min-width: 768px){.feedback-modal-content{max-width:var(--feedback-modal-content-max-width)}.feedback-modal-content.feedback-modal-content--bottom-right{bottom:var(--feedback-modal-content-position-bottom);left:initial;right:var(--feedback-modal-content-position-right);top:initial;transform:initial}.feedback-modal-content.feedback-modal-content--bottom-left{bottom:var(--feedback-modal-content-position-bottom);left:var(--feedback-modal-content-position-left);top:initial;transform:initial}.feedback-modal-content.feedback-modal-content--top-right{right:var(--feedback-modal-content-position-right);top:var(--feedback-modal-content-position-top);transform:initial}.feedback-modal-content.feedback-modal-content--top-left{left:var(--feedback-modal-content-position-left);top:var(--feedback-modal-content-position-top);transform:initial}.feedback-modal-content.feedback-modal-content--center-left{left:5px;right:auto;top:50%;transform:translateY(-50%)}.feedback-modal-content.feedback-modal-content--center-right{left:auto;right:5px;top:50%;transform:translateY(-50%)}.feedback-modal-content.feedback-modal-content--sidebar-left.feedback-modal-content--open,.feedback-modal-content.feedback-modal-content--sidebar-right.feedback-modal-content--open{transform:translateX(0)}.feedback-modal-content.feedback-modal-content--sidebar-left{max-width:var(--feedback-modal-content-sidebar-max-width);left:0;right:auto;height:100vh;top:0;transform:translateX(-100%);transition:transform 0.5s ease-in-out;border-radius:0}.feedback-modal-content.feedback-modal-content--sidebar-right{max-width:var(--feedback-modal-content-sidebar-max-width);left:auto;right:0;height:100vh;top:0;transform:translateX(100%);transition:transform 0.5s ease-in-out;border-radius:0}.feedback-modal-text textarea{height:150px;min-height:150px}.feedback-modal-content.feedback-modal-content--bottom-right{transform:translateY(20px)}.feedback-modal-content.feedback-modal-content--bottom-right.feedback-modal-content--open{transform:translateY(0)}.feedback-modal-content.feedback-modal-content--bottom-left{transform:translateY(20px)}.feedback-modal-content.feedback-modal-content--bottom-left.feedback-modal-content--open{transform:translateY(0)}.feedback-modal-content.feedback-modal-content--top-right{transform:translateY(-20px)}.feedback-modal-content.feedback-modal-content--top-right.feedback-modal-content--open{transform:translateY(0)}.feedback-modal-content.feedback-modal-content--top-left{transform:translateY(-20px)}.feedback-modal-content.feedback-modal-content--top-left.feedback-modal-content--open{transform:translateY(0)}}@media (max-width: 768px){.canvas-editor-modal{width:100vw;height:100vh;border-radius:0}.canvas-editor-header{padding:8px 12px;gap:8px}.canvas-editor-toolbar{flex-direction:column;align-items:stretch;gap:12px}.toolbar-section{justify-content:center}.toolbar-section:last-child{margin-left:0;justify-content:stretch;gap:8px}.action-btn{flex:1;min-width:auto}.canvas-editor-content{padding:8px}.tool-group{flex-wrap:wrap;justify-content:center}.color-palette{flex-wrap:wrap;justify-content:center}.size-control{flex-direction:column;gap:6px;text-align:center}.size-slider{width:100px}}";
8795
8810
 
8796
8811
  const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
8797
8812
  constructor() {
@@ -8880,8 +8895,27 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
8880
8895
  this.showScreenshotTopBar = false;
8881
8896
  this.hasSelectedElement = false;
8882
8897
  this.encodedScreenshot = null;
8883
- this.originalElement = null;
8884
- this.selectedElementBounds = null;
8898
+ // Remove highlight from ALL selected elements
8899
+ document.querySelectorAll('.feedback-modal-element-selected').forEach(el => {
8900
+ el.classList.remove('feedback-modal-element-selected');
8901
+ });
8902
+ // Reset canvas editor states
8903
+ this.takingScreenshot = false;
8904
+ this.showPreviewModal = false;
8905
+ this.showCanvasEditor = false;
8906
+ this.annotations = [];
8907
+ this.currentAnnotation = null;
8908
+ this.isDrawing = false;
8909
+ this.canvasRef = null;
8910
+ this.canvasContext = null;
8911
+ this.originalImageData = null;
8912
+ // Reset resizing states
8913
+ this.isResizing = false;
8914
+ this.resizingAnnotation = null;
8915
+ this.resizeStartSize = 16;
8916
+ this.hoveredAnnotation = null;
8917
+ this.resizeHandle = false;
8918
+ // Reset form states
8885
8919
  this.formSuccess = false;
8886
8920
  this.formError = false;
8887
8921
  this.formErrorStatus = 500;
@@ -8890,109 +8924,609 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
8890
8924
  this.resetOverflow();
8891
8925
  }, 200);
8892
8926
  };
8893
- this.openScreenShot = () => {
8894
- this.hasSelectedElement = false;
8895
- this.showModal = false;
8896
- this.showScreenshotMode = true;
8897
- this.showScreenshotTopBar = true;
8898
- this.encodedScreenshot = null;
8899
- this.originalElement = null;
8900
- this.selectedElementBounds = null;
8901
- if (window.innerWidth > document.documentElement.clientWidth) {
8902
- document.documentElement.classList.add('feedback-modal-screenshot-open--scroll');
8927
+ this.openScreenShot = async () => {
8928
+ // Show loading state immediately
8929
+ this.takingScreenshot = true;
8930
+ try {
8931
+ // Capture viewport screenshot immediately
8932
+ const dataUrl = await this.captureViewportScreenshot();
8933
+ this.encodedScreenshot = dataUrl;
8934
+ this.originalImageData = dataUrl;
8935
+ // Reset loading state
8936
+ this.takingScreenshot = false;
8937
+ // Skip preview modal and go directly to canvas editor
8938
+ this.showModal = false;
8939
+ this.showCanvasEditor = true;
8940
+ // Initialize canvas after a short delay to ensure DOM is ready
8941
+ setTimeout(() => {
8942
+ this.initializeCanvas();
8943
+ }, 100);
8944
+ }
8945
+ catch (error) {
8946
+ console.error('Failed to capture screenshot:', error);
8947
+ // Reset loading state on error
8948
+ this.takingScreenshot = false;
8949
+ // Show modal anyway
8950
+ this.showModal = true;
8903
8951
  }
8904
- const scrollY = window.scrollY;
8905
- document.documentElement.style.top = `-${scrollY}px`;
8906
- window.scrollTo(0, parseInt(document.documentElement.style.top || '0') * -1);
8907
- document.documentElement.classList.add('feedback-modal-screenshot-open');
8908
8952
  };
8909
- this.closeScreenShot = () => {
8953
+ this.openCanvasEditor = (event) => {
8954
+ if (event) {
8955
+ event.stopPropagation();
8956
+ }
8910
8957
  this.showModal = false;
8911
- this.showScreenshotMode = false;
8912
- this.showScreenshotTopBar = false;
8913
- this.hasSelectedElement = false;
8914
- this.encodedScreenshot = null;
8915
- this.originalElement = null;
8916
- this.selectedElementBounds = null;
8917
- this.resetOverflow();
8958
+ this.showCanvasEditor = true;
8959
+ // Initialize canvas after a short delay to ensure DOM is ready
8960
+ setTimeout(() => {
8961
+ this.initializeCanvas();
8962
+ }, 100);
8963
+ };
8964
+ this.closeCanvasEditor = () => {
8965
+ this.showCanvasEditor = false;
8966
+ this.showModal = true;
8967
+ };
8968
+ this.saveAnnotations = () => {
8969
+ if (this.canvasRef) {
8970
+ // Create final image with annotations
8971
+ const finalDataUrl = this.canvasRef.toDataURL('image/png');
8972
+ this.encodedScreenshot = finalDataUrl;
8973
+ }
8974
+ this.showCanvasEditor = false;
8975
+ this.showModal = true;
8918
8976
  };
8919
- this.handleMouseOverScreenShot = (event) => {
8920
- event.preventDefault();
8921
- if (this.hasSelectedElement)
8977
+ this.initializeCanvas = () => {
8978
+ if (!this.canvasRef || !this.originalImageData)
8922
8979
  return;
8923
- const borderOffset = 2;
8924
- this.screenshotModal.style.display = 'none';
8925
- const elementUnder = document.elementFromPoint(event.clientX, event.clientY);
8926
- const rect = elementUnder.getBoundingClientRect();
8927
- this.screenshotModal.style.display = '';
8928
- // Get the bounding box of the element selected
8929
- this.elementSelected.style.position = 'absolute';
8930
- this.elementSelected.style.left = `${rect.left}px`;
8931
- this.elementSelected.style.top = `${rect.top}px`;
8932
- this.elementSelected.style.width = `${rect.width}px`;
8933
- this.elementSelected.style.height = `${rect.height}px`;
8934
- this.elementSelected.classList.add('feedback-modal-element-hover');
8935
- // Set the background color of nonselected areas
8936
- // Top
8937
- this.topSide.style.position = 'absolute';
8938
- this.topSide.style.left = `${rect.left}px`;
8939
- this.topSide.style.top = '0px';
8940
- this.topSide.style.width = `${rect.width + borderOffset}px`;
8941
- this.topSide.style.height = `${rect.top}px`;
8942
- this.topSide.style.backgroundColor = 'rgba(0, 0, 0, 0.4)';
8943
- // Left
8944
- this.leftSide.style.position = 'absolute';
8945
- this.leftSide.style.left = '0px';
8946
- this.leftSide.style.top = '0px';
8947
- this.leftSide.style.width = `${rect.left}px`;
8948
- this.leftSide.style.height = '100vh';
8949
- this.leftSide.style.backgroundColor = 'rgba(0, 0, 0, 0.4)';
8950
- // Bottom
8951
- this.bottomSide.style.position = 'absolute';
8952
- this.bottomSide.style.left = `${rect.left}px`;
8953
- this.bottomSide.style.top = `${rect.bottom + borderOffset}px`;
8954
- this.bottomSide.style.width = `${rect.width + borderOffset}px`;
8955
- this.bottomSide.style.height = '100vh';
8956
- this.bottomSide.style.backgroundColor = 'rgba(0, 0, 0, 0.4)';
8957
- // Right
8958
- this.rightSide.style.position = 'absolute';
8959
- this.rightSide.style.left = `${rect.right + borderOffset}px`;
8960
- this.rightSide.style.top = '0px';
8961
- this.rightSide.style.width = '100%';
8962
- this.rightSide.style.height = '100vh';
8963
- this.rightSide.style.backgroundColor = 'rgba(0, 0, 0, 0.4)';
8964
- // Restore the visibility of the screenshot-modal
8965
- this.screenshotModal.style.backgroundColor = 'transparent';
8966
- };
8967
- this.handleMouseClickedSelectedElement = async (event) => {
8968
- event.preventDefault();
8969
- if (!this.elementSelected) {
8980
+ this.canvasContext = this.canvasRef.getContext('2d');
8981
+ const img = new Image();
8982
+ img.onload = () => {
8983
+ // Set canvas to original image dimensions
8984
+ this.canvasRef.width = img.width;
8985
+ this.canvasRef.height = img.height;
8986
+ // Get available container dimensions
8987
+ const containerWidth = this.canvasRef.parentElement.clientWidth - 32; // Account for reduced padding (16px * 2)
8988
+ const containerHeight = this.canvasRef.parentElement.clientHeight - 32;
8989
+ // Calculate scale factors for both dimensions
8990
+ const scaleX = containerWidth / img.width;
8991
+ const scaleY = containerHeight / img.height;
8992
+ // Use the smaller scale to ensure complete image fits
8993
+ const scale = Math.min(scaleX, scaleY, 1); // Never scale up, only down
8994
+ // Calculate final display dimensions
8995
+ const displayWidth = img.width * scale;
8996
+ const displayHeight = img.height * scale;
8997
+ // Set CSS size for display (this scales the canvas visually)
8998
+ this.canvasRef.style.width = `${displayWidth}px`;
8999
+ this.canvasRef.style.height = `${displayHeight}px`;
9000
+ console.log('Canvas initialized with complete image fit:', {
9001
+ originalWidth: img.width,
9002
+ originalHeight: img.height,
9003
+ displayWidth,
9004
+ displayHeight,
9005
+ scale,
9006
+ scaleX,
9007
+ scaleY,
9008
+ containerWidth,
9009
+ containerHeight,
9010
+ usingScale: scale === scaleX ? 'width-limited' : 'height-limited'
9011
+ });
9012
+ // Draw the original image at full resolution
9013
+ this.canvasContext.drawImage(img, 0, 0);
9014
+ // Redraw existing annotations
9015
+ this.redrawAnnotations();
9016
+ };
9017
+ img.src = this.originalImageData;
9018
+ };
9019
+ this.redrawAnnotations = () => {
9020
+ if (!this.canvasContext)
8970
9021
  return;
9022
+ // Clear and redraw background image
9023
+ const img = new Image();
9024
+ img.onload = () => {
9025
+ this.canvasContext.clearRect(0, 0, this.canvasRef.width, this.canvasRef.height);
9026
+ this.canvasContext.drawImage(img, 0, 0);
9027
+ // Draw all annotations
9028
+ this.annotations.forEach(annotation => {
9029
+ this.drawAnnotation(annotation);
9030
+ });
9031
+ };
9032
+ img.src = this.originalImageData;
9033
+ };
9034
+ this.drawAnnotation = (annotation) => {
9035
+ if (!this.canvasContext)
9036
+ return;
9037
+ this.canvasContext.strokeStyle = annotation.color;
9038
+ this.canvasContext.lineWidth = annotation.lineWidth;
9039
+ this.canvasContext.lineCap = 'round';
9040
+ this.canvasContext.lineJoin = 'round';
9041
+ switch (annotation.type) {
9042
+ case 'rectangle':
9043
+ this.canvasContext.strokeRect(annotation.startX, annotation.startY, annotation.width, annotation.height);
9044
+ // Rectangle resize handles disabled for now
9045
+ break;
9046
+ case 'line':
9047
+ this.canvasContext.beginPath();
9048
+ this.canvasContext.moveTo(annotation.startX, annotation.startY);
9049
+ this.canvasContext.lineTo(annotation.endX, annotation.endY);
9050
+ this.canvasContext.stroke();
9051
+ // Draw resize handles if this annotation is hovered
9052
+ if (this.hoveredAnnotation === annotation) {
9053
+ this.drawLineResizeHandles(annotation);
9054
+ }
9055
+ break;
9056
+ case 'arrow':
9057
+ this.drawArrow(annotation.startX, annotation.startY, annotation.endX, annotation.endY);
9058
+ // Draw resize handles if this annotation is hovered
9059
+ if (this.hoveredAnnotation === annotation) {
9060
+ this.drawLineResizeHandles(annotation); // Same as line
9061
+ }
9062
+ break;
9063
+ case 'text':
9064
+ const fontSize = annotation.fontSize || 16;
9065
+ this.canvasContext.fillStyle = annotation.color;
9066
+ this.canvasContext.font = `${fontSize}px Arial`;
9067
+ this.canvasContext.fillText(annotation.text, annotation.x, annotation.y);
9068
+ // Draw resize handle if this annotation is hovered
9069
+ if (this.hoveredAnnotation === annotation) {
9070
+ this.drawTextResizeHandle(annotation);
9071
+ }
9072
+ break;
8971
9073
  }
8972
- this.hasSelectedElement = true;
8973
- this.elementSelected.classList.add('feedback-modal-element-selected');
8974
- // Store the original element that was under the mouse
8975
- this.screenshotModal.style.display = 'none';
8976
- this.originalElement = document.elementFromPoint(event.clientX, event.clientY);
8977
- this.selectedElementBounds = this.originalElement.getBoundingClientRect();
8978
- this.screenshotModal.style.display = '';
8979
- // Hide the screenshot interface
8980
- this.showScreenshotTopBar = false;
8981
- this.showModal = false;
8982
- try {
8983
- const dataUrl = await this.captureScreenshot();
8984
- console.log('Screenshot captured');
8985
- this.encodedScreenshot = dataUrl;
9074
+ };
9075
+ // Draw resize handle for text annotation
9076
+ this.drawTextResizeHandle = (annotation) => {
9077
+ if (!this.canvasContext || annotation.type !== 'text')
9078
+ return;
9079
+ const fontSize = annotation.fontSize || 16;
9080
+ const textWidth = this.getTextWidth(annotation.text, fontSize);
9081
+ const handleSize = 8;
9082
+ const handleX = annotation.x + textWidth;
9083
+ const handleY = annotation.y;
9084
+ // Draw resize handle (small square) - using widget primary color
9085
+ this.canvasContext.fillStyle = '#0070F4'; // var(--feedback-primary-color)
9086
+ this.canvasContext.strokeStyle = '#ffffff';
9087
+ this.canvasContext.lineWidth = 2;
9088
+ this.canvasContext.fillRect(handleX - handleSize / 2, handleY - handleSize / 2, handleSize, handleSize);
9089
+ this.canvasContext.strokeRect(handleX - handleSize / 2, handleY - handleSize / 2, handleSize, handleSize);
9090
+ };
9091
+ this.drawArrow = (fromX, fromY, toX, toY) => {
9092
+ const headlen = 15; // Arrow head length
9093
+ const angle = Math.atan2(toY - fromY, toX - fromX);
9094
+ // Draw line
9095
+ this.canvasContext.beginPath();
9096
+ this.canvasContext.moveTo(fromX, fromY);
9097
+ this.canvasContext.lineTo(toX, toY);
9098
+ this.canvasContext.stroke();
9099
+ // Draw arrow head
9100
+ this.canvasContext.beginPath();
9101
+ this.canvasContext.moveTo(toX, toY);
9102
+ this.canvasContext.lineTo(toX - headlen * Math.cos(angle - Math.PI / 6), toY - headlen * Math.sin(angle - Math.PI / 6));
9103
+ this.canvasContext.moveTo(toX, toY);
9104
+ this.canvasContext.lineTo(toX - headlen * Math.cos(angle + Math.PI / 6), toY - headlen * Math.sin(angle + Math.PI / 6));
9105
+ this.canvasContext.stroke();
9106
+ };
9107
+ this.undoLastAnnotation = () => {
9108
+ this.annotations = this.annotations.slice(0, -1);
9109
+ this.redrawAnnotations();
9110
+ };
9111
+ // Handle color slot editing
9112
+ this.handleColorSlotClick = (colorIndex) => {
9113
+ if (this.editingColorIndex === colorIndex) {
9114
+ // If already editing this slot, just select the color
9115
+ this.canvasDrawingColor = this.defaultColors[colorIndex];
9116
+ this.showColorPicker = false;
9117
+ this.editingColorIndex = -1;
8986
9118
  }
8987
- catch (error) {
8988
- console.error('Failed to capture screenshot:', error);
8989
- this.hasSelectedElement = false;
9119
+ else {
9120
+ // Start editing this color slot
9121
+ this.editingColorIndex = colorIndex;
9122
+ this.showColorPicker = true;
9123
+ this.canvasDrawingColor = this.defaultColors[colorIndex];
8990
9124
  }
8991
- finally {
8992
- // Show the modal again
8993
- this.showModal = true;
9125
+ };
9126
+ // Update color in slot
9127
+ this.updateColorSlot = (newColor) => {
9128
+ if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
9129
+ this.defaultColors[this.editingColorIndex] = newColor;
9130
+ this.canvasDrawingColor = newColor;
9131
+ this.showColorPicker = false;
9132
+ this.editingColorIndex = -1;
9133
+ // Force reactivity
9134
+ this.defaultColors = [...this.defaultColors];
9135
+ }
9136
+ };
9137
+ // Handle color picker input without closing
9138
+ this.handleColorPickerInput = (event) => {
9139
+ event.stopPropagation();
9140
+ const newColor = event.target.value;
9141
+ if (this.editingColorIndex >= 0 && this.editingColorIndex < this.defaultColors.length) {
9142
+ this.defaultColors[this.editingColorIndex] = newColor;
9143
+ this.canvasDrawingColor = newColor;
9144
+ // Force reactivity
9145
+ this.defaultColors = [...this.defaultColors];
9146
+ }
9147
+ };
9148
+ // Handle color picker click to prevent closing
9149
+ this.handleColorPickerClick = (event) => {
9150
+ event.stopPropagation();
9151
+ };
9152
+ // Close color picker
9153
+ this.closeColorPicker = () => {
9154
+ this.showColorPicker = false;
9155
+ this.editingColorIndex = -1;
9156
+ };
9157
+ // Check if point is in resize handle for any annotation type
9158
+ this.isPointInResizeHandle = (x, y, annotation) => {
9159
+ const handleSize = 8;
9160
+ switch (annotation.type) {
9161
+ case 'text':
9162
+ const textWidth = this.getTextWidth(annotation.text, annotation.fontSize || 16);
9163
+ const handleX = annotation.x + textWidth;
9164
+ const handleY = annotation.y;
9165
+ return x >= handleX - handleSize / 2 && x <= handleX + handleSize / 2 &&
9166
+ y >= handleY - handleSize / 2 && y <= handleY + handleSize / 2;
9167
+ case 'rectangle':
9168
+ // Rectangle resizing disabled for now
9169
+ return false;
9170
+ case 'line':
9171
+ case 'arrow':
9172
+ // Check both endpoint handles
9173
+ const lineHandles = [
9174
+ { x: annotation.startX, y: annotation.startY, point: 'start' },
9175
+ { x: annotation.endX, y: annotation.endY, point: 'end' }
9176
+ ];
9177
+ for (const handle of lineHandles) {
9178
+ if (x >= handle.x - handleSize / 2 && x <= handle.x + handleSize / 2 &&
9179
+ y >= handle.y - handleSize / 2 && y <= handle.y + handleSize / 2) {
9180
+ return handle.point; // Return which endpoint was clicked
9181
+ }
9182
+ }
9183
+ return false;
9184
+ default:
9185
+ return false;
8994
9186
  }
8995
9187
  };
9188
+ // Get text width for resize handle positioning
9189
+ this.getTextWidth = (text, fontSize) => {
9190
+ // Approximate text width calculation
9191
+ return text.length * fontSize * 0.6;
9192
+ };
9193
+ // Start text resize
9194
+ this.startTextResize = (annotation, startPos) => {
9195
+ this.isResizing = true;
9196
+ this.resizingAnnotation = annotation;
9197
+ this.resizeStartSize = annotation.fontSize || 16;
9198
+ this.dragStartPos = startPos;
9199
+ };
9200
+ // Handle text resize
9201
+ this.handleTextResize = (currentPos) => {
9202
+ if (!this.resizingAnnotation || !this.dragStartPos)
9203
+ return;
9204
+ const deltaX = currentPos.x - this.dragStartPos.x;
9205
+ const deltaY = currentPos.y - this.dragStartPos.y;
9206
+ const avgDelta = (deltaX + deltaY) / 2;
9207
+ // Calculate new font size (minimum 8px, maximum 72px)
9208
+ const newSize = Math.max(8, Math.min(72, this.resizeStartSize + avgDelta * 0.5));
9209
+ // Update annotation font size
9210
+ const index = this.annotations.findIndex(a => a === this.resizingAnnotation);
9211
+ if (index !== -1) {
9212
+ this.annotations[index] = Object.assign(Object.assign({}, this.resizingAnnotation), { fontSize: Math.round(newSize) });
9213
+ this.resizingAnnotation = this.annotations[index];
9214
+ }
9215
+ this.redrawAnnotations();
9216
+ };
9217
+ // Start resize for any annotation type
9218
+ this.startResize = (annotation, handle, startPos) => {
9219
+ this.isResizing = true;
9220
+ this.resizingAnnotation = annotation;
9221
+ this.resizeHandle = handle;
9222
+ this.dragStartPos = startPos;
9223
+ // Store original values for different annotation types
9224
+ if (annotation.type === 'text') {
9225
+ this.resizeStartSize = annotation.fontSize || 16;
9226
+ }
9227
+ };
9228
+ // Enhanced mouse down handler with resize detection for all annotation types
9229
+ this.handleCanvasMouseDown = (event) => {
9230
+ if (!this.canvasRef)
9231
+ return;
9232
+ // Close color picker if open
9233
+ if (this.showColorPicker) {
9234
+ this.closeColorPicker();
9235
+ }
9236
+ const coords = this.getCanvasCoordinates(event);
9237
+ // Check if clicking on existing annotation first
9238
+ const found = this.findAnnotationAt(coords.x, coords.y);
9239
+ if (found) {
9240
+ // Check if clicking on resize handle for any annotation type
9241
+ const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
9242
+ if (handle) {
9243
+ this.startResize(found.annotation, handle, coords);
9244
+ this.canvasRef.style.cursor = 'nw-resize';
9245
+ return;
9246
+ }
9247
+ // Start dragging existing annotation
9248
+ if (!this.isDrawing) {
9249
+ this.isDragging = true;
9250
+ this.draggedAnnotation = found.annotation;
9251
+ this.dragStartPos = coords;
9252
+ this.canvasRef.style.cursor = 'grabbing';
9253
+ return;
9254
+ }
9255
+ }
9256
+ // Original drawing logic
9257
+ this.isDrawing = true;
9258
+ if (this.canvasDrawingTool === 'text') {
9259
+ const text = prompt('Enter text:');
9260
+ if (text) {
9261
+ const annotation = {
9262
+ type: 'text',
9263
+ x: coords.x,
9264
+ y: coords.y,
9265
+ text,
9266
+ color: this.canvasDrawingColor,
9267
+ fontSize: 16
9268
+ };
9269
+ this.annotations = [...this.annotations, annotation];
9270
+ this.redrawAnnotations();
9271
+ }
9272
+ this.isDrawing = false;
9273
+ }
9274
+ else {
9275
+ this.currentAnnotation = {
9276
+ type: this.canvasDrawingTool,
9277
+ startX: coords.x,
9278
+ startY: coords.y,
9279
+ color: this.canvasDrawingColor,
9280
+ lineWidth: this.canvasLineWidth
9281
+ };
9282
+ }
9283
+ };
9284
+ this.handleCanvasMouseMove = (event) => {
9285
+ if (!this.canvasRef)
9286
+ return;
9287
+ const coords = this.getCanvasCoordinates(event);
9288
+ // Handle resizing for any annotation type
9289
+ if (this.isResizing && this.resizingAnnotation) {
9290
+ this.handleResize(coords);
9291
+ return;
9292
+ }
9293
+ // Handle dragging existing annotation
9294
+ if (this.isDragging && this.draggedAnnotation && this.dragStartPos) {
9295
+ const deltaX = coords.x - this.dragStartPos.x;
9296
+ const deltaY = coords.y - this.dragStartPos.y;
9297
+ // Update annotation position
9298
+ const updatedAnnotation = Object.assign({}, this.draggedAnnotation);
9299
+ switch (updatedAnnotation.type) {
9300
+ case 'rectangle':
9301
+ updatedAnnotation.startX += deltaX;
9302
+ updatedAnnotation.startY += deltaY;
9303
+ break;
9304
+ case 'line':
9305
+ case 'arrow':
9306
+ updatedAnnotation.startX += deltaX;
9307
+ updatedAnnotation.startY += deltaY;
9308
+ updatedAnnotation.endX += deltaX;
9309
+ updatedAnnotation.endY += deltaY;
9310
+ break;
9311
+ case 'text':
9312
+ updatedAnnotation.x += deltaX;
9313
+ updatedAnnotation.y += deltaY;
9314
+ break;
9315
+ }
9316
+ // Update annotation in array
9317
+ const index = this.annotations.findIndex(a => a === this.draggedAnnotation);
9318
+ if (index !== -1) {
9319
+ this.annotations[index] = updatedAnnotation;
9320
+ this.draggedAnnotation = updatedAnnotation;
9321
+ }
9322
+ this.dragStartPos = coords;
9323
+ this.redrawAnnotations();
9324
+ return;
9325
+ }
9326
+ // Handle drawing new annotation
9327
+ if (this.isDrawing && this.currentAnnotation) {
9328
+ if (this.canvasDrawingTool === 'rectangle') {
9329
+ this.currentAnnotation.width = coords.x - this.currentAnnotation.startX;
9330
+ this.currentAnnotation.height = coords.y - this.currentAnnotation.startY;
9331
+ }
9332
+ else {
9333
+ this.currentAnnotation.endX = coords.x;
9334
+ this.currentAnnotation.endY = coords.y;
9335
+ }
9336
+ this.redrawAnnotations();
9337
+ this.drawAnnotation(this.currentAnnotation);
9338
+ return;
9339
+ }
9340
+ // Handle hover states and cursor changes
9341
+ const found = this.findAnnotationAt(coords.x, coords.y);
9342
+ if (found) {
9343
+ // Check if hovering over resize handle for any annotation type
9344
+ const handle = this.isPointInResizeHandle(coords.x, coords.y, found.annotation);
9345
+ if (handle) {
9346
+ this.canvasRef.style.cursor = 'nw-resize';
9347
+ this.hoveredAnnotation = found.annotation;
9348
+ this.redrawAnnotations();
9349
+ return;
9350
+ }
9351
+ // Regular hover over annotation
9352
+ this.canvasRef.style.cursor = 'grab';
9353
+ if (this.hoveredAnnotation !== found.annotation) {
9354
+ this.hoveredAnnotation = found.annotation;
9355
+ this.redrawAnnotations();
9356
+ }
9357
+ }
9358
+ else {
9359
+ // No annotation under cursor
9360
+ this.canvasRef.style.cursor = 'crosshair';
9361
+ if (this.hoveredAnnotation) {
9362
+ this.hoveredAnnotation = null;
9363
+ this.redrawAnnotations();
9364
+ }
9365
+ }
9366
+ };
9367
+ this.handleCanvasMouseUp = () => {
9368
+ // Handle end of text resizing
9369
+ if (this.isResizing) {
9370
+ this.isResizing = false;
9371
+ this.resizingAnnotation = null;
9372
+ this.dragStartPos = null;
9373
+ this.resizeHandle = false;
9374
+ if (this.canvasRef) {
9375
+ this.canvasRef.style.cursor = 'crosshair';
9376
+ }
9377
+ return;
9378
+ }
9379
+ // Handle end of dragging
9380
+ if (this.isDragging) {
9381
+ this.isDragging = false;
9382
+ this.draggedAnnotation = null;
9383
+ this.dragStartPos = null;
9384
+ if (this.canvasRef) {
9385
+ this.canvasRef.style.cursor = 'crosshair';
9386
+ }
9387
+ return;
9388
+ }
9389
+ // Handle end of drawing
9390
+ if (!this.isDrawing || !this.currentAnnotation)
9391
+ return;
9392
+ this.isDrawing = false;
9393
+ this.annotations = [...this.annotations, this.currentAnnotation];
9394
+ this.currentAnnotation = null;
9395
+ this.redrawAnnotations();
9396
+ };
9397
+ // Draw resize handles for rectangle annotation
9398
+ this.drawRectangleResizeHandles = (annotation) => {
9399
+ if (!this.canvasContext || annotation.type !== 'rectangle')
9400
+ return;
9401
+ const handleSize = 8;
9402
+ const left = annotation.startX;
9403
+ const top = annotation.startY;
9404
+ const right = annotation.startX + annotation.width;
9405
+ const bottom = annotation.startY + annotation.height;
9406
+ // Define handle positions (4 corners)
9407
+ const handles = [
9408
+ { x: left, y: top },
9409
+ { x: right, y: top },
9410
+ { x: right, y: bottom },
9411
+ { x: left, y: bottom } // Bottom-left
9412
+ ];
9413
+ // Draw each handle
9414
+ this.canvasContext.fillStyle = '#0070F4'; // Primary color
9415
+ this.canvasContext.strokeStyle = '#ffffff';
9416
+ this.canvasContext.lineWidth = 2;
9417
+ handles.forEach(handle => {
9418
+ this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
9419
+ this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
9420
+ });
9421
+ };
9422
+ // Draw resize handles for line/arrow annotation
9423
+ this.drawLineResizeHandles = (annotation) => {
9424
+ if (!this.canvasContext || (annotation.type !== 'line' && annotation.type !== 'arrow'))
9425
+ return;
9426
+ const handleSize = 8;
9427
+ // Define handle positions (2 endpoints)
9428
+ const handles = [
9429
+ { x: annotation.startX, y: annotation.startY },
9430
+ { x: annotation.endX, y: annotation.endY } // End point
9431
+ ];
9432
+ // Draw each handle
9433
+ this.canvasContext.fillStyle = '#0070F4'; // Primary color
9434
+ this.canvasContext.strokeStyle = '#ffffff';
9435
+ this.canvasContext.lineWidth = 2;
9436
+ handles.forEach(handle => {
9437
+ this.canvasContext.fillRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
9438
+ this.canvasContext.strokeRect(handle.x - handleSize / 2, handle.y - handleSize / 2, handleSize, handleSize);
9439
+ });
9440
+ };
9441
+ // Convert screen coordinates to canvas coordinates
9442
+ this.getCanvasCoordinates = (event) => {
9443
+ if (!this.canvasRef)
9444
+ return { x: 0, y: 0 };
9445
+ const rect = this.canvasRef.getBoundingClientRect();
9446
+ // Calculate the scale factor between display size and actual canvas size
9447
+ const scaleX = this.canvasRef.width / rect.width;
9448
+ const scaleY = this.canvasRef.height / rect.height;
9449
+ const x = (event.clientX - rect.left) * scaleX;
9450
+ const y = (event.clientY - rect.top) * scaleY;
9451
+ return { x, y };
9452
+ };
9453
+ // Find annotation under mouse cursor
9454
+ this.findAnnotationAt = (x, y) => {
9455
+ // Check in reverse order (top to bottom)
9456
+ for (let i = this.annotations.length - 1; i >= 0; i--) {
9457
+ const annotation = this.annotations[i];
9458
+ if (this.isPointInAnnotation(x, y, annotation)) {
9459
+ return { annotation, index: i };
9460
+ }
9461
+ }
9462
+ return null;
9463
+ };
9464
+ // Check if point is within annotation bounds
9465
+ this.isPointInAnnotation = (x, y, annotation) => {
9466
+ const tolerance = 10; // Click tolerance
9467
+ switch (annotation.type) {
9468
+ case 'rectangle':
9469
+ const left = Math.min(annotation.startX, annotation.startX + annotation.width);
9470
+ const right = Math.max(annotation.startX, annotation.startX + annotation.width);
9471
+ const top = Math.min(annotation.startY, annotation.startY + annotation.height);
9472
+ const bottom = Math.max(annotation.startY, annotation.startY + annotation.height);
9473
+ return x >= left - tolerance && x <= right + tolerance &&
9474
+ y >= top - tolerance && y <= bottom + tolerance;
9475
+ case 'line':
9476
+ case 'arrow':
9477
+ // Distance from point to line
9478
+ const A = annotation.endY - annotation.startY;
9479
+ const B = annotation.startX - annotation.endX;
9480
+ const C = annotation.endX * annotation.startY - annotation.startX * annotation.endY;
9481
+ const distance = Math.abs(A * x + B * y + C) / Math.sqrt(A * A + B * B);
9482
+ return distance <= tolerance;
9483
+ case 'text':
9484
+ // Simple bounding box for text
9485
+ return x >= annotation.x - tolerance && x <= annotation.x + 100 &&
9486
+ y >= annotation.y - 20 && y <= annotation.y + tolerance;
9487
+ default:
9488
+ return false;
9489
+ }
9490
+ };
9491
+ // Handle resize for different annotation types
9492
+ this.handleResize = (currentPos) => {
9493
+ if (!this.resizingAnnotation || !this.dragStartPos)
9494
+ return;
9495
+ const annotation = this.resizingAnnotation;
9496
+ const index = this.annotations.findIndex(a => a === annotation);
9497
+ if (index === -1)
9498
+ return;
9499
+ let updatedAnnotation = Object.assign({}, annotation);
9500
+ switch (annotation.type) {
9501
+ case 'text':
9502
+ // Text resize logic (existing)
9503
+ const deltaX = currentPos.x - this.dragStartPos.x;
9504
+ const deltaY = currentPos.y - this.dragStartPos.y;
9505
+ const avgDelta = (deltaX + deltaY) / 2;
9506
+ const newSize = Math.max(8, Math.min(72, this.resizeStartSize + avgDelta * 0.5));
9507
+ updatedAnnotation.fontSize = Math.round(newSize);
9508
+ break;
9509
+ case 'rectangle':
9510
+ // Rectangle resizing disabled for now
9511
+ return;
9512
+ case 'line':
9513
+ case 'arrow':
9514
+ // Line/arrow resize logic - move endpoints
9515
+ if (this.resizeHandle === 'start') {
9516
+ updatedAnnotation.startX = currentPos.x;
9517
+ updatedAnnotation.startY = currentPos.y;
9518
+ }
9519
+ else if (this.resizeHandle === 'end') {
9520
+ updatedAnnotation.endX = currentPos.x;
9521
+ updatedAnnotation.endY = currentPos.y;
9522
+ }
9523
+ break;
9524
+ }
9525
+ // Update annotation in array
9526
+ this.annotations[index] = updatedAnnotation;
9527
+ this.resizingAnnotation = updatedAnnotation;
9528
+ this.redrawAnnotations();
9529
+ };
8996
9530
  this.sending = false;
8997
9531
  this.formMessage = '';
8998
9532
  this.formEmail = '';
@@ -9006,6 +9540,26 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9006
9540
  this.selectedRating = -1;
9007
9541
  this.overlayVisible = false;
9008
9542
  this.isAnimating = false;
9543
+ this.takingScreenshot = false;
9544
+ this.showPreviewModal = false;
9545
+ this.showCanvasEditor = false;
9546
+ this.canvasDrawingTool = 'rectangle';
9547
+ this.canvasDrawingColor = '#ff0000';
9548
+ this.canvasLineWidth = 3;
9549
+ this.isDrawing = false;
9550
+ this.annotations = [];
9551
+ this.currentAnnotation = null;
9552
+ this.isDragging = false;
9553
+ this.draggedAnnotation = null;
9554
+ this.dragStartPos = null;
9555
+ this.showColorPicker = false;
9556
+ this.editingColorIndex = -1;
9557
+ this.isResizing = false;
9558
+ this.resizingAnnotation = null;
9559
+ this.resizeStartSize = 16;
9560
+ this.hoveredAnnotation = null;
9561
+ this.resizeHandle = false;
9562
+ this.defaultColors = ['#ff0000', '#00ff00', '#0000ff', '#000000'];
9009
9563
  this.customFont = false;
9010
9564
  this.emailAddress = '';
9011
9565
  this.hideEmail = false;
@@ -9036,10 +9590,14 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9036
9590
  this.ratingPlaceholder = 'Was this page helpful?';
9037
9591
  this.ratingStarsPlaceholder = 'How would you rate this page?';
9038
9592
  this.sendButtonText = 'Send';
9039
- this.screenshotButtonText = 'Add a screenshot';
9040
9593
  this.screenshotAttachedText = 'Screenshot attached';
9594
+ this.screenshotButtonText = 'Add a screenshot';
9595
+ this.screenshotTakingText = 'Taking screenshot...';
9041
9596
  this.screenshotTopbarText = 'Select an element on this page';
9042
9597
  this.successMessage = '';
9598
+ this.canvasEditorTitle = 'Edit screenshot';
9599
+ this.canvasEditorCancelText = 'Cancel';
9600
+ this.canvasEditorSaveText = 'Save';
9043
9601
  }
9044
9602
  componentWillLoad() {
9045
9603
  if (this.fetchData)
@@ -9063,15 +9621,10 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9063
9621
  }
9064
9622
  }
9065
9623
  resetOverflow() {
9624
+ // Just clean up any stray classes, don't add/remove during screenshot
9066
9625
  document.documentElement.classList.remove('feedback-modal-screenshot-open');
9067
9626
  document.documentElement.classList.remove('feedback-modal-screenshot-open--scroll');
9068
- document.documentElement.classList.add('feedback-modal-screenshot-closing');
9069
- // Only restore scroll position if we previously modified it
9070
- if (document.documentElement.style.top) {
9071
- window.scrollTo(0, parseInt(document.documentElement.style.top || '0') * -1);
9072
- document.documentElement.style.top = '';
9073
- }
9074
- window.addEventListener('scroll', this.onScrollDebounced);
9627
+ document.documentElement.classList.remove('feedback-modal-screenshot-closing');
9075
9628
  }
9076
9629
  handleMessageInput(event) {
9077
9630
  this.formMessage = event.target.value;
@@ -9079,31 +9632,48 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9079
9632
  handleEmailInput(event) {
9080
9633
  this.formEmail = event.target.value;
9081
9634
  }
9082
- captureScreenshot() {
9635
+ captureViewportScreenshot() {
9083
9636
  return new Promise((resolve, reject) => {
9084
9637
  requestAnimationFrame(() => {
9085
- html2canvasPro(document.body, {
9086
- x: window.scrollX,
9087
- y: window.scrollY,
9088
- width: window.innerWidth,
9089
- height: window.innerHeight,
9090
- allowTaint: true,
9638
+ // Get viewport dimensions and scroll position
9639
+ const viewportWidth = window.innerWidth;
9640
+ const viewportHeight = window.innerHeight;
9641
+ const scrollX = window.scrollX || window.pageXOffset || 0;
9642
+ const scrollY = window.scrollY || window.pageYOffset || 0;
9643
+ // Capture exactly what the user sees in their viewport
9644
+ html2canvasPro(document.documentElement, {
9645
+ x: scrollX,
9646
+ y: scrollY,
9647
+ width: viewportWidth,
9648
+ height: viewportHeight,
9649
+ scrollX: 0,
9650
+ scrollY: 0,
9651
+ allowTaint: false,
9091
9652
  useCORS: true,
9092
9653
  scale: 1,
9654
+ backgroundColor: '#ffffff',
9655
+ logging: false,
9656
+ foreignObjectRendering: false,
9657
+ imageTimeout: 15000,
9658
+ windowWidth: viewportWidth,
9659
+ windowHeight: viewportHeight,
9660
+ removeContainer: true,
9661
+ ignoreElements: (element) => {
9662
+ // Ignore all feedback modal elements
9663
+ return element.closest('feedback-modal') !== null ||
9664
+ element.classList.contains('feedback-overlay') ||
9665
+ element.classList.contains('feedback-modal-screenshot-header') ||
9666
+ element.tagName === 'FEEDBACK-MODAL' ||
9667
+ element.tagName === 'FEEDBACK-BUTTON';
9668
+ }
9093
9669
  })
9094
9670
  .then((canvas) => {
9095
- const context = canvas.getContext('2d');
9096
- if (context && this.selectedElementBounds) {
9097
- // Use the same color as HTML highlight
9098
- context.strokeStyle = 'rgba(0, 123, 255, 0.8)'; // Example color
9099
- context.lineWidth = 3;
9100
- context.strokeRect(this.selectedElementBounds.left + window.scrollX, this.selectedElementBounds.top + window.scrollY, this.selectedElementBounds.width, this.selectedElementBounds.height);
9101
- }
9102
- const dataUrl = canvas.toDataURL();
9671
+ const dataUrl = canvas.toDataURL('image/png');
9672
+ console.log('Screenshot captured successfully, size:', canvas.width, 'x', canvas.height);
9103
9673
  resolve(dataUrl);
9104
9674
  })
9105
9675
  .catch((error) => {
9106
- console.error('Failed to capture screenshot:', error);
9676
+ console.error('Failed to capture viewport screenshot:', error);
9107
9677
  reject(error);
9108
9678
  });
9109
9679
  });
@@ -9118,12 +9688,8 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9118
9688
  handleRatingChange(newRating) {
9119
9689
  this.selectedRating = newRating;
9120
9690
  }
9121
- // Remove the preview modal toggle function
9122
- // togglePreviewModal() {
9123
- // this.showPreviewModal = !this.showPreviewModal;
9124
- // }
9125
9691
  render() {
9126
- return (h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''}` }, this.showScreenshotMode && (h("div", { class: "feedback-modal-screenshot", ref: (el) => (this.screenshotModal = el), onMouseMove: this.handleMouseOverScreenShot }, h("div", { class: "feedback-modal-screenshot-element-selected", ref: (el) => (this.elementSelected = el), onClick: this.handleMouseClickedSelectedElement }), h("div", { class: "top-side", ref: (el) => (this.topSide = el) }), h("div", { class: "left-side", ref: (el) => (this.leftSide = el) }), h("div", { class: "bottom-side", ref: (el) => (this.bottomSide = el) }), h("div", { class: "right-side", ref: (el) => (this.rightSide = el) }), this.showScreenshotTopBar && (h("div", { class: "feedback-modal-screenshot-header", onClick: this.closeScreenShot }, h("span", null, this.screenshotTopbarText), h("span", { class: "feedback-modal-screenshot-close" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "#191919", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "feather feather-x" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" }))))))), this.showModal && (h("div", { class: `feedback-overlay ${this.isAnimating ? 'feedback-overlay--visible' : ''}` })), this.showModal && (h("div", { class: `feedback-modal-content feedback-modal-content--${this.modalPosition} ${this.isAnimating ? 'feedback-modal-content--open' : ''}`, ref: (el) => (this.modalContent = el) }, h("div", { class: "feedback-modal-header" }, !this.formSuccess && !this.formError ? (h("span", null, this.modalTitle)) : this.formSuccess ? (h("span", null, this.modalTitleSuccess)) : (h("span", null, this.modalTitleError)), h("button", { class: "feedback-modal-close", onClick: this.close }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "#191919", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "feather feather-x" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))), h("div", { class: "feedback-modal-body" }, !this.formSuccess && !this.formError ? (h("form", { onSubmit: this.handleSubmit }, !this.hideRating && (h("div", { class: "feedback-modal-rating" }, this.ratingMode === 'thumbs' ? (h("div", { class: "feedback-modal-rating-content" }, h("span", { class: "feedback-modal-input-heading" }, this.ratingPlaceholder), h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--thumbs" }, h("button", { title: "Yes", class: `feedback-modal-rating-button ${this.selectedRating === 1
9692
+ return (h("div", { class: `feedback-modal-wrapper ${this.customFont ? 'feedback-modal-wrapper--custom-font' : ''}` }, this.showModal && (h("div", { class: `feedback-overlay ${this.isAnimating ? 'feedback-overlay--visible' : ''}` })), this.showModal && (h("div", { class: `feedback-modal-content feedback-modal-content--${this.modalPosition} ${this.isAnimating ? 'feedback-modal-content--open' : ''}`, ref: (el) => (this.modalContent = el) }, h("div", { class: "feedback-modal-header" }, !this.formSuccess && !this.formError ? (h("span", null, this.modalTitle)) : this.formSuccess ? (h("span", null, this.modalTitleSuccess)) : (h("span", null, this.modalTitleError)), h("button", { class: "feedback-modal-close", onClick: this.close }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "#191919", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round", class: "feather feather-x" }, h("line", { x1: "18", y1: "6", x2: "6", y2: "18" }), h("line", { x1: "6", y1: "6", x2: "18", y2: "18" })))), h("div", { class: "feedback-modal-body" }, !this.formSuccess && !this.formError ? (h("form", { onSubmit: this.handleSubmit }, !this.hideRating && (h("div", { class: "feedback-modal-rating" }, this.ratingMode === 'thumbs' ? (h("div", { class: "feedback-modal-rating-content" }, h("span", { class: "feedback-modal-input-heading" }, this.ratingPlaceholder), h("div", { class: "feedback-modal-rating-buttons feedback-modal-rating-buttons--thumbs" }, h("button", { title: "Yes", class: `feedback-modal-rating-button ${this.selectedRating === 1
9127
9693
  ? 'feedback-modal-rating-button--selected'
9128
9694
  : ''}`, onClick: (event) => {
9129
9695
  event.preventDefault();
@@ -9138,7 +9704,8 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9138
9704
  : ''}`, onClick: (event) => {
9139
9705
  event.preventDefault();
9140
9706
  this.handleRatingChange(rating);
9141
- } }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "#5F6368", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" })))))))))), h("div", { class: "feedback-modal-text" }, h("textarea", { placeholder: this.messagePlaceholder, value: this.formMessage, onInput: (event) => this.handleMessageInput(event) })), !this.hideEmail && (h("div", { class: "feedback-modal-email" }, h("input", { placeholder: this.emailPlaceholder, type: "email", onInput: (event) => this.handleEmailInput(event), value: this.formEmail, required: this.isEmailRequired }))), h("div", { class: "feedback-verification" }, h("input", { type: "text", name: "verification", style: { display: 'none' }, onInput: (event) => this.handleVerification(event), value: this.formVerification })), !this.hidePrivacyPolicy && (h("div", { class: "feedback-modal-privacy" }, h("input", { type: "checkbox", id: "privacyPolicy", onChange: (ev) => this.handleCheckboxChange(ev), required: true }), h("span", { innerHTML: this.privacyPolicyText }))), h("div", { class: `feedback-modal-buttons ${this.hideScreenshotButton ? 'single' : ''}` }, !this.hideScreenshotButton && (h("button", { type: "button", class: `feedback-modal-button feedback-modal-button--screenshot ${this.encodedScreenshot ? 'feedback-modal-button--active' : ''}`, onClick: this.openScreenShot, disabled: this.sending }, this.encodedScreenshot && (h("div", { class: "screenshot-preview" }, h("img", { src: this.encodedScreenshot, alt: "Screenshot Preview" }))), !this.encodedScreenshot && (h("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24", viewBox: "0 -960 960 960", width: "24" }, h("path", { d: "M680-80v-120H560v-80h120v-120h80v120h120v80H760v120h-80ZM200-200v-200h80v120h120v80H200Zm0-360v-200h200v80H280v120h-80Zm480 0v-120H560v-80h200v200h-80Z" }))), this.encodedScreenshot ? this.screenshotAttachedText : this.screenshotButtonText)), h("button", { class: "feedback-modal-button feedback-modal-button--submit", type: "submit", disabled: this.sending }, this.sendButtonText)))) : this.formSuccess && !this.formError ? (h("div", { class: "feedback-modal-success" }, h("p", { class: "feedback-modal-message" }, this.successMessage))) : this.formError && this.formErrorStatus == 404 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage404)) : this.formError && this.formErrorStatus == 403 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage403)) : this.formError ? (h("p", { class: "feedback-modal-message" }, this.errorMessage)) : (h("span", null))), h("div", { class: "feedback-modal-footer" }, h("div", { class: "feedback-logo", style: { display: this.whitelabel ? 'none' : 'block' } }, "Powered by", ' ', h("a", { target: "_blank", href: "https://pushfeedback.com" }, "PushFeedback.com")), this.footerText && (h("div", { class: "feedback-footer-text" }, h("span", { innerHTML: this.footerText }))))))));
9707
+ } }, h("svg", { xmlns: "http://www.w3.org/2000/svg", width: "28", height: "28", viewBox: "0 0 24 24", fill: "none", stroke: "#5F6368", "stroke-width": "2", "stroke-linecap": "round", "stroke-linejoin": "round" }, h("polygon", { points: "12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" })))))))))), h("div", { class: "feedback-modal-text" }, h("textarea", { placeholder: this.messagePlaceholder, value: this.formMessage, onInput: (event) => this.handleMessageInput(event) })), !this.hideEmail && (h("div", { class: "feedback-modal-email" }, h("input", { placeholder: this.emailPlaceholder, type: "email", onInput: (event) => this.handleEmailInput(event), value: this.formEmail, required: this.isEmailRequired }))), h("div", { class: "feedback-verification" }, h("input", { type: "text", name: "verification", style: { display: 'none' }, onInput: (event) => this.handleVerification(event), value: this.formVerification })), !this.hidePrivacyPolicy && (h("div", { class: "feedback-modal-privacy" }, h("input", { type: "checkbox", id: "privacyPolicy", onChange: (ev) => this.handleCheckboxChange(ev), required: true }), h("span", { innerHTML: this.privacyPolicyText }))), h("div", { class: `feedback-modal-buttons ${this.hideScreenshotButton ? 'single' : ''}` }, !this.hideScreenshotButton && (h("button", { type: "button", class: `feedback-modal-button feedback-modal-button--screenshot ${this.encodedScreenshot ? 'feedback-modal-button--active' : ''}`, onClick: this.openScreenShot, disabled: this.sending || this.takingScreenshot }, this.encodedScreenshot && (h("div", { class: "screenshot-preview", onClick: this.openCanvasEditor }, h("img", { src: this.encodedScreenshot, alt: "Screenshot Preview" }))), !this.encodedScreenshot && !this.takingScreenshot && (h("svg", { xmlns: "http://www.w3.org/2000/svg", height: "24", viewBox: "0 -960 960 960", width: "24" }, h("path", { d: "M680-80v-120H560v-80h120v-120h80v120h120v80H760v120h-80ZM200-200v-200h80v120h120v80H200Zm0-360v-200h200v80H280v120h-80Zm480 0v-120H560v-80h200v200h-80Z" }))), this.takingScreenshot && (h("div", { class: "screenshot-loading" }, h("svg", { width: "16", height: "16", viewBox: "0 0 16 16" }, h("circle", { cx: "8", cy: "8", r: "6", fill: "none", stroke: "#666", "stroke-width": "2", "stroke-dasharray": "6 6", "transform-origin": "8 8" }, h("animateTransform", { attributeName: "transform", type: "rotate", values: "0 8 8;360 8 8", dur: "1s", repeatCount: "indefinite" }))))), this.takingScreenshot ? this.screenshotTakingText :
9708
+ this.encodedScreenshot ? this.screenshotAttachedText : this.screenshotButtonText)), h("button", { class: "feedback-modal-button feedback-modal-button--submit", type: "submit", disabled: this.sending }, this.sendButtonText)))) : this.formSuccess && !this.formError ? (h("div", { class: "feedback-modal-success" }, h("p", { class: "feedback-modal-message" }, this.successMessage))) : this.formError && this.formErrorStatus == 404 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage404)) : this.formError && this.formErrorStatus == 403 ? (h("p", { class: "feedback-modal-message" }, this.errorMessage403)) : this.formError ? (h("p", { class: "feedback-modal-message" }, this.errorMessage)) : (h("span", null))), h("div", { class: "feedback-modal-footer" }, h("div", { class: "feedback-logo", style: { display: this.whitelabel ? 'none' : 'block' } }, "Powered by", ' ', h("a", { target: "_blank", href: "https://pushfeedback.com" }, "PushFeedback.com")), this.footerText && (h("div", { class: "feedback-footer-text" }, h("span", { innerHTML: this.footerText })))))), 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) })))))))), h("div", { class: "toolbar-section" }, h("div", { class: "size-control" }, h("input", { type: "range", min: "1", max: "10", value: this.canvasLineWidth, onInput: (e) => this.canvasLineWidth = parseInt(e.target.value), class: "size-slider" }), h("span", { class: "size-value" }, 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 }))))))));
9142
9709
  }
9143
9710
  componentDidRender() {
9144
9711
  if (this.showModal) {
@@ -9187,10 +9754,14 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9187
9754
  "ratingPlaceholder": [1, "rating-placeholder"],
9188
9755
  "ratingStarsPlaceholder": [1, "rating-stars-placeholder"],
9189
9756
  "sendButtonText": [1, "send-button-text"],
9190
- "screenshotButtonText": [1, "screenshot-button-text"],
9191
9757
  "screenshotAttachedText": [1, "screenshot-attached-text"],
9758
+ "screenshotButtonText": [1, "screenshot-button-text"],
9759
+ "screenshotTakingText": [1, "screenshot-taking-text"],
9192
9760
  "screenshotTopbarText": [1, "screenshot-topbar-text"],
9193
9761
  "successMessage": [1, "success-message"],
9762
+ "canvasEditorTitle": [1, "canvas-editor-title"],
9763
+ "canvasEditorCancelText": [1, "canvas-editor-cancel-text"],
9764
+ "canvasEditorSaveText": [1, "canvas-editor-save-text"],
9194
9765
  "sending": [32],
9195
9766
  "formMessage": [32],
9196
9767
  "formEmail": [32],
@@ -9204,6 +9775,26 @@ const FeedbackModal = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement
9204
9775
  "selectedRating": [32],
9205
9776
  "overlayVisible": [32],
9206
9777
  "isAnimating": [32],
9778
+ "takingScreenshot": [32],
9779
+ "showPreviewModal": [32],
9780
+ "showCanvasEditor": [32],
9781
+ "canvasDrawingTool": [32],
9782
+ "canvasDrawingColor": [32],
9783
+ "canvasLineWidth": [32],
9784
+ "isDrawing": [32],
9785
+ "annotations": [32],
9786
+ "currentAnnotation": [32],
9787
+ "isDragging": [32],
9788
+ "draggedAnnotation": [32],
9789
+ "dragStartPos": [32],
9790
+ "showColorPicker": [32],
9791
+ "editingColorIndex": [32],
9792
+ "isResizing": [32],
9793
+ "resizingAnnotation": [32],
9794
+ "resizeStartSize": [32],
9795
+ "hoveredAnnotation": [32],
9796
+ "resizeHandle": [32],
9797
+ "defaultColors": [32],
9207
9798
  "openModal": [64]
9208
9799
  }]);
9209
9800
  function defineCustomElement() {